shithub: sl

Download patch

ref: cafc89996b87185d6a10a53ac548afd778e2d759
parent: 2e0207bceefae6fd08191bb7569cf965da673560
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sat May 3 19:20:10 EDT 2025

help: make (help a group) and (help group a) work the same way

--- a/boot/sl.boot
+++ b/boot/sl.boot
@@ -43,12 +43,11 @@
   subscripts… new-value))  cdaadr ((lst))  car ((lst))  <= ((v . rest))  u32 (((n 0)))  arr ((type . rest))  cons ((first
   second))  - ((n . rest))  u64 (((n 0)))  rand (NIL)  assq ((key lst))  asin ((x))  log ((x))  length> ((seq
   n))  arg-error (args)  assv ((key lst))  cdaddr ((lst))  bignum (((n 0)))  vec? ((v))  min ((v . rest))  cddaar ((lst))  eqv? ((a
-  b))  io? ((term))  eof-object? ((v))  list (rest)  help ((term (kind NIL) (:print-header
-                                                                             help-print-header)))  memv ((item
+  b))  io? ((term))  eof-object? ((v))  list (rest)  help (((:print-header help-print-header) . rest))  memv ((item
   lst))  max ((v . rest))  cddadr ((lst))  rand-u32 (NIL)  closure? ((v))  __init_globals (NIL)  sinh ((r))  top-level-exception-handler ((e))  rand-f64 (NIL)  help-print-header ((term
   sigs (:kind NIL) (:lpad "")))  p32 (((n 0)))  s16 (((n 0)))  rune? ((v))  defc*r ((name))  identity ((v)))  *doc* #table(io-eof? "Return `T` if `io` is currently in the \"end of file\" state, `NIL`\notherwise."  cadddr "Shorthand for (car (cdr (cdr (cdr lst))))."  fixnum? "Return `T` if `v` is of a fixnum type, `NIL` otherwise."  exit "Terminate the process with the specified status.  Does not return.\nThe status is expected to be a string in case of an error.\n\nExamples:\n\n    (exit) ; exit with status 0 (nil on Plan 9)\n    (exit \"error\") ; exit with status 1 (\"error\" on Plan 9)"  __finish "A function called right before exit by the VM.\n\nThe exit `status` is either `NIL` or a string referring to an error\ncondition."  caaar "Shorthand for (car (car (car lst)))."  s32 "Construct a 32-bit signed number."  u8 "Construct a 8-bit unsigned number."  any "Return `T` if the predicate is true for _any_ element of the list,\n`NIL` otherwise.\n\nExample:\n\n   (any even? '(1 3 5 7))                       → NIL\n   (any (λ (s) (length> s 1)) '(\"ab\" \"cd\" \"e\")) → T"  s8 "Construct a 8-bit signed number."  num? "Return `T` if `v` is of a numerical type, `NIL` otherwise.\n\nNumerical types include floating point, fixnum, bignum, etc.\nNote: ironically, a NaN value is considered a number by this function\nsince it's only testing the _type_ of the value."  assert "Throw an exception if `expr` evaluates to `NIL`.  Return `T` in any\nother case.\n\nExamples:\n\n    (def s \"abc\")\n    (assert (= (length s) 3))         → T\n    (assert (eq? (str-rune s 0) #\\x)) → assertion failed: ..."  1+ "Equivalent to `(+ n 1)` - increment by one."  throw "Raise an exception consisting of a tag and a value.\n\nThis exception can be caught by `catch`."  positive? "Return `T` if `n` is greater than zero. Shorthand for `(> n 0)`."  atan "Return the arc tangent of `x` in radians."  *builtins* "VM instructions as closures."  remprop "Remove a property value associated with the symbol."  (doc
   group list) "Working with lists."  (doc group array) "Arrays and vectors."  cdddar "Shorthand for (cdr (cdr (cdr (car lst))))."  set-cdr! "Modify a cons cell (a list) in-place by putting `new-second` as its\nsecond element (tail of the list).  Return the modified cons\ncell (list).\n\nExamples:\n\n    (def q '(1 2 3 4 5))\n    (set-cdr! q '(6 7)) → (1 6 7)\n    q                   → (1 6 7)"  eq? "Return `T` if `a` and `b` are the same object, `NIL` otherwise.\n\nExamples:\n\n    (eq? 0.0 0) → NIL\n    (eq? 0 0)   → T\n    (def a \"1\")\n    (def b \"1\")\n    (eq? a b)   → NIL\n    (def a '(1))\n    (def b '(1))\n    (eq? a b)   → NIL"  io->str "Return an in-memory `io` buffer converted to a string."  bound? "Return `T` if `symbol` has a value associated with it, `NIL` otherwise."  odd? "Return `T` if `n` is an odd integer, `NIL` otherwise."  list? "Return `T` if the value is either `NIL` or a cons cell, `NIL`\notherwise."  sym "Return a symbol with the name being the concatenation of terms\nformatted as strings.\n\nThis is equivalent to `(sym (str terms…))`.\n\nExamples:\n\n    (sym \"a\" 'b 1) → ab1"  tanh "Return the hyperbolic tangent of `x`."  for "Call the function `f` with a single integer argument, starting from\n`min` and ending with `max`.\n\nExamples:\n\n    (for 0 2 (λ (i) (print (- 2 i)))) → 210"  (doc
-  group vm) "VM-related functions."  (doc group rand) "Random numbers generation."  tan "Return the tangent of `r`, where `r` is given in radians."  doc-group "Define documentation for a group."  cdaaar "Shorthand for (cdr (car (car (car lst))))."  bounds-error "Raise a bounds error exception."  even? "Return `T` if `n` is an even integer, `NIL` otherwise."  *properties* "All properties of symbols recorded with `putprop` are recorded in this\ntable."  zero? "Return `T` if `n` is zero. Shorthand for `(= n 0)`."  proper-list? "Return `T` is the value is a proper list.  That is, a non-circular\nlist with the last element being `NIL`, as opposed to a dotted list.\n\nExamples:\n\n    (proper-list? NIL)      → T\n    (proper-list? '(1))     → T\n    (proper-list? '(1 . 2)) → NIL\n    (def l '(1))\n    (set-cdr! l l)          → #0=(1 . #0#)\n    (length l)              → +inf.0\n    (proper-list? l)        → NIL"  random "Return a random number in the range `[0, max]` (inclusive).\n\nThe result is either an integer or a floating point number, depending\non the type of the `max` argument.\n\nExamples:\n\n    (random 1)   → 1\n    (random 1.0) → 0.69517"  eval "Evaluate expression.\n\nExamples:\n\n    (eval '(begin (set! x 1) (set! y 2) (+ x y)))\n    → 3\n    x → 1\n    y → 2"  cdaadr "Shorthand for (cdr (car (car (cdr lst))))."  u32 "Construct a 32-bit unsigned number."  cons "Return a cons cell containing two arguments.\n\nExamples:\n\n    (cons 1 2)                     → (1 . 2)\n    (cons 1 '(2))                  → (1 2)\n    (cons 1 (cons 2 (cons 3 NIL))) → (1 2 3)"  assq "Return a pair of a matching key and the associated value, or `NIL` if\nnone matched.  Keys are compared using `eq?`."  most-positive-fixnum "A constant integer closest to positive infinity that can be\nrepresented by fixnum type on this particular platform."  vec? "Return `T` if `v` is a vector, `NIL` otherwise."  min "Return the smallest among the arguments.\n\nExamples:\n\n    (min 3 1 9 4)     → 1\n    (min 'c 'h 'z 'a) → a\n    (min \"t\" \"g\" \"a\") → \"a\""  cddaar "Shorthand for (cdr (cdr (car (car lst))))."  io? "Return `T` if `term` is of `io` type, `NIL` otherwise."  eof-object? "Return `T` if the argument is `#<eof>`, `NIL` otherwise.\n\nThis object is returned by I/O functions to signal end of file,\nwhere applicable."  help "Display documentation the specified term, if available.\n\nThe optional parameter `kind` can be set to `group` to show\ndocumentation for the specified group instead of a single term.\nAll available documentation groups can be displayed with `(help\ngroups)`.\n\nAsterisk can be added to the beginning and/or end of the `term` in\norder to list the matching terms defined in the current environment.\nThis can be useful to recall a function's name.\n\nExamples:\n\n    (help str?)       ; show documentation for str?\n    (help type group) ; list items for dealing with types\n    (help str->*)     ; find functions converting from strings\n    (help *->str)     ; find functions converting to strings\n    (help *num*)      ; find anything related to numbers"  p32 "Construct a 32-bit abstract pointer value."  sym-set-doc "Set the documentation for the symbol."  macrocall? "Return the macro application function if `e` refers to a macro call,\n`NIL` otherwise.\n\nExamples:\n\n    (macrocall? '(car NIL))       → NIL\n    (macrocall? '(let ((x 1)) 2)) → #fn(...)"  *syntax-environment* "Table containing macro definitions.\n\nThe keys are macro names, the values are their application functions."  macroexpand "Return a fully macro-expanded expression.  Expansion will continue\nuntil no more macro calls are left.\n\nExamples:\n\n    (let ((a 3) (b 4) (c 5))\n      (macroexpand `(let* {[x ,a] [y ,b]} (+ x y ,c))))\n    → ((λ (x)\n         ((λ (y)\n            (+ x y 5))\n          4))\n       3)"  caadr "Shorthand for (car (car (cdr lst)))."  defstruct "Defines a structure type with a specific name and slots.\n\nThe default underlying type is a \"named\" vector (`:type vec`), where\nthe first ele
\ No newline at end of file
+  group vm) "VM-related functions."  (doc group rand) "Random numbers generation."  tan "Return the tangent of `r`, where `r` is given in radians."  doc-group "Define documentation for a group."  cdaaar "Shorthand for (cdr (car (car (car lst))))."  bounds-error "Raise a bounds error exception."  even? "Return `T` if `n` is an even integer, `NIL` otherwise."  *properties* "All properties of symbols recorded with `putprop` are recorded in this\ntable."  zero? "Return `T` if `n` is zero. Shorthand for `(= n 0)`."  proper-list? "Return `T` is the value is a proper list.  That is, a non-circular\nlist with the last element being `NIL`, as opposed to a dotted list.\n\nExamples:\n\n    (proper-list? NIL)      → T\n    (proper-list? '(1))     → T\n    (proper-list? '(1 . 2)) → NIL\n    (def l '(1))\n    (set-cdr! l l)          → #0=(1 . #0#)\n    (length l)              → +inf.0\n    (proper-list? l)        → NIL"  random "Return a random number in the range `[0, max]` (inclusive).\n\nThe result is either an integer or a floating point number, depending\non the type of the `max` argument.\n\nExamples:\n\n    (random 1)   → 1\n    (random 1.0) → 0.69517"  eval "Evaluate expression.\n\nExamples:\n\n    (eval '(begin (set! x 1) (set! y 2) (+ x y)))\n    → 3\n    x → 1\n    y → 2"  cdaadr "Shorthand for (cdr (car (car (cdr lst))))."  u32 "Construct a 32-bit unsigned number."  cons "Return a cons cell containing two arguments.\n\nExamples:\n\n    (cons 1 2)                     → (1 . 2)\n    (cons 1 '(2))                  → (1 2)\n    (cons 1 (cons 2 (cons 3 NIL))) → (1 2 3)"  assq "Return a pair of a matching key and the associated value, or `NIL` if\nnone matched.  Keys are compared using `eq?`."  most-positive-fixnum "A constant integer closest to positive infinity that can be\nrepresented by fixnum type on this particular platform."  vec? "Return `T` if `v` is a vector, `NIL` otherwise."  min "Return the smallest among the arguments.\n\nExamples:\n\n    (min 3 1 9 4)     → 1\n    (min 'c 'h 'z 'a) → a\n    (min \"t\" \"g\" \"a\") → \"a\""  cddaar "Shorthand for (cdr (cdr (car (car lst))))."  io? "Return `T` if `term` is of `io` type, `NIL` otherwise."  eof-object? "Return `T` if the argument is `#<eof>`, `NIL` otherwise.\n\nThis object is returned by I/O functions to signal end of file,\nwhere applicable."  help "Display documentation for a specific term or group of terms, if\navailable.\n\nAn optional symbol `group` is used to query for documentation on a\ngroup instead of a single term.  All available documentation groups\ncan be displayed with `(help groups)`.\n\nAsterisk can be added to the beginning and/or end of the term in order\nto list the matching terms defined in the current environment.  This\ncan be useful to recall a function's name.\n\nExamples:\n\n    (help str?)       ; show documentation for str?\n    (help groups)     ; show documentation groups\n    (help type group) ; list items for dealing with types\n    (help group type) ; same as ^\n    (help str->*)     ; find functions converting from strings\n    (help *->str)     ; find functions converting to strings\n    (help *num*)      ; find anything related to numbers"  p32 "Construct a 32-bit abstract pointer value."  sym-set-doc "Set the documentation for the symbol."  macrocall? "Return the macro application function if `e` refers to a macro call,\n`NIL` otherwise.\n\nExamples:\n\n    (macrocall? '(car NIL))       → NIL\n    (macrocall? '(let ((x 1)) 2)) → #fn(...)"  *syntax-environment* "Table containing macro definitions.\n\nThe keys are macro names, the values are their application functions."  macroexpand "Return a fully macro-expanded expression.  Expansion will continue\nuntil no more macro calls are left.\n\nExamples:\n\n    (let ((a 3) (b 4) (c 5))\n      (macroexpand `(let* {[x ,a] [y ,b]} (+ x y ,c))))\n    → ((λ (x)\n         ((λ (y)\n            (+ x y 5))\n          4))\n       3)"  caadr "Shorthand for (car (car (cdr lst)))."  defstruct "Defines a structure type with a specific name and slots.\n\nThe d
\ No newline at end of file
 ment is the name of the structure's type, the rest are\nthe keyworded slot values.  A list with slot values alone can be used\ninstead by adding `:type list` option.  The list will not contain the\nname of the struct by default, which can be enabled with `:named T`\noption.\n\nAs an example, the following declaration\n\n    (defstruct blah \"Return stuff.\" :doc-group stuff a b (c 1 :read-only T))\n\nGenerates the default constructor for a structure of three slots, with\nthe third (`c`) having a specific default value and being read-only.\n\n    (make-blah (:a NIL) (:b NIL) (:c 1))\n    (blah-a s)\n    (blah-b s)\n    (blah-c s)\n\nSlot's options, if any, should be specified after its default value.\nSupported options are:\n\n    ; mark the slot as read-only\n    ; its value can be read, but trying to modify it will throw an error\n    … :read-only T\n\nThe constructor can be changed in several ways:\n\n    ; disable the constructor altogether\n    (defstruct blah :constructor NIL a b c)\n    ; only change its name\n    (defstruct blah :constructor blargh a b c)\n    ; rename AND avoid using keywords\n    (defstruct blah :constructor (blah a b c) a b c)\n\nThe option `:conc-name` specifies the slot accessor prefix, which\ndefaults to `structname-`.  Prefix can be disabled entirely with\n`:conc-name NIL`.\n\nDefault predicate can be disabled or its name, which defaults to\n`structname?`, changed:\n\n    ; use \"blargh?\" instead of \"blah?\"\n    (defstruct blah :predicate blargh? a b c)\n    ; without predicate\n    (defstruct blah :predicate NIL a b c)"  caadar "Shorthand for (car (car (cdr (car lst))))."  buffer "Return an in-memory buffer for I/O, of `io` type.\n\nA buffer can be used for both reading and writing at the same\ntime."  list-tail "Return the reminder of the list after at most `n` elements, or `NIL`\nif the list is shorter.\n\nExamples:\n\n    (def l '(a b c))\n    (list-tail l 1)  → (b c)\n    (list-tail l 2)  → (c)\n    (list-tail l 10) → NIL"  assoc-list "Return an association list built of the arguments.\n\nEvery two arguments are expected to be a key and a value associated\nwith that key.\n\nExamples:\n\n    (assoc-list 'a 0 'b 1) → ((a . 0) (b . 1))"  builtin? "Return `T` if `v` is a built-in function implemented in C, `NIL`\notherwise.\n\nExamples:\n\n    (builtin? map)         → T\n    (builtin? macroexpand) → NIL"  macroexpand-1 "Return an macro-expanded expression.  If the expression is not a macro\ncall, it is returned unchanged.  Only a single level of expansion is\nperformed.\n\nExamples:\n\n    (let ((a 3) (b 4) (c 5))\n      (macroexpand-1 `(let* {[x ,a] [y ,b]} (+ x y ,c))))\n    → ((λ (x) ; note how the inner let* expression isn't expanded\n         (let* ((y 4)) (+ x y 5)))\n       3)"  str "Return concatenation of terms formatted as strings.\n\nThis is equivalent to `(princ terms…)`, except the string is\nreturned, rather than printed.\n\nExamples:\n\n    (str \"a\" 'b 1 #(0)) → \"ab1#(0)\""  negative? "Return `T` if `n` is a negative number. Shorthand for `(< n 0)`."  void "Return the constant `#<void>` while ignoring any arguments.\n\n`#<void>` is mainly used when a function has side effects but does not\nproduce any meaningful value to return, so even though `T` or `NIL` could\nbe returned instead, in case of `#<void>` alone, REPL will not print\nit."  assert-fail "Throw an \"assertion failed\" exception if evaluating `expr` itself does\nnot result in an exception thrown. Return `T` otherwise.\n\nTo test for a specific exception type, an optional `what` argument can\nbe used.\n\nExamples:\n\n    (def s \"abc\")\n    (assert-fail (= (length s) 3))   → assertion failed: ...\n    (assert-fail (= s 1) type-error) → T"  1- "Equivalent to `(- n 1)` - decrement by one."  equal? "Return `T` if both `a` and `b` are of the same value.  For non-leaf\ntypes (cons cell and vector), the equality test is performed\nthroughout the whole structure of the values.\n\nExamples:\n\n    (equal? 0.0 0) → NIL\n    (equal? 0 0)   → T\n    (def a \"1\")\n    (def b \"1\")\n    (e
\ No newline at end of file
   group number) "Operations with numbers."  abs "Return absolute value of the argument."  str? "Return `T` if the argument is a string, `NIL` otherwise."  cons? "Return `T` if `v` is a cons cell, `NIL` otherwise.\n\nExamples:\n\n    (cons? 0)    → NIL\n    (cons? NIL)  → NIL\n    (cons? '(1)) → T"  aset! "Modify the sequence element specified by the subscripts and return the\nnew value.  The sequence can be an array, vector, a list.\nMulti-dimensional sequences of variating types are also supported.\n\nExamples:\n\n    (def a '((1 #(2 (3)) 4)))\n    (aset! a 1 'x)     → index 1 out of bounds\n    (aset! a 0 0 'x)   → x\n    a                  → ((x #(2 (3)) 4))\n    (aset! a 0 1 9)    → 9\n    a                  → ((x #(9 (3)) 4))"  T "A boolean \"true\".\n\nExamples:\n\n    (not T)         → NIL\n    (if T 'yes 'no) → yes"  - "Return the result of subtraction.  With only one argument a\nnegation is performed.\n\nExamples:\n\n    (- 1.5) → -1.5\n    (- 3 2) → 1"  rand "Return a random non-negative fixnum on its maximum range."  (doc
   group string) "String-related functionality."  sinh "Return the hyperbolic sine of `x`."  *argv* "The list of command line arguments.\n\nIf StreetLISP was started in interactive mode without a file specified\nfor execution, `*argv*` will be a list containing just one value - the\nname of the `sl` executable.\n\nOtherwise, the file specified for execution and the rest of the remaining\narguments will form the `*argv*` list.\n\nStreetLISP's own options, such as `-i` and `-H ...` will be stripped\nout in any case.\n\nExamples:\n\n    $ sl -i -H 12345\n    #;> *argv*            → (\"sl\")\n    $ sl script.sl -i abc\n    #;> *argv*            → (\"script.sl\" \"-i\" \"abc\")"  top-level-exception-handler "Print the exception `e` and the stack trace to `*stderr*`.\n\nThis is the top level exception handler that is used by `load` and\n`repl` functions to handle exceptions that weren't handled at the\nlower level."  (doc
@@ -150,10 +149,10 @@
  bound? ((:doc-group . builtin))  * ((:doc-group . number)
   (:doc-group . builtin))  putprop ((:doc-group . prop) (:doc-see . getprop))  getprop ((:doc-group . prop)
                                                                                         (:doc-see . putprop))  caaadr ((:doc-group . list))  odd? ((:doc-group . number)
- caddar ((:doc-group . list))  caaaar ((:doc-group . list))  cdddar ((:doc-group . list))  list? ((:doc-group . list)
+  (:doc-see . even?))  caaddr ((:doc-group . list))  cosh ((:doc-group . math))  caddar ((:doc-group . list))  caaaar ((:doc-group . list))  cdddar ((:doc-group . list))  list? ((:doc-group . list)
 oc-see . list) (:doc-see . proper-list?))  iota ((:doc-group . list) (:doc-see . map-int))  table? ((:doc-group . type)
-. vm)
-                                                                                (:doc-see . *interactive*))  print-stack-trace ((:doc-group . error)
+. table))  < ((:doc-group . compare) (:doc-group . builtin))  repl ((:doc-group . vm)
+                                                                                (:doc-see . *interactive*))  print-stack-trace ((:doc-group . error)
 64 ((:doc-group . number) (:doc-see . u64))  NIL ((:doc-see . T))  f32 ((:doc-group . number)
   (:doc-see . f64))  sin ((:doc-group . math))  tanh ((:doc-group . math))  for ((:doc-group . builtin))  assoc ((:doc-group . list)
   (:doc-see . assoc-list) (:doc-see . assq) (:doc-see . assv))  > ((:doc-group . compare))  + ((:doc-group . number)
@@ -177,8 +176,8 @@
 e . assoc) (:doc-see . assv))  asin ((:doc-group . math))  log ((:doc-group . math))  most-positive-fixnum ((:doc-group . number)
   (:doc-see . most-negative-fixnum))  Instructions ((:doc-group . builtin))  assv ((:doc-group . list)
                                                                                    (:doc-see . assoc)
-                                      (:doc-see . assq))  cdaadr ((:doc-group . list))  cdaddr ((:doc-group . list))  bignum ((:doc-group . number)
-  (:doc-see . bignum?))  length> ((:doc-group . list) (:doc-see . length=))  vec? ((:doc-group . type)
+                (:doc-see . assoc)
+                                                                                   (:doc-see . assq))  cdaadr ((:doc-group . list))  cdaddr ((:doc-group . list))  bignum ((:doc-group . number)
                                                                   (:doc-group . type))  list ((:doc-see . list?)
   (:doc-see . cons) (:doc-group . builtin))  most-negative-fixnum ((:doc-group . number) (:doc-see . most-positive-fixnum))  help ((:doc-group . doc))  memv ((:doc-group . list)
   (:doc-see . member) (:doc-see . memq))  max ((:doc-group . compare) (:doc-see . min))  rand-u32 ((:doc-group . rand))  closure? ((:doc-group . type)
@@ -195,12 +194,12 @@
 ;J404086;35040=70711225251<863I0232487e22489e22488e2e4:232487e22489e2e3:" #(separate-doc-from-body
   append (NIL) sym-set-doc quote) 13)  with-input-from #fn("z12021e1220e2e1e17315163:" #(#fn(nconc)
   with-bindings *io-in* copy-list) 9)  unless #fn("z1200q211Pe4:" #(if begin) 9)  defmacro #fn("z17015186<86=873?0710<870=53@30q42223240<e22526e10=e177885153e3e2:" #(separate-doc-from-body
-17015186<86=873?0710<870=53@30q42223240<e22526e10=e177885153e3e2:" #(separate-doc-from-body
+egin) 9)  defmacro #fn("z17015186<86=873?0710<870=53@30q42223240<e22526e10=e177885153e3e2:" #(separate-doc-from-body
 e123024252622e121e32728e5e3e3:" #(let
   #:g510 time-now prog1 princ "Elapsed time: " - " seconds" *linefeed*) 13)  cond #fn("z0Ib520852185>1_51485<061:" #(#0=#fn("z0I:" #() void 4)
   #fn("n10H340q:0<85<20Q;J80485<DQ3C085=J6085<:2185=P:85=J@02285<A<0=51e3:85T23C\x94074758551513c07675855151278685<e2e12886217975855151PA<0=51e4e3:272:85<e2e1282:7585512:e2A<0=51e4e3:2885<2185=PA<0=51e4:" #(else
   begin or => 1arg-lambda? caddr caadr let if cddr #:g439) cond-clauses->if 14)) 7)  do #fn("z21<2071052207205220230522425268827872829e17:1=51522829e17:82512825e18:52e153e4e3e2e12825e18952e3:" #(#fn(map)
-829e17:82512825e18:52e153e4e3e2e12825e18952e3:" #(#fn(map)
+25268827872829e17:1=51522829e17:82512825e18:52e153e4e3e2e12825e18952e3:" #(#fn(map)
 ("z12021220qe32324e113E0252624e2271<e2e3@30De3e3e2:" #(assert
                                                                                         trycatch
                                                                                         begin λ e
@@ -213,7 +212,7 @@
 @e283DQ83;3\\0483H;3M0483DQ;3:042<2A052;J504838CP;J5048384DQ;3:042B02C52;J50484I222D8E108B8F>5?M5142E2Fe18H3{02G8H2He28E3E02I2J2He22K8Ie2e3@V02L2M2N2HEe32K0e2e32O2P2He27Q8A51e3e3e3@30qe18K3C02G8K<8M8K=51e3@30qe18E3U02R2K0e22K2Se28J3808K<@808M8C51e4@30qe17T7U2V8D8B8L8E8H8I8F0>88A525165:" #(#(:constructor
   2 :predicate 4 NIL NIL :type 0 :named 1 :conc-name 3 NIL NIL) vec #0#
   #fn("n10H370q:@30q4207172051f22324850A>38652486:" #((:read-only) assoc-list cddr #fn(for-each)
-850A>38652486:" #((:read-only) assoc-list cddr #fn(for-each)
+370q:@30q4207172051f22324850A>38652486:" #((:read-only) assoc-list cddr #fn(for-each)
           #fn("n1700<A52340q:712223F<24922505661:" #(member
   error #fn(str) "invalid option in slot " " of struct " ": ") 12)) slot-opts 9)
   #fn("n12021062:" #(#fn(map) #fn("n10B;35040<85;J404085;35040=;J604qe186RS;J9042086513=071228652@30q42324865287B38087<@30qe2:" #(#fn(keyword?)
@@ -625,7 +624,7 @@
                         *io-out* #0#
                                                                                    #fn("n02021{227351S;3q047484517585513M07584513@076504277851@30q@=079855147:5047;85w<61:" #(#fn("n0207122D63:" #(#fn(read)
   *io-in* :whitespace) 8) #fn("n1207151422061:" #(#fn(io-discardbuffer) *io-in* #fn(raise)) 6)
-o-in* eval void? *prompt* #fn(io-flush) *io-out* print newline void that) prompt 8)
+1207151422061:" #(#fn(io-discardbuffer) *io-in* #fn(raise)) 6)
                                                                      #fn("n020A>121{370F<60:q:" #(#fn("n0A<60:" 5)
   #fn("n1700514D:" #(top-level-exception-handler) 6)) reploop 5) newline) repl 8)
             revappend #fn("n2701062:" #(reverse-) revappend 7) reverse
--- a/src/system.sl
+++ b/src/system.sl
@@ -164,27 +164,31 @@
         (newline)))
   (newline))
 
-(defmacro (help term (kind NIL) (:print-header help-print-header))
-  "Display documentation the specified term, if available.
+(defmacro (help (:print-header help-print-header) . rest)
+  "Display documentation for a specific term or group of terms, if
+   available.
 
-   The optional parameter `kind` can be set to `group` to show
-   documentation for the specified group instead of a single term.
-   All available documentation groups can be displayed with `(help
-   groups)`.
+   An optional symbol `group` is used to query for documentation on a
+   group instead of a single term.  All available documentation groups
+   can be displayed with `(help groups)`.
 
-   Asterisk can be added to the beginning and/or end of the `term` in
-   order to list the matching terms defined in the current environment.
-   This can be useful to recall a function's name.
+   Asterisk can be added to the beginning and/or end of the term in order
+   to list the matching terms defined in the current environment.  This
+   can be useful to recall a function's name.
 
    Examples:
 
        (help str?)       ; show documentation for str?
+       (help groups)     ; show documentation groups
        (help type group) ; list items for dealing with types
+       (help group type) ; same as ^
        (help str->*)     ; find functions converting from strings
        (help *->str)     ; find functions converting to strings
        (help *num*)      ; find anything related to numbers"
   :doc-group doc
-  (let* {[doc-extra-term (and kind (cons (sym ":doc-" kind) term))]
+  (let* {[term (or (if (eq? (car rest) 'group) (cadr rest) (car rest)) (car rest))]
+         [kind (and (cons? (cdr rest)) (if (eq? (car rest) term) (cadr rest) (car rest)))]
+         [doc-extra-term (and kind (cons (sym ":doc-" kind) term))]
          [docterm (if kind (list 'doc kind term) term)]
          [doc (getprop docterm '*doc*)]
          [formals-list (getprop docterm '*formals-list*)]
--