summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3experimental/l3sys-shell.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/l3experimental/l3sys-shell.dtx
Initial commit
Diffstat (limited to 'macros/latex/contrib/l3experimental/l3sys-shell.dtx')
-rw-r--r--macros/latex/contrib/l3experimental/l3sys-shell.dtx372
1 files changed, 372 insertions, 0 deletions
diff --git a/macros/latex/contrib/l3experimental/l3sys-shell.dtx b/macros/latex/contrib/l3experimental/l3sys-shell.dtx
new file mode 100644
index 0000000000..4f8c3bee40
--- /dev/null
+++ b/macros/latex/contrib/l3experimental/l3sys-shell.dtx
@@ -0,0 +1,372 @@
+% \iffalse meta-comment
+%
+%% File: l3sys-shell.dtx
+%
+% Copyright (C) 2018,2019 The LaTeX3 Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3experimental bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver|package>
+\RequirePackage{expl3}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3sys-shell} package\\ System shell functions^^A
+% }
+%
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2019-08-25}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \begin{function}[added = 2018-07-28]{\sys_shell_cp:nn}
+% \begin{syntax}
+% \cs{sys_shell_cp:nn} \Arg{source} \Arg{dest}
+% \end{syntax}
+% Copies the files specified in the \meta{source} (which may include
+% wildcards) to the \meta{dest}. The file paths should be specified using
+% |/| as a path separator. Copying is \emph{not} recursive: only files at
+% the path level given are copied. If unrestricted shell escape is not
+% enabled, no action is attempted.
+% \end{function}
+%
+% \begin{function}[added = 2018-07-27]{\sys_shell_mkdir:n}
+% \begin{syntax}
+% \cs{sys_shell_mkdir:n} \Arg{directory}
+% \end{syntax}
+% Creates the \meta{directory}, which should should be specified using |/| as
+% a path separator. If unrestricted shell escape is not enabled, no action is
+% attempted.
+% \end{function}
+%
+% \begin{function}[added = 2018-07-28]{\sys_shell_mv:nn}
+% \begin{syntax}
+% \cs{sys_shell_mv:nn} \Arg{old} \Arg{new}
+% \end{syntax}
+% Moves the files from the \meta{old} to \meta{new} names/locations: the
+% \meta{old} names may include wildcards. In both arguments, |/| should be
+% used as the path separator. If unrestricted shell escape is not enabled, no
+% action is attempted.
+% \end{function}
+%
+% \begin{function}[added = 2018-07-27]{\sys_shell_rm:n}
+% \begin{syntax}
+% \cs{sys_shell_rm:n} \Arg{files}
+% \end{syntax}
+% Removes the \meta{files} (which may include wildcards). The file path should
+% be specified using |/| as a path separator. If unrestricted shell escape is
+% not enabled, no action is attempted.
+% \end{function}
+%
+% \begin{function}[added = 2018-07-27]{\sys_shell_rmdir:n}
+% \begin{syntax}
+% \cs{sys_shell_rmdir:n} \Arg{directory}
+% \end{syntax}
+% Removes the \meta{directory}, which should should be specified using |/| as
+% a path separator. If unrestricted shell escape is not enabled, no action is
+% attempted.
+% \end{function}
+%
+% \begin{function}[added = 2018-07-28]{\sys_shell_get_pwd:N}
+% \begin{syntax}
+% \cs{sys_shell_get_pwd:N} \meta{str var}
+% \end{syntax}
+% Sets the \meta{str var} to the present working directory (the output of
+% |pwd| on Unix or |cd| on Windows). Note that on Windows this will contain
+% string backslash chars (|\|). If unrestricted shell escape is not
+% enabled, no action is taken.
+% \end{function}
+%
+% \begin{function}[added = 2018-07-28]{\sys_shell_split_ls:nN}
+% \begin{syntax}
+% \cs{sys_shell_split_ls:N} \Arg{glob} \meta{seq}
+% \end{syntax}
+% Sets the \meta{seq var} to contain one entry per directory listing
+% (equivalent to |ls -1| or |dir /b|) as specified by the \meta{glob}: the
+% entries are strings. If unrestricted shell is not enabled, no action is
+% taken.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3sys-shell} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=sys>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage{l3sys-shell}{2019-08-25}{}
+ {L3 Experimental system shell functions}
+%</package>
+% \end{macrocode}
+%
+% \begin{macro}[EXP]{\@@_path_to_win:n}
+% \begin{macro}[EXP]{\@@_path_to_win:w}
+% \begin{macro}[EXP]{\@@_path_to_win:N}
+% A simple expandable search-and-replace for providing Windows-style paths.
+% \begin{macrocode}
+\cs_new:Npn \@@_path_to_win:n #1
+ {
+ \exp_after:wN \@@_path_to_win:w \tl_to_str:n {#1} ~ \q_stop
+ }
+\cs_new:Npn \@@_path_to_win:w #1 ~ #2 \q_stop
+ {
+ \@@_path_to_win:N #1 \q_nil
+ \tl_if_empty:nF {#2}
+ {
+ \c_space_tl
+ \@@_path_to_win:w #2 \q_stop
+ }
+ }
+\cs_new:Npn \@@_path_to_win:N #1
+ {
+ \quark_if_nil:NF #1
+ {
+ \token_if_eq_meaning:NNTF #1 /
+ { \c_backslash_str }
+ {#1}
+ \@@_path_to_win:N
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\sys_shell_cp:nn}
+% Simple Unix-like file copying: at some stage we may need a directory-only
+% version as Windows and Unix have different requirements here.
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_cp:nn #1#2
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \sys_shell_now:x
+ {
+ \sys_if_platform_unix:T
+ {
+ cp~-f~ \exp_not:N \tl_to_str:n {#1} ~
+ \exp_not:N \tl_to_str:n {#2}
+ }
+ \sys_if_platform_windows:T
+ {
+ copy~/y~ \exp_not:N \@@_path_to_win:n {#1} ~
+ \exp_not:N \@@_path_to_win:n {#2}
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sys_shell_mkdir:n}
+% Windows (with the extensions) will automatically make directory trees but
+% issues a warning if the directory already exists: avoid by including a
+% test.
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_mkdir:n #1
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \sys_shell_now:x
+ {
+ \sys_if_platform_unix:T
+ { mkdir~-p~ \exp_not:N \tl_to_str:n {#1} }
+ \sys_if_platform_windows:T
+ {
+ if~not~exist~
+ \exp_not:N \@@_path_to_win:n { #1 / nul } ~
+ mkdir~ \exp_not:N \@@_path_to_win:n {#1}
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sys_shell_mv:nn}
+% On Windows we do not have a single |mv| operation, so copy-and-delete
+% instead.
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_mv:nn #1#2
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \sys_shell_now:x
+ {
+ \sys_if_platform_unix:T
+ {
+ mv~ \exp_not:N \tl_to_str:n {#1} ~
+ \exp_not:N \tl_to_str:n {#2}
+ }
+ \sys_if_platform_windows:T
+ {
+ copy~/y~ \exp_not:N \@@_path_to_win:n {#1} ~
+ \exp_not:N \@@_path_to_win:n {#2}
+ \token_to_str:N & \token_to_str:N &
+ del~/f~/q~\exp_not:N \@@_path_to_win:n {#1}
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sys_shell_rm:n}
+% Deletion: obviously a big health warning here!
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_rm:n #1
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \sys_shell_now:x
+ {
+ \sys_if_platform_unix:T
+ { rm~-f~ \exp_not:N \tl_to_str:n {#1} }
+ \sys_if_platform_windows:T
+ { del~/f~/q~ \exp_not:N \@@_path_to_win:n {#1} }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sys_shell_rmdir:n}
+% When removing a directory, we create it first as that avoids errors in
+% the Windows case.
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_rmdir:n #1
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \sys_shell_mkdir:n {#1}
+ \sys_shell_now:x
+ {
+ \sys_if_platform_unix:T
+ { rm~-rf~ \exp_not:N \tl_to_str:n {#1} }
+ \sys_if_platform_windows:T
+ { rmdir~/s~/q~ \exp_not:N \@@_path_to_win:n {#1} }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_tmp_tl}
+% Scratch space.
+% \begin{macrocode}
+\tl_new:N \l_@@_tmp_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\sys_shell_get_pwd:N}
+% Getting the path is easy: the main work is avoiding loosing any
+% information. (This information can be obtained using the recorder file:
+% that does not require shell escape. However, it's hard to see how it might
+% be useful without the other file functions.)
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_get_pwd:N #1
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \exp_not:N \sys_shell_get:nnN
+ {
+ \sys_if_platform_unix:T { pwd }
+ \sys_if_platform_windows:T { cd }
+ }
+ {
+ \char_set_catcode_other:N \exp_not:N \\
+ \char_set_catcode_other:N \exp_not:N \#
+ \char_set_catcode_other:N \exp_not:N \~
+ \char_set_catcode_other:N \exp_not:N \%
+ \char_set_catcode_space:N \exp_not:N \ %
+ \tex_endlinechar:D -1 \scan_stop:
+ }
+ \exp_not:N \l_@@_tmp_tl
+ \str_set:NV #1 \exp_not:N \l_@@_tmp_tl
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\sys_shell_split_ls:nN}
+% Getting a one-per-line listing is easy enough. We need to set
+% \cs{ExplSyntaxOff} as that deals with the end-of-line character. After that,
+% just a case of tidying up. The listing always ends in |^^M| so there is an
+% extra entry to trim.
+% \begin{macrocode}
+\cs_new_protected:Npx \sys_shell_split_ls:nN #1#2
+ {
+ \sys_if_shell_unrestricted:T
+ {
+ \exp_not:N \sys_shell_get:nnN
+ {
+ \sys_if_platform_unix:T { ls~-1~ #1 }
+ \sys_if_platform_windows:T { dir~/b~ #1 }
+ }
+ {
+ \ExplSyntaxOff
+ \char_set_catcode_other:N \exp_not:N \\
+ \char_set_catcode_other:N \exp_not:N \#
+ \char_set_catcode_other:N \exp_not:N \~
+ \char_set_catcode_other:N \exp_not:N \%
+ \char_set_catcode_other:n { 13 }
+ }
+ \exp_not:N \l_@@_tmp_tl
+ \str_set:NV \exp_not:N \l_@@_tmp_tl \exp_not:N \l_@@_tmp_tl
+ \seq_set_split:NnV #2 { \char_generate:nn { `\^^M } { 12 } }
+ \exp_not:N \l_@@_tmp_tl
+ \seq_pop_right:NN #2 \exp_not:N \l_@@_tmp_tl
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex