zsh history is too short [closed] - zsh

Closed. This question is not about programming or software development. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 3 months ago.
The community reviewed whether to reopen this question 3 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
When I run history in Bash, I get a load of results (1000+). However, when I run history the zsh shell I only get 15 results. This makes grepping history in zsh mostly useless.
My .zshrc file contains the following lines:
HISTFILE=~/.zhistory
HISTSIZE=SAVEHIST=10000
setopt sharehistory
setopt extendedhistory
How can I fix zsh to make my shell history more useful?
UPDATE
If in zsh I call history 1 I get all of my history, just as I do in Bash with history. I could alias the command to get the same result, but I wonder why does history behave differently in zsh and in Bash.

NVaughan (the OP) has already stated the answer in an update to the question: history behaves differently in bash than it does in zsh:
In short:
zsh:
history lists only the 15 most recent history entries
history 1 lists all - see below.
bash:
history lists all history entries.
Sadly, passing a numerical operand to history behaves differently, too:
zsh:
history <n> shows all entries starting with <n> - therefore, history 1 shows all entries.
(history -<n> - note the - - shows the <n> most recent entries, so the default behavior is effectively history -15)
bash:
history <n> shows the <n> most recent entries.
(bash's history doesn't support listing from an entry number; you can use fc -l <n>, but a specific entry <n> must exist, otherwise the command fails - see below.)
Optional background info:
In zsh, history is effectively (not actually) an alias for fc -l: see man zshbuiltins
For the many history-related features, see man zshall
In bash, history is its own command whose syntax differs from fc -l
See: man bash
Both bash and zsh support fc -l <fromNum> [<toNum>] to list a given range of history entries:
bash: specific entry <fromNum> must exist.
zsh: command succeeds as long as least 1 entry falls in the (explicit or implied) range.
Thus, fc -l 1 works in zsh to return all history entries, whereas in bash it generally won't, given that entry #1 typically no longer exists (but, as stated, you can use history without arguments to list all entries in bash).

#set history size
export HISTSIZE=10000
#save history after logout
export SAVEHIST=10000
#history file
export HISTFILE=~/.zhistory
#append into history file
setopt INC_APPEND_HISTORY
#save only one command if 2 common are same and consistent
setopt HIST_IGNORE_DUPS
#add timestamp for each entry
setopt EXTENDED_HISTORY
this is my setting, and it work

Perhaps late however coming across this post and trying to apply it, and failed .... so in practical terms, put this in .zshrc :
alias history='history 1'
and you'll see anything until the HIST_SIZE runs out. To find a command I use (after the .zshrc change)
history | grep "my_grep_string"

Related

ZSH shell start up profiling

my zsh shell has a quite long start up time and if I hold done the enter key the terminal prompt lags behind significantly. So I looked out for solutions and profiling options and found this github issue. Further done one comment suggests to run the following commands:
zsh -xv 2>&1 | ts -i "%.s" > zsh_startup.log
followed by
sort --field-separator=' ' -r -k1 zsh_startup.log> sorted.log
which gives me the following output:
2.106722 ESC[?1hESC=ESC[?1lESC>l
1.388755 ESC[?1hESC=ESC[?1lESC>l
1.185498 ESC[?1hESC=ESC[?1lESC>exit
1.153527 ESC[?1hESC=ESC[?1lESC>ls -la
0.065941 +powerline_precmd:1> PS1=$'%{\C-[[38;5;15m%}%{\C-[[48;5;31m%} ~ %{\C-[[48;5;237m%}%{\C-[[38;5;31m%}%{\C-[[38;5;250m%}%{\C-[[48;5;237m%} Private %{\C-[[48;5;237m%}%{\C-[[38;5;244m%}%{\C-[[38;5;254m%}%{\C-[[48;5;237m%} tmp %{\C-[[48;5;238m%}%{\C-[[38;5;237m%}%{\C-[[38;5;39m%}%{\C-[[48;5;238m%} 1 %{\C-[[48;5;236m%}%{\C-[[38;5;238m%}%{\C-[[38;5;15m%}%{\C-[[48;5;236m%} %# %{\C-[[0m%}%{\C-[[38;5;236m%}%{\C-[[0m%} '
0.052396 +powerline_precmd:1> PS1=$'%{\C-[[38;5;15m%}%{\C-[[48;5;31m%} ~ %{\C-[[48;5;237m%}%{\C-[[38;5;31m%}%{\C-[[38;5;250m%}%{\C-[[48;5;237m%} Private %{\C-[[48;5;237m%}%{\C-[[38;5;244m%}%{\C-[[38;5;254m%}%{\C-[[48;5;237m%} tmp %{\C-[[48;5;238m%}%{\C-[[38;5;237m%}%{\C-[[38;5;39m%}%{\C-[[48;5;238m%} 1 %{\C-[[48;5;236m%}%{\C-[[38;5;238m%}%{\C-[[38;5;15m%}%{\C-[[48;5;236m%} %# %{\C-[[0m%}%{\C-[[38;5;236m%}%{\C-[[0m%} '
...
It looks like the first four commands (or whatever the lines represent) are taking up the majority of the time. I'm having a hard time understanding the output and would like to have some guidance in interpreting the first lines - no need for solving the underlying problem of having a slow shell :) just the interpretation of the first four lines.
The file itself is much longer and I just included the first few lines.
Notes:
I'm using oh-my-zsh with the following plugins
plugins=(
z
git
kubectl
zsh-syntax-highlighting
zsh-autosuggestions
)
I configured l to be an alias for l -la in my .zshrc
this is what happens when I keep pressing the enter key:
(when there are no gaps between prompts I had already released the enter key again)

Select from zsh completion menu by number

I discovered this little navigation trick the other day, which allows me to trigger menu completions by number when I enter 'cd -'
~ cd -
0 -- ~/home
1 -- ~/home/stuff
2 -- ~/downloads
3 -- ~/wallpaper
Shell scripting syntax still reads like a foreign language to me, but to get this functionality my directory stack history is piped into the function below.
DIRSTACKSIZE=9
DIRSTACKFILE=~/.zdirs
if [[ -f $DIRSTACKFILE ]] && [[ $#dirstack -eq 0 ]];
then dirstack=( ${(f)"$(< $DIRSTACKFILE)"} )
[[ -d $dirstack[1] ]] && cd $dirstack[1] && cd $OLDPWD
fi
chpwd() {
print -l $PWD ${(u)dirstack} >$DIRSTACKFILE
}
The magical part is being able to choose from the list by number, but I have come to learn that this is probably
because the functionality for navigation by number is baked in to the 'cd -' command. Still, I'd like to use this everywhere.
Any tips writing a wrapper function (or something like that, I guess) for the completion menu that pipes in completions from the menu when it is triggered
and displays them in a numbered list where those numbers select the corresponding element?
I've gotten started reading the manual and what not, but everything remains rather opaque. Thanks!
First off, the code snippet you show has nothing to do with completion. Instead, what it does is to record the directory stack to a file in order to preserve it between zsh sessions. (Personally, I'm not even sure this is a good idea.)
A good place to start investigating zsh completions is the _complete_help ZLE widget. This is bound by default to ^Xh in zsh's viins (vi insert) keyboard map, but is unbound by default in the emacs keymap. If you want to use it in the emacs keymap (the default for many people), you have to bind it:
bindkey -M emacs "^Xh" _complete_help
Now you can type cd - (or cd +) and follow it by CTRL-Xh instead of TAB. You should see the following output:
tags in context :completion::complete:cd::
directory-stack (_directory_stack _cd)
(At this point I'll admit we're getting close to the limits of my knowledge of the zsh completion system.)
Now you can see the completer functions for the directory-stack tag in this particular context. The one you're probably interested in is _directory_stack, and you can see the content of that function with:
functions _directory_stack
…which is where those leading numbers are actually generated.
Arguably it's possible to write similar completion functions for other completion contexts, and apply the using zstyle. However, this is non-trivial completion magic, and beyond anything I have attempted

In what order does cat choose files to display?

I have the following line in a bash script:
find . -name "paramsFile.*" | xargs -n131072 cat > parameters.txt
I need to make sure the order the files are concatenated in does not change when I use this command. For example, if I run this command twice on the same set of paramsFile.*, parameters.txt should be the same both times. My question is, is this the case? And if it isn't, how can I make sure it is?
Thanks!
Edit: the same question goes for xargs: would that change how the files are fed to cat?
Edit2: as William Pursell pointed out, this question is actually about find. Does find always return files in the same order?
From description in man cat:
The cat utility reads files sequentially, writing them to the standard
output. The file operands are processed in command-line order.
If file is a single dash (`-') or absent, cat reads from the standard input. If file is a UNIX domain socket, cat connects to it
and
then reads it until EOF. This complements the UNIX domain binding capability available in inetd(8).
So yes as long as you pass the files to cat in the same order every time you'll be ok.

Vim execute a command and send out buffer over stdout [duplicate]

This question already has answers here:
Redirect ex command to STDOUT in vim
(3 answers)
Closed 9 years ago.
Here's how you can automate vim in an interesting way:
vim -c '0,$d | r source.txt | 1d | w | q' dest.txt
This uses vim ex commands to erase dest.txt, read source.txt into the buffer, erase the first line (which ends up as a blank line due to the way r works), write to the file (dest.txt), and then quit.
This (as far as I can tell) skips the entire vim terminal UI from loading and is conceptually a little like having a vimscript interpreter.
Now I'd love to be able to take this just one little step further to abuse the capabilities of vim: I want a script to peer at the currently edited changes of an opened file (as part of an interactive automation shell script) which exist in the vim *.swp swapfiles, apply the changes through vim's recover command, and then obtain the output.
Of course it would be perfectly serviceable to use an actual file, e.g. orig_file.txt is being edited in vim in another terminal; my script could do this at each point that the swapfile is detected to change:
cp orig_file.txt orig_file_ephemeral.txt
cp .orig_file.txt.swp .orig_file.txt_ephemeral.txt.swp
vim -c 'recover | w | q'
At this point orig_file_ephemeral.txt shall contain the content of the vim buffer from the other process in which editing is taking place, and we obtained this data without requiring any direct interaction with said process. Which is neat.
Of course for practical purposes it would probably make more sense to do exactly that, and just have the primary vim participate in the process. It would be splitting the functionality for the script out into the configuration of vim, which is a downside, but it would be more straightforward conceptually and computationally as it already has the buffer contents readily available for writing, and it should be straightforward to do so as I believe there exists an autocommand we can use (though whether that autocommand is run prior to saving the swapfile or not remains to be seen).
Either way, for the sake of completeness I'm curious to know if there exists an ex command to write stuff to the STDOUT of vim. Or if this even makes any sense.
I think it perhaps makes no sense as STDOUT is bound to be the actual terminal, e.g. it is where vim sends out its "view" of its UI and the buffer, and everything, to the terminal. So that for example if any of the vim -c 'vimscript commands' commands produce vim errors, I'll be seeing vim's terminal output to display these errors over STDOUT.
Therefore it may only be practical to use a file. But maybe there's some kind of craziness like !tee /dev/fd/3 I could do?
In addition, there is a wrinkle with this roundabout approach, which is that vim presents a Warning: Original file may have been changed error in bright red background text for about a second, and this is surely due to renaming the file. I can likely work around that by doing this work inside of a sub-directory while keeping the filenames identical.
That's the p command (and where the p in grep comes from):
ex -sc '%p|q' file
Would be a bit like cat file.

Memorizing *nix command line arguments

For my developer work I reside in the *nix shell environment pretty much all day, but still can't seem to memorize the name and argument specifics of programs I don't use daily. I wonder how other 'casual amnesiacs' handle this. Do you maintain an big cheat sheet? Do you rehearse the emacs shortcuts when you take your weekly shower? Or is your desk covered under sticky notes?
Using bash_completion is one way of not having to remember the precise syntax of program arguments.
> svn [tab][tab]
--help checkout delete lock pdel propget revert
--version ci diff log pedit proplist rm
-h cleanup export ls pget propset status
add co help merge plist pset switch
annotate commit import mkdir praise remove unlock
blame copy info move propdel rename update
cat cp list mv propedit resolved
If I don't use a command regularly enough to remember what I want, I tend to just use --help or the man pages when I need to.
Or, if I'm lucky, I use CTRL+R and let bash's history search find when I last used it.
Eventually you just remember them, well the set that you use anyway. I used to maintain a README in my home directory when I was starting out but that disappeared many years ago.
One useful command is man -k which you pass a word to and it will return a list of all commands whose man page summary contains that word.
'apropos' is also a very useful command. It will list all commands whose man pages contain the keyword.

Resources