I've included in my ~/.zshrc the following code:

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    zle redisplay
    zle push-input
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z

... which I found in an answer to the question Remember a half-typed command while I check something.

It works, but originally the code contained this statement:

emulate -LR zsh

I looked for the emulate command inside man zshbuiltins to understand the -L and -R options.

It seems that emulate -R zsh resets all the options to their default values, which I checked with this command:

vimdiff <(setopt) <(emulate -R zsh; setopt)

However, if I execute emulate -R zsh in an interactive shell, it resets the options definitively, so I suppose that's where the -L flag is needed:
to make the new values of the options local to the current function (if any).

It also seems to imply that options can have a local value, in addition to a global one, and that in case of a conflict, the local one has priority.

So, emulate -LR zsh is used to re-create a local environment with default and predictable values for the options, in which the author of a widget doesn't have to wonder what the options will be when its function is invoked, or to save (at the beginning of the function) then restore (at the end) all the options which may change the intended behavior of the widget.

I didn't copy the line because it seems to work without it. However, I would like to know if my understanding of this command is correct, and if someone could provide one or two simple examples, where emulate -LR zsh is necessary to avoid side effects.

  • That seems a mighty complicated way to write bindkey "^z" push-line-or-edit – thrig Jun 22 '17 at 17:52
  • @thrig The whole point of this function is to do something different when the command line is empty. – Gilles Jun 23 '17 at 1:28

Your understanding is correct.

emulate -R zsh resets all options to the zsh defaults. The -L flag makes this local to the containing function (and more generally makes all option changes local to the function).

Putting emulate -LR zsh near the beginning of a function definition is good hygiene when the function is meant to be used in contexts where options are potentially different, especially in interactive shells.

In this particular instance, emulate -LR zsh is not needed, because the code is not affected by any option. But it doesn't do any harm.

Here are some examples of options that a user may set in their initialization file, or that may be disabled by surrounding code that calls the function, and that can break a function:

  • Turning off bare_glob_qual breaks the use of glob qualifiers.
  • Turning off care_glob or case_match would make some pattern matching case-insensitive, even though it might not make sense in the function.
  • null_glob and csh_null_glob affect the behavior of glob patterns that match no file.
  • numeric_glob_sort can break a function that requires patterns to be expanded in lexicographic order.
  • err_exit and unset can cause errors where the function's code intended the default behavior (ignore a command's status, treat an undefined variable as empty).
  • That code may be affected by errexit and is affected by posixidentifiers (for $#BUFFER). Note that most widgets shipped with zsh use -L instead of -LR. With -R, you're also resetting things like xtrace which may not be desirable. – Stéphane Chazelas Jun 25 '17 at 7:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.