4 A Programmer's Text Editor
8 Copyright (C) 1991-2011 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['move_left'] = sub (d) { mp.move(d, mp.move_left); };
31 mp.actions['move_right'] = sub (d) { mp.move(d, mp.move_right); };
32 mp.actions['move_up'] = sub (d) { mp.move(d, mp.move_up); };
33 mp.actions['move_down'] = sub (d) { mp.move(d, mp.move_down); };
34 mp.actions['move_pgup'] = sub (d) { mp.move(d, mp.move_pgup); };
35 mp.actions['move_pgdn'] = sub (d) { mp.move(d, mp.move_pgdn); };
36 mp.actions['move_bol'] = sub (d) {
37 if (mp.config.smart_bol)
38 mp.move(d, mp.move_bol_smart);
40 mp.move(d, mp.move_bol);
42 mp.actions['move_eol'] = sub (d) { mp.move(d, mp.move_eol); };
43 mp.actions['move_bof'] = sub (d) { mp.move(d, mp.move_bof); };
44 mp.actions['move_eof'] = sub (d) { mp.move(d, mp.move_eof); };
45 mp.actions['move_word_left'] = sub (d) { mp.move(d, mp.move_word_left); };
46 mp.actions['move_word_right'] = sub (d) { mp.move(d, mp.move_word_right); };
48 mp.actions['goto'] = sub (d, line) {
53 'label' => L("Line to go to:"),
60 if (t != NULL && t[0] >= 1)
66 mp.set_y(d, line - 1);
72 mp.actions['move_to_mouse_position'] = sub (d) {
73 /* move the cursor there */
74 mp.move_to_coords_xy(d, mp.mouse_x, mp.mouse_y);
76 /* mouse click always unmarks */
82 mp.actions['move_mouse_wheel_up'] = sub (d) {
91 mp.actions['move_mouse_wheel_down'] = sub (d) {
100 mp.actions['document_list'] = sub (d) {
104 'label' => L("Document list"),
106 'list' => mp.get_doc_names(60),
107 'value' => mp.active_i
120 /** default key bindings **/
122 mp.keycodes['cursor-left'] = "move_left";
123 mp.keycodes['cursor-right'] = "move_right";
124 mp.keycodes['cursor-up'] = "move_up";
125 mp.keycodes['cursor-down'] = "move_down";
126 mp.keycodes['page-up'] = "move_pgup";
127 mp.keycodes['page-down'] = "move_pgdn";
128 mp.keycodes['home'] = "move_bol";
129 mp.keycodes['end'] = "move_eol";
130 mp.keycodes['ctrl-home'] = "move_bof";
131 mp.keycodes['ctrl-end'] = "move_eof";
132 mp.keycodes['ctrl-cursor-left'] = "move_word_left";
133 mp.keycodes['ctrl-cursor-right'] = "move_word_right";
134 mp.keycodes['alt-home'] = "move_bof";
135 mp.keycodes['alt-end'] = "move_eof";
136 mp.keycodes['ctrl-g'] = "goto";
137 mp.keycodes['mouse-left-button'] = "move_to_mouse_position";
138 mp.keycodes['mouse-right-button'] = "move_to_mouse_position";
139 mp.keycodes['mouse-middle-button'] = "move_to_mouse_position";
140 mp.keycodes['mouse-wheel-up'] = "move_mouse_wheel_up";
141 mp.keycodes['mouse-wheel-down'] = "move_mouse_wheel_down";
143 /** action descriptions **/
145 mp.actdesc['move_left'] = LL("Character left");
146 mp.actdesc['move_right'] = LL("Character right");
147 mp.actdesc['move_up'] = LL("Line up");
148 mp.actdesc['move_down'] = LL("Line down");
149 mp.actdesc['move_pgup'] = LL("Page up");
150 mp.actdesc['move_pgdn'] = LL("Page down");
151 mp.actdesc['move_bol'] = LL("Beginning of line");
152 mp.actdesc['move_eol'] = LL("End of line");
153 mp.actdesc['move_bof'] = LL("Beginning of document");
154 mp.actdesc['move_eof'] = LL("End of document");
155 mp.actdesc['move_word_left'] = LL("Word left");
156 mp.actdesc['move_word_right'] = LL("Word right");
157 mp.actdesc['goto'] = LL("Go to line...");
158 mp.actdesc['move_to_mouse_position'] = LL("Move cursor to mouse click");
159 mp.actdesc['move_mouse_wheel_down'] = LL("Mouse wheel up");
160 mp.actdesc['move_mouse_wheel_up'] = LL("Mouse wheel down");
161 mp.actdesc['document_list'] = LL("Document list");
165 sub mp.move(doc, func)
166 /* wrapper for movement functions, with possible shift selection */
169 if (mp.shift_pressed) {
170 /* shift pressed? move selecting */
171 if (doc.txt.mark == NULL)
185 sub mp.split_by_words(s, r)
186 /* splits a string by words */
188 /* if no special-purpose regex set, take global one */
192 return regex(s, r ~ 'g');
196 sub mp.split_line_by_words(doc, r)
197 /* splits current line by words and returns a three element array containing
198 the list of words, the list of offsets and the current position */
200 local txt, l, w, c, ol, oc, p;
203 l = txt.lines[txt.y];
208 /* if no special-purpose regex set, take global one */
212 while ((w = regex(l, r, c[0] + c[1])) != NULL) {
216 /* get coordinates */
219 /* push the starting column */
222 /* if matching coords are between the cursor, store it */
223 if (c[0] <= txt.x && c[0] + c[1] >= txt.x)
227 /* it txt.x is still further than the last match, it means
228 that the 'current' position is beyond the last word */
229 if (txt.x > c[0] + c[1])
232 /* return the list of words, the list of
233 coordinates and the current one */
234 return [ ol, oc, p ];
238 sub mp.get_word(doc, r)
239 /* returns the word under the cursor */
241 local l = mp.split_line_by_words(doc, r);
243 /* no word over cursor? */
251 sub mp.get_range(doc, bx, by, ex, ey, v)
252 /* gets a range or characters from a document */
261 /* block is just one line; take the inside
262 part and push it onto the clipboard */
264 w = splice(txt.lines[by], NULL, bx, ex - bx);
271 /* block has more than one line */
275 /* use normal selection block */
277 /* take from the beginning to the end of the first line */
278 w = splice(txt.lines[n], NULL, bx, -1);
283 /* take the central lines */
285 push(r, txt.lines[n++]);
287 /* take the last line */
288 w = splice(txt.lines[n], NULL, 0, ex);
292 /* use vertical selection block */
294 w = splice(txt.lines[n++], NULL, bx, ex - bx + 1);
296 local p = ex - bx - size(l);
298 /* pad out to end of block line */
312 /* sets the x position */
317 /* cursor moved left of the bol; effective cursor up + eol */
322 /* set x to the end of the line */
323 txt.x = size(txt.lines[txt.y]);
327 /* test if moved beyond end of line */
328 if (x > size(txt.lines[txt.y])) {
329 if (txt.y < size(txt.lines) - 1) {
330 /* cursor moved right of eol;
331 effective cursor down + bol */
345 /* sets the y position */
350 /* get current visual x position */
351 vx = mp.x2vx(txt.lines[txt.y], txt.x);
356 if (y >= size(txt.lines))
357 y = size(txt.lines) - 1;
362 /* adjust new x to match previously one */
363 txt.x = mp.vx2x(txt.lines[txt.y], vx);
370 /* moves one line up */
372 mp.set_y(doc, doc.txt.y - 1);
376 sub mp.move_down(doc)
377 /* moves one line down */
379 mp.set_y(doc, doc.txt.y + 1);
383 sub mp.move_pgup(doc)
384 /* moves one page up */
386 mp.set_y(doc, doc.txt.y - mp.window.ty);
390 sub mp.move_pgdn(doc)
391 /* moves one page down */
393 mp.set_y(doc, doc.txt.y + mp.window.ty);
397 sub mp.move_left(doc)
398 /* moves one char left */
400 if (doc.txt.x + doc.txt.y)
401 mp.set_x(doc, doc.txt.x - 1);
407 sub mp.move_right(doc)
408 /* moves one char right */
410 mp.set_x(doc, doc.txt.x + 1);
415 /* moves to the beginning of the line */
421 sub mp.move_bol_smart(doc)
422 /* moves to the first non-whitespace or if already there the beginning of the line */
425 local l = split(doc.txt.lines[doc.txt.y]);
427 while (non_white < size(l) &&
429 cmp(l[non_white], " ") == 0 ||
430 cmp(l[non_white], "\t") == 0)
436 if (doc.txt.x == non_white) {
439 doc.txt.x = non_white;
444 /* moves to the end of the line */
446 doc.txt.x = size(doc.txt.lines[doc.txt.y]);
452 /* moves to the beginning of the file */
461 /* moves to the end of the file */
463 doc.txt.y = size(doc.txt.lines) - 1;
468 sub mp.move_word_left(doc)
469 /* moves a word to the left */
475 local l = mp.split_line_by_words(doc);
477 /* get current word */
481 /* if it's not at the beginning of a word,
483 if (i < size(l[1]) && txt.x != l[1][i]) {
488 /* go to previous word */
491 /* if that position exists, move there */
498 /* no lines up? exit */
503 txt.x = size(txt.lines[txt.y]);
510 sub mp.move_word_right(doc)
511 /* moves a word to the right */
515 while (txt.y < size(txt.lines) - 1) {
517 local l = mp.split_line_by_words(doc);
519 /* get next position */
522 /* if that position exists, move there */
523 if (i < size(l[1])) {
537 sub mp.move_to_coords_xy(doc, x, y)
538 /* move the cursor to the character on the visual coords x and y */
541 mp.set_y(doc, doc.txt.vy + y);
543 /* calculate the real position in that line
544 where the mouse click seem to be */
545 x = mp.vx2x(doc.txt.lines[doc.txt.y], doc.txt.vx + x);