Andre Noll [Tue, 24 Oct 2023 21:55:27 +0000 (23:55 +0200)]
gui: Implement descriptive tree items.
A restriction of the current gui module is that the text shown in the
menu items must also be a valid identifier for the corresponding bash
function. In particular no whitespace is allowed there.
To overcome this restriction we introduce the concept of a menu item
identifier and an optional menu item description. If the description
is absent, the identifier is used as the description, providing
backward compatibility.
Andre Noll [Tue, 22 Aug 2023 16:06:57 +0000 (18:06 +0200)]
gui: Remember menu position.
That's generally the expected behaviour, and it's not too hard to
implement. We let _gsu_menu() take an additional argument for the
default item and maintain its value in _browse().
Andre Noll [Wed, 25 Oct 2023 23:17:05 +0000 (01:17 +0200)]
README: Mention that the gui example script must be named "lsi".
By default, the prefix for the gsu action handlers is the basename
of the script and an underscore character. In the example script of
README.md all handlers are prefixed with "lsi_", so tell the reader
that the script will only work if it is saved under the name "lsi".
Andre Noll [Wed, 2 Aug 2023 21:09:11 +0000 (23:09 +0200)]
com_help(): Improve formating of command/description list
The help output, which consists of the subcommand name and the
one-line description, is formatted incorrectly if the name of one
or more subcommands exceeds 16 characters. Pre-compute the maximal
length of the command names upfront to fix that.
Andre Noll [Wed, 2 Aug 2023 20:35:16 +0000 (22:35 +0200)]
subcommand: Improve formatting of command list.
If a gsu application is run without specifying a subcommand we print
the available subcommands in tabular form. Currently, this output
always consists of four columns and we also assume that the length
of a subcommand name is shorter than 16 characters. If longer names
exist, the help output is formatted incorrectly. This commit should
fix that. We now compute the maximal command length and the width of
the terminal upfront, and derive the number of columns for the output
from this information.
Andre Noll [Tue, 5 Jul 2022 22:10:59 +0000 (00:10 +0200)]
gui: Treat dialog exit code 255 just like 1.
Dialog exits with code 255 if escape was pressed. This change makes the
escape key more useful in the main menu invoked via _browse() since it
no longer terminates the program but results to show the parent menu.
Andre Noll [Thu, 13 Sep 2018 19:26:31 +0000 (21:26 +0200)]
Implement help -a.
In most cases, the user does not want to see the four subcommands
which are auto-generated by gsu, so omit them from the default output
and provide -a to show them anyway.
This patch has been languishing in a development branch for several
years, so it's kind of well tested.
Andre Noll [Thu, 19 Jul 2018 19:04:09 +0000 (21:04 +0200)]
subcommand: Don't print error messages to stdout.
If an invalid command name was given, we print the list of available
commands, followed by an error message. The list of commands is
sent to stdout while the error message goes to stderr. This is a bit
unfortunate, so print both to stderr instead.
Andre Noll [Thu, 16 Aug 2018 12:39:59 +0000 (14:39 +0200)]
Simplify arithmetic evaluation.
Shell variables may be referenced by name without using the parameter
expansion syntax. In fact, this is to be preferred. Also no quotes
are neccessary.
This also fixes the hello world example.
Reported-by: Johannes Woerner <woerner@tuebingen.mpg.de> Tested-by: Johannes Woerner <woerner@tuebingen.mpg.de>
Andre Noll [Wed, 4 Oct 2017 18:43:31 +0000 (20:43 +0200)]
Redo the logo as svg.
dia started to segfault on my home box, and the export mode of dia to
convert a .dia file to png format is broken. Let's replace the .dia
file with a similar looking .svg file instead. It was made with vi.
Andre Noll [Mon, 13 Nov 2017 01:13:46 +0000 (02:13 +0100)]
Fall back to filename completion if no completer is defined.
If a gsu application does not implement subcommand completers, it's
best to complete on file names, if only to make completion work in
the common case of redirections. For example we like to complete the
last word of a partial command line of the form
app subcommand > /dev/nu
This did not work so far. With the patch applied, it does.
The application can always override the behaviour by implementing a
suitable completer.
Andre Noll [Mon, 17 Apr 2017 14:19:38 +0000 (16:19 +0200)]
subcommand: Fix and document return value of gsu_complete_options().
The value returned in $ret was undocumented so far. And it did not
make sense either: We used to return 0 if the current word does not
start with a hyphen, and the number of options in the given optstring
otherwise. Hence the value of zero is ambiguous.
Nobody needs the number of options anyway, so let's simply return 0
or 1, and document this.
Andre Noll [Mon, 17 Apr 2017 14:07:31 +0000 (16:07 +0200)]
subcommand: Implement roff and html output for com_man().
This implements the -m option of the internal man subcommand to specify
the output format for the manual page (text, roff, or html). html is
generated by running the html postprocessor of groff. Another option,
-b, is introduced to let the user specify the browser for html output.
The commit introduces new public variable $gsu_package whose value is
shown at the bottom left of the man page.
The documentation is updated accordingly, and the example subcommand
of README.md has been enhaced to illustrate how subcommand options
should be formatted to look nice in both html and roff output.
Andre Noll [Wed, 4 Oct 2017 15:27:01 +0000 (17:27 +0200)]
Fix gsu_cword_is_option_parameter().
The function did not recognize option combining. For example, the
current word was not recognized as an argument to -c if -c was given
as -abc. This patch should fix this issue.
Andre Noll [Sun, 5 Mar 2017 22:03:36 +0000 (23:03 +0100)]
subcommand: Use pager for man output if possible.
The manual can be much longer than one page, and it is easy to tell
whether stdout is associated with a terminal. The new _gsu_isatty()
takes care of that. It has been verified to work on FreeBSD, NetBSD
and Linux.
Andre Noll [Wed, 8 Mar 2017 07:38:56 +0000 (08:38 +0100)]
require bash-4.3
bash-4.3, released in 2014, is the oldest version which supports the
nameref variables and options. Ubuntu-14.04 already ships bash-4.3
so it should be OK to depend on it.
Andre Noll [Mon, 17 Apr 2017 13:27:54 +0000 (15:27 +0200)]
config: Declare local config variables earlier.
In gsu_check_options() we declare the six option variables (name,
option_type, ...) local to avoid overwriting the content of
user-defined variables of the same name.
Of course this only works if the variables are declared local before
we assign to them. This is currently not the case because the
eval "${gsu_options[$i]}"
statement in the first loop sets these variables before they are
declared in the body of the second loop.
This bug is benign since gsu_check_options() is usually called before
any command handler is executed. Let's fix it anyway.
Andre Noll [Sun, 5 Mar 2017 22:03:36 +0000 (23:03 +0100)]
subcommand: Make help text variables private.
It is unnecessary to export these as they are never needed in the
environment of subsequently executed commands. In fact, these variables
should be considered private to gsu. The name should thus start with
an underscore.
Andre Noll [Sun, 5 Mar 2017 21:36:25 +0000 (22:36 +0100)]
subcommand: Move gsu_check_arg_count().
It is called from gsu_getopts() which is defined further up in the
file. This does not really matter in bash, but it is still confusing,
so let's move gsu_check_arg_count() up.
Andre Noll [Sun, 5 Mar 2017 21:13:53 +0000 (22:13 +0100)]
subcommand: Simplify gsu().
There is no need to special-case the four autocommands in the main
entry function gsu(). Dropping the undercore in the name of the
four command handlers allows to treat them in the same way as the
subcommands which are provided by the application.
Andre Noll [Sun, 5 Mar 2017 18:55:13 +0000 (19:55 +0100)]
subcommand: Use POSIX compatible command regex.
The POSIX way to ask for one or more matches of the preceeding atom
is {1,} while the plus character is a non-portable shortcut.
Note that since the closing brace of the regex bound is inside
parameter expansion, we need to escape it with a backslash while the
opening brace must not be escaped.
Andre Noll [Thu, 28 Jul 2016 11:56:05 +0000 (13:56 +0200)]
gsu_make_tempfile(): Avoid reading an unbound variable.
If a gsu script
(a) enables the -u option to treat unset variables as
an error for parameter expansion,
(b) does not set TMPDIR,
(c) calls gsu_make_tempfile(),
gsu_make_tempfile() fails with an "TMPDIR: unbound variable" error.
The code already contains a fallback for this case, so we can use
the :- construct to avoid the error and fall back to /tmp if TMPDIR
is unset or NULL.
Andre Noll [Wed, 20 Jan 2016 09:54:35 +0000 (10:54 +0100)]
Add gsu_make_tempfile() and fix bug in gui module.
While mkstemp(3) is required by POSIX.1-2001, mktemp(1) is not in POSIX
and the various Unixes ship different and incompatible implementations
of this command line utility.
This commit adds the new public gsu_make_tempfile() helper to the
common part of gsu and changes the gui module to use it.
The mktemp invocation in the gui module was buggy because it ran
mktemp with a relative template (no slash). Hence the temporary file
was created in the current working directory. Of course this fails
if $CWD is not writable. The new public function gets this right.
If a subcommand does not set $ret (like the minimal "hello" example
does), and sets the nounset bash option (set -u), gsu aborts at
the attempt to reference $ret. Fix this flaw by setting $ret to
$GSU_SUCCESS prior to calling the subcommand.
Andre Noll [Tue, 3 Mar 2015 17:15:52 +0000 (18:15 +0100)]
_gsu_print_available_commands(): Don't abort if set -e is set.
It was pointed out by Congmao Wang that the example hello.bash script
prints only the first subcommand and exits if it is called with an
invalid subcommand and set -e is set. This is due to the "let count++"
statement which returns 1 in the first iteration of the loop since
count is zero.
This patch changes the statement to "let ++count" which returns zero
in all cases.
Andre Noll [Sat, 14 Feb 2015 20:17:53 +0000 (21:17 +0100)]
common: Fix gsu_is_a_number().
We must use [ ... ] in gsu_is_a_number() because arithmetic expansion
with ((...)) undergoes parameter and variable expansion. For example
x=foo
gsu_is_a_number "$x"
will pass "foo" to gsu_is_a_number() where the expression (("$1"))
tries to expand the (non-existing) variable foo, aborting the script
if set -u was given.
This bug was introduced a few month ago in commit 44860e92 (Use modern
style arithmetic evaluation everwhere).
Andre Noll [Sat, 30 Aug 2014 12:46:37 +0000 (14:46 +0200)]
Add README.
Up to now the API of gsu was completely undocumented. This commit
tries to improve on this. It adds a README file which explains the
public functions and variables of the three gsu modules (subcommand,
config and gui). Most features are illustrated by examples.
The README file is formatted in the grutatxt markup language, so it
can easily be converted to a nice html document.
Many thanks to George Wang who read an early draft of this document
and contributed many improvements.
Andre Noll [Sat, 6 Sep 2014 17:41:16 +0000 (19:41 +0200)]
gui: Introduce _set_dialog_ret().
The improved exit code handling for dialog(1) also makes sense for
the other invocations of dialog. This patch abtracts out the logic
into the new internal _set_dialog_ret() function.
Andre Noll [Mon, 1 Sep 2014 22:23:41 +0000 (00:23 +0200)]
gui: Conform to $ret and $result conventions.
Unlike the rest of gsu, the functions of the gui module did not follow
the rule that functions should always set $ret to indicate error or
success, and $result to either the result of the function (if any)
or to an error context string. This commit makes all functions of
the gui module conform to this rule.
This patch also improves the error handling of _gsu_menu(). This
function should distinguish between three cases, according to the
exit code of dialog(1): OK (user selected the OK button), Cancel
(user pressed the escape key or selected the Cancel button), and error
(dialog(1) failed to execute or returned unsuccessfully).
The old code does not distinguish between the last two cases. Hence one
could not exit the application by pressing CTRL+C from a menu. This
patch changes _gsu_menu() to look more carefully at the exit code of
dialog(1) to tell apart the "error" case and the "cancel" case.
Andre Noll [Mon, 1 Sep 2014 21:58:29 +0000 (23:58 +0200)]
gui: Make _gsu_node_name_pattern private.
Conform to the convention that the name of a private variables should
start with an underscore character. Also there is no need to export
the variable.
Andre Noll [Mon, 1 Sep 2014 21:54:09 +0000 (23:54 +0200)]
gui: Make gsu_menu() private.
Its single caller is _browse(), which is a private function as
well. This patch prepends an underscore to the function name to
indicate that the function is not supposed to be called by application
code.
Andre Noll [Sun, 31 Aug 2014 17:06:40 +0000 (19:06 +0200)]
Fix _gsu_banner_msg().
This function did not print the banner at all. It also had only a
single caller. This patch removes the function and changes the single
caller to print the banner text.
Andre Noll [Sun, 31 Aug 2014 19:01:02 +0000 (21:01 +0200)]
Unify gsu_dir handling.
The three locations which include the common part of gsu need to know
the gsu installation directory. Currently we rely on the application
to set $gsu_dir. This is unnecessary since gsu can tell where it is
installed by examining ${BASH_SOURCE[0]}.
Also the fallback to $HOME/.gsu is not required. This commit unifies
all three locations and also calls _gsu_setup as early as possible:
when the gsu module is sourced.
This function is rather confused. It uses gsu_short_msg() to print
the header to stderr while the list of subcommands is printed to
stdout. This is "fixed" by executing all commands in a subshell and
redirecting stderr to stdout.
It's easier to just print everything to stdout. This patch also
renames the loop variable i to cmd, declares $count as a local
integer variable and switches to single quoted string constants.
Andre Noll [Tue, 26 Aug 2014 21:18:58 +0000 (23:18 +0200)]
gsu: Improve documentation of _gsu_get_command_regex().
Although this function is private, it is central to the subcommand
part of gsu and should thus be properly documented. The new text is
more precise about the meaning of the regular expression that is used
to identify subcommands.
Andre Noll [Tue, 26 Aug 2014 19:52:07 +0000 (21:52 +0200)]
gsu: Don't fail if HOME is unset.
As pointed out by Joffrey Fitz, gsu-based scripts do not work when
run as a user without home directory. This happens for example if
the script is executed through a web application as the www-data user.
This patch replaces all references to HOME by ${HOME:-}, i.e. we just
default to the empty string but don't fail immediately.
Andre Noll [Mon, 25 Aug 2014 20:24:07 +0000 (22:24 +0200)]
gsu: Improve documentation of gsu_getopts().
The sentence which explains how $o_X is set for both types of options
was rather confusing. The new text should be better.
While we're at it,
* mention that getopts is a bash builtin
* switch to "modern" ((expr)) arithmetic evaluation in example
* use '' to quote constants in example
Andre Noll [Sun, 24 Aug 2014 14:57:08 +0000 (16:57 +0200)]
gsu: Improve help text of complete subcommand.
The current help text talks about two forms to run this command,
but only one is mentioned. This commit tries to clarify that the
function behaves differently when called without argument.
Andre Noll [Fri, 16 May 2014 13:35:32 +0000 (15:35 +0200)]
gsu: User banner text also for gsu gui.
Currently the $gsu_banner_txt variable is used only for subcommand
utilities but not for dialog-based tools. There is no real reason for
this restriction, so this commit starts to use the variable also for
the various GUIs.
Andre Noll [Fri, 13 Dec 2013 09:57:42 +0000 (10:57 +0100)]
gsu_gui: Add check for dialog executable.
Currently, programs which use gsu_gui exit silently with no indication about
what went wrong if dialog is not installed. This patch makes it print an error
message in this case.
Andre Noll [Wed, 12 Oct 2011 08:26:38 +0000 (10:26 +0200)]
gsu_getopts: Rename local variable opt to _gsu_getopts_opt.
As pointed out by Sebastian Stark, calling the loop variable "opt"
in code which is supposed to be eval'd by the application may conflict
with another local variable of the same name defined in the function
which calls gsu_getopt().
This could lead to rather obscure bugs which are hard to detect.
The callers don't use this loop variable directly, so we are free
to call it whatever we want. Therefore this patch renames $opt to
something which is much less likely to cause a conflict.
Andre Noll [Thu, 29 Sep 2011 13:12:33 +0000 (15:12 +0200)]
gsu: Overhaul of the rexexp matching for help commands.
The old sed scripts were unreadable and broken on non-gnu systems
since they made use of some gnuisms of grep and sed like \+ in regular
expressions to match at least one character or sed's T command which
jumps to a label if no substitution has been made since the most
recent reading of an input line.
This patch switches to extended regular expressions and replaces all
broken sed scripts by portable ones, which are known to work at least
on FreeBSD and MacOS. The new scripts are commented verbosely so that
any subsequent changes do not require a full rewrite, hopefully.
Andre Noll [Fri, 23 Sep 2011 15:21:58 +0000 (17:21 +0200)]
gsu: Initial completion support.
This adds the framework for command completion of scripts which make
use of the gsu subcommand library. The idea is to implement as much
as possible as generic helpers within gsu in order to minimize code
duplication in the scripts which source the gsu library.
The new "complete" subcommand is automatically included in each
application, just like the help, man and prefs commands we already
have. This subommand is meant to be used as the completer which calls
the custom subcommand completers included in the application.
Two new public helper functions, gsu_complete_options() and
gsu_cword_is_option_parameter() are introduced in this commit.
The former function takes a usual getopt string and completes according
to all options in this string. The latter is useful for completers
which need to determine whether the current word is the parameter to
some option in order to find out how to complete the current word.
For example, the -s option of cmt's vmem command takes a mandatory
parameter which is a number. So the completer for this command must
complete differently depending on whether the previous word is "-s".