#!/usr/bin/perl
$default_vshnucap = '';
$default_vshnurc = '';
($cfg::VNAME, $cfg::VERSION, $cfg::REQUIRE) = qw(vshnucfg 1.0500 1.0500);
&addversions($cfg::VNAME, $cfg::VERSION);
&quit("$0: $cfg::VNAME $cfg::VERSION requires at least $VNAME $cfg::REQUIRE ",
"($VERSION)\n") if $cfg::REQUIRE > $VERSION;
$cfg::editor = $ENV{VISUAL} || $ENV{EDITOR} || 'vi';
$cfg::mailer = $ENV{MAILER} || 'mail';
$pager = do { `less -V > /dev/null 2>&1`; ($?) ? 'more' : 'less' };
$pager .= "; echo Press Return | tr -d '\\012'; sh -c 'read x' < /dev/tty"
if $pager eq 'more';
$pagera = $ENV{PAGERA} || $pager;
$pagerr = $ENV{PAGERR} || $pager;
$pagerr .= do { `less -R /dev/null > /dev/null 2>&1`; ($?) ? ' -r' : ' -R' }
if $pagerr =~ /\bless\b/ && $pagerr !~ /\s-\S*r/i;
$pager = $ENV{PAGER} || $pager;
$pager .= "; echo Press Return | tr -d '\\012'; sh -c 'read x' < /dev/tty"
if $pager =~ /\bmore\b/ && $pager !~ /(\s-\S*w|Press)/;
$mailbox = $ENV{MAIL};
@bak = qw/~$/;
$cfg::xcb = 0;
sub cfg::xcut { &pipeto("xcb -s $cfg::xcb", @_) }
sub cfg::xpaste { `xcb -p $cfg::xcb` }
$co_decor = ($>) ? 'reverse' : ($color) ? 'on_red' : '';
$co_error = ($color) ? 'bold red' : 'bold';
$co_msg = ($color) ? 'green' : '';
$co_ftype = ($color) ? 'yellow' : '';
$co_perms = ($color) ? 'white' : '';
$co_myper = ($color) ? '' : 'bold';
$co_write = ($color) ? 'red' : 'reverse';
$co_sbits = ($color) ? 'cyan' : '';
$co_nlink = '';
$co_size1 = '';
$co_size2 = ($color) ? 'white' : 'bold';
$co_xaged = ($color) ? '' : 'bold';
$co_aged = ($color) ? 'white' : '';
$co_symln = ($color) ? 'yellow' : '';
%co_user = ($color) ? ($user => 'blue', 0 => 'red', 'other' => 'green')
: ();
$co_title = 'reverse';
$co_key = ($color) ? '' : '';
$co_ckey = ($color) ? 'green' : 'bold';
$co_nkey = ($color) ? 'red' : 'reverse';
$co_wkey = ($color) ? 'red' : 'reverse';
$co_0key = ($color) ? 'cyan' : 'bold';
$co_Akey = ($color) ? 'green' : 'bold';
$co_akey = ($color) ? 'white' : 'bold';
$co_code = ($color) ? 'yellow' : '';
$co_cmd = ($color) ? '' : 'bold';
$co_tail = ($color) ? 'white' : '';
$co_com = ($color) ? 'yellow' : 'reverse';
$co_desc = ($color) ? 'bold cyan' : '';
$co_prmt = ($color) ? 'bold green' : '';
$co_xuse = ($color) ? 'on_green' : 'reverse';
@tail = qw/ret keymap home win winch\s*\d*/;
$aged = '12h';
$full = '90';
$minfilelen = 15;
$maxfilecols = 0;
$maxcdhist = '$scr->{ROWS} - 4';
$maxdohist = '$scr->{ROWS} - 4';
$typemaptab = 32;
$mousemaptab = 16;
$initmouse = 'on';
$forcemouse = 0;
%onsub = (
'cd' => 'altls; $#cdhist && cfg::abssets $cdhist[1]{ls}',
'altls' => 'longls',
'winch' => 'longls',
);
@bagkeys = @cfg::savebagkeys = ('a' .. 'z');
%bagmap = (
'' => ['point <KEY>; dotype <FILE>',
'act on <FILE> by its type'],
'choose' => ['point <KEY>; choose <FILE>', 'choose <FILE>'],
);
%nobag = ();
$insertkey = 'M-v';
$insertcmd = [
['@choose', 'insert chosen files', 'cC/', 'chosen files'],
['$point', 'insert point file', 'p>', 'point file'],
['$_ = $point; s/\.[^\.\/]*$//; $_',
'insert point file sans ext', 'P<', 'point file sans ext'],
['$cwd', 'insert current directory', '.', 'current directory'],
['pwd', 'insert hard directory', 'hH', 'hard directory'],
['$cdhist[1]{ls}',
'insert prior directory', "\\", 'prior directory'],
['df && $df->mount(pwd)',
'insert mount point', 'mM', 'mount point'],
['@cfg::set1', 'insert file set 1', '1', 'file set 1'],
['@cfg::set2', 'insert file set 2', '2', 'file set 2'],
['@cfg::set3', 'insert file set 3', '3', 'file set 3'],
['@cfg::set4', 'insert file set 4', '4', 'file set 4'],
['map { $_->{ls} } @cdhist',
'insert directory history', 'dD', 'directory history'],
['@dohist', 'insert file history', 'fF', 'file history'],
['getmark getkey("Mark:"), "dir"',
'insert marked directory', '(', 'marked directory'],
['getmark getkey("Mark:"), "file"',
'insert marked file', ')', 'marked file'],
['getmark getkey("Mark:"), "path"',
'insert marked path', '9', 'marked path'],
['split(/\n/, cfg::xpaste)',
'insert X cut buffer $cfg::xcb', 'xX', 'X cut buffer'],
];
%typemap_ = @typemap_ = (
'TTL_' => 'EDIT MODE FILE ACTIONS',
'/^$/' => 'win',
'-e _ && -d _' => ['cd $_; win', 'enter this directory'],
'' => ['run -s_ $cfg::editor', 'edit this file'],
);
@typemap_ = &akeys(@typemap_);
%typemap_expand = @typemap_expand = (
'TTL"' => 'EXPAND MODE FILE ACTIONS',
'/^$/' => 'win',
'! -e _' => 'beep; win',
'-d _' => ['expandtoggle $_; win',
'expand or collapse this directory'],
'' => 'beep',
);
@typemap_expand = &akeys(@typemap_expand);
sub cfg::zarbrowse {
['run -X "konqueror -- ' . $_[0] . ':$_fq"',
"browse the contents of this $_[1]", 'bBkK', 'browse'] }
sub cfg::tarbrowse { &cfg::zarbrowse('tar', @_) }
sub cfg::zipbrowse { &cfg::zarbrowse('zip', @_) }
%typemap_do = @typemap_do = (
'TTL?' => 'DO MODE FILE ACTIONS',
'/^$/' => 'win',
'! -e _' => 'beep; win',
'-d _' => [['run -=g "ls -lR", unlessopt("a"), ifopt("L"),'
. ' ifopt("T", "-F")', 'long list'
. ' this directory recursively', 'lL', 'ls -lR'],
['run -_g "tree -A", unlessopt("a"), ifopt("C"),'
. ' ifopt("L", "-l"), ifopt("T", "-F")',
'tree list this directory', 'tT', 'tree'],
['run -_g "tree -Apug", unlessopt("a"), ifopt("C"),'
. ' ifopt("L", "-l"), ifopt("T", "-F")',
'long tree list this directory', 'pPuUgG', 'tree -pug']],
&mailcap2typemap($ENV{VSHNUCAP} || $default_vshnucap ||
((-f "$ENV{HOME}/.vshnucap") ? "$ENV{HOME}/.vshnucap" : 'vshnucap'),
"'v'; "),
'/(\.tnef|(^|\/)winmail\.dat)$/i'
=> [['run -s=2p "tnef -tv"',
'list the contents of this tnef archive',
'tTlL', 'list contents'],
['run -s=r "tnef", "-wv"', 'extract this tnef archive',
'xX', 'extract']],
'/(^|\/|\.)mbox$/'
=> ['run -s_ "mail", "-f"', 'run `mail` on this mbox file'],
'ext 7z' => ['run -s=2p "7zr l"',
'list the contents of this 7zip archive'],
'Ext \d\w? man' => ['run -s_g "nroff -man <"', 'view this man page formatted'],
'Ext aif[cf]? au snd'
=> ['run -x_ "xplay -stay"', 'play this AU/AIFF audio file'],
'ext asf avi flv m[4k][av] mo?v(ie)? mp[34e] mpe?g ogg qt vob'
. ' wav webm wm[av] 3gp'
=> ['run -x= "xterm -e vlc"', 'play this audio/video file'],
'ext bmp gif ico jpe?g p[bgnp]m pcx png svg tiff? xbm xpm'
=> ['run -x= "eog"', 'display this image file'],
'ext csv docx? dot o[dt]t ods pp[ts]x? rtf sdw st[cdiw] sx[cdgimw] vor vsd' .
' xls[xm]?' => ['run -x_ "libreoffice"','load this file into LibreOffice'],
'Ext deb' => [['run -s=2p "dpkg -I"',
'view the info of this Debian package',
'?', 'info'],
['run -s=2p "dpkg -c"',
'view the contents of this Debian package',
'cClLtT', 'contents'],
['run -s=r "dpkg", "-i"',
'install this Debian package', 'iI', 'install'],
['run -s=r "dpkg", "-i", "--force-architecture"',
'install Debian package despite architecture',
'fF', 'force install'],
['run -s2p "dpkg-deb", "-X", $_, "."',
'extract Debian package to the current directory',
'xXeE', 'extract']],
'Ext dir pag' => ['run -s2p "makedbm -u $_rq"',
'view a dump of this dbm file'],
'Ext (wr|vrm)l(\.g?[Zz])?'
=> ['run -x= "freewrl"', 'display this VRML file'],
'Ext a' => ['run -s_2p "ar tv"', 'list the contents of this archive'],
'Ext apk' => [['run -s_2P "unzip -l"',
'list the contents of this app package', 'tTlL', 'list'],
&cfg::zipbrowse('app package')],
'Ext aup' => ['run -x_ "audacity"', 'load this Audacity project'],
'Ext crl' => ['run -s_2p "openssl crl -noout -text -in"',
'view this certificate revocation list'],
'Ext cer crt pem'
=> ['run -s_2p "openssl x509 -noout -text -purpose -in"',
'view this certificate'],
'Ext csr' => ['run -s_2p "openssl req -noout -text -in"',
'view this certificate signing request'],
'Ext dvi' => ['run -x_ "xdvi"', 'display this DVI file'],
'ext e?ps' => ['run -x= "evince"', 'display this PostScript file'],
'Ext fig' => ['run -x_ "xfig"', 'load this figure file into Xfig'],
'Ext gpg' => ['run -s=r "gpg"', 'decrypt this GPG file'],
'ext iso' => [['run -s_2P "isoinfo -d -i"',
'list the info about this ISO image', 'iI', 'info'],
['run -s_2P "isoinfo -l -i"',
'list the files in this ISO image', 'lL', 'list'],
['run -s= "isodump"',
'view the dump of this ISO image', 'dDvV', 'dump']],
'Ext [jew]ar' => [['run -s_2P "unzip -l"',
'list the contents of this Java archive', 'tTlL', 'list'],
&cfg::zipbrowse('Java archive'),
['run -_r "java -jar"',
'run this Java archive', 'rR', 'run']],
'Ext(qw(jks (key|trust)store)) || /(^|\/)cacerts/'
=> ['run -s_2p "echo Default password: changeit;'
. ' keytool -list -v -keystore"',
'view this java keystore'],
'Ext key' => ['run -s_2p "openssl rsa -noout -text -in"',
'view this private key'],
'Ext km[lz]' => ['run -xF "google-earth"',
'load this file into Google Earth'],
'Ext lyx' => ['run -x_ "lyx"', 'load this file into LyX'],
'Ext o' => ['run -s=p "nm"', 'view the name list of this object file'],
'ext pdf' => sub { my $c =
['run -x= "evince"',
'display this PDF file', 'dDrR', 'display'];
&cfg::onecmd() ? $c : [$c,
['run -p "pdftotext -layout -- $_q -"',
'view a text version of this PDF file',
'tTvV', 'view as text'],
['run -=r "pdfinfo"',
'view the info of this PDF file', 'iI', 'info']] },
'Ext pgp' => ['run -s=r "pgp"', 'decrypt this PGP file'],
'Ext prm' => ['run -s_2p "openssl dsaparam -noout -text -in"',
'view this DSA parameter file'],
'Ext r(am?|m)' => ['run -x_ "realplay"', 'play this Real file'],
'ext rar' => ['run -s=2p "unrar vt"',
'list the contents of this rar archive'],
'Ext rpm' => [['run -s=2p "rpm -qisp"',
'view the info of this RPM package','qQ', 'query'],
['run -s=r "rpm", "-ihv"',
'install this RPM package', 'iI', 'install'],
['run -s=r "rpm", "-Fhv"',
'freshen this RPM package', 'fF', 'freshen']],
'ext t(a(r\.?)?)?bz2'
=> [['run -s2P "bzip2 -d < $_q | tar -tvf -"',
'list the contents of this bzip2 tarball',
'tTlL', 'list'],
&cfg::tarbrowse('bzip2 tarball')],
'ext t(a(r\.?)?)?gz'
=> [['run -s2P "gzip -d < $_q | tar -tvf -"',
'list the contents of this gzip tarball', 'tTlL', 'list'],
&cfg::tarbrowse('gzip tarball')],
'ext t(a(r\.?)?)?z'
=> ['run -s2P "uncompress < $_q | tar -tvf -"',
'list the contents of this compress tarball'],
'ext tar' => [['run -s_2p "tar -tvf"',
'list the contents of this tar archive', 'tTlL', 'list'],
&cfg::tarbrowse('tar archive'),
['run -s_2p "tar -xpvf"',
'extract this entire tar archive', 'xX', 'extract all']],
'Ext uu' => [['run -s=2p "uudecode -p"',
'view this uuencoded file', 'vVpP', 'view'],
['run -s=r "uudecode"',
'extract this uuencoded file', 'xX', 'extract']],
'Ext vshnu(cfg|rc)'
=> ['do $_q; err $@; win', 'load this vshnu config file'],
'Ext xcf' => ['run -x_ "gimp"', 'load this image file into GIMP'],
'Ext xwd' => ['run -x_ "xwud -in"', 'display this window dump'],
'ext zip' => [['run -s=2P "unzip -l"',
'list the contents of this zip archive', 'tTlL', 'list'],
&cfg::zipbrowse('zip archive')],
'/(^|\/)Imakefile$/'
=> ['run -r getcmd "xmkmf"',
'run `xmkmf` which will use this Imakefile'],
'/[Ii]makefile/'=> ['run -r getcmd "imake -f $_q"',
'run `imake` using this Imakefile'],
'/[Mm]akefile/' => ['@cfg::makefiles = ($_); setcomplete \&cfg::maketargets; '
. 'run "-/r", getcmd "make -f $_q"; undef @cfg::makefiles',
'run `make` using this Makefile'],
'Ext Z' => ['run -s_2P "uncompress <"', 'view this file uncompressed'],
'Ext bz2' => ['run -s_2P "bzip2 -d <"', 'view this file bunzipped'],
'Ext g?z' => ['run -s_2P "gzip -d <"', 'view this file gunzipped'],
'! -f _' => ['run -s=r "stat"', 'run `stat` on this special file'],
&mailcap2typemap('', '', ['take' => 'ALL'],
'text/plain', 'text/x-mail', 'message/rfc822', 'message/news'),
'-s _ && -B _' => ['run -s_2p "strings <"',
'view the strings in this binary file'],
'' => ['run -s_ $pager', 'view this file'],
);
@typemap_do = &akeys(@typemap_do);
$cfg::quemarkmsg = 'For help, press % or ^ or &; To quit, press ^Q';
sub cfg::pipetoshell { &pipeto(&getshell('|Shell:'), @_); &ret(); &winch() }
%keymap_ = @keymap_ = (
'TTL_' => 'MAIN MODE KEY COMMANDS',
"\cA" => ['cd pwd; win', "cd to the current directory's hard path"],
"\cB" => ['@bagkeys ? rebag : rebag(@cfg::savebagkeys)',
"toggle the bag's presence"],
"\cC" => ['altls \@choose, "Chosen Files"; win',
'switch to/from the chosen files display'],
"\cD" => ['altls \@cdhist, "Directory History"; win',
'switch to/from the directory history display'],
"\cF" => ['altls \@dohist, "File History"; win',
'switch to/from the file history display'],
"\cG" => ['msg diskspace', 'report the disk space for the current disk'],
"\cH" => ['bag "["', 'slide the bag backward on the screen'],
"\cI" => ['bag "]"', 'slide the bag forward on the screen'],
"\cJ" => ['msg $point', 'report the point file'],
"\cL" => ['winch', 'redraw the screen, clearing any long listing'],
"\cM" => ['cd ".."; win', 'cd to the parent directory'],
"\cN" => ['setnorun "once"; win',
"don't run but describe the next key command"],
"\cP" => ['cdhist "prev"; win',
'cd to the previous directory in the history'],
"\cQ" => [['do $vshnucfg; err $@; win', 'reload the config file ($vshnucfg)',
"cC\cClL\cL", 'load $vshnucfg'],
['restart', 'restart and reinitialize $VNAME ($0)',
"sS\cS", 'restart'],
['stop; winch', 'suspend to the master shell',
"zZ\cZvV\cVyY\cY", 'suspend'],
['last', 'quit $VNAME', "qQ", 'quit']],
"\cR" => ['rechoose; keymap "=choose"',
'rechoose the previously chosen set'],
"\cT" => ['cfg::setset(@choose) && win',
'append the chosen set to the current file set display'],
"\cU" => ['clear; win', 'clear the chosen set or current set display'],
"\cV" => ['perl "print versions"; ret; winch',
'list the $VNAME software versions and packages'],
"\cW" => ['cdhist "start"; win',
'rewind and cd to the start of the directory history'],
"\cY" => ['msg filecount', 'report the numbers of directories and files'],
"\c[" => ['win "<1"', 'shift the file display left one column'],
"\034" => ['mousemode("toggle") || beep; win', 'toggle the mouse mode'],
"\c]" => ['win ">1"', 'shift the file display right one column'],
"\c^" => ['msg $cwd', 'report the current directory'],
"\c_" => ['pipeto $pager, "#!/bin/perl\n", vardump get "Refs (all):"; winch',
'list the given perl variables with their values'],
" " => ['win "]#", 1, 1', 'page to the next screen of this display'],
"\"" => ['typemap "*expand"', 'toggle the expand/collapse file type mode'],
"#" => [['$aged = gets "Age ($aged):"; winch',
'set the age threshold ($aged) for time coloring',
'aA', 'age threshold ($aged)'],
['$depth = gets "Depth ($depth):"; winch',
'set the depth limit ($depth) for expanding, <0 means no limit',
'dD', 'depth limit ($depth)'],
['$where = gets "Where {$where}:"; winch',
'set the where clause {$where} for display subsets',
'wW', 'where clause {$where}'],
['$full = gets "Full ($full):"; winch',
'set the % disk full warning threshold ($full) for df coloring',
'fF', '% disk full threshold ($full)'],
['$cfg::xcb = gets "X Cut Buffer ($cfg::xcb):"; winch',
'set the X cut buffer number ($cfg::xcb) for cuts and pastes',
'xX', 'X cut buffer ($cfg::xcb)']],
"\$" => ['shellv "Shell"; winch',
'run a series of shell (or ;perl) commands, `v` to exit'],
"%" => ['help "-unused"; winch',
'list the commands for the main key mode'],
"&" => ['help "=typemap"; winch',
'list the commands for the current file type mode'],
"'" => ['keymap "=choose"; point',
'choose the point file and enter choose mode'],
"(" => ['setmark(getkey("Set Mark:"), @bagkeys) || beep; home',
'mark the current directory position with the given non-bag key'],
")" => ['cfg::pointormark getkey "To:"; winch 1',
'go to the given mark or point to the given bag key'],
"*" => ['winat getfile "Find:"',
'page to the file alphabetically >= the given string'],
"+" => ['longtrunc "toggle"; win',
'truncate the long listing area on the left/right'],
"-" => ['point "<1"; point',
'act on the file above the point by its type'],
"." => ['setcomplete \&completetypepath, "Gnu";'
. ' dotypepath getfile "File:"; setcomplete',
'act on the given file by its type,' .
' searching in \$CD_PATH and histories'],
"/" => ['keymap "choose"', 'enter/exit choose key mode'],
"0" => ['point "-\$"; win 1, 1, 1', 'page to the top of the directory'],
"1" => ['altls \@cfg::set1, "File Set 1"; win',
'switch to/from the first file set display'],
"2" => ['altls \@cfg::set2, "File Set 2"; win',
'switch to/from the second file set display'],
"3" => ['altls \@cfg::set3, "File Set 3"; win',
'switch to/from the third file set display'],
"4" => ['altls \@cfg::set4, "File Set 4"; win',
'switch to/from the fourth file set display'],
"5" => ['longls "-win", "md5sum -- \@_ 2>&1"',
'long list files with their `md5sum` output'],
"8" => ['(@cfg::disks = disks) && longls ";diskspace"'
. ' if altls \@cfg::disks, "Disks"; win',
'switch to/from the disks file set df display'],
"9" => ['helpmarks; winch', 'list the defined marks'],
":" => ['shellp getshell "Shell:"; ret; winch',
'run a shell (or ;perl) command, leaving output'],
";" => ['shellp getshell "Shell;"; winch',
'run a shell (or ;perl) command, clearing output'],
"<" => ['run -s $cfg::mailer', 'run mailer'],
"=" => ['point ">1"; point',
'act on the file below the point by its type'],
">" => ['point', 'act on the point file by its type'],
"?" => ['typemap "*do"; msg $cfg::quemarkmsg',
'toggle the special action file type mode'],
"B" => ['run getcmd "man"', 'run `man` with the given arguments'],
"F" => ['cfg::longls2 ["file", ifopt("L"), "--"], [";mimetype"]',
'long list files with their `file` output or MIME type'],
"L" => ['longls "-win", "+1"',
'long list files with their stat info, repeat for more'],
"M" => ['setcomplete \&cfg::maketargets; run "-/r", getcmd "make"',
'run `make` with the given arguments'],
"O" => ['keymap "opts"', 'push to option key mode'],
"P" => ['longls "-win", "rpm -qf -- \$_ 2>&1"',
'long list files with their owning RPM package'],
"Q" => ['longls "-win", gets "Command:"',
'long list files with the queried shell command output'],
"S" => [['cfg::pipetoshell $cwd',
'pipe the current directory to a shell command',
'.', 'current directory'],
['cfg::pipetoshell atabsfile $cwd',
'pipe the current user\@host:directory to a shell command',
'dD', 'user\@host:directory'],
['cfg::pipetoshell absfile $point',
'pipe the point file to a shell command',
'>pP', 'point file'],
['cfg::pipetoshell atabsfile $point',
'pipe the point user\@host:file to a shell command',
'fF', 'user\@host:file'],
['cfg::pipetoshell join(" ", map { absfile $_ } @choose)',
'pipe the chosen files to a shell command, one-line',
'\\', 'chosen files, one-line'],
['cfg::pipetoshell join("\n", map { absfile $_ } @choose)',
'pipe the chosen files to a shell command, multi-line',
'/', 'chosen files, multi-line'],
['cfg::pipetoshell join("\0", (map { absfile $_ } @choose), "")',
'pipe the chosen files to a shell command, null-ended',
'0', 'chosen files, null-ended'],
['cfg::pipetoshell join(" ", map { atabsfile $_ } @choose)',
'pipe the user\@host:chosen files to a shell command, one-line',
'c', 'user\@host:chosen, one-line'],
['cfg::pipetoshell join("\n", map { atabsfile $_ } @choose)',
'pipe the user\@host:chosen files to a shell command, multi-line',
'C', 'user\@host:chosen, multi-line'],
['cfg::pipetoshell join("\0", (map { atabsfile $_ } @choose), "")',
'pipe the user\@host:chosen files to a shell command, null-ended',
"\cC", 'user\@host:chosen, null-ended']],
"T" => ['run "top"', 'run `top`'],
"U" => ['collapse lsall; win', 'collapse all the display files'],
"V" => ['stop; winch', 'suspend to the master shell'],
"X" => [['cfg::xcut $cwd',
'copy the current directory to X cut buffer $cfg::xcb',
'.', 'current directory'],
['cfg::xcut atabsfile $cwd',
'copy the current user\@host:directory to X cut buffer $cfg::xcb',
'dD', 'user\@host:directory'],
['cfg::xcut absfile $point',
'copy the point file to X cut buffer $cfg::xcb',
'>pP', 'point file'],
['cfg::xcut atabsfile $point',
'copy the point user\@host:file to X cut buffer $cfg::xcb',
'fF', 'user\@host:file'],
['cfg::xcut join(" ", map { absfile $_ } @choose)',
'copy the chosen files to X cut buffer $cfg::xcb, one-line',
'\\', 'chosen files, one-line'],
['cfg::xcut join("\n", map { absfile $_ } @choose)',
'copy the chosen files to X cut buffer $cfg::xcb, multi-line',
'/', 'chosen files, multi-line'],
['cfg::xcut join(" ", map { atabsfile $_ } @choose)',
'copy the user\@host:chosen files to X cut buffer, one-line',
'c', 'user\@host:chosen, one-line'],
['cfg::xcut join("\n", map { atabsfile $_ } @choose)',
'copy the user\@host:chosen files to X cut buffer, multi-line',
'C', 'user\@host:chosen, multi-line']],
"Y" => ['expand cfg::lsexpand; win', 'expand the display files'],
"[" => ['expand $point; win', 'expand the point file'],
"\\" => ['cdhist "back"; win', 'cd back to the prior directory'],
"]" => ['collapse $point; win', 'collapse the point file'],
"^" => ['help "=mousemap"; winch',
'list the commands for the current mouse mode'],
"_" => ['longlen "+33%r"; win',
'shift the long listing area to the left, wrapping around'],
"`" => ['run -sr "cal -3"', 'view the current calendar'],
"{" => ['point "<1"', 'slide the point up one file, wrapping around'],
"|" => ['columns "<1"', 'decrement the number of file cols,'
. ' wrapping around to the max'],
"}" => ['point ">1"', 'slide the point down one file, wrapping around'],
"~" => ['cd "~"; win', "cd to the user's home directory"],
"kd" => ['bag "", "+1"', 'slide the bag down on the screen'],
"kl" => ['bag "-1"', 'slide the bag left on the screen'],
"kr" => ['bag "+1"', 'slide the bag right on the screen'],
"ku" => ['bag "", "-1"', 'slide the bag up on the screen'],
"mous" => ['domouse', 'handle a mouse event'],
"pgdn" => ['point "+1"', 'slide the point down one file'],
"pgup" => ['point "-1"', 'slide the point up one file'],
"" => ['beep; home', 'invalid command key'],
);
@keymap_ = &akeys(@keymap_);
&mapadd('keymap_', "\cZ", $keymap_{"\cQ"}, ">\cY");
&mapadd('keymap_', "\177", $keymap_{"\cH"}, "<kd");
&mapadd('keymap_', "del", $keymap_{"\cH"}, "<kd");
&mapadd('keymap_', "end", $keymap_{"\c["}, "<kd");
&mapadd('keymap_', "home", $keymap_{"~"}, "<kd");
&mapadd('keymap_', "ins", $keymap_{"\cI"}, "<kd");
$cfg::unchoose = '; unchoose @choose; keymap; winch';
sub cfg::mapchoose { "map { @_ } \@choose; ret" . $cfg::unchoose }
%keymap_choose = @keymap_choose = (
'TTL/' => 'CHOOSE MODE KEY COMMANDS',
"\cB" => ['choose @bagfiles', 'choose all the bag files'],
"\cE" => ['map { dotype } @choose',
'act on each chosen file in turn by its type'],
"\cO" => ['do { my $s = gets("Shell:"); map { run "-_n", $s } @choose };'
. ' ret' . $cfg::unchoose,
'run a shell command with each chosen file'],
"\cX" => ['unchoose $choose[$#choose]; win',
'unchoose the last chosen file'],
"!" => ['choose grepls gets "Expr:"; winch',
'choose the display files for which the given expression is true'],
"#" => ['choosebyn getkey "Digit:"',
'choose the Nth chosen file for the given N'],
"%" => ['help "-unused"; winch',
'list the commands for the choose key mode'],
"." => ['choose matchfiles gets "Regexp:"; winch',
'choose the display files that match the given pattern'],
":" => ['run -ruk gets("(Shell:"), quote(@choose), get("Shell):")',
'run a shell command with the chosen files, leaving output'],
";" => ['run -uk gets("(Shell;"), quote(@choose), get("Shell);")',
'run a shell command with the chosen files, clearing output'],
"@" => ['choose lsall', 'choose all the display files'],
"A" => ['run -#puk "stat", ifopt("L")', 'run `stat` on the chosen files'],
"B" => ['run -X#uk "konqueror"', 'browse the chosen files'],
"C" => [['setcomplete \&users; run "-s+/rukL", "chown", gets "Owner:"',
'run `chown` on the chosen files', 'oO', 'chown'],
['setcomplete \&groups;'
. ' run "-s+/rukL", "chgrp", ifopt("h"), gets "Group:"',
'run `chgrp` on the chosen files', 'gG', 'chgrp'],
['setcomplete sub {}; run "-s+/rukL", "chmod", gets "Mode:"',
'run `chmod` on the chosen files', 'mM', 'chmod'],
['setcomplete sub {}; run "-s+/rukL", "chmod", "+r"',
'run `chmod +r` on the chosen files', 'rR', 'chmod +r'],
['setcomplete sub {}; run "-s+/rukL", "chmod", "+w"',
'run `chmod +w` on the chosen files', 'wW', 'chmod +w'],
['setcomplete sub {}; run "-s+/rukL", "chmod", "+x"',
'run `chmod +x` on the chosen files', 'xX', 'chmod +x'],
['setcomplete sub {}; run "-s+/rukL", "chmod", "go-rwx"',
'run `chmod go-rwx` on the chosen files', '-', 'chmod go-rwx']],
"D" => ['ask "Remove recursively?"; run "-#buk", "rm -r"', 'recursively'
. ' remove the chosen files/directories (background)'],
"E" => ['run -s+uk $cfg::editor', 'edit the chosen files'],
"I" => ['run -x#uk "eog"', 'display the chosen image files'],
"R" => ['ask "Remove?"; remove @choose' . $cfg::unchoose,
'remove the chosen files and empty directories'],
"[" => ['expand @choose' . $cfg::unchoose,
'expand the chosen directories'],
"]" => ['collapse @choose' . $cfg::unchoose,
'collapse the chosen directories'],
"`" => [['choose getoutput "`Shell`;"; winch',
'choose the file list output of a shell (or ;perl) command',
'cCsS`;:$', 'command'],
['choose split /:/, $ENV{PATH}; win',
'choose the elements of the PATH environment variable',
'p', 'PATH'],
['choose split /:/, $ENV{CD_PATH}; win',
'choose the elements of the CD_PATH environment variable',
'P', 'CD_PATH'],
['choose sort &disks; win', 'choose all system disks',
'dDmM', 'disks'],
['choose sort &diskdevs; win', 'choose all system disk devices',
'vV', 'disk devices']],
"" => ['cmdeval keymapcmd ""',
'execute the main mode command for this key'],
);
@keymap_choose = &akeys(@keymap_choose);
%keymap_opts = @keymap_opts = (
'TTLO' => 'OPTS MODE KEY COMMANDS',
"\cN" => $keymap_{"\cN"},
"%" => ['help "-unused", "=keymap_opts"; winch',
'list the commands for the option key mode'],
"=" => ['initopts; keymap; win', 'reset all options'],
"O" => ['keymap', 'pop from option key mode'],
"mous" => $keymap_{"mous"},
"" => ['beep; keymap; home', 'invalid option'],
);
@keymap_opts = &akeys(@keymap_opts);
$optkeys = '#*/ABCDFHILNPSTVXabcdfghiklmnoprstuvx';
$optons = ($color) ? '*CHVn' : 'V';
%cfg::desc_opts = (
"#" => "list inode number instead of size in long listings",
"*" => "use color",
"/" => "sort by increasing path depth",
"A" => "don't list . and ..",
"B" => "don't list backup files",
"C" => "color files",
"D" => "segregate directories to the list top",
"F" => "sort by file color",
"H" => "color command listings and prompts",
"I" => "sort by increasing inode",
"L" => "follow symlinks for long listings, stat sorting, etc",
"N" => "show/sort owners and groups by ids not names",
"P" => "sort by file basename",
"S" => "sort by decreasing size",
"T" => "tag files",
"V" => "use an audio beep",
"X" => "sort by file extension",
"a" => "don't list dot files",
"b" => "segregate dot files to the list bottom",
"c" => "sort by change time (newest first)",
"d" => "segregate directories to the list bottom",
"f" => "don't sort list",
"g" => "sort by group or increasing gid",
"h" => "long list a symlink's stats not its destination, etc",
"i" => "sort case-insensitively",
"k" => "sort command listings by key",
"l" => "sort by decreasing number of links",
"m" => "sort by decreasing permissions mode",
"n" => "color long listings",
"o" => "sort by owner or increasing uid",
"p" => "prefer command strings instead of command descriptions",
"r" => "reverse list",
"s" => "show Internet time in screen date",
"t" => "sort by modification time (newest first)",
"u" => "sort by access time (newest first)",
"v" => "use a visual beep",
"x" => "don't color files as executable",
);
foreach (split(//, $optons)) {
$cfg::desc_opts{$_} = "don't $cfg::desc_opts{$_}"
unless $cfg::desc_opts{$_} =~ s/^don't //;
}
foreach (split(//, $optkeys)) {
&mapadd('keymap_opts', $_,
["setopt '$_'; keymap; win", $cfg::desc_opts{$_}]);
}
undef %cfg::desc_opts;
sub opton {
my $opt = shift;
return unless length($opt) == 1 && index($optkeys, $opt) >= 0;
$optons .= $opt unless $optons =~ s/$opt//;
$keymap_opts{$opt}[1] = "don't $keymap_opts{$opt}[1]"
unless $keymap_opts{$opt}[1] =~ s/^don't //;
}
%cfg::typering = ('' => 'do', 'do' => 'expand', 'expand' => '');
%mousemap_ = @mousemap_ = (
'TTL_' => 'MOUSE COMMANDS',
'user' => [[@{$keymap_{"~"}}, &mev2c('1u')]],
'dir' => [['setopt "t"; win', ${$keymap_opts{"t"}}[1],
&mev2c('1u')],
[@{${$keymap_{"X"}}[1]}[0, 1], &mev2c('3u')],
[@{$keymap_{"Y"}}, &mev2c('Wd')],
[@{$keymap_{"U"}}, &mev2c('Wu')]],
'dir...' => ['msg $_', 'report the full directory name'],
'title' => [[@{$keymap_{"\cF"}}, &mev2c('1u')],
[@{$keymap_{"\cD"}}, &mev2c('2u')],
[@{$keymap_{"\cC"}}, &mev2c('3u')],
['cmdeval $keymap_{cfg::nextset(+1) || 4}',
'cycle forward through the file set displays',
&mev2c('Wd')],
['cmdeval $keymap_{cfg::nextset(-1) || 1}',
'cycle backward through the file set displays',
&mev2c('Wu')],
[@{$keymap_{"8"}}, &mev2c('cWd', 'cWu')]],
'title...' => ['msg $_', 'report the full title'],
'state' => [['initopts; win', ${$keymap_opts{"="}}[1], &mev2c('2u')],
[@{$keymap_{"|"}}, &mev2c('3u')]],
'file' => [['dotypein', 'act on the file by its type'
. ' per normal mode', &mev2c('1u')],
['dotypein "do"', 'act on the file by its type'
. ' per special action mode', &mev2c('2u')],
['choose $_; keymap "=choose"',
'choose the file and enter choose mode', &mev2c('3u')],
['expand $_; win', 'expand the file', &mev2c('Wd')],
['collapse $_; win', 'collapse the file', &mev2c('Wu')],
['do { local $depth = -1; expand $_ }; win',
'completely expand the file', &mev2c('cWd')],
['do { local $depth = -1; collapse $_ }; win',
'completely collapse the file', &mev2c('cWu')]],
'file...' => ['msg $_', 'report the full filename'],
'longls' => [[@{$keymap_{"_"}}, &mev2c('1u')],
['setopt "L"; win', ${$keymap_opts{"L"}}[1],
&mev2c('2u')],
[@{$keymap_{"+"}}, &mev2c('3u')]],
'long' => [[@{$keymap_{"_"}}, &mev2c('1u')],
[@{$keymap_{"+"}}, &mev2c('3u')]],
'bag' => [['point $_[1]', 'point to the file', &mev2c('1u')],
[@{$keymap_{"\cB"}}, &mev2c('2u')],
['cfg::xcut atabsfile $_',
'copy the user\@host:file to X cut buffer $cfg::xcb',
&mev2c('3u')],
[@{$keymap_{"\cI"}}, &mev2c('Wd', 'cWd')],
[@{$keymap_{"\cH"}}, &mev2c('Wu', 'cWu')]],
'point' => [['point $_[1]', 'point to the file', &mev2c('1u')],
[@{$keymap_{"\cB"}}, &mev2c('2u')],
[@{${$keymap_{"X"}}[3]}[0, 1], &mev2c('3u')],
[@{$keymap_{"}"}}, &mev2c('Wd')],
[@{$keymap_{"{"}}, &mev2c('Wu')],
[@{$keymap_{"pgdn"}}, &mev2c('cWd')],
[@{$keymap_{"pgup"}}, &mev2c('cWu')]],
'chose#' => [['$_[1] ? unchoose($_) : choose($_)',
"toggle the file's choose status", &mev2c('1u')],
['unchoose $_', 'unchoose the file', &mev2c('2u')],
['choose $_', 'choose the file', &mev2c('3u')]],
'mode' => [
['typemap "*$cfg::typering{$typemap[$#typemap]}"',
'change the file type mode', &mev2c('2u')],
[${$keymap_{"/"}}[0],
'change the key mode', &mev2c('3u')],
[@{${$keymap_{"X"}}[6]}[0, 1], &mev2c( 'Wd', 'Wu')],
[@{${$keymap_{"X"}}[7]}[0, 1], &mev2c('cWd', 'cWu')]],
'mode...' => ['msg $_', 'report the full mode text'],
'time' => [['win', 'redraw the screen', &mev2c('1u')],
['opton "s"; win',
'toggle the Internet time display', &mev2c('2u')],
[@{$keymap_{"\cL"}}, &mev2c('3u')],
[@{$keymap_{"L"}}, &mev2c('Wd', 'Wu')]],
'time_' => [['mousemap "test"',
'toggle the test mouse mode', &mev2c('3u')]],
'' => [
[@{$keymap_{"\cM"}}, &mev2c('2u')],
[@{$keymap_{"\\"}}, &mev2c('3u')],
[@{$keymap_{" "}}, &mev2c('Wd')],
[@{$keymap_{"0"}}, &mev2c('Wu')],
[@{$keymap_{"\c]"}}, &mev2c('cWd')],
[@{$keymap_{"\c["}}, &mev2c('cWu')]],
);
@mousemap_ = &akeys(@mousemap_);
&mapadd('mousemap_', 'page', $mousemap_{'state'}, '<title');
&mapadd('mousemap_', 'filetag', $mousemap_{'file'}, '>file');
&mapadd('mousemap_', 'file/', $mousemap_{'file...'}, '>file...');
%mousemap_test = @mousemap_test = (
'TTLt' => 'TEST MODE MOUSE COMMANDS',
'time_' => $mousemap_{'time_'},
'' => ['msg mousetxt', 'report the mouse event'],
);
@mousemap_test = &akeys(@mousemap_test);
sub onrestart { 1 }
sub onquit { 1 }
sub cfgcolorlong {
local $_ = join('', @_); my $s;
($s = &rccolorlong($_)) ne '' && ($_ = $s) if defined &rccolorlong;
return &colorlongline($_, $co_error)
if $long =~ /^\s*md5sum\b/ && ! /^\\?[0-9a-f]*\\?$/i;
return &colorlongline($_, $co_msg)
if $long =~ /^\s*rpm\b/ && /is ?n[o']t owned/i;
return &colorlongline($_, $co_error)
if $long =~ /^\s*;.*mimetype\b/ && /Can ?n?['o]t stat/i;
s/^([^\s,;]*)(\/)([^\s,;]*)(,\s*)?([^;]*)(;\s*)?(.*)/
&color($1, $co_ftype) . $2 .
&color($3, $co_myper) . $4 .
&color($5, $co_sbits) . $6 .
&color($7, $co_perms)/e if $long =~ /^\s*;.*mimetype/;
$_;
}
sub cfg::longls2 {
my @cmd1 = @{$_[0]}; my @cmd2 = @{$_[1]};
&longls("-win", $long =~ /^\s*\Q$cmd1[0]\E\b/ ? @cmd2 : @cmd1);
}
sub cfg::lsexpand { grep { ! /(^|\/)\.git$/ } &lsall() }
sub cfg::onecmd { 0 }
sub cfg::pointormark {
return &point($_[0]) if grep($_[0] eq $_, @bagkeys);
local($mark, $dir, $file, $path) =
map { &getmark($_[0], $_) } '', qw(dir file path);
return &beep() if ! $mark;
&cmdeval([['cd $mark', "cd to mark $_[0]",
'dc', "cd to $dir @ $file"],
['dotype $path', "act on mark $_[0] by its type",
'fp', "act on $path"]]);
}
sub cfg::setset {
grep($altls == $_, \@cfg::set1, \@cfg::set2, \@cfg::set3, \@cfg::set4)
? do { push(@$altls, @_); 1 } : do { &beep(); 0 };
}
sub cfg::abssets {
foreach (\@cfg::set1, \@cfg::set2, \@cfg::set3, \@cfg::set4) {
map(/^\// || do { $_ = &absfile($_, $_[0]) }, @$_);
}
}
sub cfg::nextset {
my $s = ($altls == \@cfg::set1) ? 1 : ($altls == \@cfg::set2) ? 2 :
($altls == \@cfg::set3) ? 3 : ($altls == \@cfg::set4) ? 4 : 0;
($s + ((defined $_[0]) ? $_[0] : 1)) % 5;
}
sub cfg::maketargets {
my %targets = ();
foreach my $makefile (@cfg::makefiles ? @cfg::makefiles
: ('makefile', 'Makefile')) {
next unless open(MAKEFILE, $makefile);
while (<MAKEFILE>) {
next unless /^[^\t#].*:/;
chomp; s/:.*//; $targets{$_}++;
}
close MAKEFILE;
}
sort keys %targets;
}
$vshnurc = $ENV{VSHNURC} || $default_vshnurc ||
((-f "$ENV{HOME}/.vshnurc") ? "$ENV{HOME}/.vshnurc" : 'vshnurc.pl');
(-r _) ? do { do $vshnurc; &err($@) } : &err("Cannot read $vshnurc")
if -f $vshnurc;
1;