Skip to content

Commit 1531a99

Browse files
committed
Add dynamic aliases functionality
1 parent 83ae346 commit 1531a99

File tree

3 files changed

+174
-17
lines changed

3 files changed

+174
-17
lines changed

doc/vcsh.1.ronn

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ vcsh(1) - Version Control System for $HOME - multiple Git repositories in $HOME
55

66
`vcsh` [<options>] <command>
77

8+
`vcsh` alias [-d] [<alias>[=<command>]]
9+
810
`vcsh` clone [-b <branch>] <url> [<repo>]
911

1012
`vcsh` delete <repo>
@@ -82,6 +84,15 @@ an interactive user.
8284

8385
## COMMANDS
8486

87+
* alias:
88+
List all aliases in <$XDG_CONFIG_HOME/vcsh/aliases>.
89+
90+
`<alias>`: Print the right side of alias definition.
91+
92+
`<alias>=<command>`: Add alias. Make backup in <$XDG_CONFIG_HOME/vcsh/aliases.bak>.
93+
94+
`-d <alias>`: Delete alias. Make backup in <$XDG_CONFIG_HOME/vcsh/aliases.bak>.
95+
8596
* clone:
8697
Clone an existing repository.
8798

@@ -183,6 +194,17 @@ an interactive user.
183194
As noted earlier, `vcsh` will set <$GIT_DIR> and <$GIT_WORK_TREE> to the
184195
appropriate values for fake bare Git repositories.
185196

197+
## ALIASES
198+
199+
`vcsh' allows to define aliases. The first existing file
200+
201+
* $XDG_CONFIG_HOME/vcsh/aliases
202+
* /etc/vcsh/aliases
203+
204+
will be read. An alias definition has the format `alias = command`.
205+
Empty lines and lines starting with '#' are ignored.
206+
207+
186208
## CONFIG
187209

188210
There are several ways to turn the various knobs on `vcsh`. In order of

t/800-aliases.t

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/perl
2+
#
3+
BEGIN { $ENV{LC_ALL} = 'C' }
4+
5+
use strict;
6+
use warnings;
7+
8+
use Cwd 'abs_path';
9+
use Test::Most;
10+
11+
chdir 't/etc/' or die $!;
12+
13+
$ENV{'HOME'} = abs_path ('.vcsh_home');
14+
15+
chdir '.vcsh_home' or die $!;
16+
17+
my $output = `../vcsh alias`;
18+
ok $output eq "", 'No aliases set up yet.';
19+
20+
system("../vcsh alias ls=list");
21+
$output = `../vcsh alias`;
22+
ok $output eq "ls = list\n", 'Add alias ls';
23+
24+
system("../vcsh alias ci=commit -a");
25+
$output = `../vcsh alias`;
26+
ok $output eq "ls = list
27+
ci = commit -a
28+
", 'Add alias ci';
29+
30+
system("../vcsh alias co=upgrade");
31+
$output = `../vcsh alias`;
32+
ok $output eq "ls = list
33+
ci = commit -a
34+
co = upgrade
35+
", 'Add alias co';
36+
37+
$output = `../vcsh alias ci`;
38+
ok $output eq "commit -a\n", 'Get alias ci';
39+
40+
system("../vcsh alias -d ci");
41+
$output = `../vcsh alias`;
42+
ok $output eq "ls = list
43+
co = upgrade
44+
", 'Delete alias ci';
45+
46+
done_testing;
47+

vcsh

Lines changed: 105 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ help() {
103103
-v Enable verbose mode
104104
105105
commands:
106+
alias [<name>] List defined aliases
106107
clone [-b <branch>] \\
107108
<remote> \\
108109
[<repo>] Clone from an existing repository
@@ -154,6 +155,79 @@ info() {
154155
echo "$SELF: info: $1"
155156
}
156157

158+
alias_read() {
159+
local aliases
160+
if [ -r "$XDG_CONFIG_HOME/vcsh/aliases" ]; then
161+
aliases="$XDG_CONFIG_HOME/vcsh/aliases"
162+
elif [ -r /etc/vcsh/aliases ]; then
163+
aliases=/etc/vcsh/aliases
164+
else
165+
return
166+
fi
167+
168+
sed -r -e 's/#.*//' -ne 's/(\w+)\s*=\s*(.+)/\1 \2/p' "$aliases"
169+
}
170+
171+
alias_get() {
172+
local a cmd
173+
if [ -n "$1" ]; then
174+
alias_read | while read a cmd; do
175+
if [ x"$1" = x"$a" ]; then
176+
echo $cmd
177+
return
178+
fi
179+
done
180+
fi
181+
}
182+
183+
alias_write() {
184+
[ -w "$XDG_CONFIG_HOME/vcsh/aliases" ] ||
185+
[ ! -e "$XDG_CONFIG_HOME/vcsh/aliases" -a -w "$XDG_CONFIG_HOME/vcsh/" ] ||
186+
fatal "File '$XDG_CONFIG_HOME/vcsh/aliases' not writeable"
187+
[ "$2" = '=' ] || fatal 'Invalid alias format'
188+
if [ -n "$(alias_get $1)" ]; then
189+
local regex="s/^$1\s*=.*/$@/"
190+
sed -i.bak -re "$regex" "$XDG_CONFIG_HOME/vcsh/aliases"
191+
else
192+
echo "$@" >> "$XDG_CONFIG_HOME/vcsh/aliases"
193+
fi
194+
}
195+
196+
alias_remove() {
197+
[ -w "$XDG_CONFIG_HOME/vcsh/aliases" ] ||
198+
[ ! -e "$XDG_CONFIG_HOME/vcsh/aliases" -a -w "$XDG_CONFIG_HOME/vcsh/" ] ||
199+
fatal "File '$XDG_CONFIG_HOME/vcsh/aliases' not writeable"
200+
[ -n "$1" ] || fatal 'Empty alias'
201+
local regex="/^$1\s*=/d"
202+
sed -i.bak -re "$regex" "$XDG_CONFIG_HOME/vcsh/aliases"
203+
}
204+
205+
aliases() {
206+
if [ -n "$1" ]; then
207+
local opts subcmd
208+
while getopts d: opts; do
209+
if [ $opts = d ]; then
210+
alias_remove "$OPTARG"
211+
fi
212+
done
213+
shift $(($OPTIND - 1))
214+
local alias="$(echo "$@" | sed -nre 's/(\w+)\s*=\s*(\w.*)/\1 = \2/p')"
215+
if [ -n "$alias" ]; then
216+
alias_write $alias
217+
else
218+
alias_get "$1"
219+
fi
220+
else
221+
# print all aliases
222+
local a cmd
223+
alias_read | while read a cmd; do
224+
if [ -n "$a" ]; then
225+
echo $a = $cmd
226+
fi
227+
done
228+
fi
229+
}
230+
157231
clone() {
158232
hook pre-clone
159233
init
@@ -379,6 +453,7 @@ push() {
379453
hook post-push
380454
}
381455

456+
382457
retire() {
383458
unset VCSH_DIRECTORY
384459
}
@@ -532,23 +607,32 @@ fi
532607

533608
VCSH_COMMAND=$1; export VCSH_COMMAND
534609

535-
case $VCSH_COMMAND in
536-
clon|clo|cl) VCSH_COMMAND=clone;;
537-
commi|comm|com|co) VCSH_COMMAND=commit;;
538-
delet|dele|del|de) VCSH_COMMAND=delete;;
539-
ente|ent|en) VCSH_COMMAND=enter;;
540-
hel|he) VCSH_COMMAND=help;;
541-
ini|in) VCSH_COMMAND=init;;
542-
pul) VCSH_COMMAND=pull;;
543-
pus) VCSH_COMMAND=push;;
544-
renam|rena|ren|re) VCSH_COMMAND=rename;;
545-
ru) VCSH_COMMAND=run;;
546-
statu|stat|sta|st) VCSH_COMMAND=status;;
547-
upgrad|upgra|upgr|up) VCSH_COMMAND=upgrade;;
548-
versio|versi|vers|ver|ve) VCSH_COMMAND=version;;
549-
which|whi|wh) VCSH_COMMAND=which;;
550-
write|writ|wri|wr) VCSH_COMMAND=write-gitignore;;
551-
esac
610+
alias=$(alias_get $VCSH_COMMAND)
611+
if [ -n "$alias" ]; then
612+
VCSH_COMMAND="$alias"
613+
else
614+
case $VCSH_COMMAND in
615+
clon|clo|cl) old_alias=1 ;;
616+
commi|comm|com|co) old_alias=1 ;;
617+
delet|dele|del|de) old_alias=1 ;;
618+
ente|ent|en) old_alias=1 ;;
619+
hel|he) old_alias=1 ;;
620+
ini|in) old_alias=1 ;;
621+
pul) old_alias=1 ;;
622+
pus) old_alias=1 ;;
623+
renam|rena|ren|re) old_alias=1 ;;
624+
ru) old_alias=1 ;;
625+
statu|stat|sta|st) old_alias=1 ;;
626+
upgrad|upgra|upgr|up) old_alias=1 ;;
627+
versio|versi|vers|ver|ve) old_alias=1 ;;
628+
which|whi|wh) old_alias=1 ;;
629+
write|writ|wri|wr) old_alias=1 ;;
630+
esac
631+
if [ -n "$old_alias" ]; then
632+
echo "Aliases now dynamically defined. See vcsh(1) for details."
633+
exit 1
634+
fi
635+
fi
552636

553637
if [ x"$VCSH_COMMAND" = x'clone' ]; then
554638
VCSH_BRANCH=
@@ -614,6 +698,10 @@ elif [ x"$VCSH_COMMAND" = x'status' ]; then
614698
shift
615699
fi
616700
VCSH_REPO_NAME=$2; export VCSH_REPO_NAME
701+
elif [ x"$VCSH_COMMAND" = x'alias' ]; then
702+
shift
703+
aliases $@
704+
exit
617705
elif [ -n "$2" ]; then
618706
VCSH_COMMAND='run'; export VCSH_COMMAND
619707
VCSH_REPO_NAME=$1; export VCSH_REPO_NAME

0 commit comments

Comments
 (0)