Aded extended commands and editor
This commit is contained in:
+552
-103
@@ -1,6 +1,7 @@
|
||||
#lang scribble/manual
|
||||
|
||||
@(require (for-label racket/base
|
||||
(only-in rackedit rkdt)
|
||||
(only-in rash-coreutils
|
||||
coreutils-pwd coreutils-ls coreutils-mkdir coreutils-rmdir
|
||||
coreutils-rm coreutils-cp coreutils-mv coreutils-cat
|
||||
@@ -10,140 +11,506 @@
|
||||
coreutils-dirname coreutils-realpath coreutils-readlink
|
||||
coreutils-stat coreutils-du coreutils-df coreutils-mktemp
|
||||
coreutils-printenv coreutils-env coreutils-date
|
||||
raco
|
||||
coreutils-raco)))
|
||||
coreutils-time coreutils-edit current-coreutils-editor
|
||||
coreutils-help dispatch-coreutils-command
|
||||
raco coreutils-raco)))
|
||||
|
||||
@title{rash-coreutils}
|
||||
@author["Hans Dijkema / hans@dijkewijk.nl"]
|
||||
|
||||
@defmodule[rash-coreutils]
|
||||
|
||||
@bold{rash-coreutils} provides platform-independent Unix-style shell commands
|
||||
for Rash. The commands are implemented in Racket, so common shell utilities do
|
||||
not depend on @tt{cmd.exe}, PowerShell, or Unix executables being installed.
|
||||
@bold{rash-coreutils} provides platform-independent Unix-style commands for
|
||||
Rash. The user-facing API is the set of commands that can be written directly
|
||||
in Rash line mode. Most commands are implemented by ordinary Racket procedures,
|
||||
so they do not depend on @tt{cmd.exe}, PowerShell, or Unix utility executables.
|
||||
|
||||
Rash remains responsible for shell syntax such as pipelines, globbing, tilde
|
||||
expansion, variable expansion, and redirection. @bold{rash-coreutils} supplies
|
||||
the commands themselves plus Racket-specific additions such as regular-expression
|
||||
path selectors.
|
||||
expansion, variable expansion, and redirection. The command aliases provided by
|
||||
this package preserve those Rash semantics and then dispatch to the internal
|
||||
Racket implementation.
|
||||
|
||||
@section{Commands}
|
||||
@section{How a Rash command is executed}
|
||||
|
||||
The package provides @tt{pwd}, @tt{ls}, @tt{mkdir}, @tt{rmdir}, @tt{rm},
|
||||
@tt{cp}, @tt{mv}, @tt{cat}, @tt{touch}, @tt{echo}, @tt{which}, @tt{head},
|
||||
@tt{tail}, @tt{wc}, @tt{sort}, @tt{uniq}, @tt{cut}, @tt{tee}, @tt{tr},
|
||||
@tt{basename}, @tt{dirname}, @tt{realpath}, @tt{readlink}, @tt{stat}, @tt{du},
|
||||
@tt{df}, @tt{mktemp}, @tt{printenv}, @tt{env}, @tt{date}, @tt{raco}, and @tt{help}.
|
||||
For a normal command such as
|
||||
|
||||
@verbatim{
|
||||
ls -l *.rkt
|
||||
}
|
||||
|
||||
Rash first processes its line syntax and pipeline semantics. The @tt{ls} alias
|
||||
then calls @racket[dispatch-coreutils-command], which looks up the registered
|
||||
command and invokes @racket[coreutils-ls]. Arguments that are Racket regular
|
||||
expressions are expanded by the rash-coreutils dispatcher before the internal
|
||||
procedure is called.
|
||||
|
||||
This means the shell command is the primary interface, while procedures such as
|
||||
@racket[coreutils-ls] are the implementation API and are also available to
|
||||
ordinary Racket code.
|
||||
|
||||
The option set is deliberately smaller than GNU coreutils. Unsupported options
|
||||
raise an error instead of silently approximating another command's behavior.
|
||||
raise an error instead of silently approximating behavior that is not
|
||||
implemented.
|
||||
|
||||
@section{Racket procedures}
|
||||
|
||||
Each shell command has an explicitly named Racket procedure. All procedures
|
||||
write to the normal current ports so Rash pipeline and redirection semantics
|
||||
continue to work.
|
||||
@section{Filesystem commands}
|
||||
|
||||
@index["rash-coreutils-pwd"]
|
||||
@defproc[(coreutils-pwd) void?]{Writes the current directory.}
|
||||
@subsection{@tt{pwd}}
|
||||
|
||||
@verbatim{
|
||||
pwd
|
||||
}
|
||||
|
||||
Writes the current directory. The command accepts no arguments.
|
||||
|
||||
Internally, @tt{pwd} dispatches to @racket[coreutils-pwd].
|
||||
|
||||
@defproc[(coreutils-pwd) void?]{Writes @racket[current-directory] using a Rash-friendly textual path.}
|
||||
|
||||
@index["rash-coreutils-ls"]
|
||||
@defproc[(coreutils-ls [arg any/c] ...) void?]{Lists paths. Supports @tt{-a}, @tt{-l}, and their long forms.}
|
||||
@subsection{@tt{ls}}
|
||||
|
||||
@verbatim{
|
||||
ls
|
||||
ls -l
|
||||
ls -a
|
||||
ls -la
|
||||
ls *.rkt
|
||||
ls #px"^info[0-9]+[.]rkt$"
|
||||
}
|
||||
|
||||
Lists files and directories. @tt{-a}/@tt{--all} includes hidden names and
|
||||
@tt{-l}/@tt{--long} writes the portable long form used by this package. Rash
|
||||
performs normal glob expansion. A Racket regular-expression value is an
|
||||
additional rash-coreutils path selector and is matched against names in the
|
||||
current directory.
|
||||
|
||||
Internally, @tt{ls} dispatches to @racket[coreutils-ls].
|
||||
|
||||
@defproc[(coreutils-ls [arg any/c] ...) void?]{Implements the listing after Rash and dispatcher argument handling.}
|
||||
|
||||
@index["rash-coreutils-mkdir"]
|
||||
@defproc[(coreutils-mkdir [arg any/c] ...) void?]{Creates directories. Supports @tt{-p}.}
|
||||
@subsection{@tt{mkdir}}
|
||||
|
||||
@verbatim{
|
||||
mkdir work
|
||||
mkdir -p build/output
|
||||
}
|
||||
|
||||
Creates one or more directories. @tt{-p}/@tt{--parents} creates missing parent
|
||||
directories.
|
||||
|
||||
Internally, @tt{mkdir} dispatches to @racket[coreutils-mkdir].
|
||||
|
||||
@defproc[(coreutils-mkdir [arg any/c] ...) void?]{Creates the requested directories.}
|
||||
|
||||
@index["rash-coreutils-rmdir"]
|
||||
@subsection{@tt{rmdir}}
|
||||
|
||||
@verbatim{
|
||||
rmdir empty-directory
|
||||
}
|
||||
|
||||
Removes one or more empty directories. No options are currently supported.
|
||||
|
||||
Internally, @tt{rmdir} dispatches to @racket[coreutils-rmdir].
|
||||
|
||||
@defproc[(coreutils-rmdir [arg any/c] ...) void?]{Removes empty directories.}
|
||||
|
||||
@index["rash-coreutils-rm"]
|
||||
@defproc[(coreutils-rm [arg any/c] ...) void?]{Removes paths. Supports recursive and force options.}
|
||||
@subsection{@tt{rm}}
|
||||
|
||||
@verbatim{
|
||||
rm file.txt
|
||||
rm -r directory
|
||||
rm -rf generated
|
||||
}
|
||||
|
||||
Removes files or links. Directories require @tt{-r}, @tt{-R}, or
|
||||
@tt{--recursive}. @tt{-f}/@tt{--force} suppresses an error for a missing path.
|
||||
The combined forms @tt{-rf}, @tt{-fr}, @tt{-Rf}, and @tt{-fR} are supported.
|
||||
|
||||
Internally, @tt{rm} dispatches to @racket[coreutils-rm].
|
||||
|
||||
@defproc[(coreutils-rm [arg any/c] ...) void?]{Removes the requested paths.}
|
||||
|
||||
@index["rash-coreutils-cp"]
|
||||
@defproc[(coreutils-cp [arg any/c] ...) void?]{Copies a source to a destination. Directory copies require @tt{-r}.}
|
||||
@subsection{@tt{cp}}
|
||||
|
||||
@verbatim{
|
||||
cp source.txt copy.txt
|
||||
cp -r source-directory copy-directory
|
||||
}
|
||||
|
||||
Copies exactly one source to one destination. Directory copies require
|
||||
@tt{-r}, @tt{-R}, or @tt{--recursive}.
|
||||
|
||||
Internally, @tt{cp} dispatches to @racket[coreutils-cp].
|
||||
|
||||
@defproc[(coreutils-cp [arg any/c] ...) void?]{Copies a file or, in recursive mode, a directory tree.}
|
||||
|
||||
@index["rash-coreutils-mv"]
|
||||
@subsection{@tt{mv}}
|
||||
|
||||
@verbatim{
|
||||
mv old-name.txt new-name.txt
|
||||
}
|
||||
|
||||
Moves or renames exactly one source path to one destination path.
|
||||
|
||||
Internally, @tt{mv} dispatches to @racket[coreutils-mv].
|
||||
|
||||
@defproc[(coreutils-mv [source any/c] [destination any/c]) void?]{Moves or renames a path.}
|
||||
|
||||
@index["rash-coreutils-cat"]
|
||||
@defproc[(coreutils-cat [arg any/c] ...) void?]{Copies files, or standard input, to standard output.}
|
||||
|
||||
@index["rash-coreutils-touch"]
|
||||
@defproc[(coreutils-touch [arg any/c] ...) void?]{Updates modification times or creates empty files.}
|
||||
@subsection{@tt{touch}}
|
||||
|
||||
@index["rash-coreutils-echo"]
|
||||
@defproc[(coreutils-echo [arg any/c] ...) void?]{Writes arguments separated by spaces.}
|
||||
@verbatim{
|
||||
touch notes.txt
|
||||
}
|
||||
|
||||
@index["rash-coreutils-which"]
|
||||
@defproc[(coreutils-which [arg any/c] ...) void?]{Finds executables using Racket's executable search.}
|
||||
Creates missing files and updates the modification time of existing files. No
|
||||
options are currently supported.
|
||||
|
||||
@index["rash-coreutils-head"]
|
||||
@defproc[(coreutils-head [arg any/c] ...) void?]{Writes the first lines of input. Supports @tt{-n}.}
|
||||
Internally, @tt{touch} dispatches to @racket[coreutils-touch].
|
||||
|
||||
@index["rash-coreutils-tail"]
|
||||
@defproc[(coreutils-tail [arg any/c] ...) void?]{Writes the last lines of input. Supports @tt{-n}.}
|
||||
|
||||
@index["rash-coreutils-wc"]
|
||||
@defproc[(coreutils-wc [arg any/c] ...) void?]{Counts lines, words, and bytes. Supports @tt{-l}, @tt{-w}, and @tt{-c}.}
|
||||
|
||||
@index["rash-coreutils-sort"]
|
||||
@defproc[(coreutils-sort [arg any/c] ...) void?]{Sorts lines. Supports @tt{-r} and @tt{-n}.}
|
||||
|
||||
@index["rash-coreutils-uniq"]
|
||||
@defproc[(coreutils-uniq [arg any/c] ...) void?]{Collapses adjacent duplicate lines. Supports @tt{-c}.}
|
||||
|
||||
@index["rash-coreutils-cut"]
|
||||
@defproc[(coreutils-cut [arg any/c] ...) void?]{Selects one delimited field with @tt{-d} and @tt{-f}.}
|
||||
|
||||
@index["rash-coreutils-tee"]
|
||||
@defproc[(coreutils-tee [arg any/c] ...) void?]{Copies standard input to standard output and files. Supports @tt{-a}.}
|
||||
|
||||
@index["rash-coreutils-tr"]
|
||||
@defproc[(coreutils-tr [arg any/c] ...) void?]{Translates characters from standard input. Character ranges such as @tt{a-z}, @tt{A-Z}, and @tt{0-9} are expanded. @tt{-d} deletes characters and @tt{-s} squeezes repeated characters.}
|
||||
@defproc[(coreutils-touch [arg any/c] ...) void?]{Touches one or more files.}
|
||||
|
||||
@index["rash-coreutils-basename"]
|
||||
@subsection{@tt{basename}}
|
||||
|
||||
@verbatim{
|
||||
basename a/b/file.txt
|
||||
}
|
||||
|
||||
Writes the final component of one path.
|
||||
|
||||
Internally, @tt{basename} dispatches to @racket[coreutils-basename].
|
||||
|
||||
@defproc[(coreutils-basename [path any/c]) void?]{Writes the final path component.}
|
||||
|
||||
@index["rash-coreutils-dirname"]
|
||||
@subsection{@tt{dirname}}
|
||||
|
||||
@verbatim{
|
||||
dirname a/b/file.txt
|
||||
}
|
||||
|
||||
Writes the directory portion of one path.
|
||||
|
||||
Internally, @tt{dirname} dispatches to @racket[coreutils-dirname].
|
||||
|
||||
@defproc[(coreutils-dirname [path any/c]) void?]{Writes the directory portion of a path.}
|
||||
|
||||
@index["rash-coreutils-realpath"]
|
||||
@defproc[(coreutils-realpath [path any/c]) void?]{Writes a complete simplified path.}
|
||||
@subsection{@tt{realpath}}
|
||||
|
||||
@verbatim{
|
||||
realpath relative/path
|
||||
}
|
||||
|
||||
Writes a complete simplified path with filesystem links resolved where the
|
||||
current filesystem supports that resolution.
|
||||
|
||||
Internally, @tt{realpath} dispatches to @racket[coreutils-realpath].
|
||||
|
||||
@defproc[(coreutils-realpath [path any/c]) void?]{Writes the complete simplified path.}
|
||||
|
||||
@index["rash-coreutils-readlink"]
|
||||
@defproc[(coreutils-readlink [path any/c]) void?]{Resolves a symbolic link.}
|
||||
@subsection{@tt{readlink}}
|
||||
|
||||
@verbatim{
|
||||
readlink link-name
|
||||
}
|
||||
|
||||
Writes the target of one symbolic link and reports an error when the supplied
|
||||
path is not a link.
|
||||
|
||||
Internally, @tt{readlink} dispatches to @racket[coreutils-readlink].
|
||||
|
||||
@defproc[(coreutils-readlink [path any/c]) void?]{Writes the resolved symbolic-link target.}
|
||||
|
||||
@index["rash-coreutils-stat"]
|
||||
@subsection{@tt{stat}}
|
||||
|
||||
@verbatim{
|
||||
stat file.txt
|
||||
stat file.txt directory
|
||||
}
|
||||
|
||||
Writes portable type, size, and modification information for one or more paths.
|
||||
|
||||
Internally, @tt{stat} dispatches to @racket[coreutils-stat].
|
||||
|
||||
@defproc[(coreutils-stat [path any/c] ...) void?]{Writes basic portable path metadata.}
|
||||
|
||||
@index["rash-coreutils-du"]
|
||||
@defproc[(coreutils-du [arg any/c] ...) void?]{Calculates recursive file size. Supports @tt{-h}.}
|
||||
|
||||
@index["rash-coreutils-df"]
|
||||
@defproc[(coreutils-df) void?]{Lists filesystem roots. Racket has no portable API for total and free filesystem capacity, so this initial implementation deliberately does not invent platform-specific subprocess fallbacks.}
|
||||
|
||||
@index["rash-coreutils-mktemp"]
|
||||
@defproc[(coreutils-mktemp [arg any/c] ...) void?]{Creates a temporary file, or a directory with @tt{-d}, and writes its path.}
|
||||
|
||||
@index["rash-coreutils-printenv"]
|
||||
@defproc[(coreutils-printenv [name any/c] ...) void?]{Writes environment variables.}
|
||||
|
||||
@index["rash-coreutils-env"]
|
||||
@defproc[(coreutils-env [arg any/c] ...) void?]{Creates a copied environment, applies leading @tt{NAME=value} assignments, and either writes that environment or runs the remaining command in it. Racket values are converted to environment strings.}
|
||||
|
||||
The Rash form can mix shell-style assignment names with Racket expressions:
|
||||
@subsection{@tt{du}}
|
||||
|
||||
@verbatim{
|
||||
du
|
||||
du -h directory
|
||||
}
|
||||
|
||||
Writes the accumulated file size of each requested path. With no path, the
|
||||
current directory is used. @tt{-h}/@tt{--human-readable} formats the size using
|
||||
binary K, M, and G units. Symbolic links are not followed.
|
||||
|
||||
Internally, @tt{du} dispatches to @racket[coreutils-du].
|
||||
|
||||
@defproc[(coreutils-du [arg any/c] ...) void?]{Calculates recursive file size.}
|
||||
|
||||
@index["rash-coreutils-df"]
|
||||
@subsection{@tt{df}}
|
||||
|
||||
@verbatim{
|
||||
df
|
||||
}
|
||||
|
||||
Lists filesystem roots visible to Racket. This portable implementation does not
|
||||
invent platform-specific subprocess fallbacks for total and free capacity.
|
||||
|
||||
Internally, @tt{df} dispatches to @racket[coreutils-df].
|
||||
|
||||
@defproc[(coreutils-df) void?]{Lists filesystem roots.}
|
||||
|
||||
@index["rash-coreutils-mktemp"]
|
||||
@subsection{@tt{mktemp}}
|
||||
|
||||
@verbatim{
|
||||
mktemp
|
||||
mktemp -d
|
||||
mktemp "rash-coreutils-~a"
|
||||
}
|
||||
|
||||
Creates a unique temporary file and writes its path. @tt{-d}/@tt{--directory}
|
||||
creates a directory instead. An optional non-option argument is used as the
|
||||
Racket temporary-file template.
|
||||
|
||||
Internally, @tt{mktemp} dispatches to @racket[coreutils-mktemp].
|
||||
|
||||
@defproc[(coreutils-mktemp [arg any/c] ...) void?]{Creates a temporary file or directory and writes its path.}
|
||||
|
||||
@section{Text and pipeline commands}
|
||||
|
||||
@index["rash-coreutils-cat"]
|
||||
@subsection{@tt{cat}}
|
||||
|
||||
@verbatim{
|
||||
cat file.txt
|
||||
cat first.txt second.txt
|
||||
producer | cat
|
||||
}
|
||||
|
||||
Copies files to standard output. With no file arguments, it copies standard
|
||||
input. This makes the implementation usable in Rash pipelines without special
|
||||
pipeline code.
|
||||
|
||||
Internally, @tt{cat} dispatches to @racket[coreutils-cat].
|
||||
|
||||
@defproc[(coreutils-cat [arg any/c] ...) void?]{Copies file or standard-input bytes to the current output port.}
|
||||
|
||||
@index["rash-coreutils-echo"]
|
||||
@subsection{@tt{echo}}
|
||||
|
||||
@verbatim{
|
||||
echo hello world
|
||||
}
|
||||
|
||||
Writes its arguments separated by spaces and terminates the result with a
|
||||
newline.
|
||||
|
||||
Internally, @tt{echo} dispatches to @racket[coreutils-echo].
|
||||
|
||||
@defproc[(coreutils-echo [arg any/c] ...) void?]{Writes the textual representation of the arguments.}
|
||||
|
||||
@index["rash-coreutils-head"]
|
||||
@subsection{@tt{head}}
|
||||
|
||||
@verbatim{
|
||||
head file.txt
|
||||
head -n 20 file.txt
|
||||
}
|
||||
|
||||
Writes the first lines of files or standard input. @tt{-n}/@tt{--lines}
|
||||
selects a non-negative line count; the default is 10. Input is scanned in fixed
|
||||
size byte blocks so memory use does not grow with file size or an individual
|
||||
line length.
|
||||
|
||||
Internally, @tt{head} dispatches to @racket[coreutils-head].
|
||||
|
||||
@defproc[(coreutils-head [arg any/c] ...) void?]{Writes the requested first lines.}
|
||||
|
||||
@index["rash-coreutils-tail"]
|
||||
@subsection{@tt{tail}}
|
||||
|
||||
@verbatim{
|
||||
tail file.txt
|
||||
tail -n 20 file.txt
|
||||
}
|
||||
|
||||
Writes the last lines of files or standard input. @tt{-n}/@tt{--lines} selects
|
||||
a non-negative line count; the default is 10. Seekable files are scanned
|
||||
backwards in fixed-size byte blocks. Input that cannot be scanned backwards is
|
||||
spooled to a temporary file, keeping memory use independent of input size and
|
||||
line length.
|
||||
|
||||
Internally, @tt{tail} dispatches to @racket[coreutils-tail].
|
||||
|
||||
@defproc[(coreutils-tail [arg any/c] ...) void?]{Writes the requested last lines.}
|
||||
|
||||
@index["rash-coreutils-wc"]
|
||||
@subsection{@tt{wc}}
|
||||
|
||||
@verbatim{
|
||||
wc file.txt
|
||||
wc -l file.txt
|
||||
wc -w file.txt
|
||||
wc -c file.txt
|
||||
}
|
||||
|
||||
Counts lines, words, and bytes. @tt{-l} selects lines, @tt{-w} words, and
|
||||
@tt{-c}/@tt{--bytes} bytes. With no count options all three values are written.
|
||||
|
||||
Internally, @tt{wc} dispatches to @racket[coreutils-wc].
|
||||
|
||||
@defproc[(coreutils-wc [arg any/c] ...) void?]{Counts input using bounded streaming buffers.}
|
||||
|
||||
@index["rash-coreutils-sort"]
|
||||
@subsection{@tt{sort}}
|
||||
|
||||
@verbatim{
|
||||
sort file.txt
|
||||
sort -r file.txt
|
||||
sort -n numbers.txt
|
||||
}
|
||||
|
||||
Sorts input lines. @tt{-r}/@tt{--reverse} reverses the ordering and
|
||||
@tt{-n}/@tt{--numeric-sort} uses numeric keys. Large input is divided into
|
||||
bounded in-memory runs and merged through temporary files.
|
||||
|
||||
Internally, @tt{sort} dispatches to @racket[coreutils-sort].
|
||||
|
||||
@defproc[(coreutils-sort [arg any/c] ...) void?]{Sorts lines without retaining the complete input in memory.}
|
||||
|
||||
@index["rash-coreutils-uniq"]
|
||||
@subsection{@tt{uniq}}
|
||||
|
||||
@verbatim{
|
||||
uniq sorted.txt
|
||||
uniq -c sorted.txt
|
||||
}
|
||||
|
||||
Collapses adjacent duplicate lines. @tt{-c}/@tt{--count} prefixes each output
|
||||
line with its run count. As with the Unix command, input should already be
|
||||
grouped when non-adjacent equal lines must also be collapsed.
|
||||
|
||||
Internally, @tt{uniq} dispatches to @racket[coreutils-uniq].
|
||||
|
||||
@defproc[(coreutils-uniq [arg any/c] ...) void?]{Collapses adjacent duplicate lines.}
|
||||
|
||||
@index["rash-coreutils-cut"]
|
||||
@subsection{@tt{cut}}
|
||||
|
||||
@verbatim{
|
||||
cut -f 2 data.txt
|
||||
cut -d ";" -f 3 data.txt
|
||||
}
|
||||
|
||||
Writes one delimited field from each input line. @tt{-f}/@tt{--fields} is
|
||||
required and currently accepts one positive field number. @tt{-d}/@tt{--delimiter}
|
||||
changes the delimiter from the default tab.
|
||||
|
||||
Internally, @tt{cut} dispatches to @racket[coreutils-cut].
|
||||
|
||||
@defproc[(coreutils-cut [arg any/c] ...) void?]{Selects one field from each input line.}
|
||||
|
||||
@index["rash-coreutils-tee"]
|
||||
@subsection{@tt{tee}}
|
||||
|
||||
@verbatim{
|
||||
producer | tee output.txt
|
||||
producer | tee -a output.txt
|
||||
}
|
||||
|
||||
Copies standard input to standard output and to each named file.
|
||||
@tt{-a}/@tt{--append} appends instead of replacing existing file content.
|
||||
|
||||
Internally, @tt{tee} dispatches to @racket[coreutils-tee].
|
||||
|
||||
@defproc[(coreutils-tee [arg any/c] ...) void?]{Copies the current input stream to the current output and files.}
|
||||
|
||||
@index["rash-coreutils-tr"]
|
||||
@subsection{@tt{tr}}
|
||||
|
||||
@verbatim{
|
||||
echo abc | tr a-z A-Z
|
||||
echo a1b2c3 | tr -d 0-9
|
||||
echo "a b" | tr -s " "
|
||||
}
|
||||
|
||||
Translates characters from standard input. Simple ranges such as @tt{a-z},
|
||||
@tt{A-Z}, and @tt{0-9} are expanded. @tt{-d}/@tt{--delete} deletes selected
|
||||
characters and @tt{-s}/@tt{--squeeze-repeats} squeezes repeated selected
|
||||
characters. @tt{-ds} and @tt{-sd} are also accepted.
|
||||
|
||||
Internally, @tt{tr} dispatches to @racket[coreutils-tr].
|
||||
|
||||
@defproc[(coreutils-tr [arg any/c] ...) void?]{Translates, deletes, or squeezes characters from the current input port.}
|
||||
|
||||
@section{Environment, time, and executable commands}
|
||||
|
||||
@index["rash-coreutils-which"]
|
||||
@subsection{@tt{which}}
|
||||
|
||||
@verbatim{
|
||||
which git
|
||||
which racket
|
||||
}
|
||||
|
||||
Finds commands using Racket's executable search and writes the resolved path.
|
||||
|
||||
Internally, @tt{which} dispatches to @racket[coreutils-which].
|
||||
|
||||
@defproc[(coreutils-which [arg any/c] ...) void?]{Finds one or more executables on @tt{PATH}.}
|
||||
|
||||
@index["rash-coreutils-printenv"]
|
||||
@subsection{@tt{printenv}}
|
||||
|
||||
@verbatim{
|
||||
printenv
|
||||
printenv PATH
|
||||
}
|
||||
|
||||
Writes the complete current environment or the values of selected variables.
|
||||
A missing selected variable produces no output.
|
||||
|
||||
Internally, @tt{printenv} dispatches to @racket[coreutils-printenv].
|
||||
|
||||
@defproc[(coreutils-printenv [name any/c] ...) void?]{Writes environment-variable values from @racket[current-environment-variables].}
|
||||
|
||||
@index["rash-coreutils-env"]
|
||||
@subsection{@tt{env}}
|
||||
|
||||
@verbatim{
|
||||
env NAME=value printenv NAME
|
||||
(define x 42)
|
||||
env ANSWER=(values x) printenv ANSWER
|
||||
}
|
||||
|
||||
A parenthesized expression in Rash line mode is ordinary Racket code. Therefore
|
||||
the value after an empty @tt{NAME=} token can be a number, symbol, path, string,
|
||||
or another printable Racket value.
|
||||
Creates a copy of the current environment, applies leading @tt{NAME=value}
|
||||
assignments, and either writes the resulting environment or runs the remaining
|
||||
command in it. A parenthesized expression in Rash line mode is ordinary Racket
|
||||
code, so the value following an empty @tt{NAME=} token can be a Racket value.
|
||||
Registered rash-coreutils commands are tried before an executable on @tt{PATH}.
|
||||
|
||||
Internally, the @tt{env} Rash alias first preserves Racket expressions in
|
||||
assignment values and then dispatches to @racket[coreutils-env].
|
||||
|
||||
@defproc[(coreutils-env [arg any/c] ...) void?]{Applies temporary environment assignments and optionally runs a command.}
|
||||
|
||||
@index["rash-coreutils-date"]
|
||||
@defproc[(coreutils-date [arg any/c] ...) void?]{Writes the current date and time using Gregor. Supports @tt{-u}/@tt{--utc}, @tt{-I}/@tt{--iso}, @tt{--tz ZONE}, and @tt{--format CLDR-PATTERN}. The format pattern follows Gregor's CLDR syntax rather than pretending to implement every GNU @tt{date} format escape.}
|
||||
@subsection{@tt{date}}
|
||||
|
||||
@verbatim{
|
||||
date
|
||||
@@ -152,47 +519,90 @@ date --utc --iso
|
||||
date --tz Europe/Amsterdam --format "yyyy-MM-dd HH:mm:ss"
|
||||
}
|
||||
|
||||
@index["rash-coreutils-raco"]
|
||||
@defproc[(raco [arg any/c] ...) void?]{Runs @tt{raco} from the current Racket installation. The executable is resolved from the active Racket installation before PATH is considered, so it also works on Windows when @tt{raco.exe} is not on PATH. Arguments may be strings, symbols, paths, numbers, or nested lists. With no arguments, the underlying @tt{raco} program is invoked without a subcommand.}
|
||||
Writes the current date and time using Gregor. @tt{-u}/@tt{--utc} selects UTC,
|
||||
@tt{-I}/@tt{--iso}/@tt{--iso-8601} selects ISO output, @tt{--tz ZONE} selects a
|
||||
time zone, and @tt{--format CLDR-PATTERN} uses Gregor's CLDR formatting syntax.
|
||||
|
||||
@defproc[(coreutils-raco [arg any/c] ...) void?]{Explicit implementation name for @racket[raco].}
|
||||
Internally, @tt{date} dispatches to @racket[coreutils-date].
|
||||
|
||||
@defproc[(coreutils-date [arg any/c] ...) void?]{Writes the current date and time in the requested representation.}
|
||||
|
||||
@index["rash-coreutils-time"]
|
||||
@subsection{@tt{time}}
|
||||
|
||||
@verbatim{
|
||||
time head -n 100 large.txt
|
||||
time raco test tests/coreutils.rkt
|
||||
}
|
||||
|
||||
Executes one registered rash-coreutils command or an executable on @tt{PATH} and
|
||||
writes timing data to standard error. The portable measurements are elapsed
|
||||
@tt{real} time, combined @tt{cpu} time for Racket and completed subprocesses,
|
||||
and Racket @tt{gc} time. Standard output from the timed command remains usable
|
||||
in pipelines and redirections.
|
||||
|
||||
Internally, @tt{time} dispatches to @racket[coreutils-time].
|
||||
|
||||
@defproc[(coreutils-time [command any/c] [arg any/c] ...) void?]{Runs and measures a command.}
|
||||
|
||||
@index["rash-coreutils-raco"]
|
||||
@subsection{@tt{raco}}
|
||||
|
||||
@verbatim{
|
||||
raco setup rash-coreutils
|
||||
raco pkg show
|
||||
}
|
||||
|
||||
The same @racket[raco] binding is a normal Racket procedure, so expression-mode code can use @racket[(raco '(setup rash-coreutils))]. The explicit implementation name @racket[coreutils-raco] is also exported.
|
||||
Runs @tt{raco} from the active Racket installation. The executable is resolved
|
||||
from that installation before @tt{PATH} is considered, which avoids accidentally
|
||||
using @tt{raco} from another Racket installation and also works on Windows when
|
||||
@tt{raco.exe} is not on @tt{PATH}.
|
||||
|
||||
@section{Path selection}
|
||||
The Rash command calls @racket[coreutils-raco]. The exported @racket[raco]
|
||||
binding is the Rash-facing command binding; ordinary Racket code can call
|
||||
@racket[coreutils-raco] explicitly.
|
||||
|
||||
Shell-style argument expansion remains Rash's responsibility. The aliases expand
|
||||
back into Rash's @tt{=unix-pipe=} operator, preserving Rash globbing, tilde
|
||||
expansion, and @tt{$} expansion.
|
||||
@defproc[(coreutils-raco [arg any/c] ...) void?]{Runs the active installation's @tt{raco} executable.}
|
||||
|
||||
@section{Editor command}
|
||||
|
||||
@index["rash-coreutils-edit"]
|
||||
@subsection{@tt{edit}}
|
||||
|
||||
@verbatim{
|
||||
ls *.rkt
|
||||
ls -l info*
|
||||
cat info*
|
||||
edit notes.rkt
|
||||
edit --wait notes.rkt
|
||||
}
|
||||
|
||||
Regular-expression values are an additional @bold{rash-coreutils} selector. A
|
||||
@racket[#rx""] or @racket[#px""] value is matched against entry names in the
|
||||
current directory.
|
||||
Opens exactly one file in the editor configured for rash-coreutils. By default,
|
||||
the editor is RackEdit's @racket[rkdt] procedure. Without @tt{--wait}, RackEdit
|
||||
opens the editor and the Rash command can continue. With @tt{--wait}, the flag
|
||||
is translated to @racket[#:wait?] @racket[#t], so the command returns only after
|
||||
the editor procedure returns.
|
||||
|
||||
Internally, @tt{edit} dispatches to @racket[coreutils-edit]. The implementation
|
||||
calls the procedure stored in @racket[current-coreutils-editor] with the file
|
||||
path and a @racket[#:wait?] keyword.
|
||||
|
||||
@defproc[(coreutils-edit [arg any/c] ...) void?]{Parses @tt{--wait}, validates that exactly one file was supplied, and invokes @racket[current-coreutils-editor].}
|
||||
|
||||
@defthing[current-coreutils-editor parameter?]{
|
||||
A parameter whose default value is @racket[rkdt]. The configured procedure must
|
||||
accept one file path and the optional keyword @racket[#:wait?]. A wrapper can be
|
||||
used to select a different editor for a dynamic extent.
|
||||
}
|
||||
|
||||
@verbatim{
|
||||
ls #px"^info[0-9]+[.]rkt$"
|
||||
(parameterize
|
||||
([current-coreutils-editor
|
||||
(λ (filename #:wait? [wait? #f])
|
||||
...)])
|
||||
...)
|
||||
}
|
||||
|
||||
@section{Help command}
|
||||
|
||||
@section{Windows paths}
|
||||
|
||||
On Windows, commands that write path names use forward slashes in their textual output. Rash treats backslashes as escape characters in line mode, so a printed path such as @tt{C:/Users/name/AppData/Local/Temp/file} can be copied directly into another Rash command. Racket path values themselves remain native and can be passed directly to a command through a Racket expression.
|
||||
|
||||
@section{Help}
|
||||
|
||||
@tt{help} uses Racket's documentation search through @tt{raco docs}. Registered
|
||||
commands use package-specific index terms such as @tt{rash-coreutils-ls}.
|
||||
@subsection{@tt{help}}
|
||||
|
||||
@verbatim{
|
||||
help
|
||||
@@ -201,10 +611,49 @@ ls --help
|
||||
help directory-list
|
||||
}
|
||||
|
||||
With no argument, @tt{help} writes the registered rash-coreutils command names.
|
||||
For a registered command, it searches Racket documentation using the command's
|
||||
package-specific index term, for example @tt{rash-coreutils-ls}. Other terms are
|
||||
passed directly to Racket's documentation search. Supplying @tt{--help} to a
|
||||
registered command uses the same mechanism.
|
||||
|
||||
The @tt{help} alias calls @racket[coreutils-help] directly. The normal command
|
||||
dispatcher intercepts @tt{--help} before invoking the command implementation.
|
||||
|
||||
@defproc[(coreutils-help [arg any/c] ...) void?]{Lists commands or opens Racket documentation for one search term.}
|
||||
|
||||
@section{Path selection and Rash expansion}
|
||||
|
||||
Normal shell-style argument expansion remains Rash's responsibility. The aliases
|
||||
expand back into Rash's pipeline machinery, preserving globbing, tilde expansion,
|
||||
variable expansion, pipelines, and redirection.
|
||||
|
||||
@verbatim{
|
||||
ls *.rkt
|
||||
ls -l info*
|
||||
cat info* | wc -l
|
||||
}
|
||||
|
||||
Racket regular-expression values are an additional rash-coreutils selector. A
|
||||
@racket[#rx""] or @racket[#px""] value is matched against entry names in the
|
||||
current directory before the internal command procedure is called.
|
||||
|
||||
@verbatim{
|
||||
ls #px"^info[0-9]+[.]rkt$"
|
||||
}
|
||||
|
||||
@section{Windows paths}
|
||||
|
||||
On Windows, commands that write path names use forward slashes in their textual
|
||||
output. Rash treats backslashes as escape characters in line mode, so a printed
|
||||
path such as @tt{C:/Users/name/AppData/Local/Temp/file} can be copied directly
|
||||
into another Rash command. Racket path values themselves remain native and can
|
||||
be passed directly to a command through a Racket expression.
|
||||
|
||||
@section{Capturing and redirecting output}
|
||||
|
||||
Commands use normal ports. Rash can therefore capture or redirect them without
|
||||
special support in this package.
|
||||
The internal Racket procedures use normal current ports. Rash can therefore
|
||||
capture, pipe, or redirect command output without command-specific support.
|
||||
|
||||
@verbatim{
|
||||
(define git-path { which git |> read-line })
|
||||
@@ -216,5 +665,5 @@ cat info.rkt &>! copy.rkt
|
||||
|
||||
The command names and common options follow Unix conventions, but this package
|
||||
does not claim complete GNU coreutils compatibility. Platform-independent
|
||||
behavior, predictable Rash scripting, and useful integration with Racket values
|
||||
are the primary goals.
|
||||
behavior, predictable Rash scripting, and integration with Racket values are
|
||||
the primary goals.
|
||||
|
||||
Reference in New Issue
Block a user