Initial import

This commit is contained in:
2026-08-17 23:19:13 +02:00
parent 8210aa8e63
commit 1d546c3d6f
20 changed files with 1799 additions and 1 deletions
+220
View File
@@ -0,0 +1,220 @@
#lang scribble/manual
@(require (for-label racket/base
(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
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.
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.
@section{Commands}
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}.
The option set is deliberately smaller than GNU coreutils. Unsupported options
raise an error instead of silently approximating another command's behavior.
@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.
@index["rash-coreutils-pwd"]
@defproc[(coreutils-pwd) void?]{Writes the current directory.}
@index["rash-coreutils-ls"]
@defproc[(coreutils-ls [arg any/c] ...) void?]{Lists paths. Supports @tt{-a}, @tt{-l}, and their long forms.}
@index["rash-coreutils-mkdir"]
@defproc[(coreutils-mkdir [arg any/c] ...) void?]{Creates directories. Supports @tt{-p}.}
@index["rash-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.}
@index["rash-coreutils-cp"]
@defproc[(coreutils-cp [arg any/c] ...) void?]{Copies a source to a destination. Directory copies require @tt{-r}.}
@index["rash-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.}
@index["rash-coreutils-echo"]
@defproc[(coreutils-echo [arg any/c] ...) void?]{Writes arguments separated by spaces.}
@index["rash-coreutils-which"]
@defproc[(coreutils-which [arg any/c] ...) void?]{Finds executables using Racket's executable search.}
@index["rash-coreutils-head"]
@defproc[(coreutils-head [arg any/c] ...) void?]{Writes the first lines of input. Supports @tt{-n}.}
@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.}
@index["rash-coreutils-basename"]
@defproc[(coreutils-basename [path any/c]) void?]{Writes the final path component.}
@index["rash-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.}
@index["rash-coreutils-readlink"]
@defproc[(coreutils-readlink [path any/c]) void?]{Resolves a symbolic link.}
@index["rash-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:
@verbatim{
(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.
@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.}
@verbatim{
date
date --iso
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.}
@defproc[(coreutils-raco [arg any/c] ...) void?]{Explicit implementation name for @racket[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.
@section{Path selection}
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.
@verbatim{
ls *.rkt
ls -l info*
cat info*
}
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.
@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{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}.
@verbatim{
help
help ls
ls --help
help directory-list
}
@section{Capturing and redirecting output}
Commands use normal ports. Rash can therefore capture or redirect them without
special support in this package.
@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 useful integration with Racket values
are the primary goals.