Abbreviated aliasing would be a great feature to bring to shells

Being able to mark in an alias definition a point of minimal abbreviation, an old feature of VAX/VMS shell (DCL) would be really nice in modern *nix shells.

In DCL you used to be able to define an alias (in its own weird syntax) which would be something like this:

$ alias fuz*zyanimals="cat dog"

The asterisk marks minimal unique abbreviation for the alias, such that all of the following invocations would work:

fuz
fuzz
fuzzy
fuzzya
fuzzyan
fuzzyanim
fuzzyanima
fuzzyanimal
fuzzyanimals

so, fuz or fuzzyanimals (or any string in between) will all evaluate "cat dog" ? Why not just use fuz ?

1 Like

Have you had a look at bash completion scripts? These are quite powerful and configurable.

The simplest example with fixed list of arguments:

$ complete -W "cat dog" fuz
$ fuz <tab><tab>
cat     dog
$ fuz c<tab>

Another example if fuz takes directory as 1st parameter:

$compete -A directory fuz
$ fuz <tab><tab>
bin/  code/ perl/  photos/ proj/
$ fuz p<tab><tab>
perl/ photos/ proj/

There is also the ability to fully program the operation of the complete using a function which can be fully tailored to your needs.

2 Likes

Short of forking bash and modifying alias, I don't think there is a way to do what you want. However, this bash function will pollute your environment with lots of aliases. To make things easier I make the assumption that all abbreviations will start at 3 letters and I make no tests for the length of the alias being shorter than 3 letters. Use at your own risk! :smiley:

nalias() {
   local fulline="$*"
   local xalias=${fulline#*=}
   local name=${fulline%%=*}
   local i
   for i in $(seq 3 ${#name})
   do 
      alias ${name::$i}="$xalias"
   done
}

Example:

$ nalias fuzzyanimals='cat dog'
$ alias | grep fuz
alias fuz='cat dog'
alias fuzz='cat dog'
alias fuzzy='cat dog'
alias fuzzya='cat dog'
alias fuzzyan='cat dog'
alias fuzzyani='cat dog'
alias fuzzyanim='cat dog'
alias fuzzyanima='cat dog'
alias fuzzyanimal='cat dog'
alias fuzzyanimals='cat dog'
$ fuzzyanim
cat: dog: No such file or directory
$ 

It would probably be possible to add the asterisk marker into the code to split the alias into minimal abbreviation + rest of alias, then add the latter to the former one letter at a time in a similar manner to the above. But this works for the two aliases I tried it on!

Andrew

Think this should do what you describe:

nalias() {
   local fulline="$*"
   local xalias=${fulline#*=}
   local name=${fulline%%=*}
   local pre=${name%%\**}
   local i

   [ "$pre" == "$name" ] && name=""
   name=${name#${pre}\*}

   for((i=0; i <= ${#name}; i++))
   do
      alias $pre${name:0:$i}=$xalias
   done
}

Of course for i in $(seq 0 ${#name}) can be used in place of the above for(( code for more compatibility with older shells, at the cost of some speed.

1 Like

No, better stick to the for(( bashism, it goes in tune with the ${name:0:$i} bashism!
Also seq is an external command, not available in some OS.

These kind of shortcuts are for an interactive shell.
Bash has the tab key for expansions.
The completion stuff as in post#3 is the correct way.