# More csh completions



## wblock@ (Oct 14, 2012)

Looking to add to my csh(1) completions.  For me, they are almost as good as a man page.  Arguably better, especially when they substitute only valid values.

Does anyone have completions for pfctl(8), zfs(8), or zpool(8)?

The full set of completions I've collected are here: http://www.wonkity.com/~wblock/csh/completions

Many of those came from examples, some from online sources including these forums, and a few are my own.  Many have been customized from generic versions to work better with FreeBSD.  Some common examples have been left out as not very useful, and more could be removed from there.

There are two styles.  The normal style actually substitutes parameters.  The other style shows valid choices, like the gpart(8) completion there (that one was one of the few I've written).  Either type is good, although the actual-value substitution is probably better when possible.


----------



## UNIXgod (Oct 14, 2012)

I'm not sure this will help. It's also online for zsh. It may be something to easy to convert. I'll post the link and the code as it looks like it's from a cache and the site is down:

http://www.zsh.org/mla/workers/2009/msg00815.html
cache:
https://webcache.googleusercontent..../2009/msg00815.html+&cd=1&hl=en&ct=clnk&gl=us


```
#compdef pfctl

local pfctl_flush_modifiers pfctl_optimizer_level pfctl_show_modifiers pfctl_tables_command pfctl_debug_level

pfctl_flush_modifiers=(
    'all:Flush all'
    'info:Flush the filter information'
    'nat:Flush the NAT rules'
    'osfp:Flush the passive operating system fingerprints'
    'queue:Flush the queue rules'
    'rules:Flush the filter rules'
    'state:Flush the stable table'
    'Sources:Flush the source tracking table'
    'Tables:Flush the tables'
)

pfctl_show_modifiers=(
    'nat:Show the currently loaded NAT rules'
    'queue:Show the currently loaded queue rules'
    'rules:Show the currently loaded filter rules'
    'Anchors:Show the currently loaded anchors directly attached to the main ruleset'
    'state:Show the contents of the state table'
    'Sources:Show the contents of the source tracking table'
    'info:Show filter information'
    'labels:Show per-rule statistics of filter rules with labels'
    'timeouts:Show the current global timeouts'
    'memory:Show the current pool memory hard limits'
    'Tables:Show the list of tables'
    'osfp:Show the list of operating system fingerprints'
    'Interfaces:Show the list of interfaces and interface drivers available to PF'
    'all:Show all except for the lists of interfaces and operating system fingerprints'
)

pfctl_optimizer_level=(
    'none:Disable the ruleset optimizer'
    'basic:Enable basic ruleset optimizations'
    'profile:Enable basic ruleset optimizations with profiling'
)
pfctl_tables_command=(
    'kill:Kill a table'
    'flush:Flush all addresses of a table'
    'add:Add one or more addresses in a table'
    'delete:Delete one or more addresses from a table'
    'expire:Delete addresses which had their statistics cleared more than number seconds ago'
    'replace:Replace the addresses of the table'
    'show:Show the content (addresses) of a table'
    'test:Test if the given addresses match a table'
    'zero:Clear all the statistics of a table'
    'load:Load only the table definitions from pf.conf(5)'
)
pfctl_debug_level=(
    "none:Don\'t generate debug messages" 
    'urgent:Generate debug messages only for serious errors' 
    'misc:Generate debug messages for various errors' 
    'loud:Generate debug messages for common conditions'
)
_iface() {
    local pfctl_iface
    pfctl_iface=($(pfctl -s Interfaces))
    compadd $pfctl_iface
}
_tables() {
    local pfctl_tables
    pfctl_tables=($(pfctl -s Tables))
     compadd $pfctl_tables
}
# TODO:
# Missing -a
#
_arguments -s \
    '-F[Flush the filter parameters specified by modifier]:modifier:(($pfctl_flush_modifiers))' \
    '-A[Load only the queue rules present in the rule file]' \
    '-D[Define macro to be set to value]:macro:' \
    '-d[Disable the packet filter]' \
    '-e[Enable the packet filter]' \
    '-f[Load the rules contained in a file]:configuration file:_files' \
    '-g[Include output helpful for debugging]' \
    '-h[Help]' \
    '-i[Restrict the operation to the given interface]:interface:_iface' \
    '-K[Kill all of the source tracking entries originating from the specified host or network]:host or network:_hosts' \
    '-k[Kill all of the state entries originating from the specified host or network]:host or network:_hosts' \
    '-m[Merge in explicitly given options]' \
    '-N[Load only the NAT rules present in the rule file]' \
    '-n[Do not actually load rules, just parse them]' \
    '-O[Load only the options present in the rule file]' \
    '-o[Control the ruleset optimizer]:level:(($pfctl_optimizer_level))' \
    '-p[Use the device file device instead of the default /dev/pf]:device:_files' \
    '-q[Only print errors and warnings]' \
    '-R[Load only the filter rules present in the rule file]' \
    '-r[Perform reverse DNS lookups on states when displaying them]' \
    '-s[Show the filter parameters specified by modifier]:modifier:(($pfctl_show_modifiers ))' \
    '-T[Specify the command to apply to the table]:command:(($pfctl_tables_command))' \
    '-t[Specify the name of the table]:table:_tables' \
    '-v[Produce more verbose output]' \
    '-x[Set the debug level]:debug level:(($pfctl_debug_level))' \
    '-z[Clear per-rule statistics]'
```


----------



## SirDice (Oct 15, 2012)

wblock@ said:
			
		

> Does anyone have completions for pfctl(8), zfs(8), or zpool(8)?



There are a whole bunch of examples in /usr/share/examples/tcsh/complete.tcsh.

As for ZFS, I've found these, can't remember where though.


```
set zpool_cmd = (create destroy add remove list iostat status\
                online offline clear attach detach replace scrub\
                import export upgrade history get set)

        set zfs_cmd =   (create destroy snapshot rollback clone promote\
                rename list set get inherit mount unmount\
                share unshare send receive)

        complete zpool \
                'p/1/$zpool_cmd/'\
                'n/destroy/`zpool list -H -o name`/'\
                'n/add/`zpool list -H -o name`/'\
                'n/remove/`zpool list -H -o name`/'\
                'n/list/`zpool list -H -o name`/'\
                'n/iostat/`zpool list -H -o name`/'\
                'n/status/`zpool list -H -o name`/'\
                'n/online/`zpool list -H -o name`/'\
                'n/offline/`zpool list -H -o name`/'\
                'n/clear/`zpool list -H -o name`/'\
                'n/attach/`zpool list -H -o name`/'\
                'n/detach/`zpool list -H -o name`/'\
                'n/replace/`zpool list -H -o name`/'\
                'n/scrub/`zpool list -H -o name`/'\
                'n/import/`zpool list -H -o name`/'\
                'n/export/`zpool list -H -o name`/'\
                'n/upgrade/`zpool list -H -o name`/'\
                'n/history/`zpool list -H -o name`/'\
                'N/get/`zpool list -H -o name`/'\
                'N/set/`zpool list -H -o name`/'

        complete zfs \
                'p/1/$zfs_cmd/'\
                'n/create/`zfs list -H -o name`/'\
                'n/destroy/`zfs list -H -o name`/'\
                'n/snapshot/`zfs list -H -o name`/'\
                'n/rollback/`zfs list -H -t snapshot -o name`/'\
                'n/clone/`zfs list -H -t snapshot -o name`/'\
                'n/promote/`zfs list -H -o name`/'\
                'n/rename/`zfs list -H -o name`/'\
                'n/list/`zfs list -H -o name`/'\
                'N/set/`zfs list -H -o name`/'\
                'N/get/`zfs list -H -o name`/'\
                'n/inherit/`zfs list -H -o name`/'\
                'n/mount/`zfs list -H -o name`/'\
                'n/unmount/`zfs list -H -o name`/'\
                'n/share/`zfs list -H -o name`/'\
                'n/unshare/`zfs list -H -o name`/'\
                'n/send/`zfs list -H -t snapshot -o name`/'\
                'n/receive/`zfs list -H -o name`/'
```

They work quite reasonably but can't seem to deal with options. That breaks the completion


----------



## wblock@ (Oct 15, 2012)

Many of mine came from /usr/share/examples.  But some of those were generic and not quite right for FreeBSD, so I updated them.  Can't recall specifics, though.

The options problem is why I went with the x: version for gpart(8).  Showing what is allowed can be considered a context-sensitive help feature:


```
% gpart [I][color="Red"]tab[/color][/I]
add      bootcode create   destroy  recover  restore  show     unset
backup   commit   delete   modify   resize   set      undo     
% gpart create [I][color="Red"]tab[/color][/I]
-s scheme [-n entries] [-f flags] provider
```


----------



## bkouhi (Feb 4, 2013)

Here are some other completions, but some of them are incomplete..


```
complete pkg 'c/-/(d j c v)/'	\
		'n/add/f:*.{txz,tbz,tgz}/'	\
		'n/remove/`pkg_info |cut  -d" " -f1`/' \
		'n/delete/`pkg_info |cut  -d" " -f1`/' \
		'n/info/`pkg_info |cut  -d" " -f1`/' \
		'n/update/`pkg_info |cut  -d" " -f1`/' \
		'n/which/f/'	\
		'p/*/( add audit autoremove backup check clean create delete fetch help info install query register \
remove repo rquery search set shell shlib stats updating upgrade version which )/'
		
complete portsnap	'c/-/(d f I k l p s)/' \
			'n/-d/d/'	\
			'n/-f/f/'	\
			'n/-p/d/'	\
			'p/*/(fetch extract update)/'
			
complete apachectl	'p/1/(start stop restart fullstatus status graceful graceful-stop configtest)/'

complete postfix	'c/-c/f/'	\
			'p/*/(check start stop abort flush reload status)/'
			
complete sudo	'p/*/c/'

complete squid 'c/-/(d f h i k n r s l u v z C D F I N O R X Y)/'\
		'n/-k/(reconfigure rotate shutdown interrupt kill debug check parse)/'	\
		'n/-f/f/'

complete Xorg	'c/-/(config configdir configure gamma logfile logverbose showconfig)/'

complete wget	'c/--/(input-file no-clobber continue timestamping spider limit-rate wait no-proxy user password header recursive \
convert-links mirror page-requisites domains include-directories exclude-directories no-parent html-extension)/'

complete gpg	'c/--/(sign clearsign encrypt decrypt verify verify-files encrypt-files decrypt-files list-keys \
list-public-keys list-secret-keys delete-key fingerprint check-sigs delete-secret-key export send-keys recv-keys \
search-keys fetch-keys gen-key edit-key sign-key keyserver armor)/'
```


----------



## Carpetsmoker (Feb 6, 2013)

I did some disk recovery with parted magic this afternoon, and I noticed I can complete dd, this works as expected:
`$ dd if=/dev/s<Tab>`

That would be nice to have ... My last experience with tcsh completions left me traumatized for a week, so I'm not going to try, but if anyone is feeling brave ...


----------



## wblock@ (Feb 6, 2013)

That's a good idea, it bugs me every time when it can't complete after if=.  For a start:


```
complete dd 'c/if=/f/' 'c/of=/f/'
```


----------



## fonz (Feb 6, 2013)

wblock@ said:
			
		

> it bugs me every time when it can't complete after if=.


My sentiments, exactly. Between this and the inability to separately redirect stdout and stderr (at least not easily), it's pretty much all that I don't like about tcsh(1).


----------



## wblock@ (Feb 6, 2013)

That completion problem is due to dd(1)'s oddball option specs.  Bash and sh aren't particularly smart about it, seem to just offer to complete with a filename if unknown.  I prefer csh(1)'s catlike indifference to sh(1)'s doglike desire to please with the wrong thing.


----------



## bkouhi (Feb 7, 2013)

completion for dd(1)():

```
complete dd	'c/if=/f/' 'c/of=/f/'	\
		'c/conv=*,/(ascii block ebcdic lcase pareven noerror notrunc osync sparse swab sync unblock)/,' \
		'c/conv=/(ascii block ebcdic lcase pareven noerror notrunc osync sparse swab sync unblock)/,' \
		'p/*/(bs cbs count files fillcahr ibs if iseek obs of oseek seek skip conv)/='
```

EDIT:

Oh, I found an useful link: complete.tcsh


----------



## Carpetsmoker (Mar 7, 2013)

I've updated some of my completions, some borrows posts in this thread, I've modified/improved some for clarity or personal taste.

In general, all completions should be cross-platform (ie. also works on Linux), and FreeBSD-specific stuff *only* works on FreeBSD (this is especially useful with commands that also exist on Linux, for example the service and kill completions in the OP give errors on Linux).

I did remove many of the single-character arguments as completions, it doesn't seem to matter if I press the `x' or `tab' key. I guess they're there as a mnemonic (?)

Another useful option is `fignore', this allows you to ignore certain file extensions when completing (for example .o or .pyc), note that this *only* works if there is just one completion possible (at first I thought it was broken).

https://bitbucket.org/Carpetsmoker/...285dfd8d40a8b/etc/csh.cshrc?at=default#cl-304


----------



## bkouhi (Apr 25, 2013)

> I did remove many of the single-character arguments as completions, it doesn't seem to matter if I press the `x' or `tab' key. I guess they're there as a mnemonic (?)



How about this kind of completion?


```
complete mergemaster    'c/-p/x:-p :  Pre-buildworld mode./' \
                        'c/-h/x:-h :  Display usage and help information./' \
                        'c/-v/x:-v :  Be more verbose about the process./'  \
                        'c/-a/x:-a :  Run automatically./' \
                        'c/-U/x:-U :  auto upgrade files that have not been user modified./' \
                        'c/-i/x:-i :  install any files that do not exist in the destination./' \
                        'c/-F/x:-F :  install the new file if the files differ only by VCS Id./' \
                        'c/-c/x:-c :  Use context diffs instead of unified diffs./'
```

For example:


```
[CMD]# mergemaster -v[/CMD][color="Red"][tab][/color]
-v :  Be more verbose about the process.
[CMD]# mergemaster -i[/CMD][color="Red"][tab][/color]
-i :  install any files that do not exist in the destination.
[CMD]# mergemaster -U[/CMD][color="Red"][tab][/color]
-U :  auto upgrade files that have not been user modified.
```


----------



## bkouhi (Apr 26, 2013)

Here is another set of tcsh/csh auto completion: (Link)

HTH


----------



## kpa (Apr 26, 2013)

Those mergemaster(8) completions are quite neat, however mergemaster is often run only in single user mode where the shell is plain sh(1). Nothing prevents one from applying the same method to other tools, let's say portmaster(8).


```
complete portmaster 'c/-L/x:-L :  List all installed ports by category, and search for updates/'
```


----------



## wblock@ (Dec 17, 2013)

Does anyone have a good set of completions for pkg yet?


----------



## nickednamed (Dec 17, 2013)

I've not written any completions for tcsh before, but zsh has the completions for pkgng. Here is the completion file for zsh.

Perhaps you can gut this file, or make use of it somehow.


----------



## wblock@ (Jan 29, 2014)

The tcsh mailing list pointed me at the Git completion that can be found in search.  I'd never really understood it before, but finally sat down and looked at it for a while.  It uses xargs(1) and echo(1) to build a list of completions including options with dashes and subcommand names to use with n, and then it uses N to complete just subcommand names.  Based on that, this is what I have for pkg(8) so far:


```
# shortcut to retrieve list of all installed packages
  alias __pkgs 'pkg info -E'

  set pkgcmds=(help add annotate audit autoremove backup check clean convert create delete fetch info install lock plugins \
                        query register repo rquery search set shell shlib stats unlock update updating upgrade version which)
  
  # aliases that show lists of possible completions including both package names and options
  alias __pkg-check-opts        '__pkgs | xargs echo -B -d -s -r -y -v -n -a -i g x'
  alias __pkg-del-opts  '__pkgs | xargs echo -a -D -f -g -i -n -q -R -x -y'
  alias __pkg-info-opts '__pkgs | xargs echo -a -A -f -R -e -D -g -i -x -d -r -k -l -b -B -s -q -O -E -o -p -F'
  alias __pkg-which-opts        '__pkgs | xargs echo -q -o -g'
                        
  complete pkg          'p/1/$pkgcmds/' \
                        'n/check/`__pkg-check-opts`/' \
                        'N/check/`__pkgs`/' \
                        'n/delete/`__pkg-del-opts`/' \
                        'N/delete/`__pkgs`/' \
                        'n/help/$pkgcmds/' \
                        'n/info/`__pkg-info-opts`/' \
                        'N/info/`__pkgs`/' \
                        'n/which/`__pkg-which-opts`/' \
                        'N/which/`__pkgs`/'
```

This type of definition could be used for other commands with subcommands, like zfs(8) or zpool(8).  I have not found a way to include x help-style completions natively.  However, a post to the tcsh mailing list revealed something that has been there all along: http://mx.gw.com/pipermail/tcsh/2014-January/004734.html

The value of the entire command line can be passed to external commands, and that means that completions can be written in any arbitrary language, working any way that seems appropriate.


----------



## DavidMarec (Mar 9, 2014)

It appears that `pkg info -E` is deprecated and not available any more from pkgng. Maybe the following is more convenient: `alias __pkgs 'pkg query -a "%n"'`.


----------



## wblock@ (Mar 9, 2014)

Right.  This works, too:

```
alias __pkgs 'pkg info -q'
```

make(1) changed also, so now the target completions no longer work.  That was surprisingly useful.  I worked on it a while back without success.  Has anyone else tried?


----------



## Carpetsmoker (Mar 10, 2014)

The *-p* flag disappeared, apparently. I thought BSD wasn't into randomly removing flags from programs...?

We can use *-dg1*, which has a different output, and outputs to stderr, which is always fun in tcsh.

Here's my attempt:

```
complete make 'n@*@`sh -c "make -dg1 -n 2>&1 | grep ,\ flags\ \[0-9\]\*,\ type\ \[0-9\]\* | cut -wf2 | tr -d , | sed /^\[^a-z\]/d | sort -u"`@'
```

Completions seem to be pretty much the same as on my 9.2 system. And this will work on GNU make too, so we win that!

It *only* works for FreeBSD 10, though. In FReeBSD <=9, you need to use the old completion; *-dg1* works, but has a different format...

To make it work for both:

```
if ($uname == FreeBSD && `uname -r | cut -d. -f1` < 10) then
        complete make 'n@*@`make -pn | sed -n -E "/^[#_.\/[:blank:]]+/d; /=/d; s/[[:blank:]]*:.*//gp;"`@'
else
        complete make 'n@*@`sh -c "make -dg1 -n 2>&1 | grep ,\ flags\ \[0-9\]\*,\ type\ \[0-9\]\* | cut -wf2 | tr -d , | sed /^\[^a-z\]/d | sort -u"`@'
endif
```


Now fetch me a beer. You owe me one.


----------



## wblock@ (Mar 11, 2014)

Excellent!  If you are at BSDCan, I'll buy you a beer.  Otherwise, it will have to be virtual: :beer

While trying to decipher that, I saw this in the make(1) output:

```
.ALLTARGETS      =  ...
```

It appears to be an easy way to find all possible targets:
`make -V .ALLTARGETS`

Using that for a completion:

```
complete make 'n/*/`make -V .ALLTARGETS`/'
```


----------



## wblock@ (Mar 12, 2014)

Updated full completions at http://www.wonkity.com/~wblock/csh/completions.


----------



## Carpetsmoker (Mar 12, 2014)

I also add my profiles from ~/.ssh/config to the hosts:


```
set hosts
if ( -r "$HOME/.hosts" ) then
        set hosts=($hosts `grep -Ev '(^#|^$)' $HOME/.hosts`)
endif

if ( -r "$HOME/.ssh/config" ) then
        set hosts=($hosts `grep ^Host ~/.ssh/config | cut -d' ' -f2`)
endif

if ( -r "$HOME/.ssh/known_hosts" ) then
        set hosts=($hosts `cut -d' ' -f 1 ~/.ssh/known_hosts | cut -d, -f1`)
endif

set hosts = `echo "$hosts" | sort -u`
```

ie:


```
Host vagrant
  HostName localhost
  Port 2222
  User vagrant
```


----------



## wblock@ (Mar 12, 2014)

That's a good idea!  That also reminds me, cut(1) now supports -w for whitespace delimiters.  No idea how long that's been around.  So

```
if ( -r "$HOME/.ssh/known_hosts" ) then
        set hosts=($hosts `cut -w -f1 ~/.ssh/known_hosts | cut -d, -f1`)
endif
```

Hmm.  Might want to filter out square brackets, sort, and remove duplicates as a final step:

```
set hosts=(`echo $hosts | tr -d '[]' | sort | uniq`)
```


----------



## Carpetsmoker (Mar 13, 2014)

*-w* is a (very useful) FreeBSD extension to *cut*, it's not very portable (ie. GNU cut doesn't have it).


----------



## Carpetsmoker (Mar 18, 2014)

I made some (minor) git completions:


```
complete git 'p/1/(add merge-recursive add--interactive merge-resolve am \
    [...snip ludicrously long list of git commands ... ]/' \
    'n@checkout@`git branch -a | sed -r "s|^[\* ]+(remotes/origin/)?||; /^HEAD/d" | sort -u`@' \
    'n@branch@`git branch -a | sed -r "s|^[\* ]+(remotes/origin/)?||" /^HEAD/d | sort -u`@'
```

... there are probably other useful completions as well.

Open question:
*git branch <tab>* works, but *git branch -d <tab>* doesn't ...


----------



## wblock@ (Mar 18, 2014)

See those new `pkg` completions.  `pkg which <tab>` works, as does `pkg which -o <tab>`.


----------



## wblock@ (Mar 18, 2014)

Yesterday, I thought the make(1) completions would benefit from being able to complete -V, showing all known variables.  Variables are shown in -dg1 output between

```
#*** Global Variables:
```
and

```
#*** Directory Cache:
```
However, sed(1) and awk(1) are so weak as to require substantial work to filter out all the trash, and even with Perl it is non-trivial.


----------



## Carpetsmoker (Mar 19, 2014)

So here's my "full" make completions, which is "Linux-safe" and works with GNU make:


```
[noparse]
if ( $uname == FreeBSD ) then
    set backslash_quote
    complete gmake 'n@*@`make -qp | awk -F: \'/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ { split($1,A,/ /); for(i in A)print A[i] }\' | sort -u`@'
    unset backslash_quote

    if ( `uname -r | cut -d. -f1` < 10 ) then
        complete make 'n@*@`make -pn | sed -n -E "/^[#_.\/[:blank:]]+/d; /=/d; s/[[:blank:]]*:.*//gp;"`@'
    else
        complete make 'n/*/`make -V .ALLTARGETS`/'
    endif
else if ( $uname == Linux ) then
    set backslash_quote
    complete make 'n@*@`make -qp | awk -F: \'/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ { split($1,A,/ /); for(i in A)print A[i] }\' | sort -u`@'
    unset backslash_quote
endif
[/noparse]
```


Another thing I've been using for a while is adding the mercurial or git branch name in my prompt, like:

```
[/data/code/nordavind](default)% hg branch
default

[~/the_silver_searcher](colors)% git branch
* colors
  master
```

In my main tcsh rc file I do:

```
if ( $uname != win32 && -f ~/.tcsh/cwdcmd.tcsh ) then
    alias cwdcmd source ~/.tcsh/cwdcmd.tcsh
else
    unalias cwdcmd
endif
```

& the contents of cwdcmd.tcsh:


```
# Show the directory in the xterm title
echo -n "\033]2;tcsh: $cwd\007"

# Interferes with running commands
unset printexitvalue

# For sanity
set backslash_quote

# stat would be better/faster, but stat is about as unportable as it gets
alias __pstat 'perl -e \'print((stat($ARGV[0]))[9])\''

# Some games for the sake of efficiency
if ( $?reporoot ) then
    if ( "$cwd" =~ "$reporoot*" ) then
        if ( $repotype == 'git' && $repochanged == `__pstat "$reporoot"/.git/HEAD` ) then
            goto end
        endif
        if ( $repotype == 'hg' && $repochanged == `__pstat "$reporoot"/.hg/branch` ) then
            goto end
        endif
    else
        unset repotype
        unset reporoot
        unset repochanged
    endif
endif

if ( ! $?repotype ) set repotype = ''
# Mercurial
if ( ! $?reporoot || $repotype == 'hg' ) then
    hg branch >& /dev/null
    if ( $? == 0 ) then
        set reporoot = `hg root`
        set repotype = 'hg'
        set repochanged = `__pstat "$reporoot"/.hg/branch`
        set prompt = "[%~](`cat $reporoot/.hg/branch`)%# "

        goto end
    endif
endif


# Git
if ( ! $?reporoot || $repotype == 'git' ) then
    git rev-parse --abbrev-ref HEAD >& /dev/null
    if ( $? == 0 ) then
        set reporoot = `git rev-parse --show-toplevel`
        set repotype = 'git'
        set repochanged = `__pstat "$reporoot"/.git/HEAD`
        set prompt = "[%~](`git rev-parse --abbrev-ref HEAD`)%# "

        goto end
    endif
endif


# We're not in a repo anymore; reset.
set prompt = "[%~]%# "
unset repotype
unset reporoot
unset repochanged


# Cleanup
end:
    set printexitvalue
    unset backslash_quote
    unalias __pstat
```

It's a bit ugly, and I feel I've really hit the limits on what one can do with tcsh while still preserving once's sanity... But I've been using this for a while, and it works...
Tested on FreeBSD 9 & Ubuntu.[/i][/i]


----------



## wblock@ (Jul 10, 2015)

Finally got around to making a working `make -V` completion:

```
alias __makevars  'make -ndv |& perl -ne '\''print "$1\n" if /^(?:Command|Global|Internal):(\S+?)\s+/;'\'' | sort -u'

  complete make  'C/F/(FORMATS= FORMATS=html FORMATS=html-split FORMATS=pdf)/' \
  'p/1/`make -V .ALLTARGETS`/' \
  'n/-V/`__makevars`/'
```

Perl could do the `sort -u` internally to avoid a fork, but the clarity is far better this way.


----------

