diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /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.dtx | 372 |
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 |