X-Git-Url: https://ruderich.org/simon/gitweb/?p=fcscs%2Ffcscs.git;a=blobdiff_plain;f=bin%2Ffcscs;h=da614bc396b3af1d6214d42aec7f425fc9fe118f;hp=a2a95b7d567e15b90d9f404b7abc02b506921027;hb=23d32b9dae77a88ea040983ab82f3ad7b6e57b9e;hpb=b59955be2da0de3a1bcecbde196e30851b5a90ac diff --git a/bin/fcscs b/bin/fcscs index a2a95b7..da614bc 100755 --- a/bin/fcscs +++ b/bin/fcscs @@ -445,7 +445,7 @@ sub get_regex_matches { sub run_command { - my ($screen, $config, $cmd) = @_; + my ($screen, $cmd) = @_; $screen->debug('run_command', "running @{$cmd}"); @@ -502,9 +502,11 @@ sub run_in_background { # Necessary for GNU screen or it'll keep the window open until an # external command has run. - close STDIN or die $!; - close STDOUT or die $!; - close STDERR or die $!; + require File::Spec; + my $devnull = File::Spec->devnull(); + open STDIN, '<', $devnull or die $!; + open STDOUT, '>', $devnull or die $!; + open STDERR, '>', $devnull or die $!; # Double-fork to prevent zombies. my $pid = fork; @@ -716,6 +718,8 @@ The following normal modes are available: =item B select URLs +=item B select IPv4 and IPv6 addresses + =back =cut @@ -743,6 +747,19 @@ sub mapping_mode_url { handler => $config->{handler}{url}, }; } +sub mapping_mode_ip { + my ($key, $screen, $config, $input) = @_; + + $screen->debug('mapping_mode_ip', 'started'); + + my @ipv4 = get_regex_matches($input, $config->{regex}{ipv4}); + my @ipv6 = get_regex_matches($input, $config->{regex}{ipv6}); + return { + select => 'ip select', + matches => [@ipv4, @ipv6], + handler => $config->{handler}{ip}, + }; +} =head2 SEARCH MODE (AND EXTEND MODE) @@ -830,6 +847,11 @@ sub mapping_mode_search { $screen->cursor(0); + $screen->prompt(name => undef, value => undef); # clear prompt + $screen->draw_prompt($config); + + $screen->debug('mapping_mode_search', 'done'); + return { select => 'search', matches => \@last_matches, @@ -865,18 +887,40 @@ sub handler_yank { # GNU screen displays an annoying "Slurping X characters into buffer". # Use 'msgwait 0' as a hack to disable it. my $msgwait = $config->{setting}{screen_msgwait}; - run_command($screen, $config, ['screen', '-X', 'msgwait', 0]); - run_command($screen, $config, ['screen', '-X', 'readbuf', $tmp]); - run_command($screen, $config, ['screen', '-X', 'msgwait', $msgwait]); + run_command($screen, ['screen', '-X', 'msgwait', 0]); + run_command($screen, ['screen', '-X', 'readbuf', $tmp]); + run_command($screen, ['screen', '-X', 'msgwait', $msgwait]); } elsif ($config->{setting}{multiplexer} eq 'tmux') { $screen->debug('handler_yank', 'using tmux'); - run_command($screen, $config, ['tmux', 'load-buffer', $tmp]); + run_command($screen, ['tmux', 'load-buffer', $tmp]); } else { die 'unsupported multiplexer'; } unlink $tmp or die $!; + + if ($config->{setting}{yank_x11}) { + $screen->debug('handler_yank', 'setting X11 selection'); + + my @xsel_cmd = qw( xsel --input --primary ); + my @xclip_cmd = qw( xclip -in -selection primary ); + + my $fh; + { + # We don't care if a program doesn't exist. + no warnings; + + if (not open $fh, '|-', @xsel_cmd) { + if (not open $fh, '|-', @xclip_cmd) { + die "install xsel or xlip to yank to X11 selection\n"; + } + } + } + print $fh $match->{value} or die $!; + close $fh or die $!; + } + return; } sub handler_paste { @@ -905,7 +949,7 @@ sub handler_paste { # Sleep until we switch back to the current window. Time::HiRes::usleep($config->{setting}{paste_sleep}); - run_command($screen, $config, \@cmd); + run_command($screen, \@cmd); }); return; } @@ -916,7 +960,7 @@ sub handler_url { run_in_background($screen, sub { my @cmd = ( @{$config->{setting}{browser}}, $match->{value} ); - run_command($screen, $config, \@cmd); + run_command($screen, \@cmd); }); return; } @@ -1002,6 +1046,8 @@ them in parentheses): =item B select URLs (C<\&mapping_mode_url>) +=item B select IPv4 and IPv6 addresses (C<\&mapping_mode_ip>) + =item B search for regex to get selection (C<\&mapping_mode_search>) =item B quit fcscs (C<\&mapping_quit>) @@ -1018,6 +1064,9 @@ The following simple mappings are available by default: =back +Note that yanking only uses the GNU screen or Tmux paste buffer by default. To +also copy to X11 selection, enable the B option. + The following additional mappings are available by default: =over @@ -1047,6 +1096,7 @@ Example: my %mapping_mode = ( f => \&mapping_mode_path, u => \&mapping_mode_url, + i => \&mapping_mode_ip, '/' => \&mapping_mode_search, q => \&mapping_quit, ); @@ -1098,23 +1148,25 @@ Defaults in parentheses. =over -=item B enable debug mode, writes to I<~/.config/fcscs/log> (C<0>) +=item B enable debug mode, writes to I<~/.config/fcscs/log> (C<0>) + +=item B start in this mode, must be a valid mode mapping (C<\&mapping_mode_url>) -=item B start in this mode, must be a valid mode mapping (C<\&mapping_mode_url>) +=item B set multiplexer ("screen" or "tmux") if not autodetected (C) -=item B set multiplexer ("screen" or "tmux") if not autodetected (C) +=item B ignore case when searching (C<0>) -=item B ignore case when searching (C<0>) +=item B ignore case unless one uppercase character is searched (C<1>) -=item B ignore case unless one uppercase character is searched (C<1>) +=item B copy selection also to X11 primary selection when yanking (C<0>) -=item B sleep x us before running paste command (C<100_000>) +=item B sleep x us before running paste command (C<100_000>) -=item B GNU Screen's msgwait variable, used when yanking (C<5>) +=item B GNU Screen's msgwait variable, used when yanking (C<5>) =item B additional accept key like return, set to C<\n> to disable (C) -=item B browser command as array reference (C<['x-www-browser']>) +=item B browser command as array reference (C<['x-www-browser']>) =back @@ -1126,26 +1178,31 @@ Example: =cut my %setting = ( # options - debug => 0, - initial_mode => \&mapping_mode_url, - multiplexer => undef, - ignorecase => 0, - smartcase => 1, - paste_sleep => 100_000, - screen_msgwait => 5, + debug => 0, + initial_mode => \&mapping_mode_url, + multiplexer => undef, + ignorecase => 0, + smartcase => 1, + yank_x11 => 0, + paste_sleep => 100_000, + screen_msgwait => 5, # global mappings alternative_return => 's', # commands - browser => ['x-www-browser'], + browser => ['x-www-browser'], ); =head2 REGEXPS =over -=item B used by C<\&mapping_mode_url()> +=item B used by C<\&mapping_mode_url> -=item B used by C<\&mapping_mode_path()> +=item B used by C<\&mapping_mode_path> + +=item B used by C<\&mapping_mode_ip> + +=item B used by C<\&mapping_mode_ip> =back @@ -1159,6 +1216,10 @@ my %regex = ( # Taken from urlview's default configuration file, thanks. url => qr{((?:(?:(?:http|https|ftp|gopher)|mailto):(?://)?[^ <>"\t]*|(?:www|ftp)[0-9]?\.[-a-z0-9.]+)[^ .,;\t\n\r<">\):]?[^, <>"\t]*[^ .,;\t\n\r<">\):])}, path => qr{(~?[a-zA-Z0-9_./-]*/[a-zA-Z0-9_./-]+)}, + # IP addresses with optional prefix. Not perfectly accurate but good + # enough. + ipv4 => qr!\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:/\d{1,2})?)\b!, + ipv6 => qr!\b((?:[0-9a-fA-F]{1,4})?(?::+[0-9a-fA-F]{1,4})+(?:/\d{1,3})?)\b!, ); =head2 HANDLERS @@ -1175,6 +1236,8 @@ The following handlers are available, defaults in parentheses. =item B used to open URLs (e.g. in a browser) (C<\&handler_url>) +=item B used to handle IPs (C<\&handler_yank>) + =back Example: @@ -1186,8 +1249,7 @@ Example: if ($match->{value} =~ m{^https://www.youtube.com/}) { return run_in_background($screen, sub { - run_command($screen, $config, - ['youtube-dl-wrapper', $match->{value}]); + run_command($screen, ['youtube-dl-wrapper', $match->{value}]); }); } handler_url(@_); @@ -1198,6 +1260,7 @@ my %handler = ( yank => \&handler_yank, paste => \&handler_paste, url => \&handler_url, + ip => \&handler_yank, ); my %state = ( @@ -1219,6 +1282,7 @@ Create a new Curses attribute with the given fore- and background color. mapping_mode_path() mapping_mode_url() + mapping_mode_ip() mapping_mode_search() mapping_paste() @@ -1256,6 +1320,7 @@ package Fcscs { sub mapping_mode_path { return main::mapping_mode_path(@_); } sub mapping_mode_url { return main::mapping_mode_url(@_); } + sub mapping_mode_ip { return main::mapping_mode_ip(@_); } sub mapping_mode_search { return main::mapping_mode_search(@_); } sub mapping_paste { return main::mapping_paste(@_); }