Recently, I accidentally typed !{0}. I think it is some kind of special zsh function because it showed one of my previous commands while I execute it.
What does it mean on zsh?
$ !{0}
Note: I'm using zsh on Ubuntu.
If you're "using zsh on ubuntu" then you are not using bash. bash and zsh are two different shells, which have slightly different behaviours.
In both shells, ! introduces a history expansion, which replaces the ! and following word with something taken from the command history.
In zsh, !{0} will be replaced with the previous command you typed which started with 0; the same as !0. In bash, the braces are treated literally, so !{0} will be replaced with the previous command which started with {0}. In both shells, !1 will be replaced with the first command in the history (if it is still remembered); in zsh, !{1} will also be replaced with the first command in the history, while in bash it will be replaced by a command starting with {1}
Related
In macOS Catalina (10.15.6), I want to use zsh for Terminal sessions. Formerly I had been using the default bash. For bash, I had a .profile containing the line
export PS1="[\u#\h:\w]$ "
which gave a prompt of the form:
[me#myhost:current-dir]$
I want something similar for zsh, but without the user-name#host-name prefix and with # instead of $ for the actual prompt.
In a zsh Terminal session, the command
PROMPT='[%/]%% '
gives the expected prompt, with the current directory enclosed in square brackets.
Of course I don't want to enter that manually each time. Instead, I want to set this in .zprofile. So in .zprofile I included the line
export PROMPT='[%/]%% '
However, that does not work as expected -- the prompt now has the form:
me#myhost current-dir %
Question: How can I get the zsh prompt to have the desired form as follows?
[current-dir] %
Just add the following export to ~/.zshrc, otherwise it won't work.
export PROMPT='[%1~] %%'
That will give you the following, my directory name is test-workflow-branch-only
[test-workflow-branch-only] %
NOTE: This will give you [~] % when in ~/ directory so don't be alarmed when you see that
UPDATE - per comment questions
We add it to ~/.zshrc as this file gets sourced in all interactive shell configurations. The file ~/.zprofile are for commands that we want to execute when we log in, therefore a non-login shell won't source this file.
Thanks for info from Edward Romero. My critique of answer is that it contains four wasted characters, '[',']',' ','%'. Using instead PROMPT='%d>' yields the nice clear absolute path, something like this:
/Users/myuser/test-workflow-branch-only>
In any case, nice to get this headache behind me, and begin reaping the wonderful benefits of using zsh, whatever they may be.
If I invoke
Rscript -e "print('hello')"
It correctly prints out the answer
[1] "hello"
However, if I switch single and double quotes, it does not work, and it looks like the double quotes are removed:
Rscript -e 'print("hello")'
gives:
Error in print(hello) : object 'hello' not found
Execution halted
Note that it's not powershell doing the escaping incorrectly. Echoing only gives the expected results:
PS> echo 'print("hello")'
print("hello")
PS> echo "print('hello')"
print('hello')
And the same behavior is not observed on macOs or Linux, where both variants are correctly parsed.
Interestingly enough, it's even crazier for command.com:
C:>Rscript -e "print('hello')"
[1] "hello"
C:>Rscript -e 'print("hello")'
[1] "print(hello)"
I mean... what?!?
This has already been mentioned here:
Single line code to run R code from Windows command line
but there's no explanation about it. In my opinion it's a bug of Rscript on windows, but I want to hear other opinions.
Dabombber's helpful answer provides all the pointers, but let me try to boil it down conceptually:
The problem is not specific to RScript.exe and potentially affects calls to any external executable from PowerShell:
Up to at least PowerShell 7.1 (current as of this writing), passing arguments with embedded double quotes (") to external programs is fundamentally broken, as detailed in GitHub issue #1995; in short: behind the scenes, PowerShell constructs a command line for the target program (process) that uses "..."-quoting only, but neglects to escape embedded verbatim " chars. for their syntactically valid inclusion in such double-quoted strings; a fix may be coming in v7.2 - see this answer.
For now, you have to manually escape embedded " chars. as \".
However, if and when the bug gets fixed, this workaround will break, because the fix requires that this escaping be applied automatically, which would then escape a verbatim \" as \\\".
# WORKAROUND as of v7.0, which will break if and when the problem gets fixed.
PS> Rscript -e 'print(\"hello\")'
The third-party Native module (install with Install-Module -Scope CurrentUser Native, for instance) offers helper function ie, which compensates for the broken behavior; it is written in a forward-compatible manner so that it will simply defer to the built-in behavior if and when it should get fixed:
# Thanks to `ie`, no workarounds are required.
PS> ie Rscript -e 'print("hello")'
As for ad hoc workarounds - both of them work for Rscript.exe, but can't be expected to be a general solution:
For target programs that support both '...' and "..." quoting: Swap the quotes to use only embedded ' chars., as shown in your question, but note that '...' and "..." strings have different semantics in PowerShell ("..." strings are expandable (interpolating) strings), and may have different semantics in the target program too (not the case in Rscript):
Rscript -e "print('hello')"
For target programs that accept input via stdin, use the PowerShell pipeline, where the bug doesn't surface (though note that you may have to set the $OutputEncoding preference variable to the character encoding expected by the target program):
'print("hello")' | Rscript -
As for your observations and background information, including about cmd.exe and POSIX-compatible shells:
Note that it's not powershell doing the escaping incorrectly.
As Dabombber points out, it is PowerShell that is the problem, but the problem only occurs when calling external programs, whereas echo is a built-in alias for the PowerShell-native
Write-Output cmdlet (verify with Get-Command echo).
On Windows, you could see the problem with the flawed parameter passing as follows, by invoking choice.exe (ignore the [Y,N]?N suffix):
PS> 'n' | choice /m 'print("hello")'
print(hello) [Y,N]?N
choice.exe with /m can be used to echo an argument as it would be received by external programs, and as you can see the double quotes were effectively lost, because PowerShell mistakenly placed print("hello") verbatim on the process command line - without escaping the " chars. - which external programs parse as verbatim print(hello), because they allow a single argument to be composed of unquoted and double-quoted parts (print( + hello (stripped of the syntactic double quotes) + )).
If verbatim print(hello) is interpreted as an R script, it looks for a variable (object) named hello - which in this scenario doesn't exist and triggers the error message you saw.
On Unix-like platforms (macOS, Linux), using the cross-platform PowerShell [Core] edition, /bin/echo 'print("hello")' shows the same problem.
And the same behavior is not observed on macOs or Linux, where both variants are correctly parsed.
Yes, if you use a native, POSIX-compatible shell there, such as bash, you'll get the correct behavior (see below).
it's even crazier for command.com:
As an aside: You probably meant cmd.exe, the legacy command processor (Command Prompt) on NT-based Windows platforms up to the current Windows 10.
(command.com was the command processor on the extinct DOS-based Windows versions that ended with Windows ME).
cmd.exe only recognizes double-quoting ("...") to demarcate argument boundaries for itself, not also single-quoting ('...'); irrespective of that, it essentially passes the original quoting through to the target executable (after performing its own interpretation of the command line, such as environment-variable expansion).
This differs fundamentally from what PowerShell and POSIX-compatible shells do:
On Unix-like platforms - where POSIX-compatible shells recognize '...'-quoted arguments - the concept of a process command line doesn't exist, and whatever arguments a POSIX-like shell has itself parsed out of its command line are passed as-is - as an array of verbatim arguments - to the target executable; thus shell string literals "print('hello')" and 'print("hello")' are passed as verbatim print('hello') and print("hello"), respectively, which works as expected, given that R too recognizes both '...' and "..." string literals.
PowerShell too has '...' strings (it treats their content verbatim), but on Windows it translates them to "..." strings behind the scenes (if quoting is needed), which is where the aforementioned bug can surface as of v7.0. The bug aside, this translation makes sense, because only "..." quoting can be assumed to have syntactic meaning on the command line for other programs (see bottom section). Unfortunately, PowerShell does the same thing on Unix-like platforms, even though it shouldn't (it constructs a pseudo command line that the .NET API then parses into an array of verbatim arguments passed to the target process), so the bug surfaces there as well.
Because cmd.exe preserves the original quoting, RScript interprets 'print("hello")' in command line Rscript -e 'print("hello")' as a string literal rather than as a command, because it removes any " chars. with syntactic function on the command line first (whereas ' (single quotes) by convention do not have syntactic meaning on the command line), before the result is interpreted as an R script:
'print("hello")' is therefore parsed as 'print( + hello (the command-line " are stripped) + ), resulting in verbatim 'print(hello)' getting interpreted as R code, which is an R string literal that therefore prints as-is (the output uses "..." quoting, but that's just an artifact of output formatting; note that an explicit call to print() isn't necessary, the result of an expression - such as string literal 'print(hello)' in this case - is automatically printed).
By contrast, "print('hello')" is parsed as verbatim print('hello') (the command-line " are stripped), which - due to the absence of enclosing quoting - is then interpreted as a command, namely a print() function call, as intended.
Ultimately, there are no hard and fast rules in the anarchic world of process command-line parsing on Windows: it is ultimately up to each program to interpret its command line - this answer contains excellent background information.
Fortunately, however, there are widely adhered-to conventions, as implemented in the MS C/C++/.NET compilers and documented here.
Unfortunately, as of PowerShell 7.0, PowerShell doesn't adhere to these conventions, due to the aforementioned bug. Since the bug has been around since v1, users have learned to work around it, such as with manual \"-escaping, as shown above. The problem is that fixing the bug would break all workarounds. Implementing a fix as an experimental feature is now being considered, for v7.1 at the earliest - see this PR on GitHub and the associated discussion here, which suggests that, in addition to implementing the widely established conventions, accommodations be made for calls to batch files and msiexec.exe-style programs, which have non-conventional quoting requirements.
It might be worth taking a look through this PowerShell issue: Arguments for external executables aren't correctly escaped. The Native module by Michael Klement provides a workaround until the problem is fixed (and shouldn't be broken post-fix like many current workarounds).
Note that it's not powershell doing the escaping incorrectly. Echoing only gives the expected results
echo is a PowerShell function rather than an external program so you won't notice the broken behaviour when using it.
PS> Get-Command echo
CommandType Name Version Source
----------- ---- ------- ------
Alias echo -> Write-Output
A better test would be to use the EchoArgs.exe command line tool from PowerShell
Community Extensions (downloadable here).
PS> echoargs.exe 'print("hello")'
Arg 0 is <print(hello)>
Command line:
"E:\echoargs.exe" print("hello")
PS> echoargs.exe "print('hello')"
Arg 0 is <print('hello')>
Command line:
"E:\echoargs.exe" print('hello')
Note that it's not powershell doing the escaping incorrectly. Echoing
only gives the expected results:
In the case of using echo, its echo which is directly consuming the argument you are passing to it, so you get the same result for single quotes or double quotes.
In the case of Rscript, I believe Rscript is just a convenient way of calling R with some additional arguments. (see https://swcarpentry.github.io/r-novice-inflammation/05-cmdline/ for explanation). Specifically, it says that "From this output, we learn that Rscript is just a convenience command for running R scripts...."
So maybe what's happening is that when you call RScript, its passing the argument to a separate process, and because of this its trying to expand hello as a variable, leading to the error (in the Powershell case)
As for cmd it has its own behavior for handling single and double quotes.
See: What does single-quoting do in Windows batch files?
and
Differences between single and double quotes in CMD
So the problem may not be with RScript. The resulting output of your use case may just be a side effect of how powershell and cmd handle double quotes and single quotes.
This may also explain why the problem is there only on windows, and not in Linux or MacOS.
Check out this one! https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7
expressions in single-quoted strings are not evaluated. They are interpreted as literals.
in a double-quoted string, expressions are evaluated, and the result is inserted in the string.
same rules apply for cmd
Problem steps like this:
copy text 'kill-server' to system clipboard
hit Prefix : to enter the tmux command prompt
hit command+v to paste
The result paste text is 200~kill-server201~ instead of kill-server. This weird bracketed paste mode text do not happen in shell prompt but in tmux command prompt, and I had tried to turn off bracketed paste mode but without luck.
Environment that has this issue:
Mac OS 10.11.1, iTerm, zsh 5.0.7, Tmux 2.1
Mac OS 10.10.1, iTerm, zsh 5.1.1, Tmux 1.9
Environment that without this issue:
Mac OS 10.11.1, iTerm, bash, Tmux 2.1
I'm posting this as an answer because it's a bit too long and I need some formatting... So here it goes.
I can reproduce only with zsh 5.1+. There's no reason to expect the problem on 5.0.x, because bracketed paste mode was introduced in 5.1. You might be doing something wrong in your testing, or there might be something peculiar about your setup, in which case you have to explain better. Also, iTerm2 probably doesn't play any part in this, since I could reproduce in Terminal.app just fine (of course they could both have the same defect...).
Considering bracketed paste mode is a ZLE feature, I think (disclaimer: the rest of this paragraph is purely my speculation) the real problem is that tmux uses the underlying shell's line editing features (ZLE, in zsh's case) in its command prompt to offer better editing experience (for instance, you have access to all the Emacs style shortcuts there), but its command prompt is a dumb term, and doesn't understand the bracketed paste sequences. So we have this weird situation of two modes of terminal emulation within tmux, one is fairly smart which happens within each pane, and the other is dumb which happens in its command prompt.
Solutions and workarounds:
This is probably worth reporting to tmux. https://github.com/tmux/tmux/issues.
Turn off ZLE bracketed paste. It does work, you're probably doing it wrong. If you don't mind losing bracketed paste in tmux, you could put the following somewhere in your shell init sequence:
(( $+TMUX )) && unset zle_bracketed_paste
In iTerm2, you have access to advanced paste (Edit->Paste Special->Advanced Paste..., or ⌥⌘V). Just uncheck "Bracketed paste mode", and you shouldn't see the escape sequences.
I solved this problem finally just deactivated the safe-paste plugin in my oh-my-zsh.
The safe-paste used to fix zsh up arrow completion issue. But now, the arrow completion issue is gone while inducing tmux bracketed paste problem. I haven't dived into the code of safe-paste yet. Hope to help others encountering the same problem.
I'm new to Vim. I was experimenting with vim-powerline and tmux (and pathogen and vundle).
Somwehere in that process I tried to remove powerline and tmux started receiving this error.
My .tmux.conf file is empty. How can I find where tmux is trying to run this command?
I had this problem, too, but not in the first tmux window. It only happened for me in subsequent windows. I found a solution, but not exactly the cause of the problem.
The short version is the set the value of the POWERLINE_COMMAND variable in your .bashrc on the line before you source the bash binding. For me, that means:
export POWERLINE_COMMAND="$HOME/powerline/scripts/powerline"
. $HOME/powerline/powerline/bindings/bash/powerline.sh
I don't get exactly why this happens in subsequent tmux windows but I added some echo lines to the bash binding to find out what's happening. When the binding is sourced in subsequent windows, POWERLINE_COMMAND is already set to powerline, so it skips the code that checks for the right place to set it. I couldn't figure out where, how, or why it's already set, though.
Here's the code that does the check from the beginning of the bash binding:
if test -z "${POWERLINE_COMMAND}" ; then
if which powerline-client &>/dev/null ; then
export POWERLINE_COMMAND=powerline-client
elif which powerline &>/dev/null ; then
export POWERLINE_COMMAND=powerline
else
# `$0` is set to `-bash` when using SSH so that won't work
export POWERLINE_COMMAND="$(dirname "$BASH_SOURCE")/../../../scripts/powerline"
fi
fi
Since it works in the first window, I just set POWERLINE_COMMAND to point to the command that it points at in the first window. Setting it before sourcing the bash binding skips the whole check.
I suggest you to check your shell's configuration files. If you use e.g. use bash, check $HOME/.{bashrc,profile} or $HOME/.zshrc for zsh. There is probably a line like
. {repository_root}/powerline/bindings/bash/powerline.sh
according to the powerline installation instructions.
This question is about configuring the R console to behave like a bash shell when it comes to navigating the command history. It is somewhat related to the ?history. For brace-enclosed multi-lines, I'd like to configure the command history navigation of R to be similar to bash.
Presently when running R in an xterm under Linux, using the up-arrow to navigate the command history causes each previous line to be recalled one by one, even if a set of lines had been enclosed in braces. This occurs, for example, when copy/pasting a multi-line function from a text editor into the R console. Not so with bash.
Here is an example of how bash functions in this regard:
In a bash shell within an xterm under Linux, after typing the following five lines...
a=1
{
x=1
y=1
}
... the first press of the up-arrow will recall a single line reformulation of the brace-enclosed commands, like this ...
{ x=1; y=1; }
... and the second press will recall this ...
a=1
It seems that in R, the up-arrow navigates backwards one line at a time, regardless of encapsulation. Is there a way to configure R so that it's command history navigation functions like bash's?
You could use rlwrap. I use it for other console programs and it works very well. You will need to prepend the R command with the rlwrap binary and then your history lines can be restored in a number of ways, including multi-line matching.
Workaround for Linux/Unix
Similarly as in Rstudio (thanks to Ari B. Friedman comment), where user in R console is using ShiftEnter to bypass RETURN, you can start newline (in R terminal) without accepting newline command using Ctrl-VCtrl-J. This way the multi-line command will be accepted into history as one-liner with line-feeds instead of enters and you will even have the chance to edit it. You can even manage in your .inputrc file to have custom combination for this action.
I do not think direct reconfiguration of R is possible.
Readline man page may help more.