Compare commits
296 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6b5c13281 | |||
|
|
ef35ea72cf | ||
|
|
8804b6dcd4 | ||
|
|
86b8388889 | ||
|
|
812c48dde4 | ||
|
|
f0f1c94afa | ||
|
|
75b312ded1 | ||
|
|
e65b0ba654 | ||
|
|
d3dd403dc7 | ||
|
|
7f4c2c6a25 | ||
| 4fefb91028 | |||
|
|
cb1b3a28ab | ||
|
|
f7d8735b6b | ||
|
|
fc42ab9b46 | ||
|
|
7f17777a4b | ||
|
|
bcdb27416c | ||
|
|
15c6396d42 | ||
|
|
2c19345e58 | ||
|
|
69a7dd86ec | ||
| 1c4bfb6446 | |||
|
|
fdcafb83e3 | ||
|
|
b8ead3b511 | ||
|
|
ffff664918 | ||
|
|
bf984ecb9b | ||
|
|
f1e238a9af | ||
|
|
5290a85afd | ||
| 070b784a49 | |||
|
|
b5157dd9cb | ||
|
|
94812d17c8 | ||
|
|
7681090c12 | ||
|
|
866490c41f | ||
|
|
0662fc4d42 | ||
|
|
078d612b9e | ||
|
|
26025f79ce | ||
|
|
1c307bc1be | ||
|
|
7abddbd752 | ||
|
|
51c9f7270c | ||
|
|
b896670e85 | ||
|
|
69dd0c40bb | ||
|
|
c374c773ad | ||
| 18eb6bae01 | |||
|
|
2fd7888a51 | ||
|
|
d19915ea44 | ||
|
|
549e37d218 | ||
|
|
7b48a9f671 | ||
|
|
344db835e4 | ||
|
|
04353acccf | ||
|
|
c33f0b7d8d | ||
|
|
fd51fee424 | ||
|
|
c8b44816fe | ||
|
|
6e88389fb8 | ||
|
|
298447e22d | ||
|
|
a3c7de8a50 | ||
|
|
264f305d94 | ||
|
|
f8ec08a928 | ||
| b5809f3793 | |||
|
|
f09e6c183e | ||
|
|
3791ed86a3 | ||
|
|
7f772693eb | ||
|
|
5771f1ea14 | ||
|
|
0f4db1ed0d | ||
| 9980a98607 | |||
|
|
4b35626aec | ||
|
|
846588ee81 | ||
|
|
4f92b12a6a | ||
|
|
4b4b20f8a9 | ||
|
|
e26fe9bddd | ||
|
|
972be2df04 | ||
|
|
374cb6a7f8 | ||
|
|
923d6300ad | ||
| 442bd49137 | |||
|
|
baa4edc6ca | ||
|
|
9875311bcc | ||
|
|
c3a453512a | ||
|
|
e413ed8e1d | ||
|
|
858f411447 | ||
|
|
19c8cea8e5 | ||
| 263c7fefbf | |||
|
|
1ae10b1487 | ||
|
|
35cde9f8d7 | ||
|
|
d4d2840f5d | ||
|
|
119ec47072 | ||
|
|
ceb305a780 | ||
|
|
1dc2a75cb6 | ||
|
|
8d7b716ea7 | ||
|
|
034af70a65 | ||
|
|
162c213e7b | ||
|
|
6fde7d8a51 | ||
|
|
e4abef5768 | ||
|
|
3922b531a8 | ||
|
|
0d1438a731 | ||
|
|
7eb66d3e09 | ||
|
|
c7a600063d | ||
|
|
5b654ce9fb | ||
|
|
98e9a881c0 | ||
|
|
f420f7c177 | ||
|
|
50954a4b6a | ||
|
|
567310e698 | ||
|
|
f90b710c9b | ||
|
|
bdaec3f934 | ||
|
|
8198fd9c58 | ||
|
|
358a10e3cc | ||
|
|
7b935e0d40 | ||
|
|
7034c3cc47 | ||
|
|
e30eadb4de | ||
|
|
3e3f4a167a | ||
|
|
c98528f8d3 | ||
|
|
75e5f885e5 | ||
|
|
40b9e68e02 | ||
|
|
e7491920fd | ||
|
|
9904aa5538 | ||
|
|
41b89aef8c | ||
|
|
3925c137a4 | ||
|
|
97fa42c82b | ||
|
|
ccabaac5a0 | ||
|
|
80f7852941 | ||
|
|
6243831dfb | ||
|
|
4f9abb52a4 | ||
|
|
7bab8780ad | ||
|
|
d0dc270eec | ||
|
|
cd9402075a | ||
|
|
b1f3bdfcbd | ||
|
|
541a2dbc88 | ||
| 02249f1655 | |||
|
|
d1e28417d5 | ||
|
|
9410a55679 | ||
|
|
25ceefbd89 | ||
|
|
a37c4bb59e | ||
|
|
ee1f8a0494 | ||
|
|
2c5459a1b7 | ||
|
|
b561c386c3 | ||
|
|
a374dd0359 | ||
|
|
aba4f4e0e2 | ||
|
|
210c94d82f | ||
|
|
c410ba4d42 | ||
|
|
f3738fe164 | ||
|
|
04a08fe6a5 | ||
|
|
69d33ec170 | ||
|
|
40a4225ed8 | ||
|
|
801622ce19 | ||
|
|
67750a30ba | ||
|
|
2f25b6a650 | ||
|
|
5a3bd329d6 | ||
|
|
8b4bf2bb8d | ||
|
|
2a515058be | ||
|
|
3785f762fc | ||
|
|
5cee9f183b | ||
|
|
958ec294b2 | ||
|
|
3a781fd719 | ||
|
|
f4a2e7efe2 | ||
|
|
027365503f | ||
|
|
e31d59ebc8 | ||
|
|
11178e14ab | ||
|
|
0bcbd0015f | ||
|
|
271bd5d3ba | ||
|
|
74d252a68f | ||
|
|
4b928b466a | ||
|
|
10b4d0c8ad | ||
|
|
433dd92196 | ||
|
|
78d284881c | ||
|
|
a36b726bde | ||
|
|
83629b9991 | ||
|
|
405c66e864 | ||
|
|
e5df84a9ed | ||
|
|
614a977259 | ||
|
|
f1651abdac | ||
|
|
05a06048fc | ||
|
|
c599bc9bff | ||
|
|
54ded4527a | ||
|
|
4f433cd601 | ||
|
|
accecb9863 | ||
|
|
079588cac5 | ||
|
|
1d10ee71bf | ||
|
|
0520cbdccb | ||
|
|
3d3270c1b2 | ||
|
|
b60a26d40b | ||
|
|
36fcdce886 | ||
|
|
b760388bbf | ||
|
|
bb18524cce | ||
|
|
05eaa0f0d7 | ||
| ac58a97a92 | |||
| 140f2d72cb | |||
|
|
d4a1dbd4a9 | ||
|
|
0e9bef3429 | ||
| b81dca5014 | |||
| 0ac593a9ce | |||
| 8daf175b09 | |||
|
|
34238dc119 | ||
| 49935c0456 | |||
| b145ce016b | |||
| 226108a59f | |||
| 01b30a5a0e | |||
| 05fa7110ec | |||
|
|
18a40caa48 | ||
|
|
1980f1b2ba | ||
|
|
ec0c13afda | ||
|
|
ed41b3cefa | ||
|
|
80a924edfa | ||
|
|
98f9518bf2 | ||
|
|
1de47610f4 | ||
|
|
25ba7712f7 | ||
|
|
a6b534d760 | ||
|
|
494b191d55 | ||
|
|
450bfa7a75 | ||
|
|
a52ac1375a | ||
|
|
4990713e9e | ||
|
|
c022c4cc6d | ||
|
|
6257dec0a7 | ||
|
|
ea9d49b9d8 | ||
|
|
42c7bfcf8a | ||
|
|
e67d1bfeb8 | ||
|
|
e2f444cfdf | ||
|
|
03b85df4eb | ||
|
|
7db5c2f225 | ||
|
|
603ce231d0 | ||
|
|
940b5eaad1 | ||
|
|
fdd946c02c | ||
|
|
81e5b57d74 | ||
|
|
b568705eec | ||
|
|
fe42eb7a1a | ||
|
|
df7b0a6d97 | ||
|
|
fcf598e797 | ||
|
|
d9cb12f6e3 | ||
|
|
0f23729253 | ||
|
|
3def429290 | ||
|
|
803ea0d7a0 | ||
|
|
9b014876cd | ||
|
|
9ccf85eaa8 | ||
|
|
93fa53c3e8 | ||
|
|
eea3e1f0b2 | ||
|
|
e6e22ea976 | ||
|
|
80c2000f87 | ||
|
|
15a0a129c8 | ||
|
|
51bd04b541 | ||
|
|
18ba7f60c1 | ||
|
|
5c3e00d70a | ||
|
|
6c4c77971e | ||
|
|
67adef8f6c | ||
|
|
ed60e16974 | ||
|
|
47c11ae83d | ||
|
|
8173b1bfbe | ||
|
|
93400ec8a1 | ||
|
|
0d85a798e5 | ||
|
|
d4d534925f | ||
|
|
a1ba7ee786 | ||
|
|
756cd4a4b8 | ||
|
|
1b186fcff3 | ||
|
|
165da9b447 | ||
|
|
aea10ed383 | ||
|
|
8fccb31436 | ||
|
|
89bb88e4f5 | ||
|
|
a58efa70bc | ||
|
|
fe1fecc5da | ||
|
|
87612582ff | ||
|
|
c3a53cffbc | ||
|
|
aeea83703b | ||
|
|
27c8f13fc9 | ||
|
|
c6ddae70f7 | ||
|
|
e4ecd03e3f | ||
|
|
a6dc5c963c | ||
|
|
989e6a9a7e | ||
|
|
c28048d20f | ||
|
|
a24e72f972 | ||
|
|
a29aa31e93 | ||
|
|
8546139997 | ||
|
|
a61586947e | ||
|
|
5e4645b082 | ||
|
|
f9f0a8fd67 | ||
|
|
637a2eeb66 | ||
|
|
13caef2de0 | ||
|
|
61c6d43231 | ||
|
|
a04f6e0165 | ||
|
|
3f494e359d | ||
|
|
8a06f70379 | ||
|
|
2290152743 | ||
|
|
3b657a26a6 | ||
|
|
ff5084479b | ||
|
|
97f4a3f4eb | ||
|
|
1ca1732d32 | ||
|
|
accd2308f1 | ||
|
|
10eec2fe17 | ||
|
|
d69cd759cb | ||
|
|
f261a8aca5 | ||
|
|
bdf64d660b | ||
|
|
2fd30ee095 | ||
|
|
9bc6f1797e | ||
|
|
32e63fe1b8 | ||
|
|
1c074cc8cc | ||
|
|
ebf6228f21 | ||
|
|
4a1db96db8 | ||
|
|
16ee4636bc | ||
|
|
6831b37b43 | ||
|
|
4d16f26ba4 | ||
|
|
4a7bc73e03 | ||
|
|
caf583ec4b | ||
|
|
e20880da21 |
4
AUTHORS
4
AUTHORS
@ -8,7 +8,9 @@ Chris Allegretta <chrisa@asty.org>
|
|||||||
Benno Schulenberg <bensberg@telfort.nl>
|
Benno Schulenberg <bensberg@telfort.nl>
|
||||||
* An array of small bug fixes, the cut-word and block-jump
|
* An array of small bug fixes, the cut-word and block-jump
|
||||||
routines, text selection by holding Shift, macro recording
|
routines, text selection by holding Shift, macro recording
|
||||||
and replay, plus some key bindings. Current maintainer.
|
and replay, extra key bindings, the --indicator, --minibar,
|
||||||
|
and --zero options, and braced functions in string binds.
|
||||||
|
Current maintainer.
|
||||||
|
|
||||||
David Lawrence Ramsey <pooka109@gmail.com>
|
David Lawrence Ramsey <pooka109@gmail.com>
|
||||||
* Former stable series maintainer. Multiple buffer support,
|
* Former stable series maintainer. Multiple buffer support,
|
||||||
|
|||||||
277
ChangeLog
277
ChangeLog
@ -1,3 +1,280 @@
|
|||||||
|
Changes between v7.1 and v7.2:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (11):
|
||||||
|
bindings: let ^/ toggle between the 'search' and 'gotoline' menus
|
||||||
|
bump version numbers and add a news item for the 7.2 release
|
||||||
|
copyright: update the years for the FSF
|
||||||
|
docs: give ^K and ^U some useful function in the alternative bindings
|
||||||
|
docs: put the binding of ^Y after its unbinding, for it to be effective
|
||||||
|
gnulib: update to its current upstream state
|
||||||
|
input: disallow bracketed pastes when in view mode
|
||||||
|
syntax: html: colorize specially the other two emphasizing tags too
|
||||||
|
tweaks: avoid warnings when compiling with -Wpedantic
|
||||||
|
tweaks: rewrap an old news item
|
||||||
|
tweaks: separate a special thanks from the preceding ones
|
||||||
|
|
||||||
|
|
||||||
|
Changes between v7.0 and v7.1:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (8):
|
||||||
|
build: fix compilation when configured with --disable-comment
|
||||||
|
bump version numbers and add a news item for the 7.1 release
|
||||||
|
copyright: update the last year for significantly changed files
|
||||||
|
docs: say thanks to the Albanian translator
|
||||||
|
rcfile: report an error when an included file does not exist
|
||||||
|
text: upon Enter, eat only lefthand blanks, not any other characters
|
||||||
|
tweaks: avoid passing NULL to access()
|
||||||
|
tweaks: wrap overlong lines in the Tcl syntax, to make them manageable
|
||||||
|
|
||||||
|
|
||||||
|
Changes between v6.4 and v7.0:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (94):
|
||||||
|
build: add options --disable-formatter and --disable-linter to configure
|
||||||
|
build: exclude some pieces that are not needed with --disable-nanorc
|
||||||
|
build: exclude two unneeded functions correctly from the tiny version
|
||||||
|
build: fix compilation when configured with --enable-tiny
|
||||||
|
bump version numbers and add a news item for the 7.0 release
|
||||||
|
completion: search through all open buffers for possible completions
|
||||||
|
docs: clarify the distinction between binding a function and "{function}"
|
||||||
|
docs: describe --disable-formatter and --disable-linter configure options
|
||||||
|
docs: explain how to include a double quote plus space in a nanorc regex
|
||||||
|
docs: improve the legibility of an itemized list
|
||||||
|
docs: mention in the man page how M-V can insert any Unicode code point
|
||||||
|
docs: mention that string binds may contain function names between braces
|
||||||
|
docs: replace control codes in the examples with {command} cartouches
|
||||||
|
docs: suggest a key binding for snipping trailing blanks
|
||||||
|
execute: show "Cancelled" instead of "Error" when the user hits ^C
|
||||||
|
extra: use the whole terminal for the crawl, and quicken it a bit
|
||||||
|
feedback: suppress undo/redo messages when option --zero is in effect
|
||||||
|
files: before sending data to an external command, decode LF back to NUL
|
||||||
|
files: improve the error handling when executing an external command
|
||||||
|
filtering: terminate also the sender process when the user hits ^C
|
||||||
|
filtering: when returning to a line number, ensure it is within range
|
||||||
|
gnulib: update to its current upstream state
|
||||||
|
goto: don't center the current line when the user specified a column only
|
||||||
|
help: don't show the New-Buffer toggle when in view mode
|
||||||
|
help: move the M-Del item up, so that M-PgUp and M-PgDn are paired
|
||||||
|
help: prioritize the unshifted Meta keystrokes for buffer switching
|
||||||
|
input: allocate a small keystroke buffer, and never free it
|
||||||
|
input: allocate two small character buffers too, and never free them
|
||||||
|
input: give up when the capacity of the keystroke buffer overflows
|
||||||
|
input: interpret commands of the form {functionname} inside string binds
|
||||||
|
memory: avoid a leak when a string bind specifies an unknown menu
|
||||||
|
prompt: allow rebinding also ^N, ^Q, and ^Y at the yes-no prompt
|
||||||
|
prompt: ingest queued characters before handling any subsequent function
|
||||||
|
prompt: prevent execution of inadmissible functions in view mode
|
||||||
|
prompt: return FALSE for non-editing functions also in the tiny version
|
||||||
|
prompt: toggle the help lines only for the 'nohelp' toggle
|
||||||
|
search: skip a match on the magic line, as it is a just convenience line
|
||||||
|
startup: ensure that +/string centers the match also with --linenumbers
|
||||||
|
startup: for +/string, center the found occurrence when possible
|
||||||
|
startup: quit when standard input is not a TTY (after handling arguments)
|
||||||
|
startup: report an empty search string also when there is a modifier
|
||||||
|
syntax: nanorc: colorize valid function names plus surrounding braces
|
||||||
|
tweaks: add parentheses for consistency, and reshuffle for conciseness
|
||||||
|
tweaks: allow the linter to be used in view mode, as it makes no changes
|
||||||
|
tweaks: attribute some of the features that were added in the last years
|
||||||
|
tweaks: avoid iterating over the same string twice in a row
|
||||||
|
tweaks: avoid sometimes calling a function three times in a row
|
||||||
|
tweaks: check the multiline regexes only for Delete and Backspace
|
||||||
|
tweaks: condense a comment, add two small ones, and reshuffle a line
|
||||||
|
tweaks: delete a flag that is no longer used
|
||||||
|
tweaks: determine in another way whether a shortcut is okay in view mode
|
||||||
|
tweaks: discard a bracketed paste in the browser more efficiently
|
||||||
|
tweaks: don't use a pointer when the value itself is all that is needed
|
||||||
|
tweaks: drop an unneeded check for permissibility of prompt shortcuts
|
||||||
|
tweaks: drop a parameter that is no longer used
|
||||||
|
tweaks: drop shunting of flags by calling the needed function directly
|
||||||
|
tweaks: elide a function that does not need to be a separate function
|
||||||
|
tweaks: elide an assignment by iterating with the target variable
|
||||||
|
tweaks: elide an intermediary variable that is no longer needed
|
||||||
|
tweaks: elide an unused parameter
|
||||||
|
tweaks: elide an unused return value
|
||||||
|
tweaks: elide a parameter by moving the general case one level up
|
||||||
|
tweaks: elide a variable, rename another, and reshuffle an assignment
|
||||||
|
tweaks: fold two cases together, because they basically do the same
|
||||||
|
tweaks: group the special keycodes for implanted strings together
|
||||||
|
tweaks: improve two comments, and exclude two unneeded prototypes
|
||||||
|
tweaks: make the crawl use the whole screen also in the tiny version
|
||||||
|
tweaks: make two error messages more succinct and easier to translate
|
||||||
|
tweaks: move the arrays of menu names and symbols to where they are used
|
||||||
|
tweaks: move the --magic option up, so that --zero comes last
|
||||||
|
tweaks: move to a given line number more efficiently
|
||||||
|
tweaks: move two checks plus corresponding calls to a better place
|
||||||
|
tweaks: normalize the indentation after the previous change
|
||||||
|
tweaks: reduce four variations of a message to a single common form
|
||||||
|
tweaks: rename a macro for clarity, and normalize some indentation
|
||||||
|
tweaks: rename a variable, away from an abbreviation
|
||||||
|
tweaks: rename two record elements and three parameters, for clarity
|
||||||
|
tweaks: replace sizeof(char) with 1, as that is assumed anyway
|
||||||
|
tweaks: reshuffle a declaration, and correct the wording of a comment
|
||||||
|
tweaks: reshuffle a line, to group things better
|
||||||
|
tweaks: reshuffle some code and drop some comments, for conciseness
|
||||||
|
tweaks: reshuffle some code, to not determine a shortcut twice
|
||||||
|
tweaks: reshuffle some lines, to be more readable instead of compact
|
||||||
|
tweaks: reshuffle two lines, for conciseness and in preparation
|
||||||
|
tweaks: reword and/or condense four comments
|
||||||
|
tweaks: rewrap line, improve wording, and correct typo in old news item
|
||||||
|
tweaks: rewrap some lines, drop a redundant call, and reshuffle a line
|
||||||
|
tweaks: simplify a function now that a Unicode code can be typed quicker
|
||||||
|
tweaks: simplify a pasting routine, modelling it after the injection one
|
||||||
|
tweaks: use an auxiliary variable to avoid dereferences of 'shortcut'
|
||||||
|
undo: make sure the current line is defined before it is referenced
|
||||||
|
verbatim: allow the user to finish Unicode input with <Enter> or <Space>
|
||||||
|
verbatim: do not overwrite the status bar when the code is invalid
|
||||||
|
verbatim: don't show dots during Unicode input, as they give wrong idea
|
||||||
|
|
||||||
|
|
||||||
|
Changes between v6.3 and v6.4:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (24):
|
||||||
|
bump version numbers and add a news item for the 6.4 release
|
||||||
|
display: remember text and column positions when softwrapping a line
|
||||||
|
docs: concisely describe how the linter behaves
|
||||||
|
docs: remove the two notices about the changed defaults
|
||||||
|
docs: rename README.GIT to README.hacking, so it's clearer what is meant
|
||||||
|
docs: stop mentioning the obsoleted keywords that were removed
|
||||||
|
files: designate the root directory with a simple "/", not with "//"
|
||||||
|
formatter: instead of leaving curses, use full_refresh() to wipe messages
|
||||||
|
gnulib: update to its current upstream state
|
||||||
|
help: reshuffle two shortcuts so that more help-line items are paired
|
||||||
|
options: stop accepting -z, as --suspendable has been dropped too
|
||||||
|
rcfile: remove five obsolete or deprecated keywords
|
||||||
|
syntax: default: do not colorize a square or angle bracket after a URL
|
||||||
|
syntax: perl: add missing keywords, and reduce the length of some lines
|
||||||
|
syntax: python: mention an alternative linter in a comment
|
||||||
|
tweaks: add a missing word to a news item
|
||||||
|
tweaks: add a translator hint
|
||||||
|
tweaks: improve a comment, and reshuffle two functions plus some lines
|
||||||
|
tweaks: put each regex on separate line, to better show many keywords
|
||||||
|
tweaks: rename a variable, to not be the same as a function name
|
||||||
|
tweaks: rename two variables, to not contain the name of another
|
||||||
|
tweaks: reshuffle a description and rewrap another
|
||||||
|
tweaks: reshuffle a few lines, to group things better
|
||||||
|
version: condense the copyright message, to not dominate the output
|
||||||
|
|
||||||
|
LIU Hao (1):
|
||||||
|
build: ignore errors from `git describe`
|
||||||
|
|
||||||
|
|
||||||
|
Changes between v6.2 and v6.3:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (41):
|
||||||
|
build: add the --disable-maintainer-mode option to ./configure
|
||||||
|
build: fix compilation for --enable-{tiny,nanorc,color}
|
||||||
|
build: fix compilation when configured with --disable-color
|
||||||
|
build: remove an obsolete check -- the dependent code was deleted
|
||||||
|
bump version numbers and add a news item for the 6.3 release
|
||||||
|
display: suppress spotlight yellow and error red when NO_COLOR is set
|
||||||
|
docs: add an example binding for copying text to the system clipboard
|
||||||
|
execute: clear an anchor only when the whole buffer gets filtered
|
||||||
|
execute: don't crash when an empty buffer is piped through a command
|
||||||
|
execute: stay on the same line number when filtering the whole buffer
|
||||||
|
feedback: show extra warning when writing failed due to "No space left"
|
||||||
|
files: do not change to a higher directory when the working one is gone
|
||||||
|
files: show a warning when the working directory is gone (when used)
|
||||||
|
files: when the working directory exists, still check its accessibility
|
||||||
|
filtering: close all output descriptors, so that 'xsel' will terminate
|
||||||
|
formatting: change cursor position only after saving it in the undo item
|
||||||
|
gnulib: pull in the workaround for a build problem on NetBSD
|
||||||
|
gnulib: update to its current upstream state
|
||||||
|
justify: stay at the same line number when doing a full justification
|
||||||
|
painting: colorize text also after an unterminated start match
|
||||||
|
painting: look for another start match only after the actual end match
|
||||||
|
painting: recalculate the multidata when making large strides or changes
|
||||||
|
painting: stop coloring an extremely long line after 2000 bytes
|
||||||
|
painting: tighten the check for a lacking end match on a colored line
|
||||||
|
syntax: xml: colorize /> properly, and colorize prolog tags differently
|
||||||
|
syntax: xml: colorize user-defined entities differently
|
||||||
|
tweaks: avoid a function call when two plain assignments will do
|
||||||
|
tweaks: change the indentation of a list, to match other indentations
|
||||||
|
tweaks: don't leave an orphaned temporary file behind when writing fails
|
||||||
|
tweaks: elide an unneeded call of strlen()
|
||||||
|
tweaks: exclude the extra truncation warning from the tiny version
|
||||||
|
tweaks: make the triggering of the recalculation of multidata less eager
|
||||||
|
tweaks: move the saving and restoring of flags to where it is needed
|
||||||
|
tweaks: normalize the indentation after the previous change
|
||||||
|
tweaks: prevent the adding of an unwanted newline in a different way
|
||||||
|
tweaks: remove redundant braces, and add two translator hints
|
||||||
|
tweaks: remove some stray spaces before a comma
|
||||||
|
tweaks: simplify a bit of code, eliding two labels and three gotos
|
||||||
|
tweaks: simplify a fragment of code, and fold two lines together
|
||||||
|
tweaks: trim a few comments, rename a function, and reshuffle some code
|
||||||
|
verbatim: with --zero, keep cursor in viewport when it was on bottom row
|
||||||
|
|
||||||
|
Mike Frysinger (1):
|
||||||
|
general: fix building for Windows
|
||||||
|
|
||||||
|
|
||||||
|
Changes between v6.1 and v6.2:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (14):
|
||||||
|
bump version numbers and add a news item for the 6.2 release
|
||||||
|
display: suppress the bottom-bar wiping only when the user is editing
|
||||||
|
linter: adjust the parsing to accommodate for a modern 'pyflakes'
|
||||||
|
syntaxes: fold a couple of regexes together, and improve a few comments
|
||||||
|
tweaks: change the type of a variable, to avoid a compiler warning
|
||||||
|
tweaks: consistently backslash-escape the dash in M-letter keystrokes
|
||||||
|
tweaks: rename a misnamed variable
|
||||||
|
tweaks: rename a variable, reshuffle five lines, and snip two comments
|
||||||
|
tweaks: rename a variable, to be more correct, and adjust two comments
|
||||||
|
tweaks: rename a variable, to be more fitting
|
||||||
|
tweaks: rename two more variables, and drop unneeded initializations
|
||||||
|
tweaks: rename two variables (to get rid of a prefix), and elide a third
|
||||||
|
tweaks: store a result, to avoid calling a function twice
|
||||||
|
tweaks: use an intermediate variable, to avoid using one for two purposes
|
||||||
|
|
||||||
|
|
||||||
|
Changes between v6.0 and v6.1:
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Benno Schulenberg (37):
|
||||||
|
build: fix compilation when configured with --enable-tiny
|
||||||
|
build: prevent autopoint from overwriting a newer M4 file from gnulib
|
||||||
|
bump version numbers and add a news item for the 6.1 release
|
||||||
|
copyright: update the last year for significantly changed files
|
||||||
|
copyright: update the years for the FSF
|
||||||
|
docs: mention bindable function 'zero', for toggling the interface bars
|
||||||
|
docs: mention 'set guidestripe' and 'set unix' in the sample nanorc
|
||||||
|
docs: remove obsolete Ctrl+Z from the cheatsheet; mention Alt+X instead
|
||||||
|
files: let ^C cancel the exiting when the file on disk was changed
|
||||||
|
gnulib: update to its current upstream state
|
||||||
|
help: make the description of <Tab> more accurate
|
||||||
|
help: update the description of M-D, to match the actual order of counts
|
||||||
|
input: instead of moving waiting keycodes, just increment a pointer
|
||||||
|
input: suppress any spotlighting when there are more keycodes waiting
|
||||||
|
menus: don't show M-6 in the help lines of any prompt
|
||||||
|
prompt: allow the user to copy the answer to the cutbuffer (with M-6)
|
||||||
|
prompt: let ^K erase text after cursor (if any), otherwise whole answer
|
||||||
|
tweaks: add some feedback to the autogen.sh script, to ease the wait
|
||||||
|
tweaks: add some small, clarifying comments
|
||||||
|
tweaks: adjust a translator hint, to fit the order in the POT file
|
||||||
|
tweaks: drop foreign M-U and M-R from among the sample CUA bindings
|
||||||
|
tweaks: remove a redundant check -- add a different one for symmetry
|
||||||
|
tweaks: remove two redundant checks
|
||||||
|
tweaks: rename a function and its two parameters, for clarity
|
||||||
|
tweaks: rename a function and reshuffle its call
|
||||||
|
tweaks: rename a function, to not contain the name of a variable
|
||||||
|
tweaks: rename another variable, to better fit in with its sisters
|
||||||
|
tweaks: rename a variable and a parameter, to be more descriptive
|
||||||
|
tweaks: rename a variable, away from an abbreviation
|
||||||
|
tweaks: rename a variable, for clarity and contrast
|
||||||
|
tweaks: rename a variable, to make it clearer it refers to a window
|
||||||
|
tweaks: rename two variables, and elide a near-enough duplicate
|
||||||
|
tweaks: reshuffle some sample bindings, to group them differently
|
||||||
|
tweaks: reword two comments, and rename a variable (away from an abbrev)
|
||||||
|
tweaks: stop asking the terminal for its new size -- let ncurses do it
|
||||||
|
tweaks: use some symbolic names instead of unclear numeric values
|
||||||
|
tweaks: when discarding keycodes, don't bother parsing them
|
||||||
|
|
||||||
|
|
||||||
Changes between v5.9 and v6.0:
|
Changes between v5.9 and v6.0:
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
Improvements in GNU nano
|
Improvements in GNU nano
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
Since 7.0:
|
||||||
|
- String binds may contain bindable function names between braces.
|
||||||
|
- Word completion looks for candidates in all open buffers.
|
||||||
|
- Unicode codes can be entered without leading zeroes.
|
||||||
|
|
||||||
Since 6.0:
|
Since 6.0:
|
||||||
- Option --zero hides the interface and uses the whole terminal for editing.
|
- Option --zero hides the interface and uses the whole terminal for editing.
|
||||||
- Colors can be given also in #rgb hexadecimal, to select the nearest color
|
- Colors can be given also in #rgb hexadecimal, to select the nearest color
|
||||||
|
|||||||
87
NEWS
87
NEWS
@ -1,3 +1,52 @@
|
|||||||
|
2023.01.18 - GNU nano 7.2 "Boer doe mij 't hekke lös!"
|
||||||
|
• <Shift+Insert> is prevented from pasting in view mode.
|
||||||
|
|
||||||
|
2022.12.14 - GNU nano 7.1 "And the devices shall be made of wood"
|
||||||
|
• When --autoindent and --breaklonglines are combined, pressing
|
||||||
|
<Enter> at a specific position no longer eats characters.
|
||||||
|
|
||||||
|
2022.11.15 - GNU nano 7.0 "Una existencia simple bajo el sol"
|
||||||
|
• String binds may contain bindable function names between braces.
|
||||||
|
For example, to move the current line down to after the next one:
|
||||||
|
bind ^D "{cut}{down}{paste}{up}" main. Of course, braced function
|
||||||
|
names may be mixed with literal text. If an existing string bind
|
||||||
|
contains a literal {, replace it with {{}.
|
||||||
|
• Unicode codes can be entered (via M-V) without leading zeroes,
|
||||||
|
by finishing short codes with <Space> or <Enter>.
|
||||||
|
• Word completion (^]) looks for candidates in all open buffers.
|
||||||
|
• No regular expression matches the final empty line any more.
|
||||||
|
|
||||||
|
|
||||||
|
2022.08.02 - GNU nano 6.4 "Regentag Dunkelbunt Hundertwasser"
|
||||||
|
• The file browser does not crash when moving up to the root folder.
|
||||||
|
• Softwrapping very long lines is done more efficiently.
|
||||||
|
• Invoking the formatter does not blink the screen.
|
||||||
|
|
||||||
|
2022.04.28 - GNU nano 6.3 "Wat zullen we drinken? Wat een dorst!"
|
||||||
|
• For multiline regexes, text is now colored as soon as a start match
|
||||||
|
is found, also when there is no end match at all.
|
||||||
|
• The colorizing of any line is stopped after two thousand bytes,
|
||||||
|
to avoid frustrating delays.
|
||||||
|
• When environment variable NO_COLOR is set, the two default colors
|
||||||
|
(yellow for the spotlight, red for error messages) are suppressed
|
||||||
|
when no interface colors are specified in a nanorc file.
|
||||||
|
• Full justification and piping the whole buffer through a command
|
||||||
|
now keep the cursor at the same line number.
|
||||||
|
• Utility 'xsel' can be used to copy a marked region to the system's
|
||||||
|
clipboard. See doc/sample.nanorc for an example.
|
||||||
|
|
||||||
|
2022.02.18 - GNU nano 6.2 "Kamperfoelie"
|
||||||
|
• The file browser clears the prompt bar also when using --minibar.
|
||||||
|
• Linting now works also with a newer 'pyflakes'.
|
||||||
|
|
||||||
|
2022.02.09 - GNU nano 6.1 "Rețelele de socializare sunt ca un frigider"
|
||||||
|
• The behavior of ^K at a prompt has been enhanced: when there is some
|
||||||
|
text after the cursor, just this text is erased. In the most common
|
||||||
|
situation, when the cursor is at the end of the answer, the behavior
|
||||||
|
is as before: the whole answer is erased.
|
||||||
|
• At a prompt, M-6 copies the current answer into the cutbuffer.
|
||||||
|
• Large external pastes into nano are handled more quickly.
|
||||||
|
|
||||||
2021.12.15 - GNU nano 6.0 "Humor heeft ook zijn leuke kanten"
|
2021.12.15 - GNU nano 6.0 "Humor heeft ook zijn leuke kanten"
|
||||||
• Option --zero hides the title bar, status bar and help lines, and
|
• Option --zero hides the title bar, status bar and help lines, and
|
||||||
uses all rows of the terminal as editing area. The title bar and
|
uses all rows of the terminal as editing area. The title bar and
|
||||||
@ -752,22 +801,22 @@
|
|||||||
the undo implementation and the default syntax config are
|
the undo implementation and the default syntax config are
|
||||||
also included. As always, Share and Enjoy!
|
also included. As always, Share and Enjoy!
|
||||||
|
|
||||||
2014.05.28 - GNU nano 2.3.3 is in its right place. This release contains
|
2014.05.28 - GNU nano 2.3.3 is in its right place. This release
|
||||||
many many improvements to the core system, including
|
contains many many improvements to the core system,
|
||||||
substantial improvements to the undo/redo code, UTF-8
|
including substantial improvements to the undo/redo code,
|
||||||
handling, the configure script, and display of shortcuts
|
UTF-8 handling, the configure script, and display of
|
||||||
on very wide terminals. New features include the
|
shortcuts on very wide terminals. New features include
|
||||||
ability to write to named pipes (--noread), as well as
|
the ability to write to named pipes (--noread), as well
|
||||||
linter support (see the nanorc man page for details). Also
|
as linter support (see the nanorc man page for details).
|
||||||
included are much improved syntax highlighting code, and
|
Also included are much improved syntax highlighting code,
|
||||||
configurations for JSON, texinfo, Go, and a default syntax
|
and configurations for JSON, texinfo, Go, and a default
|
||||||
for catch-all highlighting. Finally, nano now has the
|
syntax for catch-all highlighting. Finally, nano now has
|
||||||
ability to set the color of the title bar, status bar, and
|
the ability to set the color of the title bar, status bar,
|
||||||
shortcut keys (e.g. "^X") and their descriptions. Again
|
and shortcut keys (e.g. "^X") and their descriptions.
|
||||||
see the nanorc page for details. There's much more, too
|
Again see the nanorc page for details. There's much more,
|
||||||
much to include here, but please keep those reports and
|
too much to include here, but please keep those reports
|
||||||
general feedback coming! Thank you for helping us help
|
and general feedback coming! Thank you for helping us
|
||||||
you help us all.
|
help you help us all.
|
||||||
|
|
||||||
2013.03.22 - GNU nano 2.3.2 "Annoy your coworkers for fun and profit" is
|
2013.03.22 - GNU nano 2.3.2 "Annoy your coworkers for fun and profit" is
|
||||||
released. This release introduces vim-style file locking
|
released. This release introduces vim-style file locking
|
||||||
@ -906,13 +955,13 @@
|
|||||||
the command line will now override any related .nanorc
|
the command line will now override any related .nanorc
|
||||||
entries. Speak now or forever hold your bugs!
|
entries. Speak now or forever hold your bugs!
|
||||||
|
|
||||||
2009.11.15 - GNU nano 2.1.99pre1 "take a bow" is out there, man, it's
|
2009.11.15 - GNU nano 2.1.99pre1 "take a bow" is out there, man,
|
||||||
out there all right. This release contains mainly
|
it's out there all right. This release contains mainly
|
||||||
bugfixes, underscoring that we are preparing for the
|
bugfixes, underscoring that we are preparing for the
|
||||||
next stable series release. Included are many fixes
|
next stable series release. Included are many fixes
|
||||||
for the new soft wrapping code, compiler warning tweaks,
|
for the new soft wrapping code, compiler warning tweaks,
|
||||||
and the modification time warning no longer triggers
|
and the modification time warning no longer triggers
|
||||||
when saving a file as a new name. Also include are
|
when saving a file with a new name. Also included are
|
||||||
some fixes for various nanorc options, and there are
|
some fixes for various nanorc options, and there are
|
||||||
surely more bugs to find before we call the code base
|
surely more bugs to find before we call the code base
|
||||||
stable, so please keep those reports coming!
|
stable, so please keep those reports coming!
|
||||||
|
|||||||
2
README
2
README
@ -15,7 +15,7 @@ Appearance
|
|||||||
In rough ASCII graphics, this is what nano's screen looks like:
|
In rough ASCII graphics, this is what nano's screen looks like:
|
||||||
|
|
||||||
____________________________________________________________________
|
____________________________________________________________________
|
||||||
| GNU nano 6.0 filename Modified |
|
| GNU nano 7.2 filename Modified |
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
| This is the text window, displaying the contents of a 'buffer', |
|
| This is the text window, displaying the contents of a 'buffer', |
|
||||||
| the contents of the file you are editing. |
|
| the contents of the file you are editing. |
|
||||||
|
|||||||
@ -8,19 +8,18 @@ building this needs a bit more care than the official tarballs.
|
|||||||
Prerequisites
|
Prerequisites
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
To successfully compile GNU nano from git, you'll need the following
|
To successfully compile GNU nano from git, you'll need the following:
|
||||||
packages:
|
|
||||||
|
|
||||||
- autoconf (version >= 2.69)
|
autoconf (version >= 2.69)
|
||||||
- automake (version >= 1.14)
|
automake (version >= 1.14)
|
||||||
- autopoint (version >= 0.18.3)
|
autopoint (version >= 0.18.3)
|
||||||
- gcc (version >= 5.0)
|
gcc (version >= 5.0)
|
||||||
- gettext (version >= 0.18.3)
|
gettext (version >= 0.18.3)
|
||||||
- git (version >= 2.7.4)
|
git (version >= 2.7.4)
|
||||||
- groff (version >= 1.12)
|
groff (version >= 1.12)
|
||||||
- make (any version)
|
make (any version)
|
||||||
- pkg-config (version >= 0.22)
|
pkg-config (version >= 0.22)
|
||||||
- texinfo (version >= 4.0)
|
texinfo (version >= 4.0)
|
||||||
|
|
||||||
You will also need to have the header files for ncurses installed,
|
You will also need to have the header files for ncurses installed,
|
||||||
from libncurses-dev on Debian, ncurses-devel on Fedora, or similar.
|
from libncurses-dev on Debian, ncurses-devel on Fedora, or similar.
|
||||||
@ -29,14 +28,14 @@ These should all be available in your distro's package manager or
|
|||||||
software center, or otherwise on any GNU mirror.
|
software center, or otherwise on any GNU mirror.
|
||||||
|
|
||||||
|
|
||||||
Download the source
|
Clone the source
|
||||||
-------------------
|
----------------
|
||||||
|
|
||||||
To obtain the current nano development branch (called 'master'), use the
|
To obtain the current nano development branch (called 'master'), use the
|
||||||
following command. It will create in your current working directory a
|
following command. It will create in your current working directory a
|
||||||
subdirectory called 'nano' containing a copy of all of the files:
|
subdirectory called 'nano' containing a copy of all of the files:
|
||||||
|
|
||||||
$ git clone git://git.savannah.gnu.org/nano.git nano
|
$ git clone git://git.savannah.gnu.org/nano.git
|
||||||
|
|
||||||
|
|
||||||
Generate the configure script
|
Generate the configure script
|
||||||
@ -84,6 +83,7 @@ Problems?
|
|||||||
Please submit any bugs you find in the code in git via the bug tracker
|
Please submit any bugs you find in the code in git via the bug tracker
|
||||||
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
|
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
|
||||||
|
|
||||||
|
|
||||||
Contributing something
|
Contributing something
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
3
THANKS
3
THANKS
@ -6,8 +6,9 @@ Translations:
|
|||||||
============
|
============
|
||||||
Pedro Albuquerque <palbuquerque73@gmail.com> Portuguese
|
Pedro Albuquerque <palbuquerque73@gmail.com> Portuguese
|
||||||
Josef Andersson <josef.andersson@fripost.org> Swedish
|
Josef Andersson <josef.andersson@fripost.org> Swedish
|
||||||
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
|
|
||||||
Mario Blättermann <mario.blaettermann@gmail.com> German
|
Mario Blättermann <mario.blaettermann@gmail.com> German
|
||||||
|
Besnik Bleta <besnik@programeshqip.org> Albanian
|
||||||
|
Laurențiu Buzdugan <buzdugan@voyager.net> Romanian
|
||||||
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
|
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
|
||||||
Antonio Ceballos <aceballos@gmail.com> Spanish
|
Antonio Ceballos <aceballos@gmail.com> Spanish
|
||||||
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
|
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
|
||||||
|
|||||||
26
autogen.sh
26
autogen.sh
@ -2,7 +2,7 @@
|
|||||||
# Generate configure & friends for GIT users.
|
# Generate configure & friends for GIT users.
|
||||||
|
|
||||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||||
gnulib_hash="135414a7f543e4d40ad0a7cbd51885e159a6e0f4"
|
gnulib_hash="2cf7f442f52f70b3df6eb396eb93ea08e54883c5"
|
||||||
|
|
||||||
modules="
|
modules="
|
||||||
futimens
|
futimens
|
||||||
@ -36,14 +36,26 @@ fi
|
|||||||
cd gnulib >/dev/null || exit 1
|
cd gnulib >/dev/null || exit 1
|
||||||
curr_hash=$(git log -1 --format=%H)
|
curr_hash=$(git log -1 --format=%H)
|
||||||
if [ "${gnulib_hash}" != "${curr_hash}" ]; then
|
if [ "${gnulib_hash}" != "${curr_hash}" ]; then
|
||||||
|
echo "Pulling..."
|
||||||
git pull
|
git pull
|
||||||
git checkout -f ${gnulib_hash}
|
git checkout --force ${gnulib_hash}
|
||||||
fi
|
fi
|
||||||
cd .. >/dev/null || exit 1
|
cd .. >/dev/null || exit 1
|
||||||
|
|
||||||
rm -rf lib
|
echo "Autopoint..."
|
||||||
./gnulib/gnulib-tool \
|
autopoint --force
|
||||||
--import \
|
|
||||||
${modules}
|
|
||||||
|
|
||||||
autoreconf -f -i -s
|
rm -rf lib
|
||||||
|
echo "Gnulib-tool..."
|
||||||
|
./gnulib/gnulib-tool --import ${modules}
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Aclocal..."
|
||||||
|
aclocal -I m4
|
||||||
|
echo "Autoconf..."
|
||||||
|
autoconf
|
||||||
|
echo "Autoheader..."
|
||||||
|
autoheader
|
||||||
|
echo "Automake..."
|
||||||
|
automake --add-missing
|
||||||
|
echo "Done."
|
||||||
|
|||||||
91
configure.ac
91
configure.ac
@ -1,6 +1,6 @@
|
|||||||
# Configuration for GNU nano - a small and user-friendly text editor
|
# Configuration for GNU nano - a small and user-friendly text editor
|
||||||
#
|
#
|
||||||
# Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
|
# Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc.
|
||||||
# Copyright (C) 2014, 2017 Mike Frysinger
|
# Copyright (C) 2014, 2017 Mike Frysinger
|
||||||
#
|
#
|
||||||
# GNU nano is free software: you can redistribute it and/or modify
|
# GNU nano is free software: you can redistribute it and/or modify
|
||||||
@ -16,10 +16,11 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see https://www.gnu.org/licenses/.
|
# along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
AC_INIT([GNU nano], [6.0], [nano-devel@gnu.org], [nano])
|
AC_INIT([GNU nano], [7.2], [nano-devel@gnu.org], [nano])
|
||||||
AC_CONFIG_SRCDIR([src/nano.c])
|
AC_CONFIG_SRCDIR([src/nano.c])
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
AM_INIT_AUTOMAKE([1.14])
|
AM_INIT_AUTOMAKE([1.14])
|
||||||
|
AM_MAINTAINER_MODE([enable])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
dnl Make sure the ONCE macros are available.
|
dnl Make sure the ONCE macros are available.
|
||||||
@ -127,6 +128,20 @@ if test "x$enable_color" != xno; then
|
|||||||
color_support=yes
|
color_support=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(folding,
|
||||||
|
AS_HELP_STRING([--disable-folding], [Disable line folding support]))
|
||||||
|
if test "x$enable_tiny" = xyes; then
|
||||||
|
if test "x$enable_folding" = xyes; then
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
*** --enable-folding cannot work with --enable-tiny])
|
||||||
|
else
|
||||||
|
enable_folding=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "x$enable_folding" != xno; then
|
||||||
|
AC_DEFINE(ENABLE_FOLDING, 1, [Define this to have line folding support.])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(comment,
|
AC_ARG_ENABLE(comment,
|
||||||
AS_HELP_STRING([--disable-comment], [Disable the comment/uncomment function]))
|
AS_HELP_STRING([--disable-comment], [Disable the comment/uncomment function]))
|
||||||
if test "x$enable_tiny" = xyes; then
|
if test "x$enable_tiny" = xyes; then
|
||||||
@ -152,6 +167,30 @@ if test "x$enable_extra" != xno; then
|
|||||||
AC_DEFINE(ENABLE_EXTRA, 1, [Define this to have an Easter egg.])
|
AC_DEFINE(ENABLE_EXTRA, 1, [Define this to have an Easter egg.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(formatter,
|
||||||
|
AS_HELP_STRING([--disable-formatter], [Disable the formatting tool]))
|
||||||
|
if test "x$enable_tiny" = xyes; then
|
||||||
|
if test "x$enable_formatter" = xyes; then
|
||||||
|
if test "x$enable_color" != xyes; then
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
*** --enable-formatter needs both --enable-color and --enable-nanorc to work])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
enable_formatter=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "x$enable_color" = xno; then
|
||||||
|
if test "x$enable_formatter" = xyes; then
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
*** --enable-formatter cannot work with --disable-color nor --disable-nanorc])
|
||||||
|
else
|
||||||
|
enable_formatter=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "x$enable_formatter" != xno; then
|
||||||
|
AC_DEFINE(ENABLE_FORMATTER, 1, [Define this to have access to a formatter.])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(help,
|
AC_ARG_ENABLE(help,
|
||||||
AS_HELP_STRING([--disable-help], [Disable the built-in help texts]))
|
AS_HELP_STRING([--disable-help], [Disable the built-in help texts]))
|
||||||
if test "x$enable_tiny" = xyes; then
|
if test "x$enable_tiny" = xyes; then
|
||||||
@ -205,7 +244,7 @@ if test "x$enable_libmagic" = xyes; then
|
|||||||
if test "x$enable_tiny" = xyes; then
|
if test "x$enable_tiny" = xyes; then
|
||||||
if test "x$enable_color" != xyes; then
|
if test "x$enable_color" != xyes; then
|
||||||
AC_MSG_ERROR([
|
AC_MSG_ERROR([
|
||||||
*** --enable-libmagic needs --enable-color and --enable-nanorc to work])
|
*** --enable-libmagic needs both --enable-color and --enable-nanorc to work])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if test "x$enable_color" = xno; then
|
if test "x$enable_color" = xno; then
|
||||||
@ -214,6 +253,30 @@ if test "x$enable_libmagic" = xyes; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(linter,
|
||||||
|
AS_HELP_STRING([--disable-linter], [Disable the linting tool]))
|
||||||
|
if test "x$enable_tiny" = xyes; then
|
||||||
|
if test "x$enable_linter" = xyes; then
|
||||||
|
if test "x$enable_color" != xyes; then
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
*** --enable-linter needs both --enable-color and --enable-nanorc to work])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
enable_linter=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "x$enable_color" = xno; then
|
||||||
|
if test "x$enable_linter" = xyes; then
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
*** --enable-linter cannot work with --disable-color nor --disable-nanorc])
|
||||||
|
else
|
||||||
|
enable_linter=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "x$enable_linter" != xno; then
|
||||||
|
AC_DEFINE(ENABLE_LINTER, 1, [Define this to have access to a linter.])
|
||||||
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(linenumbers,
|
AC_ARG_ENABLE(linenumbers,
|
||||||
AS_HELP_STRING([--disable-linenumbers], [Disable line numbering]))
|
AS_HELP_STRING([--disable-linenumbers], [Disable line numbering]))
|
||||||
if test "x$enable_tiny" = xyes; then
|
if test "x$enable_tiny" = xyes; then
|
||||||
@ -271,14 +334,14 @@ if test "x$enable_operatingdir" != xno; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(speller,
|
AC_ARG_ENABLE(speller,
|
||||||
AS_HELP_STRING([--disable-speller], [Disable the spell-checker functions]))
|
AS_HELP_STRING([--disable-speller], [Disable the spell-checking tool]))
|
||||||
if test "x$enable_tiny" = xyes; then
|
if test "x$enable_tiny" = xyes; then
|
||||||
if test "x$enable_speller" != xyes; then
|
if test "x$enable_speller" != xyes; then
|
||||||
enable_speller=no
|
enable_speller=no
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if test "x$enable_speller" != xno; then
|
if test "x$enable_speller" != xno; then
|
||||||
AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have the spell-checker functions.])
|
AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have access to a spell checker.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(tabcomp,
|
AC_ARG_ENABLE(tabcomp,
|
||||||
@ -353,6 +416,9 @@ if test "x$enable_utf8" != xno; then
|
|||||||
AC_CHECK_FUNCS(iswalpha iswalnum iswpunct mbstowcs wctomb)
|
AC_CHECK_FUNCS(iswalpha iswalnum iswpunct mbstowcs wctomb)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS_ONCE(chmod chown fchmod fchown flockfile funlockfile
|
||||||
|
fork fsync geteuid pipe wait waitpid)
|
||||||
|
|
||||||
dnl Checks for available flags.
|
dnl Checks for available flags.
|
||||||
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"], [], [])
|
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"], [], [])
|
||||||
@ -510,21 +576,6 @@ int main(void)
|
|||||||
*** Can't check need for _XOPEN_SOURCE_EXTENDED when cross-compiling.]))
|
*** Can't check need for _XOPEN_SOURCE_EXTENDED when cross-compiling.]))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether LINES and COLS can be redefined])
|
|
||||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
|
||||||
#include <curses.h>
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
LINES = 80;
|
|
||||||
COLS = 25;
|
|
||||||
return 0;
|
|
||||||
}]])],
|
|
||||||
AC_DEFINE(REDEFINING_MACROS_OK, 1, [Define this if you know your curses library allows LINES and COLS to be redefined to deal with a resizing bug.])
|
|
||||||
AC_MSG_RESULT(yes),
|
|
||||||
AC_MSG_RESULT(no),
|
|
||||||
AC_MSG_WARN([
|
|
||||||
*** Can't check for macro redefinability when cross-compiling.]))
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_libmagic" != "xno"], [
|
AS_IF([test "x$enable_libmagic" != "xno"], [
|
||||||
AC_CHECK_HEADERS([magic.h])
|
AC_CHECK_HEADERS([magic.h])
|
||||||
AC_CHECK_LIB(magic, magic_open)
|
AC_CHECK_LIB(magic, magic_open)
|
||||||
|
|||||||
@ -118,11 +118,11 @@
|
|||||||
<tr><td>Alt+A</td><td>Turn the mark on/off</td></tr>
|
<tr><td>Alt+A</td><td>Turn the mark on/off</td></tr>
|
||||||
<tr><td>Tab</td><td>Indent marked region</td></tr>
|
<tr><td>Tab</td><td>Indent marked region</td></tr>
|
||||||
<tr><td>Shift+Tab </td><td>Unindent marked region</td></tr>
|
<tr><td>Shift+Tab </td><td>Unindent marked region</td></tr>
|
||||||
|
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
|
||||||
<tr><td>Alt+N</td><td>Turn line numbers on/off</td></tr>
|
<tr><td>Alt+N</td><td>Turn line numbers on/off</td></tr>
|
||||||
<tr><td>Alt+P</td><td>Turn visible whitespace on/off</td></tr>
|
<tr><td>Alt+P</td><td>Turn visible whitespace on/off</td></tr>
|
||||||
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
|
<tr><td>Alt+X</td><td>Hide or unhide the help lines</td></tr>
|
||||||
<tr><td>Ctrl+L</td><td>Refresh the screen</td></tr>
|
<tr><td>Ctrl+L</td><td>Refresh the screen</td></tr>
|
||||||
<tr><td>Ctrl+Z</td><td>Suspend nano</td></tr>
|
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|||||||
20
doc/faq.html
20
doc/faq.html
@ -5,7 +5,7 @@
|
|||||||
<title>The GNU nano editor FAQ</title>
|
<title>The GNU nano editor FAQ</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<meta name="description" content="The genesis story of the nano editor, plus the solution to some common problems.">
|
<meta name="description" content="The genesis story of the nano editor, plus the solution to some common problems.">
|
||||||
<style>
|
<style type="text/css">
|
||||||
.indented { margin-left: 2em; font-family: courier; font-size: 110%; }
|
.indented { margin-left: 2em; font-family: courier; font-size: 110%; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<a href="#2.1">2.1. FTP and WWW sites that carry nano.</a><br>
|
<a href="#2.1">2.1. FTP and WWW sites that carry nano.</a><br>
|
||||||
<a href="#2.2">2.2. RedHat and derivatives (.rpm) packages.</a><br>
|
<a href="#2.2">2.2. RedHat and derivatives (.rpm) packages.</a><br>
|
||||||
<a href="#2.3">2.3. Debian (.deb) packages.</a><br>
|
<a href="#2.3">2.3. Debian (.deb) packages.</a><br>
|
||||||
<a href="#2.4">2.4. By GIT (for the brave).</a>
|
<a href="#2.4">2.4. By git (for the brave).</a>
|
||||||
</p></blockquote>
|
</p></blockquote>
|
||||||
<h3><a href="#3">3. Installation and Configuration</a></h3>
|
<h3><a href="#3">3. Installation and Configuration</a></h3>
|
||||||
<blockquote><p>
|
<blockquote><p>
|
||||||
@ -72,7 +72,7 @@
|
|||||||
<a href="#7.2">7.2. How do I submit a bug report or patch?</a><br>
|
<a href="#7.2">7.2. How do I submit a bug report or patch?</a><br>
|
||||||
<a href="#7.3">7.3. I want to send the development team a big load of cash (or just a thank you).</a><br>
|
<a href="#7.3">7.3. I want to send the development team a big load of cash (or just a thank you).</a><br>
|
||||||
<a href="#7.4">7.4. How do I join the development team?</a><br>
|
<a href="#7.4">7.4. How do I join the development team?</a><br>
|
||||||
<a href="#7.5">7.5. Can I have write access to the GIT tree?</a>
|
<a href="#7.5">7.5. Can I have write access to the git tree?</a>
|
||||||
</p></blockquote>
|
</p></blockquote>
|
||||||
<hr width="100%">
|
<hr width="100%">
|
||||||
|
|
||||||
@ -92,7 +92,7 @@
|
|||||||
<h3><a name="1.3"></a>1.3. Why the name change from TIP?</h3>
|
<h3><a name="1.3"></a>1.3. Why the name change from TIP?</h3>
|
||||||
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||||
<h3><a name="1.4"></a>1.4. What is the current version of nano?</h3>
|
<h3><a name="1.4"></a>1.4. What is the current version of nano?</h3>
|
||||||
<blockquote><p>The current version of nano <i>should</i> be <b>6.0</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
<blockquote><p>The current version of nano <i>should</i> be <b>7.2</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||||
<h3><a name="1.5"></a>1.5. I want to read the man page without having to download the program!</h3>
|
<h3><a name="1.5"></a>1.5. I want to read the man page without having to download the program!</h3>
|
||||||
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/latest/nano.1.html">here</a>.</p></blockquote>
|
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/latest/nano.1.html">here</a>.</p></blockquote>
|
||||||
<hr width="100%">
|
<hr width="100%">
|
||||||
@ -121,8 +121,8 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<p>You can also have a look at the <a href="http://ftp.debian.org/debian/pool/main/n/nano/">Package Pool</a> to see all the available binary and source packages.</p>
|
<p>You can also have a look at the <a href="http://ftp.debian.org/debian/pool/main/n/nano/">Package Pool</a> to see all the available binary and source packages.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<h3><a name="2.4"></a>2.4. By GIT (for the brave).</h3>
|
<h3><a name="2.4"></a>2.4. By git (for the brave).</h3>
|
||||||
<blockquote><p>For the 'bleeding edge' current version of nano, you can use GIT to download the current source code. <b>Note:</b> believe it or not, by downloading code that has not yet stabilized into an official release, there could quite possibly be bugs, in fact the code may not even compile! Anyway, see <a href="http://git.savannah.gnu.org/cgit/nano.git/tree/README.GIT">the nano GIT document</a> for info on anonymous GIT access to the nano source.</p></blockquote>
|
<blockquote><p>For the "bleeding edge" current version of nano, you can use <b>git</b> to download the current source code. <i>Note:</i> believe it or not, by downloading code that has not yet stabilized into an official release, there could quite possibly be bugs, in fact the code may not even compile! Anyway, see <a href="http://git.savannah.gnu.org/cgit/nano.git/tree/README.hacking">the hacking document</a> for info on getting and building nano from git.</p></blockquote>
|
||||||
<hr width="100%">
|
<hr width="100%">
|
||||||
|
|
||||||
<h1><a name="3"></a>3. Installation and Configuration</h1>
|
<h1><a name="3"></a>3. Installation and Configuration</h1>
|
||||||
@ -150,16 +150,18 @@
|
|||||||
<b>--disable-color</b> Disable color and syntax highlighting
|
<b>--disable-color</b> Disable color and syntax highlighting
|
||||||
<b>--disable-comment</b> Disable the comment/uncomment function
|
<b>--disable-comment</b> Disable the comment/uncomment function
|
||||||
<b>--disable-extra</b> Disable the easter egg
|
<b>--disable-extra</b> Disable the easter egg
|
||||||
|
<b>--disable-formatter</b> Disable the formatting tool
|
||||||
<b>--disable-help</b> Disable the built-in help texts
|
<b>--disable-help</b> Disable the built-in help texts
|
||||||
<b>--disable-histories</b> Disable the saving of search strings and cursor positions
|
<b>--disable-histories</b> Disable the saving of search strings and cursor positions
|
||||||
<b>--disable-justify</b> Disable the justify/unjustify functions
|
<b>--disable-justify</b> Disable the justify/unjustify functions
|
||||||
<b>--disable-libmagic</b> Disable the use of libmagic for determining a file's syntax
|
<b>--disable-libmagic</b> Disable the use of libmagic for determining a file's syntax
|
||||||
<b>--disable-linenumbers</b> Disable line numbering
|
<b>--disable-linenumbers</b> Disable line numbering
|
||||||
|
<b>--disable-linter</b> Disable the linting tool
|
||||||
<b>--disable-mouse</b> Disable mouse support
|
<b>--disable-mouse</b> Disable mouse support
|
||||||
<b>--disable-multibuffer</b> Disable the opening of multiple file buffers
|
<b>--disable-multibuffer</b> Disable the opening of multiple file buffers
|
||||||
<b>--disable-nanorc</b> Disable the use of .nanorc files
|
<b>--disable-nanorc</b> Disable the use of .nanorc files
|
||||||
<b>--disable-operatingdir</b> Disable the setting of an operating directory
|
<b>--disable-operatingdir</b> Disable the setting of an operating directory
|
||||||
<b>--disable-speller</b> Disable the spell-checker functions
|
<b>--disable-speller</b> Disable the spell-checking tool
|
||||||
<b>--disable-tabcomp</b> Disable the tab-completion functions
|
<b>--disable-tabcomp</b> Disable the tab-completion functions
|
||||||
<b>--disable-wordcomp</b> Disable the word-completion function
|
<b>--disable-wordcomp</b> Disable the word-completion function
|
||||||
<b>--disable-wrapping</b> Disable all hard-wrapping of text</pre>
|
<b>--disable-wrapping</b> Disable all hard-wrapping of text</pre>
|
||||||
@ -220,10 +222,10 @@
|
|||||||
<blockquote><p>Try holding down the Shift key and selecting or pasting the text as you normally would.</p></blockquote>
|
<blockquote><p>Try holding down the Shift key and selecting or pasting the text as you normally would.</p></blockquote>
|
||||||
<h3><a name="4.6"></a>4.6. When I paste text into a document, each line gets indented further than the last. Why? And how can I stop this?</h3>
|
<h3><a name="4.6"></a>4.6. When I paste text into a document, each line gets indented further than the last. Why? And how can I stop this?</h3>
|
||||||
<blockquote><p>You have the <i>autoindent</i> feature turned on. Hit <b>Meta-I</b> to turn it off, paste your text, and then hit <b>Meta-I</b> again to turn it back on.</p>
|
<blockquote><p>You have the <i>autoindent</i> feature turned on. Hit <b>Meta-I</b> to turn it off, paste your text, and then hit <b>Meta-I</b> again to turn it back on.</p>
|
||||||
<p><i>Update:</i> Since version 4.8, nano will suppress auto-indentation during a paste, so you no longer need to toggle it off and on manually.</p></blockquote>
|
<p><i>Update:</i> Since version 4.8, nano will suppress auto-indentation during a paste (when your terminal understands <a href="https://en.wikipedia.org/wiki/Bracketed-paste">bracketed pastes</a>), so you no longer need to toggle it off and on manually.</p></blockquote>
|
||||||
<h3><a name="4.7"></a>4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</h3>
|
<h3><a name="4.7"></a>4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</h3>
|
||||||
<blockquote><p>When pasting from Windows, in some situations linefeeds are sent instead of carriage returns (Enters). And linefeeds are <b>^J</b>s, which make nano justify (rewrap) the current paragraph. To prevent these linefeeds from causing these unwanted justifications, add this line to your .nanorc on the remote Linux box: <b>unbind ^J main</b> or <b>bind ^J enter main</b>, depending on whether the paste contains CR + LF or only LF.</p>
|
<blockquote><p>When pasting from Windows, in some situations linefeeds are sent instead of carriage returns (Enters). And linefeeds are <b>^J</b>s, which make nano justify (rewrap) the current paragraph. To prevent these linefeeds from causing these unwanted justifications, add this line to your .nanorc on the remote Linux box: <b>unbind ^J main</b> or <b>bind ^J enter main</b>, depending on whether the paste contains CR + LF or only LF.</p>
|
||||||
<p><i>Update:</i> Since version 4.8, nano will ignore linefeed characters in a paste, so you no longer need the above workaround.</p></blockquote>
|
<p><i>Update:</i> Since version 4.8, nano will ignore linefeed characters in a paste (when your terminal understands <a href="https://en.wikipedia.org/wiki/Bracketed-paste">bracketed pastes</a>), so you no longer need the above workaround.</p></blockquote>
|
||||||
<h3><a name="4.8"></a>4.8. I've compiled nano with color support, but I don't see any color when I run it!</h3>
|
<h3><a name="4.8"></a>4.8. I've compiled nano with color support, but I don't see any color when I run it!</h3>
|
||||||
<blockquote><p>If you want nano to actually use color, you have to specify the color configurations you want it to use in your .nanorc. Several example configurations are in the <b>syntax/</b> subdirectory of the nano source, which are normally installed to <b>/usr/local/share/nano/</b>. To enable all of them, uncomment the line <b># include "/usr/local/share/nano/*.nanorc"</b> in your nanorc. See also section <a href="#3.9">3.9</a>.</p></blockquote>
|
<blockquote><p>If you want nano to actually use color, you have to specify the color configurations you want it to use in your .nanorc. Several example configurations are in the <b>syntax/</b> subdirectory of the nano source, which are normally installed to <b>/usr/local/share/nano/</b>. To enable all of them, uncomment the line <b># include "/usr/local/share/nano/*.nanorc"</b> in your nanorc. See also section <a href="#3.9">3.9</a>.</p></blockquote>
|
||||||
<h3><a name="4.9"></a>4.9. How do I make nano my default editor (in Pine, mutt, etc.)?</h3>
|
<h3><a name="4.9"></a>4.9. How do I make nano my default editor (in Pine, mutt, etc.)?</h3>
|
||||||
|
|||||||
69
doc/nano.1
69
doc/nano.1
@ -1,4 +1,4 @@
|
|||||||
.\" Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
|
.\" Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc.
|
||||||
.\"
|
.\"
|
||||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||||
.\" under the terms of either of the following licenses:
|
.\" under the terms of either of the following licenses:
|
||||||
@ -16,19 +16,22 @@
|
|||||||
.\" Documentation License along with this program. If not, see
|
.\" Documentation License along with this program. If not, see
|
||||||
.\" <https://www.gnu.org/licenses/>.
|
.\" <https://www.gnu.org/licenses/>.
|
||||||
.\"
|
.\"
|
||||||
.TH NANO 1 "version 6.0" "December 2021"
|
.TH NANO 1 "version 7.2" "January 2023"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nano \- Nano's ANOther editor, inspired by Pico
|
nano \- Nano's ANOther text editor, inspired by Pico
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B nano
|
.B nano
|
||||||
.RI [ options "] [[\fB+" line [\fB, column "]] " file ]...
|
.RI [ options "] [[\fB+" line [\fB, column "]] " file ]...
|
||||||
.sp
|
.sp
|
||||||
.BR nano " [" \fIoptions "] [[" + [ crCR ]( / | ? ) \fIstring "] " \fIfile ]...
|
.B nano
|
||||||
|
.RI [ options "] [" file [\fB: line [\fB: column "]]]..."
|
||||||
|
.sp
|
||||||
|
.BR nano " [" \fIoptions "] [[" + [ crCR ]{ / | ? } \fIstring "] " \fIfile ]...
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBnano\fP is a small and friendly editor. It copies the look and feel
|
\fBnano\fP is a small and friendly text editor. It copies the look and feel
|
||||||
of Pico, but is free software, and implements several features that Pico
|
of Pico, but is free software, and implements several features that Pico
|
||||||
lacks, such as: opening multiple files, scrolling per line, undo/redo,
|
lacks, such as: opening multiple files, scrolling per line, undo/redo,
|
||||||
syntax coloring, line numbering, and soft-wrapping overlong lines.
|
syntax coloring, line numbering, and soft-wrapping overlong lines.
|
||||||
@ -36,7 +39,11 @@ syntax coloring, line numbering, and soft-wrapping overlong lines.
|
|||||||
When giving a filename on the command line, the cursor can be put on a
|
When giving a filename on the command line, the cursor can be put on a
|
||||||
specific line by adding the line number with a plus sign (\fB+\fR) before
|
specific line by adding the line number with a plus sign (\fB+\fR) before
|
||||||
the filename, and even in a specific column by adding it with a comma.
|
the filename, and even in a specific column by adding it with a comma.
|
||||||
(Negative numbers count from the end of the file or line.)
|
Negative numbers count from the end of the file or line.
|
||||||
|
The line and column numbers may also be specified by gluing them with colons
|
||||||
|
after the filename. (When a filename contains a colon followed by digits,
|
||||||
|
escape the colon by preceding it with a triple backslash.)
|
||||||
|
.sp
|
||||||
The cursor can be put on the first or last occurrence of a specific string
|
The cursor can be put on the first or last occurrence of a specific string
|
||||||
by specifying that string after \fB+/\fR or \fB+?\fR before the filename.
|
by specifying that string after \fB+/\fR or \fB+?\fR before the filename.
|
||||||
The string can be made case sensitive and/or caused to be interpreted as a
|
The string can be made case sensitive and/or caused to be interpreted as a
|
||||||
@ -74,25 +81,17 @@ using the arrow keys. Holding down the Ctrl or Alt key too will increase
|
|||||||
the stride.
|
the stride.
|
||||||
Any cursor movement without Shift being held will cancel such a selection.
|
Any cursor movement without Shift being held will cancel such a selection.
|
||||||
.sp
|
.sp
|
||||||
|
Any valid Unicode code point can be inserted into the buffer by typing
|
||||||
|
\fBM\-V\fR followed by the hexadecimal digits of the code point (concluded
|
||||||
|
with \fB<Space>\fR or \fB<Enter>\fR when it are fewer than six digits).
|
||||||
|
A literal control code (except \fB^J\fR) can be inserted by typing
|
||||||
|
\fBM\-V\fR followed by the pertinent keystroke.
|
||||||
|
.sp
|
||||||
The two lines at the bottom of the screen show some important commands;
|
The two lines at the bottom of the screen show some important commands;
|
||||||
the built-in help (\fB^G\fR) lists all the available ones.
|
the built-in help (\fB^G\fR) lists all the available ones.
|
||||||
The default key bindings can be changed via a \fInanorc\fR file -- see
|
The default key bindings can be changed via a \fInanorc\fR file -- see
|
||||||
.BR nanorc (5).
|
.BR nanorc (5).
|
||||||
|
|
||||||
.SH NOTICE
|
|
||||||
Since version 4.0, \fBnano\fR by default:
|
|
||||||
.sp
|
|
||||||
.RS 4
|
|
||||||
\(bu does not automatically hard-wrap lines that become overlong,
|
|
||||||
.br
|
|
||||||
\(bu includes the line below the title bar in the editing area,
|
|
||||||
.br
|
|
||||||
\(bu does linewise (smooth) scrolling.
|
|
||||||
.RE
|
|
||||||
.sp
|
|
||||||
If you want the old, Pico behavior back, you can use \fB\-\-breaklonglines\fR,
|
|
||||||
\fB\-\-emptyline\fR, and \fB\-\-jumpyscrolling\fR (or \fB\-bej\fR for short).
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BR \-A ", " \-\-smarthome
|
.BR \-A ", " \-\-smarthome
|
||||||
@ -120,6 +119,7 @@ nanorc file. See \fBnanorc\fR(5).
|
|||||||
.BR \-E ", " \-\-tabstospaces
|
.BR \-E ", " \-\-tabstospaces
|
||||||
Convert each typed tab to spaces -- to the number of spaces
|
Convert each typed tab to spaces -- to the number of spaces
|
||||||
that a tab at that position would take up.
|
that a tab at that position would take up.
|
||||||
|
(Note: pasted tabs are not converted.)
|
||||||
.TP
|
.TP
|
||||||
.BR \-F ", " \-\-multibuffer
|
.BR \-F ", " \-\-multibuffer
|
||||||
Read a file into a new buffer by default.
|
Read a file into a new buffer by default.
|
||||||
@ -309,7 +309,6 @@ using the built-in corrector that calls \fBhunspell\fR(1) or \fBspell\fR(1).
|
|||||||
.TP
|
.TP
|
||||||
.BR \-t ", " \-\-saveonexit
|
.BR \-t ", " \-\-saveonexit
|
||||||
Save a changed buffer without prompting (when exiting with \fB^X\fR).
|
Save a changed buffer without prompting (when exiting with \fB^X\fR).
|
||||||
(The old form of the long option, \fB\-\-tempfile\fR, is deprecated.)
|
|
||||||
.TP
|
.TP
|
||||||
.BR \-u ", " \-\-unix
|
.BR \-u ", " \-\-unix
|
||||||
Save a file by default in Unix format. This overrides nano's
|
Save a file by default in Unix format. This overrides nano's
|
||||||
@ -332,10 +331,9 @@ Don't show the two help lines at the bottom of the screen.
|
|||||||
.BR \-y ", " \-\-afterends
|
.BR \-y ", " \-\-afterends
|
||||||
Make Ctrl+Right and Ctrl+Delete stop at word ends instead of beginnings.
|
Make Ctrl+Right and Ctrl+Delete stop at word ends instead of beginnings.
|
||||||
.TP
|
.TP
|
||||||
.BR \-z ", " \-\-suspendable
|
.BR \-! ", " \-\-magic
|
||||||
Obsolete option; ignored. Suspension is enabled by default,
|
When neither the file's name nor its first line give a clue,
|
||||||
reachable via \fB^T^Z\fR. (If you want a plain \fB^Z\fR to
|
try using libmagic to determine the applicable syntax.
|
||||||
suspend nano, add \fBbind ^Z suspend main\fR to your nanorc.)
|
|
||||||
.TP
|
.TP
|
||||||
.BR \-% ", " \-\-stateflags
|
.BR \-% ", " \-\-stateflags
|
||||||
Use the top-right corner of the screen for showing some state flags:
|
Use the top-right corner of the screen for showing some state flags:
|
||||||
@ -359,7 +357,7 @@ the number of lines in the buffer is displayed after the filename.
|
|||||||
This number is cleared upon the next keystroke, or replaced with an
|
This number is cleared upon the next keystroke, or replaced with an
|
||||||
[i/n] counter when multiple buffers are open.
|
[i/n] counter when multiple buffers are open.
|
||||||
The line plus column numbers and the character code are displayed only when
|
The line plus column numbers and the character code are displayed only when
|
||||||
\fB\-\-constantshow\fR is used, and can be toggled on and off with \fBM-C\fR.
|
\fB\-\-constantshow\fR is used, and can be toggled on and off with \fBM\-C\fR.
|
||||||
The state flags are displayed only when \fB\-\-stateflags\fR is used.
|
The state flags are displayed only when \fB\-\-stateflags\fR is used.
|
||||||
.TP
|
.TP
|
||||||
.BR \-0 ", " \-\-zero
|
.BR \-0 ", " \-\-zero
|
||||||
@ -367,12 +365,8 @@ Hide all elements of the interface (title bar, status bar, and help lines)
|
|||||||
and use all rows of the terminal for showing the contents of the buffer.
|
and use all rows of the terminal for showing the contents of the buffer.
|
||||||
The status bar appears only when there is a significant message,
|
The status bar appears only when there is a significant message,
|
||||||
and disappears after 1.5 seconds or upon the next keystroke.
|
and disappears after 1.5 seconds or upon the next keystroke.
|
||||||
With \fBM-Z\fR the title bar plus status bar can be toggled.
|
With \fBM\-Z\fR the title bar plus status bar can be toggled.
|
||||||
With \fBM-X\fR the help lines.
|
With \fBM\-X\fR the help lines.
|
||||||
.TP
|
|
||||||
.BR \-! ", " \-\-magic
|
|
||||||
When neither the file's name nor its first line give a clue,
|
|
||||||
try using libmagic to determine the applicable syntax.
|
|
||||||
|
|
||||||
.SH TOGGLES
|
.SH TOGGLES
|
||||||
Several of the above options can be switched on and off also while
|
Several of the above options can be switched on and off also while
|
||||||
@ -400,6 +394,14 @@ See \fI/usr/share/nano/\fR and \fI/usr/share/nano/extra/\fR
|
|||||||
for available syntax-coloring definitions.
|
for available syntax-coloring definitions.
|
||||||
|
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
|
Option \fB\-z\fR (\fB\-\-suspendable\fR) has been removed.
|
||||||
|
Suspension is enabled by default, reachable via \fB^T^Z\fR.
|
||||||
|
(If you want a plain \fB^Z\fR to suspend nano, add
|
||||||
|
\fBbind ^Z suspend main\fR to your nanorc.)
|
||||||
|
.sp
|
||||||
|
When you want to copy marked text from \fBnano\fR to the system's clipboard,
|
||||||
|
see one of the examples in the \fBnanorc\fR(5) man page.
|
||||||
|
.sp
|
||||||
If no alternative spell checker command is specified on the command
|
If no alternative spell checker command is specified on the command
|
||||||
line nor in one of the \fInanorc\fP files, \fBnano\fP will check the
|
line nor in one of the \fInanorc\fP files, \fBnano\fP will check the
|
||||||
\fBSPELL\fP environment variable for one.
|
\fBSPELL\fP environment variable for one.
|
||||||
@ -413,6 +415,9 @@ that name already exists in the current directory, it will add ".save"
|
|||||||
plus a number (e.g.\& ".save.1") to the current filename in order to make
|
plus a number (e.g.\& ".save.1") to the current filename in order to make
|
||||||
it unique. In multibuffer mode, \fBnano\fP will write all the open
|
it unique. In multibuffer mode, \fBnano\fP will write all the open
|
||||||
buffers to their respective emergency files.
|
buffers to their respective emergency files.
|
||||||
|
.sp
|
||||||
|
If you have any question about how to use \fBnano\fR in some specific
|
||||||
|
situation, you can ask on \fIhelp-nano@gnu.org\fR.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
The recording and playback of keyboard macros works correctly only on a
|
The recording and playback of keyboard macros works correctly only on a
|
||||||
|
|||||||
168
doc/nano.texi
168
doc/nano.texi
@ -12,9 +12,9 @@ The complete manual for the GNU nano text editor.
|
|||||||
@end documentdescription
|
@end documentdescription
|
||||||
|
|
||||||
@smallbook
|
@smallbook
|
||||||
@set EDITION 0.6
|
@set EDITION 0.7
|
||||||
@set VERSION 6.0
|
@set VERSION 7.2
|
||||||
@set UPDATED December 2021
|
@set UPDATED January 2023
|
||||||
|
|
||||||
@dircategory Editors
|
@dircategory Editors
|
||||||
@direntry
|
@direntry
|
||||||
@ -29,18 +29,18 @@ The complete manual for the GNU nano text editor.
|
|||||||
|
|
||||||
@title GNU @command{nano}
|
@title GNU @command{nano}
|
||||||
@subtitle a small and friendly text editor
|
@subtitle a small and friendly text editor
|
||||||
@subtitle version 6.0
|
@subtitle version 7.2
|
||||||
|
|
||||||
@author Chris Allegretta
|
@author Chris Allegretta
|
||||||
|
|
||||||
@page
|
@page
|
||||||
|
|
||||||
This manual documents the GNU @command{nano} editor.
|
This manual documents the GNU @command{nano} text editor.
|
||||||
@sp 1
|
@sp 1
|
||||||
The contents of this manual are part of the GNU @command{nano} distribution.
|
The contents of this manual are part of the GNU @command{nano} distribution.
|
||||||
|
|
||||||
@sp 5
|
@sp 5
|
||||||
Copyright @copyright{} 1999-2009, 2014-2021 Free Software Foundation, Inc.
|
Copyright @copyright{} 1999-2009, 2014-2023 Free Software Foundation, Inc.
|
||||||
@sp 1
|
@sp 1
|
||||||
This document is dual-licensed. You may distribute and/or modify it
|
This document is dual-licensed. You may distribute and/or modify it
|
||||||
under the terms of either of the following licenses:
|
under the terms of either of the following licenses:
|
||||||
@ -58,6 +58,9 @@ under the terms of either of the following licenses:
|
|||||||
|
|
||||||
@sp 5
|
@sp 5
|
||||||
You may contact the original author by e-mail: @email{chrisa@@asty.org}
|
You may contact the original author by e-mail: @email{chrisa@@asty.org}
|
||||||
|
|
||||||
|
Or contact the current maintainer: @email{bensberg@@coevern.nl}
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
For suggesting improvements: @email{nano-devel@@gnu.org}
|
For suggesting improvements: @email{nano-devel@@gnu.org}
|
||||||
|
|
||||||
@ -76,7 +79,7 @@ For suggesting improvements: @email{nano-devel@@gnu.org}
|
|||||||
@node Top
|
@node Top
|
||||||
@top
|
@top
|
||||||
|
|
||||||
This manual documents GNU @command{nano}, version 6.0.
|
This manual documents GNU @command{nano}, version 7.2.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Introduction::
|
* Introduction::
|
||||||
@ -120,6 +123,9 @@ following options: @option{--breaklonglines},
|
|||||||
@blankline
|
@blankline
|
||||||
Please report bugs via @url{https://savannah.gnu.org/bugs/?group=nano}.
|
Please report bugs via @url{https://savannah.gnu.org/bugs/?group=nano}.
|
||||||
|
|
||||||
|
@blankline
|
||||||
|
Questions about using nano you can ask at @email{help-nano@@gnu.org}.
|
||||||
|
|
||||||
@blankline
|
@blankline
|
||||||
For background information see @url{https://nano-editor.org/}.
|
For background information see @url{https://nano-editor.org/}.
|
||||||
|
|
||||||
@ -136,12 +142,17 @@ The usual way to invoke @command{nano} is:
|
|||||||
@blankline
|
@blankline
|
||||||
|
|
||||||
But it is also possible to specify one or more options (@pxref{Command-line Options}),
|
But it is also possible to specify one or more options (@pxref{Command-line Options}),
|
||||||
and to edit several files in a row. Additionally, the cursor
|
and to edit several files in a row.
|
||||||
can be put on a specific line of a file by adding the line number
|
|
||||||
with a plus sign before the filename, and even in a specific column by
|
The cursor can be put on a specific line of a file by adding
|
||||||
adding it with a comma.
|
the line number with a plus sign before the filename, and even
|
||||||
(Negative numbers count from the end of the file or line.)
|
in a specific column by adding it with a comma.
|
||||||
The cursor can also be put on the first or last occurrence of a specific string
|
Negative numbers count from the end of the file or line.
|
||||||
|
The line and column numbers may also be specified by gluing them with colons
|
||||||
|
after the filename. (When a filename contains a colon followed by digits,
|
||||||
|
escape the colon by preceding it with a triple backslash.)
|
||||||
|
|
||||||
|
The cursor can be put on the first or last occurrence of a specific string
|
||||||
by specifying that string after @code{+/} or @code{+?} before the filename.
|
by specifying that string after @code{+/} or @code{+?} before the filename.
|
||||||
The string can be made case sensitive and/or caused to be interpreted as a
|
The string can be made case sensitive and/or caused to be interpreted as a
|
||||||
regular expression by inserting a @code{c} and/or @code{r} after the plus sign.
|
regular expression by inserting a @code{c} and/or @code{r} after the plus sign.
|
||||||
@ -152,7 +163,7 @@ A more complete command synopsis thus is:
|
|||||||
|
|
||||||
@blankline
|
@blankline
|
||||||
@example
|
@example
|
||||||
@code{nano [OPTION]@dots{} [[+LINE[,COLUMN]|+[crCR](/|?)STRING] FILE]@dots{}}
|
@code{nano [OPTION]@dots{} [[+LINE[,COLUMN]|+[crCR]@{/|?@}STRING] FILE]@dots{}}
|
||||||
@end example
|
@end example
|
||||||
@blankline
|
@blankline
|
||||||
|
|
||||||
@ -222,14 +233,18 @@ typed the key with that value.
|
|||||||
|
|
||||||
@item
|
@item
|
||||||
For any possible character, pressing @kbd{M-V} (Alt+V) and then typing a
|
For any possible character, pressing @kbd{M-V} (Alt+V) and then typing a
|
||||||
six-digit hexadecimal number (starting with @kbd{0} or @kbd{1}) will enter the
|
series of hexadecimal digits (at most six, or concluded with @kbd{Enter} or
|
||||||
corresponding Unicode character into the buffer.
|
@kbd{Space}) will enter the corresponding Unicode character into the buffer.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
For example, typing @kbd{Esc Esc 2 3 4} will enter the character "ê" ---
|
For example, typing @kbd{Esc Esc 2 3 4} will enter the character "ê" ---
|
||||||
useful when writing about a French party. Typing @kbd{M-V 0 0 2 2 c 4}
|
useful when writing about a French party. Typing @kbd{M-V 0 0 2 2 c 4}
|
||||||
will enter the symbol "⋄", a little diamond.
|
will enter the symbol "⋄", a little diamond.
|
||||||
|
|
||||||
|
Typing @kbd{M-V} followed by anything other than a hexadecimal digit
|
||||||
|
will enter this keystroke verbatim into the buffer, allowing the user
|
||||||
|
to insert literal control codes (except @code{^J}) or escape sequences.
|
||||||
|
|
||||||
@node Commands
|
@node Commands
|
||||||
@section Commands
|
@section Commands
|
||||||
|
|
||||||
@ -399,6 +414,7 @@ nanorc file. @xref{@code{set keycolor}} for details.
|
|||||||
@itemx --tabstospaces
|
@itemx --tabstospaces
|
||||||
Convert each typed tab to spaces --- to the number of spaces
|
Convert each typed tab to spaces --- to the number of spaces
|
||||||
that a tab at that position would take up.
|
that a tab at that position would take up.
|
||||||
|
(Note: pasted tabs are not converted.)
|
||||||
|
|
||||||
@item -F
|
@item -F
|
||||||
@itemx --multibuffer
|
@itemx --multibuffer
|
||||||
@ -636,7 +652,6 @@ to be installed.
|
|||||||
Save a changed buffer without prompting (when exiting with @kbd{^X}).
|
Save a changed buffer without prompting (when exiting with @kbd{^X}).
|
||||||
This can be handy when @command{nano} is used as the composer of an
|
This can be handy when @command{nano} is used as the composer of an
|
||||||
email program.
|
email program.
|
||||||
(The old form of the long option, @code{--tempfile}, is deprecated.)
|
|
||||||
|
|
||||||
@item -u
|
@item -u
|
||||||
@item --unix
|
@item --unix
|
||||||
@ -673,11 +688,10 @@ disabled to display the help-system navigation keys.
|
|||||||
Make @kbd{Ctrl+Right} and @kbd{Ctrl+Delete} stop at word ends
|
Make @kbd{Ctrl+Right} and @kbd{Ctrl+Delete} stop at word ends
|
||||||
instead of beginnings.
|
instead of beginnings.
|
||||||
|
|
||||||
@item -z
|
@item -!
|
||||||
@itemx --suspendable
|
@itemx --magic
|
||||||
Obsolete option; ignored. Suspension is enabled by default,
|
When neither the file's name nor its first line give a clue,
|
||||||
reachable via @kbd{^T^Z}. (If you want a plain @kbd{^Z} to
|
try using libmagic to determine the applicable syntax.
|
||||||
suspend nano, add @code{bind ^Z suspend main} to your nanorc.)
|
|
||||||
|
|
||||||
@item -%
|
@item -%
|
||||||
@itemx --stateflags
|
@itemx --stateflags
|
||||||
@ -715,13 +729,14 @@ and disappears after 1.5 seconds or upon the next keystroke.
|
|||||||
With @kbd{M-Z} the title bar plus status bar can be toggled.
|
With @kbd{M-Z} the title bar plus status bar can be toggled.
|
||||||
With @kbd{M-X} the help lines.
|
With @kbd{M-X} the help lines.
|
||||||
|
|
||||||
@item -!
|
|
||||||
@itemx --magic
|
|
||||||
When neither the file's name nor its first line give a clue,
|
|
||||||
try using libmagic to determine the applicable syntax.
|
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@sp 1
|
||||||
|
Option @code{-z} (@code{--suspendable}) has been removed.
|
||||||
|
Suspension is enabled by default, reachable via @kbd{^T^Z}.
|
||||||
|
(If you want a plain @kbd{^Z} to suspend nano, add
|
||||||
|
@code{bind ^Z suspend main} to your nanorc.)
|
||||||
|
|
||||||
|
|
||||||
@node Feature Toggles
|
@node Feature Toggles
|
||||||
@chapter Feature Toggles
|
@chapter Feature Toggles
|
||||||
@ -732,6 +747,7 @@ or nanorc options. Each toggle can be flicked via a Meta-key combination
|
|||||||
--- the @kbd{Meta} key is normally the @kbd{Alt} key (@pxref{Commands}
|
--- the @kbd{Meta} key is normally the @kbd{Alt} key (@pxref{Commands}
|
||||||
for more details). The following global toggles are available:
|
for more details). The following global toggles are available:
|
||||||
|
|
||||||
|
@sp 1
|
||||||
@table @code
|
@table @code
|
||||||
|
|
||||||
@item Constant Cursor Position Display
|
@item Constant Cursor Position Display
|
||||||
@ -1073,7 +1089,6 @@ Regular expressions in @command{nano} are of the extended type (ERE).
|
|||||||
|
|
||||||
@item set saveonexit
|
@item set saveonexit
|
||||||
Save a changed buffer automatically on exit (@kbd{^X}); don't prompt.
|
Save a changed buffer automatically on exit (@kbd{^X}); don't prompt.
|
||||||
(The old form of this option, @code{set tempfile}, is deprecated.)
|
|
||||||
|
|
||||||
@item set scrollercolor @var{fgcolor},@var{bgcolor}
|
@item set scrollercolor @var{fgcolor},@var{bgcolor}
|
||||||
Use this color combination for the indicator alias "scrollbar".
|
Use this color combination for the indicator alias "scrollbar".
|
||||||
@ -1127,11 +1142,6 @@ Use this color combination for the status bar.
|
|||||||
Use this color combination for the vertical guiding stripe.
|
Use this color combination for the vertical guiding stripe.
|
||||||
@xref{@code{set keycolor}} for valid color names.
|
@xref{@code{set keycolor}} for valid color names.
|
||||||
|
|
||||||
@item set suspendable
|
|
||||||
Obsolete option; ignored. Suspension is enabled by default,
|
|
||||||
reachable via @kbd{^T^Z}. (If you want a plain @kbd{^Z} to
|
|
||||||
suspend nano, add @code{bind ^Z suspend main} to your nanorc.)
|
|
||||||
|
|
||||||
@item set tabsize @var{number}
|
@item set tabsize @var{number}
|
||||||
Use a tab size of @var{number} columns. The value of @var{number} must be
|
Use a tab size of @var{number} columns. The value of @var{number} must be
|
||||||
greater than 0. The default value is @t{8}.
|
greater than 0. The default value is @t{8}.
|
||||||
@ -1139,6 +1149,7 @@ greater than 0. The default value is @t{8}.
|
|||||||
@item set tabstospaces
|
@item set tabstospaces
|
||||||
Convert each typed tab to spaces --- to the number of spaces
|
Convert each typed tab to spaces --- to the number of spaces
|
||||||
that a tab at that position would take up.
|
that a tab at that position would take up.
|
||||||
|
(Note: pasted tabs are not converted.)
|
||||||
|
|
||||||
@item set titlecolor [bold,][italic,]@var{fgcolor},@var{bgcolor}
|
@item set titlecolor [bold,][italic,]@var{fgcolor},@var{bgcolor}
|
||||||
Use this color combination for the title bar.
|
Use this color combination for the title bar.
|
||||||
@ -1209,6 +1220,14 @@ It also means that lookahead and lookbehind are not possible.
|
|||||||
A complete explanation can be found in the manual of GNU grep:
|
A complete explanation can be found in the manual of GNU grep:
|
||||||
@code{info grep regular}.
|
@code{info grep regular}.
|
||||||
|
|
||||||
|
Each regular expression in a @file{nanorc} file should be wrapped in
|
||||||
|
double quotes (@code{""}). Multiple regular expressions can follow
|
||||||
|
each other on a line by separating them with blanks. This means that
|
||||||
|
a regular expression cannot contain a double quote followed by a blank.
|
||||||
|
When you need this combination inside a regular expression,
|
||||||
|
then either the double quote or the blank should be put
|
||||||
|
between square brackets (@code{[]}).
|
||||||
|
|
||||||
A separate syntax can be defined for each kind of file
|
A separate syntax can be defined for each kind of file
|
||||||
via the following commands in a nanorc file:
|
via the following commands in a nanorc file:
|
||||||
|
|
||||||
@ -1221,9 +1240,10 @@ will be added to this syntax, until a new @code{syntax}
|
|||||||
command is encountered.
|
command is encountered.
|
||||||
|
|
||||||
When @command{nano} is run, this syntax will be automatically
|
When @command{nano} is run, this syntax will be automatically
|
||||||
activated if the current filename matches the extended regular
|
activated (for the relevant buffer) if the absolute filename
|
||||||
expression @var{fileregex}. Or the syntax can be explicitly
|
matches the extended regular expression @var{fileregex}.
|
||||||
activated by using the @option{-Y} or @option{--syntax}
|
Or the syntax can be explicitly activated (for all buffers)
|
||||||
|
by using the @option{-Y} or @option{--syntax}
|
||||||
command-line option followed by the @var{name}.
|
command-line option followed by the @var{name}.
|
||||||
|
|
||||||
The @code{default} syntax is special: it takes no @var{fileregex},
|
The @code{default} syntax is special: it takes no @var{fileregex},
|
||||||
@ -1246,9 +1266,6 @@ on the system and will be silently ignored otherwise.)
|
|||||||
|
|
||||||
@item formatter @var{program} [@var{argument} @dots{}]
|
@item formatter @var{program} [@var{argument} @dots{}]
|
||||||
Run the given @var{program} on the full contents of the current buffer.
|
Run the given @var{program} on the full contents of the current buffer.
|
||||||
(The current buffer is written out to a temporary file, the program is
|
|
||||||
run on it, and then the temporary file is read back in, replacing the
|
|
||||||
contents of the buffer.)
|
|
||||||
|
|
||||||
@item linter @var{program} [@var{argument} @dots{}]
|
@item linter @var{program} [@var{argument} @dots{}]
|
||||||
Use the given @var{program} to do a syntax check on the current buffer.
|
Use the given @var{program} to do a syntax check on the current buffer.
|
||||||
@ -1347,9 +1364,9 @@ Rebinds @code{key} to @code{function} in the context of @code{menu}
|
|||||||
@item bind key "string" menu
|
@item bind key "string" menu
|
||||||
Makes @code{key} produce @code{string} in the context of @code{menu}
|
Makes @code{key} produce @code{string} in the context of @code{menu}
|
||||||
(or in all menus where the key exists when @code{all} is used).
|
(or in all menus where the key exists when @code{all} is used).
|
||||||
The @code{string} can consist of text or commands or a mix of them.
|
Besides literal text and/or control codes, the @code{string} may contain
|
||||||
(To enter a command into the @code{string}, precede its keystroke
|
function names between braces. These functions will be invoked when the
|
||||||
with @kbd{M-V}.)
|
key is typed. To include a literal opening brace, use @code{@{@{@}}.
|
||||||
|
|
||||||
@item unbind key menu
|
@item unbind key menu
|
||||||
Unbinds @code{key} from @code{menu}
|
Unbinds @code{key} from @code{menu}
|
||||||
@ -1357,37 +1374,50 @@ Unbinds @code{key} from @code{menu}
|
|||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
Note that @code{bind key "@{function@}" menu} is equivalent to
|
||||||
|
@code{bind key function menu}, except that for the latter form
|
||||||
|
@command{nano} will check the availability of the @code{function}
|
||||||
|
in the given @code{menu} at startup time (and report an error if
|
||||||
|
it does not exist there), whereas for the first form @command{nano}
|
||||||
|
will check at execution time that the @code{function} exists but not
|
||||||
|
whether it makes any sense in the current menu. The user has to take
|
||||||
|
care that a function name between braces (or any sequence of them)
|
||||||
|
is appropriate. Strange behavior can result when it is not.
|
||||||
|
|
||||||
@sp 1
|
@sp 1
|
||||||
The format of @code{key} should be one of:
|
The format of @code{key} should be one of:
|
||||||
|
|
||||||
@itemize @w{}
|
@indentedblock
|
||||||
@item
|
@table @asis
|
||||||
@code{^@var{X}} ------ where @var{X} is a Latin letter, or one of several
|
|
||||||
|
@item @code{^@var{X}}
|
||||||
|
where @var{X} is a Latin letter, or one of several
|
||||||
ASCII characters (@@, ], \, ^, _), or the word "Space".
|
ASCII characters (@@, ], \, ^, _), or the word "Space".
|
||||||
Example: @code{^C}.
|
Example: @code{^C}.
|
||||||
|
|
||||||
@item
|
@item @code{M-@var{X}}
|
||||||
@code{M-@var{X}} ------ where @var{X} is any ASCII character except [,
|
where @var{X} is any ASCII character except [, or the word "Space".
|
||||||
or the word "Space".
|
|
||||||
Example: @code{M-8}.
|
Example: @code{M-8}.
|
||||||
|
|
||||||
@item
|
@item @code{Sh-M-@var{X}}
|
||||||
@code{Sh-M-@var{X}} ------ where @var{X} is a Latin letter.
|
where @var{X} is a Latin letter.
|
||||||
Example: @code{Sh-M-U}.
|
Example: @code{Sh-M-U}.
|
||||||
By default, each Meta+letter keystroke does the same as the corresponding
|
By default, each Meta+letter keystroke does the same as the corresponding
|
||||||
Shift+Meta+letter. But when any Shift+Meta bind is made, that will
|
Shift+Meta+letter. But when any Shift+Meta bind is made, that will
|
||||||
no longer be the case, for all letters.
|
no longer be the case, for all letters.
|
||||||
|
|
||||||
@item
|
@item @code{F@var{n}}
|
||||||
@code{F@var{n}} ------ where @var{n} is a numeric value from 1 to 24.
|
where @var{n} is a numeric value from 1 to 24.
|
||||||
Example: @code{F10}.
|
Example: @code{F10}.
|
||||||
(Often, @code{F13} to @code{F24} can be typed as @code{F1} to @code{F12}
|
(Often, @code{F13} to @code{F24} can be typed as @code{F1} to @code{F12}
|
||||||
with Shift.)
|
with Shift.)
|
||||||
|
|
||||||
@item
|
@item @code{Ins} or @code{Del}
|
||||||
@code{Ins} or @code{Del}.
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
|
@end table
|
||||||
|
@end indentedblock
|
||||||
|
|
||||||
|
@sp 1
|
||||||
Rebinding @code{^M} (Enter) or @code{^I} (Tab) is probably not a good idea.
|
Rebinding @code{^M} (Enter) or @code{^I} (Tab) is probably not a good idea.
|
||||||
Rebinding @code{^[} (Esc) is not possible, because its keycode
|
Rebinding @code{^[} (Esc) is not possible, because its keycode
|
||||||
is the starter byte of Meta keystrokes and escape sequences.
|
is the starter byte of Meta keystrokes and escape sequences.
|
||||||
@ -1471,7 +1501,6 @@ Or, when it is set, unsets the mark.
|
|||||||
@item location
|
@item location
|
||||||
Reports the current position of the cursor in the buffer:
|
Reports the current position of the cursor in the buffer:
|
||||||
the line, column, and character positions.
|
the line, column, and character positions.
|
||||||
(The old name of this function, 'curpos', is deprecated.)
|
|
||||||
|
|
||||||
@item wordcount
|
@item wordcount
|
||||||
Counts and reports on the status bar the number of lines, words,
|
Counts and reports on the status bar the number of lines, words,
|
||||||
@ -1488,15 +1517,23 @@ or GNU @command{spell}, or the one defined by @option{--speller} or
|
|||||||
|
|
||||||
@item formatter
|
@item formatter
|
||||||
Invokes a full-buffer-processing program (if the active syntax defines one).
|
Invokes a full-buffer-processing program (if the active syntax defines one).
|
||||||
|
(The current buffer is written out to a temporary file, the program
|
||||||
|
is run on it, and then the temporary file is read back in, replacing
|
||||||
|
the contents of the buffer.)
|
||||||
|
|
||||||
@item linter
|
@item linter
|
||||||
Invokes a syntax-checking program (if the active syntax defines one).
|
Invokes a syntax-checking program (if the active syntax defines one).
|
||||||
|
If this program produces lines of the form "filename:linenum:charnum:
|
||||||
|
some message", then the cursor will be put at the indicated position
|
||||||
|
in the mentioned file while showing "some message" on the status bar.
|
||||||
|
You can move from message to message with @kbd{PgUp} and @kbd{PgDn},
|
||||||
|
and leave linting mode with @kbd{^C} or @kbd{Enter}.
|
||||||
|
|
||||||
@item justify
|
@item justify
|
||||||
Justifies the current paragraph (or the marked region).
|
Justifies the current paragraph (or the marked region).
|
||||||
A paragraph is a group of contiguous lines
|
A paragraph is a group of contiguous lines that, apart from possibly
|
||||||
that, apart from possibly the first line, all have the same indentation. The
|
the first line, all have the same indentation. The beginning of a
|
||||||
beginning of a paragraph is detected by either this lone line with a differing
|
paragraph is detected by either this lone line with a differing
|
||||||
indentation or by a preceding blank line.
|
indentation or by a preceding blank line.
|
||||||
|
|
||||||
@item fulljustify
|
@item fulljustify
|
||||||
@ -1605,7 +1642,8 @@ Switches to editing/viewing the previous buffer when multiple buffers are open.
|
|||||||
Switches to editing/viewing the next buffer when multiple buffers are open.
|
Switches to editing/viewing the next buffer when multiple buffers are open.
|
||||||
|
|
||||||
@item verbatim
|
@item verbatim
|
||||||
Inserts the next keystroke verbatim into the file.
|
Inserts the next keystroke verbatim into the file, or begins Unicode input
|
||||||
|
when a hexadecimal digit is typed (@pxref{Entering Text} for details).
|
||||||
|
|
||||||
@item tab
|
@item tab
|
||||||
Inserts a tab at the current cursor location.
|
Inserts a tab at the current cursor location.
|
||||||
@ -1715,6 +1753,9 @@ Toggles the presence of the two-line list of key bindings at the bottom of the s
|
|||||||
(This toggle is special: it is available in all menus except the help viewer
|
(This toggle is special: it is available in all menus except the help viewer
|
||||||
and the linter. All further toggles are available in the main menu only.)
|
and the linter. All further toggles are available in the main menu only.)
|
||||||
|
|
||||||
|
@item zero
|
||||||
|
Toggles the presence of title bar and status bar.
|
||||||
|
|
||||||
@item constantshow
|
@item constantshow
|
||||||
Toggles the constant display of the current line, column, and character positions.
|
Toggles the constant display of the current line, column, and character positions.
|
||||||
|
|
||||||
@ -1800,7 +1841,6 @@ The 'go to directory' menu in the file browser.
|
|||||||
The menu for inserting the output from an external command,
|
The menu for inserting the output from an external command,
|
||||||
or for filtering the buffer (or the marked region) through
|
or for filtering the buffer (or the marked region) through
|
||||||
an external command, or for executing one of several tools.
|
an external command, or for executing one of several tools.
|
||||||
(The old form of this menu name, 'extcmd', is deprecated.)
|
|
||||||
|
|
||||||
@item spell
|
@item spell
|
||||||
The menu of the integrated spell checker where the user can edit a misspelled word.
|
The menu of the integrated spell checker where the user can edit a misspelled word.
|
||||||
@ -1943,6 +1983,9 @@ Exclude the single-keystroke comment/uncomment function (@w{@kbd{M-3}}).
|
|||||||
@item --disable-extra
|
@item --disable-extra
|
||||||
Exclude the Easter egg: a crawl of major contributors.
|
Exclude the Easter egg: a crawl of major contributors.
|
||||||
|
|
||||||
|
@item --disable-formatter
|
||||||
|
Exclude the code for calling a formatting tool.
|
||||||
|
|
||||||
@item --disable-help
|
@item --disable-help
|
||||||
Exclude the help texts (@kbd{^G}). This makes the binary much smaller,
|
Exclude the help texts (@kbd{^G}). This makes the binary much smaller,
|
||||||
but also makes it difficult for new users to learn more than very basic
|
but also makes it difficult for new users to learn more than very basic
|
||||||
@ -1968,6 +2011,9 @@ in most cases the regexes for filename and header line will be enough).
|
|||||||
Exclude the ability to show line numbers. This also eliminates
|
Exclude the ability to show line numbers. This also eliminates
|
||||||
the @option{-l} command-line option, which turns line numbering on.
|
the @option{-l} command-line option, which turns line numbering on.
|
||||||
|
|
||||||
|
@item --disable-linter
|
||||||
|
Exclude the code for calling a linting tool.
|
||||||
|
|
||||||
@item --disable-mouse
|
@item --disable-mouse
|
||||||
Exclude all mouse functionality. This also eliminates the @option{-m}
|
Exclude all mouse functionality. This also eliminates the @option{-m}
|
||||||
command-line option, which enables the mouse functionality.
|
command-line option, which enables the mouse functionality.
|
||||||
|
|||||||
106
doc/nanorc.5
106
doc/nanorc.5
@ -1,4 +1,4 @@
|
|||||||
.\" Copyright (C) 2003-2011, 2013-2021 Free Software Foundation, Inc.
|
.\" Copyright (C) 2003-2011, 2013-2023 Free Software Foundation, Inc.
|
||||||
.\"
|
.\"
|
||||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||||
.\" under the terms of either of the following licenses:
|
.\" under the terms of either of the following licenses:
|
||||||
@ -16,14 +16,14 @@
|
|||||||
.\" Documentation License along with this program. If not, see
|
.\" Documentation License along with this program. If not, see
|
||||||
.\" <https://www.gnu.org/licenses/>.
|
.\" <https://www.gnu.org/licenses/>.
|
||||||
.\"
|
.\"
|
||||||
.TH NANORC 5 "version 6.0" "December 2021"
|
.TH NANORC 5 "version 7.2" "January 2023"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nanorc \- GNU nano's configuration file
|
nanorc \- GNU nano's configuration file
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The \fInanorc\fP files contain the default settings for \fBnano\fP,
|
The \fInanorc\fP files contain the default settings for \fBnano\fP,
|
||||||
a small and friendly editor. During startup, if \fB\-\-rcfile\fR
|
a small and friendly text editor. During startup, if \fB\-\-rcfile\fR
|
||||||
is not given, \fBnano\fR will read two files: first the
|
is not given, \fBnano\fR will read two files: first the
|
||||||
system-wide settings, from \fI/etc/nanorc\fP (the exact path might be
|
system-wide settings, from \fI/etc/nanorc\fP (the exact path might be
|
||||||
different on your system), and then the user-specific settings, either
|
different on your system), and then the user-specific settings, either
|
||||||
@ -32,20 +32,6 @@ or from \fI~/.config/nano/nanorc\fR, whichever is encountered first.
|
|||||||
If \fB\-\-rcfile\fR is given, \fBnano\fR will read just the specified
|
If \fB\-\-rcfile\fR is given, \fBnano\fR will read just the specified
|
||||||
settings file.
|
settings file.
|
||||||
|
|
||||||
.SH NOTICE
|
|
||||||
Since version 4.0, \fBnano\fR by default:
|
|
||||||
.sp
|
|
||||||
.RS 4
|
|
||||||
\(bu does not automatically hard-wrap lines that become overlong,
|
|
||||||
.br
|
|
||||||
\(bu includes the line below the title bar in the editing area,
|
|
||||||
.br
|
|
||||||
\(bu does linewise (smooth) scrolling.
|
|
||||||
.RE
|
|
||||||
.sp
|
|
||||||
To get the old, Pico behavior back, you can use \fBset breaklonglines\fR,
|
|
||||||
\fBset emptyline\fR, and \fBset jumpyscrolling\fR.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
The configuration file accepts a series of \fBset\fP and \fBunset\fP
|
The configuration file accepts a series of \fBset\fP and \fBunset\fP
|
||||||
commands, which can be used to configure nano on startup without using
|
commands, which can be used to configure nano on startup without using
|
||||||
@ -196,7 +182,7 @@ the number of lines in the buffer is displayed after the filename.
|
|||||||
This number is cleared upon the next keystroke, or replaced with an
|
This number is cleared upon the next keystroke, or replaced with an
|
||||||
[i/n] counter when multiple buffers are open.
|
[i/n] counter when multiple buffers are open.
|
||||||
The line plus column numbers and the character code are displayed only when
|
The line plus column numbers and the character code are displayed only when
|
||||||
\fBset constantshow\fR is used, and can be toggled on and off with \fBM-C\fR.
|
\fBset constantshow\fR is used, and can be toggled on and off with \fBM\-C\fR.
|
||||||
The state flags are displayed only when \fBset stateflags\fR is used.
|
The state flags are displayed only when \fBset stateflags\fR is used.
|
||||||
.TP
|
.TP
|
||||||
.B set minicolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
.B set minicolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
||||||
@ -289,7 +275,6 @@ Regular expressions in \fBnano\fR are of the extended type (ERE).
|
|||||||
.TP
|
.TP
|
||||||
.B set saveonexit
|
.B set saveonexit
|
||||||
Save a changed buffer automatically on exit (\fB^X\fR); don't prompt.
|
Save a changed buffer automatically on exit (\fB^X\fR); don't prompt.
|
||||||
(The old form of this option, \fBset tempfile\fR, is deprecated.)
|
|
||||||
.TP
|
.TP
|
||||||
.B set scrollercolor \fIfgcolor\fB,\fIbgcolor\fR
|
.B set scrollercolor \fIfgcolor\fB,\fIbgcolor\fR
|
||||||
Use this color combination for the indicator alias "scrollbar".
|
Use this color combination for the indicator alias "scrollbar".
|
||||||
@ -335,7 +320,7 @@ and \fBS\fR when soft-wrapping.
|
|||||||
When the buffer is modified, a star (\fB*\fR) is shown after the
|
When the buffer is modified, a star (\fB*\fR) is shown after the
|
||||||
filename in the center of the title bar.
|
filename in the center of the title bar.
|
||||||
.TP
|
.TP
|
||||||
.B set statuscolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
.B set statuscolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
||||||
Use this color combination for the status bar.
|
Use this color combination for the status bar.
|
||||||
See \fBset titlecolor\fR for more details.
|
See \fBset titlecolor\fR for more details.
|
||||||
.TP
|
.TP
|
||||||
@ -343,11 +328,6 @@ See \fBset titlecolor\fR for more details.
|
|||||||
Use this color combination for the vertical guiding stripe.
|
Use this color combination for the vertical guiding stripe.
|
||||||
See \fBset titlecolor\fR for more details.
|
See \fBset titlecolor\fR for more details.
|
||||||
.TP
|
.TP
|
||||||
.B set suspendable
|
|
||||||
Obsolete option; ignored. Suspension is enabled by default,
|
|
||||||
reachable via \fB^T^Z\fR. (If you want a plain \fB^Z\fR to
|
|
||||||
suspend nano, add \fBbind ^Z suspend main\fR to your nanorc.)
|
|
||||||
.TP
|
|
||||||
.B set tabsize \fInumber\fR
|
.B set tabsize \fInumber\fR
|
||||||
Use a tab size of \fInumber\fR columns. The value of \fInumber\fP must be
|
Use a tab size of \fInumber\fR columns. The value of \fInumber\fP must be
|
||||||
greater than 0. The default value is \fB8\fR.
|
greater than 0. The default value is \fB8\fR.
|
||||||
@ -355,6 +335,7 @@ greater than 0. The default value is \fB8\fR.
|
|||||||
.B set tabstospaces
|
.B set tabstospaces
|
||||||
Convert each typed tab to spaces -- to the number of spaces
|
Convert each typed tab to spaces -- to the number of spaces
|
||||||
that a tab at that position would take up.
|
that a tab at that position would take up.
|
||||||
|
(Note: pasted tabs are not converted.)
|
||||||
.TP
|
.TP
|
||||||
.B set titlecolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
.B set titlecolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
||||||
Use this color combination for the title bar.
|
Use this color combination for the title bar.
|
||||||
@ -415,8 +396,8 @@ Hide all elements of the interface (title bar, status bar, and help lines)
|
|||||||
and use all rows of the terminal for showing the contents of the buffer.
|
and use all rows of the terminal for showing the contents of the buffer.
|
||||||
The status bar appears only when there is a significant message,
|
The status bar appears only when there is a significant message,
|
||||||
and disappears after 1.5 seconds or upon the next keystroke.
|
and disappears after 1.5 seconds or upon the next keystroke.
|
||||||
With \fBM-Z\fR the title bar plus status bar can be toggled.
|
With \fBM\-Z\fR the title bar plus status bar can be toggled.
|
||||||
With \fBM-X\fR the help lines.
|
With \fBM\-X\fR the help lines.
|
||||||
|
|
||||||
.SH SYNTAX HIGHLIGHTING
|
.SH SYNTAX HIGHLIGHTING
|
||||||
Coloring the different syntactic elements of a file
|
Coloring the different syntactic elements of a file
|
||||||
@ -440,6 +421,14 @@ It also means that lookahead and lookbehind are not possible.
|
|||||||
A complete explanation can be found in the manual page of GNU grep:
|
A complete explanation can be found in the manual page of GNU grep:
|
||||||
\fBman grep\fR.
|
\fBman grep\fR.
|
||||||
.sp
|
.sp
|
||||||
|
Each regular expression in a \fBnanorc\fR file should be wrapped in
|
||||||
|
double quotes (\fB""\fR). Multiple regular expressions can follow
|
||||||
|
each other on a line by separating them with blanks. This means that
|
||||||
|
a regular expression cannot contain a double quote followed by a blank.
|
||||||
|
When you need this combination inside a regular expression,
|
||||||
|
then either the double quote or the blank should be put
|
||||||
|
between square brackets (\fB[]\fR).
|
||||||
|
.sp
|
||||||
For each kind of file a separate syntax can be defined
|
For each kind of file a separate syntax can be defined
|
||||||
via the following commands:
|
via the following commands:
|
||||||
.TP
|
.TP
|
||||||
@ -450,9 +439,10 @@ will be added to this syntax, until a new \fBsyntax\fR
|
|||||||
command is encountered.
|
command is encountered.
|
||||||
.sp
|
.sp
|
||||||
When \fBnano\fR is run, this syntax will be automatically
|
When \fBnano\fR is run, this syntax will be automatically
|
||||||
activated if the current filename matches the extended regular
|
activated (for the relevant buffer) if the absolute filename
|
||||||
expression \fIfileregex\fR. Or the syntax can be explicitly
|
matches the extended regular expression \fIfileregex\fR.
|
||||||
activated by using the \fB\-Y\fR or \fB\-\-syntax\fR
|
Or the syntax can be explicitly activated (for all buffers)
|
||||||
|
by using the \fB\-Y\fR or \fB\-\-syntax\fR
|
||||||
command-line option followed by the \fIname\fR.
|
command-line option followed by the \fIname\fR.
|
||||||
.sp
|
.sp
|
||||||
The syntax \fBdefault\fP is special: it takes no \fIfileregex\fR,
|
The syntax \fBdefault\fP is special: it takes no \fIfileregex\fR,
|
||||||
@ -475,9 +465,6 @@ system and will be silently ignored otherwise.)
|
|||||||
.TP
|
.TP
|
||||||
.BI formatter " program " \fR[ "argument " \fR...]
|
.BI formatter " program " \fR[ "argument " \fR...]
|
||||||
Run the given \fIprogram\fR on the full contents of the current buffer.
|
Run the given \fIprogram\fR on the full contents of the current buffer.
|
||||||
(The current buffer is written out to a temporary file, the program is
|
|
||||||
run on it, and then the temporary file is read back in, replacing the
|
|
||||||
contents of the buffer.)
|
|
||||||
.TP
|
.TP
|
||||||
.BI linter " program " \fR[ "argument " \fR...]
|
.BI linter " program " \fR[ "argument " \fR...]
|
||||||
Use the given \fIprogram\fR to run a syntax check on the current buffer.
|
Use the given \fIprogram\fR to run a syntax check on the current buffer.
|
||||||
@ -568,14 +555,23 @@ Rebinds the given \fIkey\fP to the given \fIfunction\fP in the given \fImenu\fP
|
|||||||
.BI bind " key " """" string """" " menu"
|
.BI bind " key " """" string """" " menu"
|
||||||
Makes the given \fIkey\fR produce the given \fIstring\fR in the given
|
Makes the given \fIkey\fR produce the given \fIstring\fR in the given
|
||||||
\fImenu\fR (or in all menus where the key exists when \fBall\fR is used).
|
\fImenu\fR (or in all menus where the key exists when \fBall\fR is used).
|
||||||
The \fIstring\fR can consist of text or commands or a mix of them.
|
Besides literal text and/or control codes, the \fIstring\fR may contain
|
||||||
(To enter a command into the \fIstring\fR, precede its keystroke
|
function names between braces. These functions will be invoked when
|
||||||
with \fBM\-V\fR.)
|
the key is typed. To include a literal opening brace, use \fB{{}\fR.
|
||||||
.TP
|
.TP
|
||||||
.BI unbind " key menu"
|
.BI unbind " key menu"
|
||||||
Unbinds the given \fIkey\fP from the given \fImenu\fP (or from all
|
Unbinds the given \fIkey\fP from the given \fImenu\fP (or from all
|
||||||
menus where the key exists when \fBall\fP is used).
|
menus where the key exists when \fBall\fP is used).
|
||||||
.RE
|
.RE
|
||||||
|
.sp
|
||||||
|
Note that \fBbind \fIkey\fR \fB"{\fIfunction\fB}"\fR \fImenu\fR is equivalent
|
||||||
|
to \fBbind \fIkey\fR \fIfunction\fR \fImenu\fR, except that for the latter form
|
||||||
|
\fBnano\fR will check the availability of the \fIfunction\fR in the given \fImenu\fR
|
||||||
|
at startup time (and report an error if it does not exist there), whereas for the
|
||||||
|
first form \fBnano\fR will check at execution time that the \fIfunction\fR exists
|
||||||
|
but not whether it makes any sense in the current menu. The user has to take care
|
||||||
|
that a function name between braces (or any sequence of them) is appropriate.
|
||||||
|
Strange behavior can result when it is not.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
The format of \fIkey\fP should be one of:
|
The format of \fIkey\fP should be one of:
|
||||||
@ -687,7 +683,6 @@ Or, when it is set, unsets the mark.
|
|||||||
.B location
|
.B location
|
||||||
Reports the current position of the cursor in the buffer:
|
Reports the current position of the cursor in the buffer:
|
||||||
the line, column, and character positions.
|
the line, column, and character positions.
|
||||||
(The old name of this function, 'curpos', is deprecated.)
|
|
||||||
.TP
|
.TP
|
||||||
.B wordcount
|
.B wordcount
|
||||||
Counts and reports on the status bar the number of lines, words,
|
Counts and reports on the status bar the number of lines, words,
|
||||||
@ -695,7 +690,7 @@ and characters in the current buffer (or in the marked region).
|
|||||||
.TP
|
.TP
|
||||||
.B execute
|
.B execute
|
||||||
Prompts for a program to execute. The program's output will be inserted
|
Prompts for a program to execute. The program's output will be inserted
|
||||||
into the current buffer (or into a new buffer when \fBM-F\fR is toggled).
|
into the current buffer (or into a new buffer when \fBM\-F\fR is toggled).
|
||||||
.TP
|
.TP
|
||||||
.B speller
|
.B speller
|
||||||
Invokes a spell-checking program, either the default \fBhunspell\fR(1) or GNU
|
Invokes a spell-checking program, either the default \fBhunspell\fR(1) or GNU
|
||||||
@ -703,15 +698,23 @@ Invokes a spell-checking program, either the default \fBhunspell\fR(1) or GNU
|
|||||||
.TP
|
.TP
|
||||||
.B formatter
|
.B formatter
|
||||||
Invokes a full-buffer-processing program (if the active syntax defines one).
|
Invokes a full-buffer-processing program (if the active syntax defines one).
|
||||||
|
(The current buffer is written out to a temporary file, the program
|
||||||
|
is run on it, and then the temporary file is read back in, replacing
|
||||||
|
the contents of the buffer.)
|
||||||
.TP
|
.TP
|
||||||
.B linter
|
.B linter
|
||||||
Invokes a syntax-checking program (if the active syntax defines one).
|
Invokes a syntax-checking program (if the active syntax defines one).
|
||||||
|
If this program produces lines of the form "filename:linenum:charnum:
|
||||||
|
some message", then the cursor will be put at the indicated position
|
||||||
|
in the mentioned file while showing "some message" on the status bar.
|
||||||
|
You can move from message to message with <PgUp> and <PgDn>,
|
||||||
|
and leave linting mode with \fB^C\fR or <Enter>.
|
||||||
.TP
|
.TP
|
||||||
.B justify
|
.B justify
|
||||||
Justifies the current paragraph (or the marked region).
|
Justifies the current paragraph (or the marked region).
|
||||||
A paragraph is a group of contiguous lines
|
A paragraph is a group of contiguous lines that, apart from possibly
|
||||||
that, apart from possibly the first line, all have the same indentation. The
|
the first line, all have the same indentation. The beginning of a
|
||||||
beginning of a paragraph is detected by either this lone line with a differing
|
paragraph is detected by either this lone line with a differing
|
||||||
indentation or by a preceding blank line.
|
indentation or by a preceding blank line.
|
||||||
.TP
|
.TP
|
||||||
.B fulljustify
|
.B fulljustify
|
||||||
@ -821,7 +824,8 @@ Switches to editing/viewing the previous buffer when multiple buffers are open.
|
|||||||
Switches to editing/viewing the next buffer when multiple buffers are open.
|
Switches to editing/viewing the next buffer when multiple buffers are open.
|
||||||
.TP
|
.TP
|
||||||
.B verbatim
|
.B verbatim
|
||||||
Inserts the next keystroke verbatim into the file.
|
Inserts the next keystroke verbatim into the file, or begins Unicode input
|
||||||
|
when a hexadecimal digit is typed.
|
||||||
.TP
|
.TP
|
||||||
.B tab
|
.B tab
|
||||||
Inserts a tab at the current cursor location.
|
Inserts a tab at the current cursor location.
|
||||||
@ -931,6 +935,9 @@ Toggles the presence of the two-line list of key bindings at the bottom of the s
|
|||||||
(This toggle is special: it is available in all menus except the help viewer
|
(This toggle is special: it is available in all menus except the help viewer
|
||||||
and the linter. All further toggles are available in the main menu only.)
|
and the linter. All further toggles are available in the main menu only.)
|
||||||
.TP
|
.TP
|
||||||
|
.B zero
|
||||||
|
Toggles the presence of title bar and status bar.
|
||||||
|
.TP
|
||||||
.B constantshow
|
.B constantshow
|
||||||
Toggles the constant display of the current line, column, and character positions.
|
Toggles the constant display of the current line, column, and character positions.
|
||||||
.TP
|
.TP
|
||||||
@ -1014,7 +1021,6 @@ The 'go to directory' menu in the file browser.
|
|||||||
The menu for inserting the output from an external command,
|
The menu for inserting the output from an external command,
|
||||||
or for filtering the buffer (or the marked region) through
|
or for filtering the buffer (or the marked region) through
|
||||||
an external command, or for executing one of several tools.
|
an external command, or for executing one of several tools.
|
||||||
(The old form of this menu name, 'extcmd', is deprecated.)
|
|
||||||
.TP
|
.TP
|
||||||
.B spell
|
.B spell
|
||||||
The menu of the integrated spell checker where the user can edit a misspelled word.
|
The menu of the integrated spell checker where the user can edit a misspelled word.
|
||||||
@ -1028,6 +1034,20 @@ For \fBbind\fR it means all menus where the specified \fIfunction\fR exists;
|
|||||||
for \fBunbind\fR it means all menus where the specified \fIkey\fR exists.
|
for \fBunbind\fR it means all menus where the specified \fIkey\fR exists.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
.SH EXAMPLES
|
||||||
|
To make \fBCtrl+Z\fR suspend nano:
|
||||||
|
.sp
|
||||||
|
.RS
|
||||||
|
.B bind ^Z suspend main
|
||||||
|
.RE
|
||||||
|
.sp
|
||||||
|
To make \fBShift+Alt+C\fR copy the marked region to the system's clipboard:
|
||||||
|
.sp
|
||||||
|
.RS
|
||||||
|
.B bind Sh-M-C """{execute}| xsel -ib {enter}{undo}""" main
|
||||||
|
.RE
|
||||||
|
.sp
|
||||||
|
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.TP
|
.TP
|
||||||
.I /etc/nanorc
|
.I /etc/nanorc
|
||||||
|
|||||||
14
doc/rnano.1
14
doc/rnano.1
@ -1,4 +1,4 @@
|
|||||||
.\" Copyright (C) 2002-2007, 2014-2021 Free Software Foundation, Inc.
|
.\" Copyright (C) 2002-2007, 2014-2023 Free Software Foundation, Inc.
|
||||||
.\"
|
.\"
|
||||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||||
.\" under the terms of either of the following licenses:
|
.\" under the terms of either of the following licenses:
|
||||||
@ -16,7 +16,7 @@
|
|||||||
.\" Documentation License along with this program. If not, see
|
.\" Documentation License along with this program. If not, see
|
||||||
.\" <https://www.gnu.org/licenses/>.
|
.\" <https://www.gnu.org/licenses/>.
|
||||||
.\"
|
.\"
|
||||||
.TH RNANO 1 "version 6.0" "December 2021"
|
.TH RNANO 1 "version 7.2" "January 2023"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
rnano \- a restricted nano
|
rnano \- a restricted nano
|
||||||
@ -32,15 +32,19 @@ access to the filesystem nor to a command shell.
|
|||||||
.sp
|
.sp
|
||||||
In restricted mode, \fBnano\fR will:
|
In restricted mode, \fBnano\fR will:
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
|
not make backups;
|
||||||
|
.IP \[bu]
|
||||||
not allow suspending;
|
not allow suspending;
|
||||||
.IP \[bu]
|
.IP \[bu]
|
||||||
|
not allow spell checking;
|
||||||
|
.IP \[bu]
|
||||||
|
not read nor write the history files;
|
||||||
|
.IP \[bu]
|
||||||
not allow saving the current buffer under a different name;
|
not allow saving the current buffer under a different name;
|
||||||
.IP \[bu]
|
.IP \[bu]
|
||||||
not allow inserting another file or opening a new buffer;
|
not allow inserting another file or opening a new buffer;
|
||||||
.IP \[bu]
|
.IP \[bu]
|
||||||
not allow appending or prepending to any file;
|
not allow appending or prepending to any file.
|
||||||
.IP \[bu]
|
|
||||||
not make backup files nor do spell checking.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@ -58,6 +58,10 @@
|
|||||||
## will be the terminal's width minus this number.
|
## will be the terminal's width minus this number.
|
||||||
# set fill -8
|
# set fill -8
|
||||||
|
|
||||||
|
## Draw a vertical stripe at the given column, to help judge text width.
|
||||||
|
## (This option does not have a default value.)
|
||||||
|
# set guidestripe 75
|
||||||
|
|
||||||
## Remember the used search/replace strings for the next session.
|
## Remember the used search/replace strings for the next session.
|
||||||
# set historylog
|
# set historylog
|
||||||
|
|
||||||
@ -142,7 +146,6 @@
|
|||||||
|
|
||||||
## Save a changed buffer automatically on exit; don't prompt.
|
## Save a changed buffer automatically on exit; don't prompt.
|
||||||
# set saveonexit
|
# set saveonexit
|
||||||
## (The old form of this option, 'set tempfile', is deprecated.)
|
|
||||||
|
|
||||||
## Put the cursor on the highlighted item in the file browser, and
|
## Put the cursor on the highlighted item in the file browser, and
|
||||||
## show the cursor in the help viewer; useful for people who use a
|
## show the cursor in the help viewer; useful for people who use a
|
||||||
@ -176,6 +179,9 @@
|
|||||||
## Snip whitespace at the end of lines when justifying or hard-wrapping.
|
## Snip whitespace at the end of lines when justifying or hard-wrapping.
|
||||||
# set trimblanks
|
# set trimblanks
|
||||||
|
|
||||||
|
## Save files by default in Unix format (also when they were DOS or Mac).
|
||||||
|
# set unix
|
||||||
|
|
||||||
## The two single-column characters used to display the first characters
|
## The two single-column characters used to display the first characters
|
||||||
## of tabs and spaces. 187 in ISO 8859-1 (0000BB in Unicode) and 183 in
|
## of tabs and spaces. 187 in ISO 8859-1 (0000BB in Unicode) and 183 in
|
||||||
## ISO-8859-1 (0000B7 in Unicode) seem to be good values for these.
|
## ISO-8859-1 (0000B7 in Unicode) seem to be good values for these.
|
||||||
@ -278,19 +284,28 @@
|
|||||||
# unbind M-T main
|
# unbind M-T main
|
||||||
## (Those functions are still accessible through ^T^J and ^T^V.)
|
## (Those functions are still accessible through ^T^J and ^T^V.)
|
||||||
|
|
||||||
## For quickly uppercasing or lowercasing the word under the cursor.
|
## For quickly uppercasing or lowercasing the word under or after the cursor.
|
||||||
## (These effectively do a Ctrl+Right followed by a Shift+Ctrl+Left,
|
## (These effectively select a word and pipe it through a sed command.)
|
||||||
## and then pipe the selected text through a sed command.)
|
#bind Sh-M-U "{nextword}{mark}{prevword}{execute}|sed 's/.*/\U&/'{enter}" main
|
||||||
# bind Sh-M-U "Oc[1;6D|sed 's/.*/\U&/'
" main
|
#bind Sh-M-L "{nextword}{mark}{prevword}{execute}|sed 's/.*/\L&/'{enter}" main
|
||||||
# bind Sh-M-L "Oc[1;6D|sed 's/.*/\L&/'
" main
|
|
||||||
|
## For copying a marked region to the system clipboard:
|
||||||
|
# bind Sh-M-T "{execute}|xsel -ib{enter}{undo}" main
|
||||||
|
|
||||||
|
## For snipping trailing blanks when you save a file:
|
||||||
|
# bind ^S "{execute}| sed 's/\s\+$//' {enter}{savefile}" main
|
||||||
|
|
||||||
## If you would like nano to have keybindings that are more "usual",
|
## If you would like nano to have keybindings that are more "usual",
|
||||||
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
|
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
|
||||||
## then uncomment these:
|
## then uncomment these:
|
||||||
|
#bind ^X cut main
|
||||||
|
#bind ^C copy main
|
||||||
|
#bind ^V paste all
|
||||||
#bind ^Q exit all
|
#bind ^Q exit all
|
||||||
#bind ^S savefile main
|
#bind ^S savefile main
|
||||||
#bind ^W writeout main
|
#bind ^W writeout main
|
||||||
#bind ^O insert main
|
#bind ^O insert main
|
||||||
|
#set multibuffer
|
||||||
#bind ^H help all
|
#bind ^H help all
|
||||||
#bind ^H exit help
|
#bind ^H exit help
|
||||||
#bind ^F whereis all
|
#bind ^F whereis all
|
||||||
@ -298,24 +313,19 @@
|
|||||||
#bind ^B wherewas all
|
#bind ^B wherewas all
|
||||||
#bind ^D findprevious all
|
#bind ^D findprevious all
|
||||||
#bind ^R replace main
|
#bind ^R replace main
|
||||||
#bind ^X cut main
|
|
||||||
#bind ^C copy main
|
|
||||||
#bind ^V paste all
|
|
||||||
#bind ^P location main
|
|
||||||
#bind ^E execute main
|
|
||||||
#bind ^A mark main
|
|
||||||
#unbind ^K main
|
|
||||||
#unbind ^U all
|
#unbind ^U all
|
||||||
#unbind ^N main
|
#unbind ^N main
|
||||||
#unbind ^Y all
|
#unbind ^Y all
|
||||||
#unbind M-J main
|
#unbind M-J main
|
||||||
#unbind M-T main
|
#unbind M-T main
|
||||||
|
#bind ^A mark main
|
||||||
|
#bind ^P location main
|
||||||
#bind ^T gotoline main
|
#bind ^T gotoline main
|
||||||
#bind ^T gotodir browser
|
#bind ^T gotodir browser
|
||||||
#bind ^T cutrestoffile execute
|
#bind ^T cutrestoffile execute
|
||||||
#bind ^L linter execute
|
#bind ^L linter execute
|
||||||
#bind M-U undo main
|
#bind ^E execute main
|
||||||
#bind M-R redo main
|
#bind ^K "{mark}{end}{zap}" main
|
||||||
|
#bind ^U "{mark}{home}{zap}" main
|
||||||
#bind ^Z undo main
|
#bind ^Z undo main
|
||||||
#bind ^Y redo main
|
#bind ^Y redo main
|
||||||
#set multibuffer
|
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
# List of available languages.
|
# List of available languages.
|
||||||
bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ko ms nb nl pl pt pt_BR ro ru sk sl sr sv tr uk vi zh_CN zh_TW
|
bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ka ko ms nb nl pl pt pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_TW
|
||||||
|
|||||||
1226
po/nano.pot
1226
po/nano.pot
File diff suppressed because it is too large
Load Diff
1246
po/pt_BR.po
1246
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1251
po/zh_CN.po
1251
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1256
po/zh_TW.po
1256
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
VERSION="6.0"
|
VERSION="7.2"
|
||||||
|
|
||||||
./configure -C --enable-tiny && make && ./configure -C &&
|
./configure -C --enable-tiny && make && ./configure -C &&
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ gpg -a -b nano-$VERSION.tar.xz &&
|
|||||||
gpg --verify nano-$VERSION.tar.gz.asc &&
|
gpg --verify nano-$VERSION.tar.gz.asc &&
|
||||||
gpg --verify nano-$VERSION.tar.xz.asc &&
|
gpg --verify nano-$VERSION.tar.xz.asc &&
|
||||||
|
|
||||||
git tag -u A0ACE884 -a v$VERSION -m "the nano $VERSION release" &&
|
git tag -u B8E1961F -a v$VERSION -m "the nano $VERSION release" &&
|
||||||
|
|
||||||
make pdf && rm -rf doc/nano.t2p &&
|
make pdf && rm -rf doc/nano.t2p &&
|
||||||
scp doc/nano.pdf bens@wh0rd.org:nano.pdf &&
|
scp doc/nano.pdf bens@wh0rd.org:nano.pdf &&
|
||||||
|
|||||||
@ -16,7 +16,8 @@ winio.o: revision.h
|
|||||||
# only when the revision actually changed.
|
# only when the revision actually changed.
|
||||||
revision.h: FORCE
|
revision.h: FORCE
|
||||||
@[ -f $@ ] || touch $@
|
@[ -f $@ ] || touch $@
|
||||||
@echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
@! git describe >/dev/null 2>&1 || \
|
||||||
|
echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
||||||
echo "#define $(SOMETHING)" > $@
|
echo "#define $(SOMETHING)" > $@
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ nano_SOURCES = \
|
|||||||
color.c \
|
color.c \
|
||||||
cut.c \
|
cut.c \
|
||||||
files.c \
|
files.c \
|
||||||
|
folding.c \
|
||||||
global.c \
|
global.c \
|
||||||
help.c \
|
help.c \
|
||||||
history.c \
|
history.c \
|
||||||
|
|||||||
273
src/browser.c
273
src/browser.c
@ -1,8 +1,8 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* browser.c -- This file is part of GNU nano. *
|
* browser.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 2001-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2015-2016, 2020 Benno Schulenberg *
|
* Copyright (C) 2015-2016, 2020, 2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -34,45 +34,43 @@ static size_t list_length = 0;
|
|||||||
/* The number of files in the list. */
|
/* The number of files in the list. */
|
||||||
static size_t usable_rows = 0;
|
static size_t usable_rows = 0;
|
||||||
/* The number of screen rows we can use to display the list. */
|
/* The number of screen rows we can use to display the list. */
|
||||||
static size_t piles = 0;
|
static int piles = 0;
|
||||||
/* The number of files that we can display per screen row. */
|
/* The number of files that we can display per screen row. */
|
||||||
static size_t longest = 0;
|
static int gauge = 0;
|
||||||
/* The number of columns in the longest filename in the list. */
|
/* The width of a 'pile' -- the widest filename plus ten. */
|
||||||
static size_t selected = 0;
|
static size_t selected = 0;
|
||||||
/* The currently selected filename in the list; zero-based. */
|
/* The currently selected filename in the list; zero-based. */
|
||||||
|
|
||||||
/* Set filelist to the list of files contained in the directory path,
|
/* Fill 'filelist' with the names of the files in the given directory, set
|
||||||
* set list_length to the number of files in that list, set longest to
|
* 'list_length' to the number of names in that list, set 'gauge' to the
|
||||||
* the width in columns of the longest filename in that list (between 15
|
* width of the widest filename plus ten, and set 'piles' to the number of
|
||||||
* and COLS), and set piles to the number of files that we can display
|
* files that can be displayed per screen row. And sort the list too. */
|
||||||
* per screen row. And sort the list too. */
|
|
||||||
void read_the_list(const char *path, DIR *dir)
|
void read_the_list(const char *path, DIR *dir)
|
||||||
{
|
{
|
||||||
size_t path_len = strlen(path), index = 0;
|
size_t path_len = strlen(path);
|
||||||
const struct dirent *nextdir;
|
const struct dirent *entry;
|
||||||
|
size_t widest = 0;
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
longest = 0;
|
/* Find the width of the widest filename in the current folder. */
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
size_t span = breadth(entry->d_name);
|
||||||
|
|
||||||
/* Find the length of the longest filename in the current folder. */
|
if (span > widest)
|
||||||
while ((nextdir = readdir(dir)) != NULL) {
|
widest = span;
|
||||||
size_t name_len = breadth(nextdir->d_name);
|
|
||||||
|
|
||||||
if (name_len > longest)
|
|
||||||
longest = name_len;
|
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put 10 characters' worth of blank space between columns of filenames
|
/* Reserve ten columns for blanks plus file size. */
|
||||||
* in the list whenever possible, as Pico does. */
|
gauge = widest + 10;
|
||||||
longest += 10;
|
|
||||||
|
|
||||||
/* If needed, make room for ".. (parent dir)". */
|
/* If needed, make room for ".. (parent dir)". */
|
||||||
if (longest < 15)
|
if (gauge < 15)
|
||||||
longest = 15;
|
gauge = 15;
|
||||||
/* Make sure we're not wider than the window. */
|
/* Make sure we're not wider than the window. */
|
||||||
if (longest > COLS)
|
if (gauge > COLS)
|
||||||
longest = COLS;
|
gauge = COLS;
|
||||||
|
|
||||||
rewinddir(dir);
|
rewinddir(dir);
|
||||||
|
|
||||||
@ -83,20 +81,19 @@ void read_the_list(const char *path, DIR *dir)
|
|||||||
|
|
||||||
filelist = nmalloc(list_length * sizeof(char *));
|
filelist = nmalloc(list_length * sizeof(char *));
|
||||||
|
|
||||||
while ((nextdir = readdir(dir)) != NULL && index < list_length) {
|
while ((entry = readdir(dir)) != NULL && index < list_length) {
|
||||||
/* Don't show the "." entry. */
|
/* Don't show the useless dot item. */
|
||||||
if (strcmp(nextdir->d_name, ".") == 0)
|
if (strcmp(entry->d_name, ".") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
filelist[index] = nmalloc(path_len + strlen(nextdir->d_name) + 1);
|
filelist[index] = nmalloc(path_len + strlen(entry->d_name) + 1);
|
||||||
sprintf(filelist[index], "%s%s", path, nextdir->d_name);
|
sprintf(filelist[index], "%s%s", path, entry->d_name);
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maybe the number of files in the directory decreased between the
|
/* Maybe the number of files in the directory decreased between
|
||||||
* first time we scanned and the second time. index is the actual
|
* the first time we scanned and the second time. */
|
||||||
* length of the file list, so record it. */
|
|
||||||
list_length = index;
|
list_length = index;
|
||||||
|
|
||||||
/* Sort the list of names. */
|
/* Sort the list of names. */
|
||||||
@ -105,33 +102,28 @@ void read_the_list(const char *path, DIR *dir)
|
|||||||
/* Calculate how many files fit on a line -- feigning room for two
|
/* Calculate how many files fit on a line -- feigning room for two
|
||||||
* spaces beyond the right edge, and adding two spaces of padding
|
* spaces beyond the right edge, and adding two spaces of padding
|
||||||
* between columns. */
|
* between columns. */
|
||||||
piles = (COLS + 2) / (longest + 2);
|
piles = (COLS + 2) / (gauge + 2);
|
||||||
|
|
||||||
usable_rows = editwinrows - (ISSET(ZERO) && LINES > 1 ? 1 : 0);
|
usable_rows = editwinrows - (ISSET(ZERO) && LINES > 1 ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for needle. If we find it, set selected to its location.
|
/* Reselect the given file or directory name, if it still exists. */
|
||||||
* Note that needle must be an exact match for a file in the list. */
|
void reselect(const char *name)
|
||||||
void browser_select_dirname(const char *needle)
|
|
||||||
{
|
{
|
||||||
size_t looking_at = 0;
|
size_t looking_at = 0;
|
||||||
|
|
||||||
for (; looking_at < list_length; looking_at++) {
|
while (looking_at < list_length && strcmp(filelist[looking_at], name) != 0)
|
||||||
if (strcmp(filelist[looking_at], needle) == 0) {
|
looking_at++;
|
||||||
selected = looking_at;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the sought name isn't found, move the highlight so that the
|
/* If the sought name was found, select it; otherwise, just move
|
||||||
* changed selection will be noticed. */
|
* the highlight so that the changed selection will be noticed,
|
||||||
if (looking_at == list_length) {
|
* but make sure to stay within the current available range. */
|
||||||
|
if (looking_at < list_length)
|
||||||
|
selected = looking_at;
|
||||||
|
else if (selected > list_length)
|
||||||
|
selected = list_length - 1;
|
||||||
|
else
|
||||||
--selected;
|
--selected;
|
||||||
|
|
||||||
/* Make sure we stay within the available range. */
|
|
||||||
if (selected >= list_length)
|
|
||||||
selected = list_length - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display at most a screenful of filenames from the gleaned filelist. */
|
/* Display at most a screenful of filenames from the gleaned filelist. */
|
||||||
@ -158,11 +150,11 @@ void browser_refresh(void)
|
|||||||
size_t infomaxlen = 7;
|
size_t infomaxlen = 7;
|
||||||
/* The maximum length of the file information in columns:
|
/* The maximum length of the file information in columns:
|
||||||
* normally seven, but will be twelve for "(parent dir)". */
|
* normally seven, but will be twelve for "(parent dir)". */
|
||||||
bool dots = (COLS >= 15 && namelen >= longest - infomaxlen);
|
bool dots = (COLS >= 15 && namelen >= gauge - infomaxlen);
|
||||||
/* Whether to put an ellipsis before the filename? We don't
|
/* Whether to put an ellipsis before the filename? We don't
|
||||||
* waste space on dots when there are fewer than 15 columns. */
|
* waste space on dots when there are fewer than 15 columns. */
|
||||||
char *disp = display_string(thename, dots ?
|
char *disp = display_string(thename, dots ?
|
||||||
namelen + infomaxlen + 4 - longest : 0, longest, FALSE, FALSE);
|
namelen + infomaxlen + 4 - gauge : 0, gauge, FALSE, FALSE);
|
||||||
/* The filename (or a fragment of it) in displayable format.
|
/* The filename (or a fragment of it) in displayable format.
|
||||||
* When a fragment, account for dots plus one space padding. */
|
* When a fragment, account for dots plus one space padding. */
|
||||||
struct stat state;
|
struct stat state;
|
||||||
@ -170,18 +162,18 @@ void browser_refresh(void)
|
|||||||
/* If this is the selected item, draw its highlighted bar upfront, and
|
/* If this is the selected item, draw its highlighted bar upfront, and
|
||||||
* remember its location to be able to place the cursor on it. */
|
* remember its location to be able to place the cursor on it. */
|
||||||
if (index == selected) {
|
if (index == selected) {
|
||||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
wattron(midwin, interface_color_pair[SELECTED_TEXT]);
|
||||||
mvwprintw(edit, row, col, "%*s", longest, " ");
|
mvwprintw(midwin, row, col, "%*s", gauge, " ");
|
||||||
the_row = row;
|
the_row = row;
|
||||||
the_column = col;
|
the_column = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the name is too long, we display something like "...ename". */
|
/* If the name is too long, we display something like "...ename". */
|
||||||
if (dots)
|
if (dots)
|
||||||
mvwaddstr(edit, row, col, "...");
|
mvwaddstr(midwin, row, col, "...");
|
||||||
mvwaddstr(edit, row, dots ? col + 3 : col, disp);
|
mvwaddstr(midwin, row, dots ? col + 3 : col, disp);
|
||||||
|
|
||||||
col += longest;
|
col += gauge;
|
||||||
|
|
||||||
/* Show information about the file: "--" for symlinks (except when
|
/* Show information about the file: "--" for symlinks (except when
|
||||||
* they point to a directory) and for files that have disappeared,
|
* they point to a directory) and for files that have disappeared,
|
||||||
@ -235,11 +227,11 @@ void browser_refresh(void)
|
|||||||
infolen = infomaxlen;
|
infolen = infomaxlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
mvwaddstr(edit, row, col - infolen, info);
|
mvwaddstr(midwin, row, col - infolen, info);
|
||||||
|
|
||||||
/* If this is the selected item, finish its highlighting. */
|
/* If this is the selected item, finish its highlighting. */
|
||||||
if (index == selected)
|
if (index == selected)
|
||||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
wattroff(midwin, interface_color_pair[SELECTED_TEXT]);
|
||||||
|
|
||||||
free(disp);
|
free(disp);
|
||||||
free(info);
|
free(info);
|
||||||
@ -247,8 +239,8 @@ void browser_refresh(void)
|
|||||||
/* Add some space between the columns. */
|
/* Add some space between the columns. */
|
||||||
col += 2;
|
col += 2;
|
||||||
|
|
||||||
/* If the next entry will not fit on this row, move to next row. */
|
/* If the next item will not fit on this row, move to next row. */
|
||||||
if (col > COLS - longest) {
|
if (col > COLS - gauge) {
|
||||||
row++;
|
row++;
|
||||||
col = 0;
|
col = 0;
|
||||||
}
|
}
|
||||||
@ -256,70 +248,46 @@ void browser_refresh(void)
|
|||||||
|
|
||||||
/* If requested, put the cursor on the selected item and switch it on. */
|
/* If requested, put the cursor on the selected item and switch it on. */
|
||||||
if (ISSET(SHOW_CURSOR)) {
|
if (ISSET(SHOW_CURSOR)) {
|
||||||
wmove(edit, the_row, the_column);
|
wmove(midwin, the_row, the_column);
|
||||||
curs_set(1);
|
curs_set(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
wnoutrefresh(edit);
|
wnoutrefresh(midwin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for the given needle in the list of files. If forwards is TRUE,
|
/* Look for the given needle in the list of files, forwards or backwards. */
|
||||||
* search forward in the list; otherwise, search backward. */
|
|
||||||
void findfile(const char *needle, bool forwards)
|
void findfile(const char *needle, bool forwards)
|
||||||
{
|
{
|
||||||
size_t looking_at = selected;
|
size_t began_at = selected;
|
||||||
/* The location in the file list of the filename we're looking at. */
|
|
||||||
const char *thename;
|
|
||||||
/* The plain filename, without the path. */
|
|
||||||
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
|
||||||
/* A storage place for the current flag settings. */
|
|
||||||
|
|
||||||
/* Save the settings of all flags. */
|
/* Iterate through the list of filenames, until a match is found or
|
||||||
memcpy(stash, flags, sizeof(flags));
|
|
||||||
|
|
||||||
/* Search forward, case insensitive, and without regexes. */
|
|
||||||
UNSET(BACKWARDS_SEARCH);
|
|
||||||
UNSET(CASE_SENSITIVE);
|
|
||||||
UNSET(USE_REGEXP);
|
|
||||||
|
|
||||||
/* Step through each filename in the list until a match is found or
|
|
||||||
* we've come back to the point where we started. */
|
* we've come back to the point where we started. */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
if (forwards) {
|
if (forwards) {
|
||||||
if (looking_at++ == list_length - 1) {
|
if (selected++ == list_length - 1) {
|
||||||
looking_at = 0;
|
selected = 0;
|
||||||
statusbar(_("Search Wrapped"));
|
statusbar(_("Search Wrapped"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (looking_at-- == 0) {
|
if (selected-- == 0) {
|
||||||
looking_at = list_length - 1;
|
selected = list_length - 1;
|
||||||
statusbar(_("Search Wrapped"));
|
statusbar(_("Search Wrapped"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the bare filename, without the path. */
|
/* When the needle occurs in the basename of the file, we have a match. */
|
||||||
thename = tail(filelist[looking_at]);
|
if (mbstrcasestr(tail(filelist[selected]), needle)) {
|
||||||
|
if (selected == began_at)
|
||||||
/* If the needle matches, we're done. And if we're back at the file
|
|
||||||
* where we started, it is the only occurrence. */
|
|
||||||
if (strstrwrapper(thename, needle, thename)) {
|
|
||||||
if (looking_at == selected)
|
|
||||||
statusbar(_("This is the only occurrence"));
|
statusbar(_("This is the only occurrence"));
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're back at the beginning and didn't find any match... */
|
/* When we're back at the starting point without any match... */
|
||||||
if (looking_at == selected) {
|
if (selected == began_at) {
|
||||||
not_found_msg(needle);
|
not_found_msg(needle);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the settings of all flags. */
|
|
||||||
memcpy(flags, stash, sizeof(flags));
|
|
||||||
|
|
||||||
/* Select the one we've found. */
|
|
||||||
selected = looking_at;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare the prompt and ask the user what to search for; then search for it.
|
/* Prepare the prompt and ask the user what to search for; then search for it.
|
||||||
@ -447,19 +415,18 @@ char *browse(char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dir != NULL) {
|
if (dir != NULL) {
|
||||||
/* Get the file list, and set longest and piles in the process. */
|
/* Get the file list, and set gauge and piles in the process. */
|
||||||
read_the_list(path, dir);
|
read_the_list(path, dir);
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
dir = NULL;
|
dir = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If given, reselect the present_name and then discard it. */
|
/* If something was selected before, reselect it;
|
||||||
|
* otherwise, just select the first item (..). */
|
||||||
if (present_name != NULL) {
|
if (present_name != NULL) {
|
||||||
browser_select_dirname(present_name);
|
reselect(present_name);
|
||||||
|
|
||||||
free(present_name);
|
free(present_name);
|
||||||
present_name = NULL;
|
present_name = NULL;
|
||||||
/* Otherwise, select the first file or directory in the list. */
|
|
||||||
} else
|
} else
|
||||||
selected = 0;
|
selected = 0;
|
||||||
|
|
||||||
@ -469,8 +436,11 @@ char *browse(char *path)
|
|||||||
|
|
||||||
titlebar(path);
|
titlebar(path);
|
||||||
|
|
||||||
while (TRUE) {
|
if (list_length == 0) {
|
||||||
functionptrtype func;
|
statusline(ALERT, _("No entries"));
|
||||||
|
napms(1200);
|
||||||
|
} else while (TRUE) {
|
||||||
|
functionptrtype function;
|
||||||
int kbinput;
|
int kbinput;
|
||||||
|
|
||||||
lastmessage = VACUUM;
|
lastmessage = VACUUM;
|
||||||
@ -484,7 +454,7 @@ char *browse(char *path)
|
|||||||
|
|
||||||
old_selected = selected;
|
old_selected = selected;
|
||||||
|
|
||||||
kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR));
|
kbinput = get_kbinput(midwin, ISSET(SHOW_CURSOR));
|
||||||
|
|
||||||
#ifdef ENABLE_MOUSE
|
#ifdef ENABLE_MOUSE
|
||||||
if (kbinput == KEY_MOUSE) {
|
if (kbinput == KEY_MOUSE) {
|
||||||
@ -492,12 +462,12 @@ char *browse(char *path)
|
|||||||
|
|
||||||
/* When the user clicked in the file list, select a filename. */
|
/* When the user clicked in the file list, select a filename. */
|
||||||
if (get_mouseinput(&mouse_y, &mouse_x, TRUE) == 0 &&
|
if (get_mouseinput(&mouse_y, &mouse_x, TRUE) == 0 &&
|
||||||
wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
|
wmouse_trafo(midwin, &mouse_y, &mouse_x, FALSE)) {
|
||||||
selected = selected - selected % (usable_rows * piles) +
|
selected = selected - selected % (usable_rows * piles) +
|
||||||
(mouse_y * piles) + (mouse_x / (longest + 2));
|
(mouse_y * piles) + (mouse_x / (gauge + 2));
|
||||||
|
|
||||||
/* When beyond end-of-row, select the preceding filename. */
|
/* When beyond end-of-row, select the preceding filename. */
|
||||||
if (mouse_x > piles * (longest + 2))
|
if (mouse_x > piles * (gauge + 2))
|
||||||
selected--;
|
selected--;
|
||||||
|
|
||||||
/* When beyond end-of-list, select the last filename. */
|
/* When beyond end-of-list, select the last filename. */
|
||||||
@ -514,73 +484,70 @@ char *browse(char *path)
|
|||||||
}
|
}
|
||||||
#endif /* ENABLE_MOUSE */
|
#endif /* ENABLE_MOUSE */
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (bracketed_paste || kbinput == BRACKETED_PASTE_MARKER) {
|
while (bracketed_paste)
|
||||||
|
kbinput = get_kbinput(midwin, BLIND);
|
||||||
|
if (kbinput == BRACKETED_PASTE_MARKER) {
|
||||||
beep();
|
beep();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
func = interpret(&kbinput);
|
function = interpret(kbinput);
|
||||||
|
|
||||||
if (func == full_refresh) {
|
if (function == full_refresh || function == do_help) {
|
||||||
full_refresh();
|
function();
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* Simulate a terminal resize to force a directory reread. */
|
/* Simulate a terminal resize to force a directory reread,
|
||||||
|
* or because the terminal dimensions might have changed. */
|
||||||
kbinput = KEY_WINCH;
|
kbinput = KEY_WINCH;
|
||||||
#endif
|
} else if (function == do_toggle && get_shortcut(kbinput)->toggle == NO_HELP) {
|
||||||
} else if (func == do_help) {
|
|
||||||
do_help();
|
|
||||||
#ifndef NANO_TINY
|
|
||||||
/* The terminal dimensions might have changed, so act as if. */
|
|
||||||
kbinput = KEY_WINCH;
|
|
||||||
} else if (func == do_toggle) {
|
|
||||||
TOGGLE(NO_HELP);
|
TOGGLE(NO_HELP);
|
||||||
window_init();
|
window_init();
|
||||||
kbinput = KEY_WINCH;
|
kbinput = KEY_WINCH;
|
||||||
#endif
|
#endif
|
||||||
} else if (func == do_search_backward) {
|
} else if (function == do_search_backward) {
|
||||||
search_filename(BACKWARD);
|
search_filename(BACKWARD);
|
||||||
} else if (func == do_search_forward) {
|
} else if (function == do_search_forward) {
|
||||||
search_filename(FORWARD);
|
search_filename(FORWARD);
|
||||||
} else if (func == do_findprevious) {
|
} else if (function == do_findprevious) {
|
||||||
research_filename(BACKWARD);
|
research_filename(BACKWARD);
|
||||||
} else if (func == do_findnext) {
|
} else if (function == do_findnext) {
|
||||||
research_filename(FORWARD);
|
research_filename(FORWARD);
|
||||||
} else if (func == do_left) {
|
} else if (function == do_left) {
|
||||||
if (selected > 0)
|
if (selected > 0)
|
||||||
selected--;
|
selected--;
|
||||||
} else if (func == do_right) {
|
} else if (function == do_right) {
|
||||||
if (selected < list_length - 1)
|
if (selected < list_length - 1)
|
||||||
selected++;
|
selected++;
|
||||||
} else if (func == to_prev_word) {
|
} else if (function == to_prev_word) {
|
||||||
selected -= (selected % piles);
|
selected -= (selected % piles);
|
||||||
} else if (func == to_next_word) {
|
} else if (function == to_next_word) {
|
||||||
selected += piles - 1 - (selected % piles);
|
selected += piles - 1 - (selected % piles);
|
||||||
if (selected >= list_length)
|
if (selected >= list_length)
|
||||||
selected = list_length - 1;
|
selected = list_length - 1;
|
||||||
} else if (func == do_up) {
|
} else if (function == do_up) {
|
||||||
if (selected >= piles)
|
if (selected >= piles)
|
||||||
selected -= piles;
|
selected -= piles;
|
||||||
} else if (func == do_down) {
|
} else if (function == do_down) {
|
||||||
if (selected + piles <= list_length - 1)
|
if (selected + piles <= list_length - 1)
|
||||||
selected += piles;
|
selected += piles;
|
||||||
} else if (func == to_prev_block) {
|
} else if (function == to_prev_block) {
|
||||||
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
|
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
|
||||||
selected % piles;
|
selected % piles;
|
||||||
} else if (func == to_next_block) {
|
} else if (function == to_next_block) {
|
||||||
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
|
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
|
||||||
selected % piles + usable_rows * piles - piles;
|
selected % piles + usable_rows * piles - piles;
|
||||||
if (selected >= list_length)
|
if (selected >= list_length)
|
||||||
selected = (list_length / piles) * piles + selected % piles;
|
selected = (list_length / piles) * piles + selected % piles;
|
||||||
if (selected >= list_length)
|
if (selected >= list_length)
|
||||||
selected -= piles;
|
selected -= piles;
|
||||||
} else if (func == do_page_up) {
|
} else if (function == do_page_up) {
|
||||||
if (selected < piles)
|
if (selected < piles)
|
||||||
selected = 0;
|
selected = 0;
|
||||||
else if (selected < usable_rows * piles)
|
else if (selected < usable_rows * piles)
|
||||||
selected = selected % piles;
|
selected = selected % piles;
|
||||||
else
|
else
|
||||||
selected -= usable_rows * piles;
|
selected -= usable_rows * piles;
|
||||||
} else if (func == do_page_down) {
|
} else if (function == do_page_down) {
|
||||||
if (selected + piles >= list_length - 1)
|
if (selected + piles >= list_length - 1)
|
||||||
selected = list_length - 1;
|
selected = list_length - 1;
|
||||||
else if (selected + usable_rows * piles >= list_length)
|
else if (selected + usable_rows * piles >= list_length)
|
||||||
@ -588,11 +555,11 @@ char *browse(char *path)
|
|||||||
list_length - piles;
|
list_length - piles;
|
||||||
else
|
else
|
||||||
selected += usable_rows * piles;
|
selected += usable_rows * piles;
|
||||||
} else if (func == to_first_file) {
|
} else if (function == to_first_file) {
|
||||||
selected = 0;
|
selected = 0;
|
||||||
} else if (func == to_last_file) {
|
} else if (function == to_last_file) {
|
||||||
selected = list_length - 1;
|
selected = list_length - 1;
|
||||||
} else if (func == goto_dir) {
|
} else if (function == goto_dir) {
|
||||||
/* Ask for the directory to go to. */
|
/* Ask for the directory to go to. */
|
||||||
if (do_prompt(MGOTODIR, "", NULL,
|
if (do_prompt(MGOTODIR, "", NULL,
|
||||||
/* TRANSLATORS: This is a prompt. */
|
/* TRANSLATORS: This is a prompt. */
|
||||||
@ -631,7 +598,7 @@ char *browse(char *path)
|
|||||||
|
|
||||||
/* Try opening and reading the specified directory. */
|
/* Try opening and reading the specified directory. */
|
||||||
goto read_directory_contents;
|
goto read_directory_contents;
|
||||||
} else if (func == do_enter) {
|
} else if (function == do_enter) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
/* It isn't possible to move up from the root directory. */
|
/* It isn't possible to move up from the root directory. */
|
||||||
@ -671,14 +638,14 @@ char *browse(char *path)
|
|||||||
path = mallocstrcpy(path, filelist[selected]);
|
path = mallocstrcpy(path, filelist[selected]);
|
||||||
goto read_directory_contents;
|
goto read_directory_contents;
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
} else if (func == (functionptrtype)implant) {
|
} else if (function == (functionptrtype)implant) {
|
||||||
implant(first_sc_for(MBROWSER, func)->expansion);
|
implant(first_sc_for(MBROWSER, function)->expansion);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
} else if (kbinput == KEY_WINCH) {
|
} else if (kbinput == KEY_WINCH) {
|
||||||
; /* Gets handled below. */
|
; /* Gets handled below. */
|
||||||
#endif
|
#endif
|
||||||
} else if (func == do_exit) {
|
} else if (function == do_exit) {
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
unbound_key(kbinput);
|
unbound_key(kbinput);
|
||||||
@ -718,14 +685,10 @@ char *browse_in(const char *inpath)
|
|||||||
path = free_and_assign(path, strip_last_component(path));
|
path = free_and_assign(path, strip_last_component(path));
|
||||||
|
|
||||||
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
|
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
|
||||||
char *currentdir = nmalloc(PATH_MAX + 1);
|
path = free_and_assign(path, realpath(".", NULL));
|
||||||
|
|
||||||
path = free_and_assign(path, getcwd(currentdir, PATH_MAX + 1));
|
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
statusline(MILD, _("The working directory has disappeared"));
|
statusline(ALERT, _("The working directory has disappeared"));
|
||||||
free(currentdir);
|
|
||||||
beep();
|
|
||||||
napms(1200);
|
napms(1200);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -733,8 +696,8 @@ char *browse_in(const char *inpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_OPERATINGDIR
|
#ifdef ENABLE_OPERATINGDIR
|
||||||
/* If the resulting path isn't in the operating directory, use
|
/* If the resulting path isn't in the operating directory,
|
||||||
* the operating directory instead. */
|
* use the operating directory instead. */
|
||||||
if (outside_of_confinement(path, FALSE))
|
if (outside_of_confinement(path, FALSE))
|
||||||
path = mallocstrcpy(path, operating_dir);
|
path = mallocstrcpy(path, operating_dir);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* chars.c -- This file is part of GNU nano. *
|
* chars.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 2001-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2016-2021 Benno Schulenberg *
|
* Copyright (C) 2016-2021 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
|
|||||||
33
src/color.c
33
src/color.c
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* color.c -- This file is part of GNU nano. *
|
* color.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 2001-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014-2017, 2020, 2021 Benno Schulenberg *
|
* Copyright (C) 2014-2017, 2020, 2021 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
@ -53,6 +53,7 @@ void set_interface_colorpairs(void)
|
|||||||
}
|
}
|
||||||
init_pair(index + 1, combo->fg, combo->bg);
|
init_pair(index + 1, combo->fg, combo->bg);
|
||||||
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
|
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
|
||||||
|
rescind_colors = FALSE;
|
||||||
} else {
|
} else {
|
||||||
if (index == FUNCTION_TAG || index == SCROLL_BAR)
|
if (index == FUNCTION_TAG || index == SCROLL_BAR)
|
||||||
interface_color_pair[index] = A_NORMAL;
|
interface_color_pair[index] = A_NORMAL;
|
||||||
@ -72,6 +73,11 @@ void set_interface_colorpairs(void)
|
|||||||
|
|
||||||
free(color_combo[index]);
|
free(color_combo[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rescind_colors) {
|
||||||
|
interface_color_pair[SPOTLIGHTED] = A_REVERSE;
|
||||||
|
interface_color_pair[ERROR_MESSAGE] = A_REVERSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign a pair number to each of the foreground/background color combinations
|
/* Assign a pair number to each of the foreground/background color combinations
|
||||||
@ -255,12 +261,14 @@ void check_the_multis(linestruct *line)
|
|||||||
if (line->multidata[ink->id] == NOTHING) {
|
if (line->multidata[ink->id] == NOTHING) {
|
||||||
if (!astart)
|
if (!astart)
|
||||||
continue;
|
continue;
|
||||||
} else if (line->multidata[ink->id] & (WHOLELINE|WOULDBE)) {
|
} else if (line->multidata[ink->id] == WHOLELINE) {
|
||||||
if (!astart && !anend)
|
/* Ensure that a detected start match is not actually an end match. */
|
||||||
|
if (!anend && (!astart || regexec(ink->end, line->data, 1,
|
||||||
|
&endmatch, 0) != 0))
|
||||||
continue;
|
continue;
|
||||||
} else if (line->multidata[ink->id] == JUSTONTHIS) {
|
} else if (line->multidata[ink->id] == JUSTONTHIS) {
|
||||||
if (astart && anend && regexec(ink->start, line->data + endmatch.rm_eo,
|
if (astart && anend && regexec(ink->start, line->data + startmatch.rm_eo +
|
||||||
1, &startmatch, 0) != 0)
|
endmatch.rm_eo, 1, &startmatch, 0) != 0)
|
||||||
continue;
|
continue;
|
||||||
} else if (line->multidata[ink->id] == STARTSHERE) {
|
} else if (line->multidata[ink->id] == STARTSHERE) {
|
||||||
if (astart && !anend)
|
if (astart && !anend)
|
||||||
@ -272,6 +280,7 @@ void check_the_multis(linestruct *line)
|
|||||||
|
|
||||||
/* There is a mismatch, so something changed: repaint. */
|
/* There is a mismatch, so something changed: repaint. */
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
|
perturbed = TRUE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,21 +351,17 @@ void precalc_multicolorinfo(void)
|
|||||||
1, &endmatch, 0) != 0)
|
1, &endmatch, 0) != 0)
|
||||||
tailline = tailline->next;
|
tailline = tailline->next;
|
||||||
|
|
||||||
/* When there is no end match, mark relevant lines as such. */
|
|
||||||
if (tailline == NULL) {
|
|
||||||
for (; line->next != NULL; line = line->next)
|
|
||||||
line->multidata[ink->id] = WOULDBE;
|
|
||||||
line->multidata[ink->id] = WOULDBE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We found it, we found it, la lala lala. Mark the lines. */
|
|
||||||
line->multidata[ink->id] = STARTSHERE;
|
line->multidata[ink->id] = STARTSHERE;
|
||||||
|
|
||||||
// Note that this also advances the line in the main loop.
|
// Note that this also advances the line in the main loop.
|
||||||
for (line = line->next; line != tailline; line = line->next)
|
for (line = line->next; line != tailline; line = line->next)
|
||||||
line->multidata[ink->id] = WHOLELINE;
|
line->multidata[ink->id] = WHOLELINE;
|
||||||
|
|
||||||
|
if (tailline == NULL) {
|
||||||
|
line = openfile->filebot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
tailline->multidata[ink->id] = ENDSHERE;
|
tailline->multidata[ink->id] = ENDSHERE;
|
||||||
|
|
||||||
/* Look for a possible new start after the end match. */
|
/* Look for a possible new start after the end match. */
|
||||||
|
|||||||
52
src/cut.c
52
src/cut.c
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* cut.c -- This file is part of GNU nano. *
|
* cut.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014 Mark Majeres *
|
* Copyright (C) 2014 Mark Majeres *
|
||||||
* Copyright (C) 2016, 2018-2020 Benno Schulenberg *
|
* Copyright (C) 2016, 2018-2020 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
@ -48,6 +48,7 @@ void do_deletion(undo_type action)
|
|||||||
memmove(&openfile->current->data[openfile->current_x],
|
memmove(&openfile->current->data[openfile->current_x],
|
||||||
&openfile->current->data[openfile->current_x + charlen],
|
&openfile->current->data[openfile->current_x + charlen],
|
||||||
line_len - charlen + 1);
|
line_len - charlen + 1);
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* When softwrapping, a changed number of chunks requires a refresh. */
|
/* When softwrapping, a changed number of chunks requires a refresh. */
|
||||||
if (ISSET(SOFTWRAP) && extra_chunks_in(openfile->current) != old_amount)
|
if (ISSET(SOFTWRAP) && extra_chunks_in(openfile->current) != old_amount)
|
||||||
@ -62,6 +63,9 @@ void do_deletion(undo_type action)
|
|||||||
} else if (openfile->current != openfile->filebot) {
|
} else if (openfile->current != openfile->filebot) {
|
||||||
linestruct *joining = openfile->current->next;
|
linestruct *joining = openfile->current->next;
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
UNFOLD_SEGMENT(joining);
|
||||||
|
|
||||||
/* If there is a magic line, and we're before it: don't eat it. */
|
/* If there is a magic line, and we're before it: don't eat it. */
|
||||||
if (joining == openfile->filebot && openfile->current_x != 0 &&
|
if (joining == openfile->filebot && openfile->current_x != 0 &&
|
||||||
!ISSET(NO_NEWLINES)) {
|
!ISSET(NO_NEWLINES)) {
|
||||||
@ -97,6 +101,13 @@ void do_deletion(undo_type action)
|
|||||||
/* We're at the end-of-file: nothing to do. */
|
/* We're at the end-of-file: nothing to do. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
if (!refresh_needed)
|
||||||
|
check_the_multis(openfile->current);
|
||||||
|
#endif
|
||||||
|
if (!refresh_needed)
|
||||||
|
update_line(openfile->current, openfile->current_x);
|
||||||
|
|
||||||
/* Adjust the file size, and remember it for a possible redo. */
|
/* Adjust the file size, and remember it for a possible redo. */
|
||||||
openfile->totsize--;
|
openfile->totsize--;
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -136,7 +147,8 @@ void do_backspace(void)
|
|||||||
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
|
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
|
||||||
do_deletion(BACK);
|
do_deletion(BACK);
|
||||||
} else if (openfile->current != openfile->filetop) {
|
} else if (openfile->current != openfile->filetop) {
|
||||||
do_left();
|
openfile->current = openfile->current->prev;
|
||||||
|
openfile->current_x = strlen(openfile->current->data);
|
||||||
do_deletion(BACK);
|
do_deletion(BACK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,7 +197,7 @@ void chop_word(bool forward)
|
|||||||
* on the edge of the original line, then put the cursor on that
|
* on the edge of the original line, then put the cursor on that
|
||||||
* edge instead, so that lines will not be joined unexpectedly. */
|
* edge instead, so that lines will not be joined unexpectedly. */
|
||||||
if (!forward) {
|
if (!forward) {
|
||||||
do_prev_word();
|
do_prev_word(ALLOW_FOLDED);
|
||||||
if (openfile->current != is_current) {
|
if (openfile->current != is_current) {
|
||||||
if (is_current_x > 0) {
|
if (is_current_x > 0) {
|
||||||
openfile->current = is_current;
|
openfile->current = is_current;
|
||||||
@ -194,13 +206,14 @@ void chop_word(bool forward)
|
|||||||
openfile->current_x = strlen(openfile->current->data);
|
openfile->current_x = strlen(openfile->current->data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
do_next_word(ISSET(AFTER_ENDS));
|
do_next_word(ISSET(AFTER_ENDS), ALLOW_FOLDED);
|
||||||
if (openfile->current != is_current &&
|
if (openfile->current != is_current &&
|
||||||
is_current->data[is_current_x] != '\0') {
|
is_current->data[is_current_x] != '\0') {
|
||||||
openfile->current = is_current;
|
openfile->current = is_current;
|
||||||
openfile->current_x = strlen(is_current->data);
|
openfile->current_x = strlen(is_current->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
|
||||||
/* Set the mark at the start of that word. */
|
/* Set the mark at the start of that word. */
|
||||||
openfile->mark = openfile->current;
|
openfile->mark = openfile->current;
|
||||||
@ -255,9 +268,20 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
|||||||
if (top == bot && top_x == bot_x)
|
if (top == bot && top_x == bot_x)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* In case bot is the start of a folded segment.
|
||||||
|
* Folds within [top, bot] are taken care of in the following loop */
|
||||||
|
UNFOLD_SEGMENT(bot);
|
||||||
|
|
||||||
if (top != bot)
|
if (top != bot)
|
||||||
for (linestruct *line = top->next; line != bot->next; line = line->next)
|
#ifdef ENABLE_FOLDING
|
||||||
|
top->folded = FALSE;
|
||||||
|
#endif
|
||||||
|
for (linestruct *line = top->next; line != bot->next; line = line->next){
|
||||||
had_anchor |= line->has_anchor;
|
had_anchor |= line->has_anchor;
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
line->folded = FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (top == bot) {
|
if (top == bot) {
|
||||||
@ -371,6 +395,8 @@ void ingraft_buffer(linestruct *topline)
|
|||||||
#endif
|
#endif
|
||||||
linestruct *botline = topline;
|
linestruct *botline = topline;
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
|
|
||||||
while (botline->next != NULL)
|
while (botline->next != NULL)
|
||||||
botline = botline->next;
|
botline = botline->next;
|
||||||
|
|
||||||
@ -435,9 +461,19 @@ void ingraft_buffer(linestruct *topline)
|
|||||||
/* Meld a copy of the given buffer into the current file buffer. */
|
/* Meld a copy of the given buffer into the current file buffer. */
|
||||||
void copy_from_buffer(linestruct *somebuffer)
|
void copy_from_buffer(linestruct *somebuffer)
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
size_t threshold = openfile->edittop->lineno + editwinrows - 1;
|
||||||
|
#endif
|
||||||
linestruct *the_copy = copy_buffer(somebuffer);
|
linestruct *the_copy = copy_buffer(somebuffer);
|
||||||
|
|
||||||
ingraft_buffer(the_copy);
|
ingraft_buffer(the_copy);
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
if (openfile->current->lineno > threshold || ISSET(SOFTWRAP))
|
||||||
|
recook = TRUE;
|
||||||
|
else
|
||||||
|
perturbed = TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -485,7 +521,7 @@ void do_snip(bool marked, bool until_eof, bool append)
|
|||||||
/* When not at the end of a line, move the rest of this line into
|
/* When not at the end of a line, move the rest of this line into
|
||||||
* the cutbuffer. Otherwise, when not at the end of the buffer,
|
* the cutbuffer. Otherwise, when not at the end of the buffer,
|
||||||
* move just the "line separator" into the cutbuffer. */
|
* move just the "line separator" into the cutbuffer. */
|
||||||
if (openfile->current_x < strlen(openfile->current->data))
|
if (line->data[openfile->current_x] != '\0')
|
||||||
extract_segment(line, openfile->current_x, line, strlen(line->data));
|
extract_segment(line, openfile->current_x, line, strlen(line->data));
|
||||||
else if (openfile->current != openfile->filebot) {
|
else if (openfile->current != openfile->filebot) {
|
||||||
extract_segment(line, openfile->current_x, line->next, 0);
|
extract_segment(line, openfile->current_x, line->next, 0);
|
||||||
@ -509,6 +545,9 @@ void do_snip(bool marked, bool until_eof, bool append)
|
|||||||
|
|
||||||
set_modified();
|
set_modified();
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
perturbed = TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move text from the current buffer into the cutbuffer. */
|
/* Move text from the current buffer into the cutbuffer. */
|
||||||
@ -708,6 +747,7 @@ void paste_text(void)
|
|||||||
statusline(AHEM, _("Cutbuffer is empty"));
|
statusline(AHEM, _("Cutbuffer is empty"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_undo(PASTE, NULL);
|
add_undo(PASTE, NULL);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* definitions.h -- This file is part of GNU nano. *
|
* definitions.h -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
@ -108,6 +108,14 @@
|
|||||||
#define BACKWARD FALSE
|
#define BACKWARD FALSE
|
||||||
#define FORWARD TRUE
|
#define FORWARD TRUE
|
||||||
|
|
||||||
|
#define YESORNO FALSE
|
||||||
|
#define YESORALLORNO TRUE
|
||||||
|
|
||||||
|
#define YES 1
|
||||||
|
#define ALL 2
|
||||||
|
#define NO 0
|
||||||
|
#define CANCEL -1
|
||||||
|
|
||||||
#define BLIND FALSE
|
#define BLIND FALSE
|
||||||
#define VISIBLE TRUE
|
#define VISIBLE TRUE
|
||||||
|
|
||||||
@ -162,8 +170,6 @@
|
|||||||
/* The start regex matches on an earlier line, the end regex on this one. */
|
/* The start regex matches on an earlier line, the end regex on this one. */
|
||||||
#define JUSTONTHIS (1<<5)
|
#define JUSTONTHIS (1<<5)
|
||||||
/* Both the start and end regexes match within this line. */
|
/* Both the start and end regexes match within this line. */
|
||||||
#define WOULDBE (1<<6)
|
|
||||||
/* An unpaired start match is on or before this line. */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Basic control codes. */
|
/* Basic control codes. */
|
||||||
@ -208,6 +214,17 @@
|
|||||||
#define SHIFT_DELETE 0x45D
|
#define SHIFT_DELETE 0x45D
|
||||||
#define SHIFT_TAB 0x45F
|
#define SHIFT_TAB 0x45F
|
||||||
|
|
||||||
|
#define FOCUS_IN 0x491
|
||||||
|
#define FOCUS_OUT 0x499
|
||||||
|
|
||||||
|
/* Special keycodes for when a string bind has been partially implanted
|
||||||
|
* or has an unpaired opening brace, or when a function in a string bind
|
||||||
|
* needs execution or a specified function name is invalid. */
|
||||||
|
#define MORE_PLANTS 0x4EA
|
||||||
|
#define MISSING_BRACE 0x4EB
|
||||||
|
#define PLANTED_A_COMMAND 0x4EC
|
||||||
|
#define NO_SUCH_FUNCTION 0x4EF
|
||||||
|
|
||||||
/* A special keycode for when <Tab> is pressed while the mark is on. */
|
/* A special keycode for when <Tab> is pressed while the mark is on. */
|
||||||
#define INDENT_KEY 0x4F1
|
#define INDENT_KEY 0x4F1
|
||||||
|
|
||||||
@ -259,6 +276,15 @@
|
|||||||
#define MSOME MMAIN|MBROWSER
|
#define MSOME MMAIN|MBROWSER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
#define UNFOLD_SEGMENT(line) unfold_folded_segment(line)
|
||||||
|
#else
|
||||||
|
#define UNFOLD_SEGMENT(line)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ALLOW_FOLDED TRUE
|
||||||
|
#define DISALLOW_FOLDED FALSE
|
||||||
|
|
||||||
/* Enumeration types. */
|
/* Enumeration types. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UNSPECIFIED, NIX_FILE, DOS_FILE, MAC_FILE
|
UNSPECIFIED, NIX_FILE, DOS_FILE, MAC_FILE
|
||||||
@ -313,7 +339,6 @@ enum {
|
|||||||
CASE_SENSITIVE,
|
CASE_SENSITIVE,
|
||||||
CONSTANT_SHOW,
|
CONSTANT_SHOW,
|
||||||
NO_HELP,
|
NO_HELP,
|
||||||
SUSPENDABLE,
|
|
||||||
NO_WRAP,
|
NO_WRAP,
|
||||||
AUTOINDENT,
|
AUTOINDENT,
|
||||||
VIEW_MODE,
|
VIEW_MODE,
|
||||||
@ -361,6 +386,12 @@ enum {
|
|||||||
ZERO
|
ZERO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FOUND_BRACKET = 0,
|
||||||
|
NOT_FOUND_BRACKET,
|
||||||
|
NOT_A_BRACKET
|
||||||
|
} bracket_search_result;
|
||||||
|
|
||||||
/* Structure types. */
|
/* Structure types. */
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
typedef struct colortype {
|
typedef struct colortype {
|
||||||
@ -419,7 +450,7 @@ typedef struct syntaxtype {
|
|||||||
/* The command with which to lint this type of file. */
|
/* The command with which to lint this type of file. */
|
||||||
char *formatter;
|
char *formatter;
|
||||||
/* The command with which to format/modify/arrange this type of file. */
|
/* The command with which to format/modify/arrange this type of file. */
|
||||||
char *tab;
|
char *tabstring;
|
||||||
/* What the Tab key should produce; NULL for default behavior. */
|
/* What the Tab key should produce; NULL for default behavior. */
|
||||||
#ifdef ENABLE_COMMENT
|
#ifdef ENABLE_COMMENT
|
||||||
char *comment;
|
char *comment;
|
||||||
@ -467,6 +498,10 @@ typedef struct linestruct {
|
|||||||
bool has_anchor;
|
bool has_anchor;
|
||||||
/* Whether the user has placed an anchor at this line. */
|
/* Whether the user has placed an anchor at this line. */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
bool folded;
|
||||||
|
/* Whether or not this line is in a fold segment */
|
||||||
|
#endif
|
||||||
} linestruct;
|
} linestruct;
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -622,17 +657,14 @@ typedef struct keystruct {
|
|||||||
typedef struct funcstruct {
|
typedef struct funcstruct {
|
||||||
void (*func)(void);
|
void (*func)(void);
|
||||||
/* The actual function to call. */
|
/* The actual function to call. */
|
||||||
const char *desc;
|
const char *tag;
|
||||||
/* The function's short description, for example "Where Is". */
|
/* The function's help-line label, for example "Where Is". */
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
const char *help;
|
const char *phrase;
|
||||||
/* The help-screen text for this function. */
|
/* The function's description for in the help viewer. */
|
||||||
bool blank_after;
|
bool blank_after;
|
||||||
/* Whether there should be a blank line after the help text
|
/* Whether to distance this function from the next in the help viewer. */
|
||||||
* for this function. */
|
|
||||||
#endif
|
#endif
|
||||||
bool viewok;
|
|
||||||
/* Is this function allowed when in view mode? */
|
|
||||||
int menus;
|
int menus;
|
||||||
/* In what menus this function applies. */
|
/* In what menus this function applies. */
|
||||||
struct funcstruct *next;
|
struct funcstruct *next;
|
||||||
|
|||||||
346
src/files.c
346
src/files.c
@ -1,8 +1,8 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* files.c -- This file is part of GNU nano. *
|
* files.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2015-2021 Benno Schulenberg *
|
* Copyright (C) 2015-2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -33,6 +33,10 @@
|
|||||||
|
|
||||||
#define RW_FOR_ALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
#define RW_FOR_ALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||||
|
|
||||||
|
#ifndef HAVE_FSYNC
|
||||||
|
# define fsync(...) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Add an item to the circular list of openfile structs. */
|
/* Add an item to the circular list of openfile structs. */
|
||||||
void make_new_buffer(void)
|
void make_new_buffer(void)
|
||||||
{
|
{
|
||||||
@ -53,7 +57,7 @@ void make_new_buffer(void)
|
|||||||
openfile->next = newnode;
|
openfile->next = newnode;
|
||||||
|
|
||||||
/* There is more than one buffer: show "Close" in help lines. */
|
/* There is more than one buffer: show "Close" in help lines. */
|
||||||
exitfunc->desc = close_tag;
|
exitfunc->tag = close_tag;
|
||||||
more_than_one = !inhelp || more_than_one;
|
more_than_one = !inhelp || more_than_one;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -143,7 +147,7 @@ const char *locking_suffix = ".swp";
|
|||||||
* existing version of that file. Return TRUE on success; FALSE otherwise. */
|
* existing version of that file. Return TRUE on success; FALSE otherwise. */
|
||||||
bool write_lockfile(const char *lockfilename, const char *filename, bool modified)
|
bool write_lockfile(const char *lockfilename, const char *filename, bool modified)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PWD_H
|
#if defined(HAVE_PWD_H) && defined(HAVE_GETEUID)
|
||||||
pid_t mypid = getpid();
|
pid_t mypid = getpid();
|
||||||
uid_t myuid = geteuid();
|
uid_t myuid = geteuid();
|
||||||
struct passwd *mypwuid = getpwuid(myuid);
|
struct passwd *mypwuid = getpwuid(myuid);
|
||||||
@ -214,7 +218,7 @@ bool write_lockfile(const char *lockfilename, const char *filename, bool modifie
|
|||||||
strncpy(&lockdata[108], filename, 768);
|
strncpy(&lockdata[108], filename, 768);
|
||||||
lockdata[1007] = (modified) ? 0x55 : 0x00;
|
lockdata[1007] = (modified) ? 0x55 : 0x00;
|
||||||
|
|
||||||
wroteamt = fwrite(lockdata, sizeof(char), LOCKSIZE, filestream);
|
wroteamt = fwrite(lockdata, 1, LOCKSIZE, filestream);
|
||||||
|
|
||||||
free(lockdata);
|
free(lockdata);
|
||||||
|
|
||||||
@ -303,14 +307,14 @@ char *do_lockfile(const char *filename, bool ask_the_user)
|
|||||||
free(postedname);
|
free(postedname);
|
||||||
free(pidstring);
|
free(pidstring);
|
||||||
|
|
||||||
choice = do_yesno_prompt(FALSE, promptstr);
|
choice = ask_user(YESORNO, promptstr);
|
||||||
free(promptstr);
|
free(promptstr);
|
||||||
|
|
||||||
/* When the user cancelled while we're still starting up, quit. */
|
/* When the user cancelled while we're still starting up, quit. */
|
||||||
if (choice < 0 && !we_are_running)
|
if (choice == CANCEL && !we_are_running)
|
||||||
finish();
|
finish();
|
||||||
|
|
||||||
if (choice < 1) {
|
if (choice != YES) {
|
||||||
free(lockfilename);
|
free(lockfilename);
|
||||||
wipe_statusbar();
|
wipe_statusbar();
|
||||||
return SKIPTHISFILE;
|
return SKIPTHISFILE;
|
||||||
@ -346,8 +350,18 @@ bool has_valid_path(const char *filename)
|
|||||||
char *parentdir = dirname(namecopy);
|
char *parentdir = dirname(namecopy);
|
||||||
struct stat parentinfo;
|
struct stat parentinfo;
|
||||||
bool validity = FALSE;
|
bool validity = FALSE;
|
||||||
|
bool gone = FALSE;
|
||||||
|
|
||||||
if (stat(parentdir, &parentinfo) == -1) {
|
if (strcmp(parentdir, ".") == 0) {
|
||||||
|
char *currentdir = realpath(".", NULL);
|
||||||
|
|
||||||
|
gone = (currentdir == NULL && errno == ENOENT);
|
||||||
|
free(currentdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gone)
|
||||||
|
statusline(ALERT, _("The working directory has disappeared"));
|
||||||
|
else if (stat(parentdir, &parentinfo) == -1) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
/* TRANSLATORS: Keep the next ten messages at most 76 characters. */
|
/* TRANSLATORS: Keep the next ten messages at most 76 characters. */
|
||||||
statusline(ALERT, _("Directory '%s' does not exist"), parentdir);
|
statusline(ALERT, _("Directory '%s' does not exist"), parentdir);
|
||||||
@ -411,7 +425,7 @@ bool open_buffer(const char *filename, bool new_one)
|
|||||||
free(realname);
|
free(realname);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(HAVE_GETEUID)
|
||||||
if (new_one && !(fileinfo.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) &&
|
if (new_one && !(fileinfo.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) &&
|
||||||
geteuid() == ROOT_UID)
|
geteuid() == ROOT_UID)
|
||||||
statusline(ALERT, _("%s is meant to be read-only"), realname);
|
statusline(ALERT, _("%s is meant to be read-only"), realname);
|
||||||
@ -521,7 +535,8 @@ void mention_name_and_linecount(void)
|
|||||||
if (ISSET(MINIBAR)) {
|
if (ISSET(MINIBAR)) {
|
||||||
report_size = TRUE;
|
report_size = TRUE;
|
||||||
return;
|
return;
|
||||||
}
|
} else if (ISSET(ZERO))
|
||||||
|
return;
|
||||||
|
|
||||||
if (openfile->fmt > NIX_FILE)
|
if (openfile->fmt > NIX_FILE)
|
||||||
/* TRANSLATORS: First %s is file name, second %s is file format. */
|
/* TRANSLATORS: First %s is file name, second %s is file format. */
|
||||||
@ -560,13 +575,14 @@ void redecorate_after_switch(void)
|
|||||||
/* Prevent a possible Shift selection from getting cancelled. */
|
/* Prevent a possible Shift selection from getting cancelled. */
|
||||||
shift_held = TRUE;
|
shift_held = TRUE;
|
||||||
|
|
||||||
|
/* If the switched-to buffer gave an error during opening, show the message
|
||||||
|
* once; otherwise, indicate on the status bar which file we switched to. */
|
||||||
if (openfile->errormessage) {
|
if (openfile->errormessage) {
|
||||||
statusline(ALERT, openfile->errormessage);
|
statusline(ALERT, openfile->errormessage);
|
||||||
free(openfile->errormessage);
|
free(openfile->errormessage);
|
||||||
openfile->errormessage = NULL;
|
openfile->errormessage = NULL;
|
||||||
} else
|
} else
|
||||||
/* Indicate on the status bar where we switched to. */
|
mention_name_and_linecount();
|
||||||
mention_name_and_linecount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Switch to the previous entry in the circular list of buffers. */
|
/* Switch to the previous entry in the circular list of buffers. */
|
||||||
@ -612,7 +628,7 @@ void close_buffer(void)
|
|||||||
|
|
||||||
/* When just one buffer remains open, show "Exit" in the help lines. */
|
/* When just one buffer remains open, show "Exit" in the help lines. */
|
||||||
if (openfile && openfile == openfile->next)
|
if (openfile && openfile == openfile->next)
|
||||||
exitfunc->desc = exit_tag;
|
exitfunc->tag = exit_tag;
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_MULTIBUFFER */
|
#endif /* ENABLE_MULTIBUFFER */
|
||||||
|
|
||||||
@ -666,6 +682,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
|||||||
if (ISSET(SOFTWRAP))
|
if (ISSET(SOFTWRAP))
|
||||||
was_leftedge = leftedge_for(xplustabs(), openfile->current);
|
was_leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||||
#endif
|
#endif
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
|
||||||
/* Create an empty buffer. */
|
/* Create an empty buffer. */
|
||||||
topline = make_new_node(NULL);
|
topline = make_new_node(NULL);
|
||||||
@ -675,9 +692,13 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
|||||||
block_sigwinch(TRUE);
|
block_sigwinch(TRUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FLOCKFILE
|
||||||
/* Lock the file before starting to read it, to avoid the overhead
|
/* Lock the file before starting to read it, to avoid the overhead
|
||||||
* of locking it for each single byte that we read from it. */
|
* of locking it for each single byte that we read from it. */
|
||||||
flockfile(f);
|
flockfile(f);
|
||||||
|
#else
|
||||||
|
# define getc_unlocked getc
|
||||||
|
#endif
|
||||||
|
|
||||||
control_C_was_pressed = FALSE;
|
control_C_was_pressed = FALSE;
|
||||||
|
|
||||||
@ -741,8 +762,10 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
|||||||
|
|
||||||
errornumber = errno;
|
errornumber = errno;
|
||||||
|
|
||||||
|
#ifdef HAVE_FUNLOCKFILE
|
||||||
/* We are done with the file, unlock it. */
|
/* We are done with the file, unlock it. */
|
||||||
funlockfile(f);
|
funlockfile(f);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
block_sigwinch(FALSE);
|
block_sigwinch(FALSE);
|
||||||
@ -826,12 +849,14 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
|||||||
report_size = TRUE;
|
report_size = TRUE;
|
||||||
|
|
||||||
/* If we inserted less than a screenful, don't center the cursor. */
|
/* If we inserted less than a screenful, don't center the cursor. */
|
||||||
if (undoable && less_than_a_screenful(was_lineno, was_leftedge))
|
if (undoable && less_than_a_screenful(was_lineno, was_leftedge)) {
|
||||||
focusing = FALSE;
|
focusing = FALSE;
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
else if (undoable)
|
perturbed = TRUE;
|
||||||
precalc_multicolorinfo();
|
} else if (undoable) {
|
||||||
|
recook = TRUE;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (undoable)
|
if (undoable)
|
||||||
@ -946,11 +971,20 @@ char *get_next_filename(const char *name, const char *suffix)
|
|||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
static pid_t pid_of_command = -1;
|
static pid_t pid_of_command = -1;
|
||||||
/* The PID of a forked process -- needed when wanting to abort it. */
|
/* The PID of a forked process -- needed when wanting to abort it. */
|
||||||
|
static pid_t pid_of_sender = -1;
|
||||||
|
/* The PID of the process that pipes data to the above process. */
|
||||||
|
static bool should_pipe = FALSE;
|
||||||
|
/* Whether we are piping data to the external command. */
|
||||||
|
|
||||||
/* Send an unconditional kill signal to the running external command. */
|
/* Send an unconditional kill signal to the running external command. */
|
||||||
void cancel_the_command(int signal)
|
void cancel_the_command(int signal)
|
||||||
{
|
{
|
||||||
kill(pid_of_command, SIGKILL);
|
#ifdef SIGKILL
|
||||||
|
if (pid_of_command > 0)
|
||||||
|
kill(pid_of_command, SIGKILL);
|
||||||
|
if (should_pipe && pid_of_sender > 0)
|
||||||
|
kill(pid_of_sender, SIGKILL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the text that starts at the given line to file descriptor fd. */
|
/* Send the text that starts at the given line to file descriptor fd. */
|
||||||
@ -963,28 +997,39 @@ void send_data(const linestruct *line, int fd)
|
|||||||
|
|
||||||
/* Send each line, except a final empty line. */
|
/* Send each line, except a final empty line. */
|
||||||
while (line != NULL && (line->next != NULL || line->data[0] != '\0')) {
|
while (line != NULL && (line->next != NULL || line->data[0] != '\0')) {
|
||||||
fprintf(tube, "%s%s", line->data, line->next == NULL ? "" : "\n");
|
size_t length = recode_LF_to_NUL(line->data);
|
||||||
|
|
||||||
|
if (fwrite(line->data, 1, length, tube) < length)
|
||||||
|
exit(5);
|
||||||
|
|
||||||
|
if (line->next && putc('\n', tube) == EOF)
|
||||||
|
exit(6);
|
||||||
|
|
||||||
line = line->next;
|
line = line->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(tube);
|
fclose(tube);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Execute the given command in a shell. Return TRUE on success. */
|
/* Execute the given command in a shell. */
|
||||||
bool execute_command(const char *command)
|
void execute_command(const char *command)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAIT)
|
||||||
int from_fd[2], to_fd[2];
|
int from_fd[2], to_fd[2];
|
||||||
/* The pipes through which text will be written and read. */
|
/* The pipes through which text will be written and read. */
|
||||||
struct sigaction oldaction, newaction = {{0}};
|
struct sigaction oldaction, newaction = {{0}};
|
||||||
/* Original and temporary handlers for SIGINT. */
|
/* Original and temporary handlers for SIGINT. */
|
||||||
const bool should_pipe = (command[0] == '|');
|
ssize_t was_lineno = (openfile->mark ? 0 : openfile->current->lineno);
|
||||||
|
int command_status, sender_status;
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
|
|
||||||
|
should_pipe = (command[0] == '|');
|
||||||
|
|
||||||
/* Create a pipe to read the command's output from, and, if needed,
|
/* Create a pipe to read the command's output from, and, if needed,
|
||||||
* a pipe to feed the command's input through. */
|
* a pipe to feed the command's input through. */
|
||||||
if (pipe(from_fd) == -1 || (should_pipe && pipe(to_fd) == -1)) {
|
if (pipe(from_fd) == -1 || (should_pipe && pipe(to_fd) == -1)) {
|
||||||
statusline(ALERT, _("Could not create pipe: %s"), strerror(errno));
|
statusline(ALERT, _("Could not create pipe: %s"), strerror(errno));
|
||||||
return FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fork a child process to run the command in. */
|
/* Fork a child process to run the command in. */
|
||||||
@ -1008,6 +1053,7 @@ bool execute_command(const char *command)
|
|||||||
if (should_pipe) {
|
if (should_pipe) {
|
||||||
if (dup2(to_fd[0], STDIN_FILENO) < 0)
|
if (dup2(to_fd[0], STDIN_FILENO) < 0)
|
||||||
exit(5);
|
exit(5);
|
||||||
|
close(from_fd[1]);
|
||||||
close(to_fd[1]);
|
close(to_fd[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1024,7 +1070,7 @@ bool execute_command(const char *command)
|
|||||||
if (pid_of_command == -1) {
|
if (pid_of_command == -1) {
|
||||||
statusline(ALERT, _("Could not fork: %s"), strerror(errno));
|
statusline(ALERT, _("Could not fork: %s"), strerror(errno));
|
||||||
close(from_fd[0]);
|
close(from_fd[0]);
|
||||||
return FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusbar(_("Executing..."));
|
statusbar(_("Executing..."));
|
||||||
@ -1054,16 +1100,20 @@ bool execute_command(const char *command)
|
|||||||
}
|
}
|
||||||
add_undo(CUT, NULL);
|
add_undo(CUT, NULL);
|
||||||
do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
|
do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
|
||||||
openfile->filetop->has_anchor = FALSE;
|
if (openfile->filetop->next == NULL)
|
||||||
|
openfile->filetop->has_anchor = FALSE;
|
||||||
update_undo(CUT);
|
update_undo(CUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a separate process for piping the data to the command. */
|
/* Create a separate process for piping the data to the command. */
|
||||||
if (fork() == 0) {
|
if ((pid_of_sender = fork()) == 0) {
|
||||||
send_data(whole_buffer ? openfile->filetop : cutbuffer, to_fd[1]);
|
send_data(whole_buffer ? openfile->filetop : cutbuffer, to_fd[1]);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pid_of_sender == -1)
|
||||||
|
statusline(ALERT, _("Could not fork: %s"), strerror(errno));
|
||||||
|
|
||||||
close(to_fd[0]);
|
close(to_fd[0]);
|
||||||
close(to_fd[1]);
|
close(to_fd[1]);
|
||||||
|
|
||||||
@ -1090,13 +1140,32 @@ bool execute_command(const char *command)
|
|||||||
else
|
else
|
||||||
read_file(stream, 0, "pipe", TRUE);
|
read_file(stream, 0, "pipe", TRUE);
|
||||||
|
|
||||||
if (should_pipe && !ISSET(MULTIBUFFER))
|
if (should_pipe && !ISSET(MULTIBUFFER)) {
|
||||||
|
if (was_lineno)
|
||||||
|
goto_line_posx(was_lineno, 0);
|
||||||
add_undo(COUPLE_END, N_("filtering"));
|
add_undo(COUPLE_END, N_("filtering"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait for the external command (and possibly data sender) to terminate. */
|
/* Wait for the external command (and possibly data sender) to terminate. */
|
||||||
wait(NULL);
|
waitpid(pid_of_command, &command_status, 0);
|
||||||
if (should_pipe)
|
if (should_pipe && pid_of_sender > 0)
|
||||||
wait(NULL);
|
waitpid(pid_of_sender, &sender_status, 0);
|
||||||
|
|
||||||
|
/* If the command failed, show what the shell reported. */
|
||||||
|
if (WIFEXITED(command_status) == 0 || WEXITSTATUS(command_status))
|
||||||
|
statusline(ALERT, WIFSIGNALED(command_status) ? _("Cancelled") :
|
||||||
|
_("Error: %s"), openfile->current->prev &&
|
||||||
|
strstr(openfile->current->prev->data, ": ") ?
|
||||||
|
strstr(openfile->current->prev->data, ": ") + 2 : "---");
|
||||||
|
else if (should_pipe && pid_of_sender > 0 &&
|
||||||
|
(WIFEXITED(sender_status) == 0 || WEXITSTATUS(sender_status)))
|
||||||
|
statusline(ALERT, _("Piping failed"));
|
||||||
|
|
||||||
|
/* If there was an error, undo and discard what the command did. */
|
||||||
|
if (lastmessage == ALERT) {
|
||||||
|
do_undo();
|
||||||
|
discard_until(openfile->current_undo);
|
||||||
|
}
|
||||||
|
|
||||||
/* Restore the original handler for SIGINT. */
|
/* Restore the original handler for SIGINT. */
|
||||||
sigaction(SIGINT, &oldaction, NULL);
|
sigaction(SIGINT, &oldaction, NULL);
|
||||||
@ -1104,8 +1173,7 @@ bool execute_command(const char *command)
|
|||||||
/* Restore the terminal to its desired state, and disable
|
/* Restore the terminal to its desired state, and disable
|
||||||
* interpretation of the special control keys again. */
|
* interpretation of the special control keys again. */
|
||||||
terminal_init();
|
terminal_init();
|
||||||
|
#endif
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
#endif /* NANO_TINY */
|
#endif /* NANO_TINY */
|
||||||
|
|
||||||
@ -1178,7 +1246,7 @@ void insert_a_file_or(bool execute)
|
|||||||
ssize_t was_current_lineno = openfile->current->lineno;
|
ssize_t was_current_lineno = openfile->current->lineno;
|
||||||
size_t was_current_x = openfile->current_x;
|
size_t was_current_x = openfile->current_x;
|
||||||
#if !defined(NANO_TINY) || defined(ENABLE_BROWSER) || defined(ENABLE_MULTIBUFFER)
|
#if !defined(NANO_TINY) || defined(ENABLE_BROWSER) || defined(ENABLE_MULTIBUFFER)
|
||||||
functionptrtype func = func_from_key(&response);
|
functionptrtype function = func_from_key(response);
|
||||||
#endif
|
#endif
|
||||||
given = mallocstrcpy(given, answer);
|
given = mallocstrcpy(given, answer);
|
||||||
|
|
||||||
@ -1186,7 +1254,7 @@ void insert_a_file_or(bool execute)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
#ifdef ENABLE_MULTIBUFFER
|
||||||
if (func == flip_newbuffer) {
|
if (function == flip_newbuffer) {
|
||||||
/* Allow toggling only when not in view mode. */
|
/* Allow toggling only when not in view mode. */
|
||||||
if (!ISSET(VIEW_MODE))
|
if (!ISSET(VIEW_MODE))
|
||||||
TOGGLE(MULTIBUFFER);
|
TOGGLE(MULTIBUFFER);
|
||||||
@ -1196,22 +1264,22 @@ void insert_a_file_or(bool execute)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (func == flip_convert) {
|
if (function == flip_convert) {
|
||||||
TOGGLE(NO_CONVERT);
|
TOGGLE(NO_CONVERT);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (func == flip_execute) {
|
if (function == flip_execute) {
|
||||||
execute = !execute;
|
execute = !execute;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (func == flip_pipe) {
|
if (function == flip_pipe) {
|
||||||
add_or_remove_pipe_symbol_from_answer();
|
add_or_remove_pipe_symbol_from_answer();
|
||||||
given = mallocstrcpy(given, answer);
|
given = mallocstrcpy(given, answer);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
if (func == to_files) {
|
if (function == to_files) {
|
||||||
char *chosen = browse_in(answer);
|
char *chosen = browse_in(answer);
|
||||||
|
|
||||||
/* If no file was chosen, go back to the prompt. */
|
/* If no file was chosen, go back to the prompt. */
|
||||||
@ -1322,106 +1390,37 @@ void do_execute(void)
|
|||||||
* absolute path (plus filename) when the path exists, and NULL when not. */
|
* absolute path (plus filename) when the path exists, and NULL when not. */
|
||||||
char *get_full_path(const char *origpath)
|
char *get_full_path(const char *origpath)
|
||||||
{
|
{
|
||||||
char *allocation, *here, *target, *last_slash;
|
char *untilded, *target, *slash;
|
||||||
char *just_filename = NULL;
|
|
||||||
int attempts = 0;
|
|
||||||
struct stat fileinfo;
|
struct stat fileinfo;
|
||||||
bool path_only;
|
|
||||||
|
|
||||||
if (origpath == NULL)
|
if (origpath == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
allocation = nmalloc(PATH_MAX + 1);
|
untilded = real_dir_from_tilde(origpath);
|
||||||
here = getcwd(allocation, PATH_MAX + 1);
|
target = realpath(untilded, NULL);
|
||||||
|
slash = strrchr(untilded, '/');
|
||||||
|
|
||||||
/* If getting the current directory failed, go up one level and try again,
|
/* If realpath() returned NULL, try without the last component,
|
||||||
* until we find an existing directory, and use that as the current one. */
|
* as this can be a file that does not exist yet. */
|
||||||
while (here == NULL && attempts < 20) {
|
if (!target && slash && slash[1]) {
|
||||||
IGNORE_CALL_RESULT(chdir(".."));
|
*slash = '\0';
|
||||||
here = getcwd(allocation, PATH_MAX + 1);
|
target = realpath(untilded, NULL);
|
||||||
attempts++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we found a directory, make sure its path ends in a slash. */
|
/* Upon success, re-add the last component of the original path. */
|
||||||
if (here != NULL) {
|
if (target) {
|
||||||
if (strcmp(here, "/") != 0) {
|
target = nrealloc(target, strlen(target) + strlen(slash + 1) + 1);
|
||||||
here = nrealloc(here, strlen(here) + 2);
|
strcat(target, slash + 1);
|
||||||
strcat(here, "/");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
here = copy_of("");
|
|
||||||
free(allocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
target = real_dir_from_tilde(origpath);
|
|
||||||
|
|
||||||
/* Determine whether the target path refers to a directory. If statting
|
|
||||||
* target fails, however, assume that it refers to a new, unsaved buffer. */
|
|
||||||
path_only = (stat(target, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
|
|
||||||
|
|
||||||
/* If the target is a directory, make sure its path ends in a slash. */
|
|
||||||
if (path_only) {
|
|
||||||
size_t length = strlen(target);
|
|
||||||
|
|
||||||
if (target[length - 1] != '/') {
|
|
||||||
target = nrealloc(target, length + 2);
|
|
||||||
strcat(target, "/");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
last_slash = strrchr(target, '/');
|
/* Ensure that a non-apex directory path ends with a slash. */
|
||||||
|
if (target && target[1] && stat(target, &fileinfo) == 0 &&
|
||||||
/* If the target path does not contain a slash, then it is a bare filename
|
S_ISDIR(fileinfo.st_mode)) {
|
||||||
* and must therefore be located in the working directory. */
|
target = nrealloc(target, strlen(target) + 2);
|
||||||
if (last_slash == NULL) {
|
strcat(target, "/");
|
||||||
just_filename = target;
|
|
||||||
target = here;
|
|
||||||
} else {
|
|
||||||
/* If target contains a filename, separate the two. */
|
|
||||||
if (!path_only) {
|
|
||||||
just_filename = copy_of(last_slash + 1);
|
|
||||||
*(last_slash + 1) = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we can't change to the target directory, give up. Otherwise,
|
|
||||||
* get the canonical path to this target directory. */
|
|
||||||
if (chdir(target) == -1) {
|
|
||||||
free(target);
|
|
||||||
target = NULL;
|
|
||||||
} else {
|
|
||||||
free(target);
|
|
||||||
|
|
||||||
allocation = nmalloc(PATH_MAX + 1);
|
|
||||||
target = getcwd(allocation, PATH_MAX + 1);
|
|
||||||
|
|
||||||
/* If we got a result, make sure it ends in a slash.
|
|
||||||
* Otherwise, ensure that we return NULL. */
|
|
||||||
if (target != NULL) {
|
|
||||||
if (strcmp(target, "/") != 0) {
|
|
||||||
target = nrealloc(target, strlen(target) + 2);
|
|
||||||
strcat(target, "/");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
path_only = TRUE;
|
|
||||||
free(allocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, go back to where we were before. We don't check
|
|
||||||
* for an error, since we can't do anything if we get one. */
|
|
||||||
IGNORE_CALL_RESULT(chdir(here));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(here);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we were given more than a bare path, concatenate the target path
|
free(untilded);
|
||||||
* with the filename portion to get the full, absolute file path. */
|
|
||||||
if (!path_only && target != NULL) {
|
|
||||||
target = nrealloc(target, strlen(target) + strlen(just_filename) + 1);
|
|
||||||
strcat(target, just_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(just_filename);
|
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
@ -1563,12 +1562,12 @@ int copy_file(FILE *inn, FILE *out, bool close_out)
|
|||||||
int (*flush_out_fnc)(FILE *) = (close_out) ? fclose : fflush;
|
int (*flush_out_fnc)(FILE *) = (close_out) ? fclose : fflush;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
charsread = fread(buf, sizeof(char), BUFSIZ, inn);
|
charsread = fread(buf, 1, BUFSIZ, inn);
|
||||||
if (charsread == 0 && ferror(inn)) {
|
if (charsread == 0 && ferror(inn)) {
|
||||||
retval = -1;
|
retval = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fwrite(buf, sizeof(char), charsread, out) < charsread) {
|
if (fwrite(buf, 1, charsread, out) < charsread) {
|
||||||
retval = 2;
|
retval = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1653,6 +1652,7 @@ bool make_backup_of(char *realname)
|
|||||||
if (backup_file == NULL)
|
if (backup_file == NULL)
|
||||||
goto problem;
|
goto problem;
|
||||||
|
|
||||||
|
#ifdef HAVE_FCHOWN
|
||||||
/* Try to change owner and group to those of the original file;
|
/* Try to change owner and group to those of the original file;
|
||||||
* ignore permission errors, as a normal user cannot change the owner. */
|
* ignore permission errors, as a normal user cannot change the owner. */
|
||||||
if (fchown(descriptor, openfile->statinfo->st_uid,
|
if (fchown(descriptor, openfile->statinfo->st_uid,
|
||||||
@ -1660,7 +1660,8 @@ bool make_backup_of(char *realname)
|
|||||||
fclose(backup_file);
|
fclose(backup_file);
|
||||||
goto problem;
|
goto problem;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FCHMOD
|
||||||
/* Set the backup's permissions to those of the original file.
|
/* Set the backup's permissions to those of the original file.
|
||||||
* It is not a security issue if this fails, as we have created
|
* It is not a security issue if this fails, as we have created
|
||||||
* the file with just read and write permission for the owner. */
|
* the file with just read and write permission for the owner. */
|
||||||
@ -1668,6 +1669,7 @@ bool make_backup_of(char *realname)
|
|||||||
fclose(backup_file);
|
fclose(backup_file);
|
||||||
goto problem;
|
goto problem;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
original = fopen(realname, "rb");
|
original = fopen(realname, "rb");
|
||||||
|
|
||||||
@ -1732,8 +1734,8 @@ bool make_backup_of(char *realname)
|
|||||||
* ask the user what to do, because if something goes wrong during the
|
* ask the user what to do, because if something goes wrong during the
|
||||||
* save of the file itself, its contents may be lost. */
|
* save of the file itself, its contents may be lost. */
|
||||||
/* TRANSLATORS: Try to keep this message at most 76 characters. */
|
/* TRANSLATORS: Try to keep this message at most 76 characters. */
|
||||||
if (errno != ENOSPC && do_yesno_prompt(FALSE, _("Cannot make backup; "
|
if (errno != ENOSPC && ask_user(YESORNO, _("Cannot make backup; "
|
||||||
"continue and save actual file? ")) == 1)
|
"continue and save actual file? ")) == YES)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* TRANSLATORS: The %s is the reason of failure. */
|
/* TRANSLATORS: The %s is the reason of failure. */
|
||||||
@ -1887,13 +1889,12 @@ bool write_file(const char *name, FILE *thefile, bool normal,
|
|||||||
statusbar(_("Writing..."));
|
statusbar(_("Writing..."));
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
size_t data_len = strlen(line->data);
|
size_t data_len, wrote;
|
||||||
size_t wrote;
|
|
||||||
|
|
||||||
/* Decode LFs as the NULs that they are, before writing to disk. */
|
/* Decode LFs as the NULs that they are, before writing to disk. */
|
||||||
recode_LF_to_NUL(line->data);
|
data_len = recode_LF_to_NUL(line->data);
|
||||||
|
|
||||||
wrote = fwrite(line->data, sizeof(char), data_len, thefile);
|
wrote = fwrite(line->data, 1, data_len, thefile);
|
||||||
|
|
||||||
/* Re-encode any embedded NULs as LFs. */
|
/* Re-encode any embedded NULs as LFs. */
|
||||||
recode_NUL_to_LF(line->data, data_len);
|
recode_NUL_to_LF(line->data, data_len);
|
||||||
@ -1974,6 +1975,19 @@ bool write_file(const char *name, FILE *thefile, bool normal,
|
|||||||
statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
|
statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
|
||||||
|
|
||||||
cleanup_and_exit:
|
cleanup_and_exit:
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
if (errno == ENOSPC && normal) {
|
||||||
|
napms(3200); lastmessage = VACUUM;
|
||||||
|
/* TRANSLATORS: This warns for data loss when the disk is full. */
|
||||||
|
statusline(ALERT, _("File on disk has been truncated!"));
|
||||||
|
napms(3200); lastmessage = VACUUM;
|
||||||
|
/* TRANSLATORS: This is a suggestion to the user,
|
||||||
|
* where "resume" means resuming from suspension.
|
||||||
|
* Try to keep this at most 76 characters. */
|
||||||
|
statusline(ALERT, _("Maybe ^T^Z, make room on disk, resume, then ^S^X"));
|
||||||
|
stat_with_alloc(realname, &openfile->statinfo);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
free(tempname);
|
free(tempname);
|
||||||
free(realname);
|
free(realname);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -2055,7 +2069,7 @@ bool write_region_to_file(const char *name, FILE *stream, bool normal,
|
|||||||
get_region(&topline, &top_x, &botline, &bot_x);
|
get_region(&topline, &top_x, &botline, &bot_x);
|
||||||
|
|
||||||
/* When needed, prepare a magic end line for the region. */
|
/* When needed, prepare a magic end line for the region. */
|
||||||
if (bot_x > 0 && !ISSET(NO_NEWLINES)) {
|
if (normal && bot_x > 0 && !ISSET(NO_NEWLINES)) {
|
||||||
stopper = make_new_node(botline);
|
stopper = make_new_node(botline);
|
||||||
stopper->data = copy_of("");
|
stopper->data = copy_of("");
|
||||||
} else
|
} else
|
||||||
@ -2112,10 +2126,10 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
functionptrtype func;
|
functionptrtype function;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
int response = 0;
|
int response = 0;
|
||||||
int choice = 0;
|
int choice = NO;
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
const char *formatstr = (openfile->fmt == DOS_FILE) ? _(" [DOS Format]") :
|
const char *formatstr = (openfile->fmt == DOS_FILE) ? _(" [DOS Format]") :
|
||||||
(openfile->fmt == MAC_FILE) ? _(" [Mac Format]") : "";
|
(openfile->fmt == MAC_FILE) ? _(" [Mac Format]") : "";
|
||||||
@ -2159,10 +2173,10 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
func = func_from_key(&response);
|
function = func_from_key(response);
|
||||||
|
|
||||||
/* Upon request, abandon the buffer. */
|
/* Upon request, abandon the buffer. */
|
||||||
if (func == discard_buffer) {
|
if (function == discard_buffer) {
|
||||||
free(given);
|
free(given);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
@ -2170,7 +2184,7 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
given = mallocstrcpy(given, answer);
|
given = mallocstrcpy(given, answer);
|
||||||
|
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
if (func == to_files) {
|
if (function == to_files) {
|
||||||
char *chosen = browse_in(answer);
|
char *chosen = browse_in(answer);
|
||||||
|
|
||||||
if (chosen == NULL)
|
if (chosen == NULL)
|
||||||
@ -2181,17 +2195,17 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (func == dos_format) {
|
if (function == dos_format) {
|
||||||
openfile->fmt = (openfile->fmt == DOS_FILE) ? NIX_FILE : DOS_FILE;
|
openfile->fmt = (openfile->fmt == DOS_FILE) ? NIX_FILE : DOS_FILE;
|
||||||
continue;
|
continue;
|
||||||
} else if (func == mac_format) {
|
} else if (function == mac_format) {
|
||||||
openfile->fmt = (openfile->fmt == MAC_FILE) ? NIX_FILE : MAC_FILE;
|
openfile->fmt = (openfile->fmt == MAC_FILE) ? NIX_FILE : MAC_FILE;
|
||||||
continue;
|
continue;
|
||||||
} else if (func == back_it_up) {
|
} else if (function == back_it_up) {
|
||||||
TOGGLE(MAKE_BACKUP);
|
TOGGLE(MAKE_BACKUP);
|
||||||
continue;
|
continue;
|
||||||
} else if (func == prepend_it || func == append_it) {
|
} else if (function == prepend_it || function == append_it) {
|
||||||
if (func == prepend_it)
|
if (function == prepend_it)
|
||||||
method = (method == PREPEND) ? OVERWRITE : PREPEND;
|
method = (method == PREPEND) ? OVERWRITE : PREPEND;
|
||||||
else
|
else
|
||||||
method = (method == APPEND) ? OVERWRITE : APPEND;
|
method = (method == APPEND) ? OVERWRITE : APPEND;
|
||||||
@ -2200,7 +2214,7 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (func == do_help)
|
if (function == do_help)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef ENABLE_EXTRA
|
#ifdef ENABLE_EXTRA
|
||||||
@ -2256,8 +2270,8 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
if (exiting || !openfile->mark)
|
if (exiting || !openfile->mark)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (do_yesno_prompt(FALSE, _("Save file under "
|
if (ask_user(YESORNO, _("Save file under "
|
||||||
"DIFFERENT NAME? ")) < 1)
|
"DIFFERENT NAME? ")) != YES)
|
||||||
continue;
|
continue;
|
||||||
maychange = TRUE;
|
maychange = TRUE;
|
||||||
}
|
}
|
||||||
@ -2270,12 +2284,12 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
|
|
||||||
sprintf(message, question, name);
|
sprintf(message, question, name);
|
||||||
|
|
||||||
choice = do_yesno_prompt(FALSE, message);
|
choice = ask_user(YESORNO, message);
|
||||||
|
|
||||||
free(message);
|
free(message);
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
if (choice < 1)
|
if (choice != YES)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2291,7 +2305,7 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
warn_and_briefly_pause(_("File on disk has changed"));
|
warn_and_briefly_pause(_("File on disk has changed"));
|
||||||
|
|
||||||
/* TRANSLATORS: Try to keep this at most 76 characters. */
|
/* TRANSLATORS: Try to keep this at most 76 characters. */
|
||||||
choice = do_yesno_prompt(FALSE, _("File was modified "
|
choice = ask_user(YESORNO, _("File was modified "
|
||||||
"since you opened it; continue saving? "));
|
"since you opened it; continue saving? "));
|
||||||
wipe_statusbar();
|
wipe_statusbar();
|
||||||
|
|
||||||
@ -2299,14 +2313,16 @@ int write_it_out(bool exiting, bool withprompt)
|
|||||||
* overwrite the file right here when requested. */
|
* overwrite the file right here when requested. */
|
||||||
if (ISSET(SAVE_ON_EXIT) && withprompt) {
|
if (ISSET(SAVE_ON_EXIT) && withprompt) {
|
||||||
free(given);
|
free(given);
|
||||||
if (choice == 1)
|
if (choice == YES)
|
||||||
return write_file(openfile->filename, NULL,
|
return write_file(openfile->filename, NULL,
|
||||||
NORMAL, OVERWRITE, NONOTES);
|
NORMAL, OVERWRITE, NONOTES);
|
||||||
else if (choice == 0)
|
else if (choice == NO) /* Discard buffer */
|
||||||
return 2;
|
return 2;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
} else if (choice != 1) {
|
} else if (choice == CANCEL && exiting) {
|
||||||
|
continue;
|
||||||
|
} else if (choice != YES) {
|
||||||
free(given);
|
free(given);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2417,13 +2433,13 @@ int diralphasort(const void *va, const void *vb)
|
|||||||
/* Return TRUE when the given path is a directory. */
|
/* Return TRUE when the given path is a directory. */
|
||||||
bool is_dir(const char *path)
|
bool is_dir(const char *path)
|
||||||
{
|
{
|
||||||
char *realpath = real_dir_from_tilde(path);
|
char *thepath = real_dir_from_tilde(path);
|
||||||
struct stat fileinfo;
|
struct stat fileinfo;
|
||||||
bool retval;
|
bool retval;
|
||||||
|
|
||||||
retval = (stat(realpath, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
|
retval = (stat(thepath, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
|
||||||
|
|
||||||
free(realpath);
|
free(thepath);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -2471,8 +2487,8 @@ char **username_completion(const char *morsel, size_t length, size_t *num_matche
|
|||||||
* This code is 'as is' with no warranty.
|
* This code is 'as is' with no warranty.
|
||||||
* This code may safely be consumed by a BSD or GPL license. */
|
* This code may safely be consumed by a BSD or GPL license. */
|
||||||
|
|
||||||
/* Try to complete the given fragment of given length to a filename. */
|
/* Try to complete the given fragment to an existing filename. */
|
||||||
char **filename_completion(const char *morsel, size_t length, size_t *num_matches)
|
char **filename_completion(const char *morsel, size_t *num_matches)
|
||||||
{
|
{
|
||||||
char *dirname = copy_of(morsel);
|
char *dirname = copy_of(morsel);
|
||||||
char *slash, *filename;
|
char *slash, *filename;
|
||||||
@ -2565,7 +2581,7 @@ char *input_tab(char *morsel, size_t *place, void (*refresh_func)(void), bool *l
|
|||||||
|
|
||||||
/* If there are no matches yet, try matching against filenames. */
|
/* If there are no matches yet, try matching against filenames. */
|
||||||
if (matches == NULL)
|
if (matches == NULL)
|
||||||
matches = filename_completion(morsel, *place, &num_matches);
|
matches = filename_completion(morsel, &num_matches);
|
||||||
|
|
||||||
/* If possible completions were listed before but none will be listed now... */
|
/* If possible completions were listed before but none will be listed now... */
|
||||||
if (*listed && num_matches < 2) {
|
if (*listed && num_matches < 2) {
|
||||||
@ -2664,23 +2680,23 @@ char *input_tab(char *morsel, size_t *place, void (*refresh_func)(void), bool *l
|
|||||||
for (match = 0; match < num_matches; match++) {
|
for (match = 0; match < num_matches; match++) {
|
||||||
char *disp;
|
char *disp;
|
||||||
|
|
||||||
wmove(edit, row, (longest_name + 2) * (match % ncols));
|
wmove(midwin, row, (longest_name + 2) * (match % ncols));
|
||||||
|
|
||||||
if (row == lastrow && (match + 1) % ncols == 0 &&
|
if (row == lastrow && (match + 1) % ncols == 0 &&
|
||||||
match + 1 < num_matches) {
|
match + 1 < num_matches) {
|
||||||
waddstr(edit, _("(more)"));
|
waddstr(midwin, _("(more)"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
disp = display_string(matches[match], 0, longest_name, FALSE, FALSE);
|
disp = display_string(matches[match], 0, longest_name, FALSE, FALSE);
|
||||||
waddstr(edit, disp);
|
waddstr(midwin, disp);
|
||||||
free(disp);
|
free(disp);
|
||||||
|
|
||||||
if ((match + 1) % ncols == 0)
|
if ((match + 1) % ncols == 0)
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
wnoutrefresh(edit);
|
wnoutrefresh(midwin);
|
||||||
*listed = TRUE;
|
*listed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
138
src/folding.c
Normal file
138
src/folding.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
* folding.c -- This file is part of GNU nano. *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2022 rexy712 *
|
||||||
|
* *
|
||||||
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, *
|
||||||
|
* or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* GNU nano is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* See the GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||||
|
* *
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "prototypes.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
/* isspace */
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
|
||||||
|
/* Remove a folded segment from the given line until end of segment */
|
||||||
|
void unfold_folded_segment_from(linestruct *line)
|
||||||
|
{
|
||||||
|
if (line != NULL)
|
||||||
|
refresh_needed = TRUE;
|
||||||
|
for(;line != NULL && line->folded;line = line->next)
|
||||||
|
line->folded = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove a folded segment containing the given line */
|
||||||
|
void unfold_folded_segment(linestruct *line)
|
||||||
|
{
|
||||||
|
unfold_folded_segment_from(get_start_of_folded_segment(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the first member of the folded segment */
|
||||||
|
linestruct *get_start_of_folded_segment(linestruct *line)
|
||||||
|
{
|
||||||
|
if (!line->folded)
|
||||||
|
return line;
|
||||||
|
|
||||||
|
while (line->prev != NULL && line->prev->folded)
|
||||||
|
line = line->prev;
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
/* Get the last member of the folded segment */
|
||||||
|
linestruct *get_end_of_folded_segment(linestruct *line)
|
||||||
|
{
|
||||||
|
if (!line->folded)
|
||||||
|
return line;
|
||||||
|
|
||||||
|
while (line->next != NULL && line->next->folded)
|
||||||
|
line = line->next;
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the span length of a folded_segment */
|
||||||
|
int get_folded_segment_length(linestruct *line)
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
if (!line->folded)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
line = get_start_of_folded_segment(line);
|
||||||
|
for (;line->next != NULL && line->next->folded;line = line->next)
|
||||||
|
++i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove any folded_segments within the range [top, bottom].
|
||||||
|
* Returns true if any segments are removed. */
|
||||||
|
bool do_unfold_segment(linestruct *line)
|
||||||
|
{
|
||||||
|
/* Attempt to find a bracketed region first.
|
||||||
|
* If not, top is unmodified. */
|
||||||
|
if (!line->folded) {
|
||||||
|
linestruct *bot;
|
||||||
|
find_bracketed_region(openfile->current, &line, &bot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line->folded) {
|
||||||
|
unfold_folded_segment(line);
|
||||||
|
move_cursor_to_proper_column();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fold the currently selected lines unless the current selection
|
||||||
|
* already contains a folded_segment. In that case, remove any
|
||||||
|
* segments that are selected. */
|
||||||
|
void do_fold_segment(void)
|
||||||
|
{
|
||||||
|
linestruct *top, *bot;
|
||||||
|
get_range(&top, &bot);
|
||||||
|
|
||||||
|
if (top == bot) {
|
||||||
|
/* First try to unfold if this line/bracketed region is folded */
|
||||||
|
if (do_unfold_segment(top))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* When not selecting multiple lines, try to find bounding
|
||||||
|
* brackets to act as top and bot. */
|
||||||
|
if (!find_bracketed_region(openfile->current, &top, &bot)) {
|
||||||
|
statusline(AHEM, _("No valid region found for automatic fold"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (linestruct* line = top;line != bot->next;line = line->next)
|
||||||
|
line->folded = TRUE;
|
||||||
|
|
||||||
|
if (top->lineno < openfile->edittop->lineno &&
|
||||||
|
bot->lineno > openfile->edittop->lineno)
|
||||||
|
openfile->edittop = top;
|
||||||
|
|
||||||
|
/* Place the cursor at the start of the fold segment.
|
||||||
|
* Anywhere else within the segment is invalid. */
|
||||||
|
if (openfile->current->folded)
|
||||||
|
openfile->current = get_start_of_folded_segment(top);
|
||||||
|
openfile->mark = NULL;
|
||||||
|
|
||||||
|
refresh_needed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ENABLE_FOLDING */
|
||||||
501
src/global.c
501
src/global.c
@ -1,8 +1,8 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* global.c -- This file is part of GNU nano. *
|
* global.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014-2020 Benno Schulenberg *
|
* Copyright (C) 2014-2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -107,6 +107,7 @@ int altpageup, altpagedown;
|
|||||||
int altinsert, altdelete;
|
int altinsert, altdelete;
|
||||||
int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
|
int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
|
||||||
#endif
|
#endif
|
||||||
|
int mousefocusin, mousefocusout;
|
||||||
|
|
||||||
#ifdef ENABLED_WRAPORJUSTIFY
|
#ifdef ENABLED_WRAPORJUSTIFY
|
||||||
ssize_t fill = -COLUMNS_FROM_EOL;
|
ssize_t fill = -COLUMNS_FROM_EOL;
|
||||||
@ -118,12 +119,12 @@ size_t wrap_at = 0;
|
|||||||
WINDOW *topwin = NULL;
|
WINDOW *topwin = NULL;
|
||||||
/* The top portion of the screen, showing the version number of nano,
|
/* The top portion of the screen, showing the version number of nano,
|
||||||
* the name of the file, and whether the buffer was modified. */
|
* the name of the file, and whether the buffer was modified. */
|
||||||
WINDOW *edit = NULL;
|
WINDOW *midwin = NULL;
|
||||||
/* The middle portion of the screen: the edit window, showing the
|
/* The middle portion of the screen: the edit window, showing the
|
||||||
* contents of the current buffer, the file we are editing. */
|
* contents of the current buffer, the file we are editing. */
|
||||||
WINDOW *bottomwin = NULL;
|
WINDOW *footwin = NULL;
|
||||||
/* The bottom portion of the screen, where we display statusbar
|
/* The bottom portion of the screen, where status-bar messages,
|
||||||
* messages, the status-bar prompt, and a list of shortcuts. */
|
* the status-bar prompt, and a list of shortcuts are shown. */
|
||||||
int editwinrows = 0;
|
int editwinrows = 0;
|
||||||
/* How many rows does the edit window take up? */
|
/* How many rows does the edit window take up? */
|
||||||
int editwincols = -1;
|
int editwincols = -1;
|
||||||
@ -201,6 +202,12 @@ char *syntaxstr = NULL;
|
|||||||
/* The color syntax name specified on the command line. */
|
/* The color syntax name specified on the command line. */
|
||||||
bool have_palette = FALSE;
|
bool have_palette = FALSE;
|
||||||
/* Whether the colors for the current syntax have been initialized. */
|
/* Whether the colors for the current syntax have been initialized. */
|
||||||
|
bool rescind_colors = FALSE;
|
||||||
|
/* Becomes TRUE when NO_COLOR is set in the environment. */
|
||||||
|
bool perturbed = FALSE;
|
||||||
|
/* Whether the multiline-coloring situation has changed. */
|
||||||
|
bool recook = FALSE;
|
||||||
|
/* Whether the multidata should be recalculated. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int currmenu = MMOST;
|
int currmenu = MMOST;
|
||||||
@ -260,6 +267,12 @@ char *startup_problem = NULL;
|
|||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
char *custom_nanorc = NULL;
|
char *custom_nanorc = NULL;
|
||||||
|
/* The argument of the --rcfile option, when given. */
|
||||||
|
|
||||||
|
char *commandname = NULL;
|
||||||
|
/* The name (of a function) between braces in a string bind. */
|
||||||
|
keystruct *planted_shortcut = NULL;
|
||||||
|
/* The function that the above name resolves to, if any. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool spotlighted = FALSE;
|
bool spotlighted = FALSE;
|
||||||
@ -274,11 +287,6 @@ size_t light_to_col = 0;
|
|||||||
#define NOVIEW FALSE
|
#define NOVIEW FALSE
|
||||||
#define BLANKAFTER TRUE /* A blank line after this one. */
|
#define BLANKAFTER TRUE /* A blank line after this one. */
|
||||||
#define TOGETHER FALSE
|
#define TOGETHER FALSE
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
|
||||||
#define CAN_OPEN_OTHER_BUFFER TRUE
|
|
||||||
#else
|
|
||||||
#define CAN_OPEN_OTHER_BUFFER FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Empty functions, for the most part corresponding to toggles. */
|
/* Empty functions, for the most part corresponding to toggles. */
|
||||||
void case_sens_void(void) {;}
|
void case_sens_void(void) {;}
|
||||||
@ -313,8 +321,8 @@ void discard_buffer(void) {;}
|
|||||||
void do_cancel(void) {;}
|
void do_cancel(void) {;}
|
||||||
|
|
||||||
/* Add a function to the linked list of functions. */
|
/* Add a function to the linked list of functions. */
|
||||||
void add_to_funcs(void (*func)(void), int menus, const char *desc,
|
void add_to_funcs(void (*function)(void), int menus, const char *tag,
|
||||||
const char *help, bool blank_after, bool viewok)
|
const char *phrase, bool blank_after)
|
||||||
{
|
{
|
||||||
funcstruct *f = nmalloc(sizeof(funcstruct));
|
funcstruct *f = nmalloc(sizeof(funcstruct));
|
||||||
|
|
||||||
@ -325,12 +333,11 @@ void add_to_funcs(void (*func)(void), int menus, const char *desc,
|
|||||||
tailfunc = f;
|
tailfunc = f;
|
||||||
|
|
||||||
f->next = NULL;
|
f->next = NULL;
|
||||||
f->func = func;
|
f->func = function;
|
||||||
f->menus = menus;
|
f->menus = menus;
|
||||||
f->desc = desc;
|
f->tag = tag;
|
||||||
f->viewok = viewok;
|
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
f->help = help;
|
f->phrase = phrase;
|
||||||
f->blank_after = blank_after;
|
f->blank_after = blank_after;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -382,7 +389,7 @@ int keycode_from_string(const char *keystring)
|
|||||||
|
|
||||||
/* Add a key combo to the linked list of shortcuts. */
|
/* Add a key combo to the linked list of shortcuts. */
|
||||||
void add_to_sclist(int menus, const char *scstring, const int keycode,
|
void add_to_sclist(int menus, const char *scstring, const int keycode,
|
||||||
void (*func)(void), int toggle)
|
void (*function)(void), int toggle)
|
||||||
{
|
{
|
||||||
static keystruct *tailsc;
|
static keystruct *tailsc;
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -399,7 +406,7 @@ void add_to_sclist(int menus, const char *scstring, const int keycode,
|
|||||||
|
|
||||||
/* Fill in the data. */
|
/* Fill in the data. */
|
||||||
sc->menus = menus;
|
sc->menus = menus;
|
||||||
sc->func = func;
|
sc->func = function;
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
sc->toggle = toggle;
|
sc->toggle = toggle;
|
||||||
/* When not the same toggle as the previous one, increment the ID. */
|
/* When not the same toggle as the previous one, increment the ID. */
|
||||||
@ -413,11 +420,11 @@ void add_to_sclist(int menus, const char *scstring, const int keycode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the first shortcut in the list of shortcuts that
|
/* Return the first shortcut in the list of shortcuts that
|
||||||
* matches the given func in the given menu. */
|
* matches the given function in the given menu. */
|
||||||
const keystruct *first_sc_for(int menu, void (*func)(void))
|
const keystruct *first_sc_for(int menu, void (*function)(void))
|
||||||
{
|
{
|
||||||
for (keystruct *sc = sclist; sc != NULL; sc = sc->next)
|
for (keystruct *sc = sclist; sc != NULL; sc = sc->next)
|
||||||
if ((sc->menus & menu) && sc->func == func && sc->keystr[0])
|
if ((sc->menus & menu) && sc->func == function && sc->keystr[0])
|
||||||
return sc;
|
return sc;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -445,24 +452,28 @@ size_t shown_entries_for(int menu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the first shortcut in the current menu that matches the given input. */
|
/* Return the first shortcut in the current menu that matches the given input. */
|
||||||
const keystruct *get_shortcut(int *keycode)
|
const keystruct *get_shortcut(const int keycode)
|
||||||
{
|
{
|
||||||
/* Plain characters and upper control codes cannot be shortcuts. */
|
/* Plain characters and upper control codes cannot be shortcuts. */
|
||||||
if (!meta_key && 0x20 <= *keycode && *keycode <= 0xFF)
|
if (!meta_key && 0x20 <= keycode && keycode <= 0xFF)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Lower control codes with Meta cannot be shortcuts either. */
|
/* Lower control codes with Meta cannot be shortcuts either. */
|
||||||
if (meta_key && *keycode < 0x20)
|
if (meta_key && keycode < 0x20)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* During a paste at a prompt, ignore all command keycodes. */
|
/* During a paste at a prompt, ignore all command keycodes. */
|
||||||
if (bracketed_paste && *keycode != BRACKETED_PASTE_MARKER)
|
if (bracketed_paste && keycode != BRACKETED_PASTE_MARKER)
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_NANORC
|
||||||
|
if (keycode == PLANTED_A_COMMAND)
|
||||||
|
return planted_shortcut;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (keystruct *sc = sclist; sc != NULL; sc = sc->next) {
|
for (keystruct *sc = sclist; sc != NULL; sc = sc->next) {
|
||||||
if ((sc->menus & currmenu) && *keycode == sc->keycode)
|
if ((sc->menus & currmenu) && keycode == sc->keycode)
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +481,7 @@ const keystruct *get_shortcut(int *keycode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return a pointer to the function that is bound to the given key. */
|
/* Return a pointer to the function that is bound to the given key. */
|
||||||
functionptrtype func_from_key(int *keycode)
|
functionptrtype func_from_key(const int keycode)
|
||||||
{
|
{
|
||||||
const keystruct *sc = get_shortcut(keycode);
|
const keystruct *sc = get_shortcut(keycode);
|
||||||
|
|
||||||
@ -481,15 +492,15 @@ functionptrtype func_from_key(int *keycode)
|
|||||||
/* Return the function that is bound to the given key in the file browser or
|
/* Return the function that is bound to the given key in the file browser or
|
||||||
* the help viewer. Accept also certain plain characters, for compatibility
|
* the help viewer. Accept also certain plain characters, for compatibility
|
||||||
* with Pico or to mimic 'less' and similar text viewers. */
|
* with Pico or to mimic 'less' and similar text viewers. */
|
||||||
functionptrtype interpret(int *keycode)
|
functionptrtype interpret(const int keycode)
|
||||||
{
|
{
|
||||||
if (!meta_key) {
|
if (!meta_key) {
|
||||||
if (*keycode == 'N')
|
if (keycode == 'N')
|
||||||
return do_findprevious;
|
return do_findprevious;
|
||||||
if (*keycode == 'n')
|
if (keycode == 'n')
|
||||||
return do_findnext;
|
return do_findnext;
|
||||||
|
|
||||||
switch (tolower(*keycode)) {
|
switch (tolower(keycode)) {
|
||||||
case 'b':
|
case 'b':
|
||||||
case '-':
|
case '-':
|
||||||
return do_page_up;
|
return do_page_up;
|
||||||
@ -602,7 +613,7 @@ void shortcut_init(void)
|
|||||||
const char *nextfile_gist = N_("Switch to the next file buffer");
|
const char *nextfile_gist = N_("Switch to the next file buffer");
|
||||||
#endif
|
#endif
|
||||||
const char *verbatim_gist = N_("Insert the next keystroke verbatim");
|
const char *verbatim_gist = N_("Insert the next keystroke verbatim");
|
||||||
const char *tab_gist = N_("Insert a tab at the cursor position");
|
const char *tab_gist = N_("Insert a tab at the cursor position (or indent marked lines)");
|
||||||
const char *enter_gist = N_("Insert a newline at the cursor position");
|
const char *enter_gist = N_("Insert a newline at the cursor position");
|
||||||
const char *delete_gist = N_("Delete the character under the cursor");
|
const char *delete_gist = N_("Delete the character under the cursor");
|
||||||
const char *backspace_gist =
|
const char *backspace_gist =
|
||||||
@ -621,7 +632,7 @@ void shortcut_init(void)
|
|||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
const char *wordcount_gist =
|
const char *wordcount_gist =
|
||||||
N_("Count the number of words, lines, and characters");
|
N_("Count the number of lines, words, and characters");
|
||||||
const char *suspend_gist = N_("Suspend the editor (return to the shell)");
|
const char *suspend_gist = N_("Suspend the editor (return to the shell)");
|
||||||
#endif
|
#endif
|
||||||
const char *refresh_gist = N_("Refresh (redraw) the current screen");
|
const char *refresh_gist = N_("Refresh (redraw) the current screen");
|
||||||
@ -635,6 +646,9 @@ void shortcut_init(void)
|
|||||||
const char *savefile_gist = N_("Save file without prompting");
|
const char *savefile_gist = N_("Save file without prompting");
|
||||||
const char *findprev_gist = N_("Search next occurrence backward");
|
const char *findprev_gist = N_("Search next occurrence backward");
|
||||||
const char *findnext_gist = N_("Search next occurrence forward");
|
const char *findnext_gist = N_("Search next occurrence forward");
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
const char *fold_gist = N_("Fold/unfold the currently selected lines");
|
||||||
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
const char *recordmacro_gist = N_("Start/stop recording a macro");
|
const char *recordmacro_gist = N_("Start/stop recording a macro");
|
||||||
const char *runmacro_gist = N_("Run the last recorded macro");
|
const char *runmacro_gist = N_("Run the last recorded macro");
|
||||||
@ -682,52 +696,54 @@ void shortcut_init(void)
|
|||||||
const char *browserrefresh_gist = N_("Refresh the file list");
|
const char *browserrefresh_gist = N_("Refresh the file list");
|
||||||
const char *gotodir_gist = N_("Go to directory");
|
const char *gotodir_gist = N_("Go to directory");
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
const char *lint_gist = N_("Invoke the linter, if available");
|
const char *lint_gist = N_("Invoke the linter, if available");
|
||||||
const char *prevlint_gist = N_("Go to previous linter msg");
|
const char *prevlint_gist = N_("Go to previous linter msg");
|
||||||
const char *nextlint_gist = N_("Go to next linter msg");
|
const char *nextlint_gist = N_("Go to next linter msg");
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
const char *formatter_gist =
|
const char *formatter_gist =
|
||||||
N_("Invoke a program to format/arrange/manipulate the buffer");
|
N_("Invoke a program to format/arrange/manipulate the buffer");
|
||||||
#endif
|
#endif
|
||||||
#endif /* ENABLE_HELP */
|
#endif /* ENABLE_HELP */
|
||||||
|
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
#define WITHORSANS(help) help
|
#define WHENHELP(description) description
|
||||||
#else
|
#else
|
||||||
#define WITHORSANS(help) ""
|
#define WHENHELP(description) ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Start populating the different menus with functions. */
|
/* Start populating the different menus with functions. */
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
add_to_funcs(do_help, (MMOST | MBROWSER) & ~MFINDINHELP,
|
add_to_funcs(do_help, (MMOST | MBROWSER) & ~MFINDINHELP,
|
||||||
/* TRANSLATORS: Try to keep the next thirteen strings at most 10 characters. */
|
/* TRANSLATORS: Try to keep the next thirteen strings at most 10 characters. */
|
||||||
N_("Help"), WITHORSANS(help_gist), TOGETHER, VIEW);
|
N_("Help"), WHENHELP(help_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_cancel, ((MMOST & ~MMAIN) | MYESNO),
|
add_to_funcs(do_cancel, ((MMOST & ~MMAIN) | MYESNO),
|
||||||
N_("Cancel"), WITHORSANS(cancel_gist), BLANKAFTER, VIEW);
|
N_("Cancel"), WHENHELP(cancel_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_exit, MMAIN,
|
add_to_funcs(do_exit, MMAIN,
|
||||||
exit_tag, WITHORSANS(exit_gist), TOGETHER, VIEW);
|
exit_tag, WHENHELP(exit_gist), TOGETHER);
|
||||||
/* Remember the entry for Exit, to be able to replace it with Close. */
|
/* Remember the entry for Exit, to be able to replace it with Close. */
|
||||||
exitfunc = tailfunc;
|
exitfunc = tailfunc;
|
||||||
|
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
add_to_funcs(do_exit, MBROWSER,
|
add_to_funcs(do_exit, MBROWSER,
|
||||||
close_tag, WITHORSANS(exitbrowser_gist), TOGETHER, VIEW);
|
close_tag, WHENHELP(exitbrowser_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ENABLE_HELP
|
#ifndef ENABLE_HELP
|
||||||
add_to_funcs(full_refresh, MMAIN|MREPLACE, "Refresh", "x", 0, VIEW);
|
add_to_funcs(full_refresh, MMAIN|MREPLACE, "Refresh", "x", 0);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(full_refresh, MINSERTFILE|MEXECUTE, "Refresh", "x", 0, VIEW);
|
add_to_funcs(full_refresh, MINSERTFILE|MEXECUTE, "Refresh", "x", 0);
|
||||||
#endif
|
#endif
|
||||||
add_to_funcs(flip_goto, MWHEREIS, "Go To Line", "x", 0, VIEW);
|
add_to_funcs(flip_goto, MWHEREIS, "Go To Line", "x", 0);
|
||||||
add_to_funcs(flip_goto, MGOTOLINE, "Go To Text", "x", 0, VIEW);
|
add_to_funcs(flip_goto, MGOTOLINE, "Go To Text", "x", 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_writeout, MMAIN,
|
add_to_funcs(do_writeout, MMAIN,
|
||||||
N_("Write Out"), WITHORSANS(writeout_gist), TOGETHER, NOVIEW);
|
N_("Write Out"), WHENHELP(writeout_gist), TOGETHER);
|
||||||
|
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
/* In restricted mode, replace Insert with Justify, when possible;
|
/* In restricted mode, replace Insert with Justify, when possible;
|
||||||
@ -735,358 +751,354 @@ void shortcut_init(void)
|
|||||||
if (!ISSET(RESTRICTED))
|
if (!ISSET(RESTRICTED))
|
||||||
#endif
|
#endif
|
||||||
add_to_funcs(do_insertfile, MMAIN,
|
add_to_funcs(do_insertfile, MMAIN,
|
||||||
N_("Read File"), WITHORSANS(readfile_gist), BLANKAFTER,
|
N_("Read File"), WHENHELP(readfile_gist), BLANKAFTER);
|
||||||
/* We allow inserting files in view mode if multibuffer mode
|
|
||||||
* is available, so that the user can view multiple files. */
|
|
||||||
CAN_OPEN_OTHER_BUFFER);
|
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
else
|
else
|
||||||
add_to_funcs(do_justify, MMAIN,
|
add_to_funcs(do_justify, MMAIN,
|
||||||
N_("Justify"), WITHORSANS(justify_gist), BLANKAFTER, NOVIEW);
|
N_("Justify"), WHENHELP(justify_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
/* The description ("x") and blank_after (0) are irrelevant,
|
/* The description ("x") and blank_after (0) are irrelevant,
|
||||||
* because the help viewer does not have a help text. */
|
* because the help viewer does not have a help text. */
|
||||||
add_to_funcs(full_refresh, MHELP, N_("Refresh"), "x", 0, VIEW);
|
add_to_funcs(full_refresh, MHELP, N_("Refresh"), "x", 0);
|
||||||
add_to_funcs(do_exit, MHELP, close_tag, "x", 0, VIEW);
|
add_to_funcs(do_exit, MHELP, close_tag, "x", 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_search_forward, MMAIN|MHELP,
|
add_to_funcs(do_search_forward, MMAIN|MHELP,
|
||||||
N_("Where Is"), WITHORSANS(whereis_gist), TOGETHER, VIEW);
|
N_("Where Is"), WHENHELP(whereis_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(do_replace, MMAIN,
|
add_to_funcs(do_replace, MMAIN,
|
||||||
N_("Replace"), WITHORSANS(replace_gist), TOGETHER, NOVIEW);
|
N_("Replace"), WHENHELP(replace_gist), TOGETHER);
|
||||||
|
|
||||||
#ifdef NANO_TINY
|
#ifdef NANO_TINY
|
||||||
add_to_funcs(do_search_backward, MHELP,
|
add_to_funcs(do_search_backward, MHELP,
|
||||||
N_("Where Was"), WITHORSANS(wherewas_gist), TOGETHER, VIEW);
|
N_("Where Was"), WHENHELP(wherewas_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(do_findprevious, MMAIN|MHELP,
|
add_to_funcs(do_findprevious, MMAIN|MHELP,
|
||||||
N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW);
|
N_("Previous"), WHENHELP(findprev_gist), TOGETHER);
|
||||||
add_to_funcs(do_findnext, MMAIN|MHELP,
|
add_to_funcs(do_findnext, MMAIN|MHELP,
|
||||||
N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW);
|
N_("Next"), WHENHELP(findnext_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(cut_text, MMAIN,
|
add_to_funcs(cut_text, MMAIN,
|
||||||
N_("Cut"), WITHORSANS(cut_gist), TOGETHER, NOVIEW);
|
N_("Cut"), WHENHELP(cut_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(paste_text, MMAIN,
|
add_to_funcs(paste_text, MMAIN,
|
||||||
N_("Paste"), WITHORSANS(paste_gist), BLANKAFTER, NOVIEW);
|
N_("Paste"), WHENHELP(paste_gist), BLANKAFTER);
|
||||||
|
|
||||||
if (!ISSET(RESTRICTED)) {
|
if (!ISSET(RESTRICTED)) {
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(do_execute, MMAIN,
|
add_to_funcs(do_execute, MMAIN,
|
||||||
N_("Execute"), WITHORSANS(execute_gist), TOGETHER, NOVIEW);
|
N_("Execute"), WHENHELP(execute_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
add_to_funcs(do_justify, MMAIN,
|
add_to_funcs(do_justify, MMAIN,
|
||||||
N_("Justify"), WITHORSANS(justify_gist), BLANKAFTER, NOVIEW);
|
N_("Justify"), WHENHELP(justify_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_funcs(report_cursor_position, MMAIN,
|
add_to_funcs(report_cursor_position, MMAIN,
|
||||||
/* TRANSLATORS: This refers to the position of the cursor. */
|
/* TRANSLATORS: This refers to the position of the cursor. */
|
||||||
N_("Location"), WITHORSANS(cursorpos_gist), TOGETHER, VIEW);
|
N_("Location"), WHENHELP(cursorpos_gist), TOGETHER);
|
||||||
|
|
||||||
#if defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
#if defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||||
/* Conditionally placing this one here or further on, to keep the
|
/* Conditionally placing this one here or further on, to keep the
|
||||||
* help items nicely paired in most conditions. */
|
* help items nicely paired in most conditions. */
|
||||||
add_to_funcs(do_gotolinecolumn, MMAIN,
|
add_to_funcs(do_gotolinecolumn, MMAIN,
|
||||||
N_("Go To Line"), WITHORSANS(gotoline_gist), BLANKAFTER, VIEW);
|
N_("Go To Line"), WHENHELP(gotoline_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(do_undo, MMAIN,
|
add_to_funcs(do_undo, MMAIN,
|
||||||
/* TRANSLATORS: Try to keep the next ten strings at most 12 characters. */
|
/* TRANSLATORS: Try to keep the next ten strings at most 12 characters. */
|
||||||
N_("Undo"), WITHORSANS(undo_gist), TOGETHER, NOVIEW);
|
N_("Undo"), WHENHELP(undo_gist), TOGETHER);
|
||||||
add_to_funcs(do_redo, MMAIN,
|
add_to_funcs(do_redo, MMAIN,
|
||||||
N_("Redo"), WITHORSANS(redo_gist), BLANKAFTER, NOVIEW);
|
N_("Redo"), WHENHELP(redo_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_mark, MMAIN,
|
add_to_funcs(do_mark, MMAIN,
|
||||||
N_("Set Mark"), WITHORSANS(mark_gist), TOGETHER, VIEW);
|
N_("Set Mark"), WHENHELP(mark_gist), TOGETHER);
|
||||||
add_to_funcs(copy_text, MMAIN,
|
add_to_funcs(copy_text, MMAIN,
|
||||||
N_("Copy"), WITHORSANS(copy_gist), BLANKAFTER, VIEW);
|
N_("Copy"), WHENHELP(copy_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(case_sens_void, MWHEREIS|MREPLACE,
|
add_to_funcs(case_sens_void, MWHEREIS|MREPLACE,
|
||||||
N_("Case Sens"), WITHORSANS(case_gist), TOGETHER, VIEW);
|
N_("Case Sens"), WHENHELP(case_gist), TOGETHER);
|
||||||
add_to_funcs(regexp_void, MWHEREIS|MREPLACE,
|
add_to_funcs(regexp_void, MWHEREIS|MREPLACE,
|
||||||
N_("Reg.exp."), WITHORSANS(regexp_gist), TOGETHER, VIEW);
|
N_("Reg.exp."), WHENHELP(regexp_gist), TOGETHER);
|
||||||
add_to_funcs(backwards_void, MWHEREIS|MREPLACE,
|
add_to_funcs(backwards_void, MWHEREIS|MREPLACE,
|
||||||
N_("Backwards"), WITHORSANS(reverse_gist), BLANKAFTER, VIEW);
|
N_("Backwards"), WHENHELP(reverse_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(flip_replace, MWHEREIS,
|
add_to_funcs(flip_replace, MWHEREIS,
|
||||||
N_("Replace"), WITHORSANS(replace_gist), BLANKAFTER, VIEW);
|
N_("Replace"), WHENHELP(replace_gist), BLANKAFTER);
|
||||||
add_to_funcs(flip_replace, MREPLACE,
|
add_to_funcs(flip_replace, MREPLACE,
|
||||||
N_("No Replace"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW);
|
N_("No Replace"), WHENHELP(whereis_gist), BLANKAFTER);
|
||||||
|
|
||||||
#ifdef ENABLE_HISTORIES
|
#ifdef ENABLE_HISTORIES
|
||||||
add_to_funcs(get_older_item, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE,
|
add_to_funcs(get_older_item, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE,
|
||||||
N_("Older"), WITHORSANS(older_gist), TOGETHER, VIEW);
|
N_("Older"), WHENHELP(older_gist), TOGETHER);
|
||||||
add_to_funcs(get_newer_item, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE,
|
add_to_funcs(get_newer_item, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE,
|
||||||
N_("Newer"), WITHORSANS(newer_gist), BLANKAFTER, VIEW);
|
N_("Newer"), WHENHELP(newer_gist), BLANKAFTER);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_HELP
|
|
||||||
add_to_funcs(flip_goto, MWHEREIS,
|
|
||||||
N_("Go To Line"), WITHORSANS(gotoline_gist), BLANKAFTER, VIEW);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
add_to_funcs(goto_dir, MBROWSER,
|
add_to_funcs(goto_dir, MBROWSER,
|
||||||
/* TRANSLATORS: Try to keep the next seven strings at most 10 characters. */
|
/* TRANSLATORS: Try to keep the next four strings at most 10 characters. */
|
||||||
N_("Go To Dir"), WITHORSANS(gotodir_gist), TOGETHER, VIEW);
|
N_("Go To Dir"), WHENHELP(gotodir_gist), TOGETHER);
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
add_to_funcs(full_refresh, MBROWSER,
|
add_to_funcs(full_refresh, MBROWSER,
|
||||||
N_("Refresh"), WITHORSANS(browserrefresh_gist), BLANKAFTER, VIEW);
|
N_("Refresh"), WHENHELP(browserrefresh_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
add_to_funcs(do_search_forward, MBROWSER,
|
add_to_funcs(do_search_forward, MBROWSER,
|
||||||
N_("Where Is"), WITHORSANS(browserwhereis_gist), TOGETHER, VIEW);
|
N_("Where Is"), WHENHELP(browserwhereis_gist), TOGETHER);
|
||||||
add_to_funcs(do_search_backward, MBROWSER,
|
add_to_funcs(do_search_backward, MBROWSER,
|
||||||
N_("Where Was"), WITHORSANS(browserwherewas_gist), TOGETHER, VIEW);
|
N_("Where Was"), WHENHELP(browserwherewas_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(do_findprevious, MBROWSER,
|
add_to_funcs(do_findprevious, MBROWSER,
|
||||||
N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW);
|
N_("Previous"), WHENHELP(findprev_gist), TOGETHER);
|
||||||
add_to_funcs(do_findnext, MBROWSER,
|
add_to_funcs(do_findnext, MBROWSER,
|
||||||
N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW);
|
N_("Next"), WHENHELP(findnext_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NANO_TINY
|
#ifdef NANO_TINY
|
||||||
add_to_funcs(to_prev_word, MMAIN,
|
add_to_funcs(to_prev_word, MMAIN,
|
||||||
"Prev Word", WITHORSANS(prevword_gist), TOGETHER, VIEW);
|
"Prev Word", WHENHELP(prevword_gist), TOGETHER);
|
||||||
add_to_funcs(to_next_word, MMAIN,
|
add_to_funcs(to_next_word, MMAIN,
|
||||||
"Next Word", WITHORSANS(nextword_gist), BLANKAFTER, VIEW);
|
"Next Word", WHENHELP(nextword_gist), BLANKAFTER);
|
||||||
#else
|
#else
|
||||||
add_to_funcs(do_find_bracket, MMAIN,
|
add_to_funcs(do_find_bracket, MMAIN,
|
||||||
N_("To Bracket"), WITHORSANS(bracket_gist), BLANKAFTER, VIEW);
|
N_("To Bracket"), WHENHELP(bracket_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_search_backward, MMAIN|MHELP,
|
add_to_funcs(do_search_backward, MMAIN|MHELP,
|
||||||
/* TRANSLATORS: This starts a backward search. */
|
/* TRANSLATORS: This starts a backward search. */
|
||||||
N_("Where Was"), WITHORSANS(wherewas_gist), TOGETHER, VIEW);
|
N_("Where Was"), WHENHELP(wherewas_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(do_findprevious, MMAIN|MHELP,
|
add_to_funcs(do_findprevious, MMAIN|MHELP,
|
||||||
/* TRANSLATORS: This refers to searching the preceding occurrence. */
|
/* TRANSLATORS: This refers to searching the preceding occurrence. */
|
||||||
N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW);
|
N_("Previous"), WHENHELP(findprev_gist), TOGETHER);
|
||||||
add_to_funcs(do_findnext, MMAIN|MHELP,
|
add_to_funcs(do_findnext, MMAIN|MHELP,
|
||||||
N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW);
|
N_("Next"), WHENHELP(findnext_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_left, MMAIN,
|
add_to_funcs(do_left, MMAIN,
|
||||||
/* TRANSLATORS: This means move the cursor one character back. */
|
/* TRANSLATORS: This means move the cursor one character back. */
|
||||||
N_("Back"), WITHORSANS(back_gist), TOGETHER, VIEW);
|
N_("Back"), WHENHELP(back_gist), TOGETHER);
|
||||||
add_to_funcs(do_right, MMAIN,
|
add_to_funcs(do_right, MMAIN,
|
||||||
N_("Forward"), WITHORSANS(forward_gist), TOGETHER, VIEW);
|
N_("Forward"), WHENHELP(forward_gist), TOGETHER);
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
add_to_funcs(do_left, MBROWSER,
|
add_to_funcs(do_left, MBROWSER,
|
||||||
N_("Back"), WITHORSANS(backfile_gist), TOGETHER, VIEW);
|
N_("Back"), WHENHELP(backfile_gist), TOGETHER);
|
||||||
add_to_funcs(do_right, MBROWSER,
|
add_to_funcs(do_right, MBROWSER,
|
||||||
N_("Forward"), WITHORSANS(forwardfile_gist), TOGETHER, VIEW);
|
N_("Forward"), WHENHELP(forwardfile_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(to_prev_word, MMAIN,
|
add_to_funcs(to_prev_word, MMAIN,
|
||||||
/* TRANSLATORS: Try to keep the next ten strings at most 12 characters. */
|
/* TRANSLATORS: Try to keep the next ten strings at most 12 characters. */
|
||||||
N_("Prev Word"), WITHORSANS(prevword_gist), TOGETHER, VIEW);
|
N_("Prev Word"), WHENHELP(prevword_gist), TOGETHER);
|
||||||
add_to_funcs(to_next_word, MMAIN,
|
add_to_funcs(to_next_word, MMAIN,
|
||||||
N_("Next Word"), WITHORSANS(nextword_gist), TOGETHER, VIEW);
|
N_("Next Word"), WHENHELP(nextword_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_home, MMAIN,
|
add_to_funcs(do_home, MMAIN,
|
||||||
N_("Home"), WITHORSANS(home_gist), TOGETHER, VIEW);
|
N_("Home"), WHENHELP(home_gist), TOGETHER);
|
||||||
add_to_funcs(do_end, MMAIN,
|
add_to_funcs(do_end, MMAIN,
|
||||||
N_("End"), WITHORSANS(end_gist), BLANKAFTER, VIEW);
|
N_("End"), WHENHELP(end_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_up, MMAIN|MBROWSER|MHELP,
|
add_to_funcs(do_up, MMAIN|MBROWSER|MHELP,
|
||||||
N_("Prev Line"), WITHORSANS(prevline_gist), TOGETHER, VIEW);
|
N_("Prev Line"), WHENHELP(prevline_gist), TOGETHER);
|
||||||
add_to_funcs(do_down, MMAIN|MBROWSER|MHELP,
|
add_to_funcs(do_down, MMAIN|MBROWSER|MHELP,
|
||||||
N_("Next Line"), WITHORSANS(nextline_gist), TOGETHER, VIEW);
|
N_("Next Line"), WHENHELP(nextline_gist), TOGETHER);
|
||||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||||
add_to_funcs(do_scroll_up, MMAIN,
|
add_to_funcs(do_scroll_up, MMAIN,
|
||||||
N_("Scroll Up"), WITHORSANS(scrollup_gist), TOGETHER, VIEW);
|
N_("Scroll Up"), WHENHELP(scrollup_gist), TOGETHER);
|
||||||
add_to_funcs(do_scroll_down, MMAIN,
|
add_to_funcs(do_scroll_down, MMAIN,
|
||||||
N_("Scroll Down"), WITHORSANS(scrolldown_gist), BLANKAFTER, VIEW);
|
N_("Scroll Down"), WHENHELP(scrolldown_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(to_prev_block, MMAIN,
|
add_to_funcs(to_prev_block, MMAIN,
|
||||||
N_("Prev Block"), WITHORSANS(prevblock_gist), TOGETHER, VIEW);
|
N_("Prev Block"), WHENHELP(prevblock_gist), TOGETHER);
|
||||||
add_to_funcs(to_next_block, MMAIN,
|
add_to_funcs(to_next_block, MMAIN,
|
||||||
N_("Next Block"), WITHORSANS(nextblock_gist), TOGETHER, VIEW);
|
N_("Next Block"), WHENHELP(nextblock_gist), TOGETHER);
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
add_to_funcs(to_para_begin, MMAIN|MGOTOLINE,
|
add_to_funcs(to_para_begin, MMAIN|MGOTOLINE,
|
||||||
/* TRANSLATORS: Try to keep these two strings at most 16 characters. */
|
/* TRANSLATORS: Try to keep these two strings at most 16 characters. */
|
||||||
N_("Begin of Paragr."), WITHORSANS(parabegin_gist), TOGETHER, VIEW);
|
N_("Begin of Paragr."), WHENHELP(parabegin_gist), TOGETHER);
|
||||||
add_to_funcs(to_para_end, MMAIN|MGOTOLINE,
|
add_to_funcs(to_para_end, MMAIN|MGOTOLINE,
|
||||||
N_("End of Paragraph"), WITHORSANS(paraend_gist), BLANKAFTER, VIEW);
|
N_("End of Paragraph"), WHENHELP(paraend_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_page_up, MMAIN|MHELP,
|
add_to_funcs(do_page_up, MMAIN|MHELP,
|
||||||
/* TRANSLATORS: Try to keep the next six strings at most 12 characters. */
|
/* TRANSLATORS: Try to keep the next six strings at most 12 characters. */
|
||||||
N_("Prev Page"), WITHORSANS(prevpage_gist), TOGETHER, VIEW);
|
N_("Prev Page"), WHENHELP(prevpage_gist), TOGETHER);
|
||||||
add_to_funcs(do_page_down, MMAIN|MHELP,
|
add_to_funcs(do_page_down, MMAIN|MHELP,
|
||||||
N_("Next Page"), WITHORSANS(nextpage_gist), TOGETHER, VIEW);
|
N_("Next Page"), WHENHELP(nextpage_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(to_first_line, MMAIN|MHELP|MGOTOLINE,
|
add_to_funcs(to_first_line, MMAIN|MHELP|MGOTOLINE,
|
||||||
N_("First Line"), WITHORSANS(firstline_gist), TOGETHER, VIEW);
|
N_("First Line"), WHENHELP(firstline_gist), TOGETHER);
|
||||||
add_to_funcs(to_last_line, MMAIN|MHELP|MGOTOLINE,
|
add_to_funcs(to_last_line, MMAIN|MHELP|MGOTOLINE,
|
||||||
N_("Last Line"), WITHORSANS(lastline_gist), BLANKAFTER, VIEW);
|
N_("Last Line"), WHENHELP(lastline_gist), BLANKAFTER);
|
||||||
|
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
#ifdef ENABLE_MULTIBUFFER
|
||||||
add_to_funcs(switch_to_prev_buffer, MMAIN,
|
add_to_funcs(switch_to_prev_buffer, MMAIN,
|
||||||
N_("Prev File"), WITHORSANS(prevfile_gist), TOGETHER, VIEW);
|
N_("Prev File"), WHENHELP(prevfile_gist), TOGETHER);
|
||||||
add_to_funcs(switch_to_next_buffer, MMAIN,
|
add_to_funcs(switch_to_next_buffer, MMAIN,
|
||||||
N_("Next File"), WITHORSANS(nextfile_gist), BLANKAFTER, VIEW);
|
N_("Next File"), WHENHELP(nextfile_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(NANO_TINY) && !defined(ENABLE_JUSTIFY)
|
#if !defined(NANO_TINY) && !defined(ENABLE_JUSTIFY)
|
||||||
add_to_funcs(do_gotolinecolumn, MMAIN,
|
add_to_funcs(do_gotolinecolumn, MMAIN,
|
||||||
N_("Go To Line"), WITHORSANS(gotoline_gist), BLANKAFTER, VIEW);
|
N_("Go To Line"), WHENHELP(gotoline_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_tab, MMAIN,
|
add_to_funcs(do_tab, MMAIN,
|
||||||
/* TRANSLATORS: The next four strings are names of keyboard keys. */
|
/* TRANSLATORS: The next four strings are names of keyboard keys. */
|
||||||
N_("Tab"), WITHORSANS(tab_gist), TOGETHER, NOVIEW);
|
N_("Tab"), WHENHELP(tab_gist), TOGETHER);
|
||||||
add_to_funcs(do_enter, MMAIN,
|
add_to_funcs(do_enter, MMAIN,
|
||||||
N_("Enter"), WITHORSANS(enter_gist), BLANKAFTER, NOVIEW);
|
N_("Enter"), WHENHELP(enter_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_backspace, MMAIN,
|
add_to_funcs(do_backspace, MMAIN,
|
||||||
N_("Backspace"), WITHORSANS(backspace_gist), TOGETHER, NOVIEW);
|
N_("Backspace"), WHENHELP(backspace_gist), TOGETHER);
|
||||||
add_to_funcs(do_delete, MMAIN,
|
add_to_funcs(do_delete, MMAIN,
|
||||||
N_("Delete"), WITHORSANS(delete_gist),
|
N_("Delete"), WHENHELP(delete_gist), BLANKAFTER);
|
||||||
#ifndef NANO_TINY
|
|
||||||
TOGETHER,
|
|
||||||
#else
|
|
||||||
BLANKAFTER,
|
|
||||||
#endif
|
|
||||||
NOVIEW);
|
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(chop_previous_word, MMAIN,
|
add_to_funcs(chop_previous_word, MMAIN,
|
||||||
/* TRANSLATORS: The next two strings refer to deleting words. */
|
/* TRANSLATORS: The next two strings refer to deleting words. */
|
||||||
N_("Chop Left"), WITHORSANS(chopwordleft_gist), TOGETHER, NOVIEW);
|
N_("Chop Left"), WHENHELP(chopwordleft_gist), TOGETHER);
|
||||||
add_to_funcs(chop_next_word, MMAIN,
|
add_to_funcs(chop_next_word, MMAIN,
|
||||||
N_("Chop Right"), WITHORSANS(chopwordright_gist), TOGETHER, NOVIEW);
|
N_("Chop Right"), WHENHELP(chopwordright_gist), TOGETHER);
|
||||||
add_to_funcs(cut_till_eof, MMAIN,
|
add_to_funcs(cut_till_eof, MMAIN,
|
||||||
N_("Cut Till End"), WITHORSANS(cuttilleof_gist), BLANKAFTER, NOVIEW);
|
N_("Cut Till End"), WHENHELP(cuttilleof_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
add_to_funcs(do_full_justify, MMAIN,
|
add_to_funcs(do_full_justify, MMAIN,
|
||||||
N_("Full Justify"), WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW);
|
N_("Full Justify"), WHENHELP(fulljustify_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(count_lines_words_and_characters, MMAIN,
|
add_to_funcs(count_lines_words_and_characters, MMAIN,
|
||||||
N_("Word Count"), WITHORSANS(wordcount_gist), TOGETHER, VIEW);
|
N_("Word Count"), WHENHELP(wordcount_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_verbatim_input, MMAIN,
|
add_to_funcs(do_verbatim_input, MMAIN,
|
||||||
N_("Verbatim"), WITHORSANS(verbatim_gist), BLANKAFTER, NOVIEW);
|
N_("Verbatim"), WHENHELP(verbatim_gist), BLANKAFTER);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifdef NANO_TINY
|
||||||
add_to_funcs(do_suspend, MMAIN,
|
add_to_funcs(do_search_backward, MMAIN,
|
||||||
N_("Suspend"), WITHORSANS(suspend_gist), TOGETHER, VIEW);
|
N_("Where Was"), WHENHELP(wherewas_gist), BLANKAFTER);
|
||||||
#endif
|
#else
|
||||||
#ifdef ENABLE_HELP
|
|
||||||
add_to_funcs(full_refresh, MMAIN,
|
|
||||||
N_("Refresh"), WITHORSANS(refresh_gist), BLANKAFTER, VIEW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
|
||||||
add_to_funcs(do_indent, MMAIN,
|
add_to_funcs(do_indent, MMAIN,
|
||||||
N_("Indent"), WITHORSANS(indent_gist), TOGETHER, NOVIEW);
|
N_("Indent"), WHENHELP(indent_gist), TOGETHER);
|
||||||
add_to_funcs(do_unindent, MMAIN,
|
add_to_funcs(do_unindent, MMAIN,
|
||||||
N_("Unindent"), WITHORSANS(unindent_gist), BLANKAFTER, NOVIEW);
|
N_("Unindent"), WHENHELP(unindent_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COMMENT
|
#ifdef ENABLE_COMMENT
|
||||||
add_to_funcs(do_comment, MMAIN,
|
add_to_funcs(do_comment, MMAIN,
|
||||||
N_("Comment Lines"), WITHORSANS(comment_gist), TOGETHER, NOVIEW);
|
N_("Comment Lines"), WHENHELP(comment_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_WORDCOMPLETION
|
#ifdef ENABLE_WORDCOMPLETION
|
||||||
add_to_funcs(complete_a_word, MMAIN,
|
add_to_funcs(complete_a_word, MMAIN,
|
||||||
N_("Complete"), WITHORSANS(completion_gist), BLANKAFTER, NOVIEW);
|
N_("Complete"), WHENHELP(completion_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(record_macro, MMAIN,
|
add_to_funcs(record_macro, MMAIN,
|
||||||
N_("Record"), WITHORSANS(recordmacro_gist), TOGETHER, VIEW);
|
N_("Record"), WHENHELP(recordmacro_gist), TOGETHER);
|
||||||
add_to_funcs(run_macro, MMAIN,
|
add_to_funcs(run_macro, MMAIN,
|
||||||
N_("Run Macro"), WITHORSANS(runmacro_gist), BLANKAFTER, VIEW);
|
N_("Run Macro"), WHENHELP(runmacro_gist), BLANKAFTER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
add_to_funcs(do_fold_segment, MMAIN, N_("Fold"),
|
||||||
|
WHENHELP(fold_gist), BLANKAFTER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
add_to_funcs(zap_text, MMAIN,
|
||||||
|
/* TRANSLATORS: This refers to deleting a line or marked region. */
|
||||||
|
N_("Zap"), WHENHELP(zap_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(put_or_lift_anchor, MMAIN,
|
add_to_funcs(put_or_lift_anchor, MMAIN,
|
||||||
N_("Anchor"), WITHORSANS(anchor_gist), TOGETHER, VIEW);
|
N_("Anchor"), WHENHELP(anchor_gist), TOGETHER);
|
||||||
add_to_funcs(to_prev_anchor, MMAIN,
|
add_to_funcs(to_prev_anchor, MMAIN,
|
||||||
N_("Up to anchor"), WITHORSANS(prevanchor_gist), TOGETHER, VIEW);
|
N_("Up to anchor"), WHENHELP(prevanchor_gist), TOGETHER);
|
||||||
add_to_funcs(to_next_anchor, MMAIN,
|
add_to_funcs(to_next_anchor, MMAIN,
|
||||||
N_("Down to anchor"), WITHORSANS(nextanchor_gist), BLANKAFTER, VIEW);
|
N_("Down to anchor"), WHENHELP(nextanchor_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(zap_text, MMAIN,
|
|
||||||
/* TRANSLATORS: This *deletes* a line or marked region. */
|
|
||||||
N_("Zap"), WITHORSANS(zap_gist), BLANKAFTER, NOVIEW);
|
|
||||||
|
|
||||||
if (!ISSET(RESTRICTED)) {
|
|
||||||
#ifdef ENABLE_SPELLER
|
#ifdef ENABLE_SPELLER
|
||||||
add_to_funcs(do_spell, MMAIN,
|
add_to_funcs(do_spell, MMAIN,
|
||||||
N_("Spell Check"), WITHORSANS(spell_gist), TOGETHER, NOVIEW);
|
N_("Spell Check"), WHENHELP(spell_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
add_to_funcs(do_linter, MMAIN,
|
add_to_funcs(do_linter, MMAIN,
|
||||||
N_("Linter"), WITHORSANS(lint_gist), TOGETHER, NOVIEW);
|
N_("Linter"), WHENHELP(lint_gist), TOGETHER);
|
||||||
add_to_funcs(do_formatter, MMAIN,
|
|
||||||
N_("Formatter"), WITHORSANS(formatter_gist), BLANKAFTER, NOVIEW);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
#ifdef ENABLE_FORMATTER
|
||||||
|
add_to_funcs(do_formatter, MMAIN,
|
||||||
|
N_("Formatter"), WHENHELP(formatter_gist), BLANKAFTER);
|
||||||
|
#endif
|
||||||
|
/* Although not allowed in restricted mode, keep execution rebindable. */
|
||||||
|
if (ISSET(RESTRICTED))
|
||||||
|
add_to_funcs(do_execute, MMAIN,
|
||||||
|
N_("Execute"), WHENHELP(execute_gist), TOGETHER);
|
||||||
|
|
||||||
|
add_to_funcs(do_suspend, MMAIN,
|
||||||
|
N_("Suspend"), WHENHELP(suspend_gist), TOGETHER);
|
||||||
#endif /* !NANO_TINY */
|
#endif /* !NANO_TINY */
|
||||||
|
|
||||||
#ifdef NANO_TINY
|
#ifdef ENABLE_HELP
|
||||||
add_to_funcs(do_search_backward, MMAIN,
|
add_to_funcs(full_refresh, MMAIN,
|
||||||
N_("Where Was"), WITHORSANS(wherewas_gist), BLANKAFTER, VIEW);
|
N_("Refresh"), WHENHELP(refresh_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||||
add_to_funcs(do_center, MMAIN,
|
add_to_funcs(do_center, MMAIN,
|
||||||
N_("Center"), WITHORSANS(center_gist), BLANKAFTER, VIEW);
|
N_("Center"), WHENHELP(center_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_to_funcs(do_savefile, MMAIN,
|
add_to_funcs(do_savefile, MMAIN,
|
||||||
N_("Save"), WITHORSANS(savefile_gist), BLANKAFTER, NOVIEW);
|
N_("Save"), WHENHELP(savefile_gist), BLANKAFTER);
|
||||||
|
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
#ifdef ENABLE_MULTIBUFFER
|
||||||
/* Multiple buffers are only available when not in restricted mode. */
|
/* Include the new-buffer toggle only when it can actually be used. */
|
||||||
if (!ISSET(RESTRICTED))
|
if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE))
|
||||||
add_to_funcs(flip_newbuffer, MINSERTFILE|MEXECUTE,
|
add_to_funcs(flip_newbuffer, MINSERTFILE|MEXECUTE,
|
||||||
N_("New Buffer"), WITHORSANS(newbuffer_gist), TOGETHER, NOVIEW);
|
N_("New Buffer"), WHENHELP(newbuffer_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(flip_pipe, MEXECUTE,
|
add_to_funcs(flip_pipe, MEXECUTE,
|
||||||
N_("Pipe Text"), WITHORSANS(pipe_gist), BLANKAFTER, NOVIEW);
|
N_("Pipe Text"), WHENHELP(pipe_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_SPELLER
|
#ifdef ENABLE_SPELLER
|
||||||
add_to_funcs(do_spell, MEXECUTE,
|
add_to_funcs(do_spell, MEXECUTE,
|
||||||
N_("Spell Check"), WITHORSANS(spell_gist), TOGETHER, NOVIEW);
|
N_("Spell Check"), WHENHELP(spell_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
add_to_funcs(do_linter, MEXECUTE,
|
add_to_funcs(do_linter, MEXECUTE,
|
||||||
N_("Linter"), WITHORSANS(lint_gist), BLANKAFTER, NOVIEW);
|
N_("Linter"), WHENHELP(lint_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
add_to_funcs(do_full_justify, MEXECUTE,
|
add_to_funcs(do_full_justify, MEXECUTE,
|
||||||
N_("Full Justify"), WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW);
|
N_("Full Justify"), WHENHELP(fulljustify_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_FORMATTER
|
||||||
add_to_funcs(do_formatter, MEXECUTE,
|
add_to_funcs(do_formatter, MEXECUTE,
|
||||||
N_("Formatter"), WITHORSANS(formatter_gist), BLANKAFTER, NOVIEW);
|
N_("Formatter"), WHENHELP(formatter_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
|
add_to_funcs(flip_goto, MWHEREIS,
|
||||||
|
N_("Go To Line"), WHENHELP(gotoline_gist), BLANKAFTER);
|
||||||
add_to_funcs(flip_goto, MGOTOLINE,
|
add_to_funcs(flip_goto, MGOTOLINE,
|
||||||
N_("Go To Text"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW);
|
N_("Go To Text"), WHENHELP(whereis_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(dos_format, MWRITEFILE,
|
add_to_funcs(dos_format, MWRITEFILE,
|
||||||
N_("DOS Format"), WITHORSANS(dos_gist), TOGETHER, NOVIEW);
|
N_("DOS Format"), WHENHELP(dos_gist), TOGETHER);
|
||||||
add_to_funcs(mac_format, MWRITEFILE,
|
add_to_funcs(mac_format, MWRITEFILE,
|
||||||
N_("Mac Format"), WITHORSANS(mac_gist), TOGETHER, NOVIEW);
|
N_("Mac Format"), WHENHELP(mac_gist), TOGETHER);
|
||||||
|
|
||||||
/* If we're using restricted mode, the Append, Prepend, and Backup toggles
|
/* If we're using restricted mode, the Append, Prepend, and Backup toggles
|
||||||
* are disabled. The first and second are not useful as they only allow
|
* are disabled. The first and second are not useful as they only allow
|
||||||
@ -1094,68 +1106,67 @@ void shortcut_init(void)
|
|||||||
* would write to a file not specified on the command line. */
|
* would write to a file not specified on the command line. */
|
||||||
if (!ISSET(RESTRICTED)) {
|
if (!ISSET(RESTRICTED)) {
|
||||||
add_to_funcs(append_it, MWRITEFILE,
|
add_to_funcs(append_it, MWRITEFILE,
|
||||||
N_("Append"), WITHORSANS(append_gist), TOGETHER, NOVIEW);
|
N_("Append"), WHENHELP(append_gist), TOGETHER);
|
||||||
add_to_funcs(prepend_it, MWRITEFILE,
|
add_to_funcs(prepend_it, MWRITEFILE,
|
||||||
N_("Prepend"), WITHORSANS(prepend_gist), TOGETHER, NOVIEW);
|
N_("Prepend"), WHENHELP(prepend_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(back_it_up, MWRITEFILE,
|
add_to_funcs(back_it_up, MWRITEFILE,
|
||||||
N_("Backup File"), WITHORSANS(backup_gist), BLANKAFTER, NOVIEW);
|
N_("Backup File"), WHENHELP(backup_gist), BLANKAFTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_funcs(flip_convert, MINSERTFILE,
|
add_to_funcs(flip_convert, MINSERTFILE,
|
||||||
N_("No Conversion"), WITHORSANS(convert_gist), BLANKAFTER, NOVIEW);
|
N_("No Conversion"), WHENHELP(convert_gist), BLANKAFTER);
|
||||||
|
|
||||||
/* Command execution is only available when not in restricted mode. */
|
/* Command execution is only available when not in restricted mode. */
|
||||||
if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE)) {
|
if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE))
|
||||||
add_to_funcs(flip_execute, MINSERTFILE,
|
add_to_funcs(flip_execute, MINSERTFILE,
|
||||||
N_("Execute Command"), WITHORSANS(execute_gist), BLANKAFTER, NOVIEW);
|
N_("Execute Command"), WHENHELP(execute_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(cut_till_eof, MEXECUTE,
|
add_to_funcs(cut_till_eof, MEXECUTE,
|
||||||
N_("Cut Till End"), WITHORSANS(cuttilleof_gist), BLANKAFTER, NOVIEW);
|
N_("Cut Till End"), WHENHELP(cuttilleof_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_suspend, MEXECUTE,
|
add_to_funcs(do_suspend, MEXECUTE,
|
||||||
N_("Suspend"), WITHORSANS(suspend_gist), BLANKAFTER, VIEW);
|
N_("Suspend"), WHENHELP(suspend_gist), BLANKAFTER);
|
||||||
}
|
|
||||||
#endif /* !NANO_TINY */
|
#endif /* !NANO_TINY */
|
||||||
|
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
/* The file browser is only available when not in restricted mode. */
|
/* The file browser is only available when not in restricted mode. */
|
||||||
if (!ISSET(RESTRICTED))
|
if (!ISSET(RESTRICTED))
|
||||||
add_to_funcs(to_files, MWRITEFILE|MINSERTFILE,
|
add_to_funcs(to_files, MWRITEFILE|MINSERTFILE,
|
||||||
/* TRANSLATORS: This invokes the file browser. */
|
/* TRANSLATORS: This invokes the file browser. */
|
||||||
N_("Browse"), WITHORSANS(tofiles_gist), BLANKAFTER, VIEW);
|
N_("Browse"), WHENHELP(tofiles_gist), BLANKAFTER);
|
||||||
|
|
||||||
add_to_funcs(do_page_up, MBROWSER,
|
add_to_funcs(do_page_up, MBROWSER,
|
||||||
N_("Prev Page"), WITHORSANS(prevpage_gist), TOGETHER, VIEW);
|
N_("Prev Page"), WHENHELP(prevpage_gist), TOGETHER);
|
||||||
add_to_funcs(do_page_down, MBROWSER,
|
add_to_funcs(do_page_down, MBROWSER,
|
||||||
N_("Next Page"), WITHORSANS(nextpage_gist), TOGETHER, VIEW);
|
N_("Next Page"), WHENHELP(nextpage_gist), TOGETHER);
|
||||||
|
|
||||||
add_to_funcs(to_first_file, MBROWSER|MWHEREISFILE,
|
add_to_funcs(to_first_file, MBROWSER|MWHEREISFILE,
|
||||||
N_("First File"), WITHORSANS(firstfile_gist), TOGETHER, VIEW);
|
N_("First File"), WHENHELP(firstfile_gist), TOGETHER);
|
||||||
add_to_funcs(to_last_file, MBROWSER|MWHEREISFILE,
|
add_to_funcs(to_last_file, MBROWSER|MWHEREISFILE,
|
||||||
N_("Last File"), WITHORSANS(lastfile_gist), BLANKAFTER, VIEW);
|
N_("Last File"), WHENHELP(lastfile_gist), BLANKAFTER);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_funcs(to_prev_word, MBROWSER,
|
add_to_funcs(to_prev_word, MBROWSER,
|
||||||
N_("Left Column"), WITHORSANS(browserlefthand_gist), TOGETHER, VIEW);
|
N_("Left Column"), WHENHELP(browserlefthand_gist), TOGETHER);
|
||||||
add_to_funcs(to_next_word, MBROWSER,
|
add_to_funcs(to_next_word, MBROWSER,
|
||||||
N_("Right Column"), WITHORSANS(browserrighthand_gist), TOGETHER, VIEW);
|
N_("Right Column"), WHENHELP(browserrighthand_gist), TOGETHER);
|
||||||
add_to_funcs(to_prev_block, MBROWSER,
|
add_to_funcs(to_prev_block, MBROWSER,
|
||||||
N_("Top Row"), WITHORSANS(browsertoprow_gist), TOGETHER, VIEW);
|
N_("Top Row"), WHENHELP(browsertoprow_gist), TOGETHER);
|
||||||
add_to_funcs(to_next_block, MBROWSER,
|
add_to_funcs(to_next_block, MBROWSER,
|
||||||
N_("Bottom Row"), WITHORSANS(browserbottomrow_gist), BLANKAFTER, VIEW);
|
N_("Bottom Row"), WHENHELP(browserbottomrow_gist), BLANKAFTER);
|
||||||
#endif
|
#endif
|
||||||
#endif /* ENABLE_BROWSER */
|
#endif /* ENABLE_BROWSER */
|
||||||
|
|
||||||
add_to_funcs(discard_buffer, MWRITEFILE,
|
add_to_funcs(discard_buffer, MWRITEFILE,
|
||||||
N_("Discard buffer"), WITHORSANS(discardbuffer_gist), BLANKAFTER, NOVIEW);
|
N_("Discard buffer"), WHENHELP(discardbuffer_gist), BLANKAFTER);
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
add_to_funcs(do_page_up, MLINTER,
|
add_to_funcs(do_page_up, MLINTER,
|
||||||
/* TRANSLATORS: The next two strings may be up to 37 characters each. */
|
/* TRANSLATORS: The next two strings may be up to 37 characters each. */
|
||||||
N_("Previous Linter message"), WITHORSANS(prevlint_gist), TOGETHER, VIEW);
|
N_("Previous Linter message"), WHENHELP(prevlint_gist), TOGETHER);
|
||||||
add_to_funcs(do_page_down, MLINTER,
|
add_to_funcs(do_page_down, MLINTER,
|
||||||
N_("Next Linter message"), WITHORSANS(nextlint_gist), TOGETHER, VIEW);
|
N_("Next Linter message"), WHENHELP(nextlint_gist), TOGETHER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -1187,27 +1198,33 @@ void shortcut_init(void)
|
|||||||
add_to_sclist(MMAIN, "^\\", 0, do_replace, 0);
|
add_to_sclist(MMAIN, "^\\", 0, do_replace, 0);
|
||||||
add_to_sclist(MMAIN, "M-R", 0, do_replace, 0);
|
add_to_sclist(MMAIN, "M-R", 0, do_replace, 0);
|
||||||
add_to_sclist(MMOST, "^K", 0, cut_text, 0);
|
add_to_sclist(MMOST, "^K", 0, cut_text, 0);
|
||||||
|
#ifdef NANO_TINY
|
||||||
|
add_to_sclist(MMAIN, "^U", 0, paste_text, 0);
|
||||||
|
#ifdef ENABLE_SPELLER
|
||||||
|
add_to_sclist(MMAIN, "^T", 0, do_spell, 0);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
add_to_sclist(MMOST, "^U", 0, paste_text, 0);
|
add_to_sclist(MMOST, "^U", 0, paste_text, 0);
|
||||||
#ifndef NANO_TINY
|
|
||||||
add_to_sclist(MMAIN, "^T", 0, do_execute, 0);
|
add_to_sclist(MMAIN, "^T", 0, do_execute, 0);
|
||||||
|
#ifdef ENABLE_SPELLER
|
||||||
|
if (!ISSET(PRESERVE))
|
||||||
|
add_to_sclist(MEXECUTE, "^S", 0, do_spell, 0);
|
||||||
|
add_to_sclist(MEXECUTE, "^T", 0, do_spell, 0);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_JUSTIFY
|
#ifdef ENABLE_JUSTIFY
|
||||||
add_to_sclist(MMAIN, "^J", '\n', do_justify, 0);
|
add_to_sclist(MMAIN, "^J", '\n', do_justify, 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_SPELLER
|
#ifdef ENABLE_LINTER
|
||||||
#ifndef NANO_TINY
|
|
||||||
if (!ISSET(PRESERVE))
|
|
||||||
add_to_sclist(MEXECUTE, "^S", 0, do_spell, 0);
|
|
||||||
add_to_sclist(MEXECUTE, "^T", 0, do_spell, 0);
|
|
||||||
#else
|
|
||||||
add_to_sclist(MMAIN, "^T", 0, do_spell, 0);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
add_to_sclist(MMAIN, "M-B", 0, do_linter, 0);
|
add_to_sclist(MMAIN, "M-B", 0, do_linter, 0);
|
||||||
add_to_sclist(MEXECUTE, "^Y", 0, do_linter, 0);
|
add_to_sclist(MEXECUTE, "^Y", 0, do_linter, 0);
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
add_to_sclist(MMAIN, "M-F", 0, do_formatter, 0);
|
add_to_sclist(MMAIN, "M-F", 0, do_formatter, 0);
|
||||||
add_to_sclist(MEXECUTE, "^O", 0, do_formatter, 0);
|
add_to_sclist(MEXECUTE, "^O", 0, do_formatter, 0);
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
add_to_sclist(MMAIN, "M-[", 0, do_fold_segment, 0);
|
||||||
#endif
|
#endif
|
||||||
add_to_sclist(MMAIN, "^C", 0, report_cursor_position, 0);
|
add_to_sclist(MMAIN, "^C", 0, report_cursor_position, 0);
|
||||||
add_to_sclist(MMAIN, SLASH_OR_DASH, 0, do_gotolinecolumn, 0);
|
add_to_sclist(MMAIN, SLASH_OR_DASH, 0, do_gotolinecolumn, 0);
|
||||||
@ -1240,10 +1257,10 @@ void shortcut_init(void)
|
|||||||
add_to_sclist(MMAIN, "M-A", 0, do_mark, 0);
|
add_to_sclist(MMAIN, "M-A", 0, do_mark, 0);
|
||||||
add_to_sclist(MMAIN, "^6", 0, do_mark, 0);
|
add_to_sclist(MMAIN, "^6", 0, do_mark, 0);
|
||||||
add_to_sclist(MMAIN, "^^", 0, do_mark, 0);
|
add_to_sclist(MMAIN, "^^", 0, do_mark, 0);
|
||||||
add_to_sclist(MMAIN, "M-6", 0, copy_text, 0);
|
add_to_sclist(MMOST, "M-6", 0, copy_text, 0);
|
||||||
add_to_sclist(MMAIN, "M-^", 0, copy_text, 0);
|
add_to_sclist(MMOST, "M-^", 0, copy_text, 0);
|
||||||
add_to_sclist(MMAIN, "M-}", 0, do_indent, 0);
|
add_to_sclist(MMAIN, "M-}", 0, do_indent, 0);
|
||||||
add_to_sclist(MMAIN, "Tab", INDENT_KEY, do_indent, 0);
|
add_to_sclist(MMAIN, "", INDENT_KEY, do_indent, 0);
|
||||||
add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0);
|
add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0);
|
||||||
add_to_sclist(MMAIN, "Sh-Tab", SHIFT_TAB, do_unindent, 0);
|
add_to_sclist(MMAIN, "Sh-Tab", SHIFT_TAB, do_unindent, 0);
|
||||||
add_to_sclist(MMAIN, "M-:", 0, record_macro, 0);
|
add_to_sclist(MMAIN, "M-:", 0, record_macro, 0);
|
||||||
@ -1272,7 +1289,7 @@ void shortcut_init(void)
|
|||||||
add_to_sclist(MMOST|MBROWSER|MHELP, "\xE2\x96\xb8", KEY_RIGHT, do_right, 0);
|
add_to_sclist(MMOST|MBROWSER|MHELP, "\xE2\x96\xb8", KEY_RIGHT, do_right, 0);
|
||||||
add_to_sclist(MSOME, "^\xE2\x97\x82", CONTROL_LEFT, to_prev_word, 0);
|
add_to_sclist(MSOME, "^\xE2\x97\x82", CONTROL_LEFT, to_prev_word, 0);
|
||||||
add_to_sclist(MSOME, "^\xE2\x96\xb8", CONTROL_RIGHT, to_next_word, 0);
|
add_to_sclist(MSOME, "^\xE2\x96\xb8", CONTROL_RIGHT, to_next_word, 0);
|
||||||
#if !defined(NANO_TINY) && defined(ENABLE_MULTIBUFFER)
|
#if defined(ENABLE_MULTIBUFFER) && !defined(NANO_TINY)
|
||||||
if (!on_a_vt) {
|
if (!on_a_vt) {
|
||||||
add_to_sclist(MMAIN, "M-\xE2\x97\x82", ALT_LEFT, switch_to_prev_buffer, 0);
|
add_to_sclist(MMAIN, "M-\xE2\x97\x82", ALT_LEFT, switch_to_prev_buffer, 0);
|
||||||
add_to_sclist(MMAIN, "M-\xE2\x96\xb8", ALT_RIGHT, switch_to_next_buffer, 0);
|
add_to_sclist(MMAIN, "M-\xE2\x96\xb8", ALT_RIGHT, switch_to_next_buffer, 0);
|
||||||
@ -1285,7 +1302,7 @@ void shortcut_init(void)
|
|||||||
add_to_sclist(MMOST|MBROWSER|MHELP, "Right", KEY_RIGHT, do_right, 0);
|
add_to_sclist(MMOST|MBROWSER|MHELP, "Right", KEY_RIGHT, do_right, 0);
|
||||||
add_to_sclist(MSOME, "^Left", CONTROL_LEFT, to_prev_word, 0);
|
add_to_sclist(MSOME, "^Left", CONTROL_LEFT, to_prev_word, 0);
|
||||||
add_to_sclist(MSOME, "^Right", CONTROL_RIGHT, to_next_word, 0);
|
add_to_sclist(MSOME, "^Right", CONTROL_RIGHT, to_next_word, 0);
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
#if defined(ENABLE_MULTIBUFFER) && !defined(NANO_TINY)
|
||||||
if (!on_a_vt) {
|
if (!on_a_vt) {
|
||||||
add_to_sclist(MMAIN, "M-Left", ALT_LEFT, switch_to_prev_buffer, 0);
|
add_to_sclist(MMAIN, "M-Left", ALT_LEFT, switch_to_prev_buffer, 0);
|
||||||
add_to_sclist(MMAIN, "M-Right", ALT_RIGHT, switch_to_next_buffer, 0);
|
add_to_sclist(MMAIN, "M-Right", ALT_RIGHT, switch_to_next_buffer, 0);
|
||||||
@ -1404,6 +1421,7 @@ void shortcut_init(void)
|
|||||||
add_to_sclist(MWHEREIS|MREPLACE, "M-B", 0, backwards_void, 0);
|
add_to_sclist(MWHEREIS|MREPLACE, "M-B", 0, backwards_void, 0);
|
||||||
add_to_sclist(MWHEREIS|MREPLACE, "^R", 0, flip_replace, 0);
|
add_to_sclist(MWHEREIS|MREPLACE, "^R", 0, flip_replace, 0);
|
||||||
add_to_sclist(MWHEREIS|MGOTOLINE, "^T", 0, flip_goto, 0);
|
add_to_sclist(MWHEREIS|MGOTOLINE, "^T", 0, flip_goto, 0);
|
||||||
|
add_to_sclist(MWHEREIS|MGOTOLINE, SLASH_OR_DASH, 0, flip_goto, 0);
|
||||||
#ifdef ENABLE_HISTORIES
|
#ifdef ENABLE_HISTORIES
|
||||||
add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "^P", 0, get_older_item, 0);
|
add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "^P", 0, get_older_item, 0);
|
||||||
add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "^N", 0, get_newer_item, 0);
|
add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "^N", 0, get_newer_item, 0);
|
||||||
@ -1454,32 +1472,29 @@ void shortcut_init(void)
|
|||||||
add_to_sclist(MINSERTFILE, "M-N", 0, flip_convert, 0);
|
add_to_sclist(MINSERTFILE, "M-N", 0, flip_convert, 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_MULTIBUFFER
|
#ifdef ENABLE_MULTIBUFFER
|
||||||
/* Only when not in restricted mode, allow multiple buffers. */
|
if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE)) {
|
||||||
if (!ISSET(RESTRICTED)) {
|
|
||||||
add_to_sclist(MINSERTFILE|MEXECUTE, "M-F", 0, flip_newbuffer, 0);
|
add_to_sclist(MINSERTFILE|MEXECUTE, "M-F", 0, flip_newbuffer, 0);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_to_sclist(MEXECUTE, "M-\\", 0, flip_pipe, 0);
|
add_to_sclist(MEXECUTE, "M-\\", 0, flip_pipe, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
add_to_sclist(MBROWSER|MHELP, "^C", 0, do_exit, 0);
|
||||||
#ifdef ENABLE_BROWSER
|
#ifdef ENABLE_BROWSER
|
||||||
/* Only when not in restricted mode, allow entering the file browser. */
|
/* Only when not in restricted mode, allow entering the file browser. */
|
||||||
if (!ISSET(RESTRICTED))
|
if (!ISSET(RESTRICTED))
|
||||||
add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", 0, to_files, 0);
|
add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", 0, to_files, 0);
|
||||||
#endif
|
/* Allow exiting the file browser with the same key as used for entry. */
|
||||||
add_to_sclist(MBROWSER|MHELP, "^C", 0, do_exit, 0);
|
|
||||||
/* Allow exiting from the file browser and the help viewer with
|
|
||||||
* the same key as they were entered. */
|
|
||||||
#ifdef ENABLE_BROWSER
|
|
||||||
add_to_sclist(MBROWSER, "^T", 0, do_exit, 0);
|
add_to_sclist(MBROWSER, "^T", 0, do_exit, 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
|
/* Allow exiting the help viewer with the same keys as used for entry. */
|
||||||
add_to_sclist(MHELP, "^G", 0, do_exit, 0);
|
add_to_sclist(MHELP, "^G", 0, do_exit, 0);
|
||||||
add_to_sclist(MHELP, "F1", KEY_F(1), do_exit, 0);
|
add_to_sclist(MHELP, "F1", KEY_F(1), do_exit, 0);
|
||||||
add_to_sclist(MHELP, "Home", KEY_HOME, to_first_line, 0);
|
add_to_sclist(MHELP, "Home", KEY_HOME, to_first_line, 0);
|
||||||
add_to_sclist(MHELP, "End", KEY_END, to_last_line, 0);
|
add_to_sclist(MHELP, "End", KEY_END, to_last_line, 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
add_to_sclist(MLINTER, "^X", 0, do_cancel, 0);
|
add_to_sclist(MLINTER, "^X", 0, do_cancel, 0);
|
||||||
#endif
|
#endif
|
||||||
add_to_sclist(MMOST & ~MFINDINHELP, "F1", KEY_F(1), do_help, 0);
|
add_to_sclist(MMOST & ~MFINDINHELP, "F1", KEY_F(1), do_help, 0);
|
||||||
|
|||||||
61
src/help.c
61
src/help.c
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* help.c -- This file is part of GNU nano. *
|
* help.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2000-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 2000-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2017 Rishabh Dave *
|
* Copyright (C) 2017 Rishabh Dave *
|
||||||
* Copyright (C) 2014-2019 Benno Schulenberg *
|
* Copyright (C) 2014-2019 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
@ -50,7 +50,7 @@ void help_init(void)
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
/* First, set up the initial help text for the current function. */
|
/* First, set up the initial help text for the current function. */
|
||||||
if (currmenu & (MWHEREIS|MREPLACE|MREPLACEWITH)) {
|
if (currmenu & (MWHEREIS|MREPLACE)) {
|
||||||
htx[0] = N_("Search Command Help Text\n\n "
|
htx[0] = N_("Search Command Help Text\n\n "
|
||||||
"Enter the words or characters you would like to "
|
"Enter the words or characters you would like to "
|
||||||
"search for, and then press Enter. If there is a "
|
"search for, and then press Enter. If there is a "
|
||||||
@ -65,6 +65,13 @@ void help_init(void)
|
|||||||
"will be replaced.\n\n The following function keys are "
|
"will be replaced.\n\n The following function keys are "
|
||||||
"available in Search mode:\n\n");
|
"available in Search mode:\n\n");
|
||||||
htx[2] = NULL;
|
htx[2] = NULL;
|
||||||
|
} else if (currmenu == MREPLACEWITH) {
|
||||||
|
htx[0] = N_("=== Replacement ===\n\n "
|
||||||
|
"Type the characters that should replace the characters that "
|
||||||
|
"you typed at the previous prompt, and press Enter.\n\n");
|
||||||
|
htx[1] = N_(" The following function keys "
|
||||||
|
"are available at this prompt:\n\n");
|
||||||
|
htx[2] = NULL;
|
||||||
} else if (currmenu == MGOTOLINE) {
|
} else if (currmenu == MGOTOLINE) {
|
||||||
htx[0] = N_("Go To Line Help Text\n\n "
|
htx[0] = N_("Go To Line Help Text\n\n "
|
||||||
"Enter the line number that you wish to go to and hit "
|
"Enter the line number that you wish to go to and hit "
|
||||||
@ -126,8 +133,8 @@ void help_init(void)
|
|||||||
"shown in brackets after the search prompt. Hitting "
|
"shown in brackets after the search prompt. Hitting "
|
||||||
"Enter without entering any text will perform the "
|
"Enter without entering any text will perform the "
|
||||||
"previous search.\n\n");
|
"previous search.\n\n");
|
||||||
htx[1] = N_(" The following function keys are available in "
|
htx[1] = N_(" The following function keys "
|
||||||
"Browser Search mode:\n\n");
|
"are available at this prompt:\n\n");
|
||||||
htx[2] = NULL;
|
htx[2] = NULL;
|
||||||
} else if (currmenu == MGOTODIR) {
|
} else if (currmenu == MGOTODIR) {
|
||||||
htx[0] = N_("Browser Go To Directory Help Text\n\n "
|
htx[0] = N_("Browser Go To Directory Help Text\n\n "
|
||||||
@ -167,8 +174,8 @@ void help_init(void)
|
|||||||
htx[1] = N_("If you just need another blank buffer, do not enter any "
|
htx[1] = N_("If you just need another blank buffer, do not enter any "
|
||||||
"command.\n\n You can also pick one of four tools, or cut a "
|
"command.\n\n You can also pick one of four tools, or cut a "
|
||||||
"large piece of the buffer, or put the editor to sleep.\n\n");
|
"large piece of the buffer, or put the editor to sleep.\n\n");
|
||||||
htx[2] = N_(" The following function keys are "
|
htx[2] = N_(" The following function keys "
|
||||||
"available in Execute Command mode:\n\n");
|
"are available at this prompt:\n\n");
|
||||||
} else if (currmenu == MLINTER) {
|
} else if (currmenu == MLINTER) {
|
||||||
htx[0] = N_("=== Linter ===\n\n "
|
htx[0] = N_("=== Linter ===\n\n "
|
||||||
"In this mode, the status bar shows an error message or "
|
"In this mode, the status bar shows an error message or "
|
||||||
@ -224,7 +231,7 @@ void help_init(void)
|
|||||||
* plus translated text, plus one or two \n's. */
|
* plus translated text, plus one or two \n's. */
|
||||||
for (f = allfuncs; f != NULL; f = f->next)
|
for (f = allfuncs; f != NULL; f = f->next)
|
||||||
if (f->menus & currmenu)
|
if (f->menus & currmenu)
|
||||||
allocsize += strlen(_(f->help)) + 21;
|
allocsize += strlen(_(f->phrase)) + 21;
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* If we're on the main list, we also count the toggle help text.
|
/* If we're on the main list, we also count the toggle help text.
|
||||||
@ -282,7 +289,7 @@ void help_init(void)
|
|||||||
ptr += 10;
|
ptr += 10;
|
||||||
|
|
||||||
/* The shortcut's description. */
|
/* The shortcut's description. */
|
||||||
ptr += sprintf(ptr, "%s\n", _(f->help));
|
ptr += sprintf(ptr, "%s\n", _(f->phrase));
|
||||||
|
|
||||||
if (f->blank_after)
|
if (f->blank_after)
|
||||||
ptr += sprintf(ptr, "\n");
|
ptr += sprintf(ptr, "\n");
|
||||||
@ -317,10 +324,10 @@ void help_init(void)
|
|||||||
/* Hard-wrap the concatenated help text, and write it into a new buffer. */
|
/* Hard-wrap the concatenated help text, and write it into a new buffer. */
|
||||||
void wrap_help_text_into_buffer(void)
|
void wrap_help_text_into_buffer(void)
|
||||||
{
|
{
|
||||||
size_t sum = 0;
|
|
||||||
/* Avoid overtight and overwide paragraphs in the introductory text. */
|
/* Avoid overtight and overwide paragraphs in the introductory text. */
|
||||||
size_t wrapping_point = ((COLS < 40) ? 40 : (COLS > 74) ? 74 : COLS) - thebar;
|
size_t wrapping_point = ((COLS < 40) ? 40 : (COLS > 74) ? 74 : COLS) - thebar;
|
||||||
const char *ptr = start_of_body;
|
const char *ptr = start_of_body;
|
||||||
|
size_t sum = 0;
|
||||||
|
|
||||||
make_new_buffer();
|
make_new_buffer();
|
||||||
|
|
||||||
@ -389,7 +396,7 @@ void wrap_help_text_into_buffer(void)
|
|||||||
void show_help(void)
|
void show_help(void)
|
||||||
{
|
{
|
||||||
int kbinput = ERR;
|
int kbinput = ERR;
|
||||||
functionptrtype func;
|
functionptrtype function;
|
||||||
/* The function of the key the user typed in. */
|
/* The function of the key the user typed in. */
|
||||||
int oldmenu = currmenu;
|
int oldmenu = currmenu;
|
||||||
/* The menu we were called from. */
|
/* The menu we were called from. */
|
||||||
@ -463,7 +470,7 @@ void show_help(void)
|
|||||||
focusing = TRUE;
|
focusing = TRUE;
|
||||||
|
|
||||||
/* Show the cursor when we searched and found something. */
|
/* Show the cursor when we searched and found something. */
|
||||||
kbinput = get_kbinput(edit, didfind == 1 || ISSET(SHOW_CURSOR));
|
kbinput = get_kbinput(midwin, didfind == 1 || ISSET(SHOW_CURSOR));
|
||||||
|
|
||||||
didfind = 0;
|
didfind = 0;
|
||||||
|
|
||||||
@ -475,28 +482,28 @@ void show_help(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
func = interpret(&kbinput);
|
function = interpret(kbinput);
|
||||||
|
|
||||||
if (func == full_refresh) {
|
if (function == full_refresh) {
|
||||||
full_refresh();
|
full_refresh();
|
||||||
} else if (ISSET(SHOW_CURSOR) && (func == do_left || func == do_right ||
|
} else if (ISSET(SHOW_CURSOR) && (function == do_left || function == do_right ||
|
||||||
func == do_up || func == do_down)) {
|
function == do_up || function == do_down)) {
|
||||||
func();
|
function();
|
||||||
} else if (func == do_up || func == do_scroll_up) {
|
} else if (function == do_up || function == do_scroll_up) {
|
||||||
do_scroll_up();
|
do_scroll_up();
|
||||||
} else if (func == do_down || func == do_scroll_down) {
|
} else if (function == do_down || function == do_scroll_down) {
|
||||||
if (openfile->edittop->lineno + editwinrows - 1 < openfile->filebot->lineno)
|
if (openfile->edittop->lineno + editwinrows - 1 < openfile->filebot->lineno)
|
||||||
do_scroll_down();
|
do_scroll_down();
|
||||||
} else if (func == do_page_up || func == do_page_down ||
|
} else if (function == do_page_up || function == do_page_down ||
|
||||||
func == to_first_line || func == to_last_line) {
|
function == to_first_line || function == to_last_line) {
|
||||||
func();
|
function();
|
||||||
} else if (func == do_search_backward || func == do_search_forward ||
|
} else if (function == do_search_backward || function == do_search_forward ||
|
||||||
func == do_findprevious || func == do_findnext) {
|
function == do_findprevious || function == do_findnext) {
|
||||||
func();
|
function();
|
||||||
bottombars(MHELP);
|
bottombars(MHELP);
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
} else if (func == (functionptrtype)implant) {
|
} else if (function == (functionptrtype)implant) {
|
||||||
implant(first_sc_for(MHELP, func)->expansion);
|
implant(first_sc_for(MHELP, function)->expansion);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_MOUSE
|
#ifdef ENABLE_MOUSE
|
||||||
} else if (kbinput == KEY_MOUSE) {
|
} else if (kbinput == KEY_MOUSE) {
|
||||||
@ -507,7 +514,7 @@ void show_help(void)
|
|||||||
} else if (kbinput == KEY_WINCH) {
|
} else if (kbinput == KEY_WINCH) {
|
||||||
; /* Nothing to do. */
|
; /* Nothing to do. */
|
||||||
#endif
|
#endif
|
||||||
} else if (func == do_exit) {
|
} else if (function == do_exit) {
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
unbound_key(kbinput);
|
unbound_key(kbinput);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* history.c -- This file is part of GNU nano. *
|
* history.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2003-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 2003-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
@ -304,12 +304,10 @@ bool write_list(const linestruct *head, FILE *histfile)
|
|||||||
const linestruct *item;
|
const linestruct *item;
|
||||||
|
|
||||||
for (item = head; item != NULL; item = item->next) {
|
for (item = head; item != NULL; item = item->next) {
|
||||||
size_t length = strlen(item->data);
|
|
||||||
|
|
||||||
/* Decode 0x0A bytes as embedded NULs. */
|
/* Decode 0x0A bytes as embedded NULs. */
|
||||||
recode_LF_to_NUL(item->data);
|
size_t length = recode_LF_to_NUL(item->data);
|
||||||
|
|
||||||
if (fwrite(item->data, sizeof(char), length, histfile) < length)
|
if (fwrite(item->data, 1, length, histfile) < length)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (putc('\n', histfile) == EOF)
|
if (putc('\n', histfile) == EOF)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -451,14 +449,13 @@ void save_poshistory(void)
|
|||||||
path_and_place = nmalloc(strlen(item->filename) + 44);
|
path_and_place = nmalloc(strlen(item->filename) + 44);
|
||||||
sprintf(path_and_place, "%s %zd %zd\n",
|
sprintf(path_and_place, "%s %zd %zd\n",
|
||||||
item->filename, item->linenumber, item->columnnumber);
|
item->filename, item->linenumber, item->columnnumber);
|
||||||
length = strlen(path_and_place);
|
|
||||||
|
|
||||||
/* Encode newlines in filenames as NULs. */
|
/* Encode newlines in filenames as NULs. */
|
||||||
recode_LF_to_NUL(path_and_place);
|
length = recode_LF_to_NUL(path_and_place);
|
||||||
/* Restore the terminating newline. */
|
/* Restore the terminating newline. */
|
||||||
path_and_place[length - 1] = '\n';
|
path_and_place[length - 1] = '\n';
|
||||||
|
|
||||||
if (fwrite(path_and_place, sizeof(char), length, histfile) < length)
|
if (fwrite(path_and_place, 1, length, histfile) < length)
|
||||||
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
|
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
|
||||||
|
|
||||||
free(path_and_place);
|
free(path_and_place);
|
||||||
|
|||||||
155
src/move.c
155
src/move.c
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* move.c -- This file is part of GNU nano. *
|
* move.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014-2018 Benno Schulenberg *
|
* Copyright (C) 2014-2018 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
@ -37,13 +37,22 @@ void to_first_line(void)
|
|||||||
void to_last_line(void)
|
void to_last_line(void)
|
||||||
{
|
{
|
||||||
openfile->current = openfile->filebot;
|
openfile->current = openfile->filebot;
|
||||||
openfile->current_x = (inhelp) ? 0 : strlen(openfile->filebot->data);
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded) {
|
||||||
|
openfile->current = get_start_of_folded_segment(openfile->current);
|
||||||
|
openfile->current_x = 0;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
openfile->current_x = (inhelp) ? 0 : strlen(openfile->filebot->data);
|
||||||
openfile->placewewant = xplustabs();
|
openfile->placewewant = xplustabs();
|
||||||
|
|
||||||
/* Set the last line of the screen as the target for the cursor. */
|
/* Set the last line of the screen as the target for the cursor. */
|
||||||
openfile->current_y = editwinrows - 1;
|
openfile->current_y = editwinrows - 1;
|
||||||
|
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif
|
||||||
focusing = FALSE;
|
focusing = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +104,8 @@ size_t proper_x(linestruct *line, size_t *leftedge, bool forward,
|
|||||||
* the middle of a tab that crosses a row boundary. */
|
* the middle of a tab that crosses a row boundary. */
|
||||||
void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
|
void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
|
||||||
{
|
{
|
||||||
bool shifted = FALSE;
|
|
||||||
size_t was_edge = *leftedge;
|
size_t was_edge = *leftedge;
|
||||||
|
bool shifted = FALSE;
|
||||||
|
|
||||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||||
actual_last_column(*leftedge, target), &shifted);
|
actual_last_column(*leftedge, target), &shifted);
|
||||||
@ -109,6 +118,15 @@ void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
|
|||||||
openfile->placewewant = *leftedge + target;
|
openfile->placewewant = *leftedge + target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Move the cursor position on the current line to the desired column */
|
||||||
|
void move_cursor_to_proper_column(void)
|
||||||
|
{
|
||||||
|
size_t leftedge;
|
||||||
|
size_t target_column;
|
||||||
|
get_edge_and_target(&leftedge, &target_column);
|
||||||
|
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Move up almost one screenful. */
|
/* Move up almost one screenful. */
|
||||||
void do_page_up(void)
|
void do_page_up(void)
|
||||||
{
|
{
|
||||||
@ -222,6 +240,9 @@ void to_para_end(void)
|
|||||||
openfile->current_x = strlen(openfile->current->data);
|
openfile->current_x = strlen(openfile->current->data);
|
||||||
|
|
||||||
edit_redraw(was_current, CENTERING);
|
edit_redraw(was_current, CENTERING);
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_JUSTIFY */
|
#endif /* ENABLE_JUSTIFY */
|
||||||
|
|
||||||
@ -229,19 +250,28 @@ void to_para_end(void)
|
|||||||
void to_prev_block(void)
|
void to_prev_block(void)
|
||||||
{
|
{
|
||||||
linestruct *was_current = openfile->current;
|
linestruct *was_current = openfile->current;
|
||||||
|
linestruct *line_step = get_prev_visible_line(openfile->current);
|
||||||
bool is_text = FALSE, seen_text = FALSE;
|
bool is_text = FALSE, seen_text = FALSE;
|
||||||
|
|
||||||
/* Skip backward until first blank line after some nonblank line(s). */
|
/* Skip backward until first blank line after some nonblank line(s). */
|
||||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
while (line_step != NULL && (!seen_text || is_text)) {
|
||||||
openfile->current = openfile->current->prev;
|
openfile->current = line_step;
|
||||||
|
line_step = get_prev_visible_line(line_step);
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
is_text = !white_string(openfile->current->data);
|
is_text = !white_string(openfile->current->data);
|
||||||
seen_text = seen_text || is_text;
|
seen_text = seen_text || is_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step forward one line again if we passed text but this line is blank. */
|
/* Step forward one line again if we passed text but this line is blank. */
|
||||||
if (seen_text && openfile->current->next != NULL &&
|
line_step = get_next_visible_line(openfile->current);
|
||||||
white_string(openfile->current->data))
|
if (seen_text && line_step != NULL &&
|
||||||
openfile->current = openfile->current->next;
|
white_string(openfile->current->data)) {
|
||||||
|
openfile->current = line_step;
|
||||||
|
line_step = get_next_visible_line(line_step);
|
||||||
|
}
|
||||||
|
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
edit_redraw(was_current, CENTERING);
|
edit_redraw(was_current, CENTERING);
|
||||||
@ -251,33 +281,57 @@ void to_prev_block(void)
|
|||||||
void to_next_block(void)
|
void to_next_block(void)
|
||||||
{
|
{
|
||||||
linestruct *was_current = openfile->current;
|
linestruct *was_current = openfile->current;
|
||||||
|
linestruct *line_step = get_next_visible_line(openfile->current);
|
||||||
bool is_white = white_string(openfile->current->data);
|
bool is_white = white_string(openfile->current->data);
|
||||||
bool seen_white = is_white;
|
bool seen_white = is_white;
|
||||||
|
|
||||||
/* Skip forward until first nonblank line after some blank line(s). */
|
/* Skip forward until first nonblank line after some blank line(s). */
|
||||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
while (line_step != NULL && (!seen_white || is_white)) {
|
||||||
openfile->current = openfile->current->next;
|
openfile->current = line_step;
|
||||||
|
line_step = get_next_visible_line(line_step);
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
is_white = white_string(openfile->current->data);
|
is_white = white_string(openfile->current->data);
|
||||||
seen_white = seen_white || is_white;
|
seen_white = seen_white || is_white;
|
||||||
}
|
}
|
||||||
|
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
edit_redraw(was_current, CENTERING);
|
edit_redraw(was_current, CENTERING);
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move to the previous word. */
|
/* Move to the previous word.
|
||||||
void do_prev_word(void)
|
* when allow_folded as true, will move to previous word even if inside
|
||||||
|
* a folded segment */
|
||||||
|
void do_prev_word(bool allow_folded)
|
||||||
{
|
{
|
||||||
bool punctuation_as_letters = ISSET(WORD_BOUNDS);
|
bool punctuation_as_letters = ISSET(WORD_BOUNDS);
|
||||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (!allow_folded && openfile->current->folded) {
|
||||||
|
openfile->current = get_prev_visible_line(openfile->current);
|
||||||
|
openfile->current_x = strlen(openfile->current->data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Move backward until we pass over the start of a word. */
|
/* Move backward until we pass over the start of a word. */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
/* If at the head of a line, move to the end of the preceding one. */
|
/* If at the head of a line, move to the end of the preceding one. */
|
||||||
if (openfile->current_x == 0) {
|
if (openfile->current_x == 0) {
|
||||||
if (openfile->current->prev == NULL)
|
if (openfile->current->prev == NULL)
|
||||||
break;
|
break;
|
||||||
openfile->current = openfile->current->prev;
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (!allow_folded) {
|
||||||
|
openfile->current = get_prev_visible_line(openfile->current);
|
||||||
|
if (openfile->current->folded)
|
||||||
|
openfile->current = openfile->current->prev;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
openfile->current = openfile->current->prev;
|
||||||
openfile->current_x = strlen(openfile->current->data);
|
openfile->current_x = strlen(openfile->current->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,11 +360,14 @@ void do_prev_word(void)
|
|||||||
/* Move one character forward again to sit on the start of the word. */
|
/* Move one character forward again to sit on the start of the word. */
|
||||||
openfile->current_x = step_right(openfile->current->data,
|
openfile->current_x = step_right(openfile->current->data,
|
||||||
openfile->current_x);
|
openfile->current_x);
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move to the next word. If after_ends is TRUE, stop at the ends of words
|
/* Move to the next word. If after_ends is TRUE, stop at the ends of words
|
||||||
* instead of at their beginnings. Return TRUE if we started on a word. */
|
* instead of at their beginnings. If allow_folded is true, go to next word
|
||||||
bool do_next_word(bool after_ends)
|
* even if it's inside a folded segment.
|
||||||
|
* Return TRUE if we started on a word. */
|
||||||
|
bool do_next_word(bool after_ends, bool allow_folded)
|
||||||
{
|
{
|
||||||
bool punctuation_as_letters = ISSET(WORD_BOUNDS);
|
bool punctuation_as_letters = ISSET(WORD_BOUNDS);
|
||||||
bool started_on_word = is_word_char(openfile->current->data +
|
bool started_on_word = is_word_char(openfile->current->data +
|
||||||
@ -320,6 +377,12 @@ bool do_next_word(bool after_ends)
|
|||||||
bool seen_word = started_on_word;
|
bool seen_word = started_on_word;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (!allow_folded && openfile->current->folded) {
|
||||||
|
openfile->current = get_next_visible_line(openfile->current);
|
||||||
|
openfile->current_x = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Move forward until we reach the start of a word. */
|
/* Move forward until we reach the start of a word. */
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
/* If at the end of a line, move to the beginning of the next one. */
|
/* If at the end of a line, move to the beginning of the next one. */
|
||||||
@ -327,7 +390,17 @@ bool do_next_word(bool after_ends)
|
|||||||
/* When at end of file, stop. */
|
/* When at end of file, stop. */
|
||||||
if (openfile->current->next == NULL)
|
if (openfile->current->next == NULL)
|
||||||
break;
|
break;
|
||||||
openfile->current = openfile->current->next;
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (!allow_folded) {
|
||||||
|
openfile->current = get_next_visible_line(openfile->current);
|
||||||
|
if (openfile->current->folded) {
|
||||||
|
/* get_next_visible_line() gives the start of a segment, so skip to the end */
|
||||||
|
openfile->current = get_end_of_folded_segment(openfile->current);
|
||||||
|
openfile->current = openfile->current->next;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
openfile->current = openfile->current->next;
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
seen_space = TRUE;
|
seen_space = TRUE;
|
||||||
} else {
|
} else {
|
||||||
@ -367,6 +440,8 @@ bool do_next_word(bool after_ends)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
|
||||||
return started_on_word;
|
return started_on_word;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,7 +450,7 @@ void to_prev_word(void)
|
|||||||
{
|
{
|
||||||
linestruct *was_current = openfile->current;
|
linestruct *was_current = openfile->current;
|
||||||
|
|
||||||
do_prev_word();
|
do_prev_word(DISALLOW_FOLDED);
|
||||||
|
|
||||||
edit_redraw(was_current, FLOWING);
|
edit_redraw(was_current, FLOWING);
|
||||||
}
|
}
|
||||||
@ -386,7 +461,7 @@ void to_next_word(void)
|
|||||||
{
|
{
|
||||||
linestruct *was_current = openfile->current;
|
linestruct *was_current = openfile->current;
|
||||||
|
|
||||||
do_next_word(ISSET(AFTER_ENDS));
|
do_next_word(ISSET(AFTER_ENDS), DISALLOW_FOLDED);
|
||||||
|
|
||||||
edit_redraw(was_current, FLOWING);
|
edit_redraw(was_current, FLOWING);
|
||||||
}
|
}
|
||||||
@ -401,12 +476,17 @@ void do_home(void)
|
|||||||
bool moved_off_chunk = TRUE;
|
bool moved_off_chunk = TRUE;
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
bool moved = FALSE;
|
bool moved = FALSE;
|
||||||
size_t leftedge = 0, leftedge_x = 0;
|
size_t leftedge = 0;
|
||||||
|
size_t left_x = 0;
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ISSET(SOFTWRAP)) {
|
if (ISSET(SOFTWRAP)) {
|
||||||
leftedge = leftedge_for(was_column, openfile->current);
|
leftedge = leftedge_for(was_column, openfile->current);
|
||||||
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
|
left_x = proper_x(openfile->current, &leftedge, FALSE, leftedge, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISSET(SMART_HOME)) {
|
if (ISSET(SMART_HOME)) {
|
||||||
@ -419,7 +499,7 @@ void do_home(void)
|
|||||||
if (openfile->current_x == indent_x) {
|
if (openfile->current_x == indent_x) {
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
moved = TRUE;
|
moved = TRUE;
|
||||||
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
|
} else if (left_x <= indent_x) {
|
||||||
openfile->current_x = indent_x;
|
openfile->current_x = indent_x;
|
||||||
moved = TRUE;
|
moved = TRUE;
|
||||||
}
|
}
|
||||||
@ -429,10 +509,10 @@ void do_home(void)
|
|||||||
if (!moved && ISSET(SOFTWRAP)) {
|
if (!moved && ISSET(SOFTWRAP)) {
|
||||||
/* If already at the left edge of the screen, move fully home.
|
/* If already at the left edge of the screen, move fully home.
|
||||||
* Otherwise, move to the left edge. */
|
* Otherwise, move to the left edge. */
|
||||||
if (openfile->current_x == leftedge_x)
|
if (openfile->current_x == left_x)
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
else {
|
else {
|
||||||
openfile->current_x = leftedge_x;
|
openfile->current_x = left_x;
|
||||||
openfile->placewewant = leftedge;
|
openfile->placewewant = leftedge;
|
||||||
moved_off_chunk = FALSE;
|
moved_off_chunk = FALSE;
|
||||||
}
|
}
|
||||||
@ -461,13 +541,19 @@ void do_end(void)
|
|||||||
size_t line_len = strlen(openfile->current->data);
|
size_t line_len = strlen(openfile->current->data);
|
||||||
bool moved_off_chunk = TRUE;
|
bool moved_off_chunk = TRUE;
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (ISSET(SOFTWRAP)) {
|
if (ISSET(SOFTWRAP)) {
|
||||||
|
bool kickoff = TRUE;
|
||||||
bool last_chunk = FALSE;
|
bool last_chunk = FALSE;
|
||||||
size_t leftedge = leftedge_for(was_column, openfile->current);
|
size_t leftedge = leftedge_for(was_column, openfile->current);
|
||||||
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
|
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
|
||||||
leftedge, &last_chunk);
|
leftedge, &kickoff, &last_chunk);
|
||||||
size_t rightedge_x;
|
size_t right_x;
|
||||||
|
|
||||||
/* If we're on the last chunk, we're already at the end of the line.
|
/* If we're on the last chunk, we're already at the end of the line.
|
||||||
* Otherwise, we're one column past the end of the line. Shifting
|
* Otherwise, we're one column past the end of the line. Shifting
|
||||||
@ -476,14 +562,14 @@ void do_end(void)
|
|||||||
if (!last_chunk)
|
if (!last_chunk)
|
||||||
rightedge--;
|
rightedge--;
|
||||||
|
|
||||||
rightedge_x = actual_x(openfile->current->data, rightedge);
|
right_x = actual_x(openfile->current->data, rightedge);
|
||||||
|
|
||||||
/* If already at the right edge of the screen, move fully to
|
/* If already at the right edge of the screen, move fully to
|
||||||
* the end of the line. Otherwise, move to the right edge. */
|
* the end of the line. Otherwise, move to the right edge. */
|
||||||
if (openfile->current_x == rightedge_x)
|
if (openfile->current_x == right_x)
|
||||||
openfile->current_x = line_len;
|
openfile->current_x = line_len;
|
||||||
else {
|
else {
|
||||||
openfile->current_x = rightedge_x;
|
openfile->current_x = right_x;
|
||||||
openfile->placewewant = rightedge;
|
openfile->placewewant = rightedge;
|
||||||
moved_off_chunk = FALSE;
|
moved_off_chunk = FALSE;
|
||||||
}
|
}
|
||||||
@ -602,7 +688,7 @@ void do_left(void)
|
|||||||
openfile->current_x);
|
openfile->current_x);
|
||||||
#endif
|
#endif
|
||||||
} else if (openfile->current != openfile->filetop) {
|
} else if (openfile->current != openfile->filetop) {
|
||||||
openfile->current = openfile->current->prev;
|
openfile->current = get_prev_visible_line(openfile->current);
|
||||||
openfile->current_x = strlen(openfile->current->data);
|
openfile->current_x = strlen(openfile->current->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,6 +700,13 @@ void do_right(void)
|
|||||||
{
|
{
|
||||||
linestruct *was_current = openfile->current;
|
linestruct *was_current = openfile->current;
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded) {
|
||||||
|
openfile->current = get_next_visible_line(openfile->current);
|
||||||
|
if (openfile->current == NULL)
|
||||||
|
openfile->current = was_current;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||||
openfile->current_x = step_right(openfile->current->data,
|
openfile->current_x = step_right(openfile->current->data,
|
||||||
openfile->current_x);
|
openfile->current_x);
|
||||||
@ -624,7 +717,7 @@ void do_right(void)
|
|||||||
openfile->current_x);
|
openfile->current_x);
|
||||||
#endif
|
#endif
|
||||||
} else if (openfile->current != openfile->filebot) {
|
} else if (openfile->current != openfile->filebot) {
|
||||||
openfile->current = openfile->current->next;
|
openfile->current = get_next_visible_line(openfile->current);
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
338
src/nano.c
338
src/nano.c
@ -1,8 +1,8 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* nano.c -- This file is part of GNU nano. *
|
* nano.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014-2021 Benno Schulenberg *
|
* Copyright (C) 2014-2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -26,7 +26,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#if defined(__linux__) || !defined(NANO_TINY)
|
#ifdef __linux__
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_UTF8
|
#ifdef ENABLE_UTF8
|
||||||
@ -78,6 +78,9 @@ linestruct *make_new_node(linestruct *prevnode)
|
|||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
newnode->has_anchor = FALSE;
|
newnode->has_anchor = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
newnode->folded = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
@ -117,6 +120,7 @@ void delete_node(linestruct *line)
|
|||||||
/* Disconnect a node from a linked list of linestructs and delete it. */
|
/* Disconnect a node from a linked list of linestructs and delete it. */
|
||||||
void unlink_node(linestruct *line)
|
void unlink_node(linestruct *line)
|
||||||
{
|
{
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
if (line->prev != NULL)
|
if (line->prev != NULL)
|
||||||
line->prev->next = line->next;
|
line->prev->next = line->next;
|
||||||
if (line->next != NULL)
|
if (line->next != NULL)
|
||||||
@ -156,6 +160,9 @@ linestruct *copy_node(const linestruct *src)
|
|||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
dst->has_anchor = src->has_anchor;
|
dst->has_anchor = src->has_anchor;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
dst->folded = src->folded;
|
||||||
|
#endif
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -243,14 +250,14 @@ void finish(void)
|
|||||||
/* Blank the status bar and (if applicable) the shortcut list. */
|
/* Blank the status bar and (if applicable) the shortcut list. */
|
||||||
blank_statusbar();
|
blank_statusbar();
|
||||||
blank_bottombars();
|
blank_bottombars();
|
||||||
wrefresh(bottomwin);
|
wrefresh(footwin);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* Deallocate the two or three subwindows. */
|
/* Deallocate the two or three subwindows. */
|
||||||
if (topwin != NULL)
|
if (topwin != NULL)
|
||||||
delwin(topwin);
|
delwin(topwin);
|
||||||
delwin(edit);
|
delwin(midwin);
|
||||||
delwin(bottomwin);
|
delwin(footwin);
|
||||||
#endif
|
#endif
|
||||||
/* Switch the cursor on, exit from curses, and restore terminal settings. */
|
/* Switch the cursor on, exit from curses, and restore terminal settings. */
|
||||||
restore_terminal();
|
restore_terminal();
|
||||||
@ -303,21 +310,21 @@ void do_exit(void)
|
|||||||
|
|
||||||
/* When unmodified, simply close. Else, when doing automatic saving
|
/* When unmodified, simply close. Else, when doing automatic saving
|
||||||
* and the file has a name, simply save. Otherwise, ask the user. */
|
* and the file has a name, simply save. Otherwise, ask the user. */
|
||||||
if (!openfile->modified)
|
if (!openfile->modified || ISSET(VIEW_MODE))
|
||||||
choice = 0;
|
choice = NO;
|
||||||
else if (ISSET(SAVE_ON_EXIT) && openfile->filename[0] != '\0')
|
else if (ISSET(SAVE_ON_EXIT) && openfile->filename[0] != '\0')
|
||||||
choice = 1;
|
choice = YES;
|
||||||
else {
|
else {
|
||||||
if (ISSET(SAVE_ON_EXIT))
|
if (ISSET(SAVE_ON_EXIT))
|
||||||
warn_and_briefly_pause(_("No file name"));
|
warn_and_briefly_pause(_("No file name"));
|
||||||
|
|
||||||
choice = do_yesno_prompt(FALSE, _("Save modified buffer? "));
|
choice = ask_user(YESORNO, _("Save modified buffer? "));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When not saving, or the save succeeds, close the buffer. */
|
/* When not saving, or the save succeeds, close the buffer. */
|
||||||
if (choice == 0 || (choice == 1 && write_it_out(TRUE, TRUE) > 0))
|
if (choice == NO || (choice == YES && write_it_out(TRUE, TRUE) > 0))
|
||||||
close_and_go();
|
close_and_go();
|
||||||
else if (choice != 1)
|
else if (choice != YES)
|
||||||
statusbar(_("Cancelled"));
|
statusbar(_("Cancelled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +346,7 @@ void emergency_save(const char *filename)
|
|||||||
fprintf(stderr, _("\nToo many .save files\n"));
|
fprintf(stderr, _("\nToo many .save files\n"));
|
||||||
else if (write_file(targetname, NULL, SPECIAL, OVERWRITE, NONOTES)) {
|
else if (write_file(targetname, NULL, SPECIAL, OVERWRITE, NONOTES)) {
|
||||||
fprintf(stderr, _("\nBuffer written to %s\n"), targetname);
|
fprintf(stderr, _("\nBuffer written to %s\n"), targetname);
|
||||||
#ifndef NANO_TINY
|
#if !defined(NANO_TINY) && defined(HAVE_CHMOD) && defined(HAVE_CHOWN)
|
||||||
/* Try to chmod/chown the saved file to the values of the original file,
|
/* Try to chmod/chown the saved file to the values of the original file,
|
||||||
* but ignore any failure as we are in a hurry to get out. */
|
* but ignore any failure as we are in a hurry to get out. */
|
||||||
if (openfile->statinfo) {
|
if (openfile->statinfo) {
|
||||||
@ -358,9 +365,9 @@ void emergency_save(const char *filename)
|
|||||||
* that were modified. */
|
* that were modified. */
|
||||||
void die(const char *msg, ...)
|
void die(const char *msg, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
|
||||||
openfilestruct *firstone = openfile;
|
openfilestruct *firstone = openfile;
|
||||||
static int stabs = 0;
|
static int stabs = 0;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
/* When dying for a second time, just give up. */
|
/* When dying for a second time, just give up. */
|
||||||
if (++stabs > 1)
|
if (++stabs > 1)
|
||||||
@ -403,11 +410,11 @@ void die(const char *msg, ...)
|
|||||||
void window_init(void)
|
void window_init(void)
|
||||||
{
|
{
|
||||||
/* When resizing, first delete the existing windows. */
|
/* When resizing, first delete the existing windows. */
|
||||||
if (edit != NULL) {
|
if (midwin != NULL) {
|
||||||
if (topwin != NULL)
|
if (topwin != NULL)
|
||||||
delwin(topwin);
|
delwin(topwin);
|
||||||
delwin(edit);
|
delwin(midwin);
|
||||||
delwin(bottomwin);
|
delwin(footwin);
|
||||||
}
|
}
|
||||||
|
|
||||||
topwin = NULL;
|
topwin = NULL;
|
||||||
@ -417,32 +424,31 @@ void window_init(void)
|
|||||||
editwinrows = (ISSET(ZERO) ? LINES : 1);
|
editwinrows = (ISSET(ZERO) ? LINES : 1);
|
||||||
/* Set up two subwindows. If the terminal is just one line,
|
/* Set up two subwindows. If the terminal is just one line,
|
||||||
* edit window and status-bar window will cover each other. */
|
* edit window and status-bar window will cover each other. */
|
||||||
edit = newwin(editwinrows, COLS, 0, 0);
|
midwin = newwin(editwinrows, COLS, 0, 0);
|
||||||
bottomwin = newwin(1, COLS, LINES - 1, 0);
|
footwin = newwin(1, COLS, LINES - 1, 0);
|
||||||
} else {
|
} else {
|
||||||
int toprows = ((ISSET(EMPTY_LINE) && LINES > 6) ? 2 : 1);
|
int toprows = ((ISSET(EMPTY_LINE) && LINES > 6) ? 2 : 1);
|
||||||
int bottomrows = ((ISSET(NO_HELP) || LINES < 6) ? 1 : 3);
|
int bottomrows = ((ISSET(NO_HELP) || LINES < 6) ? 1 : 3);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
|
||||||
if (ISSET(MINIBAR) || ISSET(ZERO))
|
if (ISSET(MINIBAR) || ISSET(ZERO))
|
||||||
toprows = 0;
|
toprows = 0;
|
||||||
#endif
|
|
||||||
editwinrows = LINES - toprows - bottomrows + (ISSET(ZERO) ? 1 : 0);
|
editwinrows = LINES - toprows - bottomrows + (ISSET(ZERO) ? 1 : 0);
|
||||||
|
|
||||||
/* Set up the normal three subwindows. */
|
/* Set up the normal three subwindows. */
|
||||||
if (toprows > 0)
|
if (toprows > 0)
|
||||||
topwin = newwin(toprows, COLS, 0, 0);
|
topwin = newwin(toprows, COLS, 0, 0);
|
||||||
edit = newwin(editwinrows, COLS, toprows, 0);
|
midwin = newwin(editwinrows, COLS, toprows, 0);
|
||||||
bottomwin = newwin(bottomrows, COLS, LINES - bottomrows, 0);
|
footwin = newwin(bottomrows, COLS, LINES - bottomrows, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case the terminal shrunk, make sure the status line is clear. */
|
/* In case the terminal shrunk, make sure the status line is clear. */
|
||||||
wnoutrefresh(bottomwin);
|
wnoutrefresh(footwin);
|
||||||
|
|
||||||
/* When not disabled, turn escape-sequence translation on. */
|
/* When not disabled, turn escape-sequence translation on. */
|
||||||
if (!ISSET(RAW_SEQUENCES)) {
|
if (!ISSET(RAW_SEQUENCES)) {
|
||||||
keypad(edit, TRUE);
|
keypad(midwin, TRUE);
|
||||||
keypad(bottomwin, TRUE);
|
keypad(footwin, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLED_WRAPORJUSTIFY
|
#ifdef ENABLED_WRAPORJUSTIFY
|
||||||
@ -480,7 +486,7 @@ void mouse_init(void)
|
|||||||
#endif /* ENABLE_MOUSE */
|
#endif /* ENABLE_MOUSE */
|
||||||
|
|
||||||
/* Print the usage line for the given option to the screen. */
|
/* Print the usage line for the given option to the screen. */
|
||||||
void print_opt(const char *shortflag, const char *longflag, const char *desc)
|
void print_opt(const char *shortflag, const char *longflag, const char *description)
|
||||||
{
|
{
|
||||||
int firstwidth = breadth(shortflag);
|
int firstwidth = breadth(shortflag);
|
||||||
int secondwidth = breadth(longflag);
|
int secondwidth = breadth(longflag);
|
||||||
@ -493,7 +499,7 @@ void print_opt(const char *shortflag, const char *longflag, const char *desc)
|
|||||||
if (secondwidth < 24)
|
if (secondwidth < 24)
|
||||||
printf("%*s", 24 - secondwidth, " ");
|
printf("%*s", 24 - secondwidth, " ");
|
||||||
|
|
||||||
printf("%s\n", _(desc));
|
printf("%s\n", _(description));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Explain how to properly use nano and its command-line options. */
|
/* Explain how to properly use nano and its command-line options. */
|
||||||
@ -651,13 +657,15 @@ void usage(void)
|
|||||||
print_opt("-x", "--nohelp", N_("Don't show the two help lines"));
|
print_opt("-x", "--nohelp", N_("Don't show the two help lines"));
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
print_opt("-y", "--afterends", N_("Make Ctrl+Right stop at word ends"));
|
print_opt("-y", "--afterends", N_("Make Ctrl+Right stop at word ends"));
|
||||||
print_opt("-%", "--stateflags", N_("Show some states on the title bar"));
|
|
||||||
print_opt("-_", "--minibar", N_("Show a feedback bar at the bottom"));
|
|
||||||
print_opt("-0", "--zero", N_("Hide all bars, use whole terminal"));
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBMAGIC
|
#ifdef HAVE_LIBMAGIC
|
||||||
print_opt("-!", "--magic", N_("Also try magic to determine syntax"));
|
print_opt("-!", "--magic", N_("Also try magic to determine syntax"));
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
print_opt("-%", "--stateflags", N_("Show some states on the title bar"));
|
||||||
|
print_opt("-_", "--minibar", N_("Show a feedback bar at the bottom"));
|
||||||
|
print_opt("-0", "--zero", N_("Hide all bars, use whole terminal"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display the version number of this nano, a copyright notice, some contact
|
/* Display the version number of this nano, a copyright notice, some contact
|
||||||
@ -670,8 +678,8 @@ void version(void)
|
|||||||
printf(_(" GNU nano, version %s\n"), VERSION);
|
printf(_(" GNU nano, version %s\n"), VERSION);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
printf(" (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.\n");
|
/* TRANSLATORS: The %s is the year of the latest release. */
|
||||||
printf(_(" (C) 2014-%s the contributors to nano\n"), "2021");
|
printf(_(" (C) %s the Free Software Foundation and various contributors\n"), "2023");
|
||||||
#endif
|
#endif
|
||||||
printf(_(" Compiled options:"));
|
printf(_(" Compiled options:"));
|
||||||
|
|
||||||
@ -686,6 +694,9 @@ void version(void)
|
|||||||
#ifdef ENABLE_EXTRA
|
#ifdef ENABLE_EXTRA
|
||||||
printf(" --enable-extra");
|
printf(" --enable-extra");
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
|
printf(" --enable-formatter");
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_HELP
|
#ifdef ENABLE_HELP
|
||||||
printf(" --enable-help");
|
printf(" --enable-help");
|
||||||
#endif
|
#endif
|
||||||
@ -701,6 +712,9 @@ void version(void)
|
|||||||
#ifdef ENABLE_LINENUMBERS
|
#ifdef ENABLE_LINENUMBERS
|
||||||
printf(" --enable-linenumbers");
|
printf(" --enable-linenumbers");
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_LINTER
|
||||||
|
printf(" --enable-linter");
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_MOUSE
|
#ifdef ENABLE_MOUSE
|
||||||
printf(" --enable-mouse");
|
printf(" --enable-mouse");
|
||||||
#endif
|
#endif
|
||||||
@ -735,6 +749,9 @@ void version(void)
|
|||||||
#ifndef ENABLE_EXTRA
|
#ifndef ENABLE_EXTRA
|
||||||
printf(" --disable-extra");
|
printf(" --disable-extra");
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ENABLE_FORMATTER
|
||||||
|
printf(" --disable-formatter");
|
||||||
|
#endif
|
||||||
#ifndef ENABLE_HELP
|
#ifndef ENABLE_HELP
|
||||||
printf(" --disable-help");
|
printf(" --disable-help");
|
||||||
#endif
|
#endif
|
||||||
@ -750,6 +767,9 @@ void version(void)
|
|||||||
#ifndef ENABLE_LINENUMBERS
|
#ifndef ENABLE_LINENUMBERS
|
||||||
printf(" --disable-linenumbers");
|
printf(" --disable-linenumbers");
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ENABLE_LINTER
|
||||||
|
printf(" --disable-linter");
|
||||||
|
#endif
|
||||||
#ifndef ENABLE_MOUSE
|
#ifndef ENABLE_MOUSE
|
||||||
printf(" --disable-mouse");
|
printf(" --disable-mouse");
|
||||||
#endif
|
#endif
|
||||||
@ -894,10 +914,11 @@ void signal_init(void)
|
|||||||
sigaction(SIGTERM, &deed, NULL);
|
sigaction(SIGTERM, &deed, NULL);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
|
#ifdef SIGWINCH
|
||||||
/* Trap SIGWINCH because we want to handle window resizes. */
|
/* Trap SIGWINCH because we want to handle window resizes. */
|
||||||
deed.sa_handler = handle_sigwinch;
|
deed.sa_handler = handle_sigwinch;
|
||||||
sigaction(SIGWINCH, &deed, NULL);
|
sigaction(SIGWINCH, &deed, NULL);
|
||||||
|
#endif
|
||||||
#ifdef SIGTSTP
|
#ifdef SIGTSTP
|
||||||
/* Prevent the suspend handler from getting interrupted. */
|
/* Prevent the suspend handler from getting interrupted. */
|
||||||
sigfillset(&deed.sa_mask);
|
sigfillset(&deed.sa_mask);
|
||||||
@ -998,11 +1019,13 @@ void continue_nano(int signal)
|
|||||||
/* Block or unblock the SIGWINCH signal, depending on the blockit parameter. */
|
/* Block or unblock the SIGWINCH signal, depending on the blockit parameter. */
|
||||||
void block_sigwinch(bool blockit)
|
void block_sigwinch(bool blockit)
|
||||||
{
|
{
|
||||||
|
#ifdef SIGWINCH
|
||||||
sigset_t winch;
|
sigset_t winch;
|
||||||
|
|
||||||
sigemptyset(&winch);
|
sigemptyset(&winch);
|
||||||
sigaddset(&winch, SIGWINCH);
|
sigaddset(&winch, SIGWINCH);
|
||||||
sigprocmask(blockit ? SIG_BLOCK : SIG_UNBLOCK, &winch, NULL);
|
sigprocmask(blockit ? SIG_BLOCK : SIG_UNBLOCK, &winch, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (the_window_resized)
|
if (the_window_resized)
|
||||||
@ -1022,38 +1045,19 @@ void handle_sigwinch(int signal)
|
|||||||
/* Reinitialize and redraw the screen completely. */
|
/* Reinitialize and redraw the screen completely. */
|
||||||
void regenerate_screen(void)
|
void regenerate_screen(void)
|
||||||
{
|
{
|
||||||
const char *tty = ttyname(0);
|
|
||||||
int fd, result = 0;
|
|
||||||
struct winsize win;
|
|
||||||
|
|
||||||
/* Reset the trigger. */
|
/* Reset the trigger. */
|
||||||
the_window_resized = FALSE;
|
the_window_resized = FALSE;
|
||||||
|
|
||||||
if (tty == NULL)
|
/* Leave and immediately reenter curses mode, so that ncurses notices
|
||||||
return;
|
* the new screen dimensions and sets LINES and COLS accordingly. */
|
||||||
fd = open(tty, O_RDWR);
|
endwin();
|
||||||
if (fd == -1)
|
refresh();
|
||||||
return;
|
|
||||||
result = ioctl(fd, TIOCGWINSZ, &win);
|
|
||||||
close(fd);
|
|
||||||
if (result == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* We could check whether COLS or LINES changed, and return otherwise,
|
|
||||||
* but it seems curses does not always update these global variables. */
|
|
||||||
#ifdef REDEFINING_MACROS_OK
|
|
||||||
COLS = win.ws_col;
|
|
||||||
LINES = win.ws_row;
|
|
||||||
#endif
|
|
||||||
thebar = (ISSET(INDICATOR) && LINES > 5 && COLS > 9) ? 1 : 0;
|
thebar = (ISSET(INDICATOR) && LINES > 5 && COLS > 9) ? 1 : 0;
|
||||||
bardata = nrealloc(bardata, LINES * sizeof(int));
|
bardata = nrealloc(bardata, LINES * sizeof(int));
|
||||||
|
|
||||||
editwincols = COLS - margin - thebar;
|
editwincols = COLS - margin - thebar;
|
||||||
|
|
||||||
/* Do as the website suggests: leave and immediately reenter curses mode. */
|
|
||||||
endwin();
|
|
||||||
doupdate();
|
|
||||||
|
|
||||||
/* Put the terminal in the desired state again, and
|
/* Put the terminal in the desired state again, and
|
||||||
* recreate the subwindows with their (new) sizes. */
|
* recreate the subwindows with their (new) sizes. */
|
||||||
terminal_init();
|
terminal_init();
|
||||||
@ -1110,7 +1114,7 @@ void toggle_this(int flag)
|
|||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
break;
|
break;
|
||||||
case TABS_TO_SPACES:
|
case TABS_TO_SPACES:
|
||||||
if (openfile->syntax && openfile->syntax->tab) {
|
if (openfile->syntax && openfile->syntax->tabstring) {
|
||||||
statusline(AHEM, _("Current syntax determines Tab"));
|
statusline(AHEM, _("Current syntax determines Tab"));
|
||||||
TOGGLE(flag);
|
TOGGLE(flag);
|
||||||
return;
|
return;
|
||||||
@ -1283,6 +1287,12 @@ void unbound_key(int code)
|
|||||||
/* TRANSLATORS: This refers to a sequence of escape codes
|
/* TRANSLATORS: This refers to a sequence of escape codes
|
||||||
* (from the keyboard) that nano does not recognize. */
|
* (from the keyboard) that nano does not recognize. */
|
||||||
statusline(AHEM, _("Unknown sequence"));
|
statusline(AHEM, _("Unknown sequence"));
|
||||||
|
#ifdef ENABLE_NANORC
|
||||||
|
else if (code == NO_SUCH_FUNCTION)
|
||||||
|
statusline(AHEM, _("Unknown function: %s"), commandname);
|
||||||
|
else if (code == MISSING_BRACE)
|
||||||
|
statusline(AHEM, _("Missing }"));
|
||||||
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
else if (code > KEY_F0 && code < KEY_F0 + 25)
|
else if (code > KEY_F0 && code < KEY_F0 + 25)
|
||||||
/* TRANSLATORS: This refers to an unbound function key. */
|
/* TRANSLATORS: This refers to an unbound function key. */
|
||||||
@ -1298,17 +1308,17 @@ void unbound_key(int code)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
if (shifted_metas && 'A' <= code && code <= 'Z')
|
if (shifted_metas && 'A' <= code && code <= 'Z')
|
||||||
statusline(AHEM, _("Unbound key: Sh-M-%c"), code);
|
statusline(AHEM, _("Unbound key: %s%c"), "Sh-M-", code);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
statusline(AHEM, _("Unbound key: M-%c"), toupper(code));
|
statusline(AHEM, _("Unbound key: %s%c"), "M-", toupper(code));
|
||||||
} else if (code == ESC_CODE)
|
} else if (code == ESC_CODE)
|
||||||
statusline(AHEM, _("Unbindable key: ^["));
|
statusline(AHEM, _("Unbindable key: ^["));
|
||||||
else if (code < 0x20)
|
else if (code < 0x20)
|
||||||
statusline(AHEM, _("Unbound key: ^%c"), code + 0x40);
|
statusline(AHEM, _("Unbound key: %s%c"), "^", code + 0x40);
|
||||||
#if defined(ENABLE_BROWSER) || defined (ENABLE_HELP)
|
#if defined(ENABLE_BROWSER) || defined (ENABLE_HELP)
|
||||||
else
|
else
|
||||||
statusline(AHEM, _("Unbound key: %c"), code);
|
statusline(AHEM, _("Unbound key: %s%c"), "", code);
|
||||||
#endif
|
#endif
|
||||||
set_blankdelay_to_one();
|
set_blankdelay_to_one();
|
||||||
}
|
}
|
||||||
@ -1325,7 +1335,7 @@ int do_mouse(void)
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* If the click was in the edit window, put the cursor in that spot. */
|
/* If the click was in the edit window, put the cursor in that spot. */
|
||||||
if (wmouse_trafo(edit, &click_row, &click_col, FALSE)) {
|
if (wmouse_trafo(midwin, &click_row, &click_col, FALSE)) {
|
||||||
linestruct *current_save = openfile->current;
|
linestruct *current_save = openfile->current;
|
||||||
ssize_t row_count = click_row - openfile->current_y;
|
ssize_t row_count = click_row - openfile->current_y;
|
||||||
size_t leftedge;
|
size_t leftedge;
|
||||||
@ -1372,7 +1382,7 @@ int do_mouse(void)
|
|||||||
/* Return TRUE when the given function is a cursor-moving command. */
|
/* Return TRUE when the given function is a cursor-moving command. */
|
||||||
bool wanted_to_move(void (*func)(void))
|
bool wanted_to_move(void (*func)(void))
|
||||||
{
|
{
|
||||||
return func == do_left || func == do_right ||
|
return (func == do_left || func == do_right ||
|
||||||
func == do_up || func == do_down ||
|
func == do_up || func == do_down ||
|
||||||
func == do_home || func == do_end ||
|
func == do_home || func == do_end ||
|
||||||
func == to_prev_word || func == to_next_word ||
|
func == to_prev_word || func == to_next_word ||
|
||||||
@ -1381,19 +1391,35 @@ bool wanted_to_move(void (*func)(void))
|
|||||||
#endif
|
#endif
|
||||||
func == to_prev_block || func == to_next_block ||
|
func == to_prev_block || func == to_next_block ||
|
||||||
func == do_page_up || func == do_page_down ||
|
func == do_page_up || func == do_page_down ||
|
||||||
func == to_first_line || func == to_last_line;
|
func == to_first_line || func == to_last_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return TRUE when the given shortcut is admissible in view mode. */
|
/* Return TRUE when the given function makes a change -- no good for view mode. */
|
||||||
bool okay_for_view(const keystruct *shortcut)
|
bool changes_something(functionptrtype f)
|
||||||
{
|
{
|
||||||
funcstruct *item = allfuncs;
|
return (f == do_savefile || f == do_writeout || f == do_enter || f == do_tab ||
|
||||||
|
f == do_delete || f == do_backspace || f == cut_text || f == paste_text ||
|
||||||
/* Search the function of the given shortcut in the list of functions. */
|
#ifndef NANO_TINY
|
||||||
while (item != NULL && item->func != shortcut->func)
|
f == chop_previous_word || f == chop_next_word ||
|
||||||
item = item->next;
|
f == zap_text || f == cut_till_eof || f == do_execute ||
|
||||||
|
f == do_indent || f == do_unindent ||
|
||||||
return (item == NULL || item->viewok);
|
#endif
|
||||||
|
#ifdef ENABLE_JUSTIFY
|
||||||
|
f == do_justify || f == do_full_justify ||
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_COMMENT
|
||||||
|
f == do_comment ||
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_SPELLER
|
||||||
|
f == do_spell ||
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
|
f == do_formatter ||
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_WORDCOMPLETION
|
||||||
|
f == complete_a_word ||
|
||||||
|
#endif
|
||||||
|
f == do_replace || f == do_verbatim_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -1408,7 +1434,7 @@ void suck_up_input_and_paste_it(void)
|
|||||||
cutbuffer = line;
|
cutbuffer = line;
|
||||||
|
|
||||||
while (bracketed_paste) {
|
while (bracketed_paste) {
|
||||||
int input = get_kbinput(edit, BLIND);
|
int input = get_kbinput(midwin, BLIND);
|
||||||
|
|
||||||
if (input == '\r' || input == '\n') {
|
if (input == '\r' || input == '\n') {
|
||||||
line->next = make_new_node(line);
|
line->next = make_new_node(line);
|
||||||
@ -1424,7 +1450,10 @@ void suck_up_input_and_paste_it(void)
|
|||||||
beep();
|
beep();
|
||||||
}
|
}
|
||||||
|
|
||||||
paste_text();
|
if (ISSET(VIEW_MODE))
|
||||||
|
print_view_warning();
|
||||||
|
else
|
||||||
|
paste_text();
|
||||||
|
|
||||||
free_lines(cutbuffer);
|
free_lines(cutbuffer);
|
||||||
cutbuffer = was_cutbuffer;
|
cutbuffer = was_cutbuffer;
|
||||||
@ -1439,6 +1468,7 @@ void inject(char *burst, size_t count)
|
|||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
size_t original_row = 0;
|
size_t original_row = 0;
|
||||||
size_t old_amount = 0;
|
size_t old_amount = 0;
|
||||||
|
UNFOLD_SEGMENT(thisline);
|
||||||
|
|
||||||
if (ISSET(SOFTWRAP)) {
|
if (ISSET(SOFTWRAP)) {
|
||||||
if (openfile->current_y == editwinrows - 1)
|
if (openfile->current_y == editwinrows - 1)
|
||||||
@ -1531,6 +1561,8 @@ void process_a_keystroke(void)
|
|||||||
/* The keystroke we read in: a character or a shortcut. */
|
/* The keystroke we read in: a character or a shortcut. */
|
||||||
static char *puddle = NULL;
|
static char *puddle = NULL;
|
||||||
/* The input buffer for actual characters. */
|
/* The input buffer for actual characters. */
|
||||||
|
static size_t capacity = 12;
|
||||||
|
/* The size of the input buffer; gets doubled whenever needed. */
|
||||||
static size_t depth = 0;
|
static size_t depth = 0;
|
||||||
/* The length of the input buffer. */
|
/* The length of the input buffer. */
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -1538,9 +1570,10 @@ void process_a_keystroke(void)
|
|||||||
#endif
|
#endif
|
||||||
static bool give_a_hint = TRUE;
|
static bool give_a_hint = TRUE;
|
||||||
const keystruct *shortcut;
|
const keystruct *shortcut;
|
||||||
|
functionptrtype function;
|
||||||
|
|
||||||
/* Read in a keystroke, and show the cursor while waiting. */
|
/* Read in a keystroke, and show the cursor while waiting. */
|
||||||
input = get_kbinput(edit, VISIBLE);
|
input = get_kbinput(midwin, VISIBLE);
|
||||||
|
|
||||||
lastmessage = VACUUM;
|
lastmessage = VACUUM;
|
||||||
|
|
||||||
@ -1553,17 +1586,18 @@ void process_a_keystroke(void)
|
|||||||
/* If the user clicked on a shortcut, read in the key code that it was
|
/* If the user clicked on a shortcut, read in the key code that it was
|
||||||
* converted into. Else the click has been handled or was invalid. */
|
* converted into. Else the click has been handled or was invalid. */
|
||||||
if (do_mouse() == 1)
|
if (do_mouse() == 1)
|
||||||
input = get_kbinput(edit, BLIND);
|
input = get_kbinput(midwin, BLIND);
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for a shortcut in the main list. */
|
/* Check for a shortcut in the main list. */
|
||||||
shortcut = get_shortcut(&input);
|
shortcut = get_shortcut(input);
|
||||||
|
function = (shortcut ? shortcut->func : NULL);
|
||||||
|
|
||||||
/* If not a command, discard anything that is not a normal character byte. */
|
/* If not a command, discard anything that is not a normal character byte. */
|
||||||
if (shortcut == NULL) {
|
if (!function) {
|
||||||
if (input < 0x20 || input > 0xFF || meta_key)
|
if (input < 0x20 || input > 0xFF || meta_key)
|
||||||
unbound_key(input);
|
unbound_key(input);
|
||||||
else if (ISSET(VIEW_MODE))
|
else if (ISSET(VIEW_MODE))
|
||||||
@ -1575,31 +1609,33 @@ void process_a_keystroke(void)
|
|||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Store the byte, and leave room for a terminating zero. */
|
/* When the input buffer (plus room for terminating NUL) is full,
|
||||||
puddle = nrealloc(puddle, depth + 2);
|
* extend it; otherwise, if it does not exist yet, create it. */
|
||||||
|
if (depth + 1 == capacity) {
|
||||||
|
capacity = 2 * capacity;
|
||||||
|
puddle = nrealloc(puddle, capacity);
|
||||||
|
} else if (!puddle)
|
||||||
|
puddle = nmalloc(capacity);
|
||||||
|
|
||||||
puddle[depth++] = (char)input;
|
puddle[depth++] = (char)input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have a command, or if there aren't any other key codes waiting,
|
/* If there are gathered bytes and we have a command or no other key codes
|
||||||
* it's time to insert the gathered bytes into the edit buffer. */
|
* are waiting, it's time to insert these bytes into the edit buffer. */
|
||||||
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
|
if (depth > 0 && (function || waiting_keycodes() == 0)) {
|
||||||
puddle[depth] = '\0';
|
puddle[depth] = '\0';
|
||||||
|
|
||||||
inject(puddle, depth);
|
inject(puddle, depth);
|
||||||
|
|
||||||
free(puddle);
|
|
||||||
puddle = NULL;
|
|
||||||
depth = 0;
|
depth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shortcut == NULL) {
|
if (!function) {
|
||||||
pletion_line = NULL;
|
pletion_line = NULL;
|
||||||
keep_cutbuffer = FALSE;
|
keep_cutbuffer = FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ISSET(VIEW_MODE) && !okay_for_view(shortcut)) {
|
if (ISSET(VIEW_MODE) && changes_something(function)) {
|
||||||
print_view_warning();
|
print_view_warning();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1612,25 +1648,25 @@ void process_a_keystroke(void)
|
|||||||
give_a_hint = FALSE;
|
give_a_hint = FALSE;
|
||||||
|
|
||||||
/* When not cutting or copying text, drop the cutbuffer the next time. */
|
/* When not cutting or copying text, drop the cutbuffer the next time. */
|
||||||
if (shortcut->func != cut_text) {
|
if (function != cut_text) {
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (shortcut->func != copy_text && shortcut->func != zap_text)
|
if (function != copy_text && function != zap_text)
|
||||||
#endif
|
#endif
|
||||||
keep_cutbuffer = FALSE;
|
keep_cutbuffer = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WORDCOMPLETION
|
#ifdef ENABLE_WORDCOMPLETION
|
||||||
if (shortcut->func != complete_a_word)
|
if (function != complete_a_word)
|
||||||
pletion_line = NULL;
|
pletion_line = NULL;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
if (shortcut->func == (functionptrtype)implant) {
|
if (function == (functionptrtype)implant) {
|
||||||
implant(shortcut->expansion);
|
implant(shortcut->expansion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (shortcut->func == do_toggle) {
|
if (function == do_toggle) {
|
||||||
toggle_this(shortcut->toggle);
|
toggle_this(shortcut->toggle);
|
||||||
if (shortcut->toggle == CUT_FROM_CURSOR)
|
if (shortcut->toggle == CUT_FROM_CURSOR)
|
||||||
keep_cutbuffer = FALSE;
|
keep_cutbuffer = FALSE;
|
||||||
@ -1649,32 +1685,21 @@ void process_a_keystroke(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Execute the function of the shortcut. */
|
/* Execute the function of the shortcut. */
|
||||||
shortcut->func();
|
function();
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* When the marked region changes without Shift being held,
|
/* When the marked region changes without Shift being held,
|
||||||
* discard a soft mark. And when the marked region covers a
|
* discard a soft mark. And when the set of lines changes,
|
||||||
* different set of lines, reset the "last line too" flag. */
|
* reset the "last line too" flag. */
|
||||||
if (openfile->mark) {
|
if (openfile->mark && openfile->softmark && !shift_held &&
|
||||||
if (!shift_held && openfile->softmark &&
|
(openfile->current != was_current ||
|
||||||
(openfile->current != was_current ||
|
openfile->current_x != was_x ||
|
||||||
openfile->current_x != was_x ||
|
wanted_to_move(function))) {
|
||||||
wanted_to_move(shortcut->func))) {
|
openfile->mark = NULL;
|
||||||
openfile->mark = NULL;
|
refresh_needed = TRUE;
|
||||||
refresh_needed = TRUE;
|
} else if (openfile->current != was_current)
|
||||||
} else if (openfile->current != was_current)
|
also_the_last = FALSE;
|
||||||
also_the_last = FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
if (!refresh_needed && !okay_for_view(shortcut))
|
|
||||||
check_the_multis(openfile->current);
|
|
||||||
#endif
|
|
||||||
if (!refresh_needed && (shortcut->func == do_delete ||
|
|
||||||
shortcut->func == do_backspace))
|
|
||||||
update_line(openfile->current, openfile->current_x);
|
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
|
||||||
if (bracketed_paste)
|
if (bracketed_paste)
|
||||||
suck_up_input_and_paste_it();
|
suck_up_input_and_paste_it();
|
||||||
|
|
||||||
@ -1752,13 +1777,11 @@ int main(int argc, char **argv)
|
|||||||
{"speller", 1, NULL, 's'},
|
{"speller", 1, NULL, 's'},
|
||||||
#endif
|
#endif
|
||||||
{"saveonexit", 0, NULL, 't'},
|
{"saveonexit", 0, NULL, 't'},
|
||||||
{"tempfile", 0, NULL, 't'}, /* Deprecated; remove in 2022. */
|
|
||||||
{"view", 0, NULL, 'v'},
|
{"view", 0, NULL, 'v'},
|
||||||
#ifdef ENABLE_WRAPPING
|
#ifdef ENABLE_WRAPPING
|
||||||
{"nowrap", 0, NULL, 'w'},
|
{"nowrap", 0, NULL, 'w'},
|
||||||
#endif
|
#endif
|
||||||
{"nohelp", 0, NULL, 'x'},
|
{"nohelp", 0, NULL, 'x'},
|
||||||
{"suspendable", 0, NULL, 'z'}, /* Obsolete; remove in 2022. */
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
{"smarthome", 0, NULL, 'A'},
|
{"smarthome", 0, NULL, 'A'},
|
||||||
{"backup", 0, NULL, 'B'},
|
{"backup", 0, NULL, 'B'},
|
||||||
@ -1805,10 +1828,12 @@ int main(int argc, char **argv)
|
|||||||
/* Back up the terminal settings so that they can be restored. */
|
/* Back up the terminal settings so that they can be restored. */
|
||||||
tcgetattr(STDIN_FILENO, &original_state);
|
tcgetattr(STDIN_FILENO, &original_state);
|
||||||
|
|
||||||
|
#if defined(F_GETFL) && defined(F_SETFL)
|
||||||
/* Get the state of standard input and ensure it uses blocking mode. */
|
/* Get the state of standard input and ensure it uses blocking mode. */
|
||||||
stdin_flags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
stdin_flags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||||
if (stdin_flags != -1)
|
if (stdin_flags != -1)
|
||||||
fcntl(STDIN_FILENO, F_SETFL, stdin_flags & ~O_NONBLOCK);
|
fcntl(STDIN_FILENO, F_SETFL, stdin_flags & ~O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_UTF8
|
#ifdef ENABLE_UTF8
|
||||||
/* If setting the locale is successful and it uses UTF-8, we will
|
/* If setting the locale is successful and it uses UTF-8, we will
|
||||||
@ -1831,8 +1856,8 @@ int main(int argc, char **argv)
|
|||||||
if (*(tail(argv[0])) == 'r')
|
if (*(tail(argv[0])) == 'r')
|
||||||
SET(RESTRICTED);
|
SET(RESTRICTED);
|
||||||
|
|
||||||
while ((optchr = getopt_long(argc, argv, "0ABC:DEFGHIJ:KLMNOPQ:RST:UVWX:Y:Z"
|
while ((optchr = getopt_long(argc, argv, "ABC:DEFGHIJ:KLMNOPQ:RS$T:UVWX:Y:Z"
|
||||||
"abcdef:ghijklmno:pqr:s:tuvwxyz$%_!", long_options, NULL)) != -1) {
|
"abcdef:ghijklmno:pqr:s:tuvwxy!%_0", long_options, NULL)) != -1) {
|
||||||
switch (optchr) {
|
switch (optchr) {
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
case 'A':
|
case 'A':
|
||||||
@ -2065,8 +2090,11 @@ int main(int argc, char **argv)
|
|||||||
SET(AFTER_ENDS);
|
SET(AFTER_ENDS);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'z':
|
#ifdef HAVE_LIBMAGIC
|
||||||
|
case '!':
|
||||||
|
SET(USE_MAGIC);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
case '%':
|
case '%':
|
||||||
SET(STATEFLAGS);
|
SET(STATEFLAGS);
|
||||||
@ -2077,11 +2105,6 @@ int main(int argc, char **argv)
|
|||||||
case '0':
|
case '0':
|
||||||
SET(ZERO);
|
SET(ZERO);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
#ifdef HAVE_LIBMAGIC
|
|
||||||
case '!':
|
|
||||||
SET(USE_MAGIC);
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
printf(_("Type '%s -h' for a list of available options.\n"), argv[0]);
|
printf(_("Type '%s -h' for a list of available options.\n"), argv[0]);
|
||||||
@ -2091,7 +2114,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Curses needs TERM; if it is unset, try falling back to a VT220. */
|
/* Curses needs TERM; if it is unset, try falling back to a VT220. */
|
||||||
if (getenv("TERM") == NULL)
|
if (getenv("TERM") == NULL)
|
||||||
setenv("TERM", "vt220", 0);
|
putenv("TERM=vt220");
|
||||||
|
|
||||||
/* Enter into curses mode. Abort if this fails. */
|
/* Enter into curses mode. Abort if this fails. */
|
||||||
if (initscr() == NULL)
|
if (initscr() == NULL)
|
||||||
@ -2101,6 +2124,9 @@ int main(int argc, char **argv)
|
|||||||
/* If the terminal can do colors, tell ncurses to switch them on. */
|
/* If the terminal can do colors, tell ncurses to switch them on. */
|
||||||
if (has_colors())
|
if (has_colors())
|
||||||
start_color();
|
start_color();
|
||||||
|
|
||||||
|
/* When requested, suppress the default spotlight and error colors. */
|
||||||
|
rescind_colors = (getenv("NO_COLOR") != NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set up the function and shortcut lists. This needs to be done
|
/* Set up the function and shortcut lists. This needs to be done
|
||||||
@ -2187,7 +2213,7 @@ int main(int argc, char **argv)
|
|||||||
alt_speller = alt_speller_cmdline;
|
alt_speller = alt_speller_cmdline;
|
||||||
}
|
}
|
||||||
/* Strip leading whitespace from the speller command, if any. */
|
/* Strip leading whitespace from the speller command, if any. */
|
||||||
while (alt_speller && *alt_speller && isblank(*alt_speller))
|
while (alt_speller && (*alt_speller == ' ' || *alt_speller == '\t'))
|
||||||
memmove(alt_speller, alt_speller + 1, strlen(alt_speller));
|
memmove(alt_speller, alt_speller + 1, strlen(alt_speller));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2408,6 +2434,8 @@ int main(int argc, char **argv)
|
|||||||
shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP);
|
shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP);
|
||||||
shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN);
|
shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN);
|
||||||
#endif
|
#endif
|
||||||
|
mousefocusin = get_keycode("kxIN", FOCUS_IN);
|
||||||
|
mousefocusout = get_keycode("kxOUT", FOCUS_OUT);
|
||||||
|
|
||||||
#ifdef HAVE_SET_ESCDELAY
|
#ifdef HAVE_SET_ESCDELAY
|
||||||
/* Tell ncurses to pass the Esc key quickly. */
|
/* Tell ncurses to pass the Esc key quickly. */
|
||||||
@ -2425,7 +2453,7 @@ int main(int argc, char **argv)
|
|||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
int n = 1;
|
int n = 1;
|
||||||
|
|
||||||
while (isalpha(argv[optind][n])) {
|
while (isalpha((unsigned char)argv[optind][n])) {
|
||||||
switch (argv[optind][n++]) {
|
switch (argv[optind][n++]) {
|
||||||
case 'c': SET(CASE_SENSITIVE); break;
|
case 'c': SET(CASE_SENSITIVE); break;
|
||||||
case 'C': UNSET(CASE_SENSITIVE); break;
|
case 'C': UNSET(CASE_SENSITIVE); break;
|
||||||
@ -2442,7 +2470,7 @@ int main(int argc, char **argv)
|
|||||||
searchstring = copy_of(&argv[optind][n + 1]);
|
searchstring = copy_of(&argv[optind][n + 1]);
|
||||||
if (argv[optind][n] == '?')
|
if (argv[optind][n] == '?')
|
||||||
SET(BACKWARDS_SEARCH);
|
SET(BACKWARDS_SEARCH);
|
||||||
} else if (n == 1)
|
} else
|
||||||
statusline(ALERT, _("Empty search string"));
|
statusline(ALERT, _("Empty search string"));
|
||||||
optind++;
|
optind++;
|
||||||
} else
|
} else
|
||||||
@ -2464,8 +2492,26 @@ int main(int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (!open_buffer(argv[optind++], TRUE))
|
{
|
||||||
continue;
|
char *filename = argv[optind++];
|
||||||
|
char *colon = filename + (*filename ? 1 : 0);
|
||||||
|
|
||||||
|
/* Search the filename for a colon. If the colon is preceded by
|
||||||
|
* a backslash, elide the backslash and skip the colon. If there
|
||||||
|
* is a valid number after the colon, chop colon and number off.
|
||||||
|
* The number is later used to place the cursor on that line. */
|
||||||
|
while ((colon = strchr(colon, ':'))) {
|
||||||
|
if (*(colon - 1) == '\\')
|
||||||
|
memmove(colon - 1, colon, strlen(colon) + 1);
|
||||||
|
else if (parse_line_column(colon + 1, &givenline, &givencol))
|
||||||
|
*colon = '\0';
|
||||||
|
else
|
||||||
|
++colon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open_buffer(filename, TRUE))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* If a position was given on the command line, go there. */
|
/* If a position was given on the command line, go there. */
|
||||||
if (givenline != 0 || givencol != 0)
|
if (givenline != 0 || givencol != 0)
|
||||||
@ -2480,6 +2526,7 @@ int main(int argc, char **argv)
|
|||||||
else if (lastmessage <= REMARK)
|
else if (lastmessage <= REMARK)
|
||||||
wipe_statusbar();
|
wipe_statusbar();
|
||||||
openfile->placewewant = xplustabs();
|
openfile->placewewant = xplustabs();
|
||||||
|
adjust_viewport(CENTERING);
|
||||||
if (ISSET(USE_REGEXP))
|
if (ISSET(USE_REGEXP))
|
||||||
tidy_up_after_search();
|
tidy_up_after_search();
|
||||||
free(last_search);
|
free(last_search);
|
||||||
@ -2500,6 +2547,10 @@ int main(int argc, char **argv)
|
|||||||
/* After handling the files on the command line, allow inserting files. */
|
/* After handling the files on the command line, allow inserting files. */
|
||||||
UNSET(NOREAD_MODE);
|
UNSET(NOREAD_MODE);
|
||||||
|
|
||||||
|
/* Nano is a hands-on editor -- it needs a keyboard. */
|
||||||
|
if (!isatty(STDIN_FILENO))
|
||||||
|
die(_("Standard input is not a terminal\n"));
|
||||||
|
|
||||||
/* If no filenames were given, or all of them were invalid things like
|
/* If no filenames were given, or all of them were invalid things like
|
||||||
* directories, then open a blank buffer and allow editing. Otherwise,
|
* directories, then open a blank buffer and allow editing. Otherwise,
|
||||||
* switch from the last opened file to the next, that is: the first. */
|
* switch from the last opened file to the next, that is: the first. */
|
||||||
@ -2524,7 +2575,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
if (startup_problem != NULL)
|
if (startup_problem != NULL)
|
||||||
statusline(ALERT, startup_problem);
|
statusline(ALERT, "%s", startup_problem);
|
||||||
|
|
||||||
#define NOTREBOUND first_sc_for(MMAIN, do_help) && \
|
#define NOTREBOUND first_sc_for(MMAIN, do_help) && \
|
||||||
first_sc_for(MMAIN, do_help)->keycode == 0x07
|
first_sc_for(MMAIN, do_help)->keycode == 0x07
|
||||||
@ -2538,6 +2589,11 @@ int main(int argc, char **argv)
|
|||||||
statusbar(_("Welcome to nano. For basic help, type Ctrl+G."));
|
statusbar(_("Welcome to nano. For basic help, type Ctrl+G."));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_LINENUMBERS
|
||||||
|
/* Set the margin to an impossible value to force re-evaluation. */
|
||||||
|
margin = 12345;
|
||||||
|
#endif
|
||||||
|
|
||||||
we_are_running = TRUE;
|
we_are_running = TRUE;
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
@ -2545,7 +2601,7 @@ int main(int argc, char **argv)
|
|||||||
confirm_margin();
|
confirm_margin();
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (on_a_vt && get_key_buffer_len() == 0)
|
if (on_a_vt && waiting_keycodes() == 0)
|
||||||
mute_modifiers = FALSE;
|
mute_modifiers = FALSE;
|
||||||
#endif
|
#endif
|
||||||
if (currmenu != MMAIN)
|
if (currmenu != MMAIN)
|
||||||
@ -2559,7 +2615,7 @@ int main(int argc, char **argv)
|
|||||||
/* Update the displayed current cursor position only when there
|
/* Update the displayed current cursor position only when there
|
||||||
* is no message and no keys are waiting in the input buffer. */
|
* is no message and no keys are waiting in the input buffer. */
|
||||||
if (ISSET(CONSTANT_SHOW) && lastmessage == VACUUM && LINES > 1 &&
|
if (ISSET(CONSTANT_SHOW) && lastmessage == VACUUM && LINES > 1 &&
|
||||||
!ISSET(ZERO) && get_key_buffer_len() == 0)
|
!ISSET(ZERO) && waiting_keycodes() == 0)
|
||||||
report_cursor_position();
|
report_cursor_position();
|
||||||
|
|
||||||
as_an_at = TRUE;
|
as_an_at = TRUE;
|
||||||
@ -2575,13 +2631,13 @@ int main(int argc, char **argv)
|
|||||||
if (ISSET(ZERO) && lastmessage > HUSH) {
|
if (ISSET(ZERO) && lastmessage > HUSH) {
|
||||||
if (openfile->current_y == editwinrows - 1 && LINES > 1) {
|
if (openfile->current_y == editwinrows - 1 && LINES > 1) {
|
||||||
edit_scroll(FORWARD);
|
edit_scroll(FORWARD);
|
||||||
wnoutrefresh(edit);
|
wnoutrefresh(midwin);
|
||||||
}
|
}
|
||||||
wredrawln(bottomwin, 0 ,1);
|
wredrawln(footwin, 0, 1);
|
||||||
wnoutrefresh(bottomwin);
|
wnoutrefresh(footwin);
|
||||||
place_the_cursor();
|
place_the_cursor();
|
||||||
} else if (ISSET(ZERO) && lastmessage > VACUUM)
|
} else if (ISSET(ZERO) && lastmessage > VACUUM)
|
||||||
wredrawln(edit, editwinrows - 1, 1);
|
wredrawln(midwin, editwinrows - 1, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|||||||
524
src/prompt.c
524
src/prompt.c
@ -1,8 +1,8 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* prompt.c -- This file is part of GNU nano. *
|
* prompt.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2016, 2018, 2020 Benno Schulenberg *
|
* Copyright (C) 2016, 2018, 2020, 2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -41,6 +41,33 @@ void do_statusbar_end(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
|
/* Move to the previous word in the answer. */
|
||||||
|
void do_statusbar_prev_word(void)
|
||||||
|
{
|
||||||
|
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||||
|
|
||||||
|
/* Move backward until we pass over the start of a word. */
|
||||||
|
while (typing_x != 0) {
|
||||||
|
typing_x = step_left(answer, typing_x);
|
||||||
|
|
||||||
|
if (is_word_char(answer + typing_x, FALSE))
|
||||||
|
seen_a_word = TRUE;
|
||||||
|
#ifdef ENABLE_UTF8
|
||||||
|
else if (is_zerowidth(answer + typing_x))
|
||||||
|
; /* skip */
|
||||||
|
#endif
|
||||||
|
else if (seen_a_word) {
|
||||||
|
/* This is space now: we've overshot the start of the word. */
|
||||||
|
step_forward = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (step_forward)
|
||||||
|
/* Move one character forward again to sit on the start of the word. */
|
||||||
|
typing_x = step_right(answer, typing_x);
|
||||||
|
}
|
||||||
|
|
||||||
/* Move to the next word in the answer. */
|
/* Move to the next word in the answer. */
|
||||||
void do_statusbar_next_word(void)
|
void do_statusbar_next_word(void)
|
||||||
{
|
{
|
||||||
@ -78,33 +105,6 @@ void do_statusbar_next_word(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move to the previous word in the answer. */
|
|
||||||
void do_statusbar_prev_word(void)
|
|
||||||
{
|
|
||||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
|
||||||
|
|
||||||
/* Move backward until we pass over the start of a word. */
|
|
||||||
while (typing_x != 0) {
|
|
||||||
typing_x = step_left(answer, typing_x);
|
|
||||||
|
|
||||||
if (is_word_char(answer + typing_x, FALSE))
|
|
||||||
seen_a_word = TRUE;
|
|
||||||
#ifdef ENABLE_UTF8
|
|
||||||
else if (is_zerowidth(answer + typing_x))
|
|
||||||
; /* skip */
|
|
||||||
#endif
|
|
||||||
else if (seen_a_word) {
|
|
||||||
/* This is space now: we've overshot the start of the word. */
|
|
||||||
step_forward = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (step_forward)
|
|
||||||
/* Move one character forward again to sit on the start of the word. */
|
|
||||||
typing_x = step_right(answer, typing_x);
|
|
||||||
}
|
|
||||||
#endif /* !NANO_TINY */
|
#endif /* !NANO_TINY */
|
||||||
|
|
||||||
/* Move left one character in the answer. */
|
/* Move left one character in the answer. */
|
||||||
@ -131,6 +131,17 @@ void do_statusbar_right(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Backspace over one character in the answer. */
|
||||||
|
void do_statusbar_backspace(void)
|
||||||
|
{
|
||||||
|
if (typing_x > 0) {
|
||||||
|
size_t was_x = typing_x;
|
||||||
|
|
||||||
|
typing_x = step_left(answer, typing_x);
|
||||||
|
memmove(answer + typing_x, answer + was_x, strlen(answer) - was_x + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete one character in the answer. */
|
/* Delete one character in the answer. */
|
||||||
void do_statusbar_delete(void)
|
void do_statusbar_delete(void)
|
||||||
{
|
{
|
||||||
@ -146,42 +157,40 @@ void do_statusbar_delete(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Backspace over one character in the answer. */
|
/* Zap the part of the answer after the cursor, or the whole answer. */
|
||||||
void do_statusbar_backspace(void)
|
void lop_the_answer(void)
|
||||||
{
|
{
|
||||||
if (typing_x > 0) {
|
if (answer[typing_x] == '\0')
|
||||||
size_t was_x = typing_x;
|
|
||||||
|
|
||||||
typing_x = step_left(answer, typing_x);
|
|
||||||
memmove(answer + typing_x, answer + was_x, strlen(answer) - was_x + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zap some or all text from the answer. */
|
|
||||||
void do_statusbar_cut_text(void)
|
|
||||||
{
|
|
||||||
if (!ISSET(CUT_FROM_CURSOR))
|
|
||||||
typing_x = 0;
|
typing_x = 0;
|
||||||
|
|
||||||
answer[typing_x] = '\0';
|
answer[typing_x] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
/* Copy the current answer (if any) into the cutbuffer. */
|
||||||
|
void copy_the_answer(void)
|
||||||
|
{
|
||||||
|
if (*answer) {
|
||||||
|
free_lines(cutbuffer);
|
||||||
|
cutbuffer = make_new_node(NULL);
|
||||||
|
cutbuffer->data = copy_of(answer);
|
||||||
|
typing_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Paste the first line of the cutbuffer into the current answer. */
|
/* Paste the first line of the cutbuffer into the current answer. */
|
||||||
void paste_into_answer(void)
|
void paste_into_answer(void)
|
||||||
{
|
{
|
||||||
size_t pastelen = strlen(cutbuffer->data);
|
size_t pastelen = strlen(cutbuffer->data);
|
||||||
char *fusion = nmalloc(strlen(answer) + pastelen + 1);
|
|
||||||
|
|
||||||
/* Concatenate: the current answer before the cursor, the first line
|
answer = nrealloc(answer, strlen(answer) + pastelen + 1);
|
||||||
* of the cutbuffer, plus the rest of the current answer. */
|
memmove(answer + typing_x + pastelen, answer + typing_x,
|
||||||
strncpy(fusion, answer, typing_x);
|
strlen(answer) - typing_x + 1);
|
||||||
strncpy(fusion + typing_x, cutbuffer->data, pastelen);
|
strncpy(answer + typing_x, cutbuffer->data, pastelen);
|
||||||
strcpy(fusion + typing_x + pastelen, answer + typing_x);
|
|
||||||
|
|
||||||
free(answer);
|
|
||||||
answer = fusion;
|
|
||||||
typing_x += pastelen;
|
typing_x += pastelen;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_MOUSE
|
#ifdef ENABLE_MOUSE
|
||||||
/* Handle a mouse click on the status-bar prompt or the shortcut list. */
|
/* Handle a mouse click on the status-bar prompt or the shortcut list. */
|
||||||
@ -191,7 +200,7 @@ int do_statusbar_mouse(void)
|
|||||||
int retval = get_mouseinput(&click_row, &click_col, TRUE);
|
int retval = get_mouseinput(&click_row, &click_col, TRUE);
|
||||||
|
|
||||||
/* We can click on the status-bar window text to move the cursor. */
|
/* We can click on the status-bar window text to move the cursor. */
|
||||||
if (retval == 0 && wmouse_trafo(bottomwin, &click_row, &click_col, FALSE)) {
|
if (retval == 0 && wmouse_trafo(footwin, &click_row, &click_col, FALSE)) {
|
||||||
size_t start_col = breadth(prompt) + 2;
|
size_t start_col = breadth(prompt) + 2;
|
||||||
|
|
||||||
/* Move to where the click occurred. */
|
/* Move to where the click occurred. */
|
||||||
@ -216,7 +225,7 @@ void inject_into_answer(char *burst, size_t count)
|
|||||||
answer = nrealloc(answer, strlen(answer) + count + 1);
|
answer = nrealloc(answer, strlen(answer) + count + 1);
|
||||||
memmove(answer + typing_x + count, answer + typing_x,
|
memmove(answer + typing_x + count, answer + typing_x,
|
||||||
strlen(answer) - typing_x + 1);
|
strlen(answer) - typing_x + 1);
|
||||||
strncpy(answer + typing_x, burst , count);
|
strncpy(answer + typing_x, burst, count);
|
||||||
|
|
||||||
typing_x += count;
|
typing_x += count;
|
||||||
}
|
}
|
||||||
@ -227,7 +236,7 @@ void do_statusbar_verbatim_input(void)
|
|||||||
size_t count = 1;
|
size_t count = 1;
|
||||||
char *bytes;
|
char *bytes;
|
||||||
|
|
||||||
bytes = get_verbatim_kbinput(bottomwin, &count);
|
bytes = get_verbatim_kbinput(footwin, &count);
|
||||||
|
|
||||||
if (0 < count && count < 999)
|
if (0 < count && count < 999)
|
||||||
inject_into_answer(bytes, count);
|
inject_into_answer(bytes, count);
|
||||||
@ -237,127 +246,92 @@ void do_statusbar_verbatim_input(void)
|
|||||||
free(bytes);
|
free(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read in a keystroke, interpret it if it is a shortcut or toggle, and
|
/* Add the given input to the input buffer when it's a normal byte,
|
||||||
* return it. Set finished to TRUE if we're done after running
|
* and inject the gathered bytes into the answer when ready. */
|
||||||
* or trying to run a function associated with a shortcut key. */
|
void absorb_character(int input, functionptrtype function)
|
||||||
int do_statusbar_input(bool *finished)
|
|
||||||
{
|
{
|
||||||
int input;
|
|
||||||
/* The character we read in. */
|
|
||||||
static char *puddle = NULL;
|
static char *puddle = NULL;
|
||||||
/* The input buffer. */
|
/* The input buffer. */
|
||||||
|
static size_t capacity = 8;
|
||||||
|
/* The size of the input buffer; gets doubled whenever needed. */
|
||||||
static size_t depth = 0;
|
static size_t depth = 0;
|
||||||
/* The length of the input buffer. */
|
/* The length of the input buffer. */
|
||||||
const keystruct *shortcut;
|
|
||||||
|
|
||||||
*finished = FALSE;
|
|
||||||
|
|
||||||
/* Read in a character. */
|
|
||||||
input = get_kbinput(bottomwin, VISIBLE);
|
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
|
||||||
if (input == KEY_WINCH)
|
|
||||||
return KEY_WINCH;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_MOUSE
|
|
||||||
/* If we got a mouse click and it was on a shortcut, read in the
|
|
||||||
* shortcut character. */
|
|
||||||
if (input == KEY_MOUSE) {
|
|
||||||
if (do_statusbar_mouse() == 1)
|
|
||||||
input = get_kbinput(bottomwin, BLIND);
|
|
||||||
else
|
|
||||||
return ERR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check for a shortcut in the current list. */
|
|
||||||
shortcut = get_shortcut(&input);
|
|
||||||
|
|
||||||
/* If not a command, discard anything that is not a normal character byte.
|
/* If not a command, discard anything that is not a normal character byte.
|
||||||
* Apart from that, only accept input when not in restricted mode, or when
|
* Apart from that, only accept input when not in restricted mode, or when
|
||||||
* not at the "Write File" prompt, or when there is no filename yet. */
|
* not at the "Write File" prompt, or when there is no filename yet. */
|
||||||
if (shortcut == NULL) {
|
if (!function) {
|
||||||
if (input < 0x20 || input > 0xFF || meta_key)
|
if (input < 0x20 || input > 0xFF || meta_key)
|
||||||
beep();
|
beep();
|
||||||
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||||
openfile->filename[0] == '\0') {
|
openfile->filename[0] == '\0') {
|
||||||
puddle = nrealloc(puddle, depth + 2);
|
/* When the input buffer (plus room for terminating NUL) is full,
|
||||||
|
* extend it; otherwise, if it does not exist yet, create it. */
|
||||||
|
if (depth + 1 == capacity) {
|
||||||
|
capacity = 2 * capacity;
|
||||||
|
puddle = nrealloc(puddle, capacity);
|
||||||
|
} else if (!puddle)
|
||||||
|
puddle = nmalloc(capacity);
|
||||||
|
|
||||||
puddle[depth++] = (char)input;
|
puddle[depth++] = (char)input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we got a shortcut, or if there aren't any other keystrokes waiting,
|
/* If there are gathered bytes and we have a command or no other key codes
|
||||||
* it's time to insert all characters in the input buffer (if not empty)
|
* are waiting, it's time to insert these bytes into the answer. */
|
||||||
* into the answer, and then clear the input buffer. */
|
if (depth > 0 && (function || waiting_keycodes() == 0)) {
|
||||||
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
|
|
||||||
puddle[depth] = '\0';
|
puddle[depth] = '\0';
|
||||||
|
|
||||||
inject_into_answer(puddle, depth);
|
inject_into_answer(puddle, depth);
|
||||||
|
|
||||||
free(puddle);
|
|
||||||
puddle = NULL;
|
|
||||||
depth = 0;
|
depth = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (shortcut) {
|
/* Handle any editing shortcut, and return TRUE when handled. */
|
||||||
if (shortcut->func == do_tab || shortcut->func == do_enter)
|
bool handle_editing(functionptrtype function)
|
||||||
;
|
{
|
||||||
#ifdef ENABLE_HISTORIES
|
if (function == do_left)
|
||||||
else if (shortcut->func == get_older_item ||
|
do_statusbar_left();
|
||||||
shortcut->func == get_newer_item)
|
else if (function == do_right)
|
||||||
;
|
do_statusbar_right();
|
||||||
#endif
|
|
||||||
else if (shortcut->func == do_left)
|
|
||||||
do_statusbar_left();
|
|
||||||
else if (shortcut->func == do_right)
|
|
||||||
do_statusbar_right();
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
else if (shortcut->func == to_prev_word)
|
else if (function == to_prev_word)
|
||||||
do_statusbar_prev_word();
|
do_statusbar_prev_word();
|
||||||
else if (shortcut->func == to_next_word)
|
else if (function == to_next_word)
|
||||||
do_statusbar_next_word();
|
do_statusbar_next_word();
|
||||||
#endif
|
#endif
|
||||||
else if (shortcut->func == do_home)
|
else if (function == do_home)
|
||||||
do_statusbar_home();
|
do_statusbar_home();
|
||||||
else if (shortcut->func == do_end)
|
else if (function == do_end)
|
||||||
do_statusbar_end();
|
do_statusbar_end();
|
||||||
/* When in restricted mode at the "Write File" prompt and the
|
/* When in restricted mode at the "Write File" prompt and the
|
||||||
* filename isn't blank, disallow any input and deletion. */
|
* filename isn't blank, disallow any input and deletion. */
|
||||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
||||||
openfile->filename[0] != '\0' &&
|
openfile->filename[0] != '\0' &&
|
||||||
(shortcut->func == do_verbatim_input ||
|
(function == do_verbatim_input ||
|
||||||
shortcut->func == cut_text ||
|
function == do_delete || function == do_backspace ||
|
||||||
shortcut->func == paste_text ||
|
function == cut_text || function == paste_text))
|
||||||
shortcut->func == do_delete ||
|
;
|
||||||
shortcut->func == do_backspace))
|
else if (function == do_verbatim_input)
|
||||||
;
|
do_statusbar_verbatim_input();
|
||||||
#ifdef ENABLE_NANORC
|
else if (function == do_delete)
|
||||||
else if (shortcut->func == (functionptrtype)implant)
|
do_statusbar_delete();
|
||||||
implant(shortcut->expansion);
|
else if (function == do_backspace)
|
||||||
#endif
|
do_statusbar_backspace();
|
||||||
else if (shortcut->func == do_verbatim_input)
|
else if (function == cut_text)
|
||||||
do_statusbar_verbatim_input();
|
lop_the_answer();
|
||||||
else if (shortcut->func == cut_text)
|
#ifndef NANO_TINY
|
||||||
do_statusbar_cut_text();
|
else if (function == copy_text)
|
||||||
else if (shortcut->func == do_delete)
|
copy_the_answer();
|
||||||
do_statusbar_delete();
|
else if (function == paste_text) {
|
||||||
else if (shortcut->func == do_backspace)
|
if (cutbuffer != NULL)
|
||||||
do_statusbar_backspace();
|
paste_into_answer();
|
||||||
else if (shortcut->func == paste_text) {
|
|
||||||
if (cutbuffer != NULL)
|
|
||||||
paste_into_answer();
|
|
||||||
} else {
|
|
||||||
/* Handle any other shortcut in the current menu, setting finished
|
|
||||||
* to TRUE to indicate that we're done after running or trying to
|
|
||||||
* run its associated function. */
|
|
||||||
if (!ISSET(VIEW_MODE) || okay_for_view(shortcut))
|
|
||||||
shortcut->func();
|
|
||||||
*finished = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return input;
|
/* Don't handle any handled function again. */
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the column number of the first character of the answer that is
|
/* Return the column number of the first character of the answer that is
|
||||||
@ -392,33 +366,33 @@ void draw_the_promptbar(void)
|
|||||||
end_page = get_statusbar_page_start(base, base + breadth(answer) - 1);
|
end_page = get_statusbar_page_start(base, base + breadth(answer) - 1);
|
||||||
|
|
||||||
/* Color the prompt bar over its full width. */
|
/* Color the prompt bar over its full width. */
|
||||||
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
|
wattron(footwin, interface_color_pair[PROMPT_BAR]);
|
||||||
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
|
||||||
|
|
||||||
mvwaddstr(bottomwin, 0, 0, prompt);
|
mvwaddstr(footwin, 0, 0, prompt);
|
||||||
waddch(bottomwin, ':');
|
waddch(footwin, ':');
|
||||||
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
|
waddch(footwin, (the_page == 0) ? ' ' : '<');
|
||||||
|
|
||||||
expanded = display_string(answer, the_page, COLS - base, FALSE, TRUE);
|
expanded = display_string(answer, the_page, COLS - base, FALSE, TRUE);
|
||||||
waddstr(bottomwin, expanded);
|
waddstr(footwin, expanded);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
|
|
||||||
if (the_page < end_page && base + breadth(answer) - the_page > COLS)
|
if (the_page < end_page && base + breadth(answer) - the_page > COLS)
|
||||||
mvwaddch(bottomwin, 0, COLS - 1, '>');
|
mvwaddch(footwin, 0, COLS - 1, '>');
|
||||||
|
|
||||||
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
|
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
|
||||||
|
|
||||||
#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20210220)
|
#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20210220)
|
||||||
/* Work around a cursor-misplacement bug -- https://sv.gnu.org/bugs/?59808. */
|
/* Work around a cursor-misplacement bug -- https://sv.gnu.org/bugs/?59808. */
|
||||||
if (ISSET(NO_HELP)) {
|
if (ISSET(NO_HELP)) {
|
||||||
wmove(bottomwin, 0, 0);
|
wmove(footwin, 0, 0);
|
||||||
wrefresh(bottomwin);
|
wrefresh(footwin);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Place the cursor at the right spot. */
|
/* Place the cursor at the right spot. */
|
||||||
wmove(bottomwin, 0, column - the_page);
|
wmove(footwin, 0, column - the_page);
|
||||||
wnoutrefresh(bottomwin);
|
wnoutrefresh(footwin);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -442,9 +416,6 @@ void add_or_remove_pipe_symbol_from_answer(void)
|
|||||||
functionptrtype acquire_an_answer(int *actual, bool *listed,
|
functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||||
linestruct **history_list, void (*refresh_func)(void))
|
linestruct **history_list, void (*refresh_func)(void))
|
||||||
{
|
{
|
||||||
int kbinput = ERR;
|
|
||||||
bool finished;
|
|
||||||
functionptrtype func;
|
|
||||||
#ifdef ENABLE_HISTORIES
|
#ifdef ENABLE_HISTORIES
|
||||||
char *stored_string = NULL;
|
char *stored_string = NULL;
|
||||||
/* Whatever the answer was before the user foraged into history. */
|
/* Whatever the answer was before the user foraged into history. */
|
||||||
@ -454,7 +425,10 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
size_t fragment_length = 0;
|
size_t fragment_length = 0;
|
||||||
/* The length of the fragment that the user tries to tab complete. */
|
/* The length of the fragment that the user tries to tab complete. */
|
||||||
#endif
|
#endif
|
||||||
#endif /* ENABLE_HISTORIES */
|
#endif
|
||||||
|
const keystruct *shortcut;
|
||||||
|
functionptrtype function;
|
||||||
|
int input;
|
||||||
|
|
||||||
if (typing_x > strlen(answer))
|
if (typing_x > strlen(answer))
|
||||||
typing_x = strlen(answer);
|
typing_x = strlen(answer);
|
||||||
@ -462,27 +436,40 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
draw_the_promptbar();
|
draw_the_promptbar();
|
||||||
|
|
||||||
kbinput = do_statusbar_input(&finished);
|
/* Read in one keystroke. */
|
||||||
|
input = get_kbinput(footwin, VISIBLE);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* If the window size changed, go reformat the prompt string. */
|
/* If the window size changed, go reformat the prompt string. */
|
||||||
if (kbinput == KEY_WINCH) {
|
if (input == KEY_WINCH) {
|
||||||
refresh_func();
|
refresh_func(); /* Only needed when in file browser. */
|
||||||
*actual = KEY_WINCH;
|
*actual = KEY_WINCH;
|
||||||
#ifdef ENABLE_HISTORIES
|
#ifdef ENABLE_HISTORIES
|
||||||
free(stored_string);
|
free(stored_string);
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif /* !NANO_TINY */
|
#endif
|
||||||
|
#ifdef ENABLE_MOUSE
|
||||||
|
/* For a click on a shortcut, read in the resulting keycode. */
|
||||||
|
if (input == KEY_MOUSE && do_statusbar_mouse() == 1)
|
||||||
|
input = get_kbinput(footwin, BLIND);
|
||||||
|
if (input == KEY_MOUSE)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
func = func_from_key(&kbinput);
|
/* Check for a shortcut in the current list. */
|
||||||
|
shortcut = get_shortcut(input);
|
||||||
|
function = (shortcut ? shortcut->func : NULL);
|
||||||
|
|
||||||
if (func == do_cancel || func == do_enter)
|
/* When it's a normal character, add it to the answer. */
|
||||||
|
absorb_character(input, function);
|
||||||
|
|
||||||
|
if (function == do_cancel || function == do_enter)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef ENABLE_TABCOMP
|
#ifdef ENABLE_TABCOMP
|
||||||
if (func == do_tab) {
|
if (function == do_tab) {
|
||||||
#ifdef ENABLE_HISTORIES
|
#ifdef ENABLE_HISTORIES
|
||||||
if (history_list != NULL) {
|
if (history_list != NULL) {
|
||||||
if (!previous_was_tab)
|
if (!previous_was_tab)
|
||||||
@ -499,9 +486,9 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
if ((currmenu & (MINSERTFILE|MWRITEFILE|MGOTODIR)) && !ISSET(RESTRICTED))
|
if ((currmenu & (MINSERTFILE|MWRITEFILE|MGOTODIR)) && !ISSET(RESTRICTED))
|
||||||
answer = input_tab(answer, &typing_x, refresh_func, listed);
|
answer = input_tab(answer, &typing_x, refresh_func, listed);
|
||||||
} else
|
} else
|
||||||
#endif /* ENABLE_TABCOMP */
|
#endif
|
||||||
#ifdef ENABLE_HISTORIES
|
#ifdef ENABLE_HISTORIES
|
||||||
if (func == get_older_item && history_list != NULL) {
|
if (function == get_older_item && history_list != NULL) {
|
||||||
/* If this is the first step into history, start at the bottom. */
|
/* If this is the first step into history, start at the bottom. */
|
||||||
if (stored_string == NULL)
|
if (stored_string == NULL)
|
||||||
reset_history_pointer_for(*history_list);
|
reset_history_pointer_for(*history_list);
|
||||||
@ -516,7 +503,7 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
answer = mallocstrcpy(answer, (*history_list)->data);
|
answer = mallocstrcpy(answer, (*history_list)->data);
|
||||||
typing_x = strlen(answer);
|
typing_x = strlen(answer);
|
||||||
}
|
}
|
||||||
} else if (func == get_newer_item && history_list != NULL) {
|
} else if (function == get_newer_item && history_list != NULL) {
|
||||||
/* If there is a newer item, move to it and copy its string. */
|
/* If there is a newer item, move to it and copy its string. */
|
||||||
if ((*history_list)->next != NULL) {
|
if ((*history_list)->next != NULL) {
|
||||||
*history_list = (*history_list)->next;
|
*history_list = (*history_list)->next;
|
||||||
@ -531,29 +518,33 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif /* ENABLE_HISTORIES */
|
#endif /* ENABLE_HISTORIES */
|
||||||
/* If we ran a function that should not exit from the prompt... */
|
if (function == do_help || function == full_refresh)
|
||||||
if (func == do_help || func == full_refresh)
|
function();
|
||||||
finished = FALSE;
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
else if (func == do_nothing)
|
else if (function == do_toggle && shortcut->toggle == NO_HELP) {
|
||||||
finished = FALSE;
|
|
||||||
else if (func == do_toggle) {
|
|
||||||
TOGGLE(NO_HELP);
|
TOGGLE(NO_HELP);
|
||||||
window_init();
|
window_init();
|
||||||
focusing = FALSE;
|
focusing = FALSE;
|
||||||
refresh_func();
|
refresh_func();
|
||||||
bottombars(currmenu);
|
bottombars(currmenu);
|
||||||
finished = FALSE;
|
} else if (function == do_nothing)
|
||||||
}
|
;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_NANORC
|
||||||
/* If we have a shortcut with an associated function, break out if
|
else if (function == (functionptrtype)implant)
|
||||||
* we're finished after running or trying to run the function. */
|
implant(shortcut->expansion);
|
||||||
if (finished)
|
#endif
|
||||||
break;
|
else if (function && !handle_editing(function)) {
|
||||||
|
/* When it's a permissible shortcut, run it and done. */
|
||||||
|
if (!ISSET(VIEW_MODE) || !changes_something(function)) {
|
||||||
|
function();
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
beep();
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP)
|
#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP)
|
||||||
previous_was_tab = (func == do_tab);
|
previous_was_tab = (function == do_tab);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,9 +556,9 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*actual = kbinput;
|
*actual = input;
|
||||||
|
|
||||||
return func;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ask a question on the status bar. Return 0 when text was entered,
|
/* Ask a question on the status bar. Return 0 when text was entered,
|
||||||
@ -577,10 +568,10 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|||||||
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||||
void (*refresh_func)(void), const char *msg, ...)
|
void (*refresh_func)(void), const char *msg, ...)
|
||||||
{
|
{
|
||||||
|
functionptrtype function = NULL;
|
||||||
|
bool listed = FALSE;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int retval;
|
int retval;
|
||||||
functionptrtype func = NULL;
|
|
||||||
bool listed = FALSE;
|
|
||||||
/* Save a possible current status-bar x position and prompt. */
|
/* Save a possible current status-bar x position and prompt. */
|
||||||
size_t was_typing_x = typing_x;
|
size_t was_typing_x = typing_x;
|
||||||
char *saved_prompt = prompt;
|
char *saved_prompt = prompt;
|
||||||
@ -602,25 +593,23 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
|
|||||||
|
|
||||||
lastmessage = VACUUM;
|
lastmessage = VACUUM;
|
||||||
|
|
||||||
func = acquire_an_answer(&retval, &listed, history_list, refresh_func);
|
function = acquire_an_answer(&retval, &listed, history_list, refresh_func);
|
||||||
free(prompt);
|
free(prompt);
|
||||||
prompt = saved_prompt;
|
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (retval == KEY_WINCH)
|
if (retval == KEY_WINCH)
|
||||||
goto redo_theprompt;
|
goto redo_theprompt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we're done with this prompt, restore the x position to what
|
/* Restore a possible previous prompt and maybe the typing position. */
|
||||||
* it was at a possible previous prompt. */
|
prompt = saved_prompt;
|
||||||
if (func == do_cancel || func == do_enter)
|
if (function == do_cancel || function == do_enter)
|
||||||
typing_x = was_typing_x;
|
typing_x = was_typing_x;
|
||||||
|
|
||||||
/* If we left the prompt via Cancel or Enter, set the return value
|
/* Set the proper return value for Cancel and Enter. */
|
||||||
* properly. */
|
if (function == do_cancel)
|
||||||
if (func == do_cancel)
|
|
||||||
retval = -1;
|
retval = -1;
|
||||||
else if (func == do_enter)
|
else if (function == do_enter)
|
||||||
retval = (*answer == '\0') ? -2 : 0;
|
retval = (*answer == '\0') ? -2 : 0;
|
||||||
|
|
||||||
if (lastmessage == VACUUM)
|
if (lastmessage == VACUUM)
|
||||||
@ -635,20 +624,24 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
|
#define UNDECIDED -2
|
||||||
* on the status bar. Return 1 for Yes, 0 for No, 2 for All (if all is
|
|
||||||
* TRUE when passed in), and -1 for Cancel. */
|
/* Ask a simple Yes/No (and optionally All) question on the status bar
|
||||||
int do_yesno_prompt(bool all, const char *msg)
|
* and return the choice -- either YES or NO or ALL or CANCEL. */
|
||||||
|
int ask_user(bool withall, const char *question)
|
||||||
{
|
{
|
||||||
int choice = -2, width = 16;
|
int choice = UNDECIDED;
|
||||||
|
int width = 16;
|
||||||
/* TRANSLATORS: For the next three strings, specify the starting letters
|
/* TRANSLATORS: For the next three strings, specify the starting letters
|
||||||
* of the translations for "Yes"/"No"/"All". The first letter of each of
|
* of the translations for "Yes"/"No"/"All". The first letter of each of
|
||||||
* these strings MUST be a single-byte letter; others may be multi-byte. */
|
* these strings MUST be a single-byte letter; others may be multi-byte. */
|
||||||
const char *yesstr = _("Yy");
|
const char *yesstr = _("Yy");
|
||||||
const char *nostr = _("Nn");
|
const char *nostr = _("Nn");
|
||||||
const char *allstr = _("Aa");
|
const char *allstr = _("Aa");
|
||||||
|
const keystruct *shortcut;
|
||||||
|
functionptrtype function;
|
||||||
|
|
||||||
while (choice == -2) {
|
while (choice == UNDECIDED) {
|
||||||
#ifdef ENABLE_NLS
|
#ifdef ENABLE_NLS
|
||||||
char letter[MAXCHARLEN + 1];
|
char letter[MAXCHARLEN + 1];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@ -669,42 +662,44 @@ int do_yesno_prompt(bool all, const char *msg)
|
|||||||
|
|
||||||
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
|
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
|
||||||
sprintf(shortstr, " %c", yesstr[0]);
|
sprintf(shortstr, " %c", yesstr[0]);
|
||||||
wmove(bottomwin, 1, 0);
|
wmove(footwin, 1, 0);
|
||||||
post_one_key(shortstr, _("Yes"), width);
|
post_one_key(shortstr, _("Yes"), width);
|
||||||
|
|
||||||
shortstr[1] = nostr[0];
|
shortstr[1] = nostr[0];
|
||||||
wmove(bottomwin, 2, 0);
|
wmove(footwin, 2, 0);
|
||||||
post_one_key(shortstr, _("No"), width);
|
post_one_key(shortstr, _("No"), width);
|
||||||
|
|
||||||
if (all) {
|
if (withall) {
|
||||||
shortstr[1] = allstr[0];
|
shortstr[1] = allstr[0];
|
||||||
wmove(bottomwin, 1, width);
|
wmove(footwin, 1, width);
|
||||||
post_one_key(shortstr, _("All"), width);
|
post_one_key(shortstr, _("All"), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
wmove(bottomwin, 2, width);
|
wmove(footwin, 2, width);
|
||||||
post_one_key(cancelshortcut->keystr, _("Cancel"), width);
|
post_one_key(cancelshortcut->keystr, _("Cancel"), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Color the prompt bar over its full width and display the question. */
|
/* Color the prompt bar over its full width and display the question. */
|
||||||
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
|
wattron(footwin, interface_color_pair[PROMPT_BAR]);
|
||||||
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
|
||||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
mvwaddnstr(footwin, 0, 0, question, actual_x(question, COLS - 1));
|
||||||
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
|
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
|
||||||
wnoutrefresh(bottomwin);
|
wnoutrefresh(footwin);
|
||||||
|
|
||||||
currmenu = MYESNO;
|
currmenu = MYESNO;
|
||||||
|
|
||||||
/* When not replacing, show the cursor while waiting for a key. */
|
/* When not replacing, show the cursor while waiting for a key. */
|
||||||
kbinput = get_kbinput(bottomwin, !all);
|
kbinput = get_kbinput(footwin, !withall);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (kbinput == KEY_WINCH)
|
if (kbinput == KEY_WINCH)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Accept the first character of an external paste. */
|
/* Accept first character of an external paste and ignore the rest. */
|
||||||
if (bracketed_paste && kbinput == BRACKETED_PASTE_MARKER)
|
if (bracketed_paste)
|
||||||
kbinput = get_kbinput(bottomwin, BLIND);
|
kbinput = get_kbinput(footwin, BLIND);
|
||||||
|
while (bracketed_paste)
|
||||||
|
get_kbinput(footwin, BLIND);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_NLS
|
#ifdef ENABLE_NLS
|
||||||
@ -715,57 +710,40 @@ int do_yesno_prompt(bool all, const char *msg)
|
|||||||
if (using_utf8() && 0xC0 <= kbinput && kbinput <= 0xF7) {
|
if (using_utf8() && 0xC0 <= kbinput && kbinput <= 0xF7) {
|
||||||
int extras = (kbinput / 16) % 4 + (kbinput <= 0xCF ? 1 : 0);
|
int extras = (kbinput / 16) % 4 + (kbinput <= 0xCF ? 1 : 0);
|
||||||
|
|
||||||
while (extras <= get_key_buffer_len() && extras-- > 0)
|
while (extras <= waiting_keycodes() && extras-- > 0)
|
||||||
letter[index++] = (unsigned char)get_kbinput(bottomwin, !all);
|
letter[index++] = (unsigned char)get_kbinput(footwin, !withall);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
letter[index] = '\0';
|
letter[index] = '\0';
|
||||||
|
|
||||||
/* See if the typed letter is in the Yes, No, or All strings. */
|
/* See if the typed letter is in the Yes, No, or All strings. */
|
||||||
if (strstr(yesstr, letter) != NULL)
|
if (strstr(yesstr, letter) != NULL)
|
||||||
choice = 1;
|
choice = YES;
|
||||||
else if (strstr(nostr, letter) != NULL)
|
else if (strstr(nostr, letter) != NULL)
|
||||||
choice = 0;
|
choice = NO;
|
||||||
else if (all && strstr(allstr, letter) != NULL)
|
else if (withall && strstr(allstr, letter) != NULL)
|
||||||
choice = 2;
|
choice = ALL;
|
||||||
else
|
else
|
||||||
#endif /* ENABLE_NLS */
|
#endif /* ENABLE_NLS */
|
||||||
if (strchr("Yy", kbinput) != NULL)
|
if (strchr("Yy", kbinput) != NULL)
|
||||||
choice = 1;
|
choice = YES;
|
||||||
else if (strchr("Nn", kbinput) != NULL)
|
else if (strchr("Nn", kbinput) != NULL)
|
||||||
choice = 0;
|
choice = NO;
|
||||||
else if (all && strchr("Aa", kbinput) != NULL)
|
else if (withall && strchr("Aa", kbinput) != NULL)
|
||||||
choice = 2;
|
choice = ALL;
|
||||||
else if (func_from_key(&kbinput) == do_cancel)
|
|
||||||
choice = -1;
|
|
||||||
/* Interpret ^N and ^Q as "No", to allow exiting in anger. */
|
|
||||||
else if (kbinput == '\x0E' || kbinput == '\x11')
|
|
||||||
choice = 0;
|
|
||||||
/* And interpret ^Y as "Yes". */
|
|
||||||
else if (kbinput == '\x19')
|
|
||||||
choice = 1;
|
|
||||||
#ifdef ENABLE_MOUSE
|
|
||||||
else if (kbinput == KEY_MOUSE) {
|
|
||||||
int mouse_x, mouse_y;
|
|
||||||
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
|
||||||
if (get_mouseinput(&mouse_y, &mouse_x, FALSE) == 0 &&
|
|
||||||
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
|
||||||
mouse_x < (width * 2) && mouse_y > 0) {
|
|
||||||
int x = mouse_x / width;
|
|
||||||
int y = mouse_y - 1;
|
|
||||||
|
|
||||||
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
if (choice != UNDECIDED)
|
||||||
choice = -2 * x * y + x - y + 1;
|
break;
|
||||||
|
|
||||||
if (choice == 2 && !all)
|
shortcut = get_shortcut(kbinput);
|
||||||
choice = -2;
|
function = (shortcut ? shortcut->func : NULL);
|
||||||
}
|
|
||||||
}
|
if (function == do_cancel)
|
||||||
#endif
|
choice = CANCEL;
|
||||||
else if (func_from_key(&kbinput) == full_refresh)
|
else if (function == full_refresh)
|
||||||
full_refresh();
|
full_refresh();
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
else if (func_from_key(&kbinput) == do_toggle) {
|
else if (function == do_toggle && shortcut->toggle == NO_HELP) {
|
||||||
TOGGLE(NO_HELP);
|
TOGGLE(NO_HELP);
|
||||||
window_init();
|
window_init();
|
||||||
titlebar(NULL);
|
titlebar(NULL);
|
||||||
@ -773,15 +751,33 @@ int do_yesno_prompt(bool all, const char *msg)
|
|||||||
edit_refresh();
|
edit_refresh();
|
||||||
focusing = TRUE;
|
focusing = TRUE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
/* Interpret ^N and ^Q as "No", to allow exiting in anger. */
|
||||||
|
else if (kbinput == '\x0E' || kbinput == '\x11')
|
||||||
|
choice = NO;
|
||||||
|
/* And interpret ^Y as "Yes". */
|
||||||
|
else if (kbinput == '\x19')
|
||||||
|
choice = YES;
|
||||||
|
#ifdef ENABLE_MOUSE
|
||||||
|
else if (kbinput == KEY_MOUSE) {
|
||||||
|
int mouse_x, mouse_y;
|
||||||
|
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
||||||
|
if (get_mouseinput(&mouse_y, &mouse_x, FALSE) == 0 &&
|
||||||
|
wmouse_trafo(footwin, &mouse_y, &mouse_x, FALSE) &&
|
||||||
|
mouse_x < (width * 2) && mouse_y > 0) {
|
||||||
|
int x = mouse_x / width;
|
||||||
|
int y = mouse_y - 1;
|
||||||
|
|
||||||
|
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
||||||
|
choice = -2 * x * y + x - y + 1;
|
||||||
|
|
||||||
|
if (choice == ALL && !withall)
|
||||||
|
choice = UNDECIDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
beep();
|
beep();
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
|
||||||
/* Ignore the rest of an external paste. */
|
|
||||||
while (bracketed_paste)
|
|
||||||
kbinput = get_kbinput(bottomwin, BLIND);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* prototypes.h -- This file is part of GNU nano. *
|
* prototypes.h -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -80,6 +80,7 @@ extern int altinsert, altdelete;
|
|||||||
extern int shiftaltleft, shiftaltright;
|
extern int shiftaltleft, shiftaltright;
|
||||||
extern int shiftaltup, shiftaltdown;
|
extern int shiftaltup, shiftaltdown;
|
||||||
#endif
|
#endif
|
||||||
|
extern int mousefocusin, mousefocusout;
|
||||||
|
|
||||||
#ifdef ENABLED_WRAPORJUSTIFY
|
#ifdef ENABLED_WRAPORJUSTIFY
|
||||||
extern ssize_t fill;
|
extern ssize_t fill;
|
||||||
@ -87,8 +88,8 @@ extern size_t wrap_at;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern WINDOW *topwin;
|
extern WINDOW *topwin;
|
||||||
extern WINDOW *edit;
|
extern WINDOW *midwin;
|
||||||
extern WINDOW *bottomwin;
|
extern WINDOW *footwin;
|
||||||
extern int editwinrows;
|
extern int editwinrows;
|
||||||
extern int editwincols;
|
extern int editwincols;
|
||||||
extern int margin;
|
extern int margin;
|
||||||
@ -141,6 +142,9 @@ extern char *alt_speller;
|
|||||||
extern syntaxtype *syntaxes;
|
extern syntaxtype *syntaxes;
|
||||||
extern char *syntaxstr;
|
extern char *syntaxstr;
|
||||||
extern bool have_palette;
|
extern bool have_palette;
|
||||||
|
extern bool rescind_colors;
|
||||||
|
extern bool perturbed;
|
||||||
|
extern bool recook;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool refresh_needed;
|
extern bool refresh_needed;
|
||||||
@ -178,6 +182,9 @@ extern char *startup_problem;
|
|||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
extern char *custom_nanorc;
|
extern char *custom_nanorc;
|
||||||
|
|
||||||
|
extern char *commandname;
|
||||||
|
extern keystruct *planted_shortcut;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool spotlighted;
|
extern bool spotlighted;
|
||||||
@ -313,12 +320,12 @@ char *input_tab(char *buf, size_t *place, void (*refresh_func)(void), bool *list
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some functions in global.c. */
|
/* Some functions in global.c. */
|
||||||
const keystruct *first_sc_for(int menu, void (*func)(void));
|
const keystruct *first_sc_for(int menu, void (*function)(void));
|
||||||
size_t shown_entries_for(int menu);
|
size_t shown_entries_for(int menu);
|
||||||
const keystruct *get_shortcut(int *keycode);
|
const keystruct *get_shortcut(const int keycode);
|
||||||
functionptrtype func_from_key(int *keycode);
|
functionptrtype func_from_key(const int keycode);
|
||||||
#if defined(ENABLE_BROWSER) || defined(ENABLE_HELP)
|
#if defined(ENABLE_BROWSER) || defined(ENABLE_HELP)
|
||||||
functionptrtype interpret(int *keycode);
|
functionptrtype interpret(const int keycode);
|
||||||
#endif
|
#endif
|
||||||
int keycode_from_string(const char *keystring);
|
int keycode_from_string(const char *keystring);
|
||||||
void shortcut_init(void);
|
void shortcut_init(void);
|
||||||
@ -359,8 +366,8 @@ void to_para_end(void);
|
|||||||
#endif
|
#endif
|
||||||
void to_prev_block(void);
|
void to_prev_block(void);
|
||||||
void to_next_block(void);
|
void to_next_block(void);
|
||||||
void do_prev_word(void);
|
void do_prev_word(bool allow_folded);
|
||||||
bool do_next_word(bool after_ends);
|
bool do_next_word(bool after_ends, bool allow_folded);
|
||||||
void to_prev_word(void);
|
void to_prev_word(void);
|
||||||
void to_next_word(void);
|
void to_next_word(void);
|
||||||
void do_home(void);
|
void do_home(void);
|
||||||
@ -374,6 +381,7 @@ void do_center(void);
|
|||||||
#endif
|
#endif
|
||||||
void do_left(void);
|
void do_left(void);
|
||||||
void do_right(void);
|
void do_right(void);
|
||||||
|
void move_cursor_to_proper_column(void);
|
||||||
|
|
||||||
/* Most functions in nano.c. */
|
/* Most functions in nano.c. */
|
||||||
linestruct *make_new_node(linestruct *prevnode);
|
linestruct *make_new_node(linestruct *prevnode);
|
||||||
@ -421,7 +429,7 @@ void terminal_init(void);
|
|||||||
void confirm_margin(void);
|
void confirm_margin(void);
|
||||||
#endif
|
#endif
|
||||||
void unbound_key(int code);
|
void unbound_key(int code);
|
||||||
bool okay_for_view(const keystruct *shortcut);
|
bool changes_something(functionptrtype f);
|
||||||
void inject(char *burst, size_t count);
|
void inject(char *burst, size_t count);
|
||||||
|
|
||||||
/* Most functions in prompt.c. */
|
/* Most functions in prompt.c. */
|
||||||
@ -430,7 +438,7 @@ void put_cursor_at_end_of_answer(void);
|
|||||||
void add_or_remove_pipe_symbol_from_answer(void);
|
void add_or_remove_pipe_symbol_from_answer(void);
|
||||||
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||||
void (*refresh_func)(void), const char *msg, ...);
|
void (*refresh_func)(void), const char *msg, ...);
|
||||||
int do_yesno_prompt(bool all, const char *msg);
|
int ask_user(bool withall, const char *question);
|
||||||
|
|
||||||
/* Most functions in rcfile.c. */
|
/* Most functions in rcfile.c. */
|
||||||
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
||||||
@ -438,6 +446,7 @@ void display_rcfile_errors(void);
|
|||||||
void jot_error(const char *msg, ...);
|
void jot_error(const char *msg, ...);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
|
keystruct *strtosc(const char *input);
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
void parse_one_include(char *file, syntaxtype *syntax);
|
void parse_one_include(char *file, syntaxtype *syntax);
|
||||||
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
|
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
|
||||||
@ -462,11 +471,16 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
|||||||
const linestruct *real_current, size_t *real_current_x);
|
const linestruct *real_current, size_t *real_current_x);
|
||||||
void do_replace(void);
|
void do_replace(void);
|
||||||
void ask_for_and_do_replacements(void);
|
void ask_for_and_do_replacements(void);
|
||||||
|
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||||
void goto_line_posx(ssize_t line, size_t pos_x);
|
void goto_line_posx(ssize_t line, size_t pos_x);
|
||||||
|
#endif
|
||||||
void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
||||||
bool interactive);
|
bool interactive);
|
||||||
void do_gotolinecolumn(void);
|
void do_gotolinecolumn(void);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
|
int find_matching_bracket_pos(linestruct **line, size_t *xpos);
|
||||||
|
bool find_bracketed_region(linestruct *in_region,
|
||||||
|
linestruct **top, linestruct **bot);
|
||||||
void do_find_bracket(void);
|
void do_find_bracket(void);
|
||||||
void put_or_lift_anchor(void);
|
void put_or_lift_anchor(void);
|
||||||
void to_prev_anchor(void);
|
void to_prev_anchor(void);
|
||||||
@ -513,15 +527,19 @@ void do_full_justify(void);
|
|||||||
#ifdef ENABLE_SPELLER
|
#ifdef ENABLE_SPELLER
|
||||||
void do_spell(void);
|
void do_spell(void);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
void do_linter(void);
|
void do_linter(void);
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
void do_formatter(void);
|
void do_formatter(void);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
void count_lines_words_and_characters(void);
|
void count_lines_words_and_characters(void);
|
||||||
#endif
|
#endif
|
||||||
void do_verbatim_input(void);
|
void do_verbatim_input(void);
|
||||||
|
#ifdef ENABLE_WORDCOMPLETION
|
||||||
void complete_a_word(void);
|
void complete_a_word(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* All functions in utils.c. */
|
/* All functions in utils.c. */
|
||||||
void get_homedir(void);
|
void get_homedir(void);
|
||||||
@ -531,7 +549,7 @@ int digits(ssize_t n);
|
|||||||
bool parse_num(const char *str, ssize_t *result);
|
bool parse_num(const char *str, ssize_t *result);
|
||||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column);
|
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column);
|
||||||
void recode_NUL_to_LF(char *string, size_t length);
|
void recode_NUL_to_LF(char *string, size_t length);
|
||||||
void recode_LF_to_NUL(char *string);
|
size_t recode_LF_to_NUL(char *string);
|
||||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||||
void free_chararray(char **array, size_t len);
|
void free_chararray(char **array, size_t len);
|
||||||
#endif
|
#endif
|
||||||
@ -561,18 +579,23 @@ void get_region(linestruct **top, size_t *top_x, linestruct **bot, size_t *bot_x
|
|||||||
void get_range(linestruct **top, linestruct **bot);
|
void get_range(linestruct **top, linestruct **bot);
|
||||||
#endif
|
#endif
|
||||||
size_t number_of_characters_in(const linestruct *begin, const linestruct *end);
|
size_t number_of_characters_in(const linestruct *begin, const linestruct *end);
|
||||||
#ifndef NANO_TINY
|
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||||
linestruct *line_from_number(ssize_t number);
|
linestruct *line_from_number(ssize_t number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Most functions in winio.c. */
|
/* Most functions in winio.c. */
|
||||||
|
linestruct *get_next_visible_line(linestruct *line);
|
||||||
|
linestruct *get_prev_visible_line(linestruct *line);
|
||||||
|
#ifndef NANO_TINY
|
||||||
void record_macro(void);
|
void record_macro(void);
|
||||||
void run_macro(void);
|
void run_macro(void);
|
||||||
size_t get_key_buffer_len(void);
|
#endif
|
||||||
|
void reserve_space_for(size_t newsize);
|
||||||
|
size_t waiting_keycodes(void);
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
void implant(const char *string);
|
void implant(const char *string);
|
||||||
#endif
|
#endif
|
||||||
int parse_kbinput(WINDOW *win);
|
int get_input(WINDOW *win);
|
||||||
int get_kbinput(WINDOW *win, bool showcursor);
|
int get_kbinput(WINDOW *win, bool showcursor);
|
||||||
char *get_verbatim_kbinput(WINDOW *win, size_t *count);
|
char *get_verbatim_kbinput(WINDOW *win, size_t *count);
|
||||||
#ifdef ENABLE_MOUSE
|
#ifdef ENABLE_MOUSE
|
||||||
@ -594,6 +617,7 @@ void warn_and_briefly_pause(const char *msg);
|
|||||||
void bottombars(int menu);
|
void bottombars(int menu);
|
||||||
void post_one_key(const char *keystroke, const char *tag, int width);
|
void post_one_key(const char *keystroke, const char *tag, int width);
|
||||||
void place_the_cursor(void);
|
void place_the_cursor(void);
|
||||||
|
int update_line_at(linestruct *line, size_t index, int row);
|
||||||
int update_line(linestruct *line, size_t index);
|
int update_line(linestruct *line, size_t index);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
int update_softwrapped_line(linestruct *line);
|
int update_softwrapped_line(linestruct *line);
|
||||||
@ -604,8 +628,8 @@ int go_forward_chunks(int nrows, linestruct **line, size_t *leftedge);
|
|||||||
bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
|
bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
|
||||||
void edit_scroll(bool direction);
|
void edit_scroll(bool direction);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
|
size_t get_softwrap_breakpoint(const char *linedata, size_t leftedge,
|
||||||
bool *end_of_line);
|
bool *kickoff, bool *end_of_line);
|
||||||
size_t get_chunk_and_edge(size_t column, linestruct *line, size_t *leftedge);
|
size_t get_chunk_and_edge(size_t column, linestruct *line, size_t *leftedge);
|
||||||
size_t chunk_for(size_t column, linestruct *line);
|
size_t chunk_for(size_t column, linestruct *line);
|
||||||
size_t leftedge_for(size_t column, linestruct *line);
|
size_t leftedge_for(size_t column, linestruct *line);
|
||||||
@ -658,3 +682,13 @@ void flip_newbuffer(void);
|
|||||||
#endif
|
#endif
|
||||||
void discard_buffer(void);
|
void discard_buffer(void);
|
||||||
void do_cancel(void);
|
void do_cancel(void);
|
||||||
|
|
||||||
|
/* Most functions in folding.c. */
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
void do_fold_segment(void);
|
||||||
|
void unfold_folded_segment(linestruct *line);
|
||||||
|
void unfold_folded_segment_from(linestruct *line);
|
||||||
|
linestruct *get_start_of_folded_segment(linestruct* line);
|
||||||
|
linestruct *get_end_of_folded_segment(linestruct* line);
|
||||||
|
int get_folded_segment_length(linestruct *line);
|
||||||
|
#endif
|
||||||
|
|||||||
86
src/rcfile.c
86
src/rcfile.c
@ -1,10 +1,10 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* rcfile.c -- This file is part of GNU nano. *
|
* rcfile.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 2001-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014 Mike Frysinger *
|
* Copyright (C) 2014 Mike Frysinger *
|
||||||
* Copyright (C) 2019 Brand Huntsman *
|
* Copyright (C) 2019 Brand Huntsman *
|
||||||
* Copyright (C) 2014-2020 Benno Schulenberg *
|
* Copyright (C) 2014-2021 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -90,9 +90,6 @@ static const rcoption rcopts[] = {
|
|||||||
#ifdef ENABLE_SPELLER
|
#ifdef ENABLE_SPELLER
|
||||||
{"speller", 0},
|
{"speller", 0},
|
||||||
#endif
|
#endif
|
||||||
{"suspend", SUSPENDABLE}, /* Deprecated; remove in 2022. */
|
|
||||||
{"suspendable", SUSPENDABLE}, /* Obsolete; remove in 2022. */
|
|
||||||
{"tempfile", SAVE_ON_EXIT}, /* Deprecated; remove in 2022. */
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
{"afterends", AFTER_ENDS},
|
{"afterends", AFTER_ENDS},
|
||||||
{"allow_insecure_backup", INSECURE_BACKUP},
|
{"allow_insecure_backup", INSECURE_BACKUP},
|
||||||
@ -156,18 +153,6 @@ static bool seen_color_command = FALSE;
|
|||||||
static colortype *lastcolor = NULL;
|
static colortype *lastcolor = NULL;
|
||||||
/* The end of the color list for the current syntax. */
|
/* The end of the color list for the current syntax. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NUMBER_OF_MENUS 17 /* Remove the deprecated 'extcmd' in 2022. */
|
|
||||||
char *menunames[NUMBER_OF_MENUS] = { "main", "search", "replace", "replacewith",
|
|
||||||
"yesno", "gotoline", "writeout", "insert",
|
|
||||||
"execute", "extcmd", "help", "spell", "linter",
|
|
||||||
"browser", "whereisfile", "gotodir",
|
|
||||||
"all" };
|
|
||||||
int menusymbols[NUMBER_OF_MENUS] = { MMAIN, MWHEREIS, MREPLACE, MREPLACEWITH,
|
|
||||||
MYESNO, MGOTOLINE, MWRITEFILE, MINSERTFILE,
|
|
||||||
MEXECUTE, MEXECUTE, MHELP, MSPELL, MLINTER,
|
|
||||||
MBROWSER, MWHEREISFILE, MGOTODIR,
|
|
||||||
MMOST|MBROWSER|MHELP|MYESNO };
|
|
||||||
#endif /* ENABLE_NANORC */
|
#endif /* ENABLE_NANORC */
|
||||||
|
|
||||||
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
||||||
@ -279,14 +264,15 @@ keystruct *strtosc(const char *input)
|
|||||||
!strcmp(input, "speller"))
|
!strcmp(input, "speller"))
|
||||||
s->func = do_spell;
|
s->func = do_spell;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
else if (!strcmp(input, "linter"))
|
else if (!strcmp(input, "linter"))
|
||||||
s->func = do_linter;
|
s->func = do_linter;
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
else if (!strcmp(input, "formatter"))
|
else if (!strcmp(input, "formatter"))
|
||||||
s->func = do_formatter;
|
s->func = do_formatter;
|
||||||
#endif
|
#endif
|
||||||
else if (!strcmp(input, "location") ||
|
else if (!strcmp(input, "location"))
|
||||||
!strcmp(input, "curpos")) /* Deprecated; remove in 2022. */
|
|
||||||
s->func = report_cursor_position;
|
s->func = report_cursor_position;
|
||||||
else if (!strcmp(input, "gotoline"))
|
else if (!strcmp(input, "gotoline"))
|
||||||
s->func = do_gotolinecolumn;
|
s->func = do_gotolinecolumn;
|
||||||
@ -497,6 +483,18 @@ keystruct *strtosc(const char *input)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NUMBER_OF_MENUS 16
|
||||||
|
char *menunames[NUMBER_OF_MENUS] = { "main", "search", "replace", "replacewith",
|
||||||
|
"yesno", "gotoline", "writeout", "insert",
|
||||||
|
"execute", "help", "spell", "linter",
|
||||||
|
"browser", "whereisfile", "gotodir",
|
||||||
|
"all" };
|
||||||
|
int menusymbols[NUMBER_OF_MENUS] = { MMAIN, MWHEREIS, MREPLACE, MREPLACEWITH,
|
||||||
|
MYESNO, MGOTOLINE, MWRITEFILE, MINSERTFILE,
|
||||||
|
MEXECUTE, MHELP, MSPELL, MLINTER,
|
||||||
|
MBROWSER, MWHEREISFILE, MGOTODIR,
|
||||||
|
MMOST|MBROWSER|MHELP|MYESNO };
|
||||||
|
|
||||||
/* Return the symbol that corresponds to the given menu name. */
|
/* Return the symbol that corresponds to the given menu name. */
|
||||||
int name_to_menu(const char *name)
|
int name_to_menu(const char *name)
|
||||||
{
|
{
|
||||||
@ -506,7 +504,7 @@ int name_to_menu(const char *name)
|
|||||||
if (strcmp(name, menunames[index]) == 0)
|
if (strcmp(name, menunames[index]) == 0)
|
||||||
return menusymbols[index];
|
return menusymbols[index];
|
||||||
|
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the name that corresponds to the given menu symbol. */
|
/* Return the name that corresponds to the given menu symbol. */
|
||||||
@ -676,7 +674,7 @@ void begin_new_syntax(char *ptr)
|
|||||||
live_syntax->magics = NULL;
|
live_syntax->magics = NULL;
|
||||||
live_syntax->linter = NULL;
|
live_syntax->linter = NULL;
|
||||||
live_syntax->formatter = NULL;
|
live_syntax->formatter = NULL;
|
||||||
live_syntax->tab = NULL;
|
live_syntax->tabstring = NULL;
|
||||||
#ifdef ENABLE_COMMENT
|
#ifdef ENABLE_COMMENT
|
||||||
live_syntax->comment = copy_of(GENERAL_COMMENT_CHARACTER);
|
live_syntax->comment = copy_of(GENERAL_COMMENT_CHARACTER);
|
||||||
#endif
|
#endif
|
||||||
@ -789,6 +787,12 @@ void parse_binding(char *ptr, bool dobind)
|
|||||||
goto free_things;
|
goto free_things;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menu = name_to_menu(menuptr);
|
||||||
|
if (menu == 0) {
|
||||||
|
jot_error(N_("Unknown menu: %s"), menuptr);
|
||||||
|
goto free_things;
|
||||||
|
}
|
||||||
|
|
||||||
if (dobind) {
|
if (dobind) {
|
||||||
/* If the thing to bind starts with a double quote, it is a string,
|
/* If the thing to bind starts with a double quote, it is a string,
|
||||||
* otherwise it is the name of a function. */
|
* otherwise it is the name of a function. */
|
||||||
@ -803,17 +807,11 @@ void parse_binding(char *ptr, bool dobind)
|
|||||||
newsc = strtosc(funcptr);
|
newsc = strtosc(funcptr);
|
||||||
|
|
||||||
if (newsc == NULL) {
|
if (newsc == NULL) {
|
||||||
jot_error(N_("Cannot map name \"%s\" to a function"), funcptr);
|
jot_error(N_("Unknown function: %s"), funcptr);
|
||||||
goto free_things;
|
goto free_things;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu = name_to_menu(menuptr);
|
|
||||||
if (menu < 1) {
|
|
||||||
jot_error(N_("Cannot map name \"%s\" to a menu"), menuptr);
|
|
||||||
goto free_things;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wipe the given shortcut from the given menu. */
|
/* Wipe the given shortcut from the given menu. */
|
||||||
for (keystruct *s = sclist; s != NULL; s = s->next)
|
for (keystruct *s = sclist; s != NULL; s = s->next)
|
||||||
if ((s->menus & menu) && s->keycode == keycode)
|
if ((s->menus & menu) && s->keycode == keycode)
|
||||||
@ -901,7 +899,7 @@ bool is_good_file(char *file)
|
|||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
/* Partially parse the syntaxes in the given file, or (when syntax
|
/* Partially parse the syntaxes in the given file, or (when syntax
|
||||||
* is not NULL) fully parse one specific syntax from the file . */
|
* is not NULL) fully parse one specific syntax from the file. */
|
||||||
void parse_one_include(char *file, syntaxtype *syntax)
|
void parse_one_include(char *file, syntaxtype *syntax)
|
||||||
{
|
{
|
||||||
char *was_nanorc = nanorc;
|
char *was_nanorc = nanorc;
|
||||||
@ -910,7 +908,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
|
|||||||
FILE *rcstream;
|
FILE *rcstream;
|
||||||
|
|
||||||
/* Don't open directories, character files, or block files. */
|
/* Don't open directories, character files, or block files. */
|
||||||
if (!is_good_file(file))
|
if (access(file, R_OK) == 0 && !is_good_file(file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rcstream = fopen(file, "rb");
|
rcstream = fopen(file, "rb");
|
||||||
@ -978,7 +976,7 @@ void parse_includes(char *ptr)
|
|||||||
|
|
||||||
/* Expand a tilde first, then try to match the globbing pattern. */
|
/* Expand a tilde first, then try to match the globbing pattern. */
|
||||||
expanded = real_dir_from_tilde(pattern);
|
expanded = real_dir_from_tilde(pattern);
|
||||||
result = glob(expanded, GLOB_ERR, NULL, &files);
|
result = glob(expanded, GLOB_ERR|GLOB_NOCHECK, NULL, &files);
|
||||||
|
|
||||||
/* If there are matches, process each of them. Otherwise, only
|
/* If there are matches, process each of them. Otherwise, only
|
||||||
* report an error if it's something other than zero matches. */
|
* report an error if it's something other than zero matches. */
|
||||||
@ -993,16 +991,22 @@ void parse_includes(char *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the index of the color that is closest to the given RGB levels,
|
/* Return the index of the color that is closest to the given RGB levels,
|
||||||
* assuming that the terminal uses the 6x6x6 color cube of xterm-256color. */
|
* assuming that the terminal uses the 6x6x6 color cube of xterm-256color.
|
||||||
|
* When red == green == blue, return an index in the xterm gray scale. */
|
||||||
short closest_index_color(short red, short green, short blue)
|
short closest_index_color(short red, short green, short blue)
|
||||||
{
|
{
|
||||||
/* Translation table, from 16 intended levels to 6 available levels. */
|
/* Translation table, from 16 intended color levels to 6 available levels. */
|
||||||
static const short level[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
|
static const short level[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
|
||||||
|
|
||||||
if (COLORS == 256)
|
/* Translation table, from 14 intended gray levels to 24 available levels. */
|
||||||
return (36 * level[red] + 6 * level[green] + level[blue] + 16);
|
static const short gray[] = { 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 18, 21, 23 };
|
||||||
else
|
|
||||||
|
if (COLORS != 256)
|
||||||
return THE_DEFAULT;
|
return THE_DEFAULT;
|
||||||
|
else if (red == green && green == blue && 0 < red && red < 0xF)
|
||||||
|
return 232 + gray[red - 1];
|
||||||
|
else
|
||||||
|
return (36 * level[red] + 6 * level[green] + level[blue] + 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COLORCOUNT 34
|
#define COLORCOUNT 34
|
||||||
@ -1327,7 +1331,7 @@ bool parse_syntax_commands(char *keyword, char *ptr)
|
|||||||
pick_up_name("comment", ptr, &live_syntax->comment);
|
pick_up_name("comment", ptr, &live_syntax->comment);
|
||||||
#endif
|
#endif
|
||||||
} else if (strcmp(keyword, "tabgives") == 0) {
|
} else if (strcmp(keyword, "tabgives") == 0) {
|
||||||
pick_up_name("tabgives", ptr, &live_syntax->tab);
|
pick_up_name("tabgives", ptr, &live_syntax->tabstring);
|
||||||
} else if (strcmp(keyword, "linter") == 0)
|
} else if (strcmp(keyword, "linter") == 0)
|
||||||
pick_up_name("linter", ptr, &live_syntax->linter);
|
pick_up_name("linter", ptr, &live_syntax->linter);
|
||||||
else if (strcmp(keyword, "formatter") == 0)
|
else if (strcmp(keyword, "formatter") == 0)
|
||||||
@ -1352,7 +1356,7 @@ static void check_vitals_mapped(void)
|
|||||||
if (f->func == vitals[v] && f->menus & inmenus[v]) {
|
if (f->func == vitals[v] && f->menus & inmenus[v]) {
|
||||||
if (first_sc_for(inmenus[v], f->func) == NULL) {
|
if (first_sc_for(inmenus[v], f->func) == NULL) {
|
||||||
jot_error(N_("No key is bound to function '%s' in menu '%s'. "
|
jot_error(N_("No key is bound to function '%s' in menu '%s'. "
|
||||||
" Exiting.\n"), f->desc, menu_to_name(inmenus[v]));
|
" Exiting.\n"), f->tag, menu_to_name(inmenus[v]));
|
||||||
die(_("If needed, use nano with the -I option "
|
die(_("If needed, use nano with the -I option "
|
||||||
"to adjust your nanorc settings.\n"));
|
"to adjust your nanorc settings.\n"));
|
||||||
} else
|
} else
|
||||||
@ -1534,7 +1538,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rcopts[i].name == NULL) {
|
if (rcopts[i].name == NULL) {
|
||||||
jot_error(N_("Unknown option \"%s\""), option);
|
jot_error(N_("Unknown option: %s"), option);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1709,7 +1713,7 @@ void do_rcfiles(void)
|
|||||||
{
|
{
|
||||||
if (custom_nanorc) {
|
if (custom_nanorc) {
|
||||||
nanorc = get_full_path(custom_nanorc);
|
nanorc = get_full_path(custom_nanorc);
|
||||||
if (access(nanorc, F_OK) != 0)
|
if (nanorc == NULL || access(nanorc, F_OK) != 0)
|
||||||
die(_("Specified rcfile does not exist\n"));
|
die(_("Specified rcfile does not exist\n"));
|
||||||
} else
|
} else
|
||||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||||
|
|||||||
344
src/search.c
344
src/search.c
@ -1,8 +1,8 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* search.c -- This file is part of GNU nano. *
|
* search.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2015-2020 Benno Schulenberg *
|
* Copyright (C) 2015-2020, 2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -65,6 +65,9 @@ void tidy_up_after_search(void)
|
|||||||
if (openfile->mark)
|
if (openfile->mark)
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare the prompt and ask the user what to search for. Keep looping
|
/* Prepare the prompt and ask the user what to search for. Keep looping
|
||||||
@ -88,7 +91,7 @@ void search_init(bool replacing, bool retain_answer)
|
|||||||
thedefault = copy_of("");
|
thedefault = copy_of("");
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
functionptrtype func;
|
functionptrtype function;
|
||||||
/* Ask the user what to search for (or replace). */
|
/* Ask the user what to search for (or replace). */
|
||||||
int response = do_prompt(
|
int response = do_prompt(
|
||||||
inhelp ? MFINDINHELP : (replacing ? MREPLACE : MWHEREIS),
|
inhelp ? MFINDINHELP : (replacing ? MREPLACE : MWHEREIS),
|
||||||
@ -135,23 +138,23 @@ void search_init(bool replacing, bool retain_answer)
|
|||||||
|
|
||||||
retain_answer = TRUE;
|
retain_answer = TRUE;
|
||||||
|
|
||||||
func = func_from_key(&response);
|
function = func_from_key(response);
|
||||||
|
|
||||||
/* If we're here, one of the five toggles was pressed, or
|
/* If we're here, one of the five toggles was pressed, or
|
||||||
* a shortcut was executed. */
|
* a shortcut was executed. */
|
||||||
if (func == case_sens_void)
|
if (function == case_sens_void)
|
||||||
TOGGLE(CASE_SENSITIVE);
|
TOGGLE(CASE_SENSITIVE);
|
||||||
else if (func == backwards_void)
|
else if (function == backwards_void)
|
||||||
TOGGLE(BACKWARDS_SEARCH);
|
TOGGLE(BACKWARDS_SEARCH);
|
||||||
else if (func == regexp_void)
|
else if (function == regexp_void)
|
||||||
TOGGLE(USE_REGEXP);
|
TOGGLE(USE_REGEXP);
|
||||||
else if (func == flip_replace) {
|
else if (function == flip_replace) {
|
||||||
if (ISSET(VIEW_MODE)) {
|
if (ISSET(VIEW_MODE)) {
|
||||||
print_view_warning();
|
print_view_warning();
|
||||||
napms(600);
|
napms(600);
|
||||||
} else
|
} else
|
||||||
replacing = !replacing;
|
replacing = !replacing;
|
||||||
} else if (func == flip_goto) {
|
} else if (function == flip_goto) {
|
||||||
goto_line_and_column(openfile->current->lineno,
|
goto_line_and_column(openfile->current->lineno,
|
||||||
openfile->placewewant + 1, TRUE, TRUE);
|
openfile->placewewant + 1, TRUE, TRUE);
|
||||||
break;
|
break;
|
||||||
@ -186,7 +189,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
/* The time we last looked at the keyboard. */
|
/* The time we last looked at the keyboard. */
|
||||||
|
|
||||||
/* Set non-blocking input so that we can just peek for a Cancel. */
|
/* Set non-blocking input so that we can just peek for a Cancel. */
|
||||||
nodelay(edit, TRUE);
|
nodelay(midwin, TRUE);
|
||||||
|
|
||||||
if (begin == NULL)
|
if (begin == NULL)
|
||||||
came_full_circle = FALSE;
|
came_full_circle = FALSE;
|
||||||
@ -219,21 +222,22 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* The match is valid. */
|
/* When not on the magic line, the match is valid. */
|
||||||
break;
|
if (line->next || line->data[0])
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (the_window_resized) {
|
if (the_window_resized) {
|
||||||
regenerate_screen();
|
regenerate_screen();
|
||||||
nodelay(edit, TRUE);
|
nodelay(midwin, TRUE);
|
||||||
statusbar(_("Searching..."));
|
statusbar(_("Searching..."));
|
||||||
feedback = 1;
|
feedback = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* If we're back at the beginning, then there is no needle. */
|
/* If we're back at the beginning, then there is no needle. */
|
||||||
if (came_full_circle) {
|
if (came_full_circle) {
|
||||||
nodelay(edit, FALSE);
|
nodelay(midwin, FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +248,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
* but stop when spell-checking or replacing in a region. */
|
* but stop when spell-checking or replacing in a region. */
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
if (whole_word_only || modus == INREGION) {
|
if (whole_word_only || modus == INREGION) {
|
||||||
nodelay(edit, FALSE);
|
nodelay(midwin, FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +272,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
|
|
||||||
/* Glance at the keyboard once every second, to check for a Cancel. */
|
/* Glance at the keyboard once every second, to check for a Cancel. */
|
||||||
if (time(NULL) - lastkbcheck > 0) {
|
if (time(NULL) - lastkbcheck > 0) {
|
||||||
int input = wgetch(edit);
|
int input = wgetch(midwin);
|
||||||
|
|
||||||
lastkbcheck = time(NULL);
|
lastkbcheck = time(NULL);
|
||||||
|
|
||||||
@ -276,12 +280,12 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
while (input != ERR) {
|
while (input != ERR) {
|
||||||
if (input == ESC_CODE) {
|
if (input == ESC_CODE) {
|
||||||
napms(20);
|
napms(20);
|
||||||
input = wgetch(edit);
|
input = wgetch(midwin);
|
||||||
meta_key = TRUE;
|
meta_key = TRUE;
|
||||||
} else
|
} else
|
||||||
meta_key = FALSE;
|
meta_key = FALSE;
|
||||||
|
|
||||||
if (func_from_key(&input) == do_cancel) {
|
if (func_from_key(input) == do_cancel) {
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (the_window_resized)
|
if (the_window_resized)
|
||||||
regenerate_screen();
|
regenerate_screen();
|
||||||
@ -289,12 +293,12 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
statusbar(_("Cancelled"));
|
statusbar(_("Cancelled"));
|
||||||
/* Clear out the key buffer (in case a macro is running). */
|
/* Clear out the key buffer (in case a macro is running). */
|
||||||
while (input != ERR)
|
while (input != ERR)
|
||||||
input = parse_kbinput(NULL);
|
input = get_input(NULL);
|
||||||
nodelay(edit, FALSE);
|
nodelay(midwin, FALSE);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
input = wgetch(edit);
|
input = wgetch(midwin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++feedback > 0)
|
if (++feedback > 0)
|
||||||
@ -304,9 +308,11 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
|
|
||||||
found_x = found - line->data;
|
found_x = found - line->data;
|
||||||
|
|
||||||
nodelay(edit, FALSE);
|
nodelay(midwin, FALSE);
|
||||||
|
|
||||||
/* Ensure that the found occurrence is not beyond the starting x. */
|
/* Ensure that the found occurrence is not beyond the starting x. */
|
||||||
if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && (found_x > begin_x ||
|
if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && (found_x > begin_x ||
|
||||||
@ -443,8 +449,8 @@ void go_looking(void)
|
|||||||
* text in the passed string only when create is TRUE. */
|
* text in the passed string only when create is TRUE. */
|
||||||
int replace_regexp(char *string, bool create)
|
int replace_regexp(char *string, bool create)
|
||||||
{
|
{
|
||||||
const char *c = answer;
|
|
||||||
size_t replacement_size = 0;
|
size_t replacement_size = 0;
|
||||||
|
const char *c = answer;
|
||||||
|
|
||||||
/* Iterate through the replacement text to handle subexpression
|
/* Iterate through the replacement text to handle subexpression
|
||||||
* replacement using \1, \2, \3, etc. */
|
* replacement using \1, \2, \3, etc. */
|
||||||
@ -522,11 +528,11 @@ char *replace_line(const char *needle)
|
|||||||
ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||||
const linestruct *real_current, size_t *real_current_x)
|
const linestruct *real_current, size_t *real_current_x)
|
||||||
{
|
{
|
||||||
|
bool skipone = ISSET(BACKWARDS_SEARCH);
|
||||||
|
bool replaceall = FALSE;
|
||||||
|
int modus = REPLACING;
|
||||||
ssize_t numreplaced = -1;
|
ssize_t numreplaced = -1;
|
||||||
size_t match_len;
|
size_t match_len;
|
||||||
bool replaceall = FALSE;
|
|
||||||
bool skipone = ISSET(BACKWARDS_SEARCH);
|
|
||||||
int modus = REPLACING;
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
linestruct *was_mark = openfile->mark;
|
linestruct *was_mark = openfile->mark;
|
||||||
linestruct *top, *bot;
|
linestruct *top, *bot;
|
||||||
@ -553,7 +559,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
|||||||
came_full_circle = FALSE;
|
came_full_circle = FALSE;
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
int choice = 0;
|
int choice = NO;
|
||||||
int result = findnextstr(needle, whole_word_only, modus,
|
int result = findnextstr(needle, whole_word_only, modus,
|
||||||
&match_len, skipone, real_current, *real_current_x);
|
&match_len, skipone, real_current, *real_current_x);
|
||||||
|
|
||||||
@ -589,21 +595,21 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
|||||||
edit_refresh();
|
edit_refresh();
|
||||||
|
|
||||||
/* TRANSLATORS: This is a prompt. */
|
/* TRANSLATORS: This is a prompt. */
|
||||||
choice = do_yesno_prompt(TRUE, _("Replace this instance?"));
|
choice = ask_user(YESORALLORNO, _("Replace this instance?"));
|
||||||
|
|
||||||
spotlighted = FALSE;
|
spotlighted = FALSE;
|
||||||
|
|
||||||
if (choice == -1) /* The replacing was cancelled. */
|
if (choice == CANCEL)
|
||||||
break;
|
break;
|
||||||
else if (choice == 2)
|
|
||||||
replaceall = TRUE;
|
replaceall = (choice == ALL);
|
||||||
|
|
||||||
/* When "No" or moving backwards, the search routine should
|
/* When "No" or moving backwards, the search routine should
|
||||||
* first move one character further before continuing. */
|
* first move one character further before continuing. */
|
||||||
skipone = (choice == 0 || ISSET(BACKWARDS_SEARCH));
|
skipone = (choice == 0 || ISSET(BACKWARDS_SEARCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (choice == 1 || replaceall) { /* Yes, replace it. */
|
if (choice == YES || replaceall) {
|
||||||
size_t length_change;
|
size_t length_change;
|
||||||
char *altered;
|
char *altered;
|
||||||
|
|
||||||
@ -657,6 +663,10 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
|||||||
free(openfile->current->data);
|
free(openfile->current->data);
|
||||||
openfile->current->data = altered;
|
openfile->current->data = altered;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
check_the_multis(openfile->current);
|
||||||
|
refresh_needed = FALSE;
|
||||||
|
#endif
|
||||||
set_modified();
|
set_modified();
|
||||||
as_an_at = TRUE;
|
as_an_at = TRUE;
|
||||||
numreplaced++;
|
numreplaced++;
|
||||||
@ -729,18 +739,28 @@ void ask_for_and_do_replacements(void)
|
|||||||
"Replaced %zd occurrences", numreplaced), numreplaced);
|
"Replaced %zd occurrences", numreplaced), numreplaced);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||||
/* Go to the specified line and x position. */
|
/* Go to the specified line and x position. */
|
||||||
void goto_line_posx(ssize_t line, size_t pos_x)
|
void goto_line_posx(ssize_t linenumber, size_t pos_x)
|
||||||
{
|
{
|
||||||
for (openfile->current = openfile->filetop; line > 1 &&
|
#ifdef ENABLE_COLOR
|
||||||
openfile->current != openfile->filebot; line--)
|
if (linenumber > openfile->edittop->lineno + editwinrows ||
|
||||||
openfile->current = openfile->current->next;
|
(ISSET(SOFTWRAP) && linenumber > openfile->current->lineno))
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (linenumber < openfile->filebot->lineno)
|
||||||
|
openfile->current = line_from_number(linenumber);
|
||||||
|
else
|
||||||
|
openfile->current = openfile->filebot;
|
||||||
|
|
||||||
openfile->current_x = pos_x;
|
openfile->current_x = pos_x;
|
||||||
openfile->placewewant = xplustabs();
|
openfile->placewewant = xplustabs();
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Go to the specified line and column, or ask for them if interactive
|
/* Go to the specified line and column, or ask for them if interactive
|
||||||
* is TRUE. In the latter case also update the screen afterwards.
|
* is TRUE. In the latter case also update the screen afterwards.
|
||||||
@ -760,7 +780,7 @@ void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_from_key(&response) == flip_goto) {
|
if (func_from_key(response) == flip_goto) {
|
||||||
UNSET(BACKWARDS_SEARCH);
|
UNSET(BACKWARDS_SEARCH);
|
||||||
/* Switch to searching but retain what the user typed so far. */
|
/* Switch to searching but retain what the user typed so far. */
|
||||||
search_init(FALSE, TRUE);
|
search_init(FALSE, TRUE);
|
||||||
@ -790,11 +810,26 @@ void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
|||||||
if (line < 1)
|
if (line < 1)
|
||||||
line = 1;
|
line = 1;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
linestruct *edit_bottom = openfile->edittop;
|
||||||
|
for (int i = 0;edit_bottom != openfile->filebot && i < editwinrows;++i)
|
||||||
|
edit_bottom = get_next_visible_line(edit_bottom);
|
||||||
|
if (line > edit_bottom->lineno ||
|
||||||
|
(ISSET(SOFTWRAP) && line > openfile->current->lineno))
|
||||||
|
#else
|
||||||
|
if (line > openfile->edittop->lineno + editwinrows)
|
||||||
|
#endif
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif /* ENABLE_COLOR */
|
||||||
|
|
||||||
/* Iterate to the requested line. */
|
/* Iterate to the requested line. */
|
||||||
for (openfile->current = openfile->filetop; line > 1 &&
|
for (openfile->current = openfile->filetop; line > 1 &&
|
||||||
openfile->current != openfile->filebot; line--)
|
openfile->current != openfile->filebot; line--)
|
||||||
openfile->current = openfile->current->next;
|
openfile->current = openfile->current->next;
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
|
||||||
/* Take a negative column number to mean: from the end of the line. */
|
/* Take a negative column number to mean: from the end of the line. */
|
||||||
if (column < 0)
|
if (column < 0)
|
||||||
column = breadth(openfile->current->data) + column + 2;
|
column = breadth(openfile->current->data) + column + 2;
|
||||||
@ -811,9 +846,9 @@ void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
|||||||
openfile->placewewant = breadth(openfile->current->data);
|
openfile->placewewant = breadth(openfile->current->data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* When the position was manually given, center the target line. */
|
/* When a line number was manually given, center the target line. */
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
adjust_viewport(CENTERING);
|
adjust_viewport((*answer == ',') ? STATIONARY : CENTERING);
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
} else {
|
} else {
|
||||||
int rows_from_tail;
|
int rows_from_tail;
|
||||||
@ -849,23 +884,110 @@ void do_gotolinecolumn(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
|
/* Search backwards for a line ending with a bracket, including the current line.
|
||||||
|
* top is an in/out parameter. The passed value is the start line for searching.
|
||||||
|
* xpos is an out parameter. It is the position in the line where the bracket is
|
||||||
|
* found. bracket_half is the halfway mark in the matchbrackets array. This way in
|
||||||
|
* a loop the halfway value isn't recomputed. */
|
||||||
|
bool find_start_of_bracketed_region(linestruct **top, size_t *xpos, size_t bracket_half)
|
||||||
|
{
|
||||||
|
/* Search backwards for a line ending with a bracket, including the current line */
|
||||||
|
for (;(*top) != NULL;*top = (*top)->prev) {
|
||||||
|
char *found;
|
||||||
|
const char *bracket;
|
||||||
|
int len = strlen((*top)->data);
|
||||||
|
|
||||||
|
/* Find the last bracket on the search line */
|
||||||
|
found = mbrevstrpbrk((*top)->data, matchbrackets, (*top)->data + len);
|
||||||
|
if (found == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*xpos = found - (*top)->data;
|
||||||
|
bracket = mbstrchr(matchbrackets, found);
|
||||||
|
|
||||||
|
/* We're looking for opening braces, not closing */
|
||||||
|
if (bracket >= matchbrackets + bracket_half)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Check if this is the last character in the line */
|
||||||
|
char *next = (*top)->data + step_right((*top)->data, *xpos);
|
||||||
|
if (*next == '\0')
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
*xpos = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the halfway point in matchbrackets, where open and close
|
||||||
|
* brackets meet. */
|
||||||
|
size_t get_matchbrackets_halfway(void)
|
||||||
|
{
|
||||||
|
size_t charcount = mbstrlen(matchbrackets) / 2;
|
||||||
|
size_t halfway = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0;i < charcount;++i)
|
||||||
|
halfway += char_length(matchbrackets + halfway);
|
||||||
|
return halfway;
|
||||||
|
}
|
||||||
|
/* Get a region surrounding the line in_region. A region here is defined
|
||||||
|
* as a block of text starting with an opening bracket at the end of a line,
|
||||||
|
* and ending with a matching closing bracket.
|
||||||
|
* top and bot are out parameters. Returns the top/bottom line of the region.
|
||||||
|
* top_pos and bot_pos are out parameters. Returns the position within the
|
||||||
|
* top and bottom lines where the brackets are found. */
|
||||||
|
bool find_bracketed_region(linestruct *in_region,
|
||||||
|
linestruct **top, linestruct **bot)
|
||||||
|
{
|
||||||
|
size_t bracket_half = get_matchbrackets_halfway();
|
||||||
|
size_t top_pos;
|
||||||
|
size_t bot_pos;
|
||||||
|
linestruct *was_top = *top;
|
||||||
|
linestruct *was_bot = *bot;
|
||||||
|
*top = in_region;
|
||||||
|
|
||||||
|
for (;find_start_of_bracketed_region(top, &top_pos, bracket_half)
|
||||||
|
;*top = (*top)->prev)
|
||||||
|
{
|
||||||
|
*bot = *top;
|
||||||
|
bot_pos = top_pos;
|
||||||
|
|
||||||
|
if (!find_matching_bracket_pos(bot, &bot_pos)) {
|
||||||
|
if ((*bot)->lineno < in_region->lineno)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int linedist = (*bot)->lineno - (*top)->lineno;
|
||||||
|
|
||||||
|
if (linedist >= 2) {
|
||||||
|
*top = (*top)->next;
|
||||||
|
*bot = (*bot)->prev;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*top = was_top;
|
||||||
|
*bot = was_bot;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Search, starting from the current position, for any of the two characters
|
/* Search, starting from the current position, for any of the two characters
|
||||||
* in bracket_pair. If reverse is TRUE, search backwards, otherwise forwards.
|
* in bracket_pair. If reverse is TRUE, search backwards, otherwise forwards.
|
||||||
* Return TRUE when one of the brackets was found, and FALSE otherwise. */
|
* Return TRUE when one of the brackets was found, and FALSE otherwise. */
|
||||||
bool find_a_bracket(bool reverse, const char *bracket_pair)
|
bool find_a_bracket(bool reverse, const char *bracket_pair,
|
||||||
|
linestruct **inout_line, size_t *xpos)
|
||||||
{
|
{
|
||||||
linestruct *line = openfile->current;
|
linestruct *line = *inout_line;
|
||||||
const char *pointer, *found;
|
const char *pointer, *found;
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
/* First step away from the current bracket. */
|
/* First step away from the current bracket. */
|
||||||
if (openfile->current_x == 0) {
|
if (*xpos == 0) {
|
||||||
line = line->prev;
|
line = line->prev;
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
pointer = line->data + strlen(line->data);
|
pointer = line->data + strlen(line->data);
|
||||||
} else
|
} else
|
||||||
pointer = line->data + step_left(line->data, openfile->current_x);
|
pointer = line->data + step_left(line->data, *xpos);
|
||||||
|
|
||||||
/* Now seek for any of the two brackets we are interested in. */
|
/* Now seek for any of the two brackets we are interested in. */
|
||||||
while (!(found = mbrevstrpbrk(line->data, bracket_pair, pointer))) {
|
while (!(found = mbrevstrpbrk(line->data, bracket_pair, pointer))) {
|
||||||
@ -875,7 +997,7 @@ bool find_a_bracket(bool reverse, const char *bracket_pair)
|
|||||||
pointer = line->data + strlen(line->data);
|
pointer = line->data + strlen(line->data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pointer = line->data + step_right(line->data, openfile->current_x);
|
pointer = line->data + step_right(line->data, *xpos);
|
||||||
|
|
||||||
while (!(found = mbstrpbrk(pointer, bracket_pair))) {
|
while (!(found = mbstrpbrk(pointer, bracket_pair))) {
|
||||||
line = line->next;
|
line = line->next;
|
||||||
@ -885,45 +1007,24 @@ bool find_a_bracket(bool reverse, const char *bracket_pair)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the current position to the found bracket. */
|
/* Set the found position to the found bracket. */
|
||||||
openfile->current = line;
|
*inout_line = line;
|
||||||
openfile->current_x = found - line->data;
|
*xpos = found - line->data;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search for a match to the bracket at the current cursor position, if
|
/* Search for the given bracket's compliment within matchbrackets.
|
||||||
* there is one. */
|
* ch must be a pointer to within matchbrackets.
|
||||||
void do_find_bracket(void)
|
* reverse is true if the found compliment came before ch in matchbrackets. */
|
||||||
|
const char *get_bracket_compliment(const char *ch, bool *reverse)
|
||||||
{
|
{
|
||||||
linestruct *was_current = openfile->current;
|
|
||||||
size_t was_current_x = openfile->current_x;
|
|
||||||
/* The current cursor position, in case we don't find a complement. */
|
|
||||||
const char *ch;
|
|
||||||
/* The location in matchbrackets of the bracket under the cursor. */
|
|
||||||
int ch_len;
|
|
||||||
/* The length of ch in bytes. */
|
|
||||||
const char *wanted_ch;
|
|
||||||
/* The location in matchbrackets of the complementing bracket. */
|
|
||||||
int wanted_ch_len;
|
|
||||||
/* The length of wanted_ch in bytes. */
|
|
||||||
char bracket_pair[MAXCHARLEN * 2 + 1];
|
|
||||||
/* The pair of characters in ch and wanted_ch. */
|
|
||||||
size_t halfway = 0;
|
|
||||||
/* The index in matchbrackets where the closing brackets start. */
|
|
||||||
size_t charcount = mbstrlen(matchbrackets) / 2;
|
size_t charcount = mbstrlen(matchbrackets) / 2;
|
||||||
/* Half the number of characters in matchbrackets. */
|
/* Half the number of characters in matchbrackets. */
|
||||||
size_t balance = 1;
|
const char *wanted_ch;
|
||||||
/* The initial bracket count. */
|
/* The location in matchbrackets of the complementing bracket. */
|
||||||
bool reverse;
|
size_t halfway = 0;
|
||||||
/* The direction we search. */
|
/* The index in matchbrackets where the closing brackets start. */
|
||||||
|
|
||||||
ch = mbstrchr(matchbrackets, openfile->current->data + openfile->current_x);
|
|
||||||
|
|
||||||
if (ch == NULL) {
|
|
||||||
statusline(AHEM, _("Not a bracket"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the halfway point in matchbrackets, where the closing ones start. */
|
/* Find the halfway point in matchbrackets, where the closing ones start. */
|
||||||
for (size_t i = 0; i < charcount; i++)
|
for (size_t i = 0; i < charcount; i++)
|
||||||
@ -931,19 +1032,35 @@ void do_find_bracket(void)
|
|||||||
|
|
||||||
/* When on a closing bracket, we have to search backwards for a matching
|
/* When on a closing bracket, we have to search backwards for a matching
|
||||||
* opening bracket; otherwise, forward for a matching closing bracket. */
|
* opening bracket; otherwise, forward for a matching closing bracket. */
|
||||||
reverse = (ch >= (matchbrackets + halfway));
|
*reverse = (ch >= (matchbrackets + halfway));
|
||||||
|
|
||||||
/* Step half the number of total characters either backwards or forwards
|
/* Step half the number of total characters either backwards or forwards
|
||||||
* through matchbrackets to find the wanted complementary bracket. */
|
* through matchbrackets to find the wanted complementary bracket. */
|
||||||
wanted_ch = ch;
|
wanted_ch = ch;
|
||||||
while (charcount-- > 0) {
|
while (charcount-- > 0) {
|
||||||
if (reverse)
|
if (*reverse)
|
||||||
wanted_ch = matchbrackets + step_left(matchbrackets,
|
wanted_ch = matchbrackets + step_left(matchbrackets,
|
||||||
wanted_ch - matchbrackets);
|
wanted_ch - matchbrackets);
|
||||||
else
|
else
|
||||||
wanted_ch += char_length(wanted_ch);
|
wanted_ch += char_length(wanted_ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return wanted_ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a bracket pair string from the given bracket in ch, assigning
|
||||||
|
* the result to bracket_pair. Reverse is set to true if we need to
|
||||||
|
* search backward for a match. */
|
||||||
|
void create_bracket_pair(char *bracket_pair, const char *ch,
|
||||||
|
int ch_len, bool* reverse)
|
||||||
|
{
|
||||||
|
const char *wanted_ch;
|
||||||
|
/* The location in matchbrackets of the complementing bracket. */
|
||||||
|
int wanted_ch_len;
|
||||||
|
/* The length of wanted_ch in bytes. */
|
||||||
|
|
||||||
|
wanted_ch = get_bracket_compliment(ch, reverse);
|
||||||
|
|
||||||
ch_len = char_length(ch);
|
ch_len = char_length(ch);
|
||||||
wanted_ch_len = char_length(wanted_ch);
|
wanted_ch_len = char_length(wanted_ch);
|
||||||
|
|
||||||
@ -951,24 +1068,65 @@ void do_find_bracket(void)
|
|||||||
strncpy(bracket_pair, ch, ch_len);
|
strncpy(bracket_pair, ch, ch_len);
|
||||||
strncpy(bracket_pair + ch_len, wanted_ch, wanted_ch_len);
|
strncpy(bracket_pair + ch_len, wanted_ch, wanted_ch_len);
|
||||||
bracket_pair[ch_len + wanted_ch_len] = '\0';
|
bracket_pair[ch_len + wanted_ch_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
while (find_a_bracket(reverse, bracket_pair)) {
|
/* Get the bracket match position for the character currently under the cursor.
|
||||||
/* Increment/decrement balance for an identical/other bracket. */
|
* If there is no bracket beneath the cursor, return NOT_A_BRACKET. If there is
|
||||||
balance += (strncmp(openfile->current->data + openfile->current_x,
|
* no match found, return NOT_FOUND_BRACKET. Otherwise returns FOUND_BRACKET
|
||||||
ch, ch_len) == 0) ? 1 : -1;
|
* and sets line and xpos to the found line and offset respectively. */
|
||||||
|
int find_matching_bracket_pos(linestruct **line, size_t *xpos)
|
||||||
|
{
|
||||||
|
const char *br_ch;
|
||||||
|
/* The location in matchbrackets of the bracket under the cursor. */
|
||||||
|
int br_ch_len;
|
||||||
|
/* The length of br_ch in bytes. */
|
||||||
|
char bracket_pair[MAXCHARLEN * 2 + 1];
|
||||||
|
/* The pair of characters in ch and wanted_ch. */
|
||||||
|
size_t balance = 1;
|
||||||
|
/* The initial bracket count. */
|
||||||
|
bool reversed;
|
||||||
|
/* The direction we search. */
|
||||||
|
|
||||||
/* When balance reached zero, we've found the complementary bracket. */
|
br_ch = mbstrchr(matchbrackets, (*line)->data + (*xpos));
|
||||||
if (balance == 0) {
|
|
||||||
edit_redraw(was_current, FLOWING);
|
if (br_ch == NULL)
|
||||||
return;
|
return NOT_A_BRACKET;
|
||||||
}
|
|
||||||
|
br_ch_len = char_length(br_ch);
|
||||||
|
create_bracket_pair(bracket_pair, br_ch, br_ch_len, &reversed);
|
||||||
|
|
||||||
|
|
||||||
|
while (find_a_bracket(reversed, bracket_pair, line, xpos)) {
|
||||||
|
balance += (strncmp((*line)->data + *xpos,
|
||||||
|
br_ch, br_ch_len) == 0) ? 1 : -1;
|
||||||
|
if (balance == 0)
|
||||||
|
return FOUND_BRACKET;
|
||||||
|
|
||||||
|
}
|
||||||
|
return NOT_FOUND_BRACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search for a match to the bracket at the current cursor position, if
|
||||||
|
* there is one. */
|
||||||
|
void do_find_bracket(void)
|
||||||
|
{
|
||||||
|
linestruct *was_current = openfile->current;
|
||||||
|
size_t was_current_x = openfile->current_x;
|
||||||
|
|
||||||
|
int res = find_matching_bracket_pos(&openfile->current,
|
||||||
|
&openfile->current_x);
|
||||||
|
if (res == FOUND_BRACKET) {
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
edit_redraw(was_current, FLOWING);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusline(AHEM, _("No matching bracket"));
|
|
||||||
|
|
||||||
/* Restore the cursor position. */
|
|
||||||
openfile->current = was_current;
|
openfile->current = was_current;
|
||||||
openfile->current_x = was_current_x;
|
openfile->current_x = was_current_x;
|
||||||
|
|
||||||
|
statusline(AHEM, res == NOT_FOUND_BRACKET ?
|
||||||
|
_("No matching bracket") :
|
||||||
|
_("Not a bracket"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place an anchor at the current line when none exists, otherwise remove it. */
|
/* Place an anchor at the current line when none exists, otherwise remove it. */
|
||||||
@ -992,6 +1150,12 @@ void go_to_and_confirm(linestruct *line)
|
|||||||
if (line != openfile->current) {
|
if (line != openfile->current) {
|
||||||
openfile->current = line;
|
openfile->current = line;
|
||||||
openfile->current_x = 0;
|
openfile->current_x = 0;
|
||||||
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
if (line->lineno > openfile->edittop->lineno + editwinrows ||
|
||||||
|
(ISSET(SOFTWRAP) && line->lineno > was_current->lineno))
|
||||||
|
recook |= perturbed;
|
||||||
|
#endif
|
||||||
edit_redraw(was_current, CENTERING);
|
edit_redraw(was_current, CENTERING);
|
||||||
statusbar(_("Jumped to anchor"));
|
statusbar(_("Jumped to anchor"));
|
||||||
} else if (openfile->current->has_anchor)
|
} else if (openfile->current->has_anchor)
|
||||||
|
|||||||
276
src/text.c
276
src/text.c
@ -1,12 +1,12 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* text.c -- This file is part of GNU nano. *
|
* text.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2014-2015 Mark Majeres *
|
* Copyright (C) 2014-2015 Mark Majeres *
|
||||||
* Copyright (C) 2016 Mike Scalora *
|
* Copyright (C) 2016 Mike Scalora *
|
||||||
* Copyright (C) 2016 Sumedh Pendurkar *
|
* Copyright (C) 2016 Sumedh Pendurkar *
|
||||||
* Copyright (C) 2018 Marco Diego Aurélio Mesquita *
|
* Copyright (C) 2018 Marco Diego Aurélio Mesquita *
|
||||||
* Copyright (C) 2015-2021 Benno Schulenberg *
|
* Copyright (C) 2015-2022 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU General Public License as published *
|
* it under the terms of the GNU General Public License as published *
|
||||||
@ -65,8 +65,8 @@ void do_mark(void)
|
|||||||
void do_tab(void)
|
void do_tab(void)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
if (openfile->syntax && openfile->syntax->tab)
|
if (openfile->syntax && openfile->syntax->tabstring)
|
||||||
inject(openfile->syntax->tab, strlen(openfile->syntax->tab));
|
inject(openfile->syntax->tabstring, strlen(openfile->syntax->tabstring));
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
@ -96,6 +96,8 @@ void indent_a_line(linestruct *line, char *indentation)
|
|||||||
if (indent_len == 0)
|
if (indent_len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
|
|
||||||
/* Add the fabricated indentation to the beginning of the line. */
|
/* Add the fabricated indentation to the beginning of the line. */
|
||||||
line->data = nrealloc(line->data, length + indent_len + 1);
|
line->data = nrealloc(line->data, length + indent_len + 1);
|
||||||
memmove(line->data + indent_len, line->data, length + 1);
|
memmove(line->data + indent_len, line->data, length + 1);
|
||||||
@ -117,8 +119,8 @@ void indent_a_line(linestruct *line, char *indentation)
|
|||||||
* depending on whether --tabstospaces is in effect. */
|
* depending on whether --tabstospaces is in effect. */
|
||||||
void do_indent(void)
|
void do_indent(void)
|
||||||
{
|
{
|
||||||
char *indentation;
|
|
||||||
linestruct *top, *bot, *line;
|
linestruct *top, *bot, *line;
|
||||||
|
char *indentation;
|
||||||
|
|
||||||
/* Use either all the marked lines or just the current line. */
|
/* Use either all the marked lines or just the current line. */
|
||||||
get_range(&top, &bot);
|
get_range(&top, &bot);
|
||||||
@ -134,8 +136,8 @@ void do_indent(void)
|
|||||||
indentation = nmalloc(tabsize + 1);
|
indentation = nmalloc(tabsize + 1);
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
if (openfile->syntax && openfile->syntax->tab)
|
if (openfile->syntax && openfile->syntax->tabstring)
|
||||||
indentation = mallocstrcpy(indentation, openfile->syntax->tab);
|
indentation = mallocstrcpy(indentation, openfile->syntax->tabstring);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
/* Set the indentation to either a bunch of spaces or a single tab. */
|
/* Set the indentation to either a bunch of spaces or a single tab. */
|
||||||
@ -173,10 +175,10 @@ size_t length_of_white(const char *text)
|
|||||||
size_t white_count = 0;
|
size_t white_count = 0;
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
if (openfile->syntax && openfile->syntax->tab) {
|
if (openfile->syntax && openfile->syntax->tabstring) {
|
||||||
size_t thelength = strlen(openfile->syntax->tab);
|
size_t thelength = strlen(openfile->syntax->tabstring);
|
||||||
|
|
||||||
while (text[white_count] == openfile->syntax->tab[white_count])
|
while (text[white_count] == openfile->syntax->tabstring[white_count])
|
||||||
if (++white_count == thelength)
|
if (++white_count == thelength)
|
||||||
return thelength;
|
return thelength;
|
||||||
|
|
||||||
@ -226,6 +228,8 @@ void unindent_a_line(linestruct *line, size_t indent_len)
|
|||||||
if (indent_len == 0)
|
if (indent_len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
|
|
||||||
/* Remove the first tab's worth of whitespace from this line. */
|
/* Remove the first tab's worth of whitespace from this line. */
|
||||||
memmove(line->data, line->data + indent_len, length - indent_len + 1);
|
memmove(line->data, line->data + indent_len, length - indent_len + 1);
|
||||||
|
|
||||||
@ -317,6 +321,8 @@ bool comment_line(undo_type action, linestruct *line, const char *comment_seq)
|
|||||||
/* Length of postfix. */
|
/* Length of postfix. */
|
||||||
size_t line_len = strlen(line->data);
|
size_t line_len = strlen(line->data);
|
||||||
|
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
|
|
||||||
if (!ISSET(NO_NEWLINES) && line == openfile->filebot)
|
if (!ISSET(NO_NEWLINES) && line == openfile->filebot)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -416,8 +422,9 @@ void do_comment(void)
|
|||||||
/* Comment/uncomment each of the selected lines when possible, and
|
/* Comment/uncomment each of the selected lines when possible, and
|
||||||
* store undo data when a line changed. */
|
* store undo data when a line changed. */
|
||||||
for (line = top; line != bot->next; line = line->next)
|
for (line = top; line != bot->next; line = line->next)
|
||||||
if (comment_line(action, line, comment_seq))
|
if (comment_line(action, line, comment_seq)) {
|
||||||
update_multiline_undo(line->lineno, "");
|
update_multiline_undo(line->lineno, "");
|
||||||
|
}
|
||||||
|
|
||||||
set_modified();
|
set_modified();
|
||||||
ensure_firstcolumn_is_aligned();
|
ensure_firstcolumn_is_aligned();
|
||||||
@ -502,10 +509,11 @@ void redo_cut(undostruct *u)
|
|||||||
void do_undo(void)
|
void do_undo(void)
|
||||||
{
|
{
|
||||||
undostruct *u = openfile->current_undo;
|
undostruct *u = openfile->current_undo;
|
||||||
linestruct *line = NULL, *intruder;
|
linestruct *oldcutbuffer, *intruder;
|
||||||
linestruct *oldcutbuffer;
|
linestruct *line = NULL;
|
||||||
char *data, *undidmsg = NULL;
|
|
||||||
size_t original_x, regain_from_x;
|
size_t original_x, regain_from_x;
|
||||||
|
char *undidmsg = NULL;
|
||||||
|
char *data;
|
||||||
|
|
||||||
if (u == NULL) {
|
if (u == NULL) {
|
||||||
statusline(AHEM, _("Nothing to undo"));
|
statusline(AHEM, _("Nothing to undo"));
|
||||||
@ -539,6 +547,7 @@ void do_undo(void)
|
|||||||
line->has_anchor |= line->next->has_anchor;
|
line->has_anchor |= line->next->has_anchor;
|
||||||
unlink_node(line->next);
|
unlink_node(line->next);
|
||||||
renumber_from(line);
|
renumber_from(line);
|
||||||
|
openfile->current = line;
|
||||||
goto_line_posx(u->head_lineno, original_x);
|
goto_line_posx(u->head_lineno, original_x);
|
||||||
break;
|
break;
|
||||||
case BACK:
|
case BACK:
|
||||||
@ -558,7 +567,8 @@ void do_undo(void)
|
|||||||
* and the nonewlines flag isn't set, do not re-add a newline that
|
* and the nonewlines flag isn't set, do not re-add a newline that
|
||||||
* wasn't actually deleted; just position the cursor. */
|
* wasn't actually deleted; just position the cursor. */
|
||||||
if ((u->xflags & WAS_BACKSPACE_AT_EOF) && !ISSET(NO_NEWLINES)) {
|
if ((u->xflags & WAS_BACKSPACE_AT_EOF) && !ISSET(NO_NEWLINES)) {
|
||||||
goto_line_posx(openfile->filebot->lineno, 0);
|
openfile->current = openfile->filebot;
|
||||||
|
openfile->current_x = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
line->data[u->tail_x] = '\0';
|
line->data[u->tail_x] = '\0';
|
||||||
@ -655,7 +665,7 @@ void do_undo(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (undidmsg && !pletion_line)
|
if (undidmsg && !ISSET(ZERO) && !pletion_line)
|
||||||
statusline(HUSH, _("Undid %s"), undidmsg);
|
statusline(HUSH, _("Undid %s"), undidmsg);
|
||||||
|
|
||||||
openfile->current_undo = openfile->current_undo->next;
|
openfile->current_undo = openfile->current_undo->next;
|
||||||
@ -665,6 +675,13 @@ void do_undo(void)
|
|||||||
|
|
||||||
openfile->totsize = u->wassize;
|
openfile->totsize = u->wassize;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
if (u->type <= REPLACE)
|
||||||
|
check_the_multis(openfile->current);
|
||||||
|
else if (u->type == INSERT)
|
||||||
|
perturbed = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* When at the point where the buffer was last saved, unset "Modified". */
|
/* When at the point where the buffer was last saved, unset "Modified". */
|
||||||
if (openfile->current_undo == openfile->last_saved) {
|
if (openfile->current_undo == openfile->last_saved) {
|
||||||
openfile->modified = FALSE;
|
openfile->modified = FALSE;
|
||||||
@ -676,10 +693,12 @@ void do_undo(void)
|
|||||||
/* Redo the last thing(s) we undid. */
|
/* Redo the last thing(s) we undid. */
|
||||||
void do_redo(void)
|
void do_redo(void)
|
||||||
{
|
{
|
||||||
linestruct *line = NULL, *intruder;
|
|
||||||
char *data, *redidmsg = NULL;
|
|
||||||
bool suppress_modification = FALSE;
|
|
||||||
undostruct *u = openfile->undotop;
|
undostruct *u = openfile->undotop;
|
||||||
|
bool suppress_modification = FALSE;
|
||||||
|
linestruct *line = NULL;
|
||||||
|
linestruct *intruder;
|
||||||
|
char *redidmsg = NULL;
|
||||||
|
char *data;
|
||||||
|
|
||||||
if (u == NULL || u == openfile->current_undo) {
|
if (u == NULL || u == openfile->current_undo) {
|
||||||
statusline(AHEM, _("Nothing to redo"));
|
statusline(AHEM, _("Nothing to redo"));
|
||||||
@ -735,6 +754,7 @@ void do_redo(void)
|
|||||||
strcat(line->data, u->strdata);
|
strcat(line->data, u->strdata);
|
||||||
unlink_node(line->next);
|
unlink_node(line->next);
|
||||||
renumber_from(line);
|
renumber_from(line);
|
||||||
|
openfile->current = line;
|
||||||
goto_line_posx(u->tail_lineno, u->tail_x);
|
goto_line_posx(u->tail_lineno, u->tail_x);
|
||||||
break;
|
break;
|
||||||
case REPLACE:
|
case REPLACE:
|
||||||
@ -815,7 +835,7 @@ void do_redo(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redidmsg)
|
if (redidmsg && !ISSET(ZERO))
|
||||||
statusline(HUSH, _("Redid %s"), redidmsg);
|
statusline(HUSH, _("Redid %s"), redidmsg);
|
||||||
|
|
||||||
openfile->current_undo = u;
|
openfile->current_undo = u;
|
||||||
@ -825,6 +845,13 @@ void do_redo(void)
|
|||||||
|
|
||||||
openfile->totsize = u->newsize;
|
openfile->totsize = u->newsize;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
if (u->type <= REPLACE)
|
||||||
|
check_the_multis(openfile->current);
|
||||||
|
else if (u->type == INSERT)
|
||||||
|
recook = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* When at the point where the buffer was last saved, unset "Modified". */
|
/* When at the point where the buffer was last saved, unset "Modified". */
|
||||||
if (openfile->current_undo == openfile->last_saved) {
|
if (openfile->current_undo == openfile->last_saved) {
|
||||||
openfile->modified = FALSE;
|
openfile->modified = FALSE;
|
||||||
@ -839,6 +866,13 @@ void do_enter(void)
|
|||||||
{
|
{
|
||||||
linestruct *newnode = make_new_node(openfile->current);
|
linestruct *newnode = make_new_node(openfile->current);
|
||||||
size_t extra = 0;
|
size_t extra = 0;
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOLDING
|
||||||
|
if (openfile->current->folded) {
|
||||||
|
newnode->folded = TRUE;
|
||||||
|
openfile->current->folded = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
linestruct *sampleline = openfile->current;
|
linestruct *sampleline = openfile->current;
|
||||||
bool allblanks = FALSE;
|
bool allblanks = FALSE;
|
||||||
@ -857,7 +891,7 @@ void do_enter(void)
|
|||||||
if (extra > openfile->current_x)
|
if (extra > openfile->current_x)
|
||||||
extra = openfile->current_x;
|
extra = openfile->current_x;
|
||||||
else if (extra == openfile->current_x)
|
else if (extra == openfile->current_x)
|
||||||
allblanks = TRUE;
|
allblanks = (indent_length(openfile->current->data) == extra);
|
||||||
}
|
}
|
||||||
#endif /* NANO_TINY */
|
#endif /* NANO_TINY */
|
||||||
newnode->data = nmalloc(strlen(openfile->current->data +
|
newnode->data = nmalloc(strlen(openfile->current->data +
|
||||||
@ -1177,7 +1211,8 @@ void update_undo(undo_type action)
|
|||||||
else if (cutbuffer != NULL) {
|
else if (cutbuffer != NULL) {
|
||||||
free_lines(u->cutbuffer);
|
free_lines(u->cutbuffer);
|
||||||
u->cutbuffer = copy_buffer(cutbuffer);
|
u->cutbuffer = copy_buffer(cutbuffer);
|
||||||
}
|
} else
|
||||||
|
break;
|
||||||
if (!(u->xflags & MARK_WAS_SET)) {
|
if (!(u->xflags & MARK_WAS_SET)) {
|
||||||
linestruct *bottomline = u->cutbuffer;
|
linestruct *bottomline = u->cutbuffer;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@ -1564,6 +1599,7 @@ void concat_paragraph(linestruct *line, size_t count)
|
|||||||
line->data = nrealloc(line->data,
|
line->data = nrealloc(line->data,
|
||||||
line_len + next_line_len - next_lead_len + 1);
|
line_len + next_line_len - next_lead_len + 1);
|
||||||
strcat(line->data, next_line->data + next_lead_len);
|
strcat(line->data, next_line->data + next_lead_len);
|
||||||
|
UNFOLD_SEGMENT(line);
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
line->has_anchor |= next_line->has_anchor;
|
line->has_anchor |= next_line->has_anchor;
|
||||||
#endif
|
#endif
|
||||||
@ -1745,6 +1781,8 @@ void justify_text(bool whole_buffer)
|
|||||||
/* The leading part for lines after the first one. */
|
/* The leading part for lines after the first one. */
|
||||||
size_t secondary_len = 0;
|
size_t secondary_len = 0;
|
||||||
/* The length of that later lead. */
|
/* The length of that later lead. */
|
||||||
|
ssize_t was_the_linenumber = openfile->current->lineno;
|
||||||
|
/* The line to return to after a full justification. */
|
||||||
|
|
||||||
/* TRANSLATORS: This one goes with Undid/Redid messages. */
|
/* TRANSLATORS: This one goes with Undid/Redid messages. */
|
||||||
add_undo(COUPLE_BEGIN, N_("justification"));
|
add_undo(COUPLE_BEGIN, N_("justification"));
|
||||||
@ -1961,7 +1999,8 @@ void justify_text(bool whole_buffer)
|
|||||||
openfile->current_x = openfile->mark_x;
|
openfile->current_x = openfile->mark_x;
|
||||||
openfile->mark = bottom;
|
openfile->mark = bottom;
|
||||||
openfile->mark_x = bottom_x;
|
openfile->mark_x = bottom_x;
|
||||||
}
|
} else if (whole_buffer && !openfile->mark)
|
||||||
|
goto_line_posx(was_the_linenumber, 0);
|
||||||
|
|
||||||
add_undo(COUPLE_END, N_("justification"));
|
add_undo(COUPLE_END, N_("justification"));
|
||||||
|
|
||||||
@ -2000,7 +2039,7 @@ void do_full_justify(void)
|
|||||||
}
|
}
|
||||||
#endif /* ENABLE_JUSTIFY */
|
#endif /* ENABLE_JUSTIFY */
|
||||||
|
|
||||||
#if defined(ENABLE_SPELLER) || defined (ENABLE_COLOR)
|
#if defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||||
/* Set up an argument list for executing the given command. */
|
/* Set up an argument list for executing the given command. */
|
||||||
void construct_argument_list(char ***arguments, char *command, char *filename)
|
void construct_argument_list(char ***arguments, char *command, char *filename)
|
||||||
{
|
{
|
||||||
@ -2017,7 +2056,9 @@ void construct_argument_list(char ***arguments, char *command, char *filename)
|
|||||||
(*arguments)[count - 2] = filename;
|
(*arguments)[count - 2] = filename;
|
||||||
(*arguments)[count - 1] = NULL;
|
(*arguments)[count - 1] = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_SPELLER) || defined (ENABLE_FORMATTER)
|
||||||
/* Open the specified file, and if that succeeds, remove the text of the marked
|
/* Open the specified file, and if that succeeds, remove the text of the marked
|
||||||
* region or of the entire buffer and read the file contents into its place. */
|
* region or of the entire buffer and read the file contents into its place. */
|
||||||
bool replace_buffer(const char *filename, undo_type action, const char *operation)
|
bool replace_buffer(const char *filename, undo_type action, const char *operation)
|
||||||
@ -2031,11 +2072,19 @@ bool replace_buffer(const char *filename, undo_type action, const char *operatio
|
|||||||
if (descriptor < 0)
|
if (descriptor < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
add_undo(COUPLE_BEGIN, operation);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* When replacing the whole buffer, start cutting at the top. */
|
||||||
|
if (action == CUT_TO_EOF) {
|
||||||
|
openfile->current = openfile->filetop;
|
||||||
|
openfile->current_x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
cutbuffer = NULL;
|
cutbuffer = NULL;
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
add_undo(COUPLE_BEGIN, operation);
|
|
||||||
|
|
||||||
/* Cut either the marked region or the whole buffer. */
|
/* Cut either the marked region or the whole buffer. */
|
||||||
add_undo(action, NULL);
|
add_undo(action, NULL);
|
||||||
do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
|
do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
|
||||||
@ -2060,6 +2109,7 @@ bool replace_buffer(const char *filename, undo_type action, const char *operatio
|
|||||||
/* Execute the given program, with the given temp file as last argument. */
|
/* Execute the given program, with the given temp file as last argument. */
|
||||||
void treat(char *tempfile_name, char *theprogram, bool spelling)
|
void treat(char *tempfile_name, char *theprogram, bool spelling)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_FORK) && defined(HAVE_WAIT)
|
||||||
ssize_t was_lineno = openfile->current->lineno;
|
ssize_t was_lineno = openfile->current->lineno;
|
||||||
size_t was_pww = openfile->placewewant;
|
size_t was_pww = openfile->placewewant;
|
||||||
size_t was_x = openfile->current_x;
|
size_t was_x = openfile->current_x;
|
||||||
@ -2089,8 +2139,11 @@ void treat(char *tempfile_name, char *theprogram, bool spelling)
|
|||||||
timestamp_nsec = (long)fileinfo.st_mtim.tv_nsec;
|
timestamp_nsec = (long)fileinfo.st_mtim.tv_nsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exit from curses mode to give the program control of the terminal. */
|
/* The spell checker needs the screen, so exit from curses mode. */
|
||||||
endwin();
|
if (spelling)
|
||||||
|
endwin();
|
||||||
|
else
|
||||||
|
statusbar(_("Invoking formatter..."));
|
||||||
|
|
||||||
construct_argument_list(&arguments, theprogram, tempfile_name);
|
construct_argument_list(&arguments, theprogram, tempfile_name);
|
||||||
|
|
||||||
@ -2110,9 +2163,13 @@ void treat(char *tempfile_name, char *theprogram, bool spelling)
|
|||||||
|
|
||||||
errornumber = errno;
|
errornumber = errno;
|
||||||
|
|
||||||
/* Restore the terminal state and reenter curses mode. */
|
/* After spell checking, restore terminal state and reenter curses mode;
|
||||||
terminal_init();
|
* after formatting, make sure that any formatter output is wiped. */
|
||||||
doupdate();
|
if (spelling) {
|
||||||
|
terminal_init();
|
||||||
|
doupdate();
|
||||||
|
} else
|
||||||
|
full_refresh();
|
||||||
|
|
||||||
if (thepid < 0) {
|
if (thepid < 0) {
|
||||||
statusline(ALERT, _("Could not fork: %s"), strerror(errornumber));
|
statusline(ALERT, _("Could not fork: %s"), strerror(errornumber));
|
||||||
@ -2154,14 +2211,9 @@ void treat(char *tempfile_name, char *theprogram, bool spelling)
|
|||||||
openfile->mark = line_from_number(was_mark_lineno);
|
openfile->mark = line_from_number(was_mark_lineno);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
openfile->current = openfile->filetop;
|
|
||||||
openfile->current_x = 0;
|
|
||||||
|
|
||||||
replaced = replace_buffer(tempfile_name, CUT_TO_EOF,
|
replaced = replace_buffer(tempfile_name, CUT_TO_EOF,
|
||||||
/* TRANSLATORS: The next two go with Undid/Redid messages. */
|
/* TRANSLATORS: The next two go with Undid/Redid messages. */
|
||||||
(spelling ? N_("spelling correction") : N_("formatting")));
|
(spelling ? N_("spelling correction") : N_("formatting")));
|
||||||
}
|
|
||||||
|
|
||||||
/* Go back to the old position. */
|
/* Go back to the old position. */
|
||||||
goto_line_posx(was_lineno, was_x);
|
goto_line_posx(was_lineno, was_x);
|
||||||
@ -2182,8 +2234,9 @@ void treat(char *tempfile_name, char *theprogram, bool spelling)
|
|||||||
statusline(REMARK, _("Finished checking spelling"));
|
statusline(REMARK, _("Finished checking spelling"));
|
||||||
else
|
else
|
||||||
statusline(REMARK, _("Buffer has been processed"));
|
statusline(REMARK, _("Buffer has been processed"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_SPELLER || ENABLE_COLOR */
|
#endif /* ENABLE_SPELLER || ENABLE_FORMATTER */
|
||||||
|
|
||||||
#ifdef ENABLE_SPELLER
|
#ifdef ENABLE_SPELLER
|
||||||
/* Let the user edit the misspelled word. Return FALSE if the user cancels. */
|
/* Let the user edit the misspelled word. Return FALSE if the user cancels. */
|
||||||
@ -2294,12 +2347,14 @@ bool fix_spello(const char *word)
|
|||||||
* correction. */
|
* correction. */
|
||||||
void do_int_speller(const char *tempfile_name)
|
void do_int_speller(const char *tempfile_name)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
|
||||||
char *misspellings, *pointer, *oneword;
|
char *misspellings, *pointer, *oneword;
|
||||||
long pipesize;
|
long pipesize;
|
||||||
size_t buffersize, bytesread, totalread;
|
size_t buffersize, bytesread, totalread;
|
||||||
int spell_fd[2], sort_fd[2], uniq_fd[2], tempfile_fd = -1;
|
int spell_fd[2], sort_fd[2], uniq_fd[2], tempfile_fd = -1;
|
||||||
pid_t pid_spell, pid_sort, pid_uniq;
|
pid_t pid_spell, pid_sort, pid_uniq;
|
||||||
int spell_status, sort_status, uniq_status;
|
int spell_status, sort_status, uniq_status;
|
||||||
|
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
||||||
|
|
||||||
/* Create all three pipes up front. */
|
/* Create all three pipes up front. */
|
||||||
if (pipe(spell_fd) == -1 || pipe(sort_fd) == -1 || pipe(uniq_fd) == -1) {
|
if (pipe(spell_fd) == -1 || pipe(sort_fd) == -1 || pipe(uniq_fd) == -1) {
|
||||||
@ -2424,6 +2479,9 @@ void do_int_speller(const char *tempfile_name)
|
|||||||
terminal_init();
|
terminal_init();
|
||||||
doupdate();
|
doupdate();
|
||||||
|
|
||||||
|
/* Save the settings of the global flags. */
|
||||||
|
memcpy(stash, flags, sizeof(flags));
|
||||||
|
|
||||||
/* Do any replacements case-sensitively, forward, and without regexes. */
|
/* Do any replacements case-sensitively, forward, and without regexes. */
|
||||||
SET(CASE_SENSITIVE);
|
SET(CASE_SENSITIVE);
|
||||||
UNSET(BACKWARDS_SEARCH);
|
UNSET(BACKWARDS_SEARCH);
|
||||||
@ -2454,6 +2512,9 @@ void do_int_speller(const char *tempfile_name)
|
|||||||
free(misspellings);
|
free(misspellings);
|
||||||
refresh_needed = TRUE;
|
refresh_needed = TRUE;
|
||||||
|
|
||||||
|
/* Restore the settings of the global flags. */
|
||||||
|
memcpy(flags, stash, sizeof(flags));
|
||||||
|
|
||||||
/* Process the end of the three processes. */
|
/* Process the end of the three processes. */
|
||||||
waitpid(pid_spell, &spell_status, 0);
|
waitpid(pid_spell, &spell_status, 0);
|
||||||
waitpid(pid_sort, &sort_status, 0);
|
waitpid(pid_sort, &sort_status, 0);
|
||||||
@ -2467,6 +2528,7 @@ void do_int_speller(const char *tempfile_name)
|
|||||||
statusline(ALERT, _("Error invoking \"spell\""));
|
statusline(ALERT, _("Error invoking \"spell\""));
|
||||||
else
|
else
|
||||||
statusline(REMARK, _("Finished checking spelling"));
|
statusline(REMARK, _("Finished checking spelling"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spell check the current file. If an alternate spell checker is
|
/* Spell check the current file. If an alternate spell checker is
|
||||||
@ -2475,7 +2537,6 @@ void do_spell(void)
|
|||||||
{
|
{
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
char *temp_name;
|
char *temp_name;
|
||||||
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
|
||||||
bool okay;
|
bool okay;
|
||||||
|
|
||||||
ran_a_tool = TRUE;
|
ran_a_tool = TRUE;
|
||||||
@ -2490,12 +2551,6 @@ void do_spell(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the settings of the global flags. */
|
|
||||||
memcpy(stash, flags, sizeof(flags));
|
|
||||||
|
|
||||||
/* Don't add an extra newline when writing out the (selected) text. */
|
|
||||||
SET(NO_NEWLINES);
|
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (openfile->mark)
|
if (openfile->mark)
|
||||||
okay = write_region_to_file(temp_name, stream, TEMPORARY, OVERWRITE);
|
okay = write_region_to_file(temp_name, stream, TEMPORARY, OVERWRITE);
|
||||||
@ -2505,6 +2560,7 @@ void do_spell(void)
|
|||||||
|
|
||||||
if (!okay) {
|
if (!okay) {
|
||||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||||
|
unlink(temp_name);
|
||||||
free(temp_name);
|
free(temp_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2519,19 +2575,17 @@ void do_spell(void)
|
|||||||
unlink(temp_name);
|
unlink(temp_name);
|
||||||
free(temp_name);
|
free(temp_name);
|
||||||
|
|
||||||
/* Restore the settings of the global flags. */
|
|
||||||
memcpy(flags, stash, sizeof(flags));
|
|
||||||
|
|
||||||
/* Ensure the help lines will be redrawn and a selection is retained. */
|
/* Ensure the help lines will be redrawn and a selection is retained. */
|
||||||
currmenu = MMOST;
|
currmenu = MMOST;
|
||||||
shift_held = TRUE;
|
shift_held = TRUE;
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_SPELLER */
|
#endif /* ENABLE_SPELLER */
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_LINTER
|
||||||
/* Run a linting program on the current buffer. */
|
/* Run a linting program on the current buffer. */
|
||||||
void do_linter(void)
|
void do_linter(void)
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
|
||||||
char *lintings, *pointer, *onelint;
|
char *lintings, *pointer, *onelint;
|
||||||
long pipesize;
|
long pipesize;
|
||||||
size_t buffersize, bytesread, totalread;
|
size_t buffersize, bytesread, totalread;
|
||||||
@ -2558,12 +2612,12 @@ void do_linter(void)
|
|||||||
edit_refresh();
|
edit_refresh();
|
||||||
|
|
||||||
if (openfile->modified) {
|
if (openfile->modified) {
|
||||||
int choice = do_yesno_prompt(FALSE, _("Save modified buffer before linting?"));
|
int choice = ask_user(YESORNO, _("Save modified buffer before linting?"));
|
||||||
|
|
||||||
if (choice == -1) {
|
if (choice == CANCEL) {
|
||||||
statusbar(_("Cancelled"));
|
statusbar(_("Cancelled"));
|
||||||
return;
|
return;
|
||||||
} else if (choice == 1 && (write_it_out(FALSE, FALSE) != 1))
|
} else if (choice == YES && (write_it_out(FALSE, FALSE) != 1))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2647,36 +2701,31 @@ void do_linter(void)
|
|||||||
if ((*pointer == '\r') || (*pointer == '\n')) {
|
if ((*pointer == '\r') || (*pointer == '\n')) {
|
||||||
*pointer = '\0';
|
*pointer = '\0';
|
||||||
if (onelint != pointer) {
|
if (onelint != pointer) {
|
||||||
char *filename = NULL, *linestr = NULL, *maybecol = NULL;
|
char *filename, *linestring, *colstring;
|
||||||
char *message = copy_of(onelint);
|
char *complaint = copy_of(onelint);
|
||||||
|
char *spacer = strstr(complaint, " ");
|
||||||
|
|
||||||
/* The recognized format is "filename:line:column: message",
|
/* The recognized format is "filename:line:column: message",
|
||||||
* where ":column" may be absent or be ",column" instead. */
|
* where ":column" may be absent or be ",column" instead. */
|
||||||
if (strstr(message, ": ") != NULL) {
|
if ((filename = strtok(onelint, ":")) && spacer) {
|
||||||
filename = strtok(onelint, ":");
|
if ((linestring = strtok(NULL, ":"))) {
|
||||||
if ((linestr = strtok(NULL, ":")) != NULL) {
|
if ((colstring = strtok(NULL, " "))) {
|
||||||
if ((maybecol = strtok(NULL, ":")) != NULL) {
|
ssize_t linenumber = strtol(linestring, NULL, 10);
|
||||||
ssize_t tmplineno = 0, tmpcolno = 0;
|
ssize_t colnumber = strtol(colstring, NULL, 10);
|
||||||
char *tmplinecol;
|
|
||||||
|
|
||||||
tmplineno = strtol(linestr, NULL, 10);
|
if (linenumber <= 0) {
|
||||||
if (tmplineno <= 0) {
|
free(complaint);
|
||||||
pointer++;
|
pointer++;
|
||||||
free(message);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpcolno = strtol(maybecol, NULL, 10);
|
if (colnumber <= 0) {
|
||||||
/* Check if the middle field is in comma format. */
|
colnumber = 1;
|
||||||
if (tmpcolno <= 0) {
|
strtok(linestring, ",");
|
||||||
strtok(linestr, ",");
|
if ((colstring = strtok(NULL, ",")))
|
||||||
if ((tmplinecol = strtok(NULL, ",")) != NULL)
|
colnumber = strtol(colstring, NULL, 10);
|
||||||
tmpcolno = strtol(tmplinecol, NULL, 10);
|
|
||||||
else
|
|
||||||
tmpcolno = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nice. We have a lint message we can use. */
|
|
||||||
parsesuccess = TRUE;
|
parsesuccess = TRUE;
|
||||||
tmplint = curlint;
|
tmplint = curlint;
|
||||||
curlint = nmalloc(sizeof(lintstruct));
|
curlint = nmalloc(sizeof(lintstruct));
|
||||||
@ -2684,17 +2733,17 @@ void do_linter(void)
|
|||||||
curlint->prev = tmplint;
|
curlint->prev = tmplint;
|
||||||
if (curlint->prev != NULL)
|
if (curlint->prev != NULL)
|
||||||
curlint->prev->next = curlint;
|
curlint->prev->next = curlint;
|
||||||
curlint->msg = copy_of(strstr(message, ": ") + 2);
|
|
||||||
curlint->lineno = tmplineno;
|
|
||||||
curlint->colno = tmpcolno;
|
|
||||||
curlint->filename = copy_of(filename);
|
curlint->filename = copy_of(filename);
|
||||||
|
curlint->lineno = linenumber;
|
||||||
|
curlint->colno = colnumber;
|
||||||
|
curlint->msg = copy_of(spacer + 1);
|
||||||
|
|
||||||
if (lints == NULL)
|
if (lints == NULL)
|
||||||
lints = curlint;
|
lints = curlint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(message);
|
free(complaint);
|
||||||
}
|
}
|
||||||
onelint = pointer + 1;
|
onelint = pointer + 1;
|
||||||
}
|
}
|
||||||
@ -2731,7 +2780,7 @@ void do_linter(void)
|
|||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
int kbinput;
|
int kbinput;
|
||||||
functionptrtype func;
|
functionptrtype function;
|
||||||
struct stat lintfileinfo;
|
struct stat lintfileinfo;
|
||||||
|
|
||||||
if (stat(curlint->filename, &lintfileinfo) != -1 &&
|
if (stat(curlint->filename, &lintfileinfo) != -1 &&
|
||||||
@ -2752,14 +2801,14 @@ void do_linter(void)
|
|||||||
|
|
||||||
sprintf(msg, _("This message is for unopened file %s,"
|
sprintf(msg, _("This message is for unopened file %s,"
|
||||||
" open it in a new buffer?"), curlint->filename);
|
" open it in a new buffer?"), curlint->filename);
|
||||||
choice = do_yesno_prompt(FALSE, msg);
|
choice = ask_user(YESORNO, msg);
|
||||||
currmenu = MLINTER;
|
currmenu = MLINTER;
|
||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
if (choice == -1) {
|
if (choice == CANCEL) {
|
||||||
statusbar(_("Cancelled"));
|
statusbar(_("Cancelled"));
|
||||||
break;
|
break;
|
||||||
} else if (choice == 1) {
|
} else if (choice == YES) {
|
||||||
open_buffer(curlint->filename, TRUE);
|
open_buffer(curlint->filename, TRUE);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
@ -2812,30 +2861,31 @@ void do_linter(void)
|
|||||||
confirm_margin();
|
confirm_margin();
|
||||||
#endif
|
#endif
|
||||||
edit_refresh();
|
edit_refresh();
|
||||||
statusline(NOTICE, curlint->msg);
|
statusline(NOTICE, "%s", curlint->msg);
|
||||||
bottombars(MLINTER);
|
bottombars(MLINTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place the cursor to indicate the affected line. */
|
/* Place the cursor to indicate the affected line. */
|
||||||
place_the_cursor();
|
place_the_cursor();
|
||||||
wnoutrefresh(edit);
|
UNFOLD_SEGMENT(openfile->current);
|
||||||
|
wnoutrefresh(midwin);
|
||||||
|
|
||||||
kbinput = get_kbinput(bottomwin, VISIBLE);
|
kbinput = get_kbinput(footwin, VISIBLE);
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
if (kbinput == KEY_WINCH)
|
if (kbinput == KEY_WINCH)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
func = func_from_key(&kbinput);
|
function = func_from_key(kbinput);
|
||||||
tmplint = curlint;
|
tmplint = curlint;
|
||||||
|
|
||||||
if (func == do_cancel || func == do_enter) {
|
if (function == do_cancel || function == do_enter) {
|
||||||
wipe_statusbar();
|
wipe_statusbar();
|
||||||
break;
|
break;
|
||||||
} else if (func == do_help) {
|
} else if (function == do_help) {
|
||||||
tmplint = NULL;
|
tmplint = NULL;
|
||||||
do_help();
|
do_help();
|
||||||
} else if (func == do_page_up || func == to_prev_block) {
|
} else if (function == do_page_up || function == to_prev_block) {
|
||||||
if (curlint->prev != NULL)
|
if (curlint->prev != NULL)
|
||||||
curlint = curlint->prev;
|
curlint = curlint->prev;
|
||||||
else if (last_wait != time(NULL)) {
|
else if (last_wait != time(NULL)) {
|
||||||
@ -2843,9 +2893,9 @@ void do_linter(void)
|
|||||||
beep();
|
beep();
|
||||||
napms(600);
|
napms(600);
|
||||||
last_wait = time(NULL);
|
last_wait = time(NULL);
|
||||||
statusline(NOTICE, curlint->msg);
|
statusline(NOTICE, "%s", curlint->msg);
|
||||||
}
|
}
|
||||||
} else if (func == do_page_down || func == to_next_block) {
|
} else if (function == do_page_down || function == to_next_block) {
|
||||||
if (curlint->next != NULL)
|
if (curlint->next != NULL)
|
||||||
curlint = curlint->next;
|
curlint = curlint->next;
|
||||||
else if (last_wait != time(NULL)) {
|
else if (last_wait != time(NULL)) {
|
||||||
@ -2853,7 +2903,7 @@ void do_linter(void)
|
|||||||
beep();
|
beep();
|
||||||
napms(600);
|
napms(600);
|
||||||
last_wait = time(NULL);
|
last_wait = time(NULL);
|
||||||
statusline(NOTICE, curlint->msg);
|
statusline(NOTICE, "%s", curlint->msg);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
beep();
|
beep();
|
||||||
@ -2876,8 +2926,11 @@ void do_linter(void)
|
|||||||
lastmessage = VACUUM;
|
lastmessage = VACUUM;
|
||||||
currmenu = MMOST;
|
currmenu = MMOST;
|
||||||
titlebar(NULL);
|
titlebar(NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif /* ENABLE_LINTER */
|
||||||
|
|
||||||
|
#ifdef ENABLE_FORMATTER
|
||||||
/* Run a manipulation program on the contents of the buffer. */
|
/* Run a manipulation program on the contents of the buffer. */
|
||||||
void do_formatter(void)
|
void do_formatter(void)
|
||||||
{
|
{
|
||||||
@ -2904,18 +2957,15 @@ void do_formatter(void)
|
|||||||
if (temp_name != NULL)
|
if (temp_name != NULL)
|
||||||
okay = write_file(temp_name, stream, TEMPORARY, OVERWRITE, NONOTES);
|
okay = write_file(temp_name, stream, TEMPORARY, OVERWRITE, NONOTES);
|
||||||
|
|
||||||
if (!okay) {
|
if (!okay)
|
||||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||||
free(temp_name);
|
else
|
||||||
return;
|
treat(temp_name, openfile->syntax->formatter, FALSE);
|
||||||
}
|
|
||||||
|
|
||||||
treat(temp_name, openfile->syntax->formatter, FALSE);
|
|
||||||
|
|
||||||
unlink(temp_name);
|
unlink(temp_name);
|
||||||
free(temp_name);
|
free(temp_name);
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_COLOR */
|
#endif /* ENABLE_FORMATTER */
|
||||||
|
|
||||||
#ifndef NANO_TINY
|
#ifndef NANO_TINY
|
||||||
/* Our own version of "wc". Note that the character count is in
|
/* Our own version of "wc". Note that the character count is in
|
||||||
@ -2959,7 +3009,7 @@ void count_lines_words_and_characters(void)
|
|||||||
* incrementing the word count for each successful step. */
|
* incrementing the word count for each successful step. */
|
||||||
while (openfile->current->lineno < botline->lineno ||
|
while (openfile->current->lineno < botline->lineno ||
|
||||||
(openfile->current == botline && openfile->current_x < bot_x)) {
|
(openfile->current == botline && openfile->current_x < bot_x)) {
|
||||||
if (do_next_word(FALSE))
|
if (do_next_word(FALSE, ALLOW_FOLDED))
|
||||||
words++;
|
words++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2982,12 +3032,19 @@ void do_verbatim_input(void)
|
|||||||
size_t count = 1;
|
size_t count = 1;
|
||||||
char *bytes;
|
char *bytes;
|
||||||
|
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
/* When barless and with cursor on bottom row, make room for the feedback. */
|
||||||
|
if (ISSET(ZERO) && openfile->current_y == editwinrows - 1 && LINES > 1) {
|
||||||
|
edit_scroll(FORWARD);
|
||||||
|
edit_refresh();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* TRANSLATORS: Shown when the next keystroke will be inserted verbatim. */
|
/* TRANSLATORS: Shown when the next keystroke will be inserted verbatim. */
|
||||||
statusline(INFO, _("Verbatim Input"));
|
statusline(INFO, _("Verbatim Input"));
|
||||||
place_the_cursor();
|
place_the_cursor();
|
||||||
|
|
||||||
/* Read in the first one or two bytes of the next keystroke. */
|
/* Read in the first one or two bytes of the next keystroke. */
|
||||||
bytes = get_verbatim_kbinput(edit, &count);
|
bytes = get_verbatim_kbinput(midwin, &count);
|
||||||
|
|
||||||
/* When something valid was obtained, unsuppress cursor-position display,
|
/* When something valid was obtained, unsuppress cursor-position display,
|
||||||
* insert the bytes into the edit buffer, and blank the status bar. */
|
* insert the bytes into the edit buffer, and blank the status bar. */
|
||||||
@ -2998,7 +3055,13 @@ void do_verbatim_input(void)
|
|||||||
if (count < 999)
|
if (count < 999)
|
||||||
inject(bytes, count);
|
inject(bytes, count);
|
||||||
|
|
||||||
wipe_statusbar();
|
#ifndef NANO_TINY
|
||||||
|
/* Ensure that the feedback will be overwritten, or clear it. */
|
||||||
|
if (ISSET(ZERO) && currmenu == MMAIN)
|
||||||
|
wredrawln(midwin, editwinrows - 1, 1);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
wipe_statusbar();
|
||||||
} else
|
} else
|
||||||
/* TRANSLATORS: An invalid verbatim Unicode code was typed. */
|
/* TRANSLATORS: An invalid verbatim Unicode code was typed. */
|
||||||
statusline(AHEM, _("Invalid code"));
|
statusline(AHEM, _("Invalid code"));
|
||||||
@ -3026,12 +3089,14 @@ char *copy_completion(char *text)
|
|||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look at the fragment the user has typed, then search the current buffer for
|
/* Look at the fragment the user has typed, then search all buffers for
|
||||||
* the first word that starts with this fragment, and tentatively complete the
|
* the first word that starts with this fragment, and tentatively complete the
|
||||||
* fragment. If the user types 'Complete' again, search and paste the next
|
* fragment. If the user types 'Complete' again, search and paste the next
|
||||||
* possible completion. */
|
* possible completion. */
|
||||||
void complete_a_word(void)
|
void complete_a_word(void)
|
||||||
{
|
{
|
||||||
|
static openfilestruct *scouring = NULL;
|
||||||
|
/* The buffer that is being searched for possible completions. */
|
||||||
char *shard, *completion = NULL;
|
char *shard, *completion = NULL;
|
||||||
size_t start_of_shard, shard_length = 0;
|
size_t start_of_shard, shard_length = 0;
|
||||||
size_t i = 0, j = 0;
|
size_t i = 0, j = 0;
|
||||||
@ -3054,6 +3119,7 @@ void complete_a_word(void)
|
|||||||
openfile->last_action = OTHER;
|
openfile->last_action = OTHER;
|
||||||
|
|
||||||
/* Initialize the starting point for searching. */
|
/* Initialize the starting point for searching. */
|
||||||
|
scouring = openfile;
|
||||||
pletion_line = openfile->filetop;
|
pletion_line = openfile->filetop;
|
||||||
pletion_x = 0;
|
pletion_x = 0;
|
||||||
|
|
||||||
@ -3165,9 +3231,17 @@ void complete_a_word(void)
|
|||||||
|
|
||||||
pletion_line = pletion_line->next;
|
pletion_line = pletion_line->next;
|
||||||
pletion_x = 0;
|
pletion_x = 0;
|
||||||
|
|
||||||
|
#ifdef ENABLE_MULTIBUFFER
|
||||||
|
/* When at end of buffer and there is another, search that one. */
|
||||||
|
if (pletion_line == NULL && scouring->next != openfile) {
|
||||||
|
scouring = scouring->next;
|
||||||
|
pletion_line = scouring->filetop;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The search has reached the end of the file. */
|
/* The search has gone through all buffers. */
|
||||||
if (list_of_completions != NULL) {
|
if (list_of_completions != NULL) {
|
||||||
edit_refresh();
|
edit_refresh();
|
||||||
statusline(AHEM, _("No further matches"));
|
statusline(AHEM, _("No further matches"));
|
||||||
|
|||||||
47
src/utils.c
47
src/utils.c
@ -1,7 +1,7 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* utils.c -- This file is part of GNU nano. *
|
* utils.c -- This file is part of GNU nano. *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
* Copyright (C) 1999-2011, 2013-2023 Free Software Foundation, Inc. *
|
||||||
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
||||||
* *
|
* *
|
||||||
* GNU nano is free software: you can redistribute it and/or modify *
|
* GNU nano is free software: you can redistribute it and/or modify *
|
||||||
@ -130,14 +130,14 @@ bool parse_num(const char *string, ssize_t *result)
|
|||||||
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
||||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||||
{
|
{
|
||||||
bool retval;
|
|
||||||
char *firstpart;
|
|
||||||
const char *comma;
|
const char *comma;
|
||||||
|
char *firstpart;
|
||||||
|
bool retval;
|
||||||
|
|
||||||
while (*str == ' ')
|
while (*str == ' ')
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
comma = strpbrk(str, "m,. /;");
|
comma = strpbrk(str, ",.:");
|
||||||
|
|
||||||
if (comma == NULL)
|
if (comma == NULL)
|
||||||
return parse_num(str, line);
|
return parse_num(str, line);
|
||||||
@ -168,14 +168,19 @@ void recode_NUL_to_LF(char *string, size_t length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the given string, recode each embedded newline as a NUL. */
|
/* In the given string, recode each embedded newline as a NUL,
|
||||||
void recode_LF_to_NUL(char *string)
|
* and return the number of bytes in the string. */
|
||||||
|
size_t recode_LF_to_NUL(char *string)
|
||||||
{
|
{
|
||||||
|
char *beginning = string;
|
||||||
|
|
||||||
while (*string != '\0') {
|
while (*string != '\0') {
|
||||||
if (*string == '\n')
|
if (*string == '\n')
|
||||||
*string = '\0';
|
*string = '\0';
|
||||||
string++;
|
string++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (string - beginning);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||||
@ -282,34 +287,26 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
|||||||
return mbstrcasestr(start, needle);
|
return mbstrcasestr(start, needle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a wrapper for the malloc() function that properly handles
|
/* Allocate the given amount of memory and return a pointer to it. */
|
||||||
* things when we run out of memory. */
|
|
||||||
void *nmalloc(size_t howmuch)
|
void *nmalloc(size_t howmuch)
|
||||||
{
|
{
|
||||||
void *r = malloc(howmuch);
|
void *section = malloc(howmuch);
|
||||||
|
|
||||||
if (howmuch == 0)
|
if (section == NULL)
|
||||||
die("Allocating zero bytes. Please report a bug.\n");
|
|
||||||
|
|
||||||
if (r == NULL)
|
|
||||||
die(_("Nano is out of memory!\n"));
|
die(_("Nano is out of memory!\n"));
|
||||||
|
|
||||||
return r;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a wrapper for the realloc() function that properly handles
|
/* Reallocate the given section of memory to have the given size. */
|
||||||
* things when we run out of memory. */
|
void *nrealloc(void *section, size_t howmuch)
|
||||||
void *nrealloc(void *ptr, size_t howmuch)
|
|
||||||
{
|
{
|
||||||
void *r = realloc(ptr, howmuch);
|
section = realloc(section, howmuch);
|
||||||
|
|
||||||
if (howmuch == 0)
|
if (section == NULL)
|
||||||
die("Allocating zero bytes. Please report a bug.\n");
|
|
||||||
|
|
||||||
if (r == NULL)
|
|
||||||
die(_("Nano is out of memory!\n"));
|
die(_("Nano is out of memory!\n"));
|
||||||
|
|
||||||
return r;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return an appropriately reallocated dest string holding a copy of src.
|
/* Return an appropriately reallocated dest string holding a copy of src.
|
||||||
@ -492,7 +489,9 @@ void get_range(linestruct **top, linestruct **bot)
|
|||||||
also_the_last = TRUE;
|
also_the_last = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* !NANO_TINY */
|
||||||
|
|
||||||
|
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||||
/* Return a pointer to the line that has the given line number. */
|
/* Return a pointer to the line that has the given line number. */
|
||||||
linestruct *line_from_number(ssize_t number)
|
linestruct *line_from_number(ssize_t number)
|
||||||
{
|
{
|
||||||
@ -507,7 +506,7 @@ linestruct *line_from_number(ssize_t number)
|
|||||||
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
#endif /* !NANO_TINY */
|
#endif
|
||||||
|
|
||||||
/* Count the number of characters from begin to end, and return it. */
|
/* Count the number of characters from begin to end, and return it. */
|
||||||
size_t number_of_characters_in(const linestruct *begin, const linestruct *end)
|
size_t number_of_characters_in(const linestruct *begin, const linestruct *end)
|
||||||
|
|||||||
1217
src/winio.c
1217
src/winio.c
File diff suppressed because it is too large
Load Diff
@ -26,10 +26,10 @@ color magenta "\<(break|continue|goto|return)\>"
|
|||||||
color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'"
|
color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'"
|
||||||
|
|
||||||
# GCC builtins.
|
# GCC builtins.
|
||||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||||
|
|
||||||
# Strings and names of included files.
|
# Strings and names of included files.
|
||||||
color brightyellow ""([^"]|\\")*"" "#[[:blank:]]*include[[:blank:]]*<[^>]+>"
|
color brightyellow ""([^"]|\\")*"|#[[:blank:]]*include[[:blank:]]*<[^>]+>"
|
||||||
|
|
||||||
# Preprocessor directives.
|
# Preprocessor directives.
|
||||||
color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$"
|
color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$"
|
||||||
|
|||||||
@ -8,8 +8,8 @@ comment "#"
|
|||||||
color ,red " + +"
|
color ,red " + +"
|
||||||
|
|
||||||
# Nano's release motto, then name plus version.
|
# Nano's release motto, then name plus version.
|
||||||
color italic,lime "\<[Nn]ano [1-6]\.[0-9][-.[:alnum:]]* "[^"]+""
|
color italic,lime "\<[Nn]ano [1-7]\.[0-9][-.[:alnum:]]* "[^"]+""
|
||||||
color brightred "\<(GNU )?[Nn]ano [1-6]\.[0-9][-.[:alnum:]]*\>"
|
color brightred "\<(GNU )?[Nn]ano [1-7]\.[0-9][-.[:alnum:]]*\>"
|
||||||
|
|
||||||
# Dates
|
# Dates
|
||||||
color latte "\<[12][0-9]{3}\.(0[1-9]|1[012])\.(0[1-9]|[12][0-9]|3[01])\>"
|
color latte "\<[12][0-9]{3}\.(0[1-9]|1[012])\.(0[1-9]|[12][0-9]|3[01])\>"
|
||||||
@ -18,7 +18,7 @@ color latte "\<[12][0-9]{3}\.(0[1-9]|1[012])\.(0[1-9]|[12][0-9]|3[01])\>"
|
|||||||
color magenta "<[[:alnum:].%_+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}>"
|
color magenta "<[[:alnum:].%_+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}>"
|
||||||
|
|
||||||
# URLs.
|
# URLs.
|
||||||
color lightblue "\<https?://\S+\.\S+[^[:space:],.)]"
|
color lightblue "\<https?://\S+\.\S+[^])>[:space:],.]"
|
||||||
|
|
||||||
# Bracketed captions in certain config files.
|
# Bracketed captions in certain config files.
|
||||||
color brightgreen "^\[[^][]+\]$"
|
color brightgreen "^\[[^][]+\]$"
|
||||||
|
|||||||
@ -3,23 +3,23 @@
|
|||||||
syntax groff "\.(m[ems]|rof|tmac)$|/tmac\.[^/]+$"
|
syntax groff "\.(m[ems]|rof|tmac)$|/tmac\.[^/]+$"
|
||||||
comment ".\""
|
comment ".\""
|
||||||
|
|
||||||
# The argument of .ds or .nr
|
# The setting of a string or register
|
||||||
color cyan "^\.(ds|nr) [^[:space:]]*"
|
color cyan "^\.(ds|nr) [^[:space:]]*"
|
||||||
# Single-character escapes
|
# Single-character escapes
|
||||||
color brightmagenta "\\."
|
color brightmagenta "\\."
|
||||||
# The argument of \f or \s in the same color
|
# The argument of \f or \s in the same color
|
||||||
color brightmagenta "\\f(.|\(..)" "\\s(\+|\-)?[0-9]"
|
color brightmagenta "\\f(.|\(..)|\\s(\+|\-)?[0-9]"
|
||||||
# Newlines
|
# References to registers
|
||||||
color cyan "\\(\\)?n(.|\(..)"
|
color cyan "\\(\\)?n(.|\(..)"
|
||||||
color cyan start="\\(\\)?n\[" end="]"
|
color cyan start="\\(\\)?n\[" end="]"
|
||||||
# Requests
|
# Requests
|
||||||
color brightgreen "^\.[[:blank:]]*[^[:space:]]*"
|
color brightgreen "^\.[[:blank:]]*[^[:space:]]*"
|
||||||
# Comments
|
# Comments
|
||||||
color yellow "^\.\\".*"
|
color yellow "^\.\\".*"
|
||||||
# Strings
|
# References to strings
|
||||||
color green "\\(\\)?\*(.|\(..)"
|
color green "\\(\\)?\*(.|\(..)"
|
||||||
color green start="\\(\\)?\*\[" end="]"
|
color green start="\\(\\)?\*\[" end="]"
|
||||||
# Characters
|
# Special characters
|
||||||
color brightred "\\\(.."
|
color brightred "\\\(.."
|
||||||
color brightred start="\\\[" end="]"
|
color brightred start="\\\[" end="]"
|
||||||
# Macro arguments
|
# Macro arguments
|
||||||
|
|||||||
@ -8,8 +8,8 @@ formatter tidy -m -q
|
|||||||
|
|
||||||
# Tags:
|
# Tags:
|
||||||
color cyan "<[[:alpha:]/!?][^>]*>"
|
color cyan "<[[:alpha:]/!?][^>]*>"
|
||||||
# Bold, italic, and underlined:
|
# Bold, italic, underlined, emphasis, and importance:
|
||||||
color brightmagenta "</?[biu]>"
|
color brightmagenta "</?(b|i|u|em|strong)>"
|
||||||
|
|
||||||
# Named character references:
|
# Named character references:
|
||||||
color red "&[^;[:space:]]*;"
|
color red "&[^;[:space:]]*;"
|
||||||
|
|||||||
@ -22,9 +22,8 @@ color green "\<(true|false|null)\>"
|
|||||||
color brightblue ""[^"]+"[[:blank:]]*:"
|
color brightblue ""[^"]+"[[:blank:]]*:"
|
||||||
|
|
||||||
# Brackets, braces, and separators.
|
# Brackets, braces, and separators.
|
||||||
color brightblue "\[" "\]"
|
color brightblue "[][]"
|
||||||
color brightred "\{" "\}"
|
color brightred "[{},:]"
|
||||||
color brightred "," ":"
|
|
||||||
|
|
||||||
# Comments.
|
# Comments.
|
||||||
color cyan "(^|[[:blank:]]+)(//|#).*"
|
color cyan "(^|[[:blank:]]+)(//|#).*"
|
||||||
|
|||||||
@ -6,10 +6,10 @@ comment ".\""
|
|||||||
|
|
||||||
# Section headers, title line, and indented paragraphs.
|
# Section headers, title line, and indented paragraphs.
|
||||||
color green "^\.(SH|SS|TH) .*"
|
color green "^\.(SH|SS|TH) .*"
|
||||||
color brightgreen "^\.(SH|SS|TH) " "^\.([HIT]P)"
|
color brightgreen "^\.((SH|SS|TH) |[HIT]P)"
|
||||||
# Type faces, and normal paragraphs.
|
# Type faces, and normal paragraphs.
|
||||||
color brightred "^\.(B[IR]?|I[BR]?|R[BI]|S[BM]) .*"
|
color brightred "^\.(B[IR]?|I[BR]?|R[BI]|S[BM]) .*"
|
||||||
color brightblue "^\.(B[IR]?|I[BR]?|R[BI]|S[BM]) " "^\.([LP]?P)$"
|
color brightblue "^\.((B[IR]?|I[BR]?|R[BI]|S[BM]) |[LP]?P$)"
|
||||||
# Inline type faces.
|
# Inline type faces.
|
||||||
color magenta "\\f[BIPR]"
|
color magenta "\\f[BIPR]"
|
||||||
# Relative margins, hyperlinks, and various other stuff.
|
# Relative margins, hyperlinks, and various other stuff.
|
||||||
|
|||||||
@ -25,6 +25,16 @@ color brightgreen "^[[:blank:]]*(syntax[[:blank:]]+[^[:space:]]+|(formatter|lint
|
|||||||
# Strings
|
# Strings
|
||||||
color brightmagenta "[[:blank:]](start=)?".+""
|
color brightmagenta "[[:blank:]](start=)?".+""
|
||||||
|
|
||||||
|
# Function names in string binds
|
||||||
|
color crimson "\{(help|cancel|exit|savefile|writeout|discardbuffer|insert|where(is|was)|find(previous|next|bracket)|replace)\}"
|
||||||
|
color crimson "\{(cut|copy|paste|zap|chopword(left|right)|cutrestoffile|execute|mark|speller|linter|formatter|(full)?justify)\}"
|
||||||
|
color crimson "\{(location|gotoline|(begin|end)para|comment|complete|(un)?indent|wordcount|(record|run)macro|anchor|undo|redo)\}"
|
||||||
|
color crimson "\{(left|right|up|down|home|end|(scroll|page)(up|down)|center|(prev|next)(word|block|anchor|buf))\}"
|
||||||
|
color crimson "\{(tab|enter|delete|backspace|verbatim|refresh|suspend|casesens|regexp|backwards|older|newer|(dos|mac)format)\}"
|
||||||
|
color crimson "\{(append|prepend|backup|flip(goto|replace|execute|pipe|convert|newbuffer)|browser|gotodir|(first|last)(file|line))\}"
|
||||||
|
color crimson "\{(nohelp|constantshow|softwrap|linenumbers|whitespacedisplay|nosyntax|zero)\}"
|
||||||
|
color crimson "\{(smarthome|autoindent|cutfromcursor|breaklonglines|tabstospaces|mouse|\{)\}"
|
||||||
|
|
||||||
# Commands
|
# Commands
|
||||||
color green "^[[:blank:]]*((un)?(bind|set)|include|syntax|header|magic|comment|formatter|linter|tabgives|extendsyntax)\>"
|
color green "^[[:blank:]]*((un)?(bind|set)|include|syntax|header|magic|comment|formatter|linter|tabgives|extendsyntax)\>"
|
||||||
color magenta "^[[:blank:]]*i?color\>|[[:blank:]](start=|end=)"
|
color magenta "^[[:blank:]]*i?color\>|[[:blank:]](start=|end=)"
|
||||||
|
|||||||
@ -15,7 +15,7 @@ color brightgreen "\<(goto|continue|break|return)\>"
|
|||||||
color brightgreen "@(encode|end|implementation|interface)|selector)\>"
|
color brightgreen "@(encode|end|implementation|interface)|selector)\>"
|
||||||
|
|
||||||
# GCC builtins.
|
# GCC builtins.
|
||||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||||
|
|
||||||
# Selector/method.
|
# Selector/method.
|
||||||
color brightmagenta "(^|[[:blank:]])\[.*[[:blank:]].*\]"
|
color brightmagenta "(^|[[:blank:]])\[.*[[:blank:]].*\]"
|
||||||
|
|||||||
@ -5,8 +5,22 @@ header "^#!.*perl"
|
|||||||
magic "Perl script"
|
magic "Perl script"
|
||||||
comment "#"
|
comment "#"
|
||||||
|
|
||||||
color red "\<(accept|alarm|atan2|bin(d|mode)|c(aller|h(dir|mod|op|own|root)|lose(dir)?|onnect|os|rypt)|d(bm(close|open)|efined|elete|ie|o|ump)|e(ach|of|val|x(ec|ists|it|p))|f(cntl|ileno|lock|ork))\>" "\<(get(c|login|peername|pgrp|ppid|priority|pwnam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport)|([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|gmtime|goto|grep|hex|index|int|ioctl|join)\>" "\<(keys|kill|last|length|link|listen|local(time)?|log|lstat|m|mkdir|msg(ctl|get|snd|rcv)|next|oct|open(dir)?|ord|pack|pipe|pop|printf?|push|q|qq|qx|rand|re(ad(dir|link)?|cv|do|name|quire|set|turn|verse|winddir)|rindex|rmdir|s|scalar|seek(dir)?)\>" "\<(se(lect|mctl|mget|mop|nd|tpgrp|tpriority|tsockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|spli(ce|t)|sprintf|sqrt|srand|stat|study|substr|symlink|sys(call|read|tem|write)|tell(dir)?|time|tr(y)?|truncate|umask)\>" "\<(un(def|link|pack|shift)|utime|values|vec|wait(pid)?|wantarray|warn|write)\>"
|
# Functions.
|
||||||
color magenta "\<(continue|else|elsif|do|for|foreach|if|unless|until|while|eq|ne|lt|gt|le|ge|cmp|x|my|sub|use|package|can|isa)\>"
|
color red "\<(abs|accept|alarm|atan2|bin(d|mode)|bless|caller|ch(dir|mod|op|omp|own|r|root)|close(dir)?|connect|cos|crypt)\>"
|
||||||
|
color red "\<(dbm(close|open)|defined|delete|dump|each|eof|eval(bytes)?|exec|exists|exp|fc|fcntl|fileno|flock|fork|format|formline)\>"
|
||||||
|
color red "\<(get(c|login|peername|pgrp|ppid|priority|(gr|pw)nam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport))\>"
|
||||||
|
color red "\<(([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|glob|gmtime|grep|hex|import|index|int|ioctl|join)\>"
|
||||||
|
color red "\<(keys|kill|lc|lcfirst|length|link|listen|local(time)?|lock|log|lstat|map|mkdir|msg(ctl|get|snd|rcv)|oct)\>"
|
||||||
|
color red "\<(open(dir)?|ord|pack|pipe|pop|pos|printf?|prototype|push|q|qq|qr|qx|qw|quotemeta|rand|read(dir|line|link|pipe)?)\>"
|
||||||
|
color red "\<(recv|redo|ref|rename|require|reset|reverse|rewinddir|rindex|rmdir|say|scalar|seek(dir)?|select|sem(ctl|get|op))\>"
|
||||||
|
color red "\<(send|set(pgrp|priority|sockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|splice|split)\>"
|
||||||
|
color red "\<(sprintf|sqrt|srand|state?|study|substr|symlink|sys(call|open|read|seek|tem|write)|tell(dir)?|tied?|times?|try?)\>"
|
||||||
|
color red "\<(truncate|uc|ucfirst|umask|un(def|link|pack|shift|tie)|utime|values|vec|wait(pid)?|wantarray|warn|write)\>"
|
||||||
|
|
||||||
|
# Control flow, logical operators, declarations.
|
||||||
|
color magenta "\<(continue|die|do|else|elsif|exit|for(each)?|fork|goto|if|last|next|return|unless|until|while)\>"
|
||||||
|
color magenta "\<(and|cmp|eq|ge|gt|isa|le|lt|ne|not|or|x|xor)\>"
|
||||||
|
color magenta "\<(my|no|our|package|sub|use)\>"
|
||||||
|
|
||||||
# Variable names.
|
# Variable names.
|
||||||
color cyan "[$%&@]([A-Za-z_][0-9A-Za-z_]*|\^[][A-Z?\^_]|[0-9]+)\>"
|
color cyan "[$%&@]([A-Za-z_][0-9A-Za-z_]*|\^[][A-Z?\^_]|[0-9]+)\>"
|
||||||
@ -14,8 +28,10 @@ color cyan "[$%&@]\{(\^?[A-Za-z_][0-9A-Za-z_]*|\^[][?\^][0-9]+)\}"
|
|||||||
color cyan "[$%&@]([][!"#'()*+,.:;<=>?`|~-]|\{[][!-/:-@\`|~]\})|\$[$%&@]"
|
color cyan "[$%&@]([][!"#'()*+,.:;<=>?`|~-]|\{[][!-/:-@\`|~]\})|\$[$%&@]"
|
||||||
color cyan "(^|[[:blank:]])[$%@][/\]"
|
color cyan "(^|[[:blank:]])[$%@][/\]"
|
||||||
|
|
||||||
|
# Strings.
|
||||||
color yellow "".*"|qq\|.*\|"
|
color yellow "".*"|qq\|.*\|"
|
||||||
color white "[sm]/.*/"
|
|
||||||
|
color white "[smy]/.*/"
|
||||||
color white start="(^use| = new)" end=";"
|
color white start="(^use| = new)" end=";"
|
||||||
|
|
||||||
# Comments.
|
# Comments.
|
||||||
|
|||||||
@ -5,6 +5,7 @@ header "^#!.*python"
|
|||||||
magic "Python script"
|
magic "Python script"
|
||||||
comment "#"
|
comment "#"
|
||||||
|
|
||||||
|
# Alternative linter: pylint --exit-zero
|
||||||
linter pyflakes
|
linter pyflakes
|
||||||
|
|
||||||
# Function definitions.
|
# Function definitions.
|
||||||
@ -23,6 +24,9 @@ color brightcyan "\<(exec|print)([[:blank:]]|$)"
|
|||||||
# Special values.
|
# Special values.
|
||||||
color brightmagenta "\<(False|None|True)\>"
|
color brightmagenta "\<(False|None|True)\>"
|
||||||
|
|
||||||
|
# Decorators.
|
||||||
|
color cyan "@[[:alpha:]_][[:alnum:]_.]*"
|
||||||
|
|
||||||
# Mono-quoted strings.
|
# Mono-quoted strings.
|
||||||
color brightgreen "'([^'\]|\\.)*'|"([^"\]|\\.)*"|'''|""""
|
color brightgreen "'([^'\]|\\.)*'|"([^"\]|\\.)*"|'''|""""
|
||||||
color normal "'''|""""
|
color normal "'''|""""
|
||||||
|
|||||||
@ -23,11 +23,11 @@ color brightmagenta "(/([^/]|\\/)*/|%r\{([^}]|\\\})*\})[iomx]*"
|
|||||||
color brightblue "`[^`]*`|%x\{[^}]*\}"
|
color brightblue "`[^`]*`|%x\{[^}]*\}"
|
||||||
|
|
||||||
# Strings, double-quoted.
|
# Strings, double-quoted.
|
||||||
color green ""([^"]|\\")*"" "%[QW]?(\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
color green ""([^"]|\\")*"|%[QW]?(\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
||||||
# Expression substitution for inside double-quoted strings, "like #{this}".
|
# Expression substitution for inside double-quoted strings, "like #{this}".
|
||||||
color brightgreen "#\{[^}]*\}"
|
color brightgreen "#\{[^}]*\}"
|
||||||
# Strings, single-quoted.
|
# Strings, single-quoted.
|
||||||
color green "'([^']|\\')*'" "%[qw](\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
color green "'([^']|\\')*'|%[qw](\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
||||||
|
|
||||||
# Comments.
|
# Comments.
|
||||||
color cyan "#([^{#].*|$)"
|
color cyan "#([^{#].*|$)"
|
||||||
|
|||||||
@ -25,7 +25,7 @@ color brightblue "\<(awk|cat|cd|ch(grp|mod|own)|cp|cut|echo|env|grep|head|instal
|
|||||||
color normal "[.-]tar\>"
|
color normal "[.-]tar\>"
|
||||||
|
|
||||||
# Basic variable names (no braces).
|
# Basic variable names (no braces).
|
||||||
color brightred "\$[-0-9@*#?$!]" "\$[[:alpha:]_][[:alnum:]_]*"
|
color brightred "\$([-@*#?$!0-9]|[[:alpha:]_][[:alnum:]_]*)"
|
||||||
# More complicated variable names; handles braces and replacements and arrays.
|
# More complicated variable names; handles braces and replacements and arrays.
|
||||||
color brightred "\$\{[#!]?([-@*#?$!]|[0-9]+|[[:alpha:]_][[:alnum:]_]*)(\[([[:blank:]]*[[:alnum:]_]+[[:blank:]]*|@)\])?(([#%/]|:?[-=?+])[^}]*\}|\[|\})"
|
color brightred "\$\{[#!]?([-@*#?$!]|[0-9]+|[[:alpha:]_][[:alnum:]_]*)(\[([[:blank:]]*[[:alnum:]_]+[[:blank:]]*|@)\])?(([#%/]|:?[-=?+])[^}]*\}|\[|\})"
|
||||||
|
|
||||||
|
|||||||
@ -5,18 +5,29 @@ magic "Tcl(/Tk)? script"
|
|||||||
comment "#"
|
comment "#"
|
||||||
|
|
||||||
# Standard Tcl [info commands]:
|
# Standard Tcl [info commands]:
|
||||||
color green "\<(after|append|array|auto_execok|auto_import|auto_load|auto_load_index|auto_qualify|binary|break|case|catch|cd|clock|close|concat|continue|encoding|eof|error|eval|exec|exit|expr|fblocked|fconfigure|fcopy|file|fileevent|flush|for|foreach|format|gets|glob|global|history|if|incr|info|interp|join|lappend|lindex|linsert|list|llength|load|lrange|lreplace|lsearch|lset|lsort|namespace|open|package|pid|puts|pwd|read|regexp|regsub|rename|return|scan|seek|set|socket|source|split|string|subst|switch|tclLog|tell|time|trace|unknown|unset|update|uplevel|upvar|variable|vwait|while)\>"
|
color green "\<(after|append|array|auto_(execok|import|load(_index)?|qualify)|binary|break)\>"
|
||||||
|
color green "\<(case|catch|cd|clock|close|concat|continue|encoding|eof|error|eval|exec|exit|expr)\>"
|
||||||
|
color green "\<(fblocked|fconfigure|fcopy|file(event)?|flush|for|foreach|format|gets|glob|global|history)\>"
|
||||||
|
color green "\<(if|incr|info|interp|join|lappend|lindex|linsert|list|llength|load|lrange|lreplace|lsearch|lset|lsort)\>"
|
||||||
|
color green "\<(namespace|open|package|pid|puts|pwd|read|regexp|regsub|rename|return)\>"
|
||||||
|
color green "\<(scan|seek|set|socket|source|split|string|subst|switch|tclLog|tell|time|trace)\>"
|
||||||
|
color green "\<(unknown|unset|update|uplevel|upvar|variable|vwait|while)\>"
|
||||||
|
|
||||||
# Basic Tcl subcommands:
|
# Basic Tcl subcommands:
|
||||||
color green "\<array (anymore|donesearch|exists|get|names|nextelement|set|size|startsearch|statistics|unset)\>"
|
color green "\<array (anymore|donesearch|exists|get|names|nextelement|set|size|startsearch|statistics|unset)\>"
|
||||||
color green "\<string (bytelength|compare|equal|first|index|is|last|length|map|match|range|repeat|replace|to|tolower|totitle|toupper|trim|trimleft|trimright|will|wordend|wordstart)\>"
|
color green "\<string (compare|equal|first|index|is|last|(byte)?length|map|match|range|repeat|replace|to(lower|title|upper)?|trim(left|right)?|will|word(end|start))\>"
|
||||||
|
|
||||||
# Extended TclX [info commands]:
|
# Extended TclX [info commands]:
|
||||||
color green "\<(alarm|auto_load_pkg|bsearch|catclose|catgets|catopen|ccollate|cconcat|cequal|chgrp|chmod|chown|chroot|cindex|clength|cmdtrace|commandloop|crange|csubstr|ctoken|ctype|dup|echo|execl|fcntl|flock|fork|fstat|ftruncate|funlock|host_info|id|infox|keyldel|keylget|keylkeys|keylset|kill|lassign|lcontain|lempty|lgets|link|lmatch|loadlibindex|loop|lvarcat|lvarpop|lvarpush|max|min|nice|pipe|profile|random|readdir|replicate|scancontext|scanfile|scanmatch|select|server_accept|server_create|signal|sleep|sync|system|tclx_findinit|tclx_fork|tclx_load_tndxs|tclx_sleep|tclx_system|tclx_wait|times|translit|try_eval|umask|wait)\>"
|
color green "\<(alarm|auto_load_pkg|bsearch|cat(close|gets|open)|ccollate|cconcat|cequal|chgrp|chmod|chown|chroot)\>"
|
||||||
|
color green "\<(cindex|clength|cmdtrace|commandloop|crange|csubstr|ctoken|ctype|dup|echo|execl)\>"
|
||||||
|
color green "\<(fcntl|flock|fork|fstat|ftruncate|funlock|host_info|id|infox|keyl(del|get|keys|set)|kill)\>"
|
||||||
|
color green "\<(lassign|lcontain|lempty|lgets|link|lmatch|loadlibindex|loop|lvar(cat|pop|push)|max|min|nice)\>"
|
||||||
|
color green "\<(pipe|profile|random|readdir|replicate|scan(context|file|match)|select|server_(accept|create)|signal)\>"
|
||||||
|
color green "\<(sleep|sync|system|tclx_(findinit|fork|load_tndxs|sleep|system|wait)|times|translit|try_eval|umask|wait)\>"
|
||||||
|
|
||||||
# Syntax:
|
# Syntax:
|
||||||
|
color green "[!$&();<=>\`|]"
|
||||||
color brightblue "\<proc[[:blank:]]|\{|\}"
|
color brightblue "\<proc[[:blank:]]|\{|\}"
|
||||||
color green "\(|\)|\;|`|\\|\$|<|>|!|=|&|\|"
|
|
||||||
color brightyellow ""([^"\]|\\.)*"|'([^'\]|\\.)*'"
|
color brightyellow ""([^"\]|\\.)*"|'([^'\]|\\.)*'"
|
||||||
color brightred "\$\{?[0-9A-Za-z_!@#$*?-]+\}?"
|
color brightred "\$\{?[0-9A-Za-z_!@#$*?-]+\}?"
|
||||||
|
|
||||||
|
|||||||
@ -5,18 +5,22 @@ header "<\?xml.*version=.*\?>"
|
|||||||
magic "(XML|SGML) (sub)?document"
|
magic "(XML|SGML) (sub)?document"
|
||||||
comment "<!--|-->"
|
comment "<!--|-->"
|
||||||
|
|
||||||
# The entire content of the tag:
|
# First the entire content of the tag (for the attributes):
|
||||||
color green start="<" end=">"
|
color green start="<" end=">"
|
||||||
|
|
||||||
# The start and the end of the tag:
|
# The angled brackets and the name of the tag:
|
||||||
color cyan "<[^> ]+" ">"
|
color cyan "<[^> ]+|/?>"
|
||||||
|
|
||||||
# The strings inside the tag:
|
# The strings inside the tag:
|
||||||
color magenta ""[^"]*""
|
color magenta ""[^"]*""
|
||||||
|
|
||||||
|
# Prolog stuff:
|
||||||
|
color #888 "<\?.+\?>|<!DOCTYPE[^>]+>|\]>"
|
||||||
|
color #888 start="<!DOCTYPE[^>]*$" end="^[^<]*>"
|
||||||
|
|
||||||
# Comments:
|
# Comments:
|
||||||
color yellow start="<!DOCTYPE" end="[/]?>"
|
|
||||||
color yellow start="<!--" end="-->"
|
color yellow start="<!--" end="-->"
|
||||||
|
|
||||||
# Escapes:
|
# Entities (custom and predefined):
|
||||||
color red "&[^;]*;"
|
color pink "&[^; ]+;"
|
||||||
|
color red "&(amp|apos|gt|lt|quot);"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user