how to enable zsh completion of path with hyphenated words - zsh

The setup
I have my code repos in folder ~/code.
Suppose I have these repos:
~/code/my-repo-awesome
~/code/my-repo-bad
~/code/my-repo-cool
ZSH has nice ability to complete paths.
For example, if I write the following
cd /u/bi/lo
then zsh will complete as follows:
cd /usr/bin/local
Question
Is it possible to configure zsh such that after typing the following
cd ~/co/m-r-c
it will complete to
cd ~/code/my-repo-cool
If so, how?

You can use matcher-list tag.
zstyle ':completion:*' matcher-list '' 'r:|-=* r:|=*'
For reference: http://zsh.sourceforge.net/Doc/Release/Completion-System.html#index-matcher_002dlist_002c-completion-style

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 to specify a custom path for my .zshrc file?

I'm trying to move .zshrc to a folder where I keep this kind of files synced with Github.
But now whenever I start a zsh session it doesn't use that config file.
Assuming I changed the file to ~/.dotfiles how can I add ~/.dotfiles/.zshrc to the PATH(?!) to make zsh start with that config?
Doing source ~./dotfiles/.zshrc only works for that session. Doesn't work anymore if I close the terminal.
You can symlink:
ln -s /path/to/original /path/to/symlink
For the zshrc you can do something like:
ln -s ~/.dotiles/.zshrc ~/.zshrc
One alternative to a symlink is to put this in ~/.zshenv:
ZDOTDIR=~/.dotfiles
If you want .zshenv in ~/.dotfiles as well, you can look into setting ZDOTDIR in one of the global configuration files (/etc/zshenv is a good choice).
Alternatively, you can do what I do and use GNU Stow. I've got my dotfiles in a repository, one subdirectory per category, like so:
dotfilerepo/zsh/.zshrc
dotfilerepo/zsh/.zlogin
dotfilerepo/git/.gitconfig
dotfilerepo/vim/.vimrc
then I can cd into repo and do stow zsh and it'll create a symlink from ~/.zshrc to repo/zsh/.zshrc, another from zsh/.zlogin to ~/.zlogin. stow vim to create symlinks from the vim subdirectory to ~, etc.
I've got a script, install-linkfarm, that does all the stow commands so when I move onto a new machine, I clone my repo, cd to it and run install-linkfarm and am good to go.
You can put this in ~/.zshrc, even as its entire contents:
if [ -r ~/.dotfiles/.zshrc ]; then
source ~/.dotfiles/.zshrc
fi
Please use the export command mentioned below to solve your problem.
export ZDOTDIR=$HOME/.dotfiles
In Linux, you can check if your zsh is loading /etc/zsh/zshrc, and edit it.
If that's the case, redirect this to your custom script by adding:
sh $HOME/.dotfiles/zshrc
Here is an interesting hack that doesn't require you to use sym-links.
In your .xsession, (or .*wmrc) have the following:
xterm -e 'zsh -c ". ~/.dotfiles/.zshrc; zsh"'.
instead of just:
xterm
Make sure to put the -e at the end after all of your other xterm options.

How can I ignore this .build folder for ctags?

I have Exuberant Ctags 5.8 and i'm trying to ignore the .build directory in: packages/ANY/.build. I'm also using ZSH via the oh-my-zsh addon.
I've tried using --exclude=packages/*/.build/, but I just get a
zsh: no matches found: --exclude=packages/*/.build/
The full command i'm using is:
ctags -R --exclude=node_modules --exclude=.meteor --exclude=packages/*/.build/
If I ls the same pattern with ls packages/*/.build/ then I get a list of each .build directory contents.
Is this a limitation of ctags?
You have to quote the * else it is interpreted by the shell. Here zsh tries to find files matching --exclude=packages/*/.build, which of course do not exist.
So this should do the trick:
ctags -R --exclude=node_modules --exclude=.meteor --exclude='packages/*/.build/'
Also, from ctags(1)
--exclude=[pattern]
[...] (be sure to quote the option parameter to protect the wildcards from being expanded by the shell before being passed to ctags; also be aware that wildcards can match the slash character, '/') [...]

automake/gnu make dealing with directories in patterned rules

When I create a patterned rule, or some other custom rule, I need to be able to deal with the target directory not existing. This is for when the project is being built in a directory other than the source directory itself.
For example:
%.out: %.in
gen_file.sh $< > $#
The problem is when somebody specifies a path in the dependency:
some_target: some/path/sample.out
This fails because the some/path directory doesn't exist.
Is there a standard way of getting this directory to be created?
NOTE: I'm trying to use mkdir now, but having issues with getting the directory name as opposed to the filename. Probably just an escaping issue. Update: Got this to work with #mkdir -p $(shell dirname $#) This isn't likely portable.
The way automake does this is by making anything that could depend on a non-existent directory depend on a target some/dir/.dirstamp. The following pattern rule should cover that:
%/.dirstamp:
mkdir -p $(#D)
touch $#
Note also the use of $(#D) to get the directory part of $#. That means you don't have to use $(shell dirname $#) (or the GNU Make built-in $(dir $#)). See the GNU Make manual for more.

how to check if a path is actual or symbolic link

I am writing my own shell program. I am currently implementing the cd command using chdir.
I want to implement the cd with the below options :
-P Do not follow symbolic links
-L Follow symbolic links (default)
When a given path is entered on the shell, how to figure out if the path is a symbolic link or an absolute path progamatically?
Thanks
Check out the lstat() function , you need to use S_ISLNK on the st_mode field.
if [ -L /path/to/file ]; then
echo "is a symlink!"
else
echo "not a symlink! maybe a directory or regular file, or does not exist"
end

Resources