Expand aliases in non-interactive shells - zsh

In bash, we can use shopt -s expand_aliases to expand aliases in scripts.
What are the equivalent commands for zsh, csh, and tcsh? Do they even exist?
In focusing my efforts on zsh, I haven’t found such a command. I even tried sourcing the file with the aliases inside the script, but it did not work.

For zsh you can use setopt aliases
#!/usr/bin/zsh
alias hoo="echo bar"
unsetopt aliases
hoo # outputs `./test.zsh:5: command not found: hoo`
setopt aliases
hoo # outputs `bar`
see man zshoptions for detail.
For csh and tcsh, sourcing the files (source ${HOME}/.cshrc, for example) suffices.

Related

zsh autocompletion for a specific program

I have a program, let's call it myprog which takes a few options (-o, --option...) with or without argument.
Is there a way to configure zsh so when I use the <TAB> key it lists the options ? It is the case when I type for example ls -<TAB>.
Here is the beginning of the file .zshrc (I found it on the web, without understanding it...) :
# Completion
autoload -U compinit
compinit
zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}'
#compinstall
zstyle ':completion:*:descriptions' format '%U%B%d%b%u'
zstyle ':completion:*:warnings' format '%BSorry, no matches for: %d%b'
zstyle ':completion:*:sudo:*' command-path /usr/local/sbin /usr/local/bin \
/usr/sbin /usr/bin /sbin /bin /usr/X11R6/bin
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path ~/.zsh_cache
zmodload zsh/complist
setopt extendedglob
zstyle ':completion:*:*:kill:*:processes' list-colors "=(#b) #([0-9]#)*=36=31"
If this is possible (I'm sure it is !), is there a way to "distribute" this auto-completion, for example to all the people that will use myprog on their computer
What you can do is distribute a shell function that does the job of generating completion matches for your programme.
If that function is installed, Zsh users will only need the first couple of .zshrc lines to run compinit.
At a technical level, there's a $fpath array in zsh for functions that is analogous to $path. Functions are auto-loaded on demand. If you distribute myprog as software, you would typically have it install the function as $prefix/share/zsh/site-functions/_myprog where $prefix is the install prefix for your software. If you're a local system administrator and want to deploy it with a tool like ansible, check $fpath for the zsh on your OS. Often, you can install it to a file named /usr/local/share/zsh/site-functions/_myprog.
How to write a completion function is too big a subject for a single answer on this site but for options you can use _arguments to do much of the work. Look at some of the examples that come with zsh (they tend to be better quality than others you may find). As a starting point, for what you describe in the question, you might have:
#compdef myprog
_arguments \
'-o[descripton for option with no argument]' \
'--option=[description for option with an argument]:argument:(one two three)' \
'*:remaining argument:_files'
The first line tells compinit which commands (or other things like specific environment variable assignments) the function should complete arguments for.

How do I use to the zsh 'command' option to execute a the builtin 'source' command?

I am trying to log each time my shell sources a file. I am using zsh, so I went into zshenv and added this function.
source() {
echo "sourcing $1"
command source $1
}
The idea is everytime "source [file]" appears in one of my dotfiles and is executed, it should print the action to terminal first, before actually sourcing the file.
instead i'm getting some errors like this
sourcing /Users/js/.cargo/env
source:2: command not found: source
sourcing /Users/js/.sources/postgres-env.sh
source:2: command not found: source
sourcing /Users/js/.oh-my-zsh/oh-my-zsh.sh
source:2: command not found: source
sourcing /Users/js/.iterm2_shell_integration.zsh
source:2: command not found: source
What is the correct way to use the shell 'command' option with zsh to call source here?
command is intended to specifically invoke external commands. For example if you have an alias or function for git, command git will bypass those.
You're looking for the builtin command to limit command lookup to only builtin commands.
source() {
echo "sourcing $1"
builtin source "$1"
}
For it to work regardless of shell, you could use this instead:
#!/usr/bin/env sh
source() {
echo "sourcing $1"
. "$1"
}
source "$1"

Alias ​to open a file by name

Aliases allow you to open certain file formats simply by typing the filename in a terminal. For example, if the file is of type html, htm, it will open in firefox. alias -s {html,htm}=firefox
I could do the same for text files and just list the types I want, but what if the file doesn't have them, like ~/.zshrc or /etc/fstab? How can I open such a file by name?
This function should do what you want (add it to .zshrc):
command_not_found_handler() {
if [[ -o interactive && -w $1 ]]; then
vi $1
else
echo zsh command_not_found_handler: command not found: $# >&2
return 1
fi
}
As the name indicates, this is called whenever zsh is unable to find a command entered in the shell. Now, if a 'command' isn't found, the editor will be invoked on that argument.
The -o interactive test should ensure that the editor is only called when you've typed something in; an invalid command in a shell script will still fail. The -w test checks for editable files.
You may find other conditions to check as you use this.
ETA: As noted in the comments, this only works with simple file names; it will not work if the path to the file is specified.
For common files you edit frequently you can make individual aliases for those files. I have aliases for
alias hosts="sudo vi /etc/hosts"
alias zshrc="vi ~/.zshrc"

Can't write function to replicate the functionality of Bash's 'help' command

I'm trying to replicate Bash's help command in my .zshrc. I thought this would work:
function help {
bash -c "help $#"
}
but this only works when I only pass a single argument -- for instance, help exit. It does not work when I pass options to help, such as help -m exit (which works in Bash). However, literally typing bash -c "help -m exit" works as expected. I imagine this has something to do with how quoting works in the shell, but I can't figure this out.
You can use
function help {
bash -c "help $*"
}
I suppose you need help for using zsh, not for bash. Bash doesn't know anything about zsh builtins and features, and the common builtins are different enough to warrant separate documentation pages.
The equivalent of bash's help builtin is run-help, but it is not active by default. It will also call man for you and comes with a few useful wrappers.
TLDR; put this in .zshrc
autoload -Uz run-help
autoload -Uz run-help-git
autoload -Uz run-help-ip
autoload -Uz run-help-openssl
autoload -Uz run-help-p4
autoload -Uz run-help-sudo
autoload -Uz run-help-svk
autoload -Uz run-help-svn
alias help=run-help
https://wiki.archlinux.org/index.php/zsh#Help_command

How do I get vim's :sh command to source my bashrc?

Whenever I start a shell in vim using :sh, it doesn't source my ~/.bashrc file. How can I get it to do this automatically?
See :help 'shell'. You can set this string to include -l or --login, which will source your .bashrc file. So, you might have a line like this in your .vimrc:
set shell=bash\ --login
Note that this will alter everything that invokes the shell, including :!. This shouldn't be much of a problem, but you should be aware of it.
The value of this command can also be changed by setting the $SHELL environment variable.
If it doesn't source your .bashrc file, it may still source your .bash_profile file. I usually make one of them a symlink to the other. If your .bashrc performs some particularly odd one-time operations, you may have to edit it to only perform those operations with a login shell, but I've never had problems with it.
~/.vimrc
cmap sh<CR> !bash --login<CR>
If you quickly enter "sh<Enter>" in command-line, you can start bash with sourcing ~/.bashrc. So dirty.

Resources