Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: PATCH: Re: GNU-style long options for zsh



Bart Schaefer wrote:
>I don't know for sure how this should work WRT an embedded `-', but an
>embedded `b' should work like csh.  Using tcsh as the example, that means
>that the NEXT word is no longer taken as an option, but that any other
>letters in the CURRENT word still act like option selectors.

Patch below.  I left embedded `-' as an error, because the convention
with -- is that it can't be followed by any more options.  `-b' obviously
has this other precedent which we should follow.  Incidentally I made
-b's meaning depend on SH_OPTION_LETTERS, rather than on the initial
emulation mode; this changes the behaviour of "zsh --sh-option-letters
-b" and similar stuff.

>} 2. Specifying an invalid option name on the command line causes zsh
>} to exit, rather than continuing with an error message.  This makes it
>} consistent with the handling of single-letter option names.
>
>That's a pretty radical change with respect to `-o badlyspeltoption'.

Desirable, I think: if you got the usage wrong, do you really want to
run the shell without that option set?  What if the option the user was
trying to set was RESTRICTED or PRIVILEGED?  Remember, this is only about
shell invocation, "set -o" remains unaffected and won't kill the shell.

>Is there a good reason that `-' is not permitted within optlookup()?
>Why not allow `setopt sh-word-split' too, and keep the special case out
>of parseargs()?

Just a stylistic hint at the semantics.  We've established that option
names look_like_this (or LIKE_THIS); the hyphenated form doesn't look
like at option name.  Other things being equal we could perfectly well
decide that from now on stuff-like-this is going to be option names, but
ZLE widget names already look-like-this.  I thought it better to keep
different types of names having a different style, as far as possible.
The GNU-style long options have their own style, --looking-like-this,
which looks different from both ZLE widget names and zsh option names.

I actually gave thought to forbidding underscores in the long options
(effectively swapping `-' and `_').  This would have enforced the style
distinction further, and made it more explicit that the GNU long options
are just a different form of the option names, rather than actually
option names plus a bodge.

I'm open to this being changed as you suggest.

>I actually originally had it that way, and then decided it wasn't kosher
>and threw in the `action &&' test to prevent it.  Do any GNU programs
>really accept `+-optionname' like that?

Not that I know of.  I'm fairly neutral on this; like the issue above,
it's a matter that I considered and came up with a weak preference which
is what I implemented.  If we want to keep strictly to the spirit of GNU
long options, we should just have "--option", no "+-option", and rely
on "--no-option" for negation.  (That's the form I had --help output
equivalences in, for this stylistic reason.)  But the rest of the zsh
option parser allows "+" where almost all other commands only allow
"-"; I don't know of any precedent of an option parser that had "+"
for negation and also GNU-style long options.  It seemed more in keeping
with zsh to allow this kind of negation.

This way also means that all the special options are treated the same
way w.r.t. "+": +b and -b are equivalent; similarly +c and -c, +- and --;
and of the GNU options, +-version is equivalent to --version and +-help
to --help.

-zefram

Index: Doc/Zsh/invoke.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/invoke.yo,v
retrieving revision 1.3
diff -c -r1.3 invoke.yo
*** Doc/Zsh/invoke.yo	2000/07/30 17:03:53	1.3
--- Doc/Zsh/invoke.yo	2000/07/30 19:06:50
***************
*** 72,79 ****
  are not permitted to be stacked after `tt(--)' (so `tt(-x-f)' is an error),
  but note the GNU-style option form discussed above, where `tt(--shwordsplit)'
  is permitted and does not end option processing.
! Except when emulating sh or ksh, the option `tt(-b)' is treated the same way
! as `tt(--)' for the purpose of ending option processing.
  
  startmenu()
  menu(Compatibility)
--- 72,82 ----
  are not permitted to be stacked after `tt(--)' (so `tt(-x-f)' is an error),
  but note the GNU-style option form discussed above, where `tt(--shwordsplit)'
  is permitted and does not end option processing.
! 
! Except when the bf(sh)/bf(ksh) emulation single-letter options are in effect,
! the option `tt(-b)' (or `tt(PLUS()b)') ends option processing.
! `tt(-b)' is like `tt(--)', except that further single-letter options can be
! stacked after the `tt(-b)' and will take effect as normal.
  
  startmenu()
  menu(Compatibility)
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.8
diff -c -r1.8 init.c
*** Src/init.c	2000/07/30 17:03:53	1.8
--- Src/init.c	2000/07/30 19:06:55
***************
*** 186,195 ****
  void
  parseargs(char **argv)
  {
      char **x;
      int action, optno;
      LinkList paramlist;
-     int bourne = (emulation == EMULATE_KSH || emulation == EMULATE_SH);
  
      argzero = *argv++;
      SHIN = 0;
--- 186,195 ----
  void
  parseargs(char **argv)
  {
+     int optionbreak = 0;
      char **x;
      int action, optno;
      LinkList paramlist;
  
      argzero = *argv++;
      SHIN = 0;
***************
*** 206,222 ****
      opts[SINGLECOMMAND] = 0;
  
      /* loop through command line options (begins with "-" or "+") */
!     while (*argv && (**argv == '-' || **argv == '+')) {
  	char *args = *argv;
  	action = (**argv == '-');
  	if (!argv[0][1])
  	    *argv = "--";
  	while (*++*argv) {
! 	    /* The pseudo-option `--' signifies the end of options. *
! 	     * `-b' does too, csh-style, unless we're emulating a   *
! 	     * Bourne style shell.                                  */
! 	    if (**argv == '-' || (!bourne && **argv == 'b')) {
  		if(!argv[0][1]) {
  		    argv++;
  		    goto doneoptions;
  		}
--- 206,220 ----
      opts[SINGLECOMMAND] = 0;
  
      /* loop through command line options (begins with "-" or "+") */
!     while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) {
  	char *args = *argv;
  	action = (**argv == '-');
  	if (!argv[0][1])
  	    *argv = "--";
  	while (*++*argv) {
! 	    if (**argv == '-') {
  		if(!argv[0][1]) {
+ 		    /* The pseudo-option `--' signifies the end of options. */
  		    argv++;
  		    goto doneoptions;
  		}
***************
*** 240,246 ****
  		goto longoptions;
  	    }
  
! 	    if (**argv == 'c') {         /* -c command */
  		cmd = *argv;
  		opts[INTERACTIVE] &= 1;
  		opts[SHINSTDIN] = 0;
--- 238,248 ----
  		goto longoptions;
  	    }
  
! 	    if (unset(SHOPTIONLETTERS) && **argv == 'b') {
! 		/* -b ends options at the end of this argument */
! 		optionbreak = 1;
! 	    } else if (**argv == 'c') {
! 		/* -c command */
  		cmd = *argv;
  		opts[INTERACTIVE] &= 1;
  		opts[SHINSTDIN] = 0;
***************
*** 321,333 ****
  static void
  printhelp(void)
  {
-     int bourne = (emulation == EMULATE_KSH || emulation == EMULATE_SH);
- 
      printf("Usage: %s [<options>] [<argument> ...]\n", argzero);
      printf("\nSpecial options:\n");
      printf("  --help     show this message, then exit\n");
      printf("  --version  show zsh version number, then exit\n");
!     if(!bourne)
  	printf("  -b         end option processing, like --\n");
      printf("  -c         take first argument as a command to execute\n");
      printf("  -o OPTION  set an option by name (see below)\n");
--- 323,333 ----
  static void
  printhelp(void)
  {
      printf("Usage: %s [<options>] [<argument> ...]\n", argzero);
      printf("\nSpecial options:\n");
      printf("  --help     show this message, then exit\n");
      printf("  --version  show zsh version number, then exit\n");
!     if(unset(SHOPTIONLETTERS))
  	printf("  -b         end option processing, like --\n");
      printf("  -c         take first argument as a command to execute\n");
      printf("  -o OPTION  set an option by name (see below)\n");
END



Messages sorted by: Reverse Date, Date, Thread, Author