The repeated word configuration interface is accepted as working (Closes: #1274).
[mp-5.x.git] / mp_writing.mpsl
blob12f7d609b0cda48472841f983915803baeae2b9d
1 /*
3     Minimum Profit 5.x
4     A Programmer's Text Editor
6     Tools for writing.
8     Copyright (C) 1991-2009 Angel Ortega <angel@triptico.com>
10     This program is free software; you can redistribute it and/or
11     modify it under the terms of the GNU General Public License
12     as published by the Free Software Foundation; either version 2
13     of the License, or (at your option) any later version.
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24     http://www.triptico.com
28 /** editor actions **/
30 mp.actions['word_count'] = sub (d) {
32         mp.busy(1);
33         local c = mp.word_count(d);
34         mp.busy(0);
36         mp.alert(sprintf(L("Lines: %d Words: %d"),
37                 size(mp.get_active_area(d)), c));
41 mp.actions['repeated_words_options'] = sub (d) {
42         local r = mp.form( [
43                 { 'label'       => L("Number of letters at the start or end:"),
44                   'type'        => 'text',
45                   'value'       => mp.config.rw_num_chars,
46                   'history'     => 'num_char' },
47                 { 'label'       => L("Maximum distance between words:"),
48                   'type'        => 'text',
49                   'value'       => mp.config.rw_max_dist,
50                   'history'     => 'max_dist' }
51                 ]);
53         if (r != NULL) {
54                 mp.config.rw_num_chars = r[0];
55                 mp.config.rw_max_dist = r[1];
56         }
60 mp.actions['seek_repeated_word'] = sub (d) {
62         mp.busy(1);
63         local c = mp.repeated_words(d, mp.config.rw_num_chars, mp.config.rw_max_dist);
64         mp.busy(0);
66         if (!c)
67                 mp.alert(L("Text not found."));
70 /** default key bindings **/
72 mp.keycodes['f6']               = 'seek_repeated_word';
74 /** action descriptions **/
76 mp.actdesc['word_count']                = LL("Count words");
77 mp.actdesc['repeated_words_options']    = LL("Repeated words options...");
78 mp.actdesc['seek_repeated_word']        = LL("Search repeated word");
80 /** data **/
82 mp.config.rw_num_chars  = 4;
83 mp.config.rw_max_dist   = 40;
85 /** code **/
87 sub mp.word_count(doc)
88 /* counts the number of words in doc */
90         local w = 0;
92         foreach (l, mp.get_active_area(doc))
93                 w += size(mp.split_by_words(l));
95         return w;
99 /**
100  * mp.repeated_words - Finds words starting or ending the same in a range.
101  * @doc: the document
102  * @num_chars: minimum length for the word to be tested
103  * @max_dist: maximum distance the word must have
105  * Finds words starting or ending the same to a maximum of @num_chars
106  * and that are less than @max_dist words apart. If a pair of these words
107  * is found, 1 is returned, the cursor positioned over the first one
108  * and both highlighted as spelling errors. Otherwise, 0 is returned
109  * and nothing is done.
110  */
111 sub mp.repeated_words(doc, num_chars, max_dist)
113         local q = [];
114         local x = doc.txt.x;
115         local y = doc.txt.y;
116         local l;
118         /* build regexes */
119         local s_rx = sprintf('/^.{1,%d}/i', num_chars);
120         local e_rx = sprintf('/.{1,%d}$/i', num_chars);
122         /* if there were previous repeated words, no longer
123            consider them as 'typos' */
124         if (mp.last_repeated_words) {
125                 hdel(mp.word_color, mp.last_repeated_words[0]);
126                 hdel(mp.word_color, mp.last_repeated_words[1]);
127         }
129         while ((l = doc.txt.lines[y]) != NULL && !ret) {
131                 local w;
133                 while ((w = regex(mp.word_regex, l, x)) != NULL) {
135                         /* get matching position */
136                         local c = regex();
138                         /* does the word measure at lest num_chars? */
139                         if (size(w) >= num_chars) {
140                                 /* enqueue this word, and dequeue another */
141                                 local w1 = queue(q, [
142                                                 w,
143                                                 c[0] + size(w),
144                                                 y,
145                                                 lc(regex(s_rx, w)),
146                                                 lc(regex(e_rx, w))
147                                         ], max_dist);
149                                 /* a word has been dequeued? */
150                                 if (w1 != NULL) {
151                                         /* seek each word in the queue */
152                                         foreach (w2, q) {
153                                                 /* does the word and any other in
154                                                    the queue match the regexes? */
155                                                 if ((w1[3] eq w2[3]) || (w1[4] eq w2[4])) {
157                                                         /* add both to the word color hash */
158                                                         mp.word_color[w1[0]] =
159                                                         mp.word_color[w2[0]] =
160                                                                 mp.colors.spell.attr;
162                                                         /* store for later removal */
163                                                         mp.last_repeated_words =
164                                                                 [ w1[0], w2[0] ];
166                                                         /* move cursor there */
167                                                         mp.set_y(doc, w1[2]);
168                                                         mp.set_x(doc, w1[1]);
170                                                         /* set the first visible line */
171                                                         doc.txt.vy = doc.txt.y;
173                                                         /* trigger a redraw */
174                                                         mp.redraw();
176                                                         return 1;
177                                                 }
178                                         }
179                                 }
180                         }
182                         /* move offset to next word */
183                         x = c[0] + c[1];
184                 }
186                 y++;
187                 x = 0;
188         }
190         return 0;