1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
|
Xedit is a simple text editor for X.
Please check xedit(1) for information about resources and configurable
options.
The authors file should list the original authors of all files, but
unfortunately most collaborators and people that changed portions of the
code is not listed.
List of default keyboard commands.
Uppercase letters means both, uppercase and lowercase.
Lowercase letter usually means Shift key is not pressed.
C- Means Control key.
M- Means Meta key.
Usually Alt key has the same effect.
S- Means Shift key.
C-A Move cursor to beginning of line.
C-B or Left
Move cursor backwards one character.
C-C Insert CUT_BUFFER0 selection at cursor position.
C-D Delete next character.
C-E Move cursor to end of line.
C-F or Right
Move cursor forwards one character.
C-G Keyboard reset.
Use it to switch direction in the Undo stack, i.e. switch between
Undo and Redo.
It can also be used to stop the lisp interpreter if it is executing
code.
C-H Deletes character before cursor.
C-J Adds a newline and indent.
If the current buffer is the *scratch* buffer, it will work
like C-X,C-E, but print the lisp output directly to the scratch
buffer. Examples:
(list 1 2 3) C-J will print (1 2 3) and move the cursor to
the next line.
C-K Deletes text from cursor position to end of line.
C-L Redraw text window.
C-M Adds a newline.
C-N or Down
Move cursor to next line.
C-O Adds one newline at cursor position without moving cursor.
C-P or Up
Move cursor to previous line.
C-R Opens search dialog, searching backwards.
C-S Opens search dialog, searching forwards.
C-T Transpose characters.
C-U Starts multiply mode.
Multiply mode means that most keyboard commands will be repeated
by its parameter. After pressing C-U type a number, that can be
negative. Examples:
C-U 10 C-F will move the cursor 10 characters forwards
C-U -10 C-F will move the cursor 10 characters backwards
If no number is specified, or if the number zero is specified,
the default value is 4.
C-V or PageDown
Move cursor to next page.
C-W Kills current selection.
C-W is also useful when there is no active selection, to return to
the previous position the left mouse was clicked in the text window.
C-Y Inserts SECONDARY selection.
This usually means text delete with commands other than by just
pressing Backspace or Delete (that can be multiplied)
C-Z Scroll one line up.
M-B or C-Left
Move cursor backwards one word.
C-Left only moves over alphabetic or numeric characters
M-C Capitalize word under cursor position, or next word.
M-F or C-Right
Move cursor forwards one word.
C-Right only moves over alphabetic or numeric characters.
M-I Opens a dialog prompting for a file name to be inserted at the
cursor position.
(This isn't very user friendly, this is a cavemen interface, you will
love it, you will never use it).
M-K Kills text from cursor position to end of paragraph.
M-L Downcase word at cursor position or next word.
M-Q Format paragraph.
Xedit interfaces Xaw code that allows several types of text
formatting. To use it, you need to Select "Auto Fill" in the
"Edit Menu" and select values for "Break Columns". After that,
Select "Edit Menu"->"Justification" for the available options.
Text typed will usually be automatically corrected, but if you
need to change text in the middle of a previous line, use M-Q
to reformat, and C-_ to undo if required.
Examples of text:
This text with align
left and break
columns at 20 and
40.
This text with align
right and break
columns at 25 and
45. Remember that
Auto Fill must be
selected. And it may
be required to press
M-Q when going back
to edit previous
lines.
This text with align center
and break columns at 40 and
70. A good tip is to make sure
there are empty lines before
and after the aligned text, so
that M-Q will not format more
text than it should.
This text with full align,
note that it will spread the
words to fully fill the
configured break columns, in
this case 15 and 45. Also note
that it doesn't remove any
extra indentation from the
first line. This may be
considered a bug or feature,
but it doesn't respect 2
spaces after an '.' dot. And
it doesn't align the last line
of text.
This text with Auto Fill disabled. When Auto Fill is disabled, tabs are
usually preserved, like this, and this. But it
will basically format the text to not be larger than the text widget screen
width and. But it the screen is scrolled horizontally, it will not work as
expected, the advantage over the above interface is that is considers font
characters width, while the other interface assumes fixed width characters.
Notice that "auto formatting" with Auto Fill mode is done when
pressing enter, but information isn't saved per paragraph, so
if values of align or break columns are changed, trying to edit
a text block with different configuration will not give the expected
results.
Also notice that lines starting with non printable characters aren't
automatically formatted. This is helpful for some editing modes
where symbols can be used before lines in a paragraph. If you don't
need this feature, usually pressing Space or Tab is enough to put the
cursor at the proper position.
M-U Upcase word at cursor position or next word.
M-V or PageUp
Move cursor to previous page.
M-Y Kill ring yank feature. Basically it will circulate over all
text that has been cut in the current session. Keep pressing it
until happy :-)
M-Z Scrolls one line down.
M-D Kill word at cursor position or next word.
S-M-D Delete word at cursor position or next word.
Does not go to the kill ring.
M-H or M-Delete or M-Backspace.
Kill word at cursor position or previous word.
S-M-H or S-M-Delete or S-M-Backspace
Delete word at cursor position or previous word.
Does not go to the kill ring.
M-. Find definition/declaration of symbol string of selected text, and/or
finds next tag when more than one definition exists for the symbol.
M-< or Home
Move cursor to beginning of file.
M-> or End
Move cursor to end of file.
M-] or C-Down
Move cursor to next paragraph.
M-[ or C-Up
Move cursor to previous paragraph.
C-_ or C-X,U
Undo.
If enabled in the given textwidget. Not enabled by default in the
message window and filename window, or any of the other text widgets
in the several available dialogs.
C-\ or C-Kanji
Reconnect Input Method.
In international mode (probably broken interface).
S-Insert
Insert PRIMARY selection from CUT_BUFFER0.
C-Q
Followed by any character, will insert the next typed character
useful to insert control characters. For example C-Q,C-L will
insert ^L at the cursor position.
LeftMouseButton
When pressed marks the start of a PRIMARY selection at CUTBUFFER0
When moved while pressed extends the selection.
MiddleMouseButton
When pressed, inserts the PRIMARY selection at CUTBUFFER0 at
the cursor position.
RightMouseButton
Can be used to adjust a selection done with LeftMouseButton.
C-A,Tab
If the loaded file has a indentation rules file, C or Lisp, xedit
will reindent the line. Also, entering a fresh character on a
newline should be enough to move the cursor to the proper position.
To override it, you may need to use the C-U to multiply the action,
as it will only indent if only one character was added.
C-X,C-C or (Pressing the Quit button)
Exits xedit.
If there are unsaved files, a message will be printed asking to
"exit" again, or save the files.
C-X,C-E
Execute lisp expression before the cursor position.
C-X,C-F
Changes keyboard input focus to the filename text input window.
In this mode, pressing Tab will try to complete the filename
being typed.
When more than one match exists, pressing Tab again will display
the directory navigation window.
The initial search path usually is the basename of the file loaded
in the current textwindow, or currently directory from where
xedit was started if the *scratch* is the current "buffer".
The character ~ can be used as a shortcut for the home directory
and ~username will be replaced by the home directory of "username"
if it exists.
C-X,C-S or (Pressing the Save button)
Saves the file in the current text window.
C-X,Tab
Indents the current paragraph.
Use the C-U modifier to specify the number of spaces to insert
or remove if the C-U parameter is negative.
C-X,0
Deletes the current window.
The file being edited is not unloaded.
C-X,1
Deletes the other window.
The file being edited is not unloaded.
C-X,2
Splits vertically the current window.
C-X,3
Splits vertically the current window.
C-X,b
Switch the contents of the current window to the next file in
the list of loaded files.
C-X,d
Displays the directory listing window.
In this window, it is possible to navigate in the file system
to choose a file to edit.
Usually, this is the same as pressing C-X,C-F,Tab
See C-X,C-F for more information.
C-X,k
Unloads the file being edited.
If the file has not been saved, a message will be displayed,
asking to either press C-X,k again, or save the file
The *scratch* buffer cannot be killed and will always
prints a warning when exiting xedit. This is the expected behavior.
C-X,o
Switch input focus to the other window, making it the current one
If the editor doesn't have splited windows, this command is ignored.
Insert
Switches between insert and overwrite mode.
In overwrite mode text is typed over existing file contents,
only extending the file contents when typing at the end of
a line (or file).
Escape
Enters the line edit mode.
In this mode it is possible to use regex expressions to search and
replace the contents of the file loaded in the current text window.
Refer to the xedit(1) manpage for more information of the regex
expression format.
Note that the regex used by xedit isn't IEEE Std 1003.2 compliant,
and not compliant with most regex implementations in that it doesn't
support some complex search patterns, usually involving patterns
like ((.*)+)? that may require too much restarts or have several
correct interpretations for multiple matches. Also, it always does
minimal matching, and it is not configurable like in pcre, example:
searching "a1a1a1" with the pattern "(.*)\d" will find "a1" and
not "a1a1a1" as could be expected.
Please refer to lisp/re/README for more information on the supported
regex expressions.
C-LeftMouseButton
Displays the "File Menu" from where it is possible to select a
new file to be edited in the current window.
C-MiddleMouseButton
Displays the "Edit Menu" that usually has the following options:
+------------------+-------------+
| Wrapping -> | Never |
| | Line |
| | Word |
| Auto Fill +-------------+
| +-------------+
| Justification -> | Left |
| | Right |
| | Center |
| | Full |
| +-------------+
| Break Columns... |
| +-------------+
| Scrollbars -> | Vertical |
| | Horizontal |
| +-------------+
| +-------------+
| Edit Mode -> | Plain/None |
| | C/C++ |
| | Lisp/Scheme |
| | X imake |
| | Makefile |
| | Unix shell |
| | SGML |
| | HTML |
| | Man page |
| | X resource |
| | XF86Config |
| | RPM spec |
| | XFree86 log |
| | Patch file |
+------------------+-------------+
"Wrapping" is disabled if "Auto Fill" is enabled.
"Justification" and "Break Columns..." are enabled if "Auto Fill"
is also enabled.
"Edit Mode" lists the available syntax highlight and indentation
rules defined.
Note that most of these options don't work in "international" mode.
Several xedit interfaces works only with 8 bits encodings, and
doesn't properly handle UTF-8.
C-RightMouseButton
Displays the "Option Menu".
Currently the only option is an Ispell frontend.
FourthMouseButton (usually also moving up the mouse wheel)
Scroll one line down
FifthMouseButton (usually also moving down the mouse wheel)
Scroll one line up
There is also some documentation in lisp/README, lisp/TODO,
lisp/re/README, lisp/re/tests.txt, and comments/justifications/wishlists for
the cases the interpreter fail to give the proper result for a given test.
The lisp interpreter implements most of a standard COMMON LISP
environment, but the compiler generates only byte code and not everything
can be compiled, in those cases the interpreter does the work. Examples are
constructs involving UNWIND-PROTECT or any kind of jump outside of the
current function body.
For more information please consult any COMMON LISP documentation or
tutorial.
Simple tutorial on writing a "foolang" syntax highlight mode for xedit.
Create a file called foolang.lsp
Add:
--
(require "syntax")
(require "indent")
(in-package "XEDIT")
--
to foolang.lsp
Check the available files if you want a custom property, or to know about
the available ones. One example is:
--
(defsynprop *prop-foolang*
"foolang"
:font "fixed"
:foreground "rgb:a/b/c"
:background "rgb:1/2/3"
:underline t
:overstrike t)
--
Check lisp/modules/xedit.lsp for the other options, like subscript,
superscript and/or combining XLFD properties.
Create a syntax definition for foolang. Check the definition of defsyntax in
lisp/modules/syntax.lsp for more details. One example for foolang is:
--
(defsyntax *foolang-mode* :foolang nil nil nil
;; use the sample property created for foolang whenever the string
;; foolang is found at the toplevel
(syntoken "\\<foolang\\>" :property *prop-foolang*)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; process C style comments
(syntoken "/*" :nospec t :begin :comment :contained t)
;; contained is an option to not "export" this definition to child
;; tables
(syntable :comment *prop-comment* #'default-indent
;; #'default-indent means a very simple indent that follows indentation
;; of previous line. Use nil for no indentation
;; Don't start a new table, instead flag as an error if nested
(syntoken "/*" :nospec t :property *prop-error*)
;; :nospec t sets the RE_NOSPEC flag for the regex, i.e. searches
;; a literal string, and * will not be a special character
(syntoken "XXX|TODO|FIXME" :property *prop-annotation*)
;; just to make it easier to flag some important comment
(syntoken "*/" :nospec t :switch -1)
;; The :switch argument is the number of tables to "pop", in
;; this case, we are at table :comment, and :switch -1 returns
;; to table :foolang, that is the "root" table
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Process lisp comments that can nest
(syntable :lisp-comment *prop-comment* nil
;; Start a comment, possibly nested
(syntoken "#|" :nospec t :begin :lisp-comment)
;; Returns to previous comment in stack or to main :foolang table
(syntoken "|#" :nospec t :switch -1)
;; For easier flagging important comments
(syntoken "XXX|FIXME|TODO" :property *prop-annotation*)
)
;; This is usually in the end of the list, but can be anywhere,
;; just that if it isn't at the end, conflicting rules are resolved
;; by declaration order
(synaugment :lisp-comment)
;; Adds the :lisp-comment table to :foolang table
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Lisp like strings that don't need a \ at the end of the line
(syntable :lisp-string *prop-string* nil
;; ignore a escaped " in the middle of the string
(syntoken "\\\\.")
;; Note that no options are used, just keep using the current
;; property. Unfortunately, backslashes must be escaped twice.
;; Once for the lisp reader and once for the regex compiler.
(syntoken "\"" :nospec: t :switch -1)
;; :nospec is used just to create a faster regex. switch -1
;; returns to the previous syntax table. It isn't an error to
;; try to go down the "root" table, but if that happens, it
;; probably means either wrong syntax definition of malformed input.
)
(synaugment :lisp-string)
;; Adds the :lisp-string table to :foolang table
;; Note that since there isn't a rule to start a string in the
;; :lisp-string table, it cannot nest, maybe because the ending
;; character is the starting character ? :-))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; C style string rules
(syntable :string *prop-string* nil
;; Ignore escaped characters
(syntoken "\\\\.")
;; Match, most, printf arguments.
(syntoken "%%|%([+-]?\\d+)?(l?[deEfgiouxX]|[cdeEfgiopsuxX])"
:property *prop-format*)
;; Just for fun. This makes easier to see printf formats in strings
;; *prop-format* is *prop-string* with the :underline option
(syntoken "\\\\$")
;; a backslash extends the string to the next line
;; A nonscaped " inside a string finishes it, since this table doesn't
;; have sub tables, and cannot nest, should return to :foolang table
;; from here
(syntoken "\"" :nospec t :switch -1)
;; This token rule starts a new table called :error because end of line
;; has been matched. Note that it is defined last, so that a line
;; ending with " or \ will be processed first.
(syntoken ".?$" :begin :error)
(synaugment :string)
;; Adds the :string table to :foolang table
;; This table is used by :string, but could be shared for other patterns
;; like characters constants, etc.
;; It uses :switch -2 because it is started inside the :string table,
;; but it is also a table, so, pops two tables from the table stack
(syntable :error *prop-error* nil
(syntoken "^.*$" :switch -2)
)
)
--
Indentation rules are significantly more complex. I suggest looking at
lisp/modules/indent.lsp for the macros and function definitions;
and lisp/modules/progmodes/lisp.lsp and lisp/modules/progmodes/c.lsp for two
sample implementations of indentation for Lisp/Scheme and C/C++
respectively.
Note also that indentation is parsed backwards, what can cause some
confusion, and make "visualization" of order or precedence of evaluation for
rules harder to understand.
A simple indentation rules definition for foolang could be:
--
(defindent *foolang-mode-indent* :foolang
;; This must be the first token and usually the only token matching
;; BOL (Beginning of Line)
(indtoken "^\\s*" :indent
:code (or *offset* (setq *offset* (+ *ind-offset* *ind-length*))))
;; the keyword :indent is a pattern put on a list when there is
;; a match, so that later patterns can be "reduced" by some other
;; rule, i.e.: (:indent :indent) could be reduced to (:indent)
(indtoken "//.*$" nil)
;; C++ style comment. Returning nil instead of a token basically
;; ignores the token, as it should not enter the reduction pattern
;; list
;; Sample C comment pattern
(indtoken "*/" :ccomment :nospec t :begin :comment)
;; Note that the indaugment macro doesn't need to be used, and actually
;; would be an error. In this example, the indentation compiler checks
;; the :begin :comment and handles it internally, as it already needs
;; to check for things like typos, unreachable labels, detectable
;; non resolving rules, etc. There is runtime check also, so it should
;; never enter an infinite loop when trying to resolve reduction rules.
;; Check lisp/modules/indent.lsp:(compile-indent-table) for the
;; implementation and more comments.
;; Indentation rules also have stacked tables
(indtable :comment
(indtoken "/*" :ocomment :nospec t :switch -1))
;; Note that the name is :ocomment (open comment), but that the
;; the table is finished when matching the open comment pattern
;; A simple initialization of a variable used by the indentation rules
(indinit (parens 0))
;; This variable can be declared anywhere in the body of defindent,
;; It will be properly moved to a "variables declaration section"
;; when expanding and compiling the table.
(indtoken "(" :oparen :nospec t :code (incf parens))
(indtoken ")" :cparen :nospec t :code (decf parens))
;; These two tokes add the patterns :oparen and :cparen to the
;; "pattern list", and also have code to remember the balancing
;; of parenthesis.
;; One of the simplest reduction rules :-)
(indreduce nil
t
((:comment)))
;; Once the boundings of a comment are found, just ignore it, like
;; what was done with the // pattern, but in that case, the boundings
;; were readily available.
;; The t (True) parameter means that this rule is always evaluated,
;; but conditional code may be used, and implicit code may be added
;; to the end of the indreduce macro.
;; Since it is a macro, code can be compiled to optimized bytecode
;; after the macro is expanded.
(indinit (indent 0))
;; Note that there is a special *indent* variable that should hold the
;; proper indentation value, but it may be required to "overwrite"
;; without forgetting that value, for things like:
;;
;; foo(bar(baz(blah
;; ^ ^
;; | |
;; indent |
;; effective indentation to be used
;;
;; where it is desirable to align the code in the next line with the
;; last open parenthesis.
Since the interface is, unfortunately, complex enough to not expect
casual users to have something like a $HOME/.xedit file, if you want to add
new modes, please check lisp/modules/xedit.lsp:*auto-modes*
There is some documentation about the variable. It should be possible to
change/update the variable from the lisp interface in the *scratch* buffer,
but for safety, it is suggested that if you add new rules, you should
restart xedit after it. Also note that there is compiled code in
lisp/xedit.c that expects that variable to follow an specific format.
You may notice that several .lsp files aren't "properly indented"; this
is because the lisp indentation rules file was made long after most of the
other files were done, and it was considered a bad practice to gratuitously
reindent all files.
At the time of this writing, the ispell interface should be again
functional, but it may be required to use some old ispell program to handle
non utf8 text. But it should work properly for the english language, and in
international mode, should work with any language. But there are problems in
international mode not fixed.
I (Paulo Cesar) considered several times to extend the normal
textwidget to handle utf8, but this is probably a lot of work/time badly
spent and I prefer to work on other personal projects, but still xedit is
the editor I use for programming. The XPRINT support unfortunately is broken
due to it. Note that xedit, like pretty much any other Xaw application can
be linked against Xaw with XPRINT support. In the case of xedit, a flag
could be used, like the "international" variable to, at runtime, disable all
the related code, if required.
Also at the time of this writing, the tags interface was added, as well
as several other bug fixes. The tags interface is documented in the manpage,
but the action shortcut may not be clear. The default shortcut is M-. .
There is no support for more than one tags file, or changing the tags file
at runtime. But the code should be easy to adapt for this case, as all
related functions receive pointers to the appropriate structures. One option
could be to descend from the directory of the loaded file searching for a
tags file, and then associate the file with the tags definition, if it isn't
already loaded. Shouldn't be hard to implement. For "inter project" files,
it should be better to have one xedit window per "project", i.e. searching
the definition of something like a libc symbol should probably be done in
another xedit window.
|