ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/selection
Revision: 1.63
Committed: Sat Jul 24 09:48:44 2021 UTC (2 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rxvt-unicode-rel-9_29, rxvt-unicode-rel-9_30, HEAD
Changes since 1.62: +1 -1 lines
Log Message:
remove =over identation

File Contents

# Content
1 #! perl
2
3 #:META:RESOURCE:%.pattern-0:string:first selection pattern
4
5 =head1 NAME
6
7 selection - more intelligent selection
8
9 =head1 DESCRIPTION
10
11 This extension tries to be more intelligent when the user extends
12 selections (double-click and further clicks). Right now, it tries to
13 select words, urls and complete shell-quoted arguments, which is very
14 convenient, too, if your F<ls> supports C<--quoting-style=shell>.
15
16 A double-click usually selects the word under the cursor, further clicks
17 will enlarge the selection.
18
19 The selection works by trying to match a number of regexes and displaying
20 them in increasing order of length. You can add your own regexes by
21 specifying resources of the form:
22
23 URxvt.selection.pattern-0: perl-regex
24 URxvt.selection.pattern-1: perl-regex
25 ...
26
27 The index number (0, 1...) must not have any holes, and each regex must
28 contain at least one pair of capturing parentheses, which will be used for
29 the match. For example, the following adds a regex that matches everything
30 between two vertical bars:
31
32 URxvt.selection.pattern-0: \\|([^|]+)\\|
33
34 Another example: Programs I use often output "absolute path: " at the
35 beginning of a line when they process multiple files. The following
36 pattern matches the filename (note, there is a single space at the very
37 end):
38
39 URxvt.selection.pattern-0: ^(/[^:]+):\
40
41 You can look at the source of the selection extension to see more
42 interesting uses, such as parsing a line from beginning to end.
43
44 This extension also offers the following actions:
45
46 =over
47
48 =item rot13
49
50 Rot-13 the selection when activated.
51
52 Example:
53
54 URxvt.keysym.C-M-r: selection:rot13
55
56 =back
57
58 =cut
59
60 sub on_user_command {
61 my ($self, $cmd) = @_;
62
63 $cmd eq "selection:rot13"
64 and $self->selection (map { y/A-Za-z/N-ZA-Mn-za-m/; $_ } $self->selection);
65
66 ()
67 }
68
69 sub on_action {
70 my ($self, $action) = @_;
71
72 $action eq "rot13"
73 and $self->selection (map { y/A-Za-z/N-ZA-Mn-za-m/; $_ } $self->selection);
74
75 ()
76 }
77
78 sub on_init {
79 my ($self) = @_;
80
81 if (defined (my $res = $self->resource ("cutchars"))) {
82 $res = $self->locale_decode ($res);
83 push @{ $self->{patterns} }, qr{\G [\Q$res\E[:space:]]* ([^\Q$res\E[:space:]]+) }x;
84 }
85
86 for (my $idx = 0; defined (my $res = $self->x_resource ("selection.pattern-$idx")); $idx++) {
87 $res = $self->locale_decode ($res);
88 push @{ $self->{patterns} }, qr/$res/;
89 }
90
91 $self->{enabled} = 1;
92
93 push @{ $self->{term}{option_popup_hook} }, sub {
94 ("new selection" => $self->{enabled}, sub { $self->{enabled} = shift })
95 };
96
97 ()
98 }
99
100 # "find interesting things"-patterns
101 my @mark_patterns = (
102 # qr{ ([[:word:]]+) }x,
103 qr{ ([^[:space:]]+) }x,
104
105 # common types of "parentheses"
106 qr{ (?<![^[:space:]]) [`'] ([^`']+) [`'] (?![^[:space:]]) }x,
107 qr{ (?<![^[:space:]]) ‘ ([^‘’]+) ’ (?![^[:space:]]) }x,
108 qr{ (?<![^[:space:]]) “ ([^“”]+) ” (?![^[:space:]]) }x,
109
110 qr{ (?<![^[:space:]]) (' [^[:space:]] [^']* ') }x,
111 qr{ (' [^']* [^[:space:]] ') (?![^[:space:]]) }x,
112 qr{ (?<![^[:space:]]) (` [^[:space:]] [^']* ') }x,
113 qr{ (` [^']* [^[:space:]] ') (?![^[:space:]]) }x,
114 qr{ (?<![^[:space:]]) (" [^[:space:]] [^"]* ") }x,
115 qr{ (" [^"]* [^[:space:]] ") (?![^[:space:]]) }x,
116
117 qr{ \{ ([^\{\}]+) \} }x,
118 qr{ \( ([^\(\)]+) \) }x,
119 qr{ \[ ([^\[\]]+) \] }x,
120 qr{ \< ([^\<\>]+) \> }x,
121
122 # urls, just a heuristic
123 qr{(
124 (?:https?://|ftp://|news://|mailto:|file://|\bwww\.)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+
125 [ab-zA-Z0-9\-\@;\/?:&=%\$_+*()~] # exclude some trailing characters (heuristic)
126 )}x,
127
128 # shell-like argument quoting, basically always matches
129 qr{\G [\ \t|&;<>()]* (
130 (?:
131 [^\\"'\ \t|&;<>()]+
132 | \\.
133 | " (?: [^\\"]+ | \\. )* "
134 | ' [^']* '
135 )+
136 )}x,
137 );
138
139 # "correct obvious? crap"-patterns
140 my @simplify_patterns = (
141 qr{^"([^\\"'\ \t|&;<>()*?]+)"$}, # "simple" => simple
142 qr{^(.*)[,\-]$}, # strip off trailing , and -
143 );
144
145 sub on_sel_extend {
146 my ($self, $time) = @_;
147
148 $self->{enabled}
149 or return;
150
151 my ($row, $col) = $self->selection_mark;
152 my $line = $self->line ($row);
153 my $text = $line->t;
154 my $markofs = $line->offset_of ($row, $col);
155 my $curlen = $line->offset_of ($self->selection_end)
156 - $line->offset_of ($self->selection_beg);
157
158 my @matches;
159
160 if ($markofs < $line->l) {
161 study $text; # _really_ helps, too :)
162
163 for my $regex (@mark_patterns, @{ $self->{patterns} }) {
164 while ($text =~ /$regex/g) {
165 if ($-[1] <= $markofs and $markofs <= $+[1]) {
166 my $ofs = $-[1];
167 my $match = $1;
168
169 for my $regex (@simplify_patterns) {
170 if ($match =~ $regex) {
171 $match = $1;
172 $ofs += $-[1];
173 }
174 }
175
176 push @matches, [$ofs, length $match];
177 }
178 }
179 }
180 }
181
182 # whole line
183 push @matches, [0, ($line->end - $line->beg + 1) * $self->ncol];
184
185 for (sort { $a->[1] <=> $b->[1] or $b->[0] <=> $a->[0] } @matches) {
186 my ($ofs, $len) = @$_;
187
188 next if $len <= $curlen;
189
190 $self->selection_beg ($line->coord_of ($ofs));
191 $self->selection_end ($line->coord_of ($ofs + $len));
192 return 1;
193 }
194
195 ()
196 }