tcsh (Vervollständigung)

bsdlamer

Well-Known Member
Sorry für mein Deutsch und schriftstellerische Leisung, aber ich wollte auch was gutes tun :)

Viele nutzen in der Console Autovervollständigung, was natürlich bequem ist und
die Arbeit in der Comandozeile beschleunigt. Tippt man die ersten Buchstaben eines
Befehls und drückt danach TAB, wird tcsh versuchen es zu vervollständigen. Falls
es mehr Befehle gibt die mit den selben Buchstaben anfangen, zeigt die tcsh sie alle
(das nennt man autolisting und es wird wie folgt aktiviert).
Code:
$ set autolist
$ xse<TAB>
xset         xsetmode     xsetpointer  xsetroot
$ xset

$ xsetm<TAB>
$ xsetmode
Das gleiche passiert wenn man Pfade vervollständigen will.
Code:
$ mpg123 /ho<TAB>
Wenige wissen aber, dass man zum Beispiel auch shell Variablen
vervollständigen kann. Beginnt der zu vervollstaendigende Text mit "$", wird der
eingegebene Text zu einer definierten Variablen erweitert.
Code:
$ echo $<TAB>
BLOCKSIZE   LOGNAME     SHELL       _           dirstack    history     old         savehist    tty         
DISPLAY     MACHTYPE    SHLVL       addsuffix   echo_style  home        owd         shell       uid
...
$ echo $B<TAB>

In tcsh gibt es eine speziele Variable "fignore" die es ermöglicht bestimmte
Ausdruecke zu ignorieren. Vor dem man sie nutzen kann, muss "fignore" wie auch "autolist"
gesetzt werden, braucht aber noch die liste von den Ausdrücken die man ignorieren will.

Code:
$ mut<TAB>
mutt          mutt_dotlock  muttbug
$ mutt

mutt_dotlock und muttbug benutzt man sehr selten, genau wie firefox-config oder gimp-2.2

Code:
$ set fignore=(firefox-config gimp-2.2 mutt_dotlock muttbug)
$ mut<TAB>

mutt_dotlock und muttbug werden jetzt ignoriert, dadurch werden sie auch nicht von
autolist angezeigt. mut<TAB> wird einfach auf mutt erweitert.
Editoren wie Vim und Emacs hinterlassen backup dateien die mit "~" enden. Es gibt
auch Dateien die man oft sehr gern übersehen möchte, z.B. *.o (oder was auch immer).
Auch hier hilft fignore

Code:
$ ls 
.  ..  file  file~  object  object.o
$ vim f<TAB>
file    file~
$ vim file 
$ set fignore=($fignore \~ .o)

die neu Liste beinhaltet $fignore um schon existierende Werte beizubehalten.

Code:
$ ls
.  ..  file  file~  object  object.o
$ vim f<TAB>
$ vim o<TAB>

Jetzt is es noch komfortabler Autovervollständigung zu nutzen.

Tcsh bietet aber noch viel mehr als das. Jeder weiss, dass "cd" als Argumente nur Verzeichnissnamen
akzeptiert, und es ist deswegen auch sehr praktisch wenn es andere Dateien/Dateitypen übersieht.
Um das zu ermöglichen kann man mit complete-Befehl (tcsh builtin) ein bisschen nachhelfen

Code:
$ cd /etc<TAB>
WindowMaker/        ftpchroot           magic               pf.conf             sensorsd.conf 
X11/                ftpusers            mail.rc             pf.os               services 
afs/                gconf/              mail/               phones              shells 
amd/                gettytab            mailer.conf         portal.conf         skel/
authpf/             gnome/              man.conf            ppp/                sliphome/
bgpd.conf           group               master.passwd       printcap            spamd.conf 
ccd.conf            group~              moduli              printcap.pre-cups   spwd.db 
changelist          hostapd.conf        monthly             protocols           ssh/
csh.cshrc           hostname.xl0        motd                pwd.db              ssl/
csh.login           hosts               mplayer/            rbootd.conf         sudoers 
csh.logout          hosts.equiv         mrouted.conf        rc                  sysctl.conf 
cups/               hosts.lpd           mtree/              rc.conf             sysctl.conf~ 
daily               hosts~              mutt/               rc.conf~            syslog.conf 
dhclient.conf       hotplug/            my.cnf              rc.local            systrace/
dhcpd.conf          ifstated.conf       myname              rc.securelevel      termcap@
dhcpd.interfaces    inetd.conf          netstart            rc.shutdown         ttys 
disklabels/         ipsec.conf          networks            remote              usermgmt.conf 
disktab             isakmpd/            newsyslog.conf      resolv.conf         weekly 
dumpdates           kerberosV/          ntpd.conf           resolv.conf.save    wgetrc 
esd.conf            ksh.kshrc           openldap/           resolv.conf.tail    wsconsctl.conf 
exports             ksysguarddrc        opera6rc            rmt@                xdg/
fbtab               localtime@          opera6rc.fixed      rpc                 xpdfrc 
firmware/           locate.rc           ospfd.conf          samba/              xprobe2/
fonts/              login.conf          pango/              scrollkeeper.conf   
fstab               lynx.cfg            passwd              security            
$ cd /etc/
$ complete cd 'p/1/d/'
$ cd /etc<TAB>
WindowMaker/  authpf/       fonts/        isakmpd/      mtree/        ppp/          ssh/          xprobe2/
X11/          cups/         gconf/        kerberosV/    mutt/         samba/        ssl/          
afs/          disklabels/   gnome/        mail/         openldap/     skel/         systrace/     
amd/          firmware/     hotplug/      mplayer/      pango/        sliphome/     xdg/
$ cd /etc/

Noch ein beispiel mit mpg123 (hier sieht mpg123 nur *.mp3, *.MP3 und Verzeichnisse, alles andere
wird ignoriert)

Code:
$ ls
.  ..  dir2  text  text.dvi  text.mp3  text.mpeg  text.pdf  text.tex
$ mpg123 <TAB>
dir2/       text        text.dvi    text.mp3    text.mpeg   text.pdf    text.tex
$ complete mpg123 'n/*/f:*.{mp3,MP3}/'
$ mpg123 <TAB>
dir2/       text.mp3
$ mpg123 t<TAB>

Möchte man bei einem program (z.B. Vim) nur bestiemte dateitypen ignorieren (*.pdf, *.dvi, *mp3),
macht man folgendes

Code:
$ complete vim 'n/*/f:^*.{dvi,pdf,mp3}/'

So sieht Vim jetzt keine PDFs, DVIs und MP3s.

Oft ist es sehr anstrengend Optionen für bestimmte Befehle von hand einzugeben, z.B. --socket
-nosound usw. Auch das kann man vervollständigen.
Kleines Beispiel (damit es übersichtlich bleibt, habe ich nur einige Optionen verwendet)
Alle optionen von mplayer beginen mit "-", einige haben eine liste von argumenten, wie z.B
"-vo" (Video Output)

Code:
$ complete mplayer 'c/-/(nosound vo quiet)/' 'n/-vo/(help xv x11 xover yuv4mpeg)/'
$ mplayer -n<TAB>
$ mplayer -v<TAB>
$ mplayer -vo <TAB>
help      x11       xover     xv        yuv4mpeg
$ mplayer -vo y<TAB>

Wie man sieht, kann man nicht nur Befehle vervollständigen, sondern alles mögliche.

Letzter Beispiel für die Inspiration :)

Wenn ich mich mit ssh auf remotehosts einloge, tue ich das normalerweise so

Code:
$ ssh lamer@very-long-hostname.de

Jedes mal "lamer@very-long-hostname.de" einzutippen macht überhaupt kein Spass. Am besten
erställt man eine Liste von Rechnern damit die tcsh dann hostnames mit Hilfe dieser Liste
vervollständigt

Code:
$ set hosts=(very-long-hostname.de another-very-very-long-hostname.ru openbsd.functional.and.secure.ua)
$ complete ssh 'c/*@/$hosts/' 'p/1/u/@'
$ ssh <TAB>
_afs      _fingerd  _isakmpd  _mysql    _portmap  _rusersd  _tftpd    lamer     popa3d    sshd      
_bgpd     _ftp      _kadmin   _ntp      _ppp      _spamd    _x11      named     proxy     uucp      
_cups     _hostapd  _kdc      _ospfd    _rbootd   _syslogd  bin       nobody    root      www       
_dhcp     _identd   _mopd     _pflogd   _rstatd   _tcpdump  daemon    operator  smmsp
$ ssh l<TAB>
$ ssh lamer@<TAB>
very-long-hostname.de            another-very-very-long-hostname.ru            openbsd.functional.and.secure.ua
$ ssh lamer@op<TAB>

Was tun wenn uns so eine grosse userliste nervt, asserdem loggt sich keiner mit _tcpdump, _dhcp ein.
Usernamen von remotehosts fehlen auch, da die Liste ausschliesslich aus Localuser besteht.
Da helfen wir ein bisschen nach.

Code:
$ set users=(lamer matreschka root dostoevskiy tolstoy)
$ uncomplete ssh
$ copmlete ssh 'c/*@/$hosts/' 'p/1/$users/@'
$ ssh <TAB>
dostoevskiy  lamer        matreschka   root         tolstoy
$ ssh d<TAB>

(hat man sich vertippt und Eingabe gedrückt, funktionert vervollständigung entweder falsch, oder
überhaupt nicht mehr. Mit "uncomplete" kann man definierte Regeln für bestimmtes Befehl zurücksetzen.
Einfach "uncomplete ssh" eingeben und noch mal versuchen. Mit "uncomplete *" wird alles zurück gesetzt.)

Wie man sieht kann man das Verhalten von Autovervollständigung (completion) beliebig
anpassen. Nun schuen wir mal Paar Beispele an um zu verstehen wie das ganze funktioniert.

Code:
$ complete cd 'p/1/d/'

complete Befehl 'wort/pattern/liste', wo "p" für "position" steht, 1 ist der Wert von "p"
und "d" steht für directory. Im Klartext heisst es "erweitere das erste Wort das nach cd kommt,
und das Wort muss ein Verzeichniss sein".
Neben "p" gibt es auch "c" - currnet und "n" - next ("N" und "C" werde ich hier nicht besprächen
steht doch alles in manpage :)
Neben "d" gibt es

Code:
                   a       Aliases
                   b       Bindings (editor commands)
                   c       Commands  (builtin  or  external  com-
                           mands)
                   C       External commands which begin with the
                           supplied path prefix
                   d       Directories
                   D       Directories  which begin with the sup-
                           plied path prefix
                   e       Environment variables
                   f       Filenames
                   F       Filenames which begin  with  the  sup-
                           plied path prefix
                   g       Groupnames
                   j       Jobs
                   l       Limits
                   n       Nothing
                   s       Shell variables
                   S       Signals
                   t       Plain (``text'') files
                   T       Plain  (``text'')  files  which  begin
                           with the supplied path prefix
                   v       Any variables
                   u       Usernames
                   x       Like n, but prints select  when  list-
                           choices is used.
                   X       Completions
                   $var    Words from the variable var
                   (...)   Words from the given list
                   `...`   Words from the output of command

Code:
complete mplayer 'c/-/(vo nosound)/' 'n/-vo/(x11 xv help)/'

1 vervollständige alle Patterns die mit - beginnen, mit "vo" oder "nosound"
2 vervollständige das wort das nach -vo kommt mit "x11", "xv" oder "help"

Zum schluss will ich noch sagen, dass dieser Artikel (wenn man das so nennen kann)
nur eine Einführung ist.
Wer das interessant findet muss unbedingt manpage lesen und sich mal
http://prdownloads.sourceforge.net/tcshrc/tcshrc-1.6.0.tar.gz anschauen. Dort
findet man Möglichkeiten/Beispiele die ich hier nich erwehnt habe.
Ich freue mich auf eure Vorschläge/Korrekturen/Kritik
 
Zuletzt bearbeitet:
Jedes mal "lamer@very-long-hostname.de" einzutippen macht überhaupt kein Spass. Am besten erstaellt man eine Liste von Rechnern damit die tcsh dann hostnames mit Hilfe dieser Liste vervollständigt

Das wiederum halte ich für recht umständlich, zumindest wenn es mehr als ne Handvoll Hosts sind. Auch öffnet sich bei mir jede neue SSH Sitzung in einem neuen Screen-Tab mit Namen des Hosts. Da dies mal par mehr sein könnten, will ich die möglichst Kurz haben, aber da gibt es zum Glück für ~/.ssh/config:

Code:
Host test
    Hostname test.domain.bla
    User testuser

Host test2
    Hostname test2.domain.bla
    User testuser2
    Port 1001

nu kann ich mich auf: »testuser@test.domain.bla« einfach mit »ssh test« verbinden.

mehr dazu: SSH_CONFIG(5)
 
Zuletzt bearbeitet von einem Moderator:
paefchen schrieb:
Das wiederum halte ich für recht umständlich, zumindest wenn es mehr als ne Handvoll Hosts sind. Auch öffnet sich bei mir jede neue SSH Sitzung in einem neuen Screen-Tab mit Namen des Hosts. Da dies mal par mehr sein könnten, will ich die möglichst Kurz haben, aber da gibt es zum Glück für ~/.ssh/config:

Code:
Host test
    Hostname test.domain.bla
    User testuser

Host test2
    Hostname test2.domain.bla
    User testuser2
    Port 1001

nu kann ich mich auf: »testuser@test.domain.bla« einfach mit »ssh test« verbinden.

mehr dazu: SSH_CONFIG(5)


Im Beispiel mit ssh war eigentlich nur Beispiel selbst wichtig. Der zeigt das man Argumente die auz zwei Teilen besehen auch vervollsaendigen kann. Aber vielen dank fuer den Tip !!! Das wusste ich net.

So kann man das noch schoener mit completion machen :)

1) ~/.ssh/config erstaellen
Code:
Host webserver
    Hostname long-hostname.de
    User testuser

Host ftpserver
    Hostname test2.domain.bla
    User testuser2
    Port 1001

Host nocheinserver
    Hostname test2.domain.bla
    User testuser2
    Port 22

2) completion definieren und Variable stezen die liste der hosts beinhaltet
Code:
$ complete ssh 'p/*/$hosts/'
$ set hosts=(webserver ftpserver nocheinserver)

jetzt gafaelt es mir am besten :)
Code:
$ ssh <TAB>
webserver           ftpserver         nocheinserver
$ ssh w<TAB>

:D Super !
 
So damit es dann auch wirklich »Perfekt« ist, ~/.cshrc:

Code:
[...]
set complete_ssh_host=(`awk '/^Host / {print $2}' ~/.ssh/config | tr "\n" " "`)
complete ssh 'p/*/$complete_ssh_host/
[...]

:D
 
paefchen schrieb:
So damit es dann auch wirklich »Perfekt« ist, ~/.cshrc:

Code:
[...]
set complete_ssh_host=(`awk '/^Host / {print $2}' ~/.ssh/config | tr "\n" " "`)
complete ssh 'p/*/$complete_ssh_host/
[...]

:D

Das ewige streben nach Perfektion :D :D :D

Einfach perfekt !!!
 
Sehr schoene Zusammenstellung! Gefaellt mir und im Wiki sollte das auf jeden Fall auch zu finden sein. Schade, das die tcsh sich nicht ganz so gut zum sh-Programmieren eignet, da nicht Posix kompatibel (afaik). Aber das nur am Rande und schon OT.
 
Zurück
Oben