4 no if ($] >= 5.018), 'warnings' => 'experimental::smartmatch';
7 #sub helpy { $pos = tell DATA; print STDERR <DATA>; seek DATA,$pos,0 }
8 sub helpy
{ system("pod2text", $me, "/dev/stderr") }
9 exit helpy
if $ARGV[0] eq '--help';
12 sub bye
{ print STDOUT
"export JOBSEL_DISPLAY_MODE=$dispmode"; exit ReadMode
0 }
13 sub getkey
{ while(not defined ($k = ReadKey
(-1))){} return $k }
14 $SIG{INT
}=$SIG{STOP
}=$SIG{STOP
}=$SIG{TSTP
}=$SIG{QUIT
}='bye';
15 $dispmode = $ENV{JOBSEL_DISPLAY_MODE
};
16 $dispmode = "x" unless $dispmode ~~ ["c", "x", "l"];
17 $dispmode = "l" unless $ARGV[1];
21 for(split/[\r\n]+/,$ARGV[0]){
22 ($j,$p)=/(\d+)\]\S?\s+(\d+)/;
23 if ( open(P
,"/proc/$p/stat") and ($c,$s)=(<P
>=~/\s\
((.+?
)\
)\s
+(\S
+)/) ) {
25 push @o,[$j,$c,$p,$s]; # job number, command, pid, state
28 push @x,sprintf "[%d] %5d %s %s",$j,$p,$s,$_;
36 print STDERR
"\033[s";
37 if($dispmode =~ /[xc]/)
39 print STDERR
"\033[1;1H";
40 if($dispmode eq "x") {
42 printf STDERR
"%s%s\033[m\n",($_==$in?
"\033[44;1;36m":"\033[1;36m"),$x[$_];
46 print STDERR
"\033[1;36mjobs: ";
48 printf STDERR
"%s[%%%s %s(%s) %s]\033[m ",($_==$in?
"\033[44;1;36m":"\033[1;36m"),@
{$o[$_]};
53 print STDERR
"\033[6n"; { local $/="R"; ($rn) = (<STDIN>=~/\
[(\d
+);/); }
54 printf STDERR
"\033[%d;1H", $rn-1;
56 printf STDERR
"%s[%%%s %s(%s) %s]\033[m ",($_==$in?
"\033[1;36m":"\033[36m"),@
{$o[$_]};
59 print STDERR
"\033[u";
66 if($k =~ /[DA]/) { # arrow left/up
69 elsif($k =~ /[CB]/) { # arrow right/down
72 elsif($k =~ /[H5]/) { # home/pg up
75 elsif($k =~ /[F6]/) { # end/pg down
78 elsif($k eq chr(27)) { bye
}
80 elsif($k eq chr(27)) { bye
}
82 elsif($k =~ /[ts ]/i) {
83 kill ${$o[$in]}[3] eq 'T' ?
18 : 20, ${$o[$in]}[2]; # CONT,TSTP
86 kill 9, ${$o[$in]}[2]; # KILL
89 kill 1, ${$o[$in]}[2]; # HUP
92 kill 2, ${$o[$in]}[2]; # INT
96 print STDERR
"Commandline:\t";
97 open A
,"/proc/".${$o[$in]}[2]."/cmdline";
98 print STDERR
join(" ",split/\x0/,<A
>)."\n";
100 print STDERR
"Directory:\t";
101 print STDERR
readlink "/proc/".${$o[$in]}[2]."/cwd","\n";
103 open A
,"/proc/".${$o[$in]}[2]."/status";
104 /^(ppid|uid|gid):/i and print STDERR
$_ while<A
>;
107 elsif($k =~ /[xcl]/i) {
110 elsif($k =~ /[?h]/i) {
113 elsif($k =~ /[\r\n]/) {
115 print STDOUT
"export JOBSEL_DISPLAY_MODE=$dispmode; fg ".$o[$in][0];
118 elsif($k =~ /q/i) { bye
}
120 # clear screen region
121 if($dispmode =~ /[xc]/) {
122 print STDERR
"\033[s\033[1;1H";
123 if($dispmode eq "x") {
124 print STDERR
" " x
$ARGV[1], "\n" for @x
126 elsif($dispmode eq "c") {
127 print STDERR
" " x
(-$pos+tell STDERR
)
129 print STDERR
"\033[u";
143 jobsel <B<joblist>> [B<COLUMNS>]
147 Improved job control frontend for bash. B<joblist> is a C<jobs -l> output from which B<jobsel> builds a menu.
148 B<COLUMNS> is an optional parameter, if omitted B<jobsel> calls tput(1) to obtain number of columns on the terminal.
152 Left,Right Select item
153 Enter Switch to job in forground
154 U Hangup selected process SIGHUP
155 I Interrupt process SIGINT
156 S,T,Space Suspend, Resume job SIGCONT,SIGTSTP
157 K Kill process SIGKILL
159 X,C,L Expanded, collapsed, in-line display mode
164 eval $(jobsel "$(jobs -l)" $COLUMNS)
168 =head2 Use as an alias
170 alias j='eval $(jobsel "$(jobs -l)" $COLUMNS)'
172 =head2 Bind a function key for it
174 bind -x '"\204"':"eval \$(jobsel \"\$(jobs -l)\" \$COLUMNS)"
175 bind '"\ej"':"\"\204\"" # ESC-J
177 Where 204 is an arbitrary free keyscan code