From 1e44da4f6e08ce2873187ba85ab3f833f22c0000 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Fri, 10 Jan 2025 18:26:33 +0100 Subject: [PATCH] added documentation about current state of lisp support --- README.md | 4 ++++ cmd/tablizer.go | 53 ++++++++++++++++++++++++++++++++++++++++++ lib/lisp.go | 8 +++---- lib/lisplib.go | 28 ++++++++++++++++++++--- tablizer.1 | 58 +++++++++++++++++++++++++++++++++++++++++++++- tablizer.pod | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 204 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 351241e..12913a4 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,10 @@ otherwise on all rows. There are more output modes like org-mode (orgtbl) and markdown. +Last but not least tablizer has support for plugins written in +lisp. This feature is expermental yet. Take a look into the manpage +for details. + ## Demo [![asciicast](demo/tablizer-demo.gif)](https://asciinema.org/a/9FKc3HPnlg8D2X8otheleEa9t) diff --git a/cmd/tablizer.go b/cmd/tablizer.go index 9e07f94..98399bb 100644 --- a/cmd/tablizer.go +++ b/cmd/tablizer.go @@ -38,6 +38,7 @@ SYNOPSIS Other Flags: --completion Generate the autocompletion script for -f, --config Configuration file (default: ~/.config/tablizer/config) + -l, --load-path Load path for lisp plugins (expects *.zy files) -d, --debug Enable debugging -h, --help help for tablizer -m, --man Display manual page @@ -303,6 +304,57 @@ CONFIGURATION AND COLORS Colorization can be turned off completely either by setting the parameter "-N" or the environment variable NO_COLOR to a true value. +LISP PLUGINS [experimental] + Tablizer supports plugins written in zygomys lisp. You can supply a + directory to the "-l" parameter containing *.zy files or a single .zy + file containing lisp code. + + You can put as much code as you want into the file, but you need to add + one lips function to a hook at the end. + + The following hooks are available: + + filter + The filter hook works one a whole line of the input. Your hook + function is expected to return true or false. If you return true, + the line will be included in the output, otherwise not. + + Multiple filter hook functions are supported. + + Example: + + /* + Simple filter hook function. Splits the argument by whitespace, + fetches the 2nd element, converts it to an int and returns true + if it s larger than 5, false otherwise. + */ + (defn uselarge [line] + (cond (> (atoi (second (resplit line `\s+`))) 5) true false)) + + /* Register the filter hook */ + (addhook %filter %uselarge) + + process + The process hook function gets a table containing the parsed input + data (see "lib/common.go:type Tabdata struct". It is expected to + return a pair containing a bool to denote if the table has been + modified, and the [modified] table. The resulting table may have + less rows than the original and cells may have changed content but + the number of columns must persist. + + transpose + not yet implemented. + + append + not yet implemented. + + Beside the existing language features, the following additional lisp + functions are provided by tablizer: + + (resplit [string, regex]) => list + (atoi [string]) => int + (matchre [string, regex]) => bool + BUGS In order to report a bug, unexpected behavior, feature requests or to submit a patch, please open an issue on github: @@ -375,6 +427,7 @@ Sort Mode Flags (mutually exclusive): Other Flags: --completion Generate the autocompletion script for -f, --config Configuration file (default: ~/.config/tablizer/config) + -l, --load-path Load path for lisp plugins (expects *.zy files) -d, --debug Enable debugging -h, --help help for tablizer -m, --man Display manual page diff --git a/lib/lisp.go b/lib/lisp.go index 456df64..d2ddf29 100644 --- a/lib/lisp.go +++ b/lib/lisp.go @@ -266,7 +266,7 @@ func RunProcessHooks(conf cfg.Config, data Tabdata) (Tabdata, bool, error) { case *zygo.SexpBool: result = th.Val default: - return userdata, false, errors.New("xpect (bool, array(hash)) as return value") + return userdata, false, errors.New("expect (bool, array(hash)) as return value") } switch sexptailtype := sexptype.Tail.(type) { @@ -276,7 +276,7 @@ func RunProcessHooks(conf cfg.Config, data Tabdata) (Tabdata, bool, error) { return userdata, false, errors.New("expect (bool, array(hash)) as return value ") } default: - return userdata, false, errors.New("filter hook shall return array of hashes ") + return userdata, false, errors.New("process hook shall return array of hashes ") } if !result { @@ -303,11 +303,11 @@ func RunProcessHooks(conf cfg.Config, data Tabdata) (Tabdata, bool, error) { case *zygo.SexpStr: row = append(row, sexptype.S) default: - return userdata, false, errors.New("hsh values should be string ") + return userdata, false, errors.New("hash values should be string ") } } default: - return userdata, false, errors.New("rturned array should contain hashes ") + return userdata, false, errors.New("returned array should contain hashes ") } userdata.entries = append(userdata.entries, row) diff --git a/lib/lisplib.go b/lib/lisplib.go index 11b763e..d65466a 100644 --- a/lib/lisplib.go +++ b/lib/lisplib.go @@ -38,7 +38,7 @@ func Splice2SexpList(list []string) zygo.Sexp { func StringReSplit(env *zygo.Zlisp, name string, args []zygo.Sexp) (zygo.Sexp, error) { if len(args) < 2 { - return zygo.SexpNull, errors.New("expecting 2 arguments") + return zygo.SexpNull, errors.New("expecting 2 arguments: , ") } var separator, input string @@ -47,14 +47,14 @@ func StringReSplit(env *zygo.Zlisp, name string, args []zygo.Sexp) (zygo.Sexp, e case *zygo.SexpStr: input = t.S default: - return zygo.SexpNull, errors.New("second argument must be a string") + return zygo.SexpNull, errors.New("first argument must be a string") } switch t := args[1].(type) { case *zygo.SexpStr: separator = t.S default: - return zygo.SexpNull, errors.New("first argument must be a string") + return zygo.SexpNull, errors.New("second argument must be a string") } sep := regexp.MustCompile(separator) @@ -82,7 +82,29 @@ func String2Int(env *zygo.Zlisp, name string, args []zygo.Sexp) (zygo.Sexp, erro return &zygo.SexpInt{Val: int64(number)}, nil } +func RegMatch(env *zygo.Zlisp, name string, args []zygo.Sexp) (zygo.Sexp, error) { + if len(args) != 2 { + return zygo.SexpNull, fmt.Errorf("argument must be , ") + } + + arguments := []string{} + + for _, arg := range args { + switch t := arg.(type) { + case *zygo.SexpStr: + arguments = append(arguments, t.S) + default: + return zygo.SexpNull, errors.New("argument must be a string") + } + } + + reg := regexp.MustCompile(arguments[0]) + + return &zygo.SexpBool{Val: reg.MatchString(arguments[1])}, nil +} + func RegisterLib(env *zygo.Zlisp) { env.AddFunction("resplit", StringReSplit) env.AddFunction("atoi", String2Int) + env.AddFunction("matchre", RegMatch) } diff --git a/tablizer.1 b/tablizer.1 index eaead61..274a323 100644 --- a/tablizer.1 +++ b/tablizer.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "TABLIZER 1" -.TH TABLIZER 1 "2024-05-07" "1" "User Commands" +.TH TABLIZER 1 "2025-01-10" "1" "User Commands" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -176,6 +176,7 @@ tablizer \- Manipulate tabular output of other programs \& Other Flags: \& \-\-completion Generate the autocompletion script for \& \-f, \-\-config Configuration file (default: ~/.config/tablizer/config) +\& \-l, \-\-load\-path Load path for lisp plugins (expects *.zy files) \& \-d, \-\-debug Enable debugging \& \-h, \-\-help help for tablizer \& \-m, \-\-man Display manual page @@ -494,6 +495,61 @@ the \f(CW\*(C`\-L\*(C'\fR parameter). .PP Colorization can be turned off completely either by setting the parameter \f(CW\*(C`\-N\*(C'\fR or the environment variable \fB\s-1NO_COLOR\s0\fR to a true value. +.SH "LISP PLUGINS [experimental]" +.IX Header "LISP PLUGINS [experimental]" +Tablizer supports plugins written in zygomys lisp. You can supply a +directory to the \f(CW\*(C`\-l\*(C'\fR parameter containing \fB*.zy\fR files or a single +\&.zy file containing lisp code. +.PP +You can put as much code as you want into the file, but you need to +add one lips function to a hook at the end. +.PP +The following hooks are available: +.IP "\fBfilter\fR" 4 +.IX Item "filter" +The filter hook works one a whole line of the input. Your hook +function is expected to return true or false. If you return true, the +line will be included in the output, otherwise not. +.Sp +Multiple filter hook functions are supported. +.Sp +Example: +.Sp +.Vb 7 +\& /* +\& Simple filter hook function. Splits the argument by whitespace, +\& fetches the 2nd element, converts it to an int and returns true +\& if it s larger than 5, false otherwise. +\& */ +\& (defn uselarge [line] +\& (cond (> (atoi (second (resplit line \`\es+\`))) 5) true false)) +\& +\& /* Register the filter hook */ +\& (addhook %filter %uselarge) +.Ve +.IP "\fBprocess\fR" 4 +.IX Item "process" +The process hook function gets a table containing the parsed input +data (see \f(CW\*(C`lib/common.go:type Tabdata struct\*(C'\fR. It is expected to +return a pair containing a bool to denote if the table has been +modified, and the [modified] table. The resulting table may have less +rows than the original and cells may have changed content but the +number of columns must persist. +.IP "\fBtranspose\fR" 4 +.IX Item "transpose" +not yet implemented. +.IP "\fBappend\fR" 4 +.IX Item "append" +not yet implemented. +.PP +Beside the existing language features, the following additional lisp +functions are provided by tablizer: +.PP +.Vb 3 +\& (resplit [string, regex]) => list +\& (atoi [string]) => int +\& (matchre [string, regex]) => bool +.Ve .SH "BUGS" .IX Header "BUGS" In order to report a bug, unexpected behavior, feature requests diff --git a/tablizer.pod b/tablizer.pod index 44a5180..ccca7b8 100644 --- a/tablizer.pod +++ b/tablizer.pod @@ -37,6 +37,7 @@ tablizer - Manipulate tabular output of other programs Other Flags: --completion Generate the autocompletion script for -f, --config Configuration file (default: ~/.config/tablizer/config) + -l, --load-path Load path for lisp plugins (expects *.zy files) -d, --debug Enable debugging -h, --help help for tablizer -m, --man Display manual page @@ -341,6 +342,66 @@ the C<-L> parameter). Colorization can be turned off completely either by setting the parameter C<-N> or the environment variable B to a true value. +=head1 LISP PLUGINS [experimental] + +Tablizer supports plugins written in zygomys lisp. You can supply a +directory to the C<-l> parameter containing B<*.zy> files or a single +.zy file containing lisp code. + +You can put as much code as you want into the file, but you need to +add one lips function to a hook at the end. + +The following hooks are available: + +=over + +=item B + +The filter hook works one a whole line of the input. Your hook +function is expected to return true or false. If you return true, the +line will be included in the output, otherwise not. + +Multiple filter hook functions are supported. + +Example: + + /* + Simple filter hook function. Splits the argument by whitespace, + fetches the 2nd element, converts it to an int and returns true + if it s larger than 5, false otherwise. + */ + (defn uselarge [line] + (cond (> (atoi (second (resplit line `\s+`))) 5) true false)) + + /* Register the filter hook */ + (addhook %filter %uselarge) + +=item B + +The process hook function gets a table containing the parsed input +data (see C. It is expected to +return a pair containing a bool to denote if the table has been +modified, and the [modified] table. The resulting table may have less +rows than the original and cells may have changed content but the +number of columns must persist. + +=item B + +not yet implemented. + +=item B + +not yet implemented. + +=back + +Beside the existing language features, the following additional lisp +functions are provided by tablizer: + + (resplit [string, regex]) => list + (atoi [string]) => int + (matchre [string, regex]) => bool + =head1 BUGS In order to report a bug, unexpected behavior, feature requests