670 lines
20 KiB
Racket
670 lines
20 KiB
Racket
#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
|
|
coreutils-touch coreutils-echo coreutils-which coreutils-head
|
|
coreutils-tail coreutils-wc coreutils-sort coreutils-uniq
|
|
coreutils-cut coreutils-tee coreutils-tr coreutils-basename
|
|
coreutils-dirname coreutils-realpath coreutils-readlink
|
|
coreutils-stat coreutils-du coreutils-df coreutils-mktemp
|
|
coreutils-printenv coreutils-env coreutils-date
|
|
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 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. The command aliases provided by
|
|
this package preserve those Rash semantics and then dispatch to the internal
|
|
Racket implementation.
|
|
|
|
@section{How a Rash command is executed}
|
|
|
|
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 behavior that is not
|
|
implemented.
|
|
|
|
@section{Filesystem commands}
|
|
|
|
@index["rash-coreutils-pwd"]
|
|
@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"]
|
|
@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"]
|
|
@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"]
|
|
@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"]
|
|
@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-touch"]
|
|
@subsection{@tt{touch}}
|
|
|
|
@verbatim{
|
|
touch notes.txt
|
|
}
|
|
|
|
Creates missing files and updates the modification time of existing files. No
|
|
options are currently supported.
|
|
|
|
Internally, @tt{touch} dispatches to @racket[coreutils-touch].
|
|
|
|
@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"]
|
|
@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"]
|
|
@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"]
|
|
@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
|
|
}
|
|
|
|
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"]
|
|
@subsection{@tt{date}}
|
|
|
|
@verbatim{
|
|
date
|
|
date --iso
|
|
date --utc --iso
|
|
date --tz Europe/Amsterdam --format "yyyy-MM-dd HH:mm:ss"
|
|
}
|
|
|
|
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.
|
|
|
|
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
|
|
}
|
|
|
|
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}.
|
|
|
|
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.
|
|
|
|
@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{
|
|
edit notes.rkt
|
|
edit --wait notes.rkt
|
|
}
|
|
|
|
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{
|
|
(parameterize
|
|
([current-coreutils-editor
|
|
(λ (filename #:wait? [wait? #f])
|
|
...)])
|
|
...)
|
|
}
|
|
|
|
@section{Help command}
|
|
|
|
@subsection{@tt{help}}
|
|
|
|
@verbatim{
|
|
help
|
|
help ls
|
|
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}
|
|
|
|
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 })
|
|
ls &> listing.txt
|
|
cat info.rkt &>! copy.rkt
|
|
}
|
|
|
|
@section{Compatibility scope}
|
|
|
|
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 integration with Racket values are
|
|
the primary goals.
|