p-gen / smenu

smenu started as a lightweight and flexible terminal menu generator, but quickly evolved into a powerful and versatile CLI selection tool for interactive or scripting use.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

feature request: exit 1 on Control-C pressed?

step- opened this issue · comments

commented

Hello,

Currently pressing control-c during smenu selection makes smenu exit 0 with no output. Is it possible to make smenu exit 1 in this case? My need is to distinguish between smenu's empty output due to empty input vs non-empty input and control-c pressed. Thank you for your consideration.

commented

Hello,

Could you elaborate? What do you mean by "empty output due to empty input? Do you want to be able to distinguish between typing a 'q' or a 'Q' and a '^C'?

Note that an empty input on stdin already returns 1 as return code.

Anyway, make sure you use the latest commit because improvements have recently been made to the signal handling.

commented

I would like to be able to distinguish the three cases below from each other: 0(no upstream input), 1(q/Q pressed), x(^C pressed to mean cancel selection), x not in {0,1}. Thank you.

~ # smenu --version
Version: 0.9.16-bd71bf8
~ # printf '' | smenu; echo $?
1
~ # printf '%s\n' a b c | smenu; echo $? # press q or Q
a b c
0
~ # printf '%s\n' a b c | smenu; echo $? # press ^C
a b c
0
~ #
commented

OK, for me, entering ^C should not be considered as an error because it is a choice of the user to cancel his action, hence the return code equal to 0

To distinguish the last two cases, I added a new option to define a string that will be automatically printed instead of an empty string when a ^C is entered. Look for -! in the manual.

Commit 7565b4f implements these changes.
 
Based on your example:

~ # R=$(printf '%s\n' a b c | smenu -int "Interrupted by CTRL-C") ; echo $?; echo $R # press ^C
a b c
0
Interrupted by CTRL-C
commented

I thank you for this change. On the other hand, I think that it would be better and more unix-like to return an exit status greater than 128 and no output, That is what the shell does, see here. Also consider a few points.

Having to inspect the -int string makes using smenu with pipes unnecessarily complicated, e.g. ls | smenu -W$'\n' -T$'\n' -d | tail -3. Here having to test output for the -int string is more complicated than setting the bash pipefail option and just looking at the error code. More so when the pipeline is part of an if condition.

Smenu wouldn't be the only program returning a non-zero exit status upon receiving a signal. For instance, yad does so extensively.

The semantics of non-zero == error is very common but not mandated, see the Semantics section in the article linked above.

Any choice of an -int string is intrinsically non-portable across user-systems, where the script author can't know in advance the input data. (Admittedly, adding control characters and other seldom-used characters to the -int string goes a long way to mitigate this point.)

In summary, I thank you for taking action and providing me with a workable solution but I also hope you reconsider your implementation to be more unix-like and friendlier to shell scripting.

commented

You convinced me :-). I reworked the trapped signals management to match the Unix shell one.
However, I kept the -!|-int|-int_string [string] option because I think it may be easier in some cases to get a specific selection when ^C is hit.

The default is now 128+SIGINT when ^C is hit.

# printf '%s\n' a b c | smenu; echo $? # press ^C
a b c
130

These changes are implemented in commit 1303c0a.

commented

Thank you for being flexible :-) I built the new commit and it works perfectly for my use case!

PS Files tests/misc/t0002.{good,tst} reference t0001.in. Intentional?

commented

No, fixed. Thanks.