Compare commits

...

884 Commits

Author SHA1 Message Date
c56bbe74bf Merge in changes from upstream 2026-08-12 16:33:21 -07:00
Benno Schulenberg
8e6360d166 po: update translations and regenerate POT file and PO files 2026-07-31 08:26:25 +02:00
Benno Schulenberg
4e8238edec bump version numbers and add a news item for the 9.2 release 2026-07-31 08:00:11 +02:00
Benno Schulenberg
c497a5f90b copyright: update the years for significantly changed files 2026-07-29 15:25:04 +02:00
Benno Schulenberg
b04a2a18ea docs: in the FAQ, adjust the wording in the item about multiple buffers
That is: mention also the new option names --newbuffer / set newbuffer.

And don't mention M-< and M-> for switching between buffers, as those
keystrokes have been reassigned to horizontal scrolling since nano-9.0.
2026-07-29 15:01:34 +02:00
Benno Schulenberg
613fe4b9b2 docs: improve the description of the flipnewbuffer bindable function 2026-07-29 15:01:34 +02:00
Benno Schulenberg
27bf87d21a docs: implement the renaming of --multibuffer to --newbuffer 2026-07-28 10:42:56 +02:00
Benno Schulenberg
b6faa5d5bb tweaks: rename the internal flag, to match the new name of the option
It also better distinguishes it from the ENABLE_MULTIBUFFER thing.
2026-07-28 10:42:56 +02:00
Benno Schulenberg
4ebd490225 options: add --newbuffer as a more fitting synonym of --multibuffer
It matches the "New Buffer" description of the M-F toggle in the file-
insertion menu, similar to how --noconvert matches "No Conversion".

(This should have been done ages ago, but it never occurred to me.)
2026-07-28 10:42:56 +02:00
Benno Schulenberg
f6e9c00f59 gnulib: update to its current upstream state 2026-07-25 09:15:11 +02:00
Benno Schulenberg
79b18f462c screen: do a full refresh for Shift+Home and Shift+End when needed
That is: make line_needs_update(), when the mark is on, return TRUE
only when "page start" for old and new cursor position are the same
OR, otherwise, when NOT doing whole-window sidescrolling (that is:
when --solosidescroll is active).

This fixes https://savannah.gnu.org/bugs/?68556.

Bug existed since version 9.0, since whole-window sideways scrolling
was introduced.
2026-07-24 16:44:18 +02:00
Benno Schulenberg
ff68fa7304 tweaks: replace an if with an else
When the identical item is not the first one, then it necessarily has
a preceding item, so there is no need to check its `prev` pointer.
2026-07-24 11:28:38 +02:00
Benno Schulenberg
b6aa309aa7 tweaks: elide an auxiliary variable that is no longer needed 2026-07-24 09:20:00 +02:00
Benno Schulenberg
6e39b405c8 tweaks: don't renumber all history items -- "renumber" only the last
Only the `lineno` of the last history item is ever referenced, so...
adjust only that number when an item is removed from the list.

This works, because whenever an item is added, it is added after the
last item, giving it automatically that item's line number plus one.

Also, make the relevant comparison a little more robust.
2026-07-23 16:29:20 +02:00
Benno Schulenberg
0c3e596ad7 tweaks: elide an unneeded auxiliary variable 2026-07-23 10:56:02 +02:00
Benno Schulenberg
b41de01e6c tweaks: drop four null-derefence guards that are no longer needed
Since the previous commit, the history routines no longer make use
of splice_node() and unlink_node(), so now `openfile` will always
have a value when these functions are called.
2026-07-23 10:40:24 +02:00
Benno Schulenberg
e075df83e9 tweaks: don't call unlink_node() nor splice_node() for history items
This makes use of some knowledge about history lists: that there is
always another item when an identical item is found (because each
list ends with an empty item), that there is no item before the
head of the list, and that a new item is always added at the end.

This code is not time critical, but not calling splice_node() when
populating the search histories during startup saves upto three
hundred function calls, double the number of ifs, and triple the
number of assignments...  Several tens of microseconds.
2026-07-23 10:40:24 +02:00
Benno Schulenberg
1cff717d98 tweaks: adjust the style of a comment and the order of a comparison
Use the same style and order as used in the two succeeding functions.
2026-07-22 16:15:02 +02:00
Benno Schulenberg
68d4b84610 startup: do not crash when a section of a history file is overlong
That is: do not dereference a null pointer when -- during startup, when
no files have been opened yet -- the search history file is read in and
a section contains more than the maximum number of items.

This fixes https://savannah.gnu.org/bugs/?68545.

Bug existed since version 4.2, commit 34d22d3f.
2026-07-22 16:04:42 +02:00
Benno Schulenberg
a41f238042 tweaks: avoid a false positive when doing static analysis
(Found with Clang's `scan-build`.)
2026-07-20 10:48:28 +02:00
Benno Schulenberg
e18c6c95e7 tweaks: drop an unneeded null-dereference guard
The function delete_node() is called right after this and
it dereferences `openfile` twice, without a guard, so...

(Found with Clang's `scan-build`.)
2026-07-20 10:48:28 +02:00
Benno Schulenberg
c4948d5035 tweaks: drop three assignments of function results, as they are not used
(Found with Clang's `scan-build`.)
2026-07-20 10:48:28 +02:00
Benno Schulenberg
4c3ab6f5fb docs: say thanks to the Italian, Kazakh, and Arabic translators 2026-07-17 11:01:02 +02:00
Vincent Yang
757ce59330 startup: quit when standard output is not a TTY, to avoid user confusion
There is no reason to redirect nano's output, as it is just a lot of
ANSI codes, so not allowing this redirection has no negative effect.

But forbidding the redirection will prevent users from accidentally
doing so and then getting stuck, not realizing what has happened.

Signed-off-by: Vincent Yang <yang.vincent.h@icloud.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-07-15 16:28:01 +02:00
Benno Schulenberg
9375b99c52 tweaks: exclude three error checks from a normal build
Unknown or mismatching undo types would be programming errors -- they
could only occur if a new type were added and not properly handled.
2026-07-14 10:18:42 +02:00
Benno Schulenberg
50df473643 tweaks: drop several unneeded elses, and correct an indentation 2026-07-14 08:30:41 +02:00
Benno Schulenberg
0c242b8666 docs: reword and reshuffle the line about saving-and-exiting 2026-07-10 11:11:22 +02:00
Benno Schulenberg
96adcef377 doc: in the FAQ, adjust the description of the Ctrl+T toggle 2026-07-09 10:42:11 +02:00
Benno Schulenberg
a6046c6668 docs: add a reference to the texi manual, via info and online 2026-07-08 17:00:07 +02:00
Benno Schulenberg
cfb9c08580 docs: explicitly mention in the man page how to save and exit
These are the two most important commands, so it's good to have them
in the man page, especially since the help lines do not list ^S.

Inspired-by: Sébastien Desreux <seb@h-k.fr>
2026-07-08 16:29:51 +02:00
Benno Schulenberg
fde24946da bindings: add a blind ^T toggle in the WhereIs and GotoLine menus
"Blind" meaning that the toggle is not shown in the help lines
nor in the help text, and that its function (`flipgoto`) cannot
be bound to another keystroke.

This addresses https://savannah.gnu.org/bugs/?68503 and
https://lists.gnu.org/archive/html/nano-devel/2026-07/msg00006.html.

Apparently there are some users who are in the habit of typing ^W^T
when they want to jump to a specific line.  Avoid frustrating their
muscle memory.

In other words: handle ^W^T and ^/^T similar to how ^W^Y and ^W^V
are handled since commit 8e302738 from seven years ago.
2026-07-08 15:34:21 +02:00
Benno Schulenberg
9797150ffd docs: mention in the FAQ how to get the ^W^T combo back
(Although ^/ and M-G have existed since nano's initial revision.)
2026-07-06 11:49:28 +02:00
Benno Schulenberg
d43809146f tweaks: invert two ifs, to reduce duplication of code
Also, drop two unneeded initializations.
2026-07-06 11:47:27 +02:00
Benno Schulenberg
2c1bbb5552 tweaks: reshuffle two declarations and rename the function in one of them
Also, drop a redundant call of fflush() -- copy_file() already did it.
2026-07-05 13:56:12 +02:00
Benno Schulenberg
f63547027c tweaks: treat temp file for speller in similar way as for formatter 2026-07-05 11:14:12 +02:00
Benno Schulenberg
ab597a6c2f tweaks: rename a variable while inverting its logic
Now the name actually conveys the purpose of the variable.
2026-06-30 07:34:15 +02:00
Benno Schulenberg
9383ed03a2 files: compare either only full names or bare names, not full with bare
And in the bargain get rid of the wrapped and nested conditionals,
which was hard to understand.
2026-06-30 07:23:09 +02:00
Benno Schulenberg
e1d954c739 docs: fix a typo in NEWS
(It went unnoticed because the local rule colorized also invalid dates.)
2026-06-23 08:07:35 +02:00
Benno Schulenberg
6d98026285 po: update translations and regenerate POT file and PO files 2026-06-23 07:46:24 +02:00
Benno Schulenberg
21d5d8707f bump version numbers and add a news item for the 9.1 release 2026-06-23 07:10:48 +02:00
Benno Schulenberg
982bca3bd3 tweaks: swap the two arms of an 'if', to have the positive case first
Also, put the actions in the two arms in the same order.
And add a comment, while dropping two unneeded ones.
2026-06-21 11:31:29 +02:00
Benno Schulenberg
834b88eed9 tweaks: rename three variables, to be more descriptive 2026-06-21 11:05:26 +02:00
Benno Schulenberg
b273b69cad tweaks: elide an unneeded parameter, and improve the related comment
And drop two other overexplicative comments.
2026-06-21 11:05:26 +02:00
Benno Schulenberg
81a3c3e82f syntax: c: add several missing C++23 keywords
References:
  https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf
  https://en.wikipedia.org/wiki/C++23
2026-06-20 16:04:31 +02:00
Benno Schulenberg
cebb2a383d tweaks: in the C syntax, gather all type specifiers into one regex
And put all lowercase type modifiers into a second regex.

Also, move 'register' and 'volatile' to the modifiers regex
-- the remaining ones in the last “green” regex are all C++
keywords, but that list is far from complete.

Furthermore, make the regex for binary and hex more succinct
-- the final \> will prevent an apostrophe from coming last.
2026-06-18 08:54:50 +02:00
Vincent Yang
2adaa1139c syntax: c: add new C23 keywords and preprocessor directives
A summary of the changes:
  https://en.wikipedia.org/wiki/C23_(C_standard_revision)

An accessible draft of the standard:
  https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf

Signed-off-by: Vincent Yang <yang.vincent.h@icloud.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-06-17 07:51:04 +02:00
Benno Schulenberg
ad92fe6638 syntax: c: colorize hexadecimal and binary numbers, and boolean constants
C23 introduced binary numbers (things like 0b101010) and predefined
constants 'true', 'false', and 'nullptr'.  Colorize them specially,
and colorize hexadecimal numbers too, for good measure.

(Note that binary and hexadecimal numbers may contain apostrophes,
for separating groups of digits, for better legibility.)

Inspired-by: Vincent Yang <yang.vincent.h@icloud.com>
2026-06-17 07:51:04 +02:00
Benno Schulenberg
4b21ed39c7 tweaks: harmonize the form of two error messages with two others
Two identical messages were adjusted a week ago, in commit 96cf1b38,
but these two in another file were overlooked.
2026-06-14 10:31:29 +02:00
Benno Schulenberg
21b833d423 gnulib: update to its current upstream state 2026-06-14 08:38:23 +02:00
Benno Schulenberg
afb9cdac24 help: further improve and modernize the Spellcheck help text
The previous commit changed the help text for the Spell Checker,
so this is a good time to further improve that text.  That is:
speak of "buffer" instead of "file", speak of "marked region"
instead of "selected text", make use of the standard phrase for
introducing the function keys, and modernize the title: wrap it
in "===" and don't include the redundant "Help Text".

Most of all, tune the text to the actual phase of the process:
here the user can make spelling *corrections* -- the checking
has already been done.
2026-06-14 08:07:07 +02:00
Benno Schulenberg
ca9d6e7dec help: use a better word in the Spellcheck help text
Suggested-by: Mirko Adam <development@four-m.de>
2026-06-13 12:35:57 +02:00
Benno Schulenberg
03a1a00ef3 help: remember, clear, and restore the value of 'spotlighted'
Otherwise the help viewer would attempt to highlight something random,
*and* the original highlighting would be gone after closing the viewer.

This fixes https://savannah.gnu.org/bugs/?68443.
Reported-by: Mirko Adam <development@four-m.de>

The underflow bug existed since version 6.0, commit 8762e046,
the spotlight-losing bug since version 5.6, commit 37717bae.
2026-06-13 12:25:41 +02:00
Benno Schulenberg
1e5c40765d docs: add an xclip example binding for copying text to system clipboard
For some reason, `xclip` needs to have its stdout and stderr forcibly
closed to make it stop running after it has ingested text.

That solution was found here:
  https://github.com/astrand/xclip/issues/34#issuecomment-686744880

This addresses https://savannah.gnu.org/bugs/?68444.
2026-06-13 12:00:34 +02:00
Benno Schulenberg
67af31e8f3 tweaks: move a function, improve three comments, and rename a parameter 2026-06-12 10:43:04 +02:00
Benno Schulenberg
57d70fedf1 tweaks: don't use index 0 when no higher indexes are used 2026-06-11 09:18:41 +02:00
Benno Schulenberg
bf4bc730c4 tweaks: slightly adjust two wordings in the main man page 2026-06-09 12:52:23 +02:00
Benno Schulenberg
6adbd4249e docs: move the notices in the main man page to after the description
For new users, the description is more important than the notices,
and... old users probably don't look at the man page anyway.

(Arguably, the notices should be moved to after the editing section,
but I don't like how things look then.)
2026-06-09 12:52:23 +02:00
Benno Schulenberg
96cf1b3807 tweaks: harmonize the form of five error messages 2026-06-09 12:31:51 +02:00
Benno Schulenberg
be46139504 files: report an error when the given filename ends in a slash
When the specified name (including the final slash) is not an existing
directory, then reject it as an invalid name -- instead of complaining
later, when the user tries to save the buffer, that the specified name
is a folder, which isn't actually true.

This addresses https://savannah.gnu.org/bugs/?68433.

Buglet existed since before version 2.0.0.
2026-06-08 12:49:37 +02:00
Benno Schulenberg
61abc2e59a files: make get_full_path() work properly also for nonexistent files
That is: make it conform to the function's comment, which says that it
returns the canonical path when this path exists (and is reachable).

This addresses https://savannah.gnu.org/bugs/?68428.

Problem existed since version 6.3, commit fdd946c0.
2026-06-08 11:22:11 +02:00
Benno Schulenberg
b53833c4f3 tweaks: make three different error messages identical to an existing one
(This saves some seventy bytes of string storage, as all the
"new" strings already exist somewhere else in the code.)
2026-06-08 08:26:49 +02:00
Benno Schulenberg
f6d38a5be0 tweaks: harmonize checking the exit status of a child process 2026-06-08 08:19:30 +02:00
Benno Schulenberg
00d137baf3 tweaks: harmonize seven more error checks with similar ones 2026-06-08 08:15:07 +02:00
Benno Schulenberg
27244483fe tweaks: modernize a URL 2026-06-06 11:17:13 +02:00
Benno Schulenberg
78f7424f37 tweaks: reshuffle and adjust a comment while dropping an unneeded 'else' 2026-06-04 20:59:15 +02:00
Benno Schulenberg
2a9121fc2d files: don't bother updating notes when closing the buffer right after
There's no point in statting the file again in write_file() after it's
been written to disk when immediately afterward the buffer gets closed.
2026-06-04 20:53:09 +02:00
Benno Schulenberg
c77a5e5169 tweaks: elide a parameter from write_file() and write_region_to_file()
The non-normality of the file to be written is easily expressed as
a separate writing method: SPECIAL.
2026-06-04 12:04:42 +02:00
Benno Schulenberg
21bedd0db9 tweaks: harmonize three error checks with those of similar calls 2026-06-04 07:40:11 +02:00
Benno Schulenberg
7fe76a4dfb tweaks: slightly improve a sentence in the nanorc manpage
(Making the same change as was what sneaked into commit 66da03e5.)
2026-06-03 19:46:07 +02:00
Benno Schulenberg
fd72375aa4 history: don't leave NUL bytes in the string of anchors
When restoring a series of anchors, don't ruin the string by leaving
a NUL byte after each number -- restore each space that was there.

This fixes https://savannah.gnu.org/bugs/?68423.

Bug existed since version 8.5, commit 60e2f2ba, since the saving
and restoring of anchors was introduced.
2026-06-03 12:50:42 +02:00
Benno Schulenberg
e9c0c8b930 docs: prevent highlighted words in the man pages from getting hyphenated 2026-06-01 12:39:30 +02:00
Benno Schulenberg
66da03e555 docs: fix a typo made a month ago, in commit 269b96b7
While adjusting Branden's patch for the changed state of the repo,
I must have mistyped the second \% in that diff.
2026-06-01 12:39:06 +02:00
Benno Schulenberg
382bcc77c0 docs: mention that M-Ins and M-Del are valid keynames
Also colorize them as valid.
2026-06-01 09:04:51 +02:00
Benno Schulenberg
dbc1f29296 rcfile: allow rebinding M-Ins and M-Del
Allowing to rebind M-Del gives the user the chance to make M-Bsp and
M-Del do symmetrical things: delete a word leftward and rightward,
respectively.  With --modernbindings, ^H calls `help` and thus the
user can no longer bind this code to `chopwordleft` to make Ctrl+Bsp
behave symmetrically to Ctrl+Del.  So, to give the user the chance
to still have symmetrical Bsp/Del combos, allow to rebind M-Del.

(Allowing to rebind M-Ins is just for symmetry -- on my two laptops
that key combination is dead: it does not produce any keycode.)
2026-06-01 09:04:51 +02:00
Benno Schulenberg
799577b4df tweaks: rename a variable, for aptness, and remove unneeded braces 2026-06-01 09:04:51 +02:00
Benno Schulenberg
57e2cc251d tweaks: unwrap some seventy lines that don't need to be wrapped
(This assumes a more modern terminal width of 100 columns.  And it
allows to exercise nano's horizontal-scrolling feature on terminals
that have the old 80-column standard width.)
2026-06-01 09:04:51 +02:00
Benno Schulenberg
8cb86c9582 files: do not call chmod() and chown() on a .save emergency file
The reason to not call chmod() on a partially edited file is that this
file may contain stuff that the person who did the editing may not want
others to see.  Whereas calling chown() is pointless for normal users,
and would be falsifying information for root.

(This does oblige the user to do `cp file.save file && rm file.save`
instead of the simple `mv file.save file` to recover the partially
edited file.  But... .save files should be such a seldom occurrence
that this extra step should not be a problem.)

This addresses the third part of
  https://lists.gnu.org/archive/html/nano-devel/2026-05/msg00040.html.
Reported-by: Arjun Basnet <disclose@securin.io>

The minor problem existed since version 2.2.0, since the chmod()
and chown() were added in 2009, in commit 123110c5, upon a request
by Mike Frysinger made in https://savannah.gnu.org/bugs/?27273.
2026-05-29 09:07:42 +02:00
Benno Schulenberg
e4852e4f56 tweaks: improve a comment, add one, and move one
Also, normalize the spelling of two keystrokes in an old news item.
2026-05-29 09:06:08 +02:00
Benno Schulenberg
2abf56546b tweaks: condense a comment, rename a function, and reshuffle four lines 2026-05-29 09:05:49 +02:00
Benno Schulenberg
02825602e2 linting: properly check for a negative return value from read()
This addresses the second part of
  https://lists.gnu.org/archive/html/nano-devel/2026-05/msg00040.html.
Reported-by: Arjun Basnet <disclose@securin.io>

Problem existed since version 2.3.3, commit 5575bfad.
2026-05-29 09:03:55 +02:00
Benno Schulenberg
0daeab17cd tweaks: reshuffle two lines of code, to avoid a memory leak 2026-05-25 15:32:56 +02:00
Benno Schulenberg
6b49b498cc spelling: properly check for a negative return value from read()
This addresses the first part of
  https://lists.gnu.org/archive/html/nano-devel/2026-05/msg00040.html.
Reported-by: Arjun Basnet <disclose@securin.io>

Problem existed since version 1.1.8, commit f21f3fcc.
2026-05-25 15:29:17 +02:00
Benno Schulenberg
924190ce7d tweaks: compare two syntaxes directly, instead of comparing their names
In theory two different syntaxes could have the same name, so comparing
their names was actually incorrect.
2026-05-24 07:21:30 +02:00
Benno Schulenberg
4a347cd7dc search: place the viewport flush left when a match easily fits within it
This avoids having the viewport positioned slightly to the right
when an earlier match needed it shifted and the current match is
somewhere near the beginning of the line.  I found that behavior
annoying, especially when the entire line fit within the viewport.
2026-05-23 09:44:15 +02:00
Benno Schulenberg
1e022b55d1 tweaks: avoid miscompilation on macOS, where 'st_atim' is unknown
Since commit d0ee91f4 from earlier today, the full timestamp is used
('st_atim' instead of 'st_atime', for example).  As macOS does not
seem to know the shorter names (see commit f516cddc from seven years
ago), define those shorter names when compiling for macOS.
2026-05-22 11:51:47 +02:00
Benno Schulenberg
29ff6abec6 tweaks: check calls of stat() for success instead of for not-failure 2026-05-22 11:51:47 +02:00
Benno Schulenberg
054b478999 tweaks: remove a fragment of code that is redundant since previous commit 2026-05-22 11:51:47 +02:00
Benno Schulenberg
e6ce29d531 files: always make a backup when the WriteOut prompt says "[Backup]"
Nano should do what it says: when it says "[Backup]" at the prompt,
it must make a backup.  No exceptions.

True, this might overwrite an earlier backup (that the user might wish
to keep) with work by another user, but really... when multiple users
could be editing a file, this file should be under version control.

This fixes https://savannah.gnu.org/bugs/?68384.

Bug existed since before version 2.0.0.
2026-05-22 10:44:22 +02:00
Benno Schulenberg
b3c195ef00 files: use the correct timestamp for the backup file
When overwriting another file, or when appending or prepending to it,
the backup file should get the original timestamp of that other file,
not the timestamp of the file in the current buffer.

This fixes https://savannah.gnu.org/bugs/?68385.

Bug existed since before version 2.0.0.
2026-05-22 10:17:52 +02:00
Benno Schulenberg
f0b1606f28 tweaks: move two assignments to where they are used
Also, drop a pointless 'static' specifier, and slightly rename
the variable, to be more fitting (as it holds two times).
2026-05-22 10:06:35 +02:00
Benno Schulenberg
d0ee91f4eb files: for a backup, use the full timestamp, not just the seconds 2026-05-22 10:02:37 +02:00
Benno Schulenberg
266a4fc748 files: allow editing a file named ~ (a lone tilde)
Nano cannot edit directories, so when the user specifies a solitary
tilde on the command line, they can only mean a file by that name.

(Other editors behave like this too, with the exception of Emacs.)

This addresses https://savannah.gnu.org/bugs/?68373.
Reported-by: Chris Martin <987687@gmail.com>
2026-05-22 08:54:52 +02:00
Benno Schulenberg
d985946ef5 syntax: lua: colorize also various backslash escapes specially
Main reference:
  https://lua.org/manual/5.5/manual.html#3.1

Also, give strings and numbers a more visible color -- red was too dark.
2026-05-21 11:23:27 +02:00
Benno Schulenberg
9644ca0ca5 syntax: lua: add new keywords and drop long-deprecated ones
• add operators `&`, `|`, and `~` (Lua-5.3)
• add statements `goto` (Lua-5.2) and `global` (Lua-5.5)
• drop `math` functions `atan2`, `cosh`, `sinh`, and `pow`
  (deprecated by Lua-5.3, `frexp` and `ldexp` returned in Lua-5.5)
• drop function `module` (deprecated since Lua-5.2)
• drop `package.seeall` (gone together with `module`)
• drop functions `getfenv` and `setfenv` (gone from Lua-5.2)
• drop functions `math.log10` and `table.maxn` (Lua-5.2)
• move function `unpack` to the `table` library (Lua-5.2)
• drop `math.mod` (renamed to `math.fmod` since Lua-5.1)
• add function `table.create` (Lua-5.5)
• add function `warn` (Lua-5.4)

Also, colorize only `==` as an operator, not a lone `=`,
because coloring also the latter looked too garish.

Furthermore, colorize labels (`::somename::`) specially,
and give _G and _VERSION from the rule for basic functions
their own rule as they are not functions.

Main reference:
  https://lua.org/manual/5.5/contents.html#index
2026-05-21 07:48:58 +02:00
Benno Schulenberg
83f0a593fd syntax: lua: colorize also multiline strings
This coloring rule existed since the syntax for Lua was added
(fifteen years ago, in commit 090e2cf7), but it was commented
out -- probably because it came after the coloring rule for
multiline comments, and would thus recolor those comments red.

Seven years later, commit 21cd953e removed the inactive rule,
but after just seven months, commit bf594939 swapped the order
of the coloring rules for strings and comments, and since then
a coloring rule for multiline strings would have worked right.

(Also, remove a rule that doesn't make sense -- the one that
colored everything between [[ and ]] in brightwhite first.)
2026-05-19 16:12:01 +02:00
G. Branden Robinson
3948c09d2b docs: more consistently set nano's name in bold
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-05-16 15:19:49 +02:00
Benno Schulenberg
b89ab4a99d docs: italicize 'nanorc' in the rnano manpage, like in the other manpages
(This should have been included in commit 5660833c, but I forgot.)
2026-05-16 15:19:49 +02:00
Benno Schulenberg
c04aa40543 docs: remove the description of the flipgoto toggle
The toggle itself was removed three commits ago.

Also, remove `flipgoto` from the relevant syntax file.
2026-05-11 11:25:23 +02:00
Benno Schulenberg
6ee4c67226 tweaks: adjust two translator hints and add two after the previous change
The available space for some has increased.
2026-05-11 11:25:23 +02:00
Benno Schulenberg
b70851e488 help: unabbreviate three words, in three different help items
And adjust two prompt modifiers to match those new help items better.
2026-05-11 11:25:23 +02:00
Benno Schulenberg
7cf20d7227 menus: remove the ^T toggle between the Where-Is and Go-To-Line menus
The `flipgoto` toggle (^T) made for an uneven number of help items in
the Where-Is and Go-To-Line menus, and an odd item doesn't look good.
Also, removing the ^T toggle from the Where-Is menu makes its number
of help items equal to that of the Replace menu, which looks nice
when toggling between the two with ^R.  And reducing the number of
help items gives the remaining ones more space, which will allow to
unabbreviate three of them in the next commit, which will look better.

Furthermore, this gets rid of the strange and unclear "Go To Text" tag
in the Go-To-Line menu.

Users who insist on having the ^T toggle can help themselves:

  bind ^T "{cancel}{gotoline}" search
  bind ^T "{cancel}{whereis}" gotoline

The only difference with the old behavior is that these bindings
don't preserve what was typed at the prompt before ^T was hit.
2026-05-11 11:25:23 +02:00
Benno Schulenberg
355a5a3bfa tweaks: rename a few variables, to harmonize with the general scheme
Also, having both `openfile->current` and `is_current` was confusing:
which one held the actual current value?
2026-05-11 11:25:08 +02:00
Benno Schulenberg
6c3e9848b2 tweaks: drop most != '\0' comparisons 2026-05-11 11:12:03 +02:00
Benno Schulenberg
ac83dddcd2 tweaks: drop most != NULL comparisons
They are redundant, are not used in several other places,
and not having them gives more contrast with `== NULL`.
2026-05-10 12:16:12 +02:00
Benno Schulenberg
e40ba24d89 tweaks: adjust the suggested max help-item length in six translator hints
Five of the counts were inaccurate, and for the sixth the available space
was reduced two years ago by commit a13cd6a1.
2026-05-05 15:10:09 +02:00
Benno Schulenberg
9639971a0e tweaks: just check for negativeness instead of for exactly minus one
(In theory this should be a teeny bit faster.)
2026-05-04 16:49:04 +02:00
Benno Schulenberg
bbab2770c5 tweaks: drop an inconsistent space before a closing parenthesis 2026-05-03 12:08:27 +02:00
Benno Schulenberg
0e7f744744 tweaks: move a condition out of a function, to avoid unneeded calls
But mostly: it makes it clearer what outside_of_confinement() checks,
and makes the function simpler.
2026-05-02 17:01:03 +02:00
Benno Schulenberg
0d36dc4942 tweaks: rename a function, to better describe what it does 2026-05-02 11:10:31 +02:00
Benno Schulenberg
faf90cfaa6 tweaks: shorten four conditions, clarify a fifth, and improve a comment 2026-05-02 09:28:29 +02:00
Benno Schulenberg
34cfbcc4d0 files: drop an unneeded call of real_dir_from_tilde()
It was made redundant ten years ago by commit bfe418fe.
2026-05-01 17:14:40 +02:00
G. Branden Robinson
376ae53608 docs: use a better word in the description of the 'locking' option
The same word as used in the nano.1 man page.

And drop the unneeded word "for".

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-30 13:02:29 +02:00
G. Branden Robinson
95bcb90691 docs: swap the left and middle footer of the man pages
Also, say "GNU nano" instead of "version".

Having the name of the software on the left and the date in the middle
aligns better with preponderant practice.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-30 12:12:41 +02:00
Benno Schulenberg
0edc6610dd docs: use curly double quotes when scare quotes are meant
Inspired-by: G. Branden Robinson <g.branden.robinson@gmail.com>
2026-04-29 12:56:17 +02:00
Benno Schulenberg
fc84a19883 docs: replace the e.g. and i.e. abbreviations with plain English words
Inspired-by: G. Branden Robinson <g.branden.robinson@gmail.com>
2026-04-29 12:56:17 +02:00
G. Branden Robinson
35e11ce7ff docs: consistently use minus sign for M- notation
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-29 12:56:17 +02:00
G. Branden Robinson
269b96b703 docs: set "foreign" software in italics, not bold
As libmagic, ncurses, and terminfo are software components that
aren't topics of nano's own man pages, use italics for them.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-29 12:55:55 +02:00
Benno Schulenberg
286aefa34a docs: reword a description to make it clearer what typeface applies
Also, make the typeface usage in the texi version more consistent.

Inspired-by: G. Branden Robinson <g.branden.robinson@gmail.com>
2026-04-28 17:33:08 +02:00
3cdc00fdf6 Merge remote-tracking branch 'upstream/master' into line-folding 2026-04-27 10:39:46 -07:00
G. Branden Robinson
5660833ce8 docs: consistently set file names in italics
Also protect them from hyphenation (by prepending \%)
and add hyphenless break points (\:) to lengthy file names.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-27 17:21:51 +02:00
G. Branden Robinson
8499183c02 docs: favor the \[ti] special character over a literal ~
Some output devices render a plain ASCII tilde as U+02DC (small tilde).

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-27 16:28:17 +02:00
G. Branden Robinson
2e59a695e7 docs: style function names with bold, not backticks
Using bold is more consistent with the rest of nano's man pages.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-27 13:15:04 +02:00
G. Branden Robinson
6fe93a6c3f docs: fix three unescaped hyphens before option names
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-27 13:15:04 +02:00
Benno Schulenberg
09db112412 syntax: man: colorize also the \[xx] special-character syntax 2026-04-27 13:15:04 +02:00
G. Branden Robinson
2de91de36b docs: use groff-style special-character syntax: \[xx] instead of \(xx
The \(xx style looks ugly with its unbalanced left parenthesis,
and \[bu], \[Fc], and \[md] are already being used.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-27 13:14:47 +02:00
Benno Schulenberg
f43240e9b0 docs: prevent some keywords and compound keywords from getting hyphenated
Inspired-by: G. Branden Robinson <g.branden.robinson@gmail.com>
2026-04-26 12:33:18 +02:00
G. Branden Robinson
ac1bf7d60e docs: sync rnano's synopsis markup with nano's
The plus and the comma are literals, so should be in bold.

(See commit a06b921f1 from seven years ago.)

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-26 11:21:22 +02:00
Benno Schulenberg
b11349d901 build: fix compilation when configured with --enable-tiny
(This should have been part of commit 22e2ea3c from last week.)
2026-04-25 09:09:28 +02:00
Benno Schulenberg
2838b2429e docs: more precisely describe what --restricted forbids and allows 2026-04-23 12:11:41 +02:00
Benno Schulenberg
97d72f4821 docs: remove all mention of the old Mac file format 2026-04-18 15:57:06 +02:00
Benno Schulenberg
5bb19b0598 help: reshuffle the Backup toggle, to keep Append and Prepend paired 2026-04-18 15:56:27 +02:00
Benno Schulenberg
22e2ea3cf4 tweaks: fold two fragments of code together 2026-04-18 15:48:22 +02:00
Benno Schulenberg
cad7948400 tweaks: normalize the indentation after the previous change 2026-04-18 15:48:22 +02:00
Benno Schulenberg
bf342bcb3c files: remove the code for reading and writing old Mac files
Twenty five years after the Mac switched from Carriage Return (CR)
to Line Feed (LF) as the line ending, it is time to ditch the code
for reading and writing the old format.
2026-04-18 15:48:08 +02:00
Benno Schulenberg
d75b7a3072 syntax: default: colorize the release motto for the 9.* series too 2026-04-12 14:04:04 +02:00
bf4d6244c6 Merged master 2026-04-08 14:31:23 -07:00
Benno Schulenberg
c7276e58c9 po: update translations and regenerate POT file and PO files 2026-04-08 17:09:21 +02:00
Benno Schulenberg
b7c9882428 bump version numbers and add a news item for the 9.0 release 2026-04-08 16:52:40 +02:00
Benno Schulenberg
cb43493e00 history: create the ~/.local directory with limited access rights
Permitting everyone to write to the .local directory gave attackers
(on platforms where umask is 000) a tiny opportunity to become the
owner of the .local/share subdirectory, which would allow them to
install malicious .desktop files.

This fixes https://bugzilla.redhat.com/2455314.
Reported-by: Michał Majchrowicz <mmajchrowicz@afine.com>
Patch-by: Michał Majchrowicz <mmajchrowicz@afine.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>

Bug existed since version 2.9.1, commit 4200ed30,
from shortly after support for XDG was added.
2026-04-06 11:23:42 +02:00
Benno Schulenberg
7cf0125e9c docs: trim stuff that is more than four years old from the changelog 2026-04-04 12:17:03 +02:00
Benno Schulenberg
3b22c1cce8 copyright: update the years for significantly changed files 2026-04-04 09:23:31 +02:00
Benno Schulenberg
c1ea0601c9 tweaks: defend against hypothetical format specifiers
With this change, any format specifiers that the now third parameter
of statusline() *might* contain will not lead to unintended accesses
of memory.

Suggested-by: Jonathan Echavarria <jrec93@gmail.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-02 11:18:24 +02:00
Benno Schulenberg
0b7328bce4 feedback: prevent interpretation of %s and similar in a filename
When a filename contains things that look like format specifiers
(%s, %p, %n, ...) and opening this file throws some error and this
file is opened together with others, then switching to the relevant
buffer would cause the %x parts to be interpreted as actual format
specifiers, resulting in the leakage of information, or in a crash,
or possibly in arbitrary memory writes.

Reported-by: Jonathan Echavarria <jrec93@gmail.com>
Patch-by: Jonathan Echavarria <jrec93@gmail.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-04-01 12:23:50 +02:00
Benno Schulenberg
0e430310b8 docs: add ^B among the list of keystrokes for --modernbindings
Even though ^B is the default binding for a backward search, the
default for a forward search (^F) is mentioned too, so...
2026-04-01 12:05:06 +02:00
Benno Schulenberg
dbfce437af moving: make the minimum step for sideways scrolling two cells
Otherwise, with a tabsize of 1, rightward scrolling would get "stuck"
on a double-width character.
2026-04-01 08:02:52 +02:00
Benno Schulenberg
a01bc5f117 docs: adjust the description of scrollright for the improved behavior
And make the description more concise.
2026-04-01 08:00:08 +02:00
Benno Schulenberg
adff8171cc moving: when scrolling sideways, search also upward for a longer line
Otherwise, when the cursor is near the bottom of the viewport, and there
are overlong lines visible *above* the cursor, it is frustrating that
nano refuses to scroll sideways further than the bottom lines allow.

(Trying to move the cursor up has to happen before trying to move it
down, otherwise nano can get "stuck" on a long line that is present
just below the viewport.)
2026-03-31 16:57:19 +02:00
Benno Schulenberg
f16e8d8888 build: add move.c to the list of files that contain translatable strings 2026-03-29 12:06:06 +02:00
Benno Schulenberg
e637fdb42c gnulib: update to its current upstream state 2026-03-29 11:36:15 +02:00
Benno Schulenberg
0b17713756 moving: ignore scrollleft and scrollright with --solosidescroll too
And give feedback when those functions are called while --softwrap or
--solosidescroll are in effect.
2026-03-26 12:21:22 +01:00
Benno Schulenberg
5d31b0f595 docs: in the cheatsheet, place Ctrl+L in the Special movement section
More than redrawing the entire screen, its most obvious effect is
centering the current line, which is a movement of the viewport.

(Also, improve the wording for Alt+G.)
2026-03-23 16:32:42 +01:00
Benno Schulenberg
a3cb12ccff syntax: elisp: remove file -- something specific to Emacs is not for nano
(Nano doesn't have a syntax for vimscript either.)

The file has been moved to:

  https://nano-editor.org/more-syntaxes/elisp.nanorc
2026-03-22 07:56:07 +01:00
Benno Schulenberg
84f7eb2d1e tweaks: rename two variables, away from abbreviations 2026-03-21 13:21:54 +01:00
Benno Schulenberg
9e2f8e0fb3 tweaks: rename a variable, for contrast, and to be more fitting
The name `list` better indicates that a "history" is a list of things
(that were typed at a prompt in the past).
2026-03-21 12:46:05 +01:00
Benno Schulenberg
8abdd80f24 tweaks: rename three functions, to be more accurate 2026-03-21 12:38:10 +01:00
Benno Schulenberg
3dc49fa6b8 tweaks: rename a variable, to be more fitting and away from an abbrev 2026-03-20 12:30:29 +01:00
Benno Schulenberg
d3019a1c40 tweaks: rename a variable, away from a double abbreviation 2026-03-20 12:15:53 +01:00
Benno Schulenberg
63594a3f92 tweaks: rename a variable, to be more fitting
The list of filenames-plus-their-last-cursor-position contains just one
cursor position per file, not a record of the last two hundred cursor
positions per file.  So the name `register` is much more fitting than
the name `history`.

Also, correct a comment.
2026-03-20 12:04:21 +01:00
Benno Schulenberg
3e104064db tweaks: rename a type, away from a double abbreviation 2026-03-20 11:48:26 +01:00
Benno Schulenberg
c05a9009be docs: adjust the description of scrollright for the changed behavior
The previous commit restricted the line-jumping behavior of the cursor
to just the lines in the current viewport, thus keeping the viewport in
the (linewise) same position in the buffer.
2026-03-17 17:44:06 +01:00
Benno Schulenberg
902378fd7d moving: stay in the viewport when stepping to a longer line
When the current line is not long enough to allow the viewport to be
scrolled another tabsize to the right, then look for a longer line
only within the current viewport (and after the current line) --
because changing the vertical position of the viewport when doing an
essentially horizontal movement was not a good idea.
2026-03-16 08:36:17 +01:00
Benno Schulenberg
3ac3b27259 help: group the sideways scrolling keystrokes with the horizontal movers
This better fits the original grouping of increasing vertical strides.
2026-03-15 13:41:57 +01:00
Benno Schulenberg
a334b64e89 display: correct the previous commit -- the -1 is needed when going left
Otherwise the step is tabsize-1, and one doesn't reach column 1 again.
2026-03-15 12:25:17 +01:00
Benno Schulenberg
f6e9b78b73 display: put cursor at CUSHION columns from edge when scrolling sideways
Put it at CUSHION columns, not at CUSHION+1 columns, when scrolling to
the right and the cursor would otherwise be outside this inner frame.

(The -1 and +1 came from attempts to make it work before I decided to
make it scroll a tabsize number of columns.)
2026-03-15 12:09:07 +01:00
Benno Schulenberg
d896becfee docs: mention that M-Left, M-Right, M-Up, and M-Down are valid keynames 2026-03-15 09:01:04 +01:00
Benno Schulenberg
98ad9496cc docs: adjust the cheatsheet for the new functions and changed bindings
And reshuffle an item to keep the two columns balanced.
2026-03-14 17:20:24 +01:00
Benno Schulenberg
80f6650c81 docs: add notices about the reassignment of the M-< and M-> keystrokes
And mention how to get their old behavior back.
2026-03-14 17:00:24 +01:00
Benno Schulenberg
c3139b8d65 docs: use rebindable names M-Up and M-Down instead of Alt+Up and Alt+Down 2026-03-14 17:00:24 +01:00
Benno Schulenberg
50107bd23a moving: ignore scrollleft and scrollright when softwrapping
When softwrapping, there is nothing to the sides of the viewport, so
it does not make sense to try and scroll the viewport sideways then.
2026-03-14 17:00:24 +01:00
Benno Schulenberg
df20e9895f display: draw the "<" marker only if part of the line is onscreen
If all text on a line is scrolled offscreen to the left, it looks ugly
to show the highlighted "<" continuation marker.  And it is misleading:
there is nothing onscreen (on that line) that is continued on the left.
2026-03-14 17:00:24 +01:00
Benno Schulenberg
df0aa86e05 syntax: nanorc: colorize M-Left, M-Right, M-Up, M-Down as valid keynames
Also, colorize {scrollleft} and {scrollright} as valid braced names.
2026-03-14 10:50:31 +01:00
Benno Schulenberg
81a6abc623 rcfile: allow rebinding M-Left, M-Right, M-Up, and M-Down
This will allow the user to make <Alt+Left> and <Alt+Right> scroll
sideways, similar to how <Alt+Up> and <Alt+Down> scroll vertically,
so that Alt plus the arrow keys work in a consistent manner.
2026-03-14 10:50:31 +01:00
Benno Schulenberg
4b14e562e2 docs: document the new bindable scrollleft and scrollright functions 2026-03-14 10:50:31 +01:00
Benno Schulenberg
6aa0f3ba39 bindings: assign M-< and M-> to the sideways-scrolling functions
Nowadays probably most people use <Alt+Left> and <Alt+Right> for
switching between buffers, and most of the others use M-, and M-.
-- most likely nobody uses M-< and M->, as they require holding
down Shift (on a US keyboard).

M-< and M-> seem like a good choice for the sideways-scrolling
functions, because "<" and ">" are used to indicate offscreen
continuation of the line, and requiring the user to hold Shift
is good as it helps to prevent accidental horizontal scrolling.
2026-03-14 10:50:31 +01:00
Benno Schulenberg
c65d25da2f new feature: bindable functions for scrolling a tabsize left or right
Now that nano can do whole-window sideways scrolling, it makes sense
to have the functions `scrollleft` and `scrollright` -- analogous to
the functions `scrollup` and `scrolldown`.  Because having to first
navigate the cursor to an overlong line and then pressing <End> (or
holding down <Ctrl+Right>) in order to see what is on the rest of
the line does not speak "ease of use".  (Sure, toggling softwrap is
much easier, but that messes with the vertical alignment of things.)
2026-03-14 10:50:31 +01:00
49a78cbb75 Fix drawing lines when folded 2026-03-09 11:22:32 -07:00
68f10939d4 Merge branch 'master' of https://git.savannah.gnu.org/git/nano into line-folding 2026-03-08 17:53:33 -07:00
Benno Schulenberg
287b7ef90b tweaks: rename a variable whose function has changed over time
The `start_line` variable hasn't been used for backtracking
since commit 15a0a129 from four years ago.
2026-03-07 14:06:27 +01:00
Benno Schulenberg
b1f5531063 display: begin looking for new start matches at the correct place
The `paintlen` variable becomes non-zero only when the endmatch
is onscreen, so choose instead a sure way of setting the `index`
to the end of the endmatch.

This fixes https://savannah.gnu.org/bugs/?68104.

Bug existed in this form since version 2.4.3, commit 3f1878d9
(things being worse before that), but became visible since the
introduction of whole-window sideways scrolling.
2026-03-06 11:30:05 +01:00
Benno Schulenberg
9713f804df syntax: groff, man: colorize also \" tail comments and \# line comments
This fixes https://savannah.gnu.org/bugs/?68109.
Reported-by: G. Branden Robinson <g.branden.robinson@gmail.com>
2026-03-06 09:32:29 +01:00
Benno Schulenberg
bdac995173 docs: advise the use of --sysconfdir=/etc when configuring nano
This makes a self-compiled nano read /etc/nanorc instead of the
unexpected /usr/local/etc/nanorc.

This addresses https://savannah.gnu.org/bugs/?68117.
Reported-by: Alexandre Conseil <contact@alexandreconseil.fr>
2026-03-04 16:41:41 +01:00
Benno Schulenberg
793d6723ec tweaks: correct and simplify the logic from the previous two commits 2026-03-01 17:06:22 +01:00
Benno Schulenberg
5670c57dd2 display: redraw the screen also when 'brink' is not what it should be
This amends the previous commit.

This addresses https://savannah.gnu.org/bugs/?68105 better.
2026-03-01 12:08:40 +01:00
Benno Schulenberg
bf8b527375 display: when scrolling sideways, refresh edit window only if mark is on
This avoids unneeded full redraws for simple cursor movements.

This addresses https://savannah.gnu.org/bugs/?68105.

Problem existed since whole-window sideways scrolling was introduced
in commit 7779a199 from five weeks ago.
2026-03-01 11:29:50 +01:00
Benno Schulenberg
a63141ecf4 tweaks: give the three "debugging" feedback messages a more unusual color
In this way they stand out from the usual status-bar feedback and errors.
2026-03-01 09:30:28 +01:00
Benno Schulenberg
dd50adb61b docs: reshuffle the --solosidescroll option to match the order in --help 2026-03-01 09:30:28 +01:00
Benno Schulenberg
4694c95524 build: exclude whole-window sideways scrolling from the tiny version
Let the tiny version scroll sideways only the current line, always.
(It then does not need the --solosidescroll option either.)
2026-03-01 09:30:28 +01:00
Benno Schulenberg
49be1275e6 syntax: guile: colorize more syntax words and procedure names
Also, colorize more quoted symbols and booleans, make the green for
syntax words and the blue for keywords lighter, and show comments
in grey italics.  Also, don't miscolorize some empty strings as if
they were the start of a multiline string.

This addresses most of https://savannah.gnu.org/patch/?10558.
2026-02-21 16:41:33 +01:00
Benno Schulenberg
8d49be96d6 syntaxes: add a license line to the files created by Mark Oteiza
He agreed to this by private email.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-02-19 17:22:18 +01:00
Benno Schulenberg
5df0b2e41a tweaks: no need to be overpolite when giving directions
(When requesting bug reports, then it's okay to say "please".)
2026-02-18 16:17:03 +01:00
Benno Schulenberg
07f84b7b61 tweaks: replace the three instances of impersonal "one" with direct "you"
This better matches the style in the rest of the manual.
2026-02-18 16:17:03 +01:00
Benno Schulenberg
083d6c70ee tweaks: lowercase subsequent words in section titles, to be less pompous 2026-02-18 16:17:03 +01:00
Benno Schulenberg
83ef26dc74 input: prevent also a string bind from breaking a chain of cuts or copies
The content of a string bind will probably break that chain, but the
keystroke itself (to which the string is bound) should not break it.
2026-02-18 16:10:05 +01:00
Benno Schulenberg
f1db15c7b6 input: prevent most toggles from breaking a series of cuts or copies
Only the cut-from-cursor toggle should break a chain of cuts or copies,
because it affects how those operations behave.  All other toggles have
no effect on those operations nor on the position of the cursor, so they
should not break a chain of cutting or copying keystrokes.

Achieve this by reshuffling a fragment of code to before the fragment
that triggers cutbuffer clearing for most operations.

(This has as interesting side effect that none of the toggles breaks a
chain of completions either.)

This fixes https://savannah.gnu.org/bugs/?68050.

Bug existed since version 4.3, commit 6c4f228f.
2026-02-18 16:10:05 +01:00
Benno Schulenberg
93ae8259c8 input: allow recordmacro and runmacro to continue cuts and copies
Starting the recording or replaying of a macro does not change anything
about the position of the cursor or the state of the buffer, so those
functions should not interrupt a series of cuts (^K) or copies (M-6).

This allows a macro to complete a series of cuts or copies that were
initiated manually (or by a previous macro).

This addresses https://savannah.gnu.org/bugs/?68046.
2026-02-15 12:32:05 +01:00
Benno Schulenberg
8771acb98a tweaks: slightly adjust a wording 2026-02-15 12:21:36 +01:00
Benno Schulenberg
a29c225b7a docs: add a section about the recording and replaying of keyboard macros
Also, move the text of the section about Limitations into this new
section, as the only documented limitation concerns macros.
2026-02-15 12:17:27 +01:00
Benno Schulenberg
db9ada1bf8 tweaks: move a function to a more logical place
Adding stuff to the macro buffer happens after recording has started
and before the macro is run.
2026-02-15 09:58:37 +01:00
Benno Schulenberg
1d3a8bc24e tweaks: reduce the scope of two variables 2026-02-15 09:50:50 +01:00
Charles Mirabile
00bfeb2dcf macro: cancel the recording if nothing was entered between start and stop
When the user stops a macro recording immediately after starting it,
cancel the recording and restore the macro that existed previously,
instead of storing a new empty macro.

This avoids overwriting an existing macro when the user realizes at
once that they've hit `recordmacro` instead of `runmacro`.

Signed-off-by: Charles Mirabile <cmirabil@redhat.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2026-02-15 09:34:44 +01:00
Benno Schulenberg
617c559628 syntax: python: require a blank after the keyword match
This avoids colorizing "match" in calls of re.match().

Reported-by: Stanislaw Majewski <essdoem@yahoo.com>
2026-02-11 16:50:10 +01:00
Benno Schulenberg
6b547f3afe tweaks: normalize brace placement after the previous change 2026-02-11 16:45:43 +01:00
Benno Schulenberg
a8dca7c918 display: let option --jumpyscrolling affect also sideways scrolling
When using --jumpy, the viewport scrolls vertically in steps of
half a screen (height).  Then it makes sense that the viewport
also scrolls horizontally in steps of half a screen (width).
2026-02-11 14:41:34 +01:00
Benno Schulenberg
965531485f tweaks: reorder a list of keys, starting with singles, ending with group 2026-02-11 14:37:25 +01:00
Benno Schulenberg
9419bc38de tweaks: condense the Python coloring rules, and reword a comment 2026-02-07 09:09:41 +01:00
Benno Schulenberg
1b7e24dc30 docs: copy the 8.7.1 news item from the release branch 2026-02-07 08:22:23 +01:00
Benno Schulenberg
bf194dae5d syntax: python: colorize also the match and case keywords
These keywords were introduced in Python-3.10:
  https://docs.python.org/3/whatsnew/3.10.html#pep-634-structural-pattern-matching

Reported-by: Stanislaw Majewski <essdoem@yahoo.com>
2026-02-03 16:37:37 +01:00
Benno Schulenberg
46a015c624 docs: add a notice about the changed sideways scrolling behavior
And mention how to get the old behavior back.
2026-01-31 15:49:03 +01:00
Benno Schulenberg
20c554c9b3 docs: add an Exit Status section to the man page and the manual
And correct and improve the description of the `discardbuffer`
bindable function.

This addresses https://savannah.gnu.org/bugs/?67979.
Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2026-01-31 11:44:24 +01:00
Benno Schulenberg
c5902343bd display: store brink per buffer, to keep the viewport stable
This fixes https://savannah.gnu.org/bugs/?67993.

Bug existed since whole-window sideways scrolling was introduced
in commit 7779a199 from last week.
2026-01-31 08:49:10 +01:00
Benno Schulenberg
aca7face38 build: avoid three warnings when compiling against glibc-2.43
Functions like strchr() now return 'const char' instead of just 'char'.

This addresses the second part of https://savannah.gnu.org/bugs/?67954.
Reported-by: Rudi Heitbaum <rudi@heitbaum.com>
2026-01-30 08:58:20 +01:00
Benno Schulenberg
5131dca77f gnulib: update to a recent version, to allow compiling against glibc-2.43
Parentheses were missing in the declaration of wmemchr().
They were added two months ago in gnulib commit df17f4f37e.

This addresses the first part of https://savannah.gnu.org/bugs/?67954.
Reported-by: Rudi Heitbaum <rudi@heitbaum.com>
2026-01-30 08:58:06 +01:00
869f75830d Merge in master 2026-01-24 20:32:53 -08:00
Benno Schulenberg
2e2a40ea09 docs: document the new --solosidescroll and 'set solosidescroll' options
These re-enable the historical jerky single-line sideways scrolling.
2026-01-23 17:37:03 +01:00
Benno Schulenberg
38f87fb5c3 display: add extra variable, to avoid one-way toggling of SOLO_SIDESCROLL
Panning should not be switched off for the whole session
when the window became too narrow at some point.
2026-01-23 17:37:03 +01:00
Benno Schulenberg
f6297f0933 display: for narrow windows, fall back to single-line sidescrolling
Otherwise the cursor can get misplaced sometimes.
2026-01-23 17:37:03 +01:00
Benno Schulenberg
a7e8dd7d6b options: accept --solosidescroll and 'set solosidescroll'
These options activate the old, jerky, single-line sideways scrolling
instead of the new default smooth whole-window sideways scrolling.
2026-01-23 17:37:03 +01:00
Benno Schulenberg
7779a19903 new default feature: smooth whole-window sideways scrolling
Instead of horizontally scrolling just the current line by nearly
a screen width when the cursor is about to go offscreen, now all
screen lines are scrolled horizontally together by just the amount
needed to keep the cursor comfortably in view.

References:
  https://lists.gnu.org/archive/html/nano-devel/2026-01/msg00000.html
  https://lists.gnu.org/archive/html/nano-devel/2026-01/msg00003.html
  https://lists.gnu.org/archive/html/nano-devel/2014-05/msg00025.html
  https://lists.gnu.org/archive/html/nano-devel/2014-06/msg00152.html

Nano could have acquired this feature nearly twelve years ago, but...
somehow that old patch fell through the cracks and was forgotten.  :|

Motivated-by: Xylia Allegretta <xylia.allegretta@gmail.com>
Original-patch-by: Mark Majeres <mark@engine12.com>
2026-01-23 17:37:03 +01:00
Benno Schulenberg
255845cc13 tweaks: correct a comment 2026-01-23 16:27:10 +01:00
244b25c88a Merge branch 'master' of https://git.savannah.gnu.org/git/nano into line-folding 2026-01-18 20:21:38 -08:00
Benno Schulenberg
f7c96dba4a copyright: update the years for the FSF 2026-01-17 12:12:55 +01:00
Benno Schulenberg
299aab6acf tweaks: refer to two renamed gnulib modules with their adjusted names 2025-12-06 12:11:05 +01:00
Benno Schulenberg
3295ca6bd8 copyright: update the years for significantly changed files 2025-11-27 11:27:31 +01:00
Benno Schulenberg
632542462a tweaks: rename two functions, reword some comments, rewrap a line 2025-11-24 15:23:02 +01:00
Benno Schulenberg
bd72b21c18 mouse: allow clicking before the answer to place cursor at its beginning
In the prompt bar, clicking beyond the end of the answer places the
cursor at the end of the answer.  Then it makes sense that clicking
before the beginning of the answer places the cursor at its beginning.
2025-11-24 13:07:30 +01:00
Benno Schulenberg
31fc5194b2 new feature: clicking in the scrollbar jumps to the corresponding line
With --mouse and --indicator, clicking in the rightmost column of
the edit window (the "scrollbar" area) now makes the cursor jump
to the line that places the indicator at the clicked position.

Inspired-by: Firefox, and originally by tilde and fte.
2025-11-24 11:21:08 +01:00
Benno Schulenberg
fc1d88a00f tweaks: avoid having to restore the original click coordinates
When going to handle clicks on shortcuts, the help lines are present,
so we know exactly where the prompt is (third line from the bottom),
so there is no need to first convert the coordinates to be relative
to the bottom window and then restore them when `mouse_y` is zero.
2025-11-24 11:05:23 +01:00
Benno Schulenberg
54e1619d6e tweaks: condense two oververbose comments 2025-11-24 11:05:23 +01:00
Benno Schulenberg
b4246d2cac tweaks: remove an unneeded parameter from get_mouseinput()
Only the Yes-No routine handles clicks on shortcuts itself, so just
exclude that menu from the shortcut handling by mouse, instead of
burdening every call with an unclear parameter.
2025-11-24 11:05:23 +01:00
Benno Schulenberg
3539d4862e tweaks: add a comment for an unclear fragment of code 2025-11-22 17:39:57 +01:00
Benno Schulenberg
1457013c53 docs: explain what "overlong" means for --breaklonglines
Inspired-by-a-report-from: Sébastien Desreux <seb@h-k.fr>
2025-11-21 16:45:45 +01:00
Benno Schulenberg
c32fdec09f tweaks: slightly improve three comments in the sample nanorc 2025-11-21 12:05:31 +01:00
Benno Schulenberg
3b983dd889 files: include also the slash when re-adding the filename to the path
Otherwise a mistaken name gets recorded in the file-positions history.

Buglet existed since version 6.1, commit fdd946c0.
2025-11-19 11:48:12 +01:00
Benno Schulenberg
71c60563a2 tweaks: reshuffle or transmute a few lines, to elide an 'if' 2025-11-14 10:17:17 +01:00
Benno Schulenberg
fd531c248e po: update translations and regenerate POT file and PO files 2025-11-12 10:48:25 +01:00
Benno Schulenberg
9735af4d78 bump version numbers and add a news item for the 8.7 release 2025-11-12 08:35:56 +01:00
Benno Schulenberg
88aa9157d1 gnulib: update to its current upstream state 2025-11-11 11:24:21 +01:00
Benno Schulenberg
2593572392 tweaks: improve a few comments, drop one, and unwrap some lines 2025-10-31 10:17:44 +01:00
Benno Schulenberg
e83e1ca4e3 display: regenerate the screen after a resize during a spell check
This refixes https://savannah.gnu.org/bugs/?56033.

This became needed after the previous commit removed the regeneration
of the screen from the blocking/unblocking of SIGWINCHes.
2025-10-29 07:49:56 +01:00
Benno Schulenberg
75ed9e4d55 display: regenerate the screen only before and after waiting for input
Otherwise a SIGWINCH could occur between finalizing the reading of the
specified files and becoming ready for user input, which would result
in the first keystroke getting transformed into the THE_WINDOW_RESIZED
meta symbol, and thus effectively being discarded.

This fixes the third part of https://savannah.gnu.org/bugs/?67635.
The issue was reported by `twofiftysix`.

Buglet has existed for a long time.
2025-10-29 07:49:56 +01:00
Benno Schulenberg
3c129ffded tweaks: reshuffle some #ifdefs, and rename a function 2025-10-29 07:49:56 +01:00
Benno Schulenberg
6136b28af7 startup: register the handler for SIGWINCH much earlier
Otherwise nano is deaf for SIGWINCHes during several milliseconds,
which can cause it to start off with wrong dimensions.

This fixes the second part of https://savannah.gnu.org/bugs/?67635.
The issue was reported, and the solution suggested, by `twofiftysix`.

Buglet has existed for a long time.
2025-10-29 07:48:02 +01:00
Benno Schulenberg
c11569fb99 display: upon resize, redraw the subwindows only when fully initialized
Otherwise 'currmenu' still has an invalid value, causing a division by
zero in bottombars() because shown_entries_for() returns zero.

This fixes the first part of https://savannah.gnu.org/bugs/?67635.
The issue was reported by `twofiftysix`.

Bug existed since version 8.6, commit 09d574ba.
2025-10-28 12:04:04 +01:00
Benno Schulenberg
a23ad70e0e tweaks: improve the punctuation of one item in the sample nanorc 2025-10-27 15:00:33 +01:00
Benno Schulenberg
e1df83c885 build: avoid a warning when configured with --disable-multibuffer 2025-10-26 11:55:10 +01:00
Benno Schulenberg
ffc456ebac docs: add example of copy-to-clipboard-with-OSC52 to the sample nanorc 2025-10-14 11:23:09 +02:00
Benno Schulenberg
4b7ec23db3 new feature: execute a command without capturing the output
The feature is activated by preceding the command with two pipes (||).
This lets the command's output go to the terminal, enabling the user
to implement the OSC52 copy-to-clipboard command with a string bind:

  bind M-* "{execute}|| printf "\033]52;c;%s\007" "$(base64 | tr -d '\n')" {enter}{undo}" main

This keystroke now copies the buffer (or the selected region) to the
local system clipboard, also when nano is running on a remote host --
if and when the used terminal implements the OSC52 command.

Inspired-by: Alessandro Carminati <alessandro.carminati@gmail.com>
2025-10-12 12:50:24 +02:00
Benno Schulenberg
50e186bc81 moving: prevent a negative relative jump from going beyond top of buffer
This fixes https://savannah.gnu.org/bugs/?67581.
Reported-by: Ivan Vorontsov <ivrntsv@yandex.ru>

Bug existed since version 8.6, since relative jumps were introduced.
2025-10-05 12:22:32 +02:00
Benno Schulenberg
3823e8e209 tweaks: unwrap three lines, for esthetics 2025-10-05 12:21:38 +02:00
Benno Schulenberg
f08c0300ce text: when blanking a line due to --autoindent, keep the mark in sync
When Enter is pressed at the end of a line that contains only blanks
while --autoindent is in effect, and thus this line gets emptied, then
the mark should be adjusted accordingly (when somewhere on this line).

This fixes https://savannah.gnu.org/bugs/?67578.
The issue was reported by `correctmost`.

Bug existed since version 2.8.1, commit 005ee8ed, but
became more exposed since version 4.0, commit f7f5514e.
2025-10-05 11:56:18 +02:00
Benno Schulenberg
43f0618f77 tweaks: replace a remaining double dash with a true emdash
Also, avoid a cluster of parentheses by replacing two with an emdash.
2025-09-09 10:34:02 +02:00
Benno Schulenberg
54c7709964 docs: mention that execute can pipe buffer or region to the command
(This should have been part of commit a18b48f0 from seven years ago.)
2025-09-06 16:22:10 +02:00
Benno Schulenberg
326e4146b2 po: update translations and regenerate POT file and PO files 2025-08-21 08:06:48 +02:00
Benno Schulenberg
fd5900c252 bump version numbers and add a news item for the 8.6 release 2025-08-20 12:44:42 +02:00
Benno Schulenberg
74faba1251 gnulib: update to its current upstream state 2025-08-20 08:37:08 +02:00
Benno Schulenberg
70e580c002 completion: don't stop looking for candidates one byte too early
This fixes https://savannah.gnu.org/bugs/?67405.
Reported-by: Ivan Vorontsov <ivrntsv@yandex.ru>

Bug existed since version 2.7.2, since word completion was introduced.
2025-08-07 15:40:29 +02:00
Benno Schulenberg
1ee74172c2 rcfile: accept also {}} in a string bind, for symmetry with {{} 2025-08-02 09:48:05 +02:00
625e1b9d12 Merge remote-tracking branch 'upstream/master' into line-folding 2025-07-29 16:16:07 -07:00
Benno Schulenberg
121dd596d9 tweaks: swap two symbolic menu names, for giggles 2025-07-10 12:02:14 +02:00
Benno Schulenberg
ea5e199d3b browser: let a refresh also reread the file list, like it used to
Until two commits ago, a full refresh (^L) would first refresh the
screen and then reread the file list and redo the screen again.
Now it will just reread the list and redo the screen, skipping the
redundant refresh.  The latter is done only for the tiny version.

Also rename a label, to be more precise.
2025-07-10 10:04:39 +02:00
Benno Schulenberg
e7c28bcb66 browser: redo the layout only when an actual resize occurred
This improves upon the previous commit.

This fixes https://savannah.gnu.org/bugs/?67294 in a better way.
2025-07-10 09:49:45 +02:00
Benno Schulenberg
21207b47a0 browser: redo the layout when the window _might_ have resized
The user may have resized the window not only while in the help viewer
but also while at the Search or Goto prompt.  Ensure that after all of
them the browser rebuilds the list according to the current dimensions.

This fixes https://savannah.gnu.org/bugs/?67294.

Bug existed since version 2.5.3, commit 813f9f72.
2025-07-09 16:07:45 +02:00
Benno Schulenberg
09d574bae9 display: when resizing, redraw the bottom bars also when in file browser
This fixes https://savannah.gnu.org/bugs/?67293.

Bug existed since version 8.2, commit fe0b928b.
2025-07-09 11:37:18 +02:00
Benno Schulenberg
b68d74effc syntax: po: colorize also the %b and %B format specifiers
Glibc's printf() recognizes these specifiers since version 2.35:
  https://sourceware.org/pipermail/libc-announce/2022/000033.html
2025-07-08 16:05:25 +02:00
Benno Schulenberg
88309f981a tweaks: put two related checks together, like they are elsewhere 2025-07-06 15:01:26 +02:00
Benno Schulenberg
653432b6a8 tweaks: reshuffle some lines, to group things better 2025-07-06 11:43:10 +02:00
Benno Schulenberg
4d4c231dad tweaks: use a direct parameter instead of an intermediary boolean
The intermediary boolean is needed in search_init(), which contains
a loop and several toggles, but it's not needed here.
2025-07-06 11:43:10 +02:00
Benno Schulenberg
a195ba6cc0 tweaks: rename a parameter, and invert its logic 2025-07-05 14:22:11 +02:00
Benno Schulenberg
e05b7a5cd5 tweaks: normalize the indentation after the previous change 2025-07-05 14:22:11 +02:00
Benno Schulenberg
2a51d35e25 tweaks: split the goto function into an interactive and command-line one 2025-07-05 14:22:11 +02:00
Benno Schulenberg
d7e427daac tweaks: reshuffle a condition to a better place, like it is elsewhere 2025-07-03 13:01:55 +02:00
Benno Schulenberg
ee37afd1e2 tweaks: reshuffle a few lines, for density and to elide an 'else' 2025-07-03 11:41:15 +02:00
Benno Schulenberg
d2e261d873 history: do not forget anchors when line number is given on command line
When a line number is given on the command line, the position-history
file needs to be read first, because it might contain saved anchors.

(Before placing the cursor on the given line, or searching for a given
string, the current position now needs to be set back to top-of-file,
as otherwise the saved column position is likely to be inherited, or
the search will start from the inherited position.)

This fixes https://savannah.gnu.org/bugs/?67272.

Bug existed since version 8.5, commit 60e2f2ba,
since the saving of anchors was introduced.
2025-07-03 11:28:53 +02:00
Benno Schulenberg
2525291ef0 docs: document the ++/-- prefix feature for the gotoline function 2025-07-02 15:02:09 +02:00
Benno Schulenberg
124b41acdb new feature: interpret a line number prefixed with ++ or -- as relative
This permits jumping a precise number of lines forward or backward.

Inspired-by: Brian Sandro <email@bsandro.tech>
2025-07-02 15:01:44 +02:00
Benno Schulenberg
2ce71a1332 tweaks: remove a check for a symbol that never gets defined
Twelve years ago, commit 2e4228f7 added a check for the 'ncursesw/
ncurses.h' header file.  A week later commit 66e5972c removed that
check again, but forgot to remove the corresponding #ifdef.

This addresses https://savannah.gnu.org/bugs/?67225.
2025-06-20 10:51:04 +02:00
Benno Schulenberg
a74e326448 po: update translations and regenerate POT file and PO files 2025-06-12 09:35:40 +02:00
Benno Schulenberg
173cd01731 docs: baptize the release 2025-06-12 09:24:23 +02:00
Benno Schulenberg
737f4057fb bump version numbers and add a news item for the 8.5 release 2025-06-12 09:09:45 +02:00
Benno Schulenberg
62966d085f gnulib: update to its current upstream state 2025-06-11 16:20:22 +02:00
Benno Schulenberg
8036d4beaa build: fix compilation when configured with --disable-histories
In a tiny nano, there are no anchors, so none need saving/restoring.
2025-06-09 12:31:02 +02:00
Benno Schulenberg
14f17c3601 tweaks: use the correct modifier, to avoid a warning on 32-bit machines 2025-06-08 14:07:06 +02:00
Benno Schulenberg
8cfa180fae docs: reword the descriptions of --operatingdir and 'set operatingdir' 2025-05-30 10:22:22 +02:00
Benno Schulenberg
e95469bcbb tweaks: properly tag some keywords in texi doc, instead of using quotes 2025-05-29 14:20:06 +02:00
Benno Schulenberg
cf71d761dc tweaks: shorten a URL, and update it to use https 2025-05-25 12:37:44 +02:00
Benno Schulenberg
c2b9211bd5 build: fix compilation for config with --enable-tiny --enable-histories 2025-05-22 14:38:48 +02:00
Benno Schulenberg
7a7405571c tweaks: rename 'use_utf8' to 'using_utf8', and make it a global variable
This elides a function call in some parts of the code.
2025-05-21 13:48:55 +02:00
Benno Schulenberg
1270657602 tweaks: elide the unneeded use of an auxiliary function 2025-05-21 11:55:05 +02:00
Benno Schulenberg
6c80b97694 feedback: suppress "Removed anchor" when the mini bar is hidden
Showing only "Placed anchor" and not "Removed anchor" makes it possible
to notice without looking at the status bar whether an anchor has been
placed or removed.  (The mini bar is not just a different interface but
is also about minimizing status-bar output.)
2025-05-20 10:39:51 +02:00
Benno Schulenberg
e6b087bcae feedback: suppress "Jumped to anchor" when line numbers are active
When line numbers are present, any anchors are displayed in the margin,
so it should be rather obvious where the cursor jumped to -- no need to
mention this on the status bar.
2025-05-20 10:39:45 +02:00
Benno Schulenberg
a0918c5e98 tweaks: random unimportant edits here and there 2025-05-18 12:34:07 +02:00
Benno Schulenberg
879885a736 tweaks: use reallocations, instead of new allocations plus frees
Probably more than half of the reallocations will be no-ops, so
this should be faster.
2025-05-18 12:27:18 +02:00
Benno Schulenberg
155258e06e docs: add a suggested key combo for wiping all anchors to sample nanorc 2025-05-18 09:42:41 +02:00
Benno Schulenberg
06e48df8a3 feedback: report the setting and removing of an anchor just once
When line numbers or the mini bar are active, there is no need for
the status-bar messages.  Only when both line numbers and mini bar
are absent, the feedback messages are needed.
2025-05-17 17:51:25 +02:00
Benno Schulenberg
88776e0eee docs: mention that --positionlog also saves the positions of anchors 2025-05-17 17:51:25 +02:00
Benno Schulenberg
9be62a6964 build: fix compilation when configured with --disable-utf8
Always include the function using_utf8(), to be able to avoid
the cluttering #ifdef that was removed in the previous commit.
2025-05-17 17:51:11 +02:00
Benno Schulenberg
c000917cda anchor: change the aspect of any anchor to a dagger (†)
Now that anchors are always saved, there is no need to differentiate
anchors that are saved (■) from anchors that will evaporate (⬥).

Choose a new appearance (†) to signal the changed behavior.
(And because I didn't much like the look of the block.)
2025-05-17 11:32:57 +02:00
Benno Schulenberg
76b87890d8 history: always save the positions of any anchors
Let the saving of anchors not depend on the presence of an anchor
on the first line.  That was a clever mechanism to allow avoiding
the unnecessary saving-of-anchors, but... it was awkward and ugly.
2025-05-17 11:32:57 +02:00
Benno Schulenberg
d0796bde4f history: always save the last cursor position, also for line=1,column=1
This may seem a little wasteful, as line=1,column=1 is the default
cursor position, but this change enables the next commit: always
saving any anchors.  In the bargain, the position-history file now
contains a list of all files that were recently opened with nano.
2025-05-17 11:31:48 +02:00
Benno Schulenberg
a6e7d5c99b tweaks: elide an auxiliary variable that is no longer needed 2025-05-17 09:14:28 +02:00
Benno Schulenberg
b37cc32de0 history: reverse the order in the file-positions list, to latest first
Putting the record for the last-edited file at the top of the list
ensures that (in case of a duplicate entry) the newest entry will
be encountered first and thus reused.  It also makes searching the
list faster, because the files that the user is likely to soon edit
again will be near the top of the list instead of near the end.

This fixes https://savannah.gnu.org/bugs/?67120.

Problem existed since version 2.3.0, since position logging was
introduced, but was aggravated by the recent anchor-saving code.
2025-05-17 08:55:45 +02:00
Benno Schulenberg
6d724f6d07 feedback: show in mini bar the presence of an anchor on the cursor line
And as the presence of an anchor is now visible in the mini bar,
the "Placed anchor"/"Removed anchor" messages are no longer needed
when the mini bar is active.
2025-05-14 15:51:45 +02:00
Benno Schulenberg
1cc19c8c6a feedback: change the appearance of anchors when they will be saved
When an anchor is present on the first line of the buffer, make any
anchors appear as little blocks (■) instead of the usual diamonds (⬥).

This different appearance lets the user know whether a placed anchor
anywhere in the file will be saved or not -- when line numbers are
active.  (In an 8-bit locale an = replaces the usual +).
2025-05-14 15:51:45 +02:00
Benno Schulenberg
60e2f2baf2 new feature: save and restore anchors when the first line has an anchor
When an anchor is placed on the first line in a buffer and --positionlog
is active, nano will now save the positions of the anchors when the file
is closed, and will restore the anchors when the file is reopened.

(The positions are stored in the file-positions history file, along
with the cursor position.)

This fulfills https://savannah.gnu.org/bugs/?62269.
Requested-by: Shi Yanling <sylphenix@126.com>
Requested-by: Sébastien Desreux <seb@h-k.fr>

Sponsored-by: Sébastien Desreux <https://doc-solus.fr>
2025-05-14 15:51:24 +02:00
Benno Schulenberg
b8c684193e tweaks: elide the unneeded passing around of three parameters
The function has_old_position() was used just twice, and both calls
were followed by basically the same call of goto_line_and_column().
So... move the latter call into the first function, to avoid the
unneeded passing back and forth of the line and column numbers.
2025-05-09 12:14:06 +02:00
Benno Schulenberg
84b1fdf6c6 syntaxes: add a license line to files that were created by Mike Frysinger
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2025-05-08 10:31:44 +02:00
Benno Schulenberg
2181853574 syntaxes: use character classes instead of range expressions
In some locales certain normal ASCII characters are not included in
the ranges [A-Z] and [a-z].  So, use [[:upper:]] and [[:lower:]]
instead, and [[:alpha:]] for [A-Za-z], and similarly for others.

This fixes https://savannah.gnu.org/bugs/?67094.
2025-05-08 10:24:49 +02:00
Benno Schulenberg
281197895f bindings: lowercase an ASCII character in a locale-proof manner
Calling tolower() on the 'I' (of "M-I") in a Turkish locale will not
return 'i' but 'I' instead.  This is because the lowercase of 'I' is
'ı' (a dotless i), which does not fit in an 8-bit character type, so
tolower() will return the 'I' unchanged.

This fixes https://savannah.gnu.org/bugs/?67092.

Buglet existed since before version 2.2.0.
2025-05-07 11:02:15 +02:00
Benno Schulenberg
d50e8feed9 tweaks: avoid using toupper() and tolower() where easily possible
Those functions can misbehave for some characters in certain locales.
2025-05-07 11:02:04 +02:00
Benno Schulenberg
8e104117a4 new feature: exit with an error status (2) for ^X^Q and ^O^Q
Nano used to exit always with a success status (0).  But now, if
the user wants to make nano report failure to a calling program,
they can use ^X^Q (when the buffer is modified) or ^O^Q (always).

This fulfills https://savannah.gnu.org/bugs/?65755.
2025-05-06 11:00:02 +02:00
Benno Schulenberg
b8b71399e8 menus: reshuffle an item, to avoid truncating its help-line label
The label "Discard buffer" is rather long (and is in most translations),
so make the item the last-but-one so that it effectively has the space
for two labels available (because the number of items in the WriteOut
menu is currently uneven).
2025-05-05 13:39:34 +02:00
Benno Schulenberg
fb78eea6fc bindings: always bind ^Q in the WriteOut menu, not only for --saveonexit
This gives the user a keystroke combo (for abandonning a buffer) that is
always the same, no matter whether the buffer is modified or not: ^O^Q.
2025-05-05 12:45:49 +02:00
Benno Schulenberg
a942be9f6f feedback: change the level of a certain message, to show it is special 2025-05-04 12:02:05 +02:00
Benno Schulenberg
34db8682b3 moving: make cycling (M-%) independent from centering (^L)
The first strike of M-% should always try to center the cursor,
also when the preceding keystroke was ^L.
2025-05-03 10:12:49 +02:00
Benno Schulenberg
61dee21466 bindings: let ^L just center the cursor, not cycle it -- let M-% cycle it
In my experience the default cycling behavior of ^L was puzzling:
hitting ^L twice left me wondering sometimes: where is the cursor?

Inspired-by: Peter Michaux <petermichaux@gmail.com>
2025-04-28 12:53:49 +02:00
Benno Schulenberg
820f68f147 bindings: do not list ^L twice (in main help text and help lines)
In my eyes this wasn't really a problem, but... better be precise.

Reported-by: Peter Michaux <petermichaux@gmail.com>
2025-04-28 12:20:25 +02:00
Benno Schulenberg
fabc1e1219 syntax: default: show hard spaces with a lightgrey background
Some keyboard layouts allow typing hard spaces (U+00A0),
which means that sometimes they can get typed by accident.
Colorize those spaces to make such accidents noticeable.

Inspired-by: Sébastien Desreux <seb@h-k.fr>
2025-04-26 12:18:42 +02:00
Benno Schulenberg
2fec40e2ec docs: in cheatsheet, equalize the spacing in three consecutive blocks 2025-04-26 11:45:07 +02:00
Benno Schulenberg
95731b800d options: accept --whitespacedisplay and 'set whitespacedisplay'
Allow some people to use 'set whitespacedisplay' in their rcfiles
(or --whitespacedisplay on the command line), but leave the option
undocumented as I think it shouldn't exist.
2025-04-25 17:07:28 +02:00
Benno Schulenberg
3142d471e1 build: swap two linker arguments, to enable compilation on Cygwin
Since nano-8.1 (which moved to gettext-0.20), compiling on Cygwin
failed with: "undefined reference to `libintl_dgettext'".  Avoid
this by moving the '-lintl' argument to after the gnulib one.

Reported-by: Philippe Baril Lecavalier <pbl.ltx@gmail.com>
2025-04-24 09:41:15 +02:00
Benno Schulenberg
045664107e tweaks: in the browser, implement M-\ and M-/ in a slightly denser way
Inspired-by: Peter Michaux <petermichaux@gmail.com>
2025-04-23 11:50:18 +02:00
Peter Michaux
e512466ff0 build: add the 'm4/host-cpu-c-abi.m4' file to .gitignore
For some reason `autopoint` from gettext-0.20 (used since nano-8.1)
started to include the 'm4/host-cpu-c-abi.m4' file.  Ignore it, to
prevent it from accidentally getting tracked.

Signed-off-by: Peter Michaux <petermichaux@gmail.com>
2025-04-22 12:05:25 +02:00
Benno Schulenberg
131849e7e8 gnulib: pull in the fix for a cross-compilation failure
This addresses https://savannah.gnu.org/bugs/?66978.
Reported-by: Chris Renshaw <osm0sis@outlook.com>
2025-04-14 10:52:12 +02:00
9a96973b00 Merge branch 'master' of https://git.savannah.gnu.org/git/nano into line-folding 2025-04-02 15:23:18 -07:00
Benno Schulenberg
186896f072 po: update translations and regenerate POT file and PO files 2025-04-02 11:07:28 +02:00
Benno Schulenberg
78eb483bc2 bump version numbers and add a news item for the 8.4 release 2025-04-02 09:29:24 +02:00
Benno Schulenberg
c7033324a9 gnulib: update to its current upstream state 2025-03-24 10:27:28 +01:00
Benno Schulenberg
334604a591 syntax: po: colorize also format specifiers like "%.6f" 2025-03-17 12:48:04 +01:00
Benno Schulenberg
7905ba80ea docs: add a suggestion to the FAQ on how to configure nano for git 2025-03-17 12:47:15 +01:00
Benno Schulenberg
ccff4685df docs: in the FAQ, replace an old item with an item about Byte Order Marks 2025-03-15 12:08:20 +01:00
Benno Schulenberg
0167f78dca feedback: warn when the cursor sits on a Byte Order Mark (BOM)
The ceck is only done at the start of a line, because in other places
the BOM will be glued to the preceding character.

This partially addresses https://bugs.debian.org/964901.
Reported-by: Nils König <oneric@oneric.de>
2025-03-15 09:17:01 +01:00
Benno Schulenberg
282ec08e5e docs: change two interface colors in the sample nanorc
For esthetics, and to showcase possibilities.
2025-03-14 11:48:29 +01:00
Benno Schulenberg
5efb7f31df tweaks: add a translator hint for the three changed file-writing prompts 2025-03-14 08:07:23 +01:00
Benno Schulenberg
bf39ffe903 prompt: accept tabs in an external paste as literal tabs
This fixes https://savannah.gnu.org/bugs/?66892.

Buglet existed since before version 2.0.0.
2025-03-12 16:59:58 +01:00
Benno Schulenberg
f2c30aa437 prompt: beep when an external paste contains a command code
Until the previous commit, nano used to beep for any command code
in an external paste.  It's better to continue doing that.

(When pasting multiple lines, it's debatable whether nano should
beep for each discarded CR.  But for any other command code, it
definitely should beep.  Maybe it should even show a message.)
2025-03-11 16:27:08 +01:00
Benno Schulenberg
bf12c90b07 input: implement bracketed pastes in a different manner
Ask ncurses to recognize the escape sequences that mark the start
and end of a bracketed paste, and thus benefit from the waiting that
ncurses does for an escape sequence to complete.  This helps prevent
nano from failing to recognize an end-of-paste sequence (resulting
in hanging or inserting some sequence characters into the buffer).

This addresses https://savannah.gnu.org/bugs/?66858 in a better way.
Reported-by: Doug Smythies <dsmythies@telus.net>
2025-03-10 17:17:07 +01:00
Benno Schulenberg
615570cf5e tweaks: remove two commented-out lines and two unused variables
And harmonize some whitespace.
2025-03-09 10:25:45 +01:00
Benno Schulenberg
aff9f4742c input: remove single-keycode detection from the bracketed-paste routine
It interferes with an upcoming change.
2025-03-08 12:08:30 +01:00
Benno Schulenberg
31a2cc9d76 tweaks: swap two fragments of code, to allow unwrapping a line 2025-03-08 12:07:49 +01:00
Benno Schulenberg
9c6a62d319 tweaks: remove an unwanted newline from a debugging message 2025-03-06 12:19:29 +01:00
Benno Schulenberg
38c8845b05 input: remove a special-case workaround
Let the more general flaw handling (added in commit 41c1b962, and
amended in the previous commit) handle also this case: it's better
to let the user know that they are using poor pasting software than
to silently work around the issue.

This effectively reverts commit 555a9878 from last week.
2025-03-06 09:42:53 +01:00
Benno Schulenberg
934d122dd4 input: robustness is good, but dropping a key code is not a good idea
If (on a bogged-down computer) a paste goes so slow that the bytes
come in one by one, nano shouldn't discard any of them -- the user
is unlikely to appreciate this.  Just switch the bracketed paste
off, for the possibility that the closing sequence went missing,
and accept that this closing sequence gets pasted into the buffer.
2025-03-06 09:42:43 +01:00
Benno Schulenberg
f8de98f7cd tweaks: condense a fragment of code 2025-03-04 16:44:32 +01:00
Benno Schulenberg
ef7f825d97 input: adjust file browser and help viewer for changed bracketed pastes
Since the previous commit, the escape-sequence-parsing code does not
set 'bracketed_paste' to FALSE any more when the closing sequence is
deficient.  So, the browser and viewer need to do that themselves.

Also, instead of just beeping and wordlessly discarding a paste when
it's done in the file browser or help viewer, report that it is being
ignored.  This is much more friendly.
2025-03-04 16:44:32 +01:00
Benno Schulenberg
41c1b9623e input: make bracketed paste more robust against loss of closing sequence
A bracketed paste should be one large batch (or several batches)
of bytes, not single bytes coming in one by one.  When the latter
happens, assume the end-of-paste sequence got swallowed somehow,
stop the bracketed paste and display a warning, while discarding
the first byte that came in alone.

This change was inspired by this report from Doug Smythies:
  https://lists.gnu.org/archive/html/nano-devel/2025-02/msg00001.html
2025-03-04 16:44:32 +01:00
Benno Schulenberg
555a987844 input: wait a bit for "~" when bracketed-paste sequence is incomplete
When pasting something into nano over OpenSSH_for_Windows, the final
tilde of the end-of-paste sequence can lag some 29 ms behind the rest
of the sequence, causing ncurses to split it off into a next batch of
bytes.  Accommodate for this by noticing the missing tilde and then
waiting at most one second for it to arrive.  This prevents the tilde
from appearing spuriously in the buffer after the paste.

This addresses https://savannah.gnu.org/bugs/?66858.
Reported-by: Doug Smythies <dsmythies@telus.net>
2025-03-04 16:44:32 +01:00
1d4ac090d8 Merge branch 'master' of https://git.savannah.gnu.org/git/nano into line-folding 2025-02-28 11:42:40 -08:00
Benno Schulenberg
c1df6dfd05 execute: retain what the user typed before a tool was invoked
When the user types something at the Execute prompt and then invokes
one of the six tools or special functions (that don't take any input),
stash the typed string and restore it upon the next invocation of the
Execute menu.  This way the typed string is not lost when the tool or
special function was invoked by accident -- which it likely was, as
those tools and functions don't take any input from the prompt.

This addresses https://savannah.gnu.org/bugs/?66637.
Suggested-by: Evgeny Pestov <fsdhfhhf@gmail.com>
2025-02-28 17:12:43 +01:00
Benno Schulenberg
163c569919 syntax: po: colorize also format specifiers like "%<PRIu64>" 2025-02-28 11:34:42 +01:00
Benno Schulenberg
63a7be115a syntax: po: colorize also a 'msgctxt' line, and the 'c++-format' flag 2025-02-20 13:49:03 +01:00
Benno Schulenberg
fed31f2a79 syntax: po: colorize also Python's "%(name)x" format specifiers 2025-02-17 13:58:35 +01:00
Benno Schulenberg
5d496b3152 syntax: po: colorize also the Python-specific conversion specifier "%r" 2025-02-16 09:44:18 +01:00
Benno Schulenberg
f5a2b8983d syntax: groff: highlight the zeroeth macro argument too
It is used in some .tmac files.
2025-02-15 17:47:20 +01:00
Benno Schulenberg
8f44800588 tweaks: add missing closing quotes, as reported by mandoc -T lint ... 2025-02-15 17:44:16 +01:00
Benno Schulenberg
68c9b6af07 tweaks: prevent some more keywords from getting hyphenated 2025-02-14 17:22:38 +01:00
Benno Schulenberg
8536b4bfcb tweaks: prevent some color keywords from getting hyphenated in man page 2025-02-14 16:50:16 +01:00
Benno Schulenberg
0694c616a2 syntax: man: highlight some escapes, like \& and \(em, specially
This helps prevent reading things like \e and \(em as text.
2025-02-14 16:42:45 +01:00
Benno Schulenberg
8e456bab9f docs: use proper emdashes instead of double hyphens: "--" => "\(em"
Also, remove redundant double quotes, protect single quotes from
possibly getting misinterpreted, and protect periods from getting
treated as end-of-sentence.  Also, use \e instead of \\.

(Overlong lines are left alone -- they don't bother me.)

This partially addresses https://bugs.debian.org/1095957.
Reported-by: Bjarni Ingi Gislason <bjarniig@simnet.is>
2025-02-14 16:29:13 +01:00
Benno Schulenberg
aa663ae386 tweaks: consistently use "\fR" for switching back to normal, roman font 2025-02-12 09:34:29 +01:00
Benno Schulenberg
01c8ffd61f tweaks: avoid running tolower() on an out-of-range value
Functions like tolower() expect characters in the range -1..255.

Reference: https://savannah.gnu.org/bugs/?50289.

The other occurrences of toupper(), tolower(), and isxdigit() that
don't do a cast are fine, because the values of 'code' or 'keycode'
are already guaranteed to be in range by the surrounding code.
2025-02-12 09:34:06 +01:00
Benno Schulenberg
58c7358cb3 tweaks: change the man-page markup of options that take an argument
This is an attempt to work around a bug in the Debian HTML-renderer of
manual pages: see how after "-C" everything is in italics [1], instead
of just the "directory" arguments.  (The renderer for Arch Linux does
even worse, showing the first argument in bold italics [2].)

The old markup was fine, though, as `groff` had no problem generating
properly formatted HTML [3].

[1] https://manpages.debian.org/bookworm/nano/nano.1.en.html
[2] https://man.archlinux.org/man/nano.1.en
[3] https://nano-editor.org/dist/v7/nano.1.html
2025-02-10 16:34:15 +01:00
Benno Schulenberg
1a150bf544 syntax: po: colorize also the %llu and %hhi format specifiers
And colorize %% only by itself, not combined with anything.
2025-02-10 11:04:06 +01:00
Benno Schulenberg
98bab0db07 docs: improve the description of the constantshow bindable function
And of the '--constantshow' and 'set constantshow' options.
2025-01-20 15:25:40 +01:00
Brand Huntsman
b9c65193af files: improve the wording of the normal file-writing prompts
Make them similar to the prompts for writing out a selection.

Signed-off-by: Brand Huntsman <alpha@qzx.com>

(The change was first proposed seven years ago as part of a patch set:
  https://lists.gnu.org/archive/html/nano-devel/2018-02/msg00144.html,
then reposted by myself:
  https://lists.gnu.org/archive/html/nano-devel/2018-02/msg00147.html,
and then... forgotten.)
2025-01-17 11:11:04 +01:00
Benno Schulenberg
20403ef8bb copyright: update the years for the FSF 2025-01-14 11:00:11 +01:00
Benno Schulenberg
e26cdd3dab tweaks: remove three redundant pairs of parentheses from a nanorc regex 2025-01-12 12:32:27 +01:00
Benno Schulenberg
2065713e5c docs: replace a word that is better not used in the plural
Noted by https://fossies.org/linux/misc/nano-8.3.tar.xz/codespell.html.
2024-12-24 17:14:23 +01:00
Benno Schulenberg
a9cf841042 po: update translations and regenerate POT file and PO files 2024-12-21 11:55:15 +01:00
Benno Schulenberg
46466530a5 bump version numbers and add a news item for the 8.3 release 2024-12-21 11:23:05 +01:00
Benno Schulenberg
94ed548366 gnulib: update to its current upstream state 2024-12-20 12:15:44 +01:00
Benno Schulenberg
1e4c69baa7 tweaks: adjust another translator hint, and add two more
The "Prev Line"/"Next Line" tags are shown in the help viewer,
so on an 80-column terminal they may be only 10 cells wide.
2024-12-16 11:16:10 +01:00
Benno Schulenberg
f04c1a6ab5 syntax: markdown: accept also digit 0 in a list marker
For ordered lists, 10., 20., 30., ... were not getting colorized.

Also, https://daringfireball.net/projects/markdown/dingus
accepts 0. by itself just fine as marker.

This addresses https://savannah.gnu.org/patch/?10492.
2024-12-15 11:39:06 +01:00
Benno Schulenberg
6393edf40a tweaks: add a small clarifying comment 2024-12-11 17:12:50 +01:00
Lukáš Zaoral
7fd38e88c1 memory: avoid a leak when linter aborts after producing parsable output
Any collected messages should be freed also after an
abnormal exit of the linter.

Buglet existed since version 2.4.1, commit f225991b.
2024-12-11 08:22:17 +01:00
Benno Schulenberg
ee66c13487 tweaks: adjust a translator hint, and add another one
For the affected four "tags" only 10 character cells are available
(on an 80-column terminal) since they are used in the help viewer.

For the other two "tags" 15 cells are available, as they are shown
only when the terminal is at least 380 columns wide.

Indirectly-reported-by: Rafael Fontenelle <rafaelff@gnome.org>
2024-11-24 17:41:04 +01:00
Benno Schulenberg
250192c603 tweaks: drop six unneeded casts
The cast is implied by the type of the assignee.
2024-11-24 17:41:02 +01:00
Benno Schulenberg
9d181a1cc6 build: fix a compilation error with gcc-15
Assigning a pointer to a boolean variable without a cast
is not accepted any more.

This addresses https://savannah.gnu.org/bugs/?66467.
Reported-by: Rudi Heitbaum <rudi@heitbaum.com>
2024-11-20 13:06:22 +01:00
LIU Hao
07a92c3988 syntax: asm: add end-of-word anchors to the keywords
Previously some of these regexes could color part of a directive;
for example, the `.int` part of `.intel_syntax`.

Signed-off-by: LIU Hao <lh_mouse@126.com>
2024-11-05 17:12:25 +01:00
Benno Schulenberg
e9b0a57490 docs: put a space after "|" and before "{enter}" in the sample nanorc
This makes the example bindings slightly more legible.

Also improve a comment.
2024-11-04 16:22:07 +01:00
Benno Schulenberg
2fca581095 syntax: groff: correct the mistaken .rof extension to .roff
Buglet existed since version 2.9.8, commit cdd637d6.
2024-10-23 11:14:48 +02:00
Benno Schulenberg
53afd90ad4 syntax: groff: recognize also the .mom extension
This addresses https://savannah.gnu.org/bugs/?66369.
Reported-by: Elfener <elfenermarcell@gmail.com>
2024-10-23 11:07:05 +02:00
Benno Schulenberg
d9ea07515b docs: clarify the possible effects of a misuse of braced function names
And fix a nearby grammatical mistake that was
caused by commit 77a8841d from four months ago.

Inspired-by: Max Gammache <bigjango13@gmail.com>
2024-10-20 17:19:27 +02:00
Benno Schulenberg
de82920819 docs: add Shift+PgUp/PgDown to the FAQ item about urxvt modified keys
So that those keystrokes will select text per screenful also on urxvt.

Inspired-by: Sébastien Desreux <seb@h-k.fr>
2024-10-12 12:57:15 +02:00
Benno Schulenberg
9a842e4bf2 tweaks: add a translator hint
This should help translators to avoid mistakenly interpreting
"Home" and "End" as names of keys.
2024-10-11 11:59:01 +02:00
9cfda05f71 Merge remote-tracking branch 'upstream/master' into line-folding 2024-10-06 17:43:50 -07:00
Benno Schulenberg
1862995aab syntax: spec: colorize all canonical architecture names
The list of canonical names was found in:
  https://github.com/rpm-software-management/rpm/blob/master/rpmrc.in

The canonical names were extracted with:

  grep arch_canon rpmrc.in | sed 's/^.*:\s*//' | sed 's/\s*..\?$//'

and then sorted and condensed into a regular expression.

Inspired-by: Funda Wang <fundawang@gmail.com>
2024-09-22 12:34:28 +02:00
Benno Schulenberg
468613c9db syntax: makefile: colorize also multiple targets
Multiple targets are separated by spaces.  Furthermore, there
may be spaces before the first target and before the colon.
2024-09-06 13:56:56 +02:00
Benno Schulenberg
28642cd047 po: update translations and regenerate POT file and PO files 2024-09-05 11:41:30 +02:00
Benno Schulenberg
f96f3546c7 bump version numbers and add a news item for the 8.2 release 2024-09-05 09:18:12 +02:00
Benno Schulenberg
205066ed12 gnulib: update to its current upstream state 2024-09-04 14:52:27 +02:00
Benno Schulenberg
7e8ee46c09 syntax: autoconf: colorize the keywords 'case', 'esac', and 'ifelse' too
Case statements occur a lot in gnulib's m4 files,
and 'ifelse' is simply part of the m4 language.
2024-08-28 17:12:17 +02:00
Collin Funk
d1e2febb6d build: update a symbol that was renamed in gnulib
As noted in a gnulib NEWS item of 2023-01-07, linking now happens
against $(CLOCK_TIME_LIB) instead of $(LIB_CLOCK_GETTIME).
2024-08-27 10:20:56 +02:00
Benno Schulenberg
3d0273de45 tweaks: improve or rewrap six comments, and add two missing ones
Also, stop initializing three variables that don't need it.
2024-08-17 10:37:41 +02:00
Benno Schulenberg
109386dfe8 syntax: nanorc: an unquoted argument of 'include' may not contain blanks
Anything after the first "word" after 'include' will be ignored
and should thus remain colorized in bright red.
2024-08-16 15:49:28 +02:00
Benno Schulenberg
ebddb49041 docs: do not quote the argument of 'include' statements in sample nanorc
This avoids those arguments getting colorized as if they were regexes
(when the relevant lines are uncommented), and instead allows them to
get colorized in bold purple by a dedicated rule.
2024-08-16 15:42:37 +02:00
Benno Schulenberg
b5f320a2f9 tweaks: delete three redundant checks from the undo/redo code
Since commit 50954a4b from two years ago, a replacing session will
not ever change the final empty line, and thus a fresh magic line
will never need to be undone or redone.

This complements commit c6a26641 from five months ago.
2024-08-12 08:41:58 +02:00
Benno Schulenberg
7568bd9af5 docs: trim stuff that is more than four years old from the changelog
A detailed list of changes is useful for just a small number of users,
and only when the changes are fairly recent.
2024-08-12 08:39:57 +02:00
Benno Schulenberg
0384c251ff docs: mention former maintainership last among an author's contributions 2024-08-10 17:36:31 +02:00
Benno Schulenberg
b812ad2926 tweaks: unwrap three lines that don't need to be wrapped
(These lines were noticed while checking that all
calls of nrealloc() use a size bigger than zero.)
2024-08-04 16:09:42 +02:00
Benno Schulenberg
fe0b928b39 tweaks: move a condition to the only place that needs it
Most calls of draw_all_subwindows() are made while in the edit window.
The only call that could occur while in the file browser is the one in
regenerate_screen().  So only this call needs to be guarded against
being made while the file list is being shown.
2024-07-31 10:04:00 +02:00
Benno Schulenberg
4b1a81e773 docs: mention the availability of ^Y, ^N, and ^A at a Yes-No prompt 2024-07-28 13:55:31 +02:00
Benno Schulenberg
af2f218192 bindings: at a Yes-No-All prompt, accept also ^A for "All"
This can be useful when replacing text in a Japanese locale,
avoiding the need to guide the input method to produce "A".

Inspired-by: Takeshi Hamasaki <hmatrjp@users.sourceforge.jp>
2024-07-28 13:54:41 +02:00
Benno Schulenberg
572247dbd8 tweaks: reshuffle a seldom-used function to the end of an if-else series 2024-07-22 15:43:37 +02:00
Benno Schulenberg
c5a0e6b60c syntax: awk: colorize escape sequences specially 2024-07-21 14:32:56 +02:00
9c2ec9f3af Merge remote-tracking branch 'upstream/master' into line-folding 2024-07-19 13:41:12 -07:00
Benno Schulenberg
d7e8665782 syntax: awk: rewrite a regex more densely, and add the missing ~ operator
Also, improve the comment.
2024-07-18 16:14:25 +02:00
Benno Schulenberg
7c86c1a185 syntax: awk: add a missing "|" between "\?" and ":"
The "\?" and ":" are meant to match the ? and : in this construct:

    condition ? thenthis : otherwisethis

The missing "|" seems to have been a typo.
2024-07-18 13:02:54 +02:00
Benno Schulenberg
4b03cc60cf moving: for Alt+Home/Alt+End, refresh the screen when the mark is on
When the mark is on, moving the cursor to the top or bottom row should
highlight the relevant area -- thus requiring a call of edit_refresh()
to be scheduled.

Also, drop two calls of place_the_cursor(), as that is done anyhow in
the main loop, either directly, or indirectly through edit_refresh().

This fixes https://savannah.gnu.org/bugs/?65992.
Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Bug existed since version 8.0, since Alt+Home/Alt+End were introduced.
2024-07-17 17:23:12 +02:00
Benno Schulenberg
c356db9f44 macro: insert it in keystroke buffer without discarding latter's contents
Instead of simply overwriting the current contents of the keystroke
buffer with the contents of the macro buffer, insert the latter's
contents at the head of the keystroke buffer.

This allows using {runmacro} in a string bind, and allows typing ahead
over a laggy connection after invoking `runmacro` (normally with M-;).

This fixes https://savannah.gnu.org/bugs/?65991.
Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Bug exists since version 2.9.4, since string binds were introduced.
2024-07-16 16:44:48 +02:00
Benno Schulenberg
c53839cefa tweaks: rename a symbol, away from an obscure abbreviation
Also, reshuffle its definition, and change its value to match
other special codes.
2024-07-15 09:38:01 +02:00
Benno Schulenberg
887803cb67 bindings: let the central numpad key (with Ctrl) center the current line
When NumLock is off, let Ctrl plus the central key on the numeric keypad
center the current line.

(This binding is not advertised anywhere
-- it's left as a little Easter egg.)
2024-07-15 09:37:48 +02:00
Benno Schulenberg
f69a08fc63 syntax: man: colorize also the .MT .ME .EX .EE .SY .OP and .YS macros
Furthermore, colorize .LP .P and .PP like .TP, as paragraph macros,
instead of inconsistenly as if they specified type faces.
2024-07-15 07:48:14 +02:00
Benno Schulenberg
4ddd61cfde po: update translations and regenerate POT file and PO files 2024-07-12 11:23:42 +02:00
Benno Schulenberg
fe39d137c7 bump version numbers and add a news item for the 8.1 release 2024-07-12 10:57:24 +02:00
Benno Schulenberg
ade975891b tweaks: add a space after a '+', for consistent formatting 2024-07-07 17:11:30 +02:00
Benno Schulenberg
479e56bdd6 tweaks: slightly reword a phrase in the explanation of --colonparsing 2024-07-07 14:27:02 +02:00
Benno Schulenberg
e5d36de24c tweaks: discard a bracketed paste in the help viewer with fewer beeps
The same change was made for the file browser two years ago,
in commit b561c386.
2024-07-07 14:25:04 +02:00
Benno Schulenberg
d824c4e633 docs: properly escape a literal '@' in the texi document
This avoids a failing `make pdf`.

Problem existed since commit 4930fbbb from five weeks ago.
2024-07-01 15:45:51 +02:00
Benno Schulenberg
f499635461 gnulib: update to its current upstream state
Also, stop distributing 'wchar_t.m4', as it was removed from gnulib
two weeks ago.
2024-07-01 11:07:03 +02:00
Benno Schulenberg
e8cf0f37f1 docs: add 'set colonparsing' to the sample nanorc 2024-06-18 15:55:00 +02:00
Benno Schulenberg
12a0c0f690 tweaks: rewrap some lines, for more even lengths
Also, slightly improve a few descriptions.
2024-06-18 10:53:28 +02:00
Benno Schulenberg
77a8841d25 tweaks: elide unhelpful occurrences of the word "will"
In most cases, "will" is just a filler word and doesn't improve clarity.

And in the bargain improve two descriptions.
2024-06-18 09:56:01 +02:00
Benno Schulenberg
7d8f13b9f7 build: use the standard autoreconf invocation
As version 0.20 of `autopoint` no longer overwrites 'extern-inline.m4',
there is no need any more for the custom calls of the various parts of
`autoreconf`.

This effectively reverts commit 4a1db96d from two and a half years ago.
2024-06-17 11:07:40 +02:00
Benno Schulenberg
ec177c84b3 build: require version 0.20 of gettext for building nano from git
Gettext-0.20 is the first version where its `autopoint` does not
overwrite the newer 'extern-inline.m4' from gnulib.

Version 0.20 is five years old, so most users will be on a distro
that includes that version of gettext or a newer one.
2024-06-17 09:50:08 +02:00
Benno Schulenberg
3809c67bb2 docs: add the Alt+Home/Alt+End shortcuts to the cheatsheet
Also, reshuffle Alt+T for balance, slightly reword the description
of Alt+A (as it differs in nature from the other toggles), and add
some spaces for better alignment.
2024-06-17 09:10:07 +02:00
Benno Schulenberg
dff779e3ad tweaks: in FAQ, use 'id' attribute instead of empty anchor with 'name'
The 'name' attribute for the <a> tag is deprecated -- 'id' is the
standard attribute that can be used in almost every tag.
2024-06-17 09:09:37 +02:00
Benno Schulenberg
ef1c9b9f2b tweaks: implement do_center() with a single call instead of three
This works because the main loop sets 'cycling_aim' to zero
whenever the current keystroke is not bound to `cycle`.
2024-06-15 09:57:06 +02:00
Benno Schulenberg
90e62db26e help: regroup the center item, placing it with the new cycle 2024-06-15 09:57:06 +02:00
Benno Schulenberg
498154804c bindings: let ^L put the cursor line at center, then top, then bottom
Something similar can be achieved with:

  bind ^T "{center}{bottomrow}{center}{toprow}" main
  bind ^B "{center}{toprow}{center}{bottomrow}" main

But that requires allocating two extra shortcuts, and it works right only
when the edit window has an odd number of rows, not with an even number.
Also, this new ^L behavior is available by default, out-of-the-box.
2024-06-15 09:57:06 +02:00
Benno Schulenberg
34dda64610 docs: explain the behavior of the new function cycle
Also colorize {cycle} when found in a nanorc file.
2024-06-15 09:57:06 +02:00
Benno Schulenberg
d1c723bc14 new feature: add bindable function cycle that pushes cursor line around
On the first call, `cycle` centers the line with the cursor, on the
second consecutive call it pushes that line to the top of the viewport,
and on the third consecutive call to the bottom of the viewport.
2024-06-15 09:57:06 +02:00
Benno Schulenberg
d477bfd4ee tweaks: drop two redundant conditions
The function do_tab() is only ever called when in the main edit window,
and never called while a bracketed paste is in progress.

(The two conditions were thoughtlessly copied when this fragment of code
was moved here three commits ago.)
2024-06-10 14:07:30 +02:00
Benno Schulenberg
6c81f60914 moving: use edit_scroll() only when scrolling one row is enough
When softwrapping with a tabsize larger than the width of the viewport,
scrolling one row when the cursor goes offscreen might not be enough,
so in that case use edit_redraw() instead.

This fixes https://savannah.gnu.org/bugs/?65860.

Bug existed since version 2.9.6, commit 0d9080a2.
2024-06-10 08:15:28 +02:00
Benno Schulenberg
aa844ada4e tweaks: remove the now unneeded special keycode INDENT_KEY 2024-06-09 16:48:06 +02:00
Benno Schulenberg
9b7a813069 text: do not check for <Tab> + mark while getting input but in do_tab()
This allows a {tab} in a string bind to indent a marked region.

This fixes https://savannah.gnu.org/bugs/?65859.

Problem existed since version 7.0, since braced function names
were introduced.
2024-06-09 16:42:14 +02:00
baadfa34f1 Merge branch 'master' of https://git.savannah.gnu.org/git/nano into line-folding 2024-06-09 07:27:29 -07:00
Benno Schulenberg
bc09f0992e tweaks: reshuffle some lines, to put vaguely related things together
And to slightly reduce the number of #ifdefs.
2024-06-08 17:08:17 +02:00
Benno Schulenberg
00e2309987 tweaks: make the inclusion condition for do_center() more strict
There is no reason why --enable-help should cause the centering function
to be included in a tiny version.
2024-06-08 16:56:52 +02:00
Benno Schulenberg
a98f82e27b startup: no not activate --modernbindings when name starts with "e"
Activating --modernbindings when the binary's name starts with "e"
interferes with Debian's alternatives system that symlinks `editor`
to `nano` in a default install.

(Also: why "e"?  It would have made more sense to check for "m",
similar to the checking for "r" for a restricted nano.)

This reverts commit 580eaf29 from fifteen months ago.

This addresses https://savannah.gnu.org/bugs/?65810.
Reported-by: Colin Snover <nano@zetafleet.com>
2024-06-08 12:14:08 +02:00
Benno Schulenberg
c70e6919c2 syntaxes: mention the original author of most of the syntax files
The names of the authors were retrieved from:

  git log -p --follow  syntax/<name>.nanorc

and from:

  git log -p --follow --all --  doc/nanorc.sample

For some files the original author is unclear, or
the file is/was too small to mention an author for.
2024-06-08 12:10:25 +02:00
Jaroslav Fowkes
abdf069ce3 syntax: fortran: fix a typo (a missing backslash)
The typo prevented several keywords from getting colorized.

This addresses https://savannah.gnu.org/patch/?10459.

Bug existed since version 2.1.6, commit 513157df,
since the Fortran syntax was introduced.
2024-06-07 15:34:03 +02:00
Benno Schulenberg
6be1f7e95a docs: avert hyphenation of the technical words "ncurses" and "terminfo"
This prevents an observed wrong hyphenation: "ter-minfo".

Also, add markup for "terminfo", like "ncurses" already has.
2024-06-07 14:57:02 +02:00
Benno Schulenberg
a1159ff484 syntax: man: colorize some of the things that manipulate hyphenation
Reference:
  https://www.gnu.org/software/groff/manual/groff.html.node/Manipulating-Hyphenation.html
2024-06-06 13:29:01 +02:00
Benno Schulenberg
0c2caa50cc docs: correct the description of --bold, as function tags are unaffected
The succinct function descriptions in the help lines are not shown in
reverse video by default, so they are not bolded by -D/--bold either.

Also, mention 'promptcolor' and 'minicolor' where they were missing.
2024-06-04 17:01:11 +02:00
Benno Schulenberg
dcbbbf8134 input: make sure that a string-bind return value is non-negative
A negative value would lead to misinterpretation by parse_kbinput().

This fixes https://savannah.gnu.org/bugs/?65832.

Bug existed since version 8.0, commit 51c9f727.
2024-06-03 15:40:03 +02:00
Benno Schulenberg
05602e29cd syntax: patch: recognize also the .rej extension
The addition was inspired by `davidhcefx`.
2024-06-02 17:16:22 +02:00
Benno Schulenberg
cd53f7cf8c docs: don't say any more that -z was removed, as it has been repurposed 2024-06-02 09:23:09 +02:00
Benno Schulenberg
689748843c files: with --rectrict, prevent invoking the browser and toggling backups
Prevent also the toggling of Append and Prepend.  All four functions
should not be available in restricted mode, and are absent from the
WriteOut menu in that mode, but using {browser}, {backup}, {append}
or {prepend} in a string bind allowed to bypass the menu checks.

This fixes https://savannah.gnu.org/bugs/?65819.

Problem existed since version 7.0, since braced function names
were introduced.
2024-06-01 11:31:09 +02:00
Benno Schulenberg
ea07eb6aa3 help: show option -Y/--syntax in --help output also in restricted mode
Since version 3.2, commit 5ca444e5, nano reads the nanorc files also
in restricted mode (when not also --ignorercfiles is given), meaning
that syntaxes are available and that a specific syntax can be selected
on the command line.  So, the --help output in restricted mode should
list the relevant option: -Y<name> / --syntax=<name>.

(This should have been part of commit b81995af from six years ago.)
2024-06-01 11:00:49 +02:00
Benno Schulenberg
5251ce1b20 tweaks: simplify a condition, to match the same condition five lines back 2024-06-01 09:30:44 +02:00
Benno Schulenberg
b3780aab33 docs: remove the 'filename:linenumber' format from the synopsis
(This should have been part of commit 4930fbbb from five days ago.)
2024-05-31 16:48:08 +02:00
Benno Schulenberg
5bc6d0ef2e tweaks: extend the deprecation period of 'set nowrap' and prefix 'bright' 2024-05-31 16:41:46 +02:00
Benno Schulenberg
b92cbf5f09 rcfile: remove old bindable function 'nowrap', alias of 'breaklonglines'
The bindable function 'nowrap' has been deprecated for three years,
since version 5.5, commit e14127b8.

(The obsolete options --nowrap and 'set nowrap' continue to exist.)
2024-05-31 15:57:01 +02:00
Benno Schulenberg
c26f901ba9 options: remove the deprecated synonym -$ of -S/--softwrap
The old short option -$ has been deprecated for four years,
since version 5.0, commit 7d3aad40.
2024-05-31 12:45:18 +02:00
Benno Schulenberg
a590645cde docs: document the new --listsyntaxes (-z) option 2024-05-31 11:14:24 +02:00
Benno Schulenberg
49c2f5dea9 new feature: option -z lists the names of available syntaxes
When one has installed additional syntaxes, one tends to forget
what exactly is there.  So it's nice to be able to list them.

The syntaxes are listed in the reverse order in which they were
read: the most recent first.

The long form of the option is, of course, --listsyntaxes,
which can be abbreviated to --list.

This fulfills https://savannah.gnu.org/bugs/?65779.
The feature was suggested by `davidhcefx`.
2024-05-31 11:14:24 +02:00
Benno Schulenberg
b408147f48 tweaks: exclude the colon-parsing code from the tiny version
The option --colonparsing is not available in the tiny version,
so there is no need for the code either.
2024-05-28 17:12:30 +02:00
Benno Schulenberg
4930fbbba7 docs: explain the details of --colonparsing / -@ / 'set colonparsing'
Also, remove the earlier explanation, when colon parsing was still
done by default.
2024-05-26 17:11:09 +02:00
Benno Schulenberg
02dd0b4ed5 options: require --colonparsing/-@ to parse colon+number after a filename
Stop doing colon parsing by default, to avoid surprises and frustration
for users that have filenames that end in a colon plus digits.

The equivalent rcfile option is, of course, 'set colonparsing'.

Using +1, or similar, before the filename disables any colon parsing
and the filename is taken as is.
2024-05-25 16:48:35 +02:00
Benno Schulenberg
add945e717 files: look for digits and colons starting from the end of the filename
Starting from the end of the provided filename avoids needlessly looking
at colons that are somewhere in the middle of the path or the filename.

It also avoids inconsistenly interpreting a specified line number as a
column number when the filename itself ends with a colon plus digits
and the filename without the colon plus digits exists too.

This also removes the eliding of a backslash before a colon, which
would mangle the filename if the name actually contained a backslash
followed by a colon.

Negative line and column numbers are no longer allowed when using the
colon notation.

This fixes https://savannah.gnu.org/bugs/?65781,
and fixes https://savannah.gnu.org/bugs/?65782.

Problems existed since version 8.0, since colon parsing was introduced.
2024-05-25 16:48:24 +02:00
Benno Schulenberg
259a3c70e3 general: disable the type-ahead checking that ncurses normally does
While updating the screen, ncurses by default polls the input source
now and then to see if there is new input, and if so, stops updating
the screen and waits for the next call of doupdate() or refresh().

  https://lists.gnu.org/archive/html/bug-ncurses/2024-05/msg00077.html

Disable this polling, as it is just a waste of time, and there *might*
be situations where the intruding keystroke does not actually trigger
a new update, which could result in a half-updated screen.
2024-05-20 17:14:09 +02:00
Benno Schulenberg
2445e77535 files: avoid mistakenly setting the column number to a given line number
When the file 'foo:24' exists (but not 'foo') and the user wants to
use the colon notation to place the cursor on a certain line, then
nano would first interpret the given line number as a column number,
before noticing that 'foo' does not exist and then skipping the first
colon.  So, when such a misinterpretation occurs, the column number
needs to be reset to zero.
2024-05-18 16:02:09 +02:00
Benno Schulenberg
d64235eb6e tweaks: reshuffle a declaration, adjust a comment, normalize indentation 2024-05-18 16:02:09 +02:00
Benno Schulenberg
54c8cb8c81 files: when a filename with a colon and digits exists, open that file
When the user specifies, on the command line, a filename that ends with
a colon plus digits, and that filename exists in the file system, then
open that file, instead of interpreting the digits as a line number.

Also, if the filename stripped of the colon plus digits does not exist,
then do not interpret the digits as a line number either but treat them
as part of the file name.

Before this change, the user would have to escape the colon whenever
they wanted to open a file whose name ended with a colon plus digits.
Now the user needs to escape the colon only when 'foo' exists and they
want to create, say, 'foo:24'.

Problem-was-reported-by: Ralph Corderoy <ralph@inputplus.co.uk>
  https://lists.gnu.org/archive/html/nano-devel/2024-05/msg00001.html
Mitigation-was-suggested-by: Mike Scalora <mike@scalora.org>
  https://lists.gnu.org/archive/html/nano-devel/2024-05/msg00008.html
2024-05-18 16:02:09 +02:00
758130f5b9 Merge in upstream changes 2024-05-14 19:11:00 -07:00
Benno Schulenberg
803a16cbcd input: drop recognition of the urxvt escape sequences for M-Home/M-End
Nano does not recognize the urxvt escape sequences for other
<Alt+cursorkey> combinations either.  And with the previous
two commits, the urxvt user can now "help themselves".

This reverts commit 363a4378 from three days ago.
2024-05-14 16:39:34 +02:00
Benno Schulenberg
0b43c8da11 docs: extend the FAQ item about urxvt modified keys, with M-Home/M-End 2024-05-14 16:39:14 +02:00
Benno Schulenberg
c446904c19 input: recognize the raw Xterm escape sequences for Alt+Home and Alt+End
This makes those keystrokes work too when --raw is used.

But more importantly: these raw sequences can be used in an
~/.Xresources file to override the odd behavior of urxvt for
those keystrokes, making the previous commit redundant.
2024-05-12 10:27:35 +02:00
Benno Schulenberg
363a4378b7 input: provide for urxvt setting a high bit or sending an extra escape
When pressing Alt+Home/Alt+End on urxvt, urxvt either sets the high bit
of the last byte in the sequence for Home/End (when Meta8 is True), or
sends an extra escape before that same sequence (when Meta8 is False).
Accommodate for this bug by recognizing the produced code sequences.

Indirectly-reported-by: Sébastien Desreux <seb@h-k.fr>
  https://lists.gnu.org/archive/html/nano-devel/2024-05/msg00007.html
2024-05-11 16:28:04 +02:00
Benno Schulenberg
f70f528730 build: check for the correct function in an #ifdef
Problem existed since version 7.0, commit 19c8cea8,
that replaced calls of wait() with calls of waitpid().
2024-05-05 10:43:23 +02:00
Benno Schulenberg
2334dedba6 tweaks: make a comment more accurate, and unabbreviate a variable name 2024-05-05 10:27:21 +02:00
Benno Schulenberg
e9c7dfa992 minibar: do not falsely report that a new, empty file is in Mac format
The 'openfile->fmt' element gets initialized to 'UNSPECIFIED',
so the code has to take that possibility into account.

This fixes https://savannah.gnu.org/bugs/?65676.

Bug existed since version 8.0, commit fe4f74f6.
2024-05-03 12:12:09 +02:00
Benno Schulenberg
33eaf3e947 po: update translations and regenerate POT file and PO files 2024-05-01 10:42:51 +02:00
Benno Schulenberg
ce5513b009 bump version numbers and add a news item for the 8.0 release 2024-05-01 10:10:15 +02:00
Benno Schulenberg
a98b03e46e tweaks: rewrap two old news items 2024-04-28 16:49:09 +02:00
Benno Schulenberg
e4c3ffcd38 tweaks: rename a variable, away from an abbreviation 2024-04-28 13:45:08 +02:00
Benno Schulenberg
5e7a3c2e7e files: run chmod and chown on the descriptor, not on the filename
This closes a window of opportunity where the emergency file could be
replaced by a malicious symlink.

The issue was reported by `MartinJM` and `InvisibleMeerkat`.

Problem existed since version 2.2.0, commit 123110c5, when chmodding
and chowning of the emergency .save file was added.
2024-04-28 10:56:21 +02:00
Benno Schulenberg
c020d53e23 input: snip the recordmacro and runmacro keystrokes in a better way
When recording a macro over a laggy connection or on a slow, overloaded
computer, several keystrokes could be recorded in one burst, and if any
but the last of those keystrokes was the shortcut for `runmacro`, then
running the macro would lead to an infinite loop and nano would hang.

This new implementation of snipping the "last keystroke" will, however,
snip *too many* keystrokes when several of them were recorded at once
and `runmacro` or `recordmacro` was among them, resulting in a cropped
and thus misrecorded macro.  But... that's better than hanging.

In general, though, the user should be slow and deliberate when
recording a macro: waiting for nano to have processed the last
keystroke before typing the next.

This fixes https://savannah.gnu.org/bugs/?65649.
The issue was reported by `correctmost`.

Problem existed since version 2.9.0, since macros were introduced.
2024-04-27 17:17:03 +02:00
Benno Schulenberg
cb02937714 wrapping: delete only single characters, not a possibly marked region
These calls of do_delete() were meant to delete just one character,
but over time do_delete() morphed into doing also other things...
Change the calls to invoke the correct function instead.

(This also avoids snipping any zero-width characters that come after
a snipped space, as that is probably not what the user wants.)

This fixes https://savannah.gnu.org/bugs/?65636.
The issue was reported by `correctmost`.

Bug existed since version 3.2, commit ae3ec178,
when --zap was introduced.
2024-04-25 11:01:42 +02:00
Benno Schulenberg
1327e296c2 tweaks: rename a function, for contrast, and update antiquated comments 2024-04-25 10:34:03 +02:00
Benno Schulenberg
d53521a631 syntax: sh: recognize more shells than sh on a shebang line for busybox
Also, elide an unneeded pair of parentheses.

Original-patch-by: Sertonix <sertonix@posteo.net>
  https://lists.gnu.org/archive/html/nano-devel/2024-04/msg00026.html
2024-04-22 10:29:02 +02:00
Benno Schulenberg
5beb14cffe softwrap: realign start-of-screen when redoing an automatic hard-wrap
Redoing an automatic hard-wrap while one or more chunks of the affected
line are offscreen, can leave 'firstcolumn' with a value that doesn't
fit the situation.  So, make sure that it has a valid value.

This complements the previous commit.

This fixes https://savannah.gnu.org/bugs/?65611.
The issue was reported by `correctmost`.

Bug existed since version 2.8.6, commit e375995d.
2024-04-19 16:11:14 +02:00
Benno Schulenberg
7b07e1ee5c softwrap: adjust start-of-screen when the 'edittop' line is hard-wrapped
When one or more chunks of the current line are above the viewport,
and this line gets hard-wrapped, then 'edittop' needs to be advanced,
otherwise the first row could be blank -- representing a chunk that
doesn't exist any more.

This fixes https://savannah.gnu.org/bugs/?65604.
The issue was reported by `correctmost`.

Bug existed since version 2.8.6, commit e375995d.
2024-04-17 17:12:09 +02:00
Benno Schulenberg
c02aec557c syntax: makefile, sh: recognize also a fresh Makefile and fresh .profile
When opening a nonexistent file with nano, it likely consists of only a
name without any path component, and thus without any slash.  So when a
file regex checks for a slash, it should check also for start-of-string.

This fixes https://savannah.gnu.org/bugs/?65591.

Problem existed for the Makefile since version 2.9.8, commit 22663f8a,
and for .profile since version 3.0, commit 4a268678 (but earlier, nano
did not recognize .profile files at all).
2024-04-14 12:09:36 +02:00
Benno Schulenberg
c695d49a86 editing: adjust the mark before trimming redundant blanks
When an entirely blank line is trimmed (when --autoindent is active and
Enter is pressed while the cursor is at the end of the current indent),
the mark needs be adjusted *before* 'current_x' is zeroed, otherwise the
mark gets moved too much to the right, which causes the region to become
bigger than what the user intended, or leads to accessing unallocated
memory.

This fixes https://savannah.gnu.org/bugs/?65586.
The issue was reported by `correctmost`.

Bug existed since version 2.8.1, commit 005ee8ed.
2024-04-13 16:24:18 +02:00
Benno Schulenberg
3cd3ba0397 gnulib: update to its current upstream state 2024-04-12 10:57:03 +02:00
Benno Schulenberg
829ab5e72d syntax: nanorc: colorize {toprow} and {bottomrow} for string binds 2024-04-07 15:55:38 +02:00
Benno Schulenberg
4ae8082552 files: do not allow M-U to remove text read from standard input
This fixes https://savannah.gnu.org/bugs/?65565.

Problem existed since version 2.1.8, commit 25d459aa,
since reading from standard input was introduced.
2024-04-07 11:33:34 +02:00
Benno Schulenberg
2c8d57fbb2 docs: document the new bindable functions 'toprow' and 'bottomrow' 2024-04-07 10:57:07 +02:00
Benno Schulenberg
e51a28e492 rcfile: add bindable functions for moving the cursor to top or bottom row 2024-04-07 10:47:03 +02:00
Benno Schulenberg
72c83badf6 feedback: lowercase a letter, as the phrase is not a full sentence
It could also have been after a comma (instead of between parentheses).
2024-04-07 10:39:06 +02:00
Benno Schulenberg
fe4f74f631 minibar: mention the file format when it's DOS or Mac
This provides feedback about the file format in a better way than
how it was done until the previous commit.
2024-04-07 10:27:21 +02:00
Benno Schulenberg
2b335060b0 feedback: suppress format-conversion messages for --zero and --mini
A "Read xx lines (converted from...)" message should be suppressed when
--zero or --minibar are active (just like the normal "Read xx lines"),
as otherwise it gets shown at a confusing moment when multiple files
are opened at the same time.  The message should get shown, however,
when inserting a file into the current buffer.

This fixes https://savannah.gnu.org/bugs/?65560.

Bug existed since version 6.0, commit f147131e.
2024-04-06 17:55:29 +02:00
Benno Schulenberg
c3fc3ec73d tweaks: slightly reword the help text for the Replace-With prompt
To avoid the vague impression that the characters typed at the two
prompts should correspond one to one.
2024-03-31 14:02:29 +02:00
Benno Schulenberg
be14fc593f tweaks: rename two variables, to be clearer and to match others
Also trim a verbose comment.
2024-03-30 12:39:15 +01:00
Benno Schulenberg
f2bfa53b61 tweaks: elide a redundant variable 2024-03-30 12:39:04 +01:00
Benno Schulenberg
25d07b422d tweaks: rename a variable, to better indicate what it represents
And also to get away from the abundance of the word "current".
2024-03-30 11:35:41 +01:00
Benno Schulenberg
8610857015 feedback: drop an unnecessary warning, to not bother the user
The idea of the warning was that `row < 0 || row >= editwinrows` would
never be true: that the check was redundant and could be removed.

As it appears to be too hard to make sure in advance that a chunk will
not fall outside the viewport, just drop the warning and leave the check
in place.

This also addresses https://savannah.gnu.org/bugs/?64168.
Reported-by: Matteo Raso <matteo_luigi_raso@protonmail.com>
2024-03-30 11:15:32 +01:00
Benno Schulenberg
17abce073f display: do not attempt to draw a line that is outside the viewport
When we're on the last row in the viewport, it is unwise to try and draw
the next line.

This fixes https://savannah.gnu.org/bugs/?65539.
The issue was reported by `correctmost`.

Bug existed since commit c2322f85 from three days ago.
2024-03-30 10:49:29 +01:00
Benno Schulenberg
02d50bd4aa help: mention M-Home and M-End in the help text and help lines
Make these new keystrokes discoverable for people who read help texts.
2024-03-29 12:56:15 +01:00
Benno Schulenberg
67d459b262 bindings: let <Alt+Home/End> move the cursor to top/bottom of viewport
For now these are hidden keystrokes -- they are not listed anywhere,
and the functions are not bindable by the user.
2024-03-28 16:04:34 +01:00
Benno Schulenberg
5ecefb8766 moving: preserve horizontal position when jumping to top or bottom row 2024-03-28 16:04:34 +01:00
Benno Schulenberg
52eb0e992d new feature: functions that jump to the top or bottom of the viewport
(The next commit will preserve the horizontal cursor position.)
2024-03-28 16:04:34 +01:00
Benno Schulenberg
19ddc081c1 tweaks: rename a variable, to be more readable 2024-03-28 16:01:48 +01:00
Benno Schulenberg
8e91e26cc5 tweaks: reshuffle three fragments of code, moving related things together
And avoid calling xplustabs() twice in a row.
2024-03-28 15:58:28 +01:00
Benno Schulenberg
c2322f8563 display: draw a new magic line rightaway when there are multiline regexes
Drawing a line will allocate multidata for it (even when the line is
actually empty), so that this multidata will not be missing later on
when the next line gets drawn in the same burst of keystrokes.

(This also removes the triggering of a full refresh when line numbers
are active: only the new magic line needs to be additionally drawn, in
order to get the line number printed.)

This fixes https://savannah.gnu.org/bugs/?65516.
The issue was reported by `correctmost`.

Problem existed since version 6.3, commit 80c2000f.
2024-03-27 11:12:47 +01:00
Benno Schulenberg
4f0683a481 docs: add an example binding for normalizing Unicode to the sample nanorc
This requires `uconv` from the 'icu-devtools' package (on Debian).
2024-03-26 11:37:29 +01:00
Benno Schulenberg
b9449de5cf docs: improve the description of the 'flipexecute' bindable function
It is bindable only in the Insert menu -- in the Execute menu it has
a "blind", unadvertised binding (because I consider toggling between
menus somewhat of a misfeature).
2024-03-26 11:29:56 +01:00
Benno Schulenberg
c3a9578b82 feedback: raise the level of "Macro is empty", to match similar messages
The other three "... is empty" messages use the AHEM error level too.
2024-03-26 11:27:38 +01:00
Benno Schulenberg
6351dab3e6 bindings: let M-" place/remove an anchor, and let M-' jump to one
On my current laptop, typing <Alt+Insert> is awkward because it requires
holding down <Fn> too.  Also, M-" and M-' are in the normal symbols area
of the keyboard, which makes them easier to type and more discoverable.
Furthermore, being next to M-: and M-; (on a US keyboard) reinforces the
meanings: start/place, stop/remove, run/goto.
2024-03-25 11:01:14 +01:00
Benno Schulenberg
3ef6399d56 tweaks: rename a variable, away from an abbreviation
And rename its sister too.
2024-03-24 10:46:46 +01:00
Benno Schulenberg
f4754bfb5a memory: prevent a leak by freeing a possibly already existing color combo
This fixes https://savannah.gnu.org/bugs/?65505.

Buglet existed in this form since version 2.9.3, commit 4b24ce1c.
2024-03-23 11:04:23 +01:00
Benno Schulenberg
3fb8efc8f2 input: prevent 'macro_length' from underflowing when hammering M-:
Normally, when recording a macro, users will make their keystrokes
slowly and carefully, and will most likely wait to see the effect
of the previous keystroke before making the next.  So, the chances
of two `recordmacro` keystrokes coming in in quick succession is
normally nil.  The 'macro_length' variable just needs a guard to
prevent it from underflowing when someone is hammering the keys.

This fixes https://savannah.gnu.org/bugs/?65394 in a better way.
2024-03-22 16:27:34 +01:00
Benno Schulenberg
9ae84071eb input: store key codes in the macro buffer as they come in from ncurses
Otherwise the leading ESC of keystrokes like M-A does not get recorded.

This reverts commit 191cf671 from three weeks ago.

This fixes https://savannah.gnu.org/bugs/?65507.
2024-03-22 16:27:11 +01:00
Benno Schulenberg
c2b4c2ae0e docs: mention that 'light' background colors do not work on Linux console
This addresses https://savannah.gnu.org/bugs/?65501.
Reported-by: Alan Cristhian Ruiz <alancristhian@protonmail.com>
2024-03-22 11:23:05 +01:00
Benno Schulenberg
9f1431be17 justify: keep as much of the marked region onscreen as possible
When the justified region fits in its entirety onscreen, then it should
be shown in its entirety, because the user is probably curious what the
region looks like after justification.  This behavior will mean that
the line above the topline of the screen will still have multidata
(when the syntax has multiline regexes).  When the justified region
does not fit onscreen, then as much as possible should be shown --
meaning that the cursor should be either at the top or the bottom
of the viewport, meaning that it should not be centered.

This fixes https://savannah.gnu.org/bugs/?65482.
The issue was reported by `correctmost`.

Bug existed since version 4.0, since justifying a region was introduced.
2024-03-19 17:18:18 +01:00
Benno Schulenberg
e1c6ae7cf3 justify: keep the cursor at the original end of a marked region
When justifying a region that was marked backwards, the cursor
should stay at the beginning of this region.  The old logic was
faulty because mark_is_before_cursor() does not give the correct
result *after* the justification has been done: for some reason
the mark ends up always before the cursor.

Bug existed since version 5.2, commit 0f8423eb,
which mistakenly removed the auxiliary variable.  :/
2024-03-19 16:45:02 +01:00
Benno Schulenberg
bb7a9fe7d2 tweaks: ungettextize three strings, to make a translator hint right again
The strings are gettextized further down, for the non-tiny version,
so they will get translated anyhow.  The relevant translator hint
is the earlier one about "the next thirteen strings".

Also adjust an indentation, and ungettextize another string for
consistency.
2024-03-19 11:56:33 +01:00
Benno Schulenberg
d77263d8ed bindings: let M-& show the ncurses version+patch, as a small Easter egg 2024-03-18 10:33:40 +01:00
Benno Schulenberg
fdd92af3ac display: add a wnoutrefresh() call for NetBSD, to force a cursor update
With NetBSD curses, when only the cursor is moved (without writing any
text), then a call of wnoutrefresh() is needed to make doupdate() move
the cursor.  Ncurses does not need this.

This addresses https://savannah.gnu.org/patch/?10438.
2024-03-18 10:02:11 +01:00
Benno Schulenberg
dd009e0bc7 tweaks: rename a function and variable, to describe better what they do 2024-03-17 17:18:48 +01:00
Benno Schulenberg
170e7d79e7 tweaks: express an 'if' more concisely, and add two blank lines
The calls of wnoutrefresh() after those new blank lines are not needed
for ncurses to show the cursor in the right place, but are logically
needed because things have been written to the screen in the preceding
code -- although nano seems to work correctly also without those calls.
2024-03-17 16:57:19 +01:00
Benno Schulenberg
a7635ceb5d tweaks: rename a variable, to be a bit more indicative 2024-03-17 16:40:04 +01:00
Benno Schulenberg
64fb0be8b2 tweaks: add another translator hint, to help avoid overlong key tags 2024-03-16 16:28:16 +01:00
Benno Schulenberg
a5a8487132 tweaks: improve three translator hints
The browser listing has a rigid format: longer translations
for "(dir)", "(parent dir)", and "(huge)" will be clipped.
2024-03-15 14:06:14 +01:00
Benno Schulenberg
8cf61af551 indicator: do not oversize the scroller when softwrapping
This fixes https://savannah.gnu.org/bugs/?65445.

Bug existed since version 5.7, commit 49d8b99e.
2024-03-11 11:18:28 +01:00
Benno Schulenberg
778f000a3b docs: use a space after #, like everywhere else in the sample nanorc
Also, use a more mnemonic example shortcut for copy-to-clipboard.
2024-03-10 17:32:09 +01:00
Benno Schulenberg
623ff4e1ed docs: trim stuff that is more than five years old from the changelog
A detailed list of changes is useful for a small number of users only,
and only when the changes are fairly recent.

The NEWS file, that contains a summary of user-visible changes and
will be useful for a larger number of users, is distributed in full.
2024-03-09 17:18:04 +01:00
Benno Schulenberg
260f00c76d screen: recalculate the multidata when detecting the need for it
This fixes https://savannah.gnu.org/bugs/?65435.
The issue was reported by `correctmost`.

Problem existed since version 6.3, commit 80c2000f.
2024-03-09 09:01:31 +01:00
Benno Schulenberg
0c8a3b5c3e tweaks: pull a fragment of code a bit forward, to enable the next commit 2024-03-09 08:32:47 +01:00
Benno Schulenberg
e76068a2de docs: adjust an example help line in the README to the current state 2024-03-08 17:12:28 +01:00
Benno Schulenberg
a12e45c355 help: show ^F/^B as primary shortcuts for search, not as secondary
This looks better in the help viewer (^F/^B matching the pair M-B/M-F),
and showing ^F instead of ^W for search in the main edit window will
prevent novice users from using ^W in situations where they shouldn't.
2024-03-08 11:50:20 +01:00
Benno Schulenberg
74b9dd6881 help: rebalance the help items when --preserve is used
As a backward search is now normally always bound (to ^B, instead of
conditionally to ^Q), ^L should always be shown in the help viewer.

This fixes https://savannah.gnu.org/bugs/?65434.

Problem existed since commit 8a304bdf, since ^F/^B do a search.
2024-03-08 11:31:02 +01:00
Benno Schulenberg
edd0823d96 docs: mention that --modernbindings overrides --preserve 2024-03-08 11:25:14 +01:00
Benno Schulenberg
4ef4eb4f12 options: make --modernbindings actually override --preserve
When modern bindings are requested, ^S should save and ^Q must exit,
so --preserve and 'set preserve' need to be cancelled.

This fixes https://savannah.gnu.org/bugs/?65433.

Bug existed since commit 18b37c98, which introduced --modernbindings.
2024-03-08 11:04:48 +01:00
Benno Schulenberg
862574f381 undo: force a screen refresh also for the special case Bsp-at-EOF
Because meanwhile the cursor might be someplace where EOF is offscreen.

This effectively reverts commit 9ccf85ea from two years ago, but also
sets 'focusing' to false so that the last line of the buffer will be at
the bottom of the edit window, where it probably was when Bsp was typed.

This fixes https://savannah.gnu.org/bugs/?65428.
The issue was reported by `correctmost`.

Bug existed since version 6.3, commit 9ccf85ea.
2024-03-07 17:14:18 +01:00
Benno Schulenberg
c67ea1ffc1 undo: recompute the multidata when a piece of text is replaced
When a justification (or even a spell check) is undone or redone,
this might affect the matching of multiline regexes, so... schedule
a recalculation of the multidata in those cases.

This fixes https://savannah.gnu.org/bugs/?65426.
The issue was reported by `correctmost`.

Problem existed since version 6.3, commit 80c2000f.
2024-03-07 16:51:08 +01:00
Benno Schulenberg
5bd5bcd06a docs: mention backreferences (for replacements with regular expressions)
Also mention that nano prompts for each occurrence, and that, when
a region is marked, replacements are made only within that region.
2024-03-05 15:50:15 +01:00
Benno Schulenberg
a13cd6a177 execute: show "Older" and "Newer" in the help lines, to allow rebinding
Since commits c8363a0d and a75bf0a1 from seven years ago, the Execute
menu permits retrieving previously executed commands, but the help text
and help lines never showed the corresponding keystrokes.

Four years ago commit d3954901 made the Execute menu directly accessible,
but I preferred to not mention the ^P/^N keystrokes in the help lines,
to leave as much space as possible for the executable functions (added
in subsequent commits), thinking that no one would want to rebind those
keystrokes anyway, as the Up/Down arrows seem more logical and easier.

The issue was reported by Ivan Vorontsov:
  https://lists.gnu.org/archive/html/help-nano/2024-02/msg00003.html
2024-03-05 11:31:48 +01:00
Benno Schulenberg
f60c6b25ad docs: delete a remark about libvte that is no longer relevant
Libvte 0.55 is more than five years old -- almost all users will
have upgraded by now to 0.55 or newer.
2024-03-05 08:44:04 +01:00
Benno Schulenberg
c6a2664106 tweaks: delete a redundant fragment of code from do_replace_loop()
Since commit 50954a4b from a year and a half ago, a replacing session
will not ever change the final empty line, so a fresh magic line will
never be needed.
2024-03-04 16:30:09 +01:00
Benno Schulenberg
4ab80abb5e justify: recompute the multidata for paragraphs larger than the viewport
A freshly justified paragraph does not yet have any multidata,
and if this new paragraph has more lines than fit in the viewport
(minus one line for the cursor), then the line above the top of the
new viewport will be without multidata.  The coloring code cannot
handle this, so all the multidata then needs to be recalculated.

This fixes https://savannah.gnu.org/bugs/?65396.
The issue was reported by `correctmost`.

Problem existed since version 6.3, commit 80c2000f.
2024-03-04 12:52:18 +01:00
Benno Schulenberg
f37d097c1c rcfile: avoid crashing on an include path that is way too long
The `gnulib` globbing module apparently does not handle an overload
of slashes well, so avoid feeding it more than it can take.

This fixes https://savannah.gnu.org/bugs/?65407.

Problem probably existed since version 2.3.3,
since globbing was introduced.
2024-03-04 11:44:22 +01:00
Benno Schulenberg
191cf671be input: store keystroke in macro buffer only when about to interpret it
When the keystroke after the keystroke bound to `recordmacro` arrived
so quickly that the two got stored together in nano's keystroke buffer,
the main loop had not yet interpreted the `recordmacro` command and had
thus not yet set 'recording' to true, meaning that that second keystroke
would not get recorded.

Nano should record keystrokes into the macro buffer when fetching them
from its own keystroke buffer, not when fetching them from ncurses.

This fixes https://savannah.gnu.org/bugs/?65394.
The issue was reported by `correctmost`.

Bug existed since version 2.9.0, since macros were introduced.
2024-03-02 17:45:11 +01:00
Benno Schulenberg
3098315e05 replacing: stash the string to be replaced while asking for replacement
During the Replace-With prompt the user could search in its help text,
which would overwite the 'last_search' string.  Make therefore sure that
the latter gets restored to what it was before the Replace-With prompt.

This fixes https://savannah.gnu.org/bugs/?65381.

Bug existed since version 2.8.2,
since searching in a help text became possible.
2024-02-28 11:44:03 +01:00
Benno Schulenberg
39db2e9d66 tweaks: implement the fix of the previous commit somewhat differently 2024-02-27 17:24:32 +01:00
Benno Schulenberg
ee1a1306e2 search: avoid crashing after searching a help text during a regex replace
Searching in a help text does not support using regular expressions,
so when 'inhelp' is set, do not free a compiled regex -- because if
there is such a regex, it belongs to a replacement session that is
about to begin.

This fixes https://savannah.gnu.org/bugs/?65369.
The issue was reported by `correctmost`.

Bug existed since version 2.8.2,
since searching in a help text became possible.
2024-02-26 13:20:24 +01:00
Benno Schulenberg
db72774458 verbatim: avoid referencing an uninitialized value
Only check input bytes when their count is nonzero.

This fixes https://savannah.gnu.org/bugs/?65365.
The issue was reported by `correctmost`.

The problem existed since version 5.7, commit c75a3839,
but occurred more easily since version 7.0, commit 75e5f885.
2024-02-26 10:48:51 +01:00
Benno Schulenberg
3d727266c3 input: for one bump of the mousewheel scroll two lines, not three
Scrolling three lines at a time goes too fast: it feels erratic.
Whereas scrolling two lines at a time still feels like scrolling.
2024-02-25 16:14:44 +01:00
Andy Koppe
4673e709b2 input: scroll on mousewheel events instead of moving the cursor
Translate mousewheel events into Alt+Up/Down key presses instead of
into plain Up/Down key presses, as the latter only start scrolling
once the cursor reaches the top or bottom.

Scrolling rather than moving the cursor is the standard behavior for
mousewheel events in GUI editors such as Gedit and Kate, as well as
in the mouse mode of terminal editors such as vim, joe, and mcedit.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
2024-02-23 16:06:33 +01:00
Benno Schulenberg
f1a04f780a syntax: javascript: recognize also the .mjs extension
The V8 JavaScript-engine developers recommend using this extension:
  https://v8.dev/features/modules#mjs

Also, add the fairly new "JavaScript source" as magic description.

This fulfills https://savannah.gnu.org/bugs/?65334.
Requested-by: Matt Whitlock <gnu@mattwhitlock.name>
2024-02-20 17:00:48 +01:00
Benno Schulenberg
eca5856d99 tweaks: remove two pairs of unneeded braces, and normalize a line 2024-02-18 15:02:51 +01:00
Benno Schulenberg
190221c91c justify: set x = 0 for the undo item, for when using --cutfromcursor
When --cutfromcursor is active, 'current_x' needs to be set to zero when
doing a justification, so that the correct starting position gets stored
in the undo item.  (Without --cutfromcursor, the value of 'current_x'
does not matter.)

This fixes https://savannah.gnu.org/bugs/?65317.
The issue was indirectly reported by `correctmost`.

Bug existed in this form since version 5.0, commit ae5a4ece.

Between versions 4.0 and 5.0, nano would not eat a line but would
instead crash when undoing a justification that was done with the
cursor away from the left edge.
2024-02-16 15:56:22 +01:00
Benno Schulenberg
77d74b5d81 input: flush the keystroke buffer upon any kind of error condition
This stops the execution of a macro or a string bind whenever something
unexpected happens, to prevent the waiting keystrokes from doing things
that were not intended.

Especially this prevents an infinite loop: when during the recording
of a macro the `runmacro` keystroke is typed in some menu (where the
keystroke is not bound), and the macro is later replayed in a way that
results in exiting from that menu before the `runmacro` keystroke gets
replayed...

This fixes https://savannah.gnu.org/bugs/?65301.
The issue was reported by `correctmost`.

Bug existed since version 2.9.0, since the macro feature was introduced.
2024-02-14 09:23:18 +01:00
Benno Schulenberg
0e44752ba1 justify: set the correct starting point also with --cutfromcursor
When --cutfromcursor is active, 'current_x' does need to be zero for
the segment extraction to do the right thing.

This fixes https://savannah.gnu.org/bugs/?65289.
The issue was indirectly reported by `correctmost`.

Bug existed since version 4.0, commit 2500debb.
2024-02-11 16:31:20 +01:00
Benno Schulenberg
20692e0c29 browser: restore typing position at prompt after "^R name ^T ^F ^V ^C"
When going back from the browser to a file prompt, restore the typing
position also after a 'to_first_file' (^Y) and 'to_last_file (^V).

The cursor misplacement existed since version 5.9, commit 508301a2.
2024-02-11 16:05:56 +01:00
Benno Schulenberg
206b4e2a7e search: avoid a crash after a nested search, reported by correctmost
When going back to a previous prompt, restore the typing position
also for 'to_first_line' (^Y) and 'to_last_line (^V).

This fixes https://savannah.gnu.org/bugs/?65278.

Bug existed since version 5.9, commit 6d5b1656, which allowed exiting
from a Search-in-help prompt with ^Y or ^V.
2024-02-11 14:57:24 +01:00
Benno Schulenberg
8fefee2d41 undo: prevent a use-after-free, reported by correctmost
When the cursor is on the last line, and an undo removes this line,
do not let 'openfile->current' become invalid.

This fixes https://savannah.gnu.org/bugs/?65279.

Bug existed since version 6.3, commit eea3e1f0.

(It should have been fixed in commit 9410a556, more than a year ago.)
2024-02-10 12:14:52 +01:00
Benno Schulenberg
cdaa43b396 syntax: makefile: ensure that the <Tab> key always produces a tab
Making it independent from the `tabstospaces` setting.

And remove the now-redundant suggestion from the sample nanorc.
2024-02-05 17:17:37 +01:00
Benno Schulenberg
a0eebf20db bindings: in the tiny version, bind M-6 only in main, not at the prompts
This prevents M-6 from unexpectedly exiting from the prompt
and then copying a line in the edit window.
2024-01-31 08:34:02 +01:00
Benno Schulenberg
b84f6fc15f general: include the Copy function (M-6 or ^C) into the tiny version
When using --modernbindings with the tiny version, it was strange that
^X cuts and ^V pastes but ^C complains about being unbound.  Fix that.
2024-01-31 08:21:28 +01:00
Benno Schulenberg
d0a1bc361a help: restore ^H and ^D as the primary shortcuts for Backspace and Delete
Commit 18b37c98 moved the bindings of ^H and ^D further down.  Now move
the bindings of <Bsp> and <Del> to after those, so that ^H and ^D will
be shown again first in the help text (when not using --modernbindings).
2024-01-30 08:13:23 +01:00
Benno Schulenberg
d35650b034 docs: document the new --modernbindings option 2024-01-29 10:40:48 +01:00
Benno Schulenberg
580eaf29d6 bindings: set up modern bindings also when binary's name starts with "e"
This allows activating the "modern" bindings without having to pass an
option, by simply invoking nano through a symlink -- for example: `en`
(short for "editor nano"), or `et` (short for "edit"), or just `e`.
2024-01-29 10:40:48 +01:00
Benno Schulenberg
a27da0d75b bindings: with --modern, do not let ^Q^Q quit nano without saving
With --modernbindings, instead accept ^Q^X for abandoning any changes
-- the inverse of the normal (but undocumented) ^X^Q.

This prevents the unintentional loss of work when the user hits ^Q twice
by accident.
2024-01-29 10:40:48 +01:00
Benno Schulenberg
26c75a6828 bindings: with --modern, use ^H for Help when the terminal allows it
Also, allow using ^H (or ^N) for exiting from Help too.
2024-01-29 10:40:48 +01:00
Benno Schulenberg
c32828bb13 tweaks: normalize the indentation after the previous change 2024-01-29 10:40:48 +01:00
Benno Schulenberg
18b37c980a new feature: option --modernbindings sets up more widespread key bindings
With --modernbindings, ^Q quits, ^F finds, ^B finds backwards, ^G finds
again, ^D finds again backwards, ^X cuts, ^C copies, ^V pastes, ^A sets
the mark, ^R replaces, ^O opens a file, ^W writes out a file, ^S saves,
^Z undoes, ^Y redoes, ^P shows the position, ^T goes to a given line,
and ^E executes.

Note that with --modernbindings ^Q and ^S are always bound, meaning that
--preserve / 'set preserve' is ignored.  This is necessary because ^Q is
an essential keystroke in the modern bindings.

Also note that these "modern bindings" are effective only in the main
edit window, not in the various menus.  In all menus ^C means Cancel,
and I can't think of a good alternative default keystroke for that
(in order for ^C to mean Copy).  And in a few menus ^V has a meaning,
and there is no good alternative for that either.  So... in the menus
the user has to use M-6 for Copy and ^U for Paste (and ^K for Erase --
Cut does not exist in the menus), like with the default bindings.
2024-01-29 10:40:48 +01:00
Benno Schulenberg
64ac4610de tweaks: rewrap a comment, and reshuffle seven declarations
Also, drop three unneeded initializations.
2024-01-28 09:35:40 +01:00
Benno Schulenberg
dea34733a4 tweaks: move two static declarations to the only function that uses them 2024-01-27 11:41:57 +01:00
Benno Schulenberg
0e72c0d372 chars: add a helper function for stripping leading blanks from a string
And apply this function to the formatter and linter command strings,
to complement the bug fixes in the previous two commits.
2024-01-25 16:50:09 +01:00
Benno Schulenberg
88c8da143f linter: do not mess up the input stream when the linter command is empty
Instead simply say that no linter is defined.

This fixes https://savannah.gnu.org/bugs/?65204.

Bug existed since version 5.5, commit bc368133, but before
that commit nano would crash on an empty linter command.
2024-01-24 16:23:09 +01:00
Benno Schulenberg
367f84b0ec formatter: do not crash when the formatter command is empty
Instead simply say that no formatter is defined.

This fixes https://savannah.gnu.org/bugs/?65196.

Bug existed since version 4.6, since the formatter was reintroduced.
2024-01-24 16:22:04 +01:00
Benno Schulenberg
1a3ef7e497 docs: fix a ten-year-old typo, reported by correctmost
This fixes https://savannah.gnu.org/bugs/?65193.
2024-01-23 13:18:09 +01:00
Benno Schulenberg
c19012d4cd docs: say "mini bar", not "minibar", when referring to the actual bar
Like is done for the other bars: title bar, status bar, prompt bar.
2024-01-20 11:02:54 +01:00
Benno Schulenberg
b502631d10 docs: mention the changed meanings of ^F/^B and also in the texi manual
Also somewhat reword the note for version 4.0.
2024-01-18 11:06:01 +01:00
Benno Schulenberg
6728e5d791 docs: mention the missing two options that override --bold
And improve one word.
2024-01-16 16:15:22 +01:00
Benno Schulenberg
101b53b541 docs: add ^T^S (spell check) and M-S (softwrap) to the cheatsheet
Also, adjust the alignment of the two header lines,
and slightly reword one of the descriptions.
2024-01-16 10:56:41 +01:00
Benno Schulenberg
11c492fdd0 docs: add M-C and M-Z to the cheatsheet, and reshuffle for balance 2024-01-13 11:27:28 +01:00
Benno Schulenberg
792d4e9a23 docs: adjust the cheatsheet for the changed meanings of ^F, ^B, M-F, M-B 2024-01-13 11:22:14 +01:00
Mike Frysinger
c59e9d228e build: link in $(GETRANDOM_LIB) from gnulib
On Windows builds, gnulib might set GETRANDOM_LIB to -lbcrypt and then
use that API.  But since we don't include $(GETRANDOM_LIB) when linking,
we fail.  On Linux systems, this is empty as getrandom APIs are part of
the main C library already.  This is also what the link requirements say
in gnulib's modules/getrandom spec.
2024-01-12 17:00:34 +01:00
Mike Frysinger
d8848df14f gnulib: import canonicalize-lgpl for realpath
Building for mingw fails due to missing realpath.  Pull in the gnulib
module to get it working again.
2024-01-12 16:59:40 +01:00
Benno Schulenberg
4a2729b780 copyright: update the years for the FSF 2024-01-10 11:24:28 +01:00
Benno Schulenberg
7c174a1a25 syntax: c: require a preceding blank when a line comment contains a quote
This avoids miscolorizing part of a string when it contains a URL.

This fixes https://savannah.gnu.org/bugs/?64340.
Reported-by: Yonut Smith <deanlast3@gmail.com>

Problem has existed for more than twenty years, at least since support
for multine-line regexes was added in commit 6c1e6612 in 2002.
2024-01-09 10:20:50 +01:00
Benno Schulenberg
f0e69b4a51 tweaks: use a pair of parentheses to clarify the order of operations
(Parentheses are used everywhere else with a bitwise &.)
2024-01-08 17:25:03 +01:00
Benno Schulenberg
4a915b1ed5 input: avoid hanging after a 39-character paste on a VSCode terminal
The terminal in VSCode splits pastes into 50-byte chunks and can
thus split an escape sequence somewhere in the middle, resulting
in nano failing to recognize the end-of-bracketed-paste sequence
and thus hanging -- until another, different-sized paste is made.

Avoid this hang by interpreting any invalid escape sequence that
starts with "\e [ 2" as a truncated end-of-bracketed-paste.

(This will leave a spurious tilde after the 39-character paste,
which is not nice but... better than hanging.)

This works around https://savannah.gnu.org/bugs/?64996.
Reported-by: Jacob Lifshay <programmerjake@gmail.com>
2023-12-21 15:40:21 +01:00
Benno Schulenberg
cbf5a5b5d3 docs: in the sample nanorc, set the guidestripe to a soft grey
This gives both an example of the #rgb format and shows that the
guidestripe can be set to an unobtrusive color.
2023-12-18 16:14:10 +01:00
Benno Schulenberg
41b52d70be input: recognize certain escape sequences for F13 to F16 again
Even though in nano the names F13 to F24 exist, these names actually
refer to Shift+F1...Shift+F12.  One cannot blame people for thinking
that F13 in nano is the same as F13 in Xorg, so... recognize the escape
sequence for the latter and map it to what nano calls F13.

This accommodates users that put F13...F16 in a custom keymap for Xorg.

This fixes https://savannah.gnu.org/bugs/?64632.
Reported-by: Danny Milosavljevic <dannym@scratchpost.org>

Problem existed since version 5.0, commit 9a6158cd.
2023-12-17 17:48:04 +01:00
Benno Schulenberg
129696cdbe gnulib: update to current upstream state, to make a fresh checkout work
Also, increase the checkout depth, so that it will work for longer.

Indirectly-reported-by: Jacob Lifshay <programmerjake@gmail.com>
2023-12-10 10:58:01 +01:00
Benno Schulenberg
8cc3ab213d tweaks: rename a variable, to be clearer when seen in context 2023-12-09 16:25:02 +01:00
Benno Schulenberg
9bf966af37 tweaks: add an extra variable, to avoid reusing one for another purpose 2023-12-08 16:12:17 +01:00
Benno Schulenberg
a76a6bf692 softwrap: remember the actual breaking point when wrapping at blanks
When softwrapping at blanks, the wrapping routine should, when called
again, continue searching from where the previous chunk ended, not from
the point it reached during that previous search, because this could be
*just* beyond the space that could be the next breaking point.

This fixes https://savannah.gnu.org/bugs/?64945.
Reported-by: Andreas Schamanek <schamane@fam.tuwien.ac.at>

Bug existed since version 6.4, commit 0e9bef34.
2023-12-06 17:18:41 +01:00
Benno Schulenberg
6a7a0c8f50 display: show the help lines down to the tiniest possible terminal size
That is: compute the minimum needed terminal height more accurately.
2023-11-25 17:07:05 +01:00
Benno Schulenberg
f5bc261944 general: let the constant-show toggle override the zero-interface mode
When the user hits the M-C toggle while option --zero is in effect,
instead of complaining "Not possible", do what the user probably
tries to achieve: cancel `zero` mode and switch on `constantshow`.
2023-11-25 17:07:05 +01:00
Benno Schulenberg
8a304bdf7c bindings: make ^F start a forward search by default
This makes nano more usable for users that are accustomed to the
near universal use of ^F for Find/Search in other programs, and
especially for users that somehow access a terminal through their
browser (where ^W will, destructively, close the terminal tab).

(To keep the bindings consistent, make ^B start a backward search,
and let M-F and M-B search for the next occurrence in the matching
direction.)

Suggested-by: Chris Allegretta <chrisa@asty.org>
Suggested-by: Donnie Ferris <DonnyBahama@gmx.com>
  https://lists.gnu.org/archive/html/nano-devel/2023-01/msg00001.html
2023-11-24 16:24:08 +01:00
Benno Schulenberg
124e86a6d2 undo the prelast commit in order to redo it with a fuller commit message 2023-11-24 14:42:08 +01:00
Benno Schulenberg
96df9e0a20 docs: mention how to get the old behavior of ^F, ^B, M-F, and M-B back 2023-11-22 10:52:34 +01:00
9228180b1e Merge branch 'master' into line-folding 2023-11-01 12:47:08 -07:00
Benno Schulenberg
a04d2a433c bindings: make ^F start a forward search by default
This makes nano more usable for users that are accustomed to the
near universal use of ^F for Find/Search in other programs.

To keep the bindings consistent, make ^B start a backward search,
and let M-F and M-B search for the next occurrence in the matching
direction.
2023-10-30 15:01:53 +01:00
Benno Schulenberg
ef35ea72cf input: neutralize two spurious keycodes from VTE terminals
At least some of the VTE-based terminals claim to be compatible with
xterm-25color (and set TERM to that value).  But they really aren't:
they mishandle the focus-in and focus-out events, for example.  So,
catch and discard the corresponding keycodes that nano shouldn't be
seeing at all.

This improves the fix for https://savannah.gnu.org/bugs/?64578.
2023-10-16 08:55:06 +02:00
Benno Schulenberg
8804b6dcd4 tweaks: adjust a comment for the changed handling of gray #rgb codes 2023-10-03 15:41:00 +02:00
Andy Koppe
86b8388889 rcfile: map the gray #rgb codes (#111 to #EEE) to the xterm grayscale
When the red, green and blue components of a three-digit hex #RGB code
are equal and they aren't #000 for black or #FFF for white, map them to
xterm-256color's 24-level grayscale ranging from index 232 to 255.

This means that the 14 gray levels available in #RGB codes all map to
different tones, whereas previously they mapped to only the four gray
tones available in the 6x6x6 color cube.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
2023-09-25 16:10:42 +02:00
Benno Schulenberg
812c48dde4 tweaks: add a comment that refers to the VTE spurious-code issue 2023-08-29 16:17:40 +02:00
Benno Schulenberg
f0f1c94afa input: intercept a spurious keycode and say what the actual problem is
Xfce Terminal sets TERM to xterm-256color even though it does not have
all the capabilities that an xterm has, leading it to misinterpret some
escape sequence and produce a spurious 0x24C key code.

Intercept this mistaken key code and tell the user what is wrong.

This mitigates https://savannah.gnu.org/bugs/?64578.
Reported-by: Lawrence R. Steeger
2023-08-27 15:01:37 +02:00
Benno Schulenberg
75b312ded1 revert the previous commit -- forget about -? as a synonym for --help
An ambiguous option like --back or --word would cause nano to spew
the entire help text.  It should do the latter only when the user
explicitly requests it.
2023-08-27 14:56:05 +02:00
b2f79e3a6e Merge branch 'master' into line-folding 2023-08-25 12:48:22 -07:00
Mateusz Kazimierczuk
e65b0ba654 options: add -? as a synonym of -h (--help)
The short option '-?' was removed nine years ago in commit 43019189,
then restored six years later in 5bd92d4c, and then removed again two
months later in 743100fe due to getopt() returning '?' for options
that aren't recognized, preventing the use of '-?' as a valid option.

However, getopt() provides a way to check for unrecognized options
via the 'optopt' variable, which gets set only for invalid options.

Signed-off-by: Mateusz Kazimierczuk <mataha+savannah@protonmail.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2023-07-31 07:40:07 +02:00
Benno Schulenberg
d3dd403dc7 browser: report an error instead of crashing when the folder disappears
When the directory that the user is browsing in is deleted by another
process at the moment that nano is building the list of file names,
this can result in an empty list, which some items in the main loop
in browse() cannot handle.  Prevent this mishandling by not entering
the loop when the list is empty.

This fixes https://savannah.gnu.org/bugs/?64465.
Reported-by: Jerry Meng <jerrytstng@gmail.com>
2023-07-24 15:25:35 +02:00
Benno Schulenberg
7f4c2c6a25 docs: add a caveat in the FAQ about bracketed pastes 2023-06-04 08:07:10 +02:00
4622210cfb Fix some sh*t 2023-06-03 19:49:44 -07:00
Benno Schulenberg
cb1b3a28ab tweaks: normalize the indentation after the previous changes 2023-05-21 11:29:02 +02:00
Benno Schulenberg
f7d8735b6b tweaks: reshuffle four lines, to allow folding some #ifdefs together
Also remove an unneeded pair of braces, split a comment,
and correct a mistaken #ifdef.
2023-05-21 11:27:45 +02:00
Benno Schulenberg
fc42ab9b46 bindings: allow speller and friends to be rebound also in restricted mode
Speller, linter, formatter, and execute-a-command cannot be used in
restricted mode, but the relevant keys should report that the function
is *disabled*, not that the key is unbound.

This fixes https://savannah.gnu.org/bugs/?64226.

Problem existed since version 3.2, since nano reads the nanorc files
also in restricted mode.
2023-05-21 10:51:37 +02:00
Benno Schulenberg
7f17777a4b docs: mention that a restricted nano does not access the history files
With some imagination, the lack of access could be inferred from the
other descriptions, but it's much better to be clear and explicit.

Also, separate two items that are unrelated and reshuffle them into
a neater order.

Triggered by https://savannah.gnu.org/bugs/?64181.
2023-05-14 08:17:25 +02:00
Benno Schulenberg
bcdb27416c docs: describe nano more specifically as a text editor
Especially the first sentences introducing nano should use the words
"text editor" and not just "editor".
2023-05-14 08:11:44 +02:00
Benno Schulenberg
15c6396d42 tweaks: rename a symbol (to be clearer), and add three missing comments 2023-05-14 08:11:05 +02:00
Benno Schulenberg
2c19345e58 docs: in a synopsis, use braces around a choice of required parts
This seems to be the convention.  For an example, see `man tar`.

This addresses https://savannah.gnu.org/bugs/?64125.
Reported-by: Eric S. Raymond <esr@thyrsus.com>
2023-05-01 10:48:02 +02:00
Benno Schulenberg
69a7dd86ec feedback: suppress filename and linecount when --zero is active
This suppression prevents the filename flashing by at the bottom
of the screen when switching between buffers.

This addresses https://savannah.gnu.org/bugs/?64019
Reported-by: Alan Cristhian Ruiz <alancristhian@protonmail.com>

Problem existed since version 6.0, since --zero was introduced.
2023-04-12 09:58:28 +02:00
9317206586 Add colorization to folding segments.
I already added this for myself since I've been using this patch for a while
so I figured I'd include it. This simply makes it possible to colorize the
folded segments as the user desires. An option 'foldedcolor' is enabled for
the rcfile.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:52:59 -07:00
7027b9b601 Add option '--enable-folding' and add shortcut for folding.
In order to test the functionality, one actually has to be able to build it!
This patch adds an option to the configure script, builds 'folding.c', and
adds a shortcut to make folding possible. The shortcut here is set to 'M-['.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:52:38 -07:00
fc3598f116 Handle all the more complicated modifications to existing functionality.
Not everything is as simple as just UNFOLD_SEGMENT. These are the cases where
specific modifications were needed. Most of the actual heavy lifting was done
when modifying the functions 'update_line' and 'do_prev_word'.

Most of the changes here actually came down to 'get_row_from_edittop' or
changing from 'update_line' to 'update_line_at'.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:52:13 -07:00
90dac326c1 Modify line number arithmetic to no longer assume linear increments.
When adding folding lines, the lines drawn on screen are no longer
guaranteed to increment one by one. There could be a large skip when
handling folded segments. So instances where the codebase assumed
'openfile->current->lineno - edittop->lineno' would yield the position
on screen of the current line needed to be modified. Similar problems
existed in many places so a function 'get_row_from_edittop' handles
finding the current position of a line in relation to 'edittop'.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:51:53 -07:00
a299827554 Modify signatures of functions to be modular for further folding patches.
The bracket search functions 'find_a_bracket' is very useful for searching for
region to fold when no selection is made. To make this possible, the function
needed to be modularized so it could be reused in a way not originally
intended.
The functions 'do_prev_word' and 'do_next_word' were interesting in that
sometimes it is desirable to get the corresponding word within a folded
segment and sometimes it was better to skip folded segments. So a boolean
parameter seemed like a good way to not duplicate functionality while
making the function work for both cases.
The 'update_line' function only worked in relation to edittop from the
given line's lineno. This obviously won't get the correct position if
there are folded lines. So I added a new function 'update_line_at' to
allow specifying where in the window to update when calling the function.
The original 'update_line' still exists to not modify existing code
utilizing it.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:50:46 -07:00
a39e61a3e0 Add calls to UNFOLD_SEGMENT in existing functions.
Nano's existing functionality needs to mesh with the ability to
fold lines. The most common of these issues is needing to unfold
when a line is updated or the user accesses a line inside of a folded
segment. This patch handles all the places this can be done simply
with a 1 or 2 line modification.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:50:22 -07:00
584571248f Add the basic support structure for the folding.
Adds in some preprocessor directives for easily adding in unfolding
support to existing functions that require it. Also adds in some
helper functions in 'folding.c' for common tasks which will need
performed. And of course add the 'folded' boolean to the linestruct
type so we know which lines are currently folded.

Signed-off-by: rexy712 <rexy712@protonmail.com>
2023-04-06 11:49:38 -07:00
Benno Schulenberg
fdcafb83e3 startup: use a format string, to deflect format-string attacks
This fixes the second part of https://savannah.gnu.org/bugs/?63964.

Reported-by: Vince Vince
2023-03-27 12:09:21 +02:00
Benno Schulenberg
b8ead3b511 linter: use a format string, to deflect format-string attacks
This fixes the first part of https://savannah.gnu.org/bugs/?63964.

Reported-by: Vince Vince
2023-03-27 12:09:21 +02:00
Benno Schulenberg
ffff664918 tweaks: shrink the set of characters recognized as line-column separator
This slightly reduces the chance that a filename is accidentally parsed
as containing both a line and a column number at its end.
2023-03-10 15:14:31 +01:00
Benno Schulenberg
bf984ecb9b docs: document the <filename>:<linenumber> thing for cursor positioning 2023-03-09 16:14:44 +01:00
Benno Schulenberg
f1e238a9af tweaks: condense the code that searches for a colon plus line number 2023-03-09 12:56:17 +01:00
Benjamin Valentin
5290a85afd new feature: interpret also <filename>:<linenumber> when opening a file
Various tools will output filenames with line numbers in the format
<filename>:<line>:<column>.  Support this format in addition to the
+<line>,<column> format when opening files.

Signed-off-by: Benjamin Valentin <benpicco@googlemail.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2023-03-08 11:48:20 +01:00
Benno Schulenberg
b5157dd9cb tweaks: avoid calling isblank()/isalpha() on what could be a signed char
The isxxxxx() functions expect their parameter to be either EOF or
a value in the unsigned char range.  Passing a negative char value
could (in theory) result in unexpected behavior.
2023-02-24 17:31:58 +01:00
Benno Schulenberg
94812d17c8 tweaks: rename a struct element, to avoid a theoretical name collision
The <term.h> header file form ncurses defines the name "tab".
2023-02-23 17:08:45 +01:00
Benno Schulenberg
7681090c12 docs: clarify that a fileregex is matched against the absolute filename 2023-02-16 11:02:15 +01:00
Benno Schulenberg
866490c41f docs: add two examples of custom key bindings to the nanorc manpage 2023-02-16 10:44:10 +01:00
Benno Schulenberg
0662fc4d42 shutdown: ignore a modified buffer when in view mode
In view mode it should be impossible to modify any buffer, but...
when (through some bug) the user did succeed in modifying a buffer,
this should not lead to writing out this modified buffer to disk.

Had this safety stop been present earlier, it would have prevented
the second part of https://savannah.gnu.org/bugs/?63616.
2023-02-14 10:25:38 +01:00
Benno Schulenberg
078d612b9e tweaks: add a missing 'type' attribute to a <style> tag
To stop the W3 validator from complaining.
2023-02-03 17:30:27 +01:00
Benno Schulenberg
26025f79ce docs: add a reference to the 'help-nano' mailing list 2023-01-30 17:13:17 +01:00
Benno Schulenberg
1c307bc1be docs: add a clarifying note to the description of --tabstospaces 2023-01-26 17:01:48 +01:00
Benno Schulenberg
7abddbd752 tweaks: slightly improve a comment, to be more accurate
A string bind can only contain bytes (chars), not keycodes (integers,
in nano upto 0x4FF).  So, apart from an error code or a placeholder
command code, get_code_from_plantation() can only return a byte.
2023-01-26 17:01:02 +01:00
Benno Schulenberg
51c9f7270c input: let the handler of string binds return a byte whenever possible
The function get_code_from_plantation() should return ERR only when
the string bind is fully exhausted.  In the normal case, where some
bytes are still available, it should return the first of these bytes,
so that the {verbatim} function will work too.

This fixes https://savannah.gnu.org/bugs/?63702.

Bug existed since version 7.0, commit 958ec294,
since command cartouches were introduced.
2023-01-26 10:01:18 +01:00
Benno Schulenberg
b896670e85 tweaks: make two strings equal to a third, to slightly ease translation 2023-01-25 16:45:50 +01:00
Benno Schulenberg
69dd0c40bb help: give the "Replace with" prompt its own help text
This addresses https://savannah.gnu.org/bugs/?63691.

Problem existed since the help texts were introduced,
in version 1.1.3, commit b3655b4c.
2023-01-23 16:41:25 +01:00
Matteo Raso
c374c773ad syntax: python: colorize decorators specially
Decorators are documented at https://peps.python.org/pep-0318/.

Signed-off-by: Matteo Raso <matteo_luigi_raso@protonmail.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
2023-01-22 12:31:45 +01:00
Benno Schulenberg
2fd7888a51 bindings: show ^- instead of ^/ for 'flipgoto' when on a Linux console
This should have been part of commit 344db835 from three days ago.
2023-01-20 14:55:11 +01:00
Jordi Mallach
d19915ea44 docs: fix "availabilty" typo in the manual and the nanorc manpage 2023-01-19 09:24:58 +01:00
Benno Schulenberg
549e37d218 po: update translations and regenerate POT file and PO files 2023-01-18 09:52:50 +01:00
Benno Schulenberg
7b48a9f671 bump version numbers and add a news item for the 7.2 release 2023-01-18 09:07:41 +01:00
Benno Schulenberg
344db835e4 bindings: let ^/ toggle between the 'search' and 'gotoline' menus
This extra binding allows the user to start a forward search with ^/^/,
so that they can avoid the ^W keystroke that would close a browser tab.
2023-01-17 11:00:27 +01:00
Benno Schulenberg
04353acccf gnulib: update to its current upstream state 2023-01-17 10:51:40 +01:00
Benno Schulenberg
c33f0b7d8d docs: give ^K and ^U some useful function in the alternative bindings
Make them behave like in a shell: let ^K delete till end-of-line,
and let ^U delete to beginning-of-line.
2023-01-12 15:55:38 +01:00
Benno Schulenberg
fd51fee424 docs: put the binding of ^Y after its unbinding, for it to be effective
The misordering existed since commit 16ee4636 from a year ago.
2023-01-12 15:44:01 +01:00
Benno Schulenberg
c8b44816fe tweaks: separate a special thanks from the preceding ones
This separation avoids the impression that we're thanking the mentioned
people for their use of nano (something they probably don't do).

(Also, remove two other blank lines -- effectively moving these two
lines further up, keeping the total amount of whitespace the same.)
2023-01-06 12:37:08 +01:00
Benno Schulenberg
6e88389fb8 copyright: update the years for the FSF 2023-01-06 10:37:15 +01:00
Benno Schulenberg
298447e22d syntax: html: colorize specially the other two emphasizing tags too
In most cases, <em> behaves like <i> and <strong> behaves like <b>,
so it makes sense to treat all of them in the same manner.
2023-01-05 17:01:20 +01:00
Benno Schulenberg
a3c7de8a50 tweaks: rewrap an old news item 2023-01-05 11:50:06 +01:00
Benno Schulenberg
264f305d94 input: disallow bracketed pastes when in view mode
When in view mode, nothing shouldbe allowed to be entered into
(or deleted from) the buffer.

This fixes https://savannah.gnu.org/bugs/?63616.
Reported-by: Timothy Liu <liuxf19@163.com>

Bug existed since version 4.8, commit 0e6d693d.
2023-01-04 11:10:28 +01:00
Benno Schulenberg
f8ec08a928 tweaks: avoid warnings when compiling with -Wpedantic 2023-01-02 10:48:18 +01:00
Benno Schulenberg
f09e6c183e po: update translations and regenerate POT file and PO files 2022-12-14 11:34:51 +01:00
Benno Schulenberg
3791ed86a3 bump version numbers and add a news item for the 7.1 release 2022-12-14 10:50:32 +01:00
Benno Schulenberg
7f772693eb tweaks: wrap overlong lines in the Tcl syntax, to make them manageable
(And also to stay within the theoretical 256-byte POSIX limit.)
2022-12-11 12:40:22 +01:00
Benno Schulenberg
5771f1ea14 copyright: update the last year for significantly changed files 2022-12-11 12:28:07 +01:00
Benno Schulenberg
0f4db1ed0d docs: say thanks to the Albanian translator
Also, properly sort a nearby name and add its missing diacritic.
2022-12-09 11:58:07 +01:00
Benno Schulenberg
4b35626aec rcfile: report an error when an included file does not exist
That is: do not silently return from parse_one_include() when the
given file does not exist, *and* return the filename (or pattern)
itself when it matches nothing.

This fixes https://savannah.gnu.org/bugs/?63446.

Bug existed since version 4.0, commit d3f0d32e.
2022-12-02 11:37:05 +01:00
Benno Schulenberg
846588ee81 tweaks: avoid passing NULL to access()
This prevents an unwanted message when nano
is compiled with -fsanitize=undefined.

This fixes https://savannah.gnu.org/bugs/?63447.

Problem existed since version 4.8, commit 343f97b3,
since the --rcfile option was added.
2022-11-30 12:08:47 +01:00
Benno Schulenberg
4f92b12a6a text: upon Enter, eat only lefthand blanks, not any other characters
Make sure that there is only whitespace to the left of the cursor
before setting 'allblanks' to TRUE, because this latter value will
cause these characters to be eaten (as a special case, to avoid
creating lines that contain only blanks when both --autoindent
and --breaklonglines are on).

This fixes https://savannah.gnu.org/bugs/?63407.
Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Bug existed since version 2.9.8, commit d00ab406.
2022-11-28 11:01:50 +01:00
Benno Schulenberg
4b4b20f8a9 build: fix compilation when configured with --disable-comment
This fixes https://savannah.gnu.org/bugs/?63372.
Reported-by: Hannu Nyman <hannu.nyman@iki.fi>

Problem existed since version 7.0, commit 4b928b46.
2022-11-18 16:49:23 +01:00
Benno Schulenberg
e26fe9bddd po: update translations and regenerate POT file and PO files 2022-11-15 11:44:29 +01:00
Benno Schulenberg
972be2df04 bump version numbers and add a news item for the 7.0 release 2022-11-15 11:17:34 +01:00
Benno Schulenberg
374cb6a7f8 gnulib: update to its current upstream state 2022-11-13 12:23:45 +01:00
Benno Schulenberg
923d6300ad tweaks: attribute some of the features that were added in the last years 2022-11-11 16:39:34 +01:00
Benno Schulenberg
baa4edc6ca docs: improve the legibility of an itemized list
Also, mention my email address in the colophon of the PDF,
to avoid the impression that Chris is the sole responsible.

And improve the general layout by adding three blank lines.
2022-10-20 15:44:44 +02:00
Benno Schulenberg
9875311bcc startup: for +/string, center the found occurrence when possible
This places the cursor in a more predictable position.

This fixes https://savannah.gnu.org/bugs/?63223.

Issue existed since version 4.4, commit a9dd73fb,
since the +/string feature was introduced.
2022-10-17 12:11:41 +02:00
Benno Schulenberg
c3a453512a startup: report an empty search string also when there is a modifier
Not just for +/ (a search command without a string) should nano report
an "Empty search string", but also for +c/ or +r/ or similar.

This fixes https://savannah.gnu.org/bugs/?63222.

Bug existed since version 4.4, commit 2326bf69.
2022-10-16 11:22:32 +02:00
Benno Schulenberg
e413ed8e1d execute: show "Cancelled" instead of "Error" when the user hits ^C
(The "Cancelled" is shown with a red background, like an error,
but that is needed so that do_undo() will be called afterward.)
2022-10-09 16:28:06 +02:00
Benno Schulenberg
858f411447 filtering: terminate also the sender process when the user hits ^C
When the user interrupts an external command that hangs or takes too
long, nano should also kill the data-sending process (when present).

This fixes https://savannah.gnu.org/bugs/?63177.

Bug existed in this form since version 4.3, commit d946f38a,
but basically existed since version 3.0, commit ec339d3b.
2022-10-09 11:24:03 +02:00
Benno Schulenberg
19c8cea8e5 files: improve the error handling when executing an external command
When something goes wrong while executing an external command or while
piping text to it, report an error on the status bar and restore the
state of the buffer to what it was before the execution.

This fixes https://savannah.gnu.org/bugs/?63114.

Bug existed since version 2.9.8, since filtering text was introduced,
but basically existed since before version 2.0.0, since executing an
external command was introduced.
2022-10-07 09:32:11 +02:00
Benno Schulenberg
1ae10b1487 tweaks: elide an unused return value
The execute_command() function — then called open_pipe() — was changed
to have a boolean return value in commit ce62e82a eighteen years ago,
but the value has never been used or checked.
2022-10-03 10:28:43 +02:00
Benno Schulenberg
35cde9f8d7 tweaks: elide an unused parameter
The parameter has been redundant since commit 9faa9545 from two years ago.
2022-10-03 10:10:10 +02:00
Benno Schulenberg
d4d2840f5d filtering: when returning to a line number, ensure it is within range
The function line_from_number() can handle only line numbers that exist,
and will crash otherwise.  (The lack of checks makes the function fast.)

This fixes https://savannah.gnu.org/bugs/?63120.

Bug existed since commit d1e28417 from five weeks ago.
2022-09-28 16:40:31 +02:00
Benno Schulenberg
119ec47072 tweaks: replace sizeof(char) with 1, as that is assumed anyway
Since commit c848ec3d from three years ago, nano has assumed that
'char' is always a single byte.  So... elide the last occurrences
of sizeof(char), as they give a false impression of generality.
2022-09-28 12:48:45 +02:00
Benno Schulenberg
ceb305a780 tweaks: avoid iterating over the same string twice in a row
The function recode_LF_to_NUL() has to iterate over the string anyway
(to replace each \n with \0), so... instead of calling strlen() right
before it, just let recode_LF_to_NUL() return the length of the string.

(This is not speed-critical code, but... it saves one iteration over
the entire buffer contents whenever writing out a file.)
2022-09-28 12:22:40 +02:00
Benno Schulenberg
1dc2a75cb6 files: before sending data to an external command, decode LF back to NUL
(There is no need to recode the NULs back to LFs because the sending of
the data happens in a separate process, which then simply disappears.)

This fixes https://savannah.gnu.org/bugs/?63106.

Bug existed since version 2.9.8, since filtering a buffer or a region
through an external command was introduced.
2022-09-27 15:48:03 +02:00
Benno Schulenberg
8d7b716ea7 startup: quit when standard input is not a TTY (after handling arguments)
Not quitting would make nano hang for several seconds (which is very
annoying) and then die and save an emergency file (which is useless).

This fixes https://savannah.gnu.org/bugs/?63109.

Bug existed chiefly since version 5.9, commit 8d1a666d,
but basically existed since before version 2.0.0.
2022-09-27 12:18:28 +02:00
Benno Schulenberg
034af70a65 tweaks: simplify a pasting routine, modelling it after the injection one 2022-09-26 16:10:15 +02:00
Benno Schulenberg
162c213e7b tweaks: improve two comments, and exclude two unneeded prototypes
And declare two more variables as 'static', like all its neighbors.
2022-09-26 15:53:22 +02:00
Benno Schulenberg
6fde7d8a51 input: allocate two small character buffers too, and never free them
Analogous to commit 3922b531: instead of allocating and later freeing
a tiny fragment of memory for every character that the user enters (in
the edit window or at a prompt), reserve a small piece in the beginning
and retain it, and increase (but never decrease) its size as needed.

This addresses the second part of https://savannah.gnu.org/bugs/?63086.
2022-09-25 16:15:31 +02:00
Benno Schulenberg
e4abef5768 input: give up when the capacity of the keystroke buffer overflows
In theory, the 'size_t' of 'capacity' could be just two bytes, which
means the keystroke buffer would overflow for pastes that are larger
than 32 kilobytes -- which are unlikely to occur, but... possible.
However, previously there was *no* overflow check when extending the
keystroke buffer (only when trying to put back a key code), so this
check is an improvement.

(On a regular machine, 'size_t' is at least four bytes, which means
the keystroke buffer would overflow at 2 gigabytes.  Such a paste
is extremely unlikely to occur, so this check is really a no-op.)
2022-09-25 10:17:32 +02:00
Benno Schulenberg
3922b531a8 input: allocate a small keystroke buffer, and never free it
Instead of allocating and freeing a tiny fragment of memory for every
keystroke, reserve a small piece in the beginning and then retain it,
because it will be needed again and again and again.  Increase the size
when needed (for a large paste, probably), but don't bother to shrink
it afterward.

This addresses the first part of https://savannah.gnu.org/bugs/?63086.
2022-09-25 09:22:29 +02:00
Benno Schulenberg
0d1438a731 tweaks: reshuffle a declaration, and correct the wording of a comment
Also, drop an unneeded condition, as memmove() allows moving zero bytes.
2022-09-23 09:34:14 +02:00
Benno Schulenberg
7eb66d3e09 tweaks: condense a comment, add two small ones, and reshuffle a line
(Apart from reducing the verbosity of the long comment, also harmonize
its format: mentioning the FreeBSD key always first.)
2022-09-22 10:50:05 +02:00
Benno Schulenberg
c7a600063d tweaks: reshuffle some lines, to be more readable instead of compact 2022-09-20 16:21:32 +02:00
Benno Schulenberg
5b654ce9fb docs: suggest a key binding for snipping trailing blanks
This addresses https://savannah.gnu.org/bugs/?63062.
2022-09-18 10:44:05 +02:00
Benno Schulenberg
98e9a881c0 docs: mention in the man page how M-V can insert any Unicode code point
This addresses https://savannah.gnu.org/bugs/?63055.

Inspired-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2022-09-18 09:05:28 +02:00
Benno Schulenberg
f420f7c177 verbatim: do not overwrite the status bar when the code is invalid
Move the triggering of the line redraw out of the error path, and
into a better place: next to the normal clearing of the feedback.

This fixes https://savannah.gnu.org/bugs/?63053.

Bug existed since version 6.0, commit 6d828cf4.
2022-09-13 16:57:28 +02:00
Benno Schulenberg
50954a4b6a search: skip a match on the magic line, as it is a just convenience line
As the magic line isn't really a line (it is not counted in the number
of lines read and written), and nothing is on it (not even a newline),
it doesn't make sense to allow any regex, like ^ or $, to match it.

This fixes https://savannah.gnu.org/bugs/?63034.
Indirectly-reported-by: Mike Scalora <mike@scalora.org>

Bug existed since before version 2.0.0.
2022-09-12 08:47:51 +02:00
Benno Schulenberg
567310e698 tweaks: reduce four variations of a message to a single common form
(This could have been done a long time ago, but it simply didn't occur
to me.)
2022-09-12 08:45:37 +02:00
Benno Schulenberg
f90b710c9b tweaks: group the special keycodes for implanted strings together
This shows better that they are related.
2022-09-11 17:49:44 +02:00
Benno Schulenberg
bdaec3f934 docs: clarify the distinction between binding a function and "{function}"
This addresses https://savannah.gnu.org/bugs/?63010.

Inspired-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2022-09-11 16:29:18 +02:00
Benno Schulenberg
8198fd9c58 tweaks: reword and/or condense four comments 2022-09-11 16:29:02 +02:00
Benno Schulenberg
358a10e3cc tweaks: elide an assignment by iterating with the target variable 2022-09-11 12:03:06 +02:00
Benno Schulenberg
7b935e0d40 tweaks: elide an intermediary variable that is no longer needed 2022-09-11 11:57:11 +02:00
Benno Schulenberg
7034c3cc47 tweaks: drop shunting of flags by calling the needed function directly
Calling strstrwrapper() with the Backwards, Casesens, and Regex flags
unset is equivalent to calling mbstrcasestr().  So... do that instead
and quit saving and restoring the flags for each call of findfile().

This saving-and-restoring has been redundant since commit b0957254
from eight years ago.
2022-09-11 11:51:34 +02:00
Benno Schulenberg
e30eadb4de verbatim: don't show dots during Unicode input, as they give wrong idea
The dots gave the impression that the next keystroke (hex digit) would
land somewhere on the dots.  But this is not so -- the current digits
are instead shifted to the left and the new digit is added at the end.

Also adjust and improve several comments.
2022-09-11 09:23:44 +02:00
Benno Schulenberg
3e3f4a167a tweaks: elide a function that does not need to be a separate function
Also elide three calls of tolower(), using ORing with 0x20 instead,
as we're dealing with plain ASCII here.

Rename a variable too, away from a double abbreviation.
2022-09-11 09:01:06 +02:00
Benno Schulenberg
c98528f8d3 tweaks: simplify a function now that a Unicode code can be typed quicker 2022-09-11 09:01:06 +02:00
Benno Schulenberg
75e5f885e5 verbatim: allow the user to finish Unicode input with <Enter> or <Space>
Instead of requiring always six digits, allow the user to indicate
with <Enter> or <Space> that the digits typed so far are the complete
Unicode code point (when prefixed with the missing number of zeroes).

This fulfills https://savannah.gnu.org/bugs/?63021.

Inspired-by: the <Ctrl+Shift+U> shortcut that some desktops have
2022-09-11 09:01:06 +02:00
Benno Schulenberg
40b9e68e02 goto: don't center the current line when the user specified a column only
This does not quite do what I would have liked (scroll only when needed)
when on a softwrapped line and jumping to a different chunk, but... it's
still better than needlessly centering the line.

(The user can still center the line, if that is what they want, by using
a period or a slash instead of a comma.)

This addresses https://savannah.gnu.org/bugs/?63008.
2022-09-04 10:49:52 +02:00
Benno Schulenberg
e7491920fd docs: explain how to include a double quote plus space in a nanorc regex
As double-quote-plus-space indicates the end of a regular expression
in a nanorc file, the inclusion of this combination *in* a regular
expression requires breaking the juxtaposition of the two, which
can be achieved by putting either of them between square brackets.

(It can also be achieved by preceding the space with a backslash,
which is shorter, but... the above method is more symmetrical.)

This addresses https://savannah.gnu.org/bugs/?62997.
2022-09-01 17:29:04 +02:00
Benno Schulenberg
9904aa5538 tweaks: make the crawl use the whole screen also in the tiny version
Nobody will configure nano with --enable-tiny --enable-extra, but *if*
someone does, the title bar should be absent during the crawl.

Also, swap two messages, so that their order in the POT file will be
more sensible -- a closing brace comes after the function name.
2022-09-01 08:38:18 +02:00
Benno Schulenberg
41b89aef8c tweaks: move the arrays of menu names and symbols to where they are used
Also, use a better return value for the "unrecognized name" case,
so that it cannot possibly be confused with the "all menus" case.
2022-08-31 17:28:09 +02:00
Benno Schulenberg
3925c137a4 tweaks: make two error messages more succinct and easier to translate
"Cannot map name %s to <thing>..." was unnecessarily verbose and vague.
I have kept these strings unchanged all these years because I didn't
want to invalidate the existing translations.  But now it's time to
harmonize things and simply say "Unknown <thing>: %s" for an invalid
function name, menu name, option name, and syntax name.

("No such <thing>: %s" is nice and snappy, but its translations often
are clumsy and longer and unclear.)
2022-08-31 16:57:58 +02:00
Benno Schulenberg
97fa42c82b memory: avoid a leak when a string bind specifies an unknown menu
(It is a harmless leak, but LeakSanitizer is loud when it complains.)

After having determined that there is a menu name, first check that
it is valid, before processing the string or the function name.

This fixes https://savannah.gnu.org/bugs/?62991.

Problem existed since version 2.9.4, since string binds were introduced.
2022-08-31 16:32:40 +02:00
Benno Schulenberg
ccabaac5a0 build: exclude two unneeded functions correctly from the tiny version
This also amends commit 4f9abb52 from yesterday -- I don't know how I
managed to overlook the warning.  :/
2022-08-29 12:31:39 +02:00
Benno Schulenberg
80f7852941 docs: describe --disable-formatter and --disable-linter configure options 2022-08-29 08:30:30 +02:00
Benno Schulenberg
6243831dfb build: add options --disable-formatter and --disable-linter to configure
This makes more sense than letting the formatter and the linter depend
on ENABLE_COLOR (which maybe should have been named ENABLE_SYNTAX).

This fulfills https://savannah.gnu.org/bugs/?50080.
2022-08-29 08:28:28 +02:00
Benno Schulenberg
4f9abb52a4 build: fix compilation when configured with --enable-tiny
Problem existed since commit d1e28417 from four days ago.
2022-08-28 14:56:44 +02:00
Benno Schulenberg
7bab8780ad tweaks: rewrap some lines, drop a redundant call, and reshuffle a line
Six years ago, commit a878f5f1 introduced a call of regenerate_screen()
directly in the input routine, which made the call of refresh_func() in
the prompt routine redundant -- except when in the file browser.
2022-08-28 09:03:09 +02:00
Benno Schulenberg
d0dc270eec tweaks: rename two record elements and three parameters, for clarity 2022-08-28 08:58:36 +02:00
Benno Schulenberg
cd9402075a tweaks: elide a variable, rename another, and reshuffle an assignment 2022-08-26 09:29:44 +02:00
Benno Schulenberg
b1f3bdfcbd extra: use the whole terminal for the crawl, and quicken it a bit
Since version 6.0, with option --zero, the edit window can cover
the whole terminal.  Make use of this also for the credits crawl.

Also, shorten and quicken the crawl a bit, and make it start always
on the bottom row, instead of (for mysterious reasons) one row higher
when the terminal has an odd number of rows.

Furthermore, don't put back the key the user typed to stop the crawl.
2022-08-26 09:17:17 +02:00
Benno Schulenberg
541a2dbc88 feedback: suppress undo/redo messages when option --zero is in effect
This fixes https://savannah.gnu.org/bugs/?62956.

Problem existed since version 6.0, since --zero was introduced.
2022-08-25 08:48:07 +02:00
Benno Schulenberg
d1e28417d5 tweaks: move to a given line number more efficiently
Instead of starting always from the top of the buffer, start at the
current line, as it is quite likely to be near the target line.

(Since the previous commit we're assuming that openfile->current is
always valid, so we might as well make use of this assumption.)

Also, rename a parameter to make its meaning more explicit.
2022-08-24 16:29:29 +02:00
Benno Schulenberg
9410a55679 undo: make sure the current line is defined before it is referenced
After undoing an <Enter> or redoing a line join, it is likely that the
"eaten" and freed line was the current line.  In fact, goto_line_posx()
should not refer to it any more, but... accommodate for this and just
set openfile->current to a valid value before calling goto_line_posx().

This fixes https://savannah.gnu.org/bugs/?62952.

Bug existed since version 6.3, commit eea3e1f0.
2022-08-24 15:45:24 +02:00
Benno Schulenberg
25ceefbd89 prompt: ingest queued characters before handling any subsequent function
This fixes https://savannah.gnu.org/bugs/?62946.

Bug existed since commit 40a4225e from five days ago.
2022-08-24 09:28:14 +02:00
Benno Schulenberg
a37c4bb59e tweaks: reshuffle a line, to group things better 2022-08-23 15:40:27 +02:00
Benno Schulenberg
ee1f8a0494 prompt: return FALSE for non-editing functions also in the tiny version
This fixes https://savannah.gnu.org/bugs/?62942.

Bug existed since commit 2f25b6a6 from four days ago.
2022-08-23 15:32:30 +02:00
Benno Schulenberg
2c5459a1b7 tweaks: fold two cases together, because they basically do the same 2022-08-21 16:57:03 +02:00
Benno Schulenberg
b561c386c3 tweaks: discard a bracketed paste in the browser more efficiently 2022-08-21 10:45:49 +02:00
Benno Schulenberg
a374dd0359 prompt: toggle the help lines only for the 'nohelp' toggle
This fixes https://savannah.gnu.org/bugs/?62914.

Problem existed since commit 958ec294 from three days ago.
2022-08-21 10:22:38 +02:00
Benno Schulenberg
aba4f4e0e2 tweaks: avoid sometimes calling a function three times in a row 2022-08-21 09:59:55 +02:00
Benno Schulenberg
210c94d82f prompt: allow rebinding also ^N, ^Q, and ^Y at the yes-no prompt
Checking for the literal ^N, ^Q, and ^Y before checking for do_toggle
and full_refresh made it impossible to rebind any of those keystrokes
to these two functions.  (Not that anyone would want this, but...)

Problem existed since version 4.3, commits 341601e1 and 82aea04c.
2022-08-21 09:42:21 +02:00
Benno Schulenberg
c410ba4d42 tweaks: reshuffle two lines, for conciseness and in preparation 2022-08-21 09:28:07 +02:00
Benno Schulenberg
f3738fe164 tweaks: don't use a pointer when the value itself is all that is needed 2022-08-21 09:12:35 +02:00
Benno Schulenberg
04a08fe6a5 tweaks: rename a variable, away from an abbreviation 2022-08-21 09:02:32 +02:00
Benno Schulenberg
69d33ec170 tweaks: rewrap line, improve wording, and correct typo in old news item 2022-08-19 16:58:09 +02:00
Benno Schulenberg
40a4225ed8 tweaks: reshuffle some code, to not determine a shortcut twice
This addresses https://savannah.gnu.org/bugs/?62913.

Problem has existed since version 2.1.0, commit eb64314f.
2022-08-19 16:38:55 +02:00
Benno Schulenberg
801622ce19 tweaks: normalize the indentation after the previous change 2022-08-19 12:48:15 +02:00
Benno Schulenberg
67750a30ba tweaks: reshuffle some code and drop some comments, for conciseness 2022-08-19 12:47:49 +02:00
Benno Schulenberg
2f25b6a650 tweaks: elide a parameter by moving the general case one level up 2022-08-19 11:56:01 +02:00
Benno Schulenberg
5a3bd329d6 prompt: prevent execution of inadmissible functions in view mode
This fixes https://savannah.gnu.org/bugs/?62912.

Bug existed since commit 958ec294 from earlier today,
but was enabled by commit 433dd921 from three days ago.
2022-08-18 16:01:31 +02:00
Benno Schulenberg
8b4bf2bb8d docs: mention that string binds may contain function names between braces 2022-08-18 09:11:49 +02:00
Benno Schulenberg
2a515058be docs: replace control codes in the examples with {command} cartouches
This avoids https://savannah.gnu.org/bugs/?61720.

Problem existed since version 5.8, commit 74c6bdac.
2022-08-18 09:11:49 +02:00
Benno Schulenberg
3785f762fc syntax: nanorc: colorize valid function names plus surrounding braces 2022-08-18 09:11:49 +02:00
Benno Schulenberg
5cee9f183b build: exclude some pieces that are not needed with --disable-nanorc 2022-08-18 09:11:49 +02:00
Benno Schulenberg
958ec294b2 input: interpret commands of the form {functionname} inside string binds
This allows specifying bindable functions in a string bind by name
instead of by the literal control code or escape sequence to which
they are bound, which makes for a much more readable string bind,
and also allows specifying functions that are not bound to any key.

The opening brace, {, is made into a special symbol inside a string
bind, and each literal occurrence there needs to be escaped as {{}.

This fulfills https://savannah.gnu.org/bugs/?61692.
Requested-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Original-idea-by: Brand Huntsman <alpha@qzx.com>
  https://lists.gnu.org/archive/html/nano-devel/2018-02/msg00006.html
2022-08-18 09:07:05 +02:00
Benno Schulenberg
3a781fd719 help: move the M-Del item up, so that M-PgUp and M-PgDn are paired
(It needs a huge terminal and a tiny font for these to come into view,
but... it's possible.)
2022-08-17 15:11:03 +02:00
Benno Schulenberg
f4a2e7efe2 tweaks: move the --magic option up, so that --zero comes last
This makes that the three options that change the default layout
of the interface (--stateflags, --minibar, --zero) come last.

Also, sort the option letters into a consistent order in the code.
2022-08-17 14:31:44 +02:00
Benno Schulenberg
027365503f tweaks: add parentheses for consistency, and reshuffle for conciseness
(That 'also_the_last' now gets reset to FALSE whenever the cursor moves
to a different line is fine -- it is redundant when the mark is off, but
it does no harm.)
2022-08-17 09:34:08 +02:00
Benno Schulenberg
e31d59ebc8 tweaks: move two checks plus corresponding calls to a better place
It was silly to check again specifically for <Del> and <Bsp> after
any possible keystroke had been handled.  It was an anomaly.

This makes the tail of do_deletion() similar to the tail of inject().

(That sometimes the current line is redrawn twice is acceptable -- how
often does one type <Backspace> while having Shift-selected something?
Normally one wouldn't, because it would cancel the selection, so it's
fine to accept some inefficiency for this case.)
2022-08-17 09:01:55 +02:00
Benno Schulenberg
11178e14ab tweaks: rename a macro for clarity, and normalize some indentation
(Continuation lines should be indented by at least two extra tabs.)
2022-08-17 08:41:14 +02:00
Benno Schulenberg
0bcbd0015f tweaks: check the multiline regexes only for Delete and Backspace
The checking for all functions that are marked as not-okay-for-view-mode
was excessive and unneeded.  It had been inherited from commit d47d8cd4
from thirteen years ago, and was never verified for correctness.

This addresses the main part of https://savannah.gnu.org/bugs/?62903.
2022-08-16 16:23:44 +02:00
Benno Schulenberg
271bd5d3ba tweaks: allow the linter to be used in view mode, as it makes no changes
The linter has been marked as NOVIEW since it was introduced in 2.3.3.
But that was a mistake, as the tool does not change the buffer contents.

This addresses a minor part of https://savannah.gnu.org/bugs/?62903.
2022-08-16 16:06:18 +02:00
Benno Schulenberg
74d252a68f tweaks: drop a parameter that is no longer used
The previous commit made the 'viewok' parameter redundant.
2022-08-16 15:12:52 +02:00
Benno Schulenberg
4b928b466a tweaks: determine in another way whether a shortcut is okay in view mode
This addresses the other part of https://savannah.gnu.org/bugs/?62899.
2022-08-16 15:03:02 +02:00
Benno Schulenberg
10b4d0c8ad tweaks: use an auxiliary variable to avoid dereferences of 'shortcut'
This is especially meant to avoid dereferences of 'shortcut' after its
linked function has been executed, because in an upcoming commit this
execution may have freed the shortcut's structure.

(For symmetry, make the same change also in do_statusbar_input(), even
though it is not needed there.)

This addresses one part of https://savannah.gnu.org/bugs/?62899.
2022-08-16 15:03:02 +02:00
Benno Schulenberg
433dd92196 tweaks: drop an unneeded check for permissibility of prompt shortcuts
The only menus that are accessible in view mode are WhereIs, Insert,
WhereIsFile, GoToDirectory, and Help.  In the WhereIs menu, the only
keystroke that is not allowed in view mode (^R) is caught explicitly.
In the other four menus, all available shortcuts are permissible in
view mode, so... there is no need to check them at execution time.

(The ^R keystroke in the WhereIs menu is still shown in view mode
so as not to upset the pairing of the subsequent shortcuts.)
2022-08-15 14:49:03 +02:00
Benno Schulenberg
78d284881c help: don't show the New-Buffer toggle when in view mode
Since commit 63f2be7a from four years ago, view mode always sets
multibuffer mode, allowing ^R (Insert) to be invoked.  But the
user is then not allowed to switch multibuffer mode off, so...
don't show the toggle.
2022-08-15 11:53:54 +02:00
Benno Schulenberg
a36b726bde completion: search through all open buffers for possible completions
This allows one to complete also words that are present in other files
(when these are open in other buffers).

This fulfills https://savannah.gnu.org/bugs/?61691.
Requested-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Original-patch-by: Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com>
2022-08-12 10:20:27 +02:00
Benno Schulenberg
83629b9991 startup: ensure that +/string centers the match also with --linenumbers
When confirm_margin() first sets the margin needed for the requested
line numbers, also then it needs to keep 'focusing' TRUE.  Only when
actually toggling --linenumbers ON (from a zero margin to something)
should focusing be suppressed, in order to obtain smooth scrolling
when the cursor is pushed off-screen.

This fixes https://savannah.gnu.org/bugs/?62885.

Bug existed since version 4.4, since the search-at-startup feature
was introduced.
2022-08-11 09:32:01 +02:00
Benno Schulenberg
405c66e864 tweaks: delete a flag that is no longer used
Suspension is always enabled since version 6.0.

(Also, swap two conditions, to match identical pairs elsewhere.)
2022-08-09 12:01:09 +02:00
Benno Schulenberg
e5df84a9ed help: prioritize the unshifted Meta keystrokes for buffer switching
In many keyboard layouts M-< and M-> are awkward to type (in a Spanish
layout, for example: Alt+Shift+AltGr+Z and Alt+Shift+AltGr+X when there
is no LSGT key), whereas M-, and M-. are simple two-key keystrokes in
most Latin-script layouts.  So, show M-,/M-. before showing M-</M->.

Also, make a condition more precise, to not show M-Left and M-Right in
the tiny version, when those shortcuts are not understood.
2022-08-05 16:29:21 +02:00
Benno Schulenberg
614a977259 po: update translations and regenerate POT file and PO files 2022-08-02 09:23:26 +02:00
Benno Schulenberg
f1651abdac bump version numbers and add a news item for the 6.4 release 2022-08-02 08:44:50 +02:00
Benno Schulenberg
05a06048fc tweaks: add a missing word to a news item 2022-08-01 09:21:55 +02:00
Benno Schulenberg
c599bc9bff tweaks: rename a variable, to not be the same as a function name 2022-08-01 09:17:35 +02:00
Benno Schulenberg
54ded4527a options: stop accepting -z, as --suspendable has been dropped too
This should have been part of commit 98f9518b from seven weeks ago.
2022-07-31 19:47:11 +02:00
Benno Schulenberg
4f433cd601 tweaks: add a translator hint 2022-07-27 11:24:08 +02:00
Benno Schulenberg
accecb9863 tweaks: reshuffle a few lines, to group things better 2022-07-26 12:28:49 +02:00
Benno Schulenberg
079588cac5 gnulib: update to its current upstream state 2022-07-26 12:28:49 +02:00
Benno Schulenberg
1d10ee71bf syntax: python: mention an alternative linter in a comment 2022-07-26 12:28:49 +02:00
Benno Schulenberg
0520cbdccb syntax: perl: add missing keywords, and reduce the length of some lines
Also, compact the keywords less, so that things are easier to read.
2022-07-25 15:53:03 +02:00
Benno Schulenberg
3d3270c1b2 tweaks: put each regex on separate line, to better show many keywords
(The long list of keywords was divided over five separate regexes to
avoid exceeding the possible limit of 256 bytes/characters per regex.)
2022-07-25 14:48:40 +02:00
Benno Schulenberg
b60a26d40b tweaks: reshuffle a description and rewrap another
The reshuffling places the detailed descriptions of some commands
in the same section.
2022-07-25 10:45:02 +02:00
Benno Schulenberg
36fcdce886 docs: concisely describe how the linter behaves 2022-07-25 10:27:15 +02:00
Benno Schulenberg
b760388bbf help: reshuffle two shortcuts so that more help-line items are paired
Since version 6.0, Suspend is no longer bound by default, which meant
that it dropped out of the help lines, leaving the items after it in an
unpaired arrangement.  Move the Suspend item and its intended partner
to near the end of the list, to reestablish pairing for several items.
2022-07-25 09:08:02 +02:00
Benno Schulenberg
bb18524cce formatter: instead of leaving curses, use full_refresh() to wipe messages
This makes invoking the formatter cleaner, by giving feedback and *not*
leaving curses mode.  Leaving curses mode had the small advantage that
any messages from the formatter would be on the terminal after closing
nano.  But it had the disadvantage that invoking the formatter flashed
the screen.

This basically reverts commit 2b9f0619 from three years ago and then
solves the issue of intruding formatter messages in a different way.

This fulfills https://savannah.gnu.org/bugs/?62789.
Requested-by: Gert Cuykens <gert.cuykens@gmail.com>
2022-07-25 08:25:15 +02:00
Benno Schulenberg
05eaa0f0d7 tweaks: improve a comment, and reshuffle two functions plus some lines 2022-07-24 16:51:39 +02:00
Benno Schulenberg
d4a1dbd4a9 tweaks: rename two variables, to not contain the name of another
Also, elide an unneeded condition: when not softwrapping, left_x will
be zero, which is always smaller than or equal to the indentation.

Furthermore, reshuffle a few lines, improve three comments, and adjust
one to mention the parameter that was added in the previous commit.
2022-07-22 15:27:41 +02:00
Benno Schulenberg
0e9bef3429 display: remember text and column positions when softwrapping a line
This adjusts the main softwrapping routine so that it remembers the
reached point in a line's text and the corresponding column.  This
avoids having to scan the line from the beginning for each iterative
call, and thus saves a substantial amount of time when softwrapping
very long lines.

This mitigates https://savannah.gnu.org/bugs/?62442.
Reported-by: Devin Hussey <husseydevin@gmail.com>

Original-patch-by: Devin Hussey <husseydevin@gmail.com>
2022-07-20 14:06:24 +02:00
Benno Schulenberg
34238dc119 files: designate the root directory with a simple "/", not with "//"
The double slash would derail the file browser, causing a crash.

This fixes https://savannah.gnu.org/bugs/?62760.
Reported-by: Frank Wolff

Bug existed since version 6.3, commit fdd946c0.
2022-07-13 19:28:53 +02:00
Benno Schulenberg
18a40caa48 docs: remove the two notices about the changed defaults
It has been more than three years since version 4.0 was released,
the moment that the defaults for line wrapping, smooth scrolling,
and the size of the editing window were changed.

Keep the note in the texi manual, though, as it is less in the way,
and the manual generally contains more info than the man pages.
2022-06-19 10:30:44 +02:00
Benno Schulenberg
1980f1b2ba docs: stop mentioning the obsoleted keywords that were removed
But keep the note about --suspendable, as it has been obsoleted rather
recentl.  Move it to the NOTES section.
2022-06-19 10:29:46 +02:00
LIU Hao
ec0c13afda build: ignore errors from git describe
Due to CVE-2022-24765, Git refuses to operate on local repositories if
it runs as a different user from its owner.  Since version 2.35.2:

  $ sudo git describe --tags
  fatal: unsafe repository ('/home/lh_mouse/GitHub/nano-win' is owned by someone else)
  To add an exception for this directory, call:

    git config --global --add safe.directory /home/lh_mouse/GitHub/nano-win

Conventionally, a user, who wishes to build and install nano from Git,
does this:

  $ ./configure
  $ make
  $ sudo make install

The first `make` command builds the program as the current user.
The `make install` then installs the built files.

However, we have a recipe for 'revision.h' that is always executed,
even in the case of `make install`.  As here it is run as root, Git
actually fails and produces an empty string.  This causes `make install`
to rebuild nano.o and winio.o and results in an empty version string in
the upper left corner.

The solution is simple: First we attempt a dryrun of `git describe`.
If it fails, 'revision.h', which should have been updated by the first
`make` command, will be left intact.

Reference: https://nvd.nist.gov/vuln/detail/CVE-2022-24765

Signed-off-by: LIU Hao <lh_mouse@126.com>
2022-06-14 11:54:47 +02:00
Benno Schulenberg
ed41b3cefa version: condense the copyright message, to not dominate the output
It is enough to mention the year of the current release in the copyright
statement -- no need to specify the historical range of years.
2022-06-12 17:31:08 +02:00
Benno Schulenberg
80a924edfa docs: rename README.GIT to README.hacking, so it's clearer what is meant 2022-06-12 17:29:32 +02:00
Benno Schulenberg
98f9518bf2 rcfile: remove five obsolete or deprecated keywords 2022-06-12 17:03:15 +02:00
Benno Schulenberg
1de47610f4 syntax: default: do not colorize a square or angle bracket after a URL
Sometimes a URL is wrapped in [] or <> brackets -- the closing ] or >
is not part of the URL and should not be colored.
2022-06-07 17:24:23 +02:00
Benno Schulenberg
25ba7712f7 po: update translations and regenerate POT file and PO files 2022-04-28 10:36:42 +02:00
Benno Schulenberg
a6b534d760 bump version numbers and add a news item for the 6.3 release 2022-04-28 10:08:34 +02:00
Benno Schulenberg
494b191d55 gnulib: pull in the workaround for a build problem on NetBSD 2022-04-27 11:23:09 +02:00
Benno Schulenberg
450bfa7a75 build: fix compilation for --enable-{tiny,nanorc,color} 2022-04-22 11:47:21 +02:00
Benno Schulenberg
a52ac1375a formatting: change cursor position only after saving it in the undo item
When one wants an Undo to restore the cursor to where it was before an
operation, one shouldn't fiddle with the position before it is stored
in the relevant undo item.

This fixes https://savannah.gnu.org/bugs/?62341.

Bug existed since version 4.9, commit 38af812a.

(This effectively reverts commit 38af812a from two years ago.)
2022-04-21 12:31:19 +02:00
Benno Schulenberg
4990713e9e tweaks: change the indentation of a list, to match other indentations 2022-04-19 11:15:18 +02:00
Benno Schulenberg
c022c4cc6d docs: add an example binding for copying text to the system clipboard 2022-04-12 11:18:25 +02:00
Benno Schulenberg
6257dec0a7 filtering: close all output descriptors, so that 'xsel' will terminate
For some reason, when copying something to the system clipboard
with 'xsel', it wants to see all output descriptors closed before
it will exit without requiring ^C.

This fixes https://savannah.gnu.org/bugs/?62276.
Reported-by: Shi Yanling <sylphenix@126.com>

Bug existed since version 2.9.8, since piping text through an
external command was introduced.
2022-04-12 11:09:09 +02:00
Benno Schulenberg
ea9d49b9d8 tweaks: remove some stray spaces before a comma 2022-04-11 10:31:39 +02:00
Benno Schulenberg
42c7bfcf8a verbatim: with --zero, keep cursor in viewport when it was on bottom row
This fixes https://savannah.gnu.org/bugs/?62285.

Bug existed since version 6.0, since --zero was introduced.
2022-04-11 10:28:09 +02:00
Benno Schulenberg
e67d1bfeb8 build: fix compilation when configured with --disable-color 2022-04-08 11:35:44 +02:00
Benno Schulenberg
e2f444cfdf gnulib: update to its current upstream state 2022-04-08 10:52:55 +02:00
Benno Schulenberg
03b85df4eb tweaks: remove redundant braces, and add two translator hints 2022-04-08 09:38:42 +02:00
Benno Schulenberg
7db5c2f225 files: when the working directory exists, still check its accessibility
This fixes https://savannah.gnu.org/bugs/?62258.

Bug existed since commit 940b5eaa from yesterday.
2022-04-06 16:41:45 +02:00
Benno Schulenberg
603ce231d0 tweaks: simplify a fragment of code, and fold two lines together 2022-04-05 12:40:45 +02:00
Benno Schulenberg
940b5eaad1 files: show a warning when the working directory is gone (when used)
Instead of silently opening an empty buffer when the user tries to
open a file in the current but disappeared directory, give a clear
warning about the absence of this directory.

This improves the fix for https://savannah.gnu.org/bugs/?62244.
2022-04-05 12:34:04 +02:00
Benno Schulenberg
fdd946c02c files: do not change to a higher directory when the working one is gone
When the working directory has been deleted from under nano's feet,
get_full_path() would move up in the directory tree until getcwd()
would succeed.  This meant that a filename that was specified on the
command line without any path (or with a relative path) would refer
to a different file than what the user intended.  Not good.

So, stop changing directories in get_full_path().  Use the realpath()
function with NULL as second parameter instead -- it has been part of
the POSIX standard since 2008, time enough for operating systems to
have caught up.

In the bargain, this saves seventy lines of complicated logic.

This fixes https://savannah.gnu.org/bugs/?62244.

Bug existed since version 2.0.0, commit 85e35e67.
2022-04-04 12:52:35 +02:00
Benno Schulenberg
81e5b57d74 syntax: xml: colorize user-defined entities differently
Also improve two comments.
2022-04-04 12:08:23 +02:00
Benno Schulenberg
b568705eec syntax: xml: colorize /> properly, and colorize prolog tags differently
Use lightgrey for the prolog tags, as they normally are unimportant
boiler-plate stuff.  Comments are likely to be more relevant.

Any /> is part of the tag itself, not of the attributes.
2022-04-04 10:01:49 +02:00
Benno Schulenberg
fe42eb7a1a painting: stop coloring an extremely long line after 2000 bytes
Especially when softwrapping and when multiline regexes are involved,
colorizing takes roughly exponential time relative to the line length.
To avoid bogging down, stop colorizing a line beyond a certain point.

This mitigates https://savannah.gnu.org/bugs/?61799.
Reported-by: Devin Hussey <husseydevin@gmail.com>
2022-04-03 12:28:22 +02:00
Benno Schulenberg
df7b0a6d97 execute: clear an anchor only when the whole buffer gets filtered
Although an anchor at the top line is rather pointless, it shouldn't
get cleared when the user pipes just a part of the buffer through an
external command.
2022-03-28 11:38:22 +02:00
Benno Schulenberg
fcf598e797 execute: stay on the same line number when filtering the whole buffer
When the filter command makes just small, per-line changes, keeping the
cursor at the same line number allows the user to observe the effect of
the changes -- which is not possible when the cursor gets moved to the
end of the buffer.

This partially fulfills https://savannah.gnu.org/bugs/?57248.
2022-03-28 11:15:04 +02:00
Benno Schulenberg
d9cb12f6e3 tweaks: move the saving and restoring of flags to where it is needed 2022-03-27 18:44:48 +02:00
Benno Schulenberg
0f23729253 tweaks: prevent the adding of an unwanted newline in a different way
The prevention is needed only for temporary files, not for normal files.
2022-03-27 18:20:17 +02:00
Benno Schulenberg
3def429290 tweaks: don't leave an orphaned temporary file behind when writing fails 2022-03-27 12:37:01 +02:00
Benno Schulenberg
803ea0d7a0 justify: stay at the same line number when doing a full justification
The same line number may not be the same position in the text, but
it will be approximately -- and it is certainly better than leaving
the cursor at the end of the buffer.

This fulfills https://savannah.gnu.org/bugs/?61175.
2022-03-24 17:05:55 +01:00
Benno Schulenberg
9b014876cd tweaks: trim a few comments, rename a function, and reshuffle some code 2022-03-20 13:20:31 +01:00
Benno Schulenberg
9ccf85eaa8 tweaks: avoid a function call when two plain assignments will do 2022-03-18 11:40:03 +01:00
Benno Schulenberg
93fa53c3e8 tweaks: elide an unneeded call of strlen() 2022-03-18 11:36:10 +01:00
Benno Schulenberg
eea3e1f0b2 tweaks: make the triggering of the recalculation of multidata less eager
Also, trigger recalculation when an undo or redo causes a large enough
forward jump.
2022-03-18 11:29:18 +01:00
Benno Schulenberg
e6e22ea976 tweaks: normalize the indentation after the previous change 2022-03-17 14:09:09 +01:00
Benno Schulenberg
80c2000f87 tweaks: simplify a bit of code, eliding two labels and three gotos 2022-03-17 14:09:09 +01:00
Benno Schulenberg
15a0a129c8 painting: recalculate the multidata when making large strides or changes
When making a forward movement larger than a screenful, we cannot rely
on the multidata of the line before the new screen start to have been
set correctly by a previous screen drawing, so we need to recompute all
of the multidata, for the whole buffer, so that afterward we can freely
move around and draw the screen without having to do any backtracking.

Also when a piece of text larger than a screenful is pasted or inserted,
all the multidata needs to be recomputed.

This fixes https://savannah.gnu.org/bugs/?60041,
and fixes https://savannah.gnu.org/bugs/?62056.

First bug existed in this form since version 2.4.2, commit d49c267f
(but editing Python was incomparably slower in those days).

Second bug existed since version 5.6, commit 43d94692.
2022-03-17 14:07:42 +01:00
Benno Schulenberg
51bd04b541 painting: colorize text also after an unterminated start match
This does not waste time looking for an end match, which is especially
wasteful when there is none.  Also, it makes the coloring behavior more
consistent: any start match will cause coloring of the subsequent text,
no matter whether the user is in the middle of the file or near the end.
2022-03-14 09:12:55 +01:00
Benno Schulenberg
18ba7f60c1 painting: tighten the check for a lacking end match on a colored line
As it's possible for the start regex to match what is actually the end
match of a multiline thing (see the Python triple quotes, for example),
make sure that such a detected start match is *not* an end match, just
to avoid a needless full-screen refresh.
2022-03-08 09:47:36 +01:00
Benno Schulenberg
5c3e00d70a build: remove an obsolete check -- the dependent code was deleted
The code fragment that was conditionalized on REDEFINING_MACROS_OK
was deleted five weeks ago in commit 3f494e35.
2022-03-07 18:09:51 +01:00
Benno Schulenberg
6c4c77971e build: add the --disable-maintainer-mode option to ./configure
By passing --disable-maintainer-mode to ./configure the user can disable
autoconf build rules that would cause configure to be rebuilt and rerun.

Kind-of-requested-by: Mike Frysinger <vapier@gentoo.org>
2022-03-07 17:26:30 +01:00
Benno Schulenberg
67adef8f6c display: suppress spotlight yellow and error red when NO_COLOR is set
This makes nano conform to the https://no-color.org/ idea: suppressing
any color in the output (in the default setup) when NO_COLOR is set in
the environment.

Specifying a color for any interface element will, however, re-enable
also yellow for the spotlight and red for error messages.
2022-03-06 17:03:42 +01:00
Benno Schulenberg
ed60e16974 tweaks: exclude the extra truncation warning from the tiny version 2022-03-04 12:12:48 +01:00
Benno Schulenberg
47c11ae83d feedback: show extra warning when writing failed due to "No space left"
This mitigates https://savannah.gnu.org/bugs/?36864.
Reported-by: Clarence Risher <sparr0@gmail.com>

Problem has existed since the beginning, as nano empties the existing
file before writing the current buffer contents into it.
2022-03-03 11:12:41 +01:00
Mike Frysinger
8173b1bfbe general: fix building for Windows
Fix building with x86_64-w64-mingw32 to cross-compile native Windows
programs.  Need to:

  * add checks for missing functions
  * don't use signals that are unavailable on the platform
  * avoid useless non-Linux sys/ioctl.h include
  * use putenv instead of setenv as the latter is unavailable
2022-03-01 11:05:07 +01:00
Benno Schulenberg
93400ec8a1 execute: don't crash when an empty buffer is piped through a command
That is, take into account that the cutbuffer could be NULL
(when updating the undo item).

This fixes https://savannah.gnu.org/bugs/?62107.

Bug existed since version 4.9, commit b15c5a7e.
2022-02-24 16:50:18 +01:00
Benno Schulenberg
0d85a798e5 painting: look for another start match only after the actual end match
The 'endmatch.rm_eo' value is relative to the end of the start match,
so to find the end of the end match, one has to add 'startmatch.rm_eo'
plus 'endmatch.rm_eo' to the starting point of the line.

This addresses https://savannah.gnu.org/bugs/?62091.

Problem existed since version 5.6, commit 0596b875.
2022-02-21 10:46:28 +01:00
Benno Schulenberg
d4d534925f po: update translations and regenerate POT file and PO files 2022-02-18 10:58:47 +01:00
Benno Schulenberg
a1ba7ee786 bump version numbers and add a news item for the 6.2 release 2022-02-18 10:44:22 +01:00
Benno Schulenberg
756cd4a4b8 tweaks: store a result, to avoid calling a function twice 2022-02-18 10:27:47 +01:00
Benno Schulenberg
1b186fcff3 tweaks: rename two more variables, and drop unneeded initializations
Also, make sure that there is a space in the complaint so that the
later strstr() call cannot fail.  And reshuffle a line.
2022-02-17 14:20:45 +01:00
Benno Schulenberg
165da9b447 tweaks: rename a variable, reshuffle five lines, and snip two comments 2022-02-17 14:00:55 +01:00
Benno Schulenberg
aea10ed383 tweaks: rename two variables (to get rid of a prefix), and elide a third 2022-02-17 13:57:22 +01:00
Benno Schulenberg
8fccb31436 linter: adjust the parsing to accommodate for a modern 'pyflakes'
In version 2.2.0, pyflakes changed its output format,
from 'filename:line: text' to 'filename:line:column text'.

This fixes https://savannah.gnu.org/bugs/?62057.

Problem existed since version 2.9.0, commit 5dcf375f.

(That commit tried to compensate for an introductory message from gcc
that no longer seems to exist.)
2022-02-16 15:39:01 +01:00
Benno Schulenberg
89bb88e4f5 syntaxes: fold a couple of regexes together, and improve a few comments 2022-02-16 13:07:11 +01:00
Benno Schulenberg
a58efa70bc tweaks: consistently backslash-escape the dash in M-letter keystrokes 2022-02-16 12:19:31 +01:00
Benno Schulenberg
fe1fecc5da tweaks: rename a variable, to be more correct, and adjust two comments
The new name 'gauge' more clearly indicates that it is a distance
between two "columns", two "pillars", two "piles".  Using 'longest'
was poor, because in fact it was set to 'widest + 10'.

(Also, change the type of 'piles' to an integer -- it will always
be smaller than COLS, and COLS is an integer.)
2022-02-13 13:07:52 +01:00
Benno Schulenberg
87612582ff tweaks: use an intermediate variable, to avoid using one for two purposes 2022-02-13 12:43:55 +01:00
Benno Schulenberg
c3a53cffbc tweaks: rename a variable, to be more fitting
It is about width (cells/columns), not about length (bytes).
2022-02-13 12:19:16 +01:00
Benno Schulenberg
aeea83703b tweaks: rename a misnamed variable 2022-02-13 12:04:57 +01:00
Benno Schulenberg
27c8f13fc9 tweaks: change the type of a variable, to avoid a compiler warning
A newer compiler (gcc-10.3) said: browser.c:174:34: warning:
  field width specifier '*' expects argument of type 'int'

It's fine for 'longest' to be an integer, as a filename in Unix is
at most 255 bytes long, which can occupy at most 510 columns (when
the name consists entirely of control codes), and that fits easily
within an 'int', which has at least fifteen bits, unsigned.

Well... in theory 'tabsize' could be set to an insanely high number,
and if a filename contains several tabs, this could cause 'longest'
to overflow.  (Why doesn't the compiler warn about that?)  If that
were to occur, and the filename with the tabs were the last in the
list, then 'longest' would get set to the minimum width: 15.  That
would not be correct, but... nothing bad would happen.

This addresses https://savannah.gnu.org/bugs/?62014.
Reported-by: Mike Frysinger <vapier@gentoo.org>
2022-02-13 11:54:14 +01:00
Benno Schulenberg
c6ddae70f7 display: suppress the bottom-bar wiping only when the user is editing
This wipe suppression is meant to prevent the last row of the edit window
getting cleared when edit window and bottom window overlap, and this is
relevant only when the user is actually editing -- the file browser and
help viewer take care not to use this bottom row for content.

This fixes https://savannah.gnu.org/bugs/?62031.

Bug existed since version 6.0, commit be61aad9.
2022-02-11 16:46:05 +01:00
Benno Schulenberg
e4ecd03e3f po: update translations and regenerate POT file and PO files 2022-02-09 11:53:47 +01:00
Benno Schulenberg
a6dc5c963c bump version numbers and add a news item for the 6.1 release 2022-02-09 11:31:03 +01:00
Benno Schulenberg
989e6a9a7e tweaks: rename two variables, and elide a near-enough duplicate
(The 'in_edit' variable was a duplicate because also when the pointer is
on the line numbers, we want to scroll when the mouse wheel is rolled.)
2022-02-04 15:51:40 +01:00
Benno Schulenberg
c28048d20f tweaks: rename another variable, to better fit in with its sisters 2022-02-04 12:17:37 +01:00
Benno Schulenberg
a24e72f972 tweaks: rename a variable, to make it clearer it refers to a window 2022-02-04 12:11:05 +01:00
Benno Schulenberg
a29aa31e93 tweaks: when discarding keycodes, don't bother parsing them 2022-02-04 11:18:52 +01:00
Benno Schulenberg
8546139997 build: fix compilation when configured with --enable-tiny
Problem existed since commit 3b657a26 from five days ago.

In addition, exclude pasting-at-the-prompt from the tiny version, as
it's hardly useful when one cannot copy a selected piece of text.
2022-02-03 13:06:21 +01:00
Benno Schulenberg
a61586947e gnulib: update to its current upstream state 2022-02-03 11:20:08 +01:00
Benno Schulenberg
5e4645b082 copyright: update the last year for significantly changed files 2022-02-02 17:40:25 +01:00
Benno Schulenberg
f9f0a8fd67 copyright: update the years for the FSF 2022-02-02 17:10:09 +01:00
Benno Schulenberg
637a2eeb66 tweaks: rename a variable and a parameter, to be more descriptive
Also, improve two comments, to describe what the functions actually do.
2022-02-01 12:22:29 +01:00
Benno Schulenberg
13caef2de0 tweaks: remove two redundant checks
The checks have been there for fifteen months, and no one ever reported
seeing those messages.
2022-02-01 12:21:31 +01:00
Benno Schulenberg
61c6d43231 tweaks: adjust a translator hint, to fit the order in the POT file
Also, reword another hint.
2022-02-01 11:38:55 +01:00
Benno Schulenberg
a04f6e0165 help: update the description of M-D, to match the actual order of counts 2022-02-01 11:16:07 +01:00
Benno Schulenberg
3f494e359d tweaks: stop asking the terminal for its new size -- let ncurses do it
When re-entering curses mode, ncurses will pick up the new size of
the terminal and set the LINES and COLS variables appropriately.

(We don't ask the terminal for its size when nano starts up, so why
would we need to do it when the terminal is resized?)
2022-01-31 16:53:35 +01:00
Benno Schulenberg
8a06f70379 tweaks: rename a function and reshuffle its call 2022-01-31 12:31:03 +01:00
Benno Schulenberg
2290152743 menus: don't show M-6 in the help lines of any prompt
None of the editing keystrokes are shown in the menus -- they are
all "blind" keys.  This corrects a mistake in the previous commit.
2022-01-31 10:48:14 +01:00
Benno Schulenberg
3b657a26a6 prompt: allow the user to copy the answer to the cutbuffer (with M-6)
Since version 2.8.7 the user can paste text at the prompt (with ^U),
but the ability to copy what is present at the prompt was overlooked.

For feedback, the cursor is moved to the start of the answer -- like
it moves to the start of the next line when in the edit buffer.

This addresses https://savannah.gnu.org/bugs/?61702.
Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2022-01-30 17:39:55 +01:00
Benno Schulenberg
ff5084479b prompt: let ^K erase text after cursor (if any), otherwise whole answer
In most cases, the cursor will be at the end of what the user typed
at the prompt (or retrieved from history), and ^K will work as it
always did, erasing the whole answer.  But if the user has moved the
cursor to somewhere in the middle of the answer, a ^K will now erase
just the part after the cursor.  A second ^K will erase the rest.

Inspired-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2022-01-29 17:23:42 +01:00
Benno Schulenberg
97f4a3f4eb tweaks: rename a variable, away from an abbreviation 2022-01-29 17:14:22 +01:00
Benno Schulenberg
1ca1732d32 tweaks: remove a redundant check -- add a different one for symmetry
Function get_input() with a non-null parameter will never return ERR.
2022-01-29 16:32:04 +01:00
Benno Schulenberg
accd2308f1 tweaks: reword two comments, and rename a variable (away from an abbrev) 2022-01-29 16:01:35 +01:00
Benno Schulenberg
10eec2fe17 input: suppress any spotlighting when there are more keycodes waiting
Because doing the spotlighting after those extra keycodes have been
handled will most likely spotlight the wrong piece of text.  Also,
if those keycodes hadn't arrived early, the first of them would have
cancelled the spotlighting.

This fixes https://savannah.gnu.org/bugs/?61962.

Bug existed since version 5.8, commit 3f340836.
2022-01-29 11:16:41 +01:00
Benno Schulenberg
d69cd759cb input: instead of moving waiting keycodes, just increment a pointer
When a large piece of text was pasted into nano, then the old way of
repeatedly moving the buffered text one more position toward the head
of the keystroke buffer would waste a lot of time.  With this change,
pasting the current NEWS file into a buffer goes down (on my machine)
from around 30 seconds to just 2.

This addresses https://savannah.gnu.org/bugs/?61822.
Reported-by: Radu Caragea <rcaragea@protonmail.com>

Problem existed in this form since version 1.3.6, commit 7483571f.
2022-01-27 10:41:24 +01:00
Benno Schulenberg
f261a8aca5 tweaks: rename a function, to not contain the name of a variable 2022-01-27 09:21:21 +01:00
Benno Schulenberg
bdf64d660b tweaks: rename a variable, for clarity and contrast 2022-01-27 09:21:21 +01:00
Benno Schulenberg
2fd30ee095 tweaks: rename a function and its two parameters, for clarity 2022-01-25 12:23:14 +01:00
Benno Schulenberg
9bc6f1797e tweaks: use some symbolic names instead of unclear numeric values 2022-01-25 11:57:34 +01:00
Benno Schulenberg
32e63fe1b8 tweaks: add some small, clarifying comments
Suggested-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2022-01-22 13:12:55 +01:00
Benno Schulenberg
1c074cc8cc files: let ^C cancel the exiting when the file on disk was changed
When the user exits with ^X and gets warned that the file on disk
has changed, then typing ^C at the question whether to continue
saving should not discard the buffer and exit, but should return
the user to the filename prompt.

This fixes https://savannah.gnu.org/bugs/?61883.
Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>

Bug existed since version 2.9.0, commit 217cfbf3.
2022-01-22 12:30:15 +01:00
Benno Schulenberg
ebf6228f21 tweaks: add some feedback to the autogen.sh script, to ease the wait 2021-12-28 15:31:23 +01:00
Benno Schulenberg
4a1db96db8 build: prevent autopoint from overwriting a newer M4 file from gnulib
For some reason, 'autopoint' (invoked by 'autoreconf') insists on
overwriting 'extern-inline.m4', even though the version from gnulib
is newer and contains a fix for a build issue on macOS with GCC 11.

So, do as the documentation says, and invoke 'autopoint' before
'gnulib-tool' (and call 'aclocal' to 'automake' afterwards).

  https://www.gnu.org/software/gnulib/manual/html_node/gettextize-and-autopoint.html

This fixes https://savannah.gnu.org/bugs/?61719.
Reported-by: Sam James <sam@cmpct.info>
2021-12-28 15:08:45 +01:00
Benno Schulenberg
16ee4636bc tweaks: reshuffle some sample bindings, to group them differently 2021-12-26 17:44:42 +01:00
Benno Schulenberg
6831b37b43 tweaks: drop foreign M-U and M-R from among the sample CUA bindings
M-U and M-R are not usual bindings for Undo and Redo.
2021-12-26 17:35:30 +01:00
Benno Schulenberg
4d16f26ba4 help: make the description of <Tab> more accurate
And don't mention <Tab> for the 'indent' function, as the keystroke
is equivalent to M-} only when lines are marked.

Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2021-12-26 11:57:57 +01:00
Benno Schulenberg
4a7bc73e03 docs: mention 'set guidestripe' and 'set unix' in the sample nanorc
Somehow these entries were missed when those options were added.

Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2021-12-24 17:38:10 +01:00
Benno Schulenberg
caf583ec4b docs: mention bindable function 'zero', for toggling the interface bars
This should have been part of commit a623f583 from six weeks ago.

Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2021-12-23 16:14:21 +01:00
Benno Schulenberg
e20880da21 docs: remove obsolete Ctrl+Z from the cheatsheet; mention Alt+X instead
This should have been part of commit d0c2c1e6 from seven weeks ago.

Reported-by: Tasos Papastylianou <tpapastylianou@hotmail.com>
2021-12-23 15:48:15 +01:00
124 changed files with 58753 additions and 44521 deletions

1
.gitignore vendored
View File

@@ -45,6 +45,7 @@ core
/m4/gettext.m4
/m4/glibc2.m4
/m4/glibc21.m4
/m4/host-cpu-c-abi.m4
/m4/iconv.m4
/m4/intdiv0.m4
/m4/intl.m4

35
AUTHORS
View File

@@ -8,19 +8,20 @@ Chris Allegretta <chrisa@asty.org>
Benno Schulenberg <bensberg@telfort.nl>
* An array of small bug fixes, the cut-word and block-jump
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>
* Former stable series maintainer. Multiple buffer support,
operating dir (-o) option, bug fixes for display routines,
wrapping code, spelling fixes, constantshow mode, parts of
UTF-8 support, softwrap overhaul, undoable (un)indentations,
undoable justifications, justifiable regions, and numerous
other fixes.
* Multiple-buffer support, operating-dir option (-o), bug fixes
for display routines, wrapping code, spelling fixes, parts of
UTF-8 support, softwrap overhaul, constantshow mode, undoable
indentations, undoable justifications, justifiable regions,
and numerous other fixes. Former stable-series maintainer.
Jordi Mallach <jordi@gnu.org>
* Debian package maintainer, fellow bug squasher.
* Internationalization support head, ca.po maintainer.
* Debian package maintainer, fellow bug squasher, translator
for Catalan. Former head of internationalization support.
Adam Rogoyski <rogoyski@cs.utexas.edu>
* New write_file() function, read_file() optimization, mouse
@@ -33,9 +34,9 @@ Robert Siemborski <rjs3@andrew.cmu.edu>
new edit display routines.
Rocco Corsi <rocco.corsi@sympatico.ca>
* Internal spelling code, many optimizations and bug fixes for
findnextstr() and search-related functions, various display
and file handling fixes.
* Internal spelling code, many optimizations and bug fixes
for findnextstr() and search-related functions, various
display and file-handling fixes.
David Benbennick <dbenbenn@math.cornell.edu>
* Wrap and justify bugfixes/enhancements, new color syntax
@@ -43,11 +44,11 @@ David Benbennick <dbenbenn@math.cornell.edu>
miscellaneous fixes.
Mike Frysinger <vapier@gentoo.org>
* Gentoo package maintainer. Whitespace display mode,
--enable-utf8/--disable-utf8 configure options for ncurses,
many new color regexes and improvements to existing color
regexes in syntax/*.nanorc, the move from svn to git, the
conversion to gnulib, and miscellaneous bug fixes.
* Whitespace display mode, --enable-utf8/--disable-utf8 configure
options for ncurses, many new color regexes and improvements to
existing ones in syntax/*.nanorc, the move from svn to git, the
conversion to gnulib, and miscellaneous bug fixes. Former
Gentoo package maintainer.
Mark Majeres <mark@engine12.com>
* A functional undo/redo system, and coloring nano's interface.

5833
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -8246,7 +8246,7 @@ nano-0.7.7 - 2000.01.19
- Added check for keystroke key sequence 407 or NANO_CONTROL_Z
in main while loop because suspend mode was broken. This should
fix it, at least for now.
- Added long option support (By popular harassment ;-) - Added
- Added long option support (by popular harassment ;-) : added
#include for getopt.h, changed getopt() to getopt_long().
Options added so far: --version (-V), --nowrap (-w), --suspend
(-z), --help (-h), --nohelp (-x).
@@ -8258,15 +8258,15 @@ nano 0.7.6 - 2000.01.15
main(): Bound CONTROL_H to backspace (oops).
Added more Alt-[-key combinations, for page up & down.
read_bytes(): New function. (Adam Rogoyski)
read_file(): Optimizations - malloc()s *buf a little at a time rather
than one huge buffer, and replaced the strcat at the end
with an index variable. Added call to read_bytes().
read_file(): Optimizations -- malloc()s *buf a little at a time
rather than one huge buffer, and replaced the strcat() at
the end with an index variable. Added call to read_bytes().
do_next_word(): New function, binding is Ctrl-Space (0). (Chris)
- winio.c:
bottombars(): Fixed non-expanding shortcut keys at bottom of screen.
(formula is extra space needed = COLS / 6 - 13).
actual_x() & strlenpt():
Added bug#9 fix - when tabs % 8 == 0, we should only
Added fix for bug #9 -- when tabs % 8 == 0, we should only
increment tabs by 1.
titlebar(): Fixed overrun in titlebar on very long filenames.

View File

@@ -1,6 +1,29 @@
Improvements in GNU nano
========================
Since 9.0:
- With M-< and M-> the viewport can be scrolled sideways.
- When the cursor nears the edge, all lines are scrolled sideways.
- M-Left, M-Right, M-Up, and M-Down have become rebindable.
- Immediately stopping a recording retains the existing macro.
- Clicking in the scrollbar crudely navigates in the buffer.
Since 8.0:
- To accommodate newcomers, ^F now starts a forward search.
- Option --modernbindings makes ^Q quit, ^X cut, ^C copy, ^V paste,
^Z undo, ^Y redo, ^O open a file, and ^G find again, among others.
- M-Home/M-End put the cursor on the first/last row in the viewport.
- With `nano filename:number` the given file will be opened with the
cursor on the given line number (when 'set colonparsing' is used).
- Option --listsyntaxes lists the names of available syntaxes.
- Anchors are saved and restored (when --positionlog is active).
- Key combos ^O^Q and ^X^Q cause an exit status of 2.
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:
- 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

228
NEWS
View File

@@ -1,3 +1,158 @@
2026.07.31 - GNU nano 9.2 "Alquézar"
• Nano refuses to start when standard output is not a terminal.
• Options --newbuffer and 'set newbuffer' were added as better
synonyms of --multibuffer and 'set multibuffer'.
• Legacy keystroke pairs ^W^T and ^/^T are recognized again.
2026.06.23 - GNU nano 9.1 "met een hongerig paard aan ons been"
• When searching, the viewport is placed snug left where possible.
• The ability to read and write files in old Mac format was removed
(that is: files that use a lone carriage return as line ending).
• The ^T toggle between WhereIs and GotoLine has been dropped.
• When --backup is active, in some situations no backup was made,
or it had a wrong timestamp. Both issues are fixed now.
• When nano crashes or is killed, any .save file is not chmodded
to the permissions of the base file, nor chowned to its owner.
• M-Ins and M-Del have become rebindable.
2026.04.08 - GNU nano 9.0 "Le bonheur est dans le pré"
• When the cursor almost goes offscreen to the right, all lines are
now scrolled sideways together, by just the amount needed to keep
the cursor in view. Use --solosidescroll or 'set solosidescroll'
to get back the old, jerky, single-line horizontal scrolling.
• The viewport can be scrolled sideways (in steps of one tabsize)
with M-< and M->. See `man nanorc` if M-< and M-> should switch
between buffers (as they did earlier).
• M-Left, M-Right, M-Up, and M-Down have become rebindable.
• Stopping the recording of a macro immediately after starting it
cancels the recording and leaves an existing macro in place.
• Feature toggles no longer break a chain of ^K cuts or M-6 copies,
except the M-K cut-from-cursor toggle.
• With --mouse and --indicator, one can click in the scrollbar area
to roughly navigate within the buffer.
2026.02.04 - GNU nano 8.7.1 "Tende Samnug"
• A build failure when compiling against glibc-2.43 is fixed.
2025.11.12 - GNU nano 8.7 "Blue Highways"
• At the Execute prompt, preceding the command with two pipe symbols
allows implementing a copy-to-clipboard feature in your nanorc (on
terminals that support OSC 52). See the doc/sample.nanorc file.
2025.08.21 - GNU nano 8.6 "reason alone was a defective compass"
• The GotoLine menu accepts the prefixes ++ and -- for jumping
a number of lines forward or backward.
• Anchors are not forgotten when a line number is given on the
command line.
2025.06.12 - GNU nano 8.5 "Sigourney"
• Anchors are now saved when a file is closed, and restored when
the file is reopened -- if and when --positionlog is active.
• Nano exits with an error status upon keystrokes ^O^Q and ^X^Q.
• Keystroke ^L just centers the cursor, while M-% cycles it.
• Option --whitespace is accepted, but left undocumented.
• Syntax coloring now works correctly in more locales.
2025.04.02 - GNU nano 8.4 "Five Miles Out"
• Bracketed pastes over a slow connection are more reliable.
• Tabs in an external paste at a prompt are not dropped.
• Feedback occurs when the cursor sits on a Byte Order Mark.
• The Execute prompt is more forgiving of a typo.
2024.12.21 - GNU nano 8.3 "like mice in the dream of a tabby cat"
• A build failure with gcc-15 is fixed.
• Several translations were updated.
2024.09.05 - GNU nano 8.2 "Charlotte will climb walls!"
• At a Yes-No prompt, beside Y and the localized initial for "Yes",
also ^Y is accepted. Similarly, ^N for "No", and ^A for "All".
• A text-highlighting bug with Alt+Home/Alt+End is fixed.
2024.07.12 - GNU nano 8.1 "de dag van de bitterkoekjespudding"
• The idiom `nano filename:linenumber` is understood only when the
option --colonparsing (or 'set colonparsing') is used.
• Modern bindings are *not* activated when nano's invocation name
starts with "e", as it jars with Debian's alternatives system.
• New bindable function 'cycle' first centers the current row,
then moves it to the top of the viewport, then to the bottom.
It is bound by default to ^L.
• Option --listsyntaxes/-z lists the names of available syntaxes.
2024.05.01 - GNU nano 8.0 "Grus grus"
• By default ^F is bound to starting a forward search, and ^B to
starting a backward search, while M-F and M-B repeat the search
in the corresponding direction. (See the documentation if you
want the old bindings back.)
• Command-line option --modernbindings (-/) makes ^Q quit, ^X cut,
^C copy, ^V paste, ^Z undo, ^Y redo, ^O open a file, ^W write a
file, ^R replace, ^G find again, ^D find again backwards, ^A set
the mark, ^T jump to a line, ^P show the position, and ^E execute.
• Above modern bindings are activated also when the name of nano's
executable (or a symlink to it) starts with the letter "e".
• To open a file at a certain line number, one can now use also
`nano filename:number`, besides `nano +number filename`.
• <Alt+Home> and <Alt+End> put the cursor on the first and last
row in the viewport, while retaining the horizontal position.
• When the three digits in an #RGB color code are all the same,
the code is mapped to the xterm grey scale, giving access to
fourteen levels of grey instead of just four.
• For easier access, M-" is bound to placing/removing an anchor,
and M-' to jumping to the next anchor.
• Whenever an error occurs, the keystroke buffer is cleared, thus
stopping the execution of a macro or a string bind.
• The mousewheel scrolls the viewport instead of moving the cursor.
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"
• 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
@@ -752,22 +907,22 @@
the undo implementation and the default syntax config are
also included. As always, Share and Enjoy!
2014.05.28 - GNU nano 2.3.3 is in its right place. This release contains
many many improvements to the core system, including
substantial improvements to the undo/redo code, UTF-8
handling, the configure script, and display of shortcuts
on very wide terminals. New features include the
ability to write to named pipes (--noread), as well as
linter support (see the nanorc man page for details). Also
included are much improved syntax highlighting code, and
configurations for JSON, texinfo, Go, and a default syntax
for catch-all highlighting. Finally, nano now has the
ability to set the color of the title bar, status bar, and
shortcut keys (e.g. "^X") and their descriptions. Again
see the nanorc page for details. There's much more, too
much to include here, but please keep those reports and
general feedback coming! Thank you for helping us help
you help us all.
2014.05.28 - GNU nano 2.3.3 is in its right place. This release
contains many many improvements to the core system,
including substantial improvements to the undo/redo code,
UTF-8 handling, the configure script, and display of
shortcuts on very wide terminals. New features include
the ability to write to named pipes (--noread), as well
as linter support (see the nanorc man page for details).
Also included are much improved syntax highlighting code,
and configurations for JSON, texinfo, Go, and a default
syntax for catch-all highlighting. Finally, nano now has
the ability to set the color of the title bar, status bar,
and shortcut keys (e.g. "^X") and their descriptions.
Again see the nanorc page for details. There's much more,
too much to include here, but please keep those reports
and general feedback coming! Thank you for helping us
help you help us all.
2013.03.22 - GNU nano 2.3.2 "Annoy your coworkers for fun and profit" is
released. This release introduces vim-style file locking
@@ -838,26 +993,23 @@
fixes for that version are still forthcoming.
2010.02.11 - GNU nano 2.2.3 "fumbling toward stability" is released.
This release contains a fix for only one bug, but a
rather irritating one: when paging up/down with smooth
scrolling, the cursor position was not being preserved
due to a bug in 2.2.2. With such a targeted fix
like this what could POSSIBLY go WRONG? Hahaha.
Enjoy and if you find new bugs, as always please
use Savannah's bug tracker.
This release contains a fix for only one bug, but a rather
irritating one: when paging up/down with smooth scrolling,
the cursor position was not being preserved due to a bug
in 2.2.2. With such a targeted fix like this what could
POSSIBLY go WRONG? Hahaha. Enjoy, and if you find new
bugs, as always please use Savannah's bug tracker:
https://savannah.gnu.org/bugs/?func=additem&group=nano
2010.01.17 - GNU nano 2.2.2 is released for you, you, you. This
release includes fixes for: crashes when writing
backup files in certain conditions, improper
screen centering when moving up/down in various
combination of smooth scrolling and soft wrapping modes,
a search crash on the armel arch, and issues with
lots of keybinding customizations causing crashing
particularly on FreeBSD. Also included are better
help menu entries for forward/back in the file browser,
some man page tweaks and one assert fix. As always,
share and enjoy!
2010.01.17 - GNU nano 2.2.2 is released for you, you, you. This release
includes fixes for: crashes when writing backup files in
certain conditions, improper screen centering when moving
up/down in various combinations of smooth scrolling and soft
wrapping modes, a search crash on the armel arch, and issues
with lots of keybinding customizations causing crashing
particularly on FreeBSD. Also included are better help menu
entries for forward/back in the file browser, some man page
tweaks and one assert fix. As always, share and enjoy!
2009.12.12 - GNU nano 2.2.1 "DLR strikes back" is open for business.
This release fixes many bugs, including: missing
@@ -906,13 +1058,13 @@
the command line will now override any related .nanorc
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
out there all right. This release contains mainly
2009.11.15 - GNU nano 2.1.99pre1 "take a bow" is out there, man,
it's out there all right. This release contains mainly
bugfixes, underscoring that we are preparing for the
next stable series release. Included are many fixes
for the new soft wrapping code, compiler warning tweaks,
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
surely more bugs to find before we call the code base
stable, so please keep those reports coming!
@@ -1542,7 +1694,7 @@
allow multiple syntax highlighting types, and a new -Y,
--syntax flag to set a specific one if there's no
filename regex to match it against (i.e. w/mutt). The
^space and M-space keys will now show up in the help
^Space and M-Space keys will now show up in the help
menu, which itself has been tweaked a bit, and many more
configure options should now cooperate (like the odd
pairing of --enable-tiny and --enable-multibuffer). The

12
README
View File

@@ -15,7 +15,7 @@ Appearance
In rough ASCII graphics, this is what nano's screen looks like:
____________________________________________________________________
| GNU nano 6.0 filename Modified |
| GNU nano 9.2 filename Modified |
--------------------------------------------------------------------
| This is the text window, displaying the contents of a 'buffer', |
| the contents of the file you are editing. |
@@ -29,7 +29,7 @@ Appearance
| |
--------------------------------------------------------------------
| [ Some status message ] |
|^G Help ^O Write Out ^W Where Is ^K Cut ^T Execute |
|^G Help ^O Write Out ^F Where Is ^K Cut ^T Execute |
|^X Exit ^R Read File ^\ Replace ^U Paste ^J Justify |
--------------------------------------------------------------------
@@ -52,8 +52,8 @@ Origin
Nowadays, nano wants to be a generally useful editor with sensible
defaults (linewise scrolling, no automatic line breaking).
The nano editor is an official GNU package. For more information on
GNU and the Free Software Foundation, please see https://www.gnu.org/.
The nano editor is an official GNU package. For more information
on GNU and the Free Software Foundation, see https://www.gnu.org/.
License
@@ -81,7 +81,9 @@ How to compile and install nano
You will need the header files of ncurses installed for ./configure
to succeed -- get them from libncurses-dev (Debian) or ncurses-devel
(Fedora) or a similarly named package. Use --prefix with ./configure
to override the default installation directory of /usr/local.
to override the default installation directory of /usr/local. And
use --sysconfdir=/etc when you want your self-compiled nano to read
the /etc/nanorc file.
After installation you may want to copy the doc/sample.nanorc file
to your home directory, rename it to ".nanorc", and then edit it

View File

@@ -8,19 +8,18 @@ building this needs a bit more care than the official tarballs.
Prerequisites
-------------
To successfully compile GNU nano from git, you'll need the following
packages:
To successfully compile GNU nano from git, you'll need the following:
- autoconf (version >= 2.69)
- automake (version >= 1.14)
- autopoint (version >= 0.18.3)
- gcc (version >= 5.0)
- gettext (version >= 0.18.3)
- git (version >= 2.7.4)
- groff (version >= 1.12)
- make (any version)
- pkg-config (version >= 0.22)
- texinfo (version >= 4.0)
autoconf (version >= 2.69)
automake (version >= 1.14)
autopoint (version >= 0.20)
gcc (version >= 5.0)
gettext (version >= 0.20)
git (version >= 2.7.4)
groff (version >= 1.12)
make (any version)
pkg-config (version >= 0.22)
texinfo (version >= 4.0)
You will also need to have the header files for ncurses installed,
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.
Download the source
-------------------
Clone the source
----------------
To obtain the current nano development branch (called 'master'), use the
following command. It will create in your current working directory a
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.git.savannah.gnu.org/nano.git
Generate the configure script
@@ -58,6 +57,9 @@ directory:
$ ./configure [--add-options-here]
Use --sysconfdir=/etc when you want your self-compiled nano to read
/etc/nanorc instead of /usr/local/etc/nanorc.
Build and install
-----------------
@@ -84,6 +86,7 @@ Problems?
Please submit any bugs you find in the code in git via the bug tracker
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
Contributing something
----------------------

6
THANKS
View File

@@ -5,9 +5,11 @@ If we missed you here, let us know!
Translations:
============
Pedro Albuquerque <palbuquerque73@gmail.com> Portuguese
Zayed Al-Saidi <zayed.alsaidi@gmail.com> Arabic
Josef Andersson <josef.andersson@fripost.org> Swedish
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
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
Antonio Ceballos <aceballos@gmail.com> Spanish
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
@@ -46,6 +48,7 @@ Jordi Mallach <jordi@gnu.org> Catalan
João Victor Duarte Martins <jvdm@sdf.lonestar.org> Brazilian Portuguese
Pavel Maryanov <acid@jack.kiev.ua> Russian
Daniele Medri <madrid@linux.it> Italian
Baurzhan Muftakhidinov <baurthefirst@gmail.com> Kazakh
Gergely Nagy <algernon@debian.org> Hungarian
Claudio Neves <cneves@nextis.com> Brazilian Portuguese
Kalle Olavi Niemitalo <kon@iki.fi> Finnish
@@ -78,6 +81,7 @@ Jacobo Tarrío <jtarrio@trasno.net> Galician
Andika Triwidada <andika@gmail.com> Indonesian
Francisco Javier Tsao Santín <tsao@members.fsf.org> Galician
Balázs Úr <urbalazs@gmail.com> Hungarian
Luca Vercelli <luca.vercelli.to@gmail.com> Italian
Miquel Vidal <miquel@sindominio.net> Catalan
Phan Vinh Thinh <teppi82@gmail.com> Vietnamese
Pauli Virtanen <pauli.virtanen@saunalahti.fi> Finnish

View File

@@ -2,9 +2,10 @@
# Generate configure & friends for GIT users.
gnulib_url="git://git.sv.gnu.org/gnulib.git"
gnulib_hash="135414a7f543e4d40ad0a7cbd51885e159a6e0f4"
gnulib_hash="833eea6be5607a85bc964bf728a7a82ca461b5b1"
modules="
canonicalize-lgpl
futimens
getdelim
getline
@@ -18,32 +19,35 @@ modules="
regex
sigaction
snprintf-posix
stdarg
stdarg-h
strcase
strcasestr-simple
strnlen
sys_wait
vsnprintf-posix
wchar
wchar-h
wctype-h
wcwidth
"
# Make sure the local gnulib git repo is up-to-date.
if [ ! -d "gnulib" ]; then
git clone --depth=1111 ${gnulib_url}
git clone --depth=2222 ${gnulib_url}
fi
cd gnulib >/dev/null || exit 1
curr_hash=$(git log -1 --format=%H)
if [ "${gnulib_hash}" != "${curr_hash}" ]; then
echo "Pulling..."
git pull
git checkout -f ${gnulib_hash}
git checkout --force ${gnulib_hash}
fi
cd .. >/dev/null || exit 1
rm -rf lib
./gnulib/gnulib-tool \
--import \
${modules}
echo "Gnulib-tool..."
./gnulib/gnulib-tool --import ${modules}
echo
autoreconf -f -i -s
echo "Autoreconf..."
autoreconf --install --symlink --force
echo "Done."

View File

@@ -1,6 +1,6 @@
# 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-2026 Free Software Foundation, Inc.
# Copyright (C) 2014, 2017 Mike Frysinger
#
# 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
# 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], [9.2], [nano-devel@gnu.org], [nano])
AC_CONFIG_SRCDIR([src/nano.c])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([1.14])
AM_MAINTAINER_MODE([enable])
AC_CONFIG_HEADERS([config.h])
dnl Make sure the ONCE macros are available.
@@ -47,7 +48,7 @@ PKG_PROG_PKG_CONFIG
dnl Internationalization macros.
AM_GNU_GETTEXT_VERSION([0.18.3])
AM_GNU_GETTEXT_VERSION([0.20])
AM_GNU_GETTEXT([external], [need-ngettext])
AM_CONDITIONAL(USE_NLS, test x$USE_NLS = xyes)
@@ -127,6 +128,20 @@ if test "x$enable_color" != xno; then
color_support=yes
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,
AS_HELP_STRING([--disable-comment], [Disable the comment/uncomment function]))
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.])
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,
AS_HELP_STRING([--disable-help], [Disable the built-in help texts]))
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_color" != xyes; then
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
if test "x$enable_color" = xno; then
@@ -214,6 +253,30 @@ if test "x$enable_libmagic" = xyes; then
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,
AS_HELP_STRING([--disable-linenumbers], [Disable line numbering]))
if test "x$enable_tiny" = xyes; then
@@ -271,14 +334,14 @@ if test "x$enable_operatingdir" != xno; then
fi
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_speller" != xyes; then
enable_speller=no
fi
fi
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
AC_ARG_ENABLE(tabcomp,
@@ -353,6 +416,9 @@ if test "x$enable_utf8" != xno; then
AC_CHECK_FUNCS(iswalpha iswalnum iswpunct mbstowcs wctomb)
fi
AC_CHECK_FUNCS_ONCE(chmod chown fchmod fchown flockfile funlockfile
fork fsync geteuid pipe wait waitpid)
dnl Checks for available flags.
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.]))
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"], [
AC_CHECK_HEADERS([magic.h])
AC_CHECK_LIB(magic, magic_open)

View File

@@ -12,8 +12,8 @@
<body>
<br>
<h1 align="center">Overview of nano's shortcuts &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</h1>
<h3 align="center">The editor's keystrokes and their functions &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</h3>
<h1 align="center">Overview of nano's shortcuts &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</h1>
<h3 align="center">The editor's keystrokes and their functions &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</h3>
<br>
<table align="center"><tbody>
@@ -33,7 +33,6 @@
<tr><td>Ctrl+K &nbsp;&nbsp;</td><td>Cut current line into cutbuffer</td></tr>
<tr><td>Alt+6</td><td>Copy current line into cutbuffer</td></tr>
<tr><td>Ctrl+U</td><td>Paste contents of cutbuffer</td></tr>
<tr><td>Alt+T</td><td>Cut until end of buffer</td></tr>
<tr><td>Ctrl+]</td><td>Complete current word</td></tr>
<tr><td>Alt+3</td><td>Comment/uncomment line/region</td></tr>
<tr><td>Alt+U</td><td>Undo last action</td></tr>
@@ -43,10 +42,10 @@
<b>Search and replace</b>
<table><tbody>
<tr><td>Ctrl+Q &nbsp;&nbsp;</td><td>Start backward search</td></tr>
<tr><td>Ctrl+W</td><td>Start forward search</td></tr>
<tr><td>Alt+Q</td><td>Find next occurrence backward</td></tr>
<tr><td>Alt+W</td><td>Find next occurrence forward</td></tr>
<tr><td>Ctrl+B &nbsp;&nbsp;</td><td>Start backward search</td></tr>
<tr><td>Ctrl+F</td><td>Start forward search</td></tr>
<tr><td>Alt+B</td><td>Find next occurrence backward</td></tr>
<tr><td>Alt+F</td><td>Find next occurrence forward</td></tr>
<tr><td>Alt+R</td><td>Start a replacing session</td></tr>
</tbody></table>
<br>
@@ -64,11 +63,16 @@
<b>Operations</b>
<table><tbody>
<tr><td>Ctrl+T &nbsp;&nbsp;</td><td>Execute some command</td></tr>
<tr><td>Ctrl+T Ctrl+S</td><td>Run a spell check</td></tr>
<tr><td>Ctrl+T Ctrl+Y</td><td>Run a syntax check</td></tr>
<tr><td>Ctrl+T Ctrl+O &nbsp;</td><td>Run a formatter</td></tr>
<tr><td>Tab</td><td>Indent marked region</td></tr>
<tr><td>Shift+Tab &nbsp;&nbsp;</td><td>Unindent marked region</td></tr>
<tr><td>Ctrl+J</td><td>Justify paragraph or region</td></tr>
<tr><td>Alt+J</td><td>Justify entire buffer</td></tr>
<tr><td>Alt+B</td><td>Run a syntax check</td></tr>
<tr><td>Alt+F</td><td>Run a formatter/fixer/arranger</td></tr>
<tr><td>Alt+:</td><td>Start/stop recording of macro</td></tr>
<tr><td>Alt+T</td><td>Cut until end of buffer</td></tr>
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
<tr><td>Alt+:</td><td>Start/stop recording of macro &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td></tr>
<tr><td>Alt+;</td><td>Replay macro</td></tr>
</tbody></table>
<br>
@@ -77,8 +81,8 @@
<b>Moving around</b>
<table><tbody>
<tr><td>Ctrl+B &nbsp;&nbsp;</td><td>One character backward</td></tr>
<tr><td>Ctrl+F</td><td>One character forward</td></tr>
<tr><td><b>&larr;</b></td><td>One character backward</td></tr>
<tr><td><b>&rarr;</b></td><td>One character forward</td></tr>
<tr><td>Ctrl+<b>&larr;</b></td><td>One word backward</td></tr>
<tr><td>Ctrl+<b>&rarr;</b></td><td>One word forward</td></tr>
<tr><td>Ctrl+A</td><td>To start of line</td></tr>
@@ -87,6 +91,8 @@
<tr><td>Ctrl+N</td><td>One line down</td></tr>
<tr><td>Ctrl+<b>&uarr;</b></td><td>To previous block</td></tr>
<tr><td>Ctrl+<b>&darr;</b></td><td>To next block</td></tr>
<tr><td>Alt+Home &nbsp;</td><td>To first row in viewport</td></tr>
<tr><td>Alt+End</td><td>To last row in viewport</td></tr>
<tr><td>Ctrl+Y</td><td>One page up</td></tr>
<tr><td>Ctrl+V</td><td>One page down</td></tr>
<tr><td>Alt+\</td><td>To top of buffer</td></tr>
@@ -96,33 +102,35 @@
<b>Special movement</b>
<table><tbody>
<tr><td>Alt+G &nbsp;&nbsp;&nbsp;</td><td>Go to specified line</td></tr>
<tr><td>Alt+G &nbsp;&nbsp;&nbsp;&nbsp;</td><td>Go to a specified line</td></tr>
<tr><td>Alt+]</td><td>Go to complementary bracket</td></tr>
<tr><td>Alt+&lt;</td><td>Scroll viewport to the left</td></tr>
<tr><td>Alt+&gt;</td><td>Scroll viewport to the right</td></tr>
<tr><td>Alt+<b>&uarr;</b></td><td>Scroll viewport up</td></tr>
<tr><td>Alt+<b>&darr;</b></td><td>Scroll viewport down</td></tr>
<tr><td>Alt+&lt;</td><td>Switch to preceding buffer</td></tr>
<tr><td>Alt+&gt;</td><td>Switch to succeeding buffer</td></tr>
<tr><td>Ctrl+L</td><td>Center the current line</td></tr>
<tr><td>Alt+<b>&larr;</b></td><td>Switch to preceding buffer</td></tr>
<tr><td>Alt+<b>&rarr;</b></td><td>Switch to succeeding buffer</td></tr>
</tbody></table>
<br>
<b>Information</b>
<table><tbody>
<tr><td>Ctrl+C &nbsp;&nbsp;</td><td>Report cursor position</td></tr>
<tr><td>Alt+D</td><td>Report line/word/character count</td></tr>
<tr><td>Alt+D</td><td>Report line/word/character counts</td></tr>
<tr><td>Ctrl+G</td><td>Display help text</td></tr>
</tbody></table>
<br>
<b>Various</b>
<table><tbody>
<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>Shift+Tab &nbsp;&nbsp;</td><td>Unindent marked region</td></tr>
<tr><td>Alt+A &nbsp;&nbsp;&nbsp;&nbsp;</td><td>Set or unset the mark</td></tr>
<tr><td>Alt+C</td><td>Turn constant position info 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+V</td><td>Enter next keystroke verbatim</td></tr>
<tr><td>Ctrl+L</td><td>Refresh the screen</td></tr>
<tr><td>Ctrl+Z</td><td>Suspend nano</td></tr>
<tr><td>Alt+S</td><td>Turn softwrapping on/off</td></tr>
<tr><td>Alt+X</td><td>Hide/unhide the help lines</td></tr>
<tr><td>Alt+Z</td><td>Hide/unhide the info bars</td></tr>
</tbody></table>
<br>

View File

@@ -5,7 +5,7 @@
<title>The GNU nano editor FAQ</title>
<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.">
<style>
<style type="text/css">
.indented { margin-left: 2em; font-family: courier; font-size: 110%; }
</style>
</head>
@@ -27,7 +27,7 @@
<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.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>
<h3><a href="#3">3. Installation and Configuration</a></h3>
<blockquote><p>
@@ -45,13 +45,13 @@
<blockquote><p>
<a href="#4.1">4.1. Alt+Up does nothing on a Linux console. How can I make it scroll?</a><br>
<a href="#4.2">4.2. How can I make Ctrl+Shift+Left/Right select words on urxvt?</a><br>
<a href="#4.3">4.3. Ack! My numeric keypad's keys don't work properly when NumLock is off! What can I do?</a><br>
<a href="#4.4">4.4. With what keystroke can I paste text from the clipboard into nano?</a><br>
<a href="#4.3">4.3. How do I remove an unwanted Byte Order Mark?</a><br>
<a href="#4.4">4.4. Where did Ctrl+T in the Search menu go?</a><br>
<a href="#4.5">4.5. How do I select text for or paste text from the clipboard when nano's mouse support is turned on?</a><br>
<a href="#4.6">4.6. When I paste text into a document, each line gets indented further than the last. Why? And how can I stop this?</a><br>
<a href="#4.7">4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</a><br>
<a href="#4.8">4.8. I've compiled nano with color support, but I don't see any color when I run it!</a><br>
<a href="#4.9">4.9. How do I make nano my default editor (in Pine, mutt, etc.)?</a><br>
<a href="#4.9">4.9. How do I make nano my default editor (in Pine, mutt, git, ...)?</a><br>
</p></blockquote>
<h3><a href="#5">5. Internationalization</a></h3>
<blockquote><p>
@@ -72,14 +72,14 @@
<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.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>
<hr width="100%">
<h1><a name="1"></a>1. General</h1>
<h3><a name="1.1"></a>1.1. What is GNU nano?</h3>
<h1 id="1">1. General</h1>
<h3 id="1.1">1.1. What is GNU nano?</h3>
<blockquote><p>GNU nano was designed to be a free replacement for the Pico text editor, part of the Pine email suite from <a href="http://www.washington.edu/pine/">The University of Washington</a>. It aimed to &quot;emulate Pico as closely as is reasonable and then include extra functionality&quot;.</p></blockquote>
<h3><a name="1.2"></a>1.2. What is the history behind nano?</h3>
<h3 id="1.2">1.2. What is the history behind nano?</h3>
<blockquote><p>Funny you should ask!</p>
<p><b>In the beginning...</b></p>
<p>For years Pine was THE program used to read email on a Unix system. The Pico text editor is the portion of the program one would use to compose his or her mail messages. Many beginners to Unix flocked to Pico and Pine because of their well organized, easy to use interfaces. With the proliferation of GNU/Linux in the mid to late 90's, many University students became intimately familiar with the strengths (and weaknesses) of Pine and Pico.</p>
@@ -89,30 +89,30 @@
<p>It was in late 1999 when Chris Allegretta (our hero) was yet again complaining to himself about the less-than-perfect license Pico was distributed under, the 1000 makefiles that came with it and how just a few small improvements could make it the Best Editor in the World (TM). Having been a convert from Slackware to Debian, he missed having a simple binary package that included Pine and Pico, and had grown tired of downloading them himself.</p>
<p>Finally something snapped inside and Chris coded and hacked like a madman for many hours straight one weekend to make a (barely usable) Pico clone, at the time called TIP (Tip Isn't Pico). The program could not be invoked without a filename, could not save files, had no help text display, spell checker, and so forth. But over time it improved, and with the help of a few great coders it matured to the (hopefully) stable state it is in today.</p>
<p>In February 2001, nano was declared an official GNU program by Richard Stallman. nano also reached its first production release on March 22, 2001.</p></blockquote>
<h3><a name="1.3"></a>1.3. Why the name change from TIP?</h3>
<h3 id="1.3">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 &quot;establishes a full duplex terminal connection to a remote host&quot;, 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>
<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>
<h3><a name="1.5"></a>1.5. I want to read the man page without having to download the program!</h3>
<h3 id="1.4">1.4. What is the current version of nano?</h3>
<blockquote><p>The current version of nano <i>should</i> be <b>9.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 id="1.5">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>
<hr width="100%">
<h1><a name="2"></a>2. Where to get GNU nano.</h1>
<h3><a name="2.1"></a>2.1. Web sites that carry nano.</h3>
<h1 id="2">2. Where to get GNU nano.</h1>
<h3 id="2.1">2.1. Web sites that carry nano.</h3>
<blockquote><p>The nano source tarballs can be downloaded from the following web sites:</p>
<ul>
<li><a href="https://nano-editor.org/dist/latest/">https://nano-editor.org/dist/latest/</a></li>
<li><a href="https://ftpmirror.gnu.org/gnu/nano/">https://ftpmirror.gnu.org/gnu/nano/</a></li>
</ul>
</blockquote>
<h3><a name="2.2"></a>2.2. RPM packages (RedHat, OpenSuse, and derivatives).</h3>
<h3 id="2.2">2.2. RPM packages (RedHat, OpenSuse, and derivatives).</h3>
<blockquote>
<ul>
<li><a href="https://kojipkgs.fedoraproject.org//packages/nano/">https://kojipkgs.fedoraproject.org//packages/nano/</a></li>
<li><a href="https://software.opensuse.org/package/nano">https://software.opensuse.org/package/nano</a></li>
</ul>
</blockquote>
<h3><a name="2.3"></a>2.3. Deb packages (Debian and derivatives):</h3>
<h3 id="2.3">2.3. Deb packages (Debian and derivatives):</h3>
<blockquote><p>Debian users can check out the current nano packages for:</p>
<ul>
<li><a href="https://packages.debian.org/stable/editors/nano">stable</a></li>
@@ -121,14 +121,14 @@
</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>
</blockquote>
<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>
<h3 id="2.4">2.4. By git (for the brave).</h3>
<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%">
<h1><a name="3"></a>3. Installation and Configuration</h1>
<h3><a name="3.1"></a>3.1. How do I install the RPM or DEB package?</h3>
<h1 id="3">3. Installation and Configuration</h1>
<h3 id="3.1">3.1. How do I install the RPM or DEB package?</h3>
<blockquote><p>It's simple really! As root, type <b>rpm -Uvh nano-x.y-1*.rpm</b> if you have a RedHat-ish system or <b>dpkg -i nano_x.y-1*.deb</b> if you have a Debian-ish system, where <b>x.y</b> is the version number of nano. There are other programs to install packages, and if you wish to use those, knock yourself out.</p></blockquote>
<h3><a name="3.2"></a>3.2. Compiling from source: WHAT THE HECK DO I DO NOW?</h3>
<h3 id="3.2">3.2. Compiling from source: WHAT THE HECK DO I DO NOW?</h3>
<blockquote><p>Okay, take a deep breath, this really isn't hard. Unpack the nano source with a command like:</p>
<p class="indented"><b>tar -xvf nano-x.y.tar.gz</b></p>
<p>Then you need to run <b>configure</b> with any options you might want (if any).</p>
@@ -137,48 +137,52 @@
<b>./configure</b><br>
<b>make</b><br>
<b>make install</b>&nbsp;&nbsp; #(as root, of course)</p></blockquote>
<h3><a name="3.3"></a>3.3. Why does everything go into /usr/local?</h3>
<h3 id="3.3">3.3. Why does everything go into /usr/local?</h3>
<blockquote><p>Well, that's what the <b>configure</b> script defaults to. If you wish to change this, simply do this:</p>
<p class="indented"><b>./configure --prefix=/usr</b></p>
<p>This will put nano into /usr/bin when you run <b>make install</b>.</p></blockquote>
<h3><a name="3.4"></a>3.4. nano should automatically run strip on the binary when installing it!</h3>
<h3 id="3.4">3.4. nano should automatically run strip on the binary when installing it!</h3>
<blockquote><p>It does when you use <b>make install-strip</b>. The default <b>make install</b> does not, and will not, run strip automatically.</p></blockquote>
<h3><a name="3.5"></a>3.5. How can I make the executable smaller? This is too bloated!</h3>
<h3 id="3.5">3.5. How can I make the executable smaller? This is too bloated!</h3>
<blockquote><p>Actually, there are several parts of the editor that can be disabled. You can pass arguments to the <b>configure</b> script that disable certain features. Here's a brief list:</p>
<pre>
<b>--disable-browser</b> Disable the built-in file browser
<b>--disable-color</b> Disable color and syntax highlighting
<b>--disable-comment</b> Disable the comment/uncomment function
<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-histories</b> Disable the saving of search strings and cursor positions
<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-linenumbers</b> Disable line numbering
<b>--disable-linter</b> Disable the linting tool
<b>--disable-mouse</b> Disable mouse support
<b>--disable-multibuffer</b> Disable the opening of multiple file buffers
<b>--disable-nanorc</b> Disable the use of .nanorc files
<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-wordcomp</b> Disable the word-completion function
<b>--disable-wrapping</b> Disable all hard-wrapping of text</pre>
<p>There's also the <b>--enable-tiny</b> option which disables everything above, as well as some larger chunks of the program (like the undo/redo code and the code for selecting text). Also, if you know you don't need other languages, you can use <b>--disable-nls</b> to disable internationalization and save a few kilobytes. And finally, there's always good old <b>strip</b> to remove all unneeded symbols.</p>
</blockquote>
<h3><a name="3.6"></a>3.6. Tell me more about this multibuffer stuff!</h3>
<blockquote><p>To use multiple file buffers, you must not have configured nano with <b>--disable-multibuffer</b> nor with <b>--enable-tiny</b> (use <b>nano -V</b> to check the compilation options). Then when you want to insert a file into its own buffer instead of into the current file, just hit <b>Meta-F</b> after typing <b>^R</b>. If you always want files to be loaded into their own buffers, use the <b>-F</b> or <b>--multibuffer</b> flag when you invoke nano, or add <b>set multibuffer</b> to your .nanorc file.</p>
<p>You can move between the buffers you have open with the <b>Meta-&lt;</b> and <b>Meta-&gt;</b> keys, or more easily without holding Shift: <b>Meta-,</b> and <b>Meta-.</b> (clear as mud, right? =-). When you have more than one buffer open, the ^X shortcut will say &quot;Close&quot;, instead of &quot;Exit&quot;.</p></blockquote>
<h3><a name="3.7"></a>3.7. Tell me more about this verbatim input stuff!</h3>
<h3 id="3.6">3.6. Tell me more about this multibuffer stuff!</h3>
<blockquote><p>To use multiple file buffers, you must not have configured nano with <b>--disable-multibuffer</b> nor with <b>--enable-tiny</b> (use <b>nano -V</b> to check the compilation options). Then when you want to insert a file into its own buffer instead of into the current file, just hit <b>Meta-F</b> after typing <b>^R</b>.</p>
<p>If you want files to be loaded always into their own buffers, use the <b>-F</b> or <b>--multibuffer</b> flag when you invoke nano, or add <b>set multibuffer</b> to your .nanorc file. (Since nano-9.2 these options are named <b>--newbuffer</b> and <b>set newbuffer</b>.)</p>
<p>You can switch between open buffers with <b>Meta-,</b> and <b>Meta-.</b> (Alt+comma and Alt+period).</p>
<p>When you have more than one buffer open, the help lines will say &quot;<i>Close</i>&quot; instead of &quot;<i>Exit</i>&quot; for the <b>^X</b> shortcut.</p></blockquote>
<h3 id="3.7">3.7. Tell me more about this verbatim input stuff!</h3>
<blockquote><p>When you want to insert a literal character into the file you're editing, such as a control character that nano usually treats as a command, first press <b>Meta-V</b> (if you're not at a prompt, you'll get the message &quot;Verbatim Input&quot; on the status bar), then press the key(s) that generate the character you want.</p>
<p>Alternatively, if Unicode support is enabled (see section <a href="#5.3">5.3</a>), you can press <b>Meta-V</b> and then type a six-digit hexadecimal code (from 000000 to 10FFFF, case-insensitive), and the character with the corresponding value will be inserted. The status bar will change to &quot;Unicode Input: ......&quot; when you do this.</p></blockquote>
<h3><a name="3.8"></a>3.8. How do I make a .nanorc file that will be read when I start nano?</h3>
<h3 id="3.8">3.8. How do I make a .nanorc file that will be read when I start nano?</h3>
<blockquote><p>It's not hard at all! Simply copy the <b>sample.nanorc</b> from the doc/ directory in the nano source package (or from /usr/doc/nano on your system) to <b>.nanorc</b> in your home directory, and then edit it. If you didn't get a sample nanorc, the syntax of the file is simple: features are turned on and off by using the words <b>set</b> and <b>unset</b> followed by the long option name of the feature (see <b>man nanorc</b> for the full list of options). For example, &quot;set quickblank&quot; or &quot;set smarthome&quot;. Of course, for this to work, your nano must <b>not</b> have been compiled with <b>--disable-nanorc</b>.</p></blockquote>
<h3><a name="3.9"></a>3.9. Why does my self-compiled nano not read /etc/nanorc?</h3>
<blockquote><p>By default (see <a href="#3.3">3.3</a>), nano gets installed into /usr/local. This also means that, at startup, nano will read <b>/usr/local/etc/nanorc</b> instead of <b>/etc/nanorc</b>. You can make a symlink from the former to the latter if you want your self-compiled nano to read the same nanorc as the system-installed nano. Or you can configure your nano to overwrite the system nano (again, see <a href="#3.3">3.3</a>).</p></blockquote>
<h3 id="3.9">3.9. Why does my self-compiled nano not read /etc/nanorc?</h3>
<blockquote><p>By default (see <a href="#3.3">3.3</a>), nano gets installed into /usr/local. This also means that, at startup, nano reads <b>/usr/local/etc/nanorc</b> instead of <b>/etc/nanorc</b>. You can make a symlink from the former to the latter if you want your self-compiled nano to read the same nanorc as the system-installed nano. Or you can simply configure your nano with <b>--sysconfdir=/etc</b>.</p></blockquote>
<hr width="100%">
<h1><a name="4"></a>4. Running</h1>
<h3><a name="4.1"></a>4.1. Alt+Up does nothing on a Linux console. How can I make it scroll?</h3>
<h1 id="4">4. Running</h1>
<h3 id="4.1">4.1. Alt+Up does nothing on a Linux console. How can I make it scroll?</h3>
<blockquote><p>On Debian and its derivatives, the <b>Alt+Up</b> keystroke on a Linux console
produces by default a 'KeyboardSignal', which normally does absolutely nothing and is useless
for the average user. To get the keystroke to do what it ought to do (scroll the viewport
@@ -191,7 +195,7 @@
&nbsp;&nbsp;&nbsp;&nbsp;sed -i 's/KeyboardSignal/Up/' ${file%.gz};<br>
&nbsp;&nbsp;&nbsp;&nbsp;gzip ${file%.gz};<br>
done</b></p></blockquote>
<h3><a name="4.2"></a>4.2. How can I make Ctrl+Shift+Left/Right select words on urxvt?</h3>
<h3 id="4.2">4.2. How can I make Ctrl+Shift+Left/Right select words on urxvt?</h3>
<blockquote><p>The urxvt terminal emulator produces non-standard escape sequences for the modified cursor keys. These deviant sequences are not listed in the terminfo database, which means that ncurses does not recognize them. The easiest way around this is to tell urxvt to produce xterm-compatible escape sequences for the relevant keystrokes. To achieve this, add the following lines to your ~/.Xresources file:</p>
<pre>
URxvt.iso14755_52: False
@@ -206,31 +210,39 @@
URxvt.keysym.M-Right: \033[1;3C
URxvt.keysym.M-Left: \033[1;3D
URxvt.keysym.M-Home: \033[1;3H
URxvt.keysym.M-End: \033[1;3F
URxvt.keysym.M-Insert: \033[2;3~
URxvt.keysym.M-Delete: \033[3;3~
URxvt.keysym.M-Page_Up: \033[5;3~
URxvt.keysym.M-Page_Down: \033[6;3~</pre>
URxvt.keysym.M-Page_Down: \033[6;3~
URxvt.keysym.S-Page_Up: \033[5;2~
URxvt.keysym.S-Page_Down: \033[6;2~</pre>
<p>Then run <b>xrdb ~/.Xresources</b> and restart your urxvt terminal. Now <b>Ctrl+Shift+Left</b> and <b>Ctrl+Shift+Right</b> will select words, <b>Alt+Up</b> and <b>Alt+Down</b> will scroll the text without moving the cursor, and several such things more.</p></blockquote>
<h3><a name="4.3"></a>4.3. Ack! My numeric keypad's keys don't work properly when NumLock is off! What can I do?</h3>
<blockquote><p>You can use the <b>-K</b> or <b>--rawsequences</b> option on the command line, or add the line <b>set rawsequences</b> to your .nanorc. However, nano's mouse support will be disabled if you do any of these things.</p></blockquote>
<h3><a name="4.4"></a>4.4. With what keystroke can I paste text from the clipboard into nano?</h3>
<blockquote><p>In most desktop environments <b>Shift+Insert</b> will paste the contents of the clipboard.</p></blockquote>
<h3><a name="4.5"></a>4.5. How do I select text for or paste text from the clipboard when nano's mouse support is turned on?</h3>
<h3 id="4.3">4.3. How do I remove an unwanted Byte Order Mark?</h3>
<blockquote><p>To check whether a file contains a Byte Order Mark (BOM), open the file and type <b>Ctrl+Home</b>. If there is a BOM, the status bar will tell you so. Now type <b>Delete</b> to remove the BOM, and <b>^S</b> to save the file.</p>
<p>If you've accidentally deleted a Byte Order Mark from a file that needs it, and you want to restore it, then type: <b>Ctrl+Home Alt+V feff Enter</b>. Verify that the BOM is back with <b>Ctrl+Home</b>, and save the file with <b>^S</b>. (Note that on Unix, files should not contain a BOM.)</p></blockquote>
<h3 id="4.4">4.4. Where did Ctrl+T in the Search menu go?</h3>
<blockquote><p>Actually, the <b>Ctrl+T</b> toggle is still there &mdash; it's just not listed in the help lines nor in the help text, and the function it executes cannot be rebound to another key. If you do want to use another key, you can emulate the rebinding with something like this in your .nanorc:</p>
<pre>
bind ^E "{cancel}{gotoline}" search
bind ^E "{cancel}{whereis}" gotoline</pre>
<p>But since forever there are also direct keystrokes for jumping to a line number: <b>Ctrl+/</b> and <b>Alt+G</b> in the main menu.</p></blockquote>
<h3 id="4.5">4.5. How do I select text for or paste text from the clipboard when nano's mouse support is turned on?</h3>
<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 id="4.6">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>
<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>
<h3><a name="4.7"></a>4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</h3>
<p><i>Update:</i> Since version 4.8, nano suppresses 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 id="4.7">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>
<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>
<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>
<p><i>Update:</i> Since version 4.8, nano ignores 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 id="4.8">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>
<h3><a name="4.9"></a>4.9. How do I make nano my default editor (in Pine, mutt, etc.)?</h3>
<h3 id="4.9">4.9. How do I make nano my default editor (in Pine, mutt, git, ...)?</h3>
<blockquote><p>You need to make nano your $EDITOR. If you want this to be saved, you should put a line like this in your <b>.bashrc</b> if you use bash (or <b>.zshrc</b> if you believe in zsh):</p>
<p class="indented"><b>export EDITOR=/usr/local/bin/nano</b></p>
<p>or, if you use tcsh, put this in your <b>.cshrc</b> file:</p>
<p class="indented"><b>setenv EDITOR /usr/local/bin/nano</b></p>
<p>Change /usr/local/bin/nano to wherever nano is installed on your system. Type &quot;which nano&quot; to find out. This will not take effect until the next time you log in. So log out and back in again.</p>
<p>Then, on top of that, if you use Pine, you must go into setup (type <b>S</b> at the main menu), and then configure (type <b>C</b>). Hit Enter on the lines that say:</p>
<p class="indented"><b>[ ] enable-alternate-editor-cmd</b><br>
@@ -238,47 +250,50 @@
<p>Then exit (<b>E</b>) and select Yes (<b>Y</b>).</p>
<p>If you're a mutt user, you should see an effect immediately the next time you log in. No further configuration is needed. However, if you want to let people know you use nano to compose your email messages, you can put a line like this in your <b>.muttrc</b>:</p>
<p class="indented"><b>my_hdr X-Composer: nano-x.y</b></p>
<p>Again, replace x.y with the version of nano you use.</p></blockquote>
<p>Again, replace x.y with the version of nano you use.</p>
<p>To use nano to edit your git commit messages, you can run:</p>
<p class="indented"><b>git config --global core.editor "nano --guide=74 --nohelp +1"</b></p>
<p>Note the <b>+1</b> at the end — it makes nano start always at the top of the edit window. The guidestripe helps you keep the text within a reasonable width.</blockquote>
<hr width="100%">
<h1><a name="5"></a>5. Internationalization</h1>
<h3><a name="5.1"></a>5.1. There's no translation for my language!</h3>
<h1 id="5">5. Internationalization</h1>
<h3 id="5.1">5.1. There's no translation for my language!</h3>
<blockquote><p>In June 2001, GNU nano entered the <a href="https://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
<p>If there isn't a translation for your language, you could ask <a href="https://translationproject.org/team/">your language team</a> to translate nano, or better still, join that team and do it yourself. Joining a team is easy. You just need to ask the team leader to add you, and then send a <a href="https://translationproject.org/disclaim.txt">translation disclaimer to the FSF</a> (this is necessary as nano is an official GNU package, but it does <b>not</b> mean that you transfer the rights of your work to the FSF, it's just so the FSF can legally manage them).</p>
<p>In any case, translating nano is easy. Just grab the latest <b>nano.pot</b> file listed on <a href="https://translationproject.org/domain/nano.html">nano's page</a> at the TP, and translate each <b>msgid</b> line into your native language on the <b>msgstr</b> line. When you're done, you should send it to the TP's central PO-file repository.</p></blockquote>
<h3><a name="5.2"></a>5.2. I don't like the translation for &lt;x&gt; in my language. How can I fix it?</h3>
<h3 id="5.2">5.2. I don't like the translation for &lt;x&gt; in my language. How can I fix it?</h3>
<blockquote><p>The best way is to send an e-mail with your suggested corrections to the team's mailing list. The address is mentioned in the <code>Language-Team:</code> field in the relevant PO file. The team leader or the assigned translator can then make the changes reach the nano-devel list.</p></blockquote>
<h3><a name="5.3"></a>5.3. What is the status of Unicode support?</h3>
<h3 id="5.3">5.3. What is the status of Unicode support?</h3>
<blockquote><p>Unicode should be fully usable nowadays. When the encoding of your terminal is set to UTF-8, and your locale (mainly the LANG environment variable) is UTF-8 too, then you should be able to read, enter and save Unicode text.</p></blockquote>
<hr width="100%">
<h1><a name="6"></a>6. Advocacy and Licensing</h1>
<h3><a name="6.1"></a>6.1. Why should I use nano instead of Pico?</h3>
<h1 id="6">6. Advocacy and Licensing</h1>
<h3 id="6.1">6.1. Why should I use nano instead of Pico?</h3>
<blockquote><p>If you want features like undo/redo, syntax highlighting, line numbers, soft-wrapping, opening multiple files at once, an interface localized to your language, or search and replace with support for regular expressions, then you want nano.</p></blockquote>
<h3><a name="6.2"></a>6.2. Why should I use Pico instead of nano?</h3>
<h3 id="6.2">6.2. Why should I use Pico instead of nano?</h3>
<blockquote><p>If you use your editor only to write emails or other texts and have no need for the above-mentioned features, then Pico will do fine for you.</p></blockquote>
<h3><a name="6.3"></a>6.3. What is so bad about the older Pine license?</h3>
<h3 id="6.3">6.3. What is so bad about the older Pine license?</h3>
<blockquote><p>The U of W license for older versions of Pine and Pico is not considered truly Free Software according to both the Free Software Foundation and the <a href="https://www.debian.org/social_contract#guidelines">Debian Free Software Guidelines</a>. The main problem regards the limitations on distributing derived works: according to UW, you can distribute their software, and you can modify it, but you can not do both, i.e. distribute modified binaries.</p></blockquote>
<h3><a name="6.4"></a>6.4. Okay, well, what mail program should I use then?</h3>
<h3 id="6.4">6.4. Okay, well, what mail program should I use then?</h3>
<blockquote><p>If you are looking to use a Free Software program similar to Pine, and Emacs is not your thing, you should definitely take a look at <a href="http://www.mutt.org/">mutt</a>. It is a full-screen, console based mail program that actually has a lot more flexibility than Pine, but has a keymap included in the distribution that allows you to use the same keystrokes as Pine would to send and receive mail. It's also under the GNU General Public License, version 2.0.</p>
<p>Of course, due to the license change you can now use the <a href="http://www.washington.edu/alpine/">Alpine distribution</a> of PINE as it is now considered Free Software, but you would be sacrificing many of nano's features to do so.</p></blockquote>
<hr width="100%">
<h1><a name="7"></a>7. Miscellaneous</h1>
<h3><a name="7.1"></a>7.1. Where can I ask questions or send suggestions?</h3>
<h1 id="7">7. Miscellaneous</h1>
<h3 id="7.1">7.1. Where can I ask questions or send suggestions?</h3>
<blockquote><p>There are three mailing lists for nano hosted at <a href="https://savannah.gnu.org/">Savannah</a>: info-nano, help-nano and nano-devel. info-nano is a very low traffic list where new versions of nano are announced (surprise!). help-nano is for getting help with the editor without needing to hear all of the development issues surrounding it. nano-devel is a normally low, sometimes high traffic list for discussing the present and future development of nano. Here are links to where you can sign up for a given list:</p>
<p>info-nano - <a href="https://lists.gnu.org/mailman/listinfo/info-nano/">https://lists.gnu.org/mailman/listinfo/info-nano/</a><br>
help-nano - <a href="https://lists.gnu.org/mailman/listinfo/help-nano/">https://lists.gnu.org/mailman/listinfo/help-nano/</a><br>
nano-devel - <a href="https://lists.gnu.org/mailman/listinfo/nano-devel/">https://lists.gnu.org/mailman/listinfo/nano-devel/</a></p></blockquote>
<h3><a name="7.2"></a>7.3. How do I submit a bug report or patch?</h3>
<h3 id="7.2">7.3. How do I submit a bug report or patch?</h3>
<blockquote>
<p>The best way to submit bugs is through the <a href="https://savannah.gnu.org/bugs/?group=nano">Savannah bug tracker</a>, as you can check whether the bug you are reporting has already been submitted, and it makes it easier for the maintainers to keep track of them.
<p>You can submit patches for nano via <a href="https://savannah.gnu.org/patch/?group=nano">Savannah's patch manager</a>.</p></blockquote>
<h3><a name="7.3"></a>7.3. I want to send the development team a big load of cash (or just a thank you).</h3>
<h3 id="7.3">7.3. I want to send the development team a big load of cash (or just a thank you).</h3>
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="https://nano-editor.org/dist/latest/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
<h3><a name="7.4"></a>7.4. How do I join the development team?</h3>
<h3 id="7.4">7.4. How do I join the development team?</h3>
<blockquote><p>The easiest way is to consistently send in good patches that add some needed functionality, fix a bug or two, and/or make the program more optimized/efficient. Then ask nicely and you will probably be added to the Savannah development list and be given write access after a while. There is a lot of responsibility that goes along with being a team member, so don't think it's just something to add to your resume.</p></blockquote>
<h3><a name="7.5"></a>7.5. Can I have write access to the git tree?</h3>
<h3 id="7.5">7.5. Can I have write access to the git tree?</h3>
<blockquote><p>Re-read section <a href="#7.4">7.4</a> and you should know the answer.</p></blockquote>
<hr width="100%">

View File

@@ -1,4 +1,4 @@
.\" Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
.\" Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc.
.\"
.\" This document is dual-licensed. You may distribute and/or modify it
.\" under the terms of either of the following licenses:
@@ -16,27 +16,28 @@
.\" Documentation License along with this program. If not, see
.\" <https://www.gnu.org/licenses/>.
.\"
.TH NANO 1 "version 6.0" "December 2021"
.TH NANO 1 "July 2026" "GNU nano 9.2"
.SH NAME
nano \- Nano's ANOther editor, inspired by Pico
nano \- Nano's ANOther text editor, inspired by Pico
.SH SYNOPSIS
.B nano
.RI [ options "] [[\fB+" line [\fB, column "]] " file ]...
.sp
.BR nano " [" \fIoptions "] [[" + [ crCR ]( / | ? ) \fIstring "] " \fIfile ]...
.BR nano " [" \fIoptions "] [[" + [ crCR ]{ / | ? } \fIstring "] " \fIfile ]...
.SH DESCRIPTION
\fBnano\fP is a small and friendly editor. It copies the look and feel
of Pico, but is free software, and implements several features that Pico
\fBnano\fR is a small and friendly text editor. It copies the look and feel
of Pico, but is free software, and implements a few features that Pico
lacks, such as: opening multiple files, scrolling per line, undo/redo,
syntax coloring, line numbering, and soft-wrapping overlong lines.
.sp
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
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.
.sp
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.
The string can be made case sensitive and/or caused to be interpreted as a
@@ -53,76 +54,107 @@ the first occurrence of the word "Foo", you would do:
As a special case: if instead of a filename a dash (\fB\-\fR) is given,
\fBnano\fR will read data from standard input.
.SH NOTICES
Since version 9.0, all lines are scrolled horizontally together
(when the cursor approaches the edge), by just the amount needed,
instead of scrolling only the current line by a large step.
If you prefer the old behavior, you can use \fB\-\-\%solo\fR on the
command line or \fBset \%solosidescroll\fR in your \fInanorc\fR.
.sp
Also since version 9.0, keystrokes \fBM\-<\fR and \fBM\->\fR have
been reassigned to the \fB\%scrollleft\fR and \fB\%scrollright\fR functions.
If you want those keystrokes to do what they did before version 9.0,
add these two lines at the end of your \fInanorc\fR file:
.sp
.RS 4
.B bind M\-< prevbuf main
.br
.B bind M\-> nextbuf main
.RE
.sp
Since version 8.0, to be newcomer friendly, \fB^F\fR starts a forward search,
\fB^B\fR starts a backward search, \fBM\-F\fR searches the next occurrence
forward, and \fBM\-B\fR searches the next occurrence backward. If you want
those keystrokes to do what they did before version 8.0, add the following
four lines at the end of your \fInanorc\fR file:
.sp
.RS 4
.B bind ^F forward main
.br
.B bind ^B back main
.br
.B bind M\-F formatter main
.br
.B bind M\-B linter main
.RE
.sp
.SH EDITING
Entering text and moving around in a file is straightforward: typing the
Entering text and moving around in a file are straightforward: typing the
letters and using the normal cursor movement keys. Commands are entered
by using the Control (^) and the Alt or Meta (M\-) keys.
Typing \fB^K\fR deletes the current line and puts it in the cutbuffer.
Consecutive \fB^K\fRs will put all deleted lines together in the cutbuffer.
Any cursor movement or executing any other command will cause the next
\fB^K\fR to overwrite the cutbuffer. A \fB^U\fR will paste the current
Consecutive \fB^K\fRs put all deleted lines together in the cutbuffer.
Any cursor movement or executing any other command causes the next
\fB^K\fR to overwrite the cutbuffer. A \fB^U\fR pastes the current
contents of the cutbuffer at the current cursor position.
.sp
When a more precise piece of text needs to be cut or copied, you can mark
its start with \fB^6\fR, move the cursor to its end (the marked text will be
highlighted), and then use \fB^K\fR to cut it, or \fBM\-6\fR to copy it to the
cutbuffer. You can also save the marked text to a file with \fB^O\fR, or
spell check it with \fB^T^T\fR.
its start with \fB^6\fR, move the cursor to its end (the marked text is
highlighted), and then use \fB^K\fR to cut it, or \fBM\-6\fR to copy it to
the cutbuffer. You can also save the marked text to a file with \fB^O\fR,
or spell check it with \fB^T^T\fR.
.sp
On some terminals, text can be selected also by holding down Shift while
using the arrow keys. Holding down the Ctrl or Alt key too will increase
using the arrow keys. Holding down the Ctrl or Alt key too increases
the stride.
Any cursor movement without Shift being held will cancel such a selection.
Any cursor movement without Shift being held cancels such a selection.
.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 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 \[em] see
.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).
With \fB^S^X\fR you can save the buffer and exit from \fBnano\fR.
.SH OPTIONS
.TP
.BR \-A ", " \-\-smarthome
Make the Home key smarter. When Home is pressed anywhere but at the
very beginning of non-whitespace characters on a line, the cursor will
jump to that beginning (either forwards or backwards). If the cursor is
already at that position, it will jump to the true beginning of the
line.
very beginning of non-whitespace characters on a line, the cursor jumps
to that beginning (either forwards or backwards). If the cursor is
already at that position, it jumps to the true beginning of the line.
.TP
.BR \-B ", " \-\-backup
When saving a file, back up the previous version of it, using the current
filename suffixed with a tilde (\fB~\fP).
filename suffixed with a tilde (\fB\[ti]\fR).
.TP
.BR \-C\ \fIdirectory ", " \-\-backupdir= \fIdirectory
Make and keep not just one backup file, but make and keep a uniquely
numbered one every time a file is saved -- when backups are enabled (\fB\-B\fR).
The uniquely numbered files are stored in the specified \fIdirectory\fR.
.BI \-C " directory\fR, " \-\-backupdir= directory
Make and keep not just one backup file, but make and keep a uniquely numbered
one every time a file is saved \[em] when backups are enabled (\fB\-B\fR).
The uniquely numbered files are stored in the specified \fI\%directory\fR.
.TP
.BR \-D ", " \-\-boldtext
For the interface, use bold instead of reverse video. This will be overridden
by setting the options \fBtitlecolor\fP, \fBstatuscolor\fP, \fBkeycolor\fP,
\fBfunctioncolor\fP, \fBnumbercolor\fP, and/or \fBselectedcolor\fP in your
nanorc file. See \fBnanorc\fR(5).
For the interface, use bold instead of reverse video.
This can be overridden for specific elements by setting the options
\fB\%titlecolor\fR, \fB\%statuscolor\fR, \fB\%promptcolor\fR,
\fB\%minicolor\fR, \fB\%keycolor\fR, \fB\%numbercolor\fR, and/or
\fB\%selectedcolor\fR in your \fInanorc\fR file. See \fBnanorc\fR(5).
.TP
.BR \-E ", " \-\-tabstospaces
Convert each typed tab to spaces -- to the number of spaces
Convert each typed tab to spaces \[em] to the number of spaces
that a tab at that position would take up.
(Note: pasted tabs are not converted.)
.TP
.BR \-F ", " \-\-multibuffer
.BR \-F ", " \-\-newbuffer
Read a file into a new buffer by default.
(The old form of this option, \fB\-\-\%multibuffer\fR, is deprecated.)
.TP
.BR \-G ", " \-\-locking
Use vim-style file locking when editing files.
@@ -134,17 +166,17 @@ executed commands, so they can be easily reused in later sessions.
.BR \-I ", " \-\-ignorercfiles
Don't look at the system's \fInanorc\fR nor at the user's \fInanorc\fR.
.TP
.BR \-J\ \fInumber ", " \-\-guidestripe= \fInumber
.BI \-J " number\fR, " \-\-guidestripe= number
Draw a vertical stripe at the given column, to help judge the width of the
text. (The color of the stripe can be changed with \fBset stripecolor\fR
text. (The color of the stripe can be changed with \fBset \%stripecolor\fR
in your \fInanorc\fR file.)
.TP
.BR \-K ", " \-\-rawsequences
Interpret escape sequences directly, instead of asking \fBncurses\fR
Interpret escape sequences directly, instead of asking \fI\%ncurses\fR
to translate them. (If you need this option to get some keys to work
properly, it means that the terminfo terminal description that is used
does not fully match the actual behavior of your terminal. This can
happen when you ssh into a BSD machine, for example.)
properly, it means that the \fI\%terminfo\fR terminal description that
is used does not fully match the actual behavior of your terminal.
This can happen when you ssh into a BSD machine, for example.)
Using this option disables \fBnano\fR's mouse support.
.TP
.BR \-L ", " \-\-nonewlines
@@ -156,7 +188,7 @@ Snip trailing whitespace from the wrapped line when automatic
hard-wrapping occurs or when text is justified.
.TP
.BR \-N ", " \-\-noconvert
Disable automatic conversion of files from DOS/Mac format.
Disable automatic conversion of files from DOS format.
.TP
.BR \-O ", " \-\-bookstyle
When justifying, treat any line that starts with whitespace as the
@@ -165,38 +197,49 @@ beginning of a paragraph (unless auto-indenting is on).
.BR \-P ", " \-\-positionlog
For the 200 most recent files, log the last position of the cursor,
and place it at that position again upon reopening such a file.
Also save and restore the positions of any anchors.
.TP
.BR "\-Q ""\fIregex\fB""" ", " "\-\-quotestr=""" \fIregex """
.BI "\-Q """ regex\fB"\fR, " \-\-quotestr=""" regex """"
Set the regular expression for matching the quoting part of a line.
The default value is "\fB^([\ \\t]*([!#%:;>|}]|//))+\fR".
(Note that \fB\\t\fP stands for an actual Tab.)
(Note that \fB\\t\fR stands for an actual Tab.)
This makes it possible to rejustify blocks of quoted text when composing
email, and to rewrap blocks of line comments when writing source code.
.TP
.BR \-R ", " \-\-restricted
Restricted mode: don't read or write to any file not specified on the
command line. This means: don't read or write history files;
don't allow suspending; don't allow spell checking;
don't allow a file to be appended to, prepended to, or saved under a
different name if it already has one; and don't make backup files.
Restricted mode can also be activated by invoking \fBnano\fP
with any name beginning with 'r' (e.g. "rnano").
Read and write only the \fIfile\fR (or files) specified on the command line.
This means: don't read or write the history files; don't allow suspending;
don't allow spell checking; don't allow executing any command in the shell;
don't allow the current buffer to be saved under a different name; don't
allow appending or prepending to any file; and don't make backup files.
.sp
As an exception, before the specified file or files, the \fInanorc\fR files
are read, to allow customization. If customization should not be allowed,
use option \fB\-I\fR (\fB\-\-\%ignorercfiles\fR) as well.
.sp
When no \fIfile\fR is specified on the command line, restricted mode
allows you to save the contents that you type into the new buffer
under any name, except that existing files may not be overwritten.
If the places where this new file may be created should be limited,
then use option \fB\-o\fR (\fB\-\-\%operatingdir\fR) as well.
.sp
Restricted mode can also be activated by invoking \fBnano\fR
with a name beginning with 'r' (for example: \fBrnano\fR).
.TP
.BR \-S ", " \-\-softwrap
Display over multiple screen rows lines that exceed the screen's width.
(You can make this soft-wrapping occur at whitespace instead of rudely at
the screen's edge, by using also \fB\-\-atblanks\fR.)
(The old short option, \fB\-$\fR, is deprecated.)
the screen's edge, by using also \fB\-\-\%atblanks\fR.)
.TP
.BR \-T\ \fInumber ", " \-\-tabsize= \fInumber
Set the size (width) of a tab to \fInumber\fP columns. The value of
\fInumber\fR must be greater than 0. The default value is \fB8\fR.
.BI \-T " number\fR, " \-\-tabsize= number
Set the size (width) of a tab to \fI\%number\fR columns. The value of
\fI\%number\fR must be greater than 0. The default value is \fB8\fR.
.TP
.BR \-U ", " \-\-quickblank
Make status-bar messages disappear after 1 keystroke instead of after 20.
Note that option \fB\-c\fR (\fB\-\-constantshow\fR) overrides this.
When option \fB\-\-minibar\fR or \fB\-\-zero\fR is in effect,
\fB\-\-quickblank\fR makes a message disappear after
Note that option \fB\-c\fR (\fB\-\-\%constantshow\fR) overrides this.
When option \fB\-\-\%minibar\fR or \fB\-\-\%zero\fR is in effect,
\fB\-\-\%quickblank\fR makes a message disappear after
0.8 seconds instead of after the default 1.5 seconds.
.
.TP
@@ -207,14 +250,14 @@ Show the current version number and exit.
Detect word boundaries differently by treating punctuation
characters as part of a word.
.TP
.BR "\-X ""\fIcharacters\fB""" ", " "\-\-wordchars=""" \fIcharacters """
.BI "\-X """ characters\fB"\fR, " \-\-wordchars=""" characters """"
Specify which other characters (besides the normal alphanumeric ones)
should be considered as part of a word. When using this option, you
probably want to omit \fB\-W\fR (\fB\-\-wordbounds\fR).
probably want to omit \fB\-W\fR (\fB\-\-\%wordbounds\fR).
.TP
.BR \-Y\ \fIname ", " \-\-syntax= \fIname
.BI \-Y " name\fR, " \-\-syntax= name
Specify the name of the syntax highlighting to use from among the ones
defined in the \fInanorc\fP files.
defined in the \fInanorc\fR files.
.TP
.BR \-Z ", " \-\-zap
Let an unmodified Backspace or Delete erase the marked region
@@ -225,13 +268,16 @@ When doing soft line wrapping, wrap lines at whitespace
instead of always at the edge of the screen.
.TP
.BR \-b ", " \-\-breaklonglines
Automatically hard-wrap the current line when it becomes overlong.
(This option is the opposite of \fB\-w\fR (\fB\-\-nowrap\fR) --
Automatically hard-wrap the current line when it becomes overlong,
that is: when it becomes wider than the value given with \fB\-r\fR
(\fB\-\-fill\fR). The default value for \fB\-r\fR is the terminal's
width minus eight.
(This option is the opposite of \fB\-w\fR (\fB\-\-\%nowrap\fR) \[em]
the last one given takes effect.)
.TP
.BR \-c ", " \-\-constantshow
Constantly show the cursor position on the status bar.
Note that this overrides option \fB\-U\fR (\fB\-\-quickblank\fR).
Constantly report the cursor position on the status bar.
Note that this overrides option \fB\-U\fR (\fB\-\-\%quickblank\fR).
.TP
.BR \-d ", " \-\-rebinddelete
Interpret the Delete and Backspace keys differently so that both Backspace
@@ -241,9 +287,9 @@ system either Backspace acts like Delete or Delete acts like Backspace.
.BR \-e ", " \-\-emptyline
Do not use the line below the title bar, leaving it entirely blank.
.TP
.BR \-f\ \fIfile ", " \-\-rcfile= \fIfile
Read only this \fIfile\fR for setting nano's options, instead of reading
both the system-wide and the user's nanorc files.
.BI \-f " file\fR, " \-\-rcfile= file
Read only this \fIfile\fR for setting \fBnano\fR's options, instead of reading
both the system-wide and the user's \fInanorc\fR files.
.TP
.BR \-g ", " \-\-showcursor
Make the cursor visible in the file browser (putting it on the
@@ -272,59 +318,59 @@ Display line numbers to the left of the text area.
.BR \-m ", " \-\-mouse
Enable mouse support, if available for your system. When enabled, mouse
clicks can be used to place the cursor, set the mark (with a double
click), and execute shortcuts. The mouse will work in the X Window
click), and execute shortcuts. The mouse works in the X Window
System, and on the console when gpm is running. Text can still be
selected through dragging by holding down the Shift key.
.TP
.BR \-n ", " \-\-noread
Treat any name given on the command line as a new file. This allows
\fBnano\fR to write to named pipes: it will start with a blank buffer,
and will write to the pipe when the user saves the "file". This way
\fBnano\fR to write to named pipes: it starts with a blank buffer,
and writes to the pipe when the user saves the \[lq]file\[rq]. This way
\fBnano\fR can be used as an editor in combination with for instance
\fBgpg\fR without having to write sensitive data to disk first.
.TP
.BR \-o\ \fIdirectory ", " \-\-operatingdir= \fIdirectory
Set the operating directory. This makes \fBnano\fP set up something
similar to a chroot.
.BI \-o " directory\fR, " \-\-operatingdir= directory
Change to the given \fI\%directory\fR, and allow reading and writing
files only in this directory and its subdirectories.
.TP
.BR \-p ", " \-\-preserve
Preserve the XON and XOFF sequences (\fB^Q\fR and \fB^S\fR) so they
will be caught by the terminal.
Preserve the XOFF and XON sequences (\fB^S\fR and \fB^Q\fR) so that
they are caught by the terminal (stopping and resuming the output).
Note that option \fB\-/\fR (\fB\-\-\%modernbindings\fR) overrides this.
.TP
.BR \-q ", " \-\-indicator
Display a "scrollbar" on the righthand side of the edit window.
Display a \[lq]scrollbar\[rq] on the righthand side of the edit window.
It shows the position of the viewport in the buffer
and how much of the buffer is covered by the viewport.
.TP
.BR \-r\ \fInumber ", " \-\-fill= \fInumber
.BI \-r " number\fR, " \-\-fill= number
Set the target width for justifying and automatic hard-wrapping at this
\fInumber\fR of columns. If the value is 0 or less, wrapping will occur
at the width of the screen minus \fInumber\fR columns, allowing the wrap
\fI\%number\fR of columns. If the value is 0 or less, wrapping occurs
at the width of the screen minus \fI\%number\fR columns, allowing the wrap
point to vary along with the width of the screen if the screen is resized.
The default value is \fB\-8\fR.
.TP
.B "\-s ""\fIprogram\fR [\fIargument \fR...]\fB""\fR, \fB\-\-speller=""\fIprogram\fR [\fIargument \fR...]\fB"""
Use this command to perform spell checking and correcting, instead of
using the built-in corrector that calls \fBhunspell\fR(1) or \fBspell\fR(1).
using the built-in corrector that calls \fB\%hunspell\fR(1) or \fBspell\fR(1).
.TP
.BR \-t ", " \-\-saveonexit
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
.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 \fBnano\fR's
default behavior of saving a file in the format that it had.
(This option has no effect when you also use \fB\-\-noconvert\fR.)
(This option has no effect when you also use \fB\-\-\%noconvert\fR.)
.TP
.BR \-v ", " \-\-view
Just view the file and disallow editing: read-only mode.
This mode allows the user to open also other files for viewing,
unless \fB\-\-restricted\fR is given too.
unless \fB\-\-\%restricted\fR is given too.
.TP
.BR \-w ", " \-\-nowrap
Do not automatically hard-wrap the current line when it becomes overlong.
This is the default. (This option is the opposite of \fB\-b\fR
(\fB\-\-breaklonglines\fR) -- the last one given takes effect.)
(\fB\-\-\%breaklonglines\fR) \[em] the last one given takes effect.)
.TP
.BR \-x ", " \-\-nohelp
Don't show the two help lines at the bottom of the screen.
@@ -332,10 +378,22 @@ Don't show the two help lines at the bottom of the screen.
.BR \-y ", " \-\-afterends
Make Ctrl+Right and Ctrl+Delete stop at word ends instead of beginnings.
.TP
.BR \-z ", " \-\-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.)
.BR \-z ", " \-\-listsyntaxes
List the names of the available syntaxes and exit.
.TP
.BR \-! ", " \-\-magic
When neither the file's name nor its first line give a clue,
try using \fI\%libmagic\fR to determine the applicable syntax.
.TP
.BR \-@ ", " \-\-colonparsing
When a filename given on the command line ends in a colon plus digits
and this filename does not exist, then snip the colon plus digits and
understand the digits as a line number. If the trimmed filename does
not exist either, then repeat the process and understand the obtained
two numbers as line and column number. But if the doubly trimmed
filename does not exist either, then forget the trimming and accept
the original filename as is. To disable this colon parsing for some
file, use \fB+1\fR or similar before the relevant filename.
.TP
.BR \-% ", " \-\-stateflags
Use the top-right corner of the screen for showing some state flags:
@@ -348,31 +406,48 @@ filename in the center of the title bar.
.BR \-_ ", " \-\-minibar
Suppress the title bar and instead show information about
the current buffer at the bottom of the screen, in the space
for the status bar. In this "minibar" the filename is shown
for the status bar. In this \[lq]mini bar\[rq] the filename is shown
on the left, followed by an asterisk if the buffer has been modified.
On the right are displayed the current line and column number, the
code of the character under the cursor (in Unicode format: U+xxxx),
the same flags as are shown by \fB\-\-stateflags\fR, and a percentage
the same flags as are shown by \fB\-\-\%stateflags\fR, and a percentage
that expresses how far the cursor is into the file (linewise).
When a file is loaded or saved, and also when switching between buffers,
the number of lines in the buffer is displayed after the filename.
This number is cleared upon the next keystroke, or replaced with an
[i/n] counter when multiple buffers are open.
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.
The state flags are displayed only when \fB\-\-stateflags\fR is used.
\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.
.TP
.BR \-0 ", " \-\-zero
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.
The status bar appears only when there is a significant message,
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-X\fR the help lines.
With \fBM\-Z\fR the title bar plus status bar can be toggled.
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.
.BR \-1 ", " \-\-solosidescroll
When the cursor approaches the right edge of the edit window, scroll only the
current line sideways by a large amount, instead of scrolling all visible lines
sideways by just the amount needed to keep the cursor in view.
This latter whole-window smooth sideways scrolling is the new default behavior.
The single-line jerky sideways scrolling enabled by this option was the old
behavior \[em] the only behavior that \fBnano\fR knew.
.TP
.BR \-/ ", " \-\-modernbindings
Use key bindings similar to the ones that most modern programs use:
\fB^X\fR cuts, \fB^C\fR copies, \fB^V\fR pastes,
\fB^Z\fR undoes, \fB^Y\fR redoes,
\fB^F\fR searches forward, \fB^G\fR searches next,
\fB^S\fR saves, \fB^O\fR opens a file, \fB^Q\fR quits,
and (when the terminal permits) \fB^H\fR shows help.
Furthermore, \fB^A\fR sets the mark, \fB^B\fR searches backward,
\fB^D\fR searches previous, \fB^R\fR makes replacements,
\fB^P\fR shows the position, \fB^T\fR goes to a line,
\fB^W\fR writes out a file, and \fB^E\fR executes a command.
Note that this option overrides option \fB\-p\fR (\fB\-\-\%preserve\fR).
.SH TOGGLES
Several of the above options can be switched on and off also while
@@ -387,32 +462,61 @@ the help viewer and the linter. All other toggles work in
the main menu only.
.SH FILES
When \fB\-\-rcfile\fR is given, \fBnano\fR will read just the specified file
for setting its options and syntaxes and key bindings. Without that option,
\fBnano\fR will read two configuration files: first the system's
When \fB\-\-\%rcfile\fR is given, \fBnano\fR reads just the specified file
for setting its options and syntaxes and key bindings. Without that
option, \fBnano\fR reads two configuration files: first the system's
\fInanorc\fR (if it exists), and then the user's \fInanorc\fR (if it
exists), either \fI~/.nanorc\fR or \fI$XDG_CONFIG_HOME/nano/nanorc\fR
or \fI~/.config/nano/nanorc\fR, whichever is encountered first. See
exists), either \fI\%\[ti]/.nanorc\fR or \fI\%$XDG_CONFIG_HOME/\:nano/\:nanorc\fR
or \fI\%\[ti]/.config/\:nano/\:nanorc\fR, whichever is encountered first. See
.BR nanorc (5)
for more information on the possible contents of those files.
.sp
See \fI/usr/share/nano/\fR and \fI/usr/share/nano/extra/\fR
See \fI/usr/\:share/\:nano/\fR and \fI/usr/\:share/\:nano/\:extra/\fR
for available syntax-coloring definitions.
.SH EXIT STATUS
.TP
.B 0
The editor finished normally.
.TP
.B 1
An invalid option or option argument was given.
.TP
.B 2
The last open buffer was discarded (with \fB^O^Q\fR or \fB^X^Q\fR).
.SH NOTES
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
\fBSPELL\fP environment variable for one.
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 \fInanorc\fR.)
.sp
In some cases \fBnano\fP will try to dump the buffer into an emergency
file. This will happen mainly if \fBnano\fP receives a SIGHUP or
SIGTERM or runs out of memory. It will write the buffer into a file
named \fInano.save\fP if the buffer didn't have a name already, or will
add a ".save" suffix to the current filename. If an emergency file with
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
it unique. In multibuffer mode, \fBnano\fP will write all the open
buffers to their respective emergency files.
At a Yes-No prompt, \fB^Y\fR can be used for "Yes", \fB^N\fR for "No",
and \fB^A\fR for "All".
(And when exiting, \fB^Q\fR can be used for "Quit with error".)
These unlisted bindings work in any locale.
.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
line nor in one of the \fInanorc\fR files, \fBnano\fR checks the
\fBSPELL\fR environment variable for one.
.sp
In some cases \fBnano\fR tries to dump the buffer into an emergency file.
This happens mainly if \fBnano\fR receives a SIGHUP or SIGTERM or runs out
of memory. It writes the buffer into a file named \fI\%nano.save\fR if the
buffer didn't have a name already, or adds a ".save" suffix to the current
filename. If an emergency file with that name already exists in the
current directory, it adds ".save" plus a number (for example: ".save.1") to
the current filename in order to make it unique. When multiple buffers are
open, \fBnano\fR writes each modified buffer to its respective emergency file.
.sp
The complete manual is maintained in Texinfo format.
You can read it with \fBinfo nano\fR, or at
.IR https://nano\-editor.org/dist/latest/nano.html .
.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
The recording and playback of keyboard macros works correctly only on a
@@ -423,7 +527,7 @@ Please report any other bugs that you encounter via:
.br
.IR https://savannah.gnu.org/bugs/?group=nano .
.sp
When nano crashes, it will save any modified buffers to emergency .save files.
When \fBnano\fR crashes, it saves any modified buffers to emergency \fI.save\fR files.
If you are able to reproduce the crash and you want to get a backtrace, define
the environment variable \fBNANO_NOCATCH\fR.
@@ -433,4 +537,4 @@ the environment variable \fBNANO_NOCATCH\fR.
.SH SEE ALSO
.BR nanorc (5)
.sp
\fI/usr/share/doc/nano/\fP (or equivalent on your system)
\fI/usr/share/doc/nano/\fR (or equivalent on your system)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
.\" Copyright (C) 2002-2007, 2014-2021 Free Software Foundation, Inc.
.\" Copyright (C) 2002-2007, 2014-2026 Free Software Foundation, Inc.
.\"
.\" This document is dual-licensed. You may distribute and/or modify it
.\" under the terms of either of the following licenses:
@@ -16,31 +16,48 @@
.\" Documentation License along with this program. If not, see
.\" <https://www.gnu.org/licenses/>.
.\"
.TH RNANO 1 "version 6.0" "December 2021"
.TH RNANO 1 "July 2026" "GNU nano 9.2"
.SH NAME
rnano \- a restricted nano
.SH SYNOPSIS
.B rnano
.RI [ options "] [[+" line [, column "]]\ " file "]..."
.RI [ options "] [[\fB+" line [\fB, column "]] " file ]...
.SH DESCRIPTION
\fBrnano\fR runs the \fBnano\fR editor in restricted mode. This allows
editing only the specified file or files, and doesn't allow the user
access to the filesystem nor to a command shell.
editing only the \fIfile\fR (or files) specified on the command line.
.sp
In restricted mode, \fBnano\fR will:
.RS 4
.IP \[bu] 2
not make backups;
.IP \[bu]
not read nor write the history files;
.IP \[bu]
not allow suspending;
.IP \[bu]
not allow spell checking;
.IP \[bu]
not allow running any command in the shell;
.IP \[bu]
not allow saving the current buffer under a different name;
.IP \[bu]
not allow inserting another file or opening a new buffer;
.IP \[bu]
not allow appending or prepending to any file;
.IP \[bu]
not make backup files nor do spell checking.
not allow appending or prepending to any file.
.RE
.sp
As an exception, before the specified file or files, the \fInanorc\fR files
are read, to allow customization. If customization should not be allowed,
use option \fB\-I\fR (\fB\-\-ignorercfiles\fR) as well.
.sp
When no \fIfile\fR is specified on the command line, the user may save
the contents that they type into the new buffer under any name, except
that existing files may not be overwritten. If the places where this
new file may be created should be limited, then additionally use the
option \fB\-o\fR (\fB\-\-operatingdir\fR).
.SH OPTIONS
.TP

View File

@@ -8,6 +8,16 @@
## Inside string parameters, quotes should not be escaped -- the last
## double quote on the line will be seen as the closing quote.
## If you want ^F, ^B, M-F and M-B to do what they did before version 8.0:
# bind ^F forward main
# bind ^B back main
# bind M-F formatter main
# bind M-B linter main
## Make M-< and M-> switch between buffers, as they did before version 9.0:
# bind M-< prevbuf main
# bind M-> nextbuf main
## Make 'nextword' (Ctrl+Right) and 'chopwordright' (Ctrl+Delete)
## stop at word ends instead of at beginnings.
# set afterends
@@ -44,7 +54,11 @@
## Do case-sensitive searches by default.
# set casesensitive
## Constantly display the cursor position in the status bar or minibar.
## Interpret digits after a colon after a filename (on the command line)
## as the line number to go to in that file.
# set colonparsing
## Constantly report the cursor position, in the status bar or minibar.
# set constantshow
## Use cut-from-cursor-to-end-of-line by default.
@@ -58,7 +72,11 @@
## will be the terminal's width minus this number.
# set fill -8
## Remember the used search/replace strings for the next session.
## 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/command strings for the next session.
# set historylog
## Display a "scrollbar" on the righthand side of the edit window.
@@ -70,9 +88,8 @@
## Display line numbers to the left (and any anchors in the margin).
# set linenumbers
## Enable vim-style lock-files. This is just to let a vim user know you
## are editing a file [s]he is trying to edit and vice versa. There are
## no plans to implement vim-style undo state in these files.
## Let other users (of nano or vim) know that you are editing the file
## they are trying to edit, and the other way around.
# set locking
## Fall back to slow libmagic to try and determine an applicable syntax.
@@ -88,16 +105,15 @@
# set minibar
## Enable mouse support, if available for your system. When enabled,
## mouse clicks can be used to place the cursor, set the mark (with a
## double click), and execute shortcuts. The mouse will work in the
## mouse clicks can be used to place the cursor, set the mark (with
## two clicks), and execute shortcuts. The mouse will work in the
## X Window System, and on the console when gpm is running.
# set mouse
## Switch on multiple file buffers (inserting a file will put it into
## a separate buffer).
# set multibuffer
## With ^R, insert a file into a separate buffer by default.
# set newbuffer
## Don't convert files from DOS/Mac format.
## Don't convert files from DOS format.
# set noconvert
## Don't display the helpful shortcut lists at the bottom of the screen.
@@ -112,14 +128,14 @@
## string means the operating-directory feature is turned off.
# set operatingdir ""
## Remember the cursor position in each file for the next editing session.
## Remember the position of cursor and anchors for the next editing session.
# set positionlog
## Preserve the XON and XOFF keys (^Q and ^S).
# set preserve
## The characters treated as closing punctuation when justifying paragraphs.
## This may not contain blank characters. Only these closing punctuations,
## This may not contain blank characters. Only these terminating characters,
## optionally followed by closing brackets, can end sentences.
# set punct "!.?"
@@ -142,7 +158,6 @@
## Save a changed buffer automatically on exit; don't prompt.
# set saveonexit
## (The old form of this option, 'set tempfile', is deprecated.)
## 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
@@ -159,6 +174,9 @@
## Spread overlong lines over multiple screen lines.
# set softwrap
## Scroll only the current line sideways (instead of all lines).
# set solosidescroll
## Use this spelling checker instead of the internal one. This option
## does not have a default value.
# set speller "aspell -x -c"
@@ -176,6 +194,9 @@
## Snip whitespace at the end of lines when justifying or hard-wrapping.
# set trimblanks
## Save files always in Unix format (also when they were DOS).
# set unix
## 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
## ISO-8859-1 (0000B7 in Unicode) seem to be good values for these.
@@ -208,9 +229,9 @@
# set statuscolor bold,white,green
# set errorcolor bold,white,red
# set spotlightcolor black,lightyellow
# set selectedcolor lightwhite,magenta
# set stripecolor ,yellow
# set scrollercolor cyan
# set selectedcolor lightwhite,#804
# set stripecolor ,#444
# set scrollercolor slate,#222
# set numbercolor cyan
# set keycolor cyan
# set functioncolor green
@@ -233,12 +254,12 @@
## For all details, see 'man nanorc', section SYNTAX HIGHLIGHTING.
## To include most of the existing syntax definitions, you can do:
# include "@PKGDATADIR@/*.nanorc"
# include @PKGDATADIR@/*.nanorc
## Or you can select just the ones you need. For example:
# include "@PKGDATADIR@/html.nanorc"
# include "@PKGDATADIR@/python.nanorc"
# include "@PKGDATADIR@/sh.nanorc"
# include @PKGDATADIR@/html.nanorc
# include @PKGDATADIR@/python.nanorc
# include @PKGDATADIR@/sh.nanorc
## In @PKGDATADIR@/extra/ you can find some syntaxes that are
## specific for certain distros or for some less common languages.
@@ -248,9 +269,6 @@
## independent of the settings of 'tabsize' and 'tabstospaces':
# extendsyntax python tabgives " "
## If <Tab> should always produce an actual TAB when editing a Makefile:
# extendsyntax makefile tabgives " "
## === Key bindings ===
## For all details, see 'man nanorc', section REBINDING KEYS.
@@ -278,44 +296,58 @@
# unbind M-T main
## (Those functions are still accessible through ^T^J and ^T^V.)
## For quickly uppercasing or lowercasing the word under the cursor.
## (These effectively do a Ctrl+Right followed by a Shift+Ctrl+Left,
## and then pipe the selected text through a sed command.)
# bind Sh-M-U "Oc|sed 's/.*/\U&/'
" main
## For quickly uppercasing or lowercasing the word that the cursor is on.
## (These effectively select a word and pipe it through a sed command.)
# bind Sh-M-U "{nextword}{mark}{prevword}{execute}| sed 's/.*/\U&/' {enter}" main
# bind Sh-M-L "{nextword}{mark}{prevword}{execute}| sed 's/.*/\L&/' {enter}" main
## Two ways of copying a marked region to the system clipboard:
# bind Sh-M-C "{execute}| xsel -ib {enter}{undo}" main
# bind Sh-M-P "{execute}| xclip -select clipboard 1>&- 2>&- {enter}{undo}" main
## For copying text to the local clipboard via OSC 52 (if terminal supports it):
# bind M-* "{execute}|| printf "\033]52;c;%s\007" "$(base64 | tr -d '\n')" {enter}{undo}" main
## For normalizing Unicode to precomposed characters:
# bind Sh-M-N "{execute}| uconv -x nfc {enter}" main
## For wiping all anchors in a buffer:
# bind Sh-M-W "{execute}| cat {enter}" 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",
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
## then uncomment these:
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
## then uncomment these:
#bind ^Q exit all
#bind ^S savefile main
#bind ^W writeout main
#bind ^O insert main
#bind ^H help all
#bind ^H exit help
#bind ^F whereis all
#bind ^G findnext all
#bind ^B wherewas all
#bind ^D findprevious all
#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 ^N main
#unbind ^Y all
#unbind M-J main
#unbind M-T main
#bind ^T gotoline main
#bind ^T gotodir browser
#bind ^T cutrestoffile execute
#bind ^L linter execute
#bind M-U undo main
#bind M-R redo main
#bind ^Z undo main
# bind ^X cut main
# bind ^C copy main
# bind ^V paste all
# bind ^Q exit all
# bind ^S savefile main
# bind ^W writeout main
# bind ^O insert main
# set newbuffer
# bind ^H help all
# bind ^H exit help
# bind ^F whereis all
# bind ^G findnext all
# bind ^B wherewas all
# bind ^D findprevious all
# bind ^R replace main
# unbind ^U all
# unbind ^N main
# unbind ^Y all
# unbind M-J main
# unbind M-T main
# bind ^A mark main
# bind ^P location main
# bind ^T gotoline main
# bind ^T gotodir browser
# bind ^T cutrestoffile execute
# bind ^L linter execute
# bind ^E execute main
# bind ^K "{mark}{end}{zap}" main
# bind ^U "{mark}{home}{zap}" main
# bind ^Z undo main
# bind ^Y redo main

View File

@@ -31,6 +31,5 @@ EXTRA_DIST = \
threadlib.m4 \
uintmax_t.m4 \
visibility.m4 \
wchar_t.m4 \
wint_t.m4 \
xsize.m4

View File

@@ -1,2 +1,2 @@
# 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
ar bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ka kk ko ms nb nl pl pt pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_TW

View File

@@ -7,6 +7,7 @@ src/files.c
src/global.c
src/help.c
src/history.c
src/move.c
src/nano.c
src/prompt.c
src/rcfile.c

3175
po/ar.po Normal file

File diff suppressed because it is too large Load Diff

2063
po/bg.po

File diff suppressed because it is too large Load Diff

1793
po/ca.po

File diff suppressed because it is too large Load Diff

1958
po/cs.po

File diff suppressed because it is too large Load Diff

2026
po/da.po

File diff suppressed because it is too large Load Diff

1829
po/de.po

File diff suppressed because it is too large Load Diff

1881
po/eo.po

File diff suppressed because it is too large Load Diff

1926
po/es.po

File diff suppressed because it is too large Load Diff

1989
po/eu.po

File diff suppressed because it is too large Load Diff

2077
po/fi.po

File diff suppressed because it is too large Load Diff

1898
po/fr.po

File diff suppressed because it is too large Load Diff

1892
po/ga.po

File diff suppressed because it is too large Load Diff

1911
po/gl.po

File diff suppressed because it is too large Load Diff

3116
po/hr.po

File diff suppressed because it is too large Load Diff

1956
po/hu.po

File diff suppressed because it is too large Load Diff

1963
po/id.po

File diff suppressed because it is too large Load Diff

2040
po/is.po

File diff suppressed because it is too large Load Diff

2348
po/it.po

File diff suppressed because it is too large Load Diff

1826
po/ja.po

File diff suppressed because it is too large Load Diff

2998
po/ka.po Normal file

File diff suppressed because it is too large Load Diff

3146
po/kk.po Normal file

File diff suppressed because it is too large Load Diff

1898
po/ko.po

File diff suppressed because it is too large Load Diff

2285
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1879
po/nb.po

File diff suppressed because it is too large Load Diff

1909
po/nl.po

File diff suppressed because it is too large Load Diff

1893
po/pl.po

File diff suppressed because it is too large Load Diff

1990
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1859
po/ro.po

File diff suppressed because it is too large Load Diff

1887
po/ru.po

File diff suppressed because it is too large Load Diff

1936
po/sk.po

File diff suppressed because it is too large Load Diff

2168
po/sl.po

File diff suppressed because it is too large Load Diff

3169
po/sq.po Normal file

File diff suppressed because it is too large Load Diff

1891
po/sr.po

File diff suppressed because it is too large Load Diff

1841
po/sv.po

File diff suppressed because it is too large Load Diff

1923
po/tr.po

File diff suppressed because it is too large Load Diff

1896
po/uk.po

File diff suppressed because it is too large Load Diff

2206
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#!/bin/bash
VERSION="6.0"
VERSION="9.2"
./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.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 &&
scp doc/nano.pdf bens@wh0rd.org:nano.pdf &&

View File

@@ -16,7 +16,8 @@ winio.o: revision.h
# only when the revision actually changed.
revision.h: FORCE
@[ -f $@ ] || touch $@
@echo "#define $(SOMETHING)" | cmp -s $@ - || \
@! git describe >/dev/null 2>&1 || \
echo "#define $(SOMETHING)" | cmp -s $@ - || \
echo "#define $(SOMETHING)" > $@
FORCE:
@@ -29,6 +30,7 @@ nano_SOURCES = \
color.c \
cut.c \
files.c \
folding.c \
global.c \
help.c \
history.c \
@@ -41,8 +43,8 @@ nano_SOURCES = \
utils.c \
winio.c
nano_LDADD = @LIBINTL@ $(top_builddir)/lib/libgnu.a \
$(LIB_CLOCK_GETTIME) $(LIBTHREAD)
nano_LDADD = $(top_builddir)/lib/libgnu.a @LIBINTL@ \
$(GETRANDOM_LIB) $(CLOCK_TIME_LIB) $(LIBTHREAD)
install-exec-hook:
cd $(DESTDIR)$(bindir) && rm -f rnano && $(LN_S) nano rnano

View File

@@ -1,8 +1,8 @@
/**************************************************************************
* browser.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2015-2016, 2020 Benno Schulenberg *
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2015, 2016, 2020, 2022, 2025 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -34,45 +34,43 @@ static size_t list_length = 0;
/* The number of files in the list. */
static size_t usable_rows = 0;
/* 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. */
static size_t longest = 0;
/* The number of columns in the longest filename in the list. */
static int gauge = 0;
/* The width of a 'pile' -- the widest filename plus ten. */
static size_t selected = 0;
/* The currently selected filename in the list; zero-based. */
/* Set filelist to the list of files contained in the directory path,
* set list_length to the number of files in that list, set longest to
* the width in columns of the longest filename in that list (between 15
* and COLS), and set piles to the number of files that we can display
* per screen row. And sort the list too. */
/* Fill 'filelist' with the names of the files in the given directory, set
* 'list_length' to the number of names in that list, set 'gauge' to the
* width of the widest filename plus ten, and set 'piles' to the number of
* files that can be displayed per screen row. And sort the list too. */
void read_the_list(const char *path, DIR *dir)
{
size_t path_len = strlen(path), index = 0;
const struct dirent *nextdir;
size_t path_len = strlen(path);
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. */
while ((nextdir = readdir(dir)) != NULL) {
size_t name_len = breadth(nextdir->d_name);
if (name_len > longest)
longest = name_len;
if (span > widest)
widest = span;
index++;
}
/* Put 10 characters' worth of blank space between columns of filenames
* in the list whenever possible, as Pico does. */
longest += 10;
/* Reserve ten columns for blanks plus file size. */
gauge = widest + 10;
/* If needed, make room for ".. (parent dir)". */
if (longest < 15)
longest = 15;
if (gauge < 15)
gauge = 15;
/* Make sure we're not wider than the window. */
if (longest > COLS)
longest = COLS;
if (gauge > COLS)
gauge = COLS;
rewinddir(dir);
@@ -83,20 +81,19 @@ void read_the_list(const char *path, DIR *dir)
filelist = nmalloc(list_length * sizeof(char *));
while ((nextdir = readdir(dir)) != NULL && index < list_length) {
/* Don't show the "." entry. */
if (strcmp(nextdir->d_name, ".") == 0)
while ((entry = readdir(dir)) != NULL && index < list_length) {
/* Don't show the useless dot item. */
if (strcmp(entry->d_name, ".") == 0)
continue;
filelist[index] = nmalloc(path_len + strlen(nextdir->d_name) + 1);
sprintf(filelist[index], "%s%s", path, nextdir->d_name);
filelist[index] = nmalloc(path_len + strlen(entry->d_name) + 1);
sprintf(filelist[index], "%s%s", path, entry->d_name);
index++;
}
/* Maybe the number of files in the directory decreased between the
* first time we scanned and the second time. index is the actual
* length of the file list, so record it. */
/* Maybe the number of files in the directory decreased between
* the first time we scanned and the second time. */
list_length = index;
/* 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
* spaces beyond the right edge, and adding two spaces of padding
* between columns. */
piles = (COLS + 2) / (longest + 2);
piles = (COLS + 2) / (gauge + 2);
usable_rows = editwinrows - (ISSET(ZERO) && LINES > 1 ? 1 : 0);
}
/* Look for needle. If we find it, set selected to its location.
* Note that needle must be an exact match for a file in the list. */
void browser_select_dirname(const char *needle)
/* Reselect the given file or directory name, if it still exists. */
void reselect(const char *name)
{
size_t looking_at = 0;
for (; looking_at < list_length; looking_at++) {
if (strcmp(filelist[looking_at], needle) == 0) {
selected = looking_at;
break;
}
}
while (looking_at < list_length && strcmp(filelist[looking_at], name) != 0)
looking_at++;
/* If the sought name isn't found, move the highlight so that the
* changed selection will be noticed. */
if (looking_at == list_length) {
/* If the sought name was found, select it; otherwise, just move
* the highlight so that the changed selection will be noticed,
* 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;
/* 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. */
@@ -158,11 +150,11 @@ void browser_refresh(void)
size_t infomaxlen = 7;
/* The maximum length of the file information in columns:
* 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
* waste space on dots when there are fewer than 15 columns. */
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.
* When a fragment, account for dots plus one space padding. */
struct stat state;
@@ -170,31 +162,31 @@ void browser_refresh(void)
/* If this is the selected item, draw its highlighted bar upfront, and
* remember its location to be able to place the cursor on it. */
if (index == selected) {
wattron(edit, interface_color_pair[SELECTED_TEXT]);
mvwprintw(edit, row, col, "%*s", longest, " ");
wattron(midwin, interface_color_pair[SELECTED_TEXT]);
mvwprintw(midwin, row, col, "%*s", gauge, " ");
the_row = row;
the_column = col;
}
/* If the name is too long, we display something like "...ename". */
if (dots)
mvwaddstr(edit, row, col, "...");
mvwaddstr(edit, row, dots ? col + 3 : col, disp);
mvwaddstr(midwin, row, col, "...");
mvwaddstr(midwin, row, dots ? col + 3 : col, disp);
col += longest;
col += gauge;
/* Show information about the file: "--" for symlinks (except when
* they point to a directory) and for files that have disappeared,
* "(dir)" for directories, and the file size for normal files. */
if (lstat(filelist[index], &state) == -1 || S_ISLNK(state.st_mode)) {
if (stat(filelist[index], &state) == -1 || !S_ISDIR(state.st_mode))
if (lstat(filelist[index], &state) < 0 || S_ISLNK(state.st_mode)) {
if (stat(filelist[index], &state) < 0 || !S_ISDIR(state.st_mode))
info = copy_of("--");
else
/* TRANSLATORS: Try to keep this at most 7 characters. */
/* TRANSLATORS: Anything more than 7 cells gets clipped. */
info = copy_of(_("(dir)"));
} else if (S_ISDIR(state.st_mode)) {
if (strcmp(thename, "..") == 0) {
/* TRANSLATORS: Try to keep this at most 12 characters. */
/* TRANSLATORS: Anything more than 12 cells gets clipped. */
info = copy_of(_("(parent dir)"));
infomaxlen = 12;
} else
@@ -223,7 +215,7 @@ void browser_refresh(void)
if (result < (1 << 10))
sprintf(info, "%4ju %cB", (intmax_t)result, modifier);
else
/* TRANSLATORS: Try to keep this at most 7 characters.
/* TRANSLATORS: Anything more than 7 cells gets clipped.
* If necessary, you can leave out the parentheses. */
info = mallocstrcpy(info, _("(huge)"));
}
@@ -235,11 +227,11 @@ void browser_refresh(void)
infolen = infomaxlen;
}
mvwaddstr(edit, row, col - infolen, info);
mvwaddstr(midwin, row, col - infolen, info);
/* If this is the selected item, finish its highlighting. */
if (index == selected)
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
wattroff(midwin, interface_color_pair[SELECTED_TEXT]);
free(disp);
free(info);
@@ -247,8 +239,8 @@ void browser_refresh(void)
/* Add some space between the columns. */
col += 2;
/* If the next entry will not fit on this row, move to next row. */
if (col > COLS - longest) {
/* If the next item will not fit on this row, move to next row. */
if (col > COLS - gauge) {
row++;
col = 0;
}
@@ -256,70 +248,46 @@ void browser_refresh(void)
/* If requested, put the cursor on the selected item and switch it on. */
if (ISSET(SHOW_CURSOR)) {
wmove(edit, the_row, the_column);
wmove(midwin, the_row, the_column);
curs_set(1);
}
wnoutrefresh(edit);
wnoutrefresh(midwin);
}
/* Look for the given needle in the list of files. If forwards is TRUE,
* search forward in the list; otherwise, search backward. */
/* Look for the given needle in the list of files, forwards or backwards. */
void findfile(const char *needle, bool forwards)
{
size_t looking_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. */
size_t began_at = selected;
/* Save the settings of all flags. */
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
/* Iterate through the list of filenames, until a match is found or
* we've come back to the point where we started. */
while (TRUE) {
if (forwards) {
if (looking_at++ == list_length - 1) {
looking_at = 0;
if (selected++ == list_length - 1) {
selected = 0;
statusbar(_("Search Wrapped"));
}
} else {
if (looking_at-- == 0) {
looking_at = list_length - 1;
if (selected-- == 0) {
selected = list_length - 1;
statusbar(_("Search Wrapped"));
}
}
/* Get the bare filename, without the path. */
thename = tail(filelist[looking_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)
/* When the needle occurs in the basename of the file, we have a match. */
if (mbstrcasestr(tail(filelist[selected]), needle)) {
if (selected == began_at)
statusbar(_("This is the only occurrence"));
break;
return;
}
/* If we're back at the beginning and didn't find any match... */
if (looking_at == selected) {
/* When we're back at the starting point without any match... */
if (selected == began_at) {
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.
@@ -330,7 +298,7 @@ void search_filename(bool forwards)
int response;
/* If something was searched for before, show it between square brackets. */
if (*last_search != '\0') {
if (*last_search) {
char *disp = display_string(last_search, 0, COLS / 3, FALSE, FALSE);
thedefault = nmalloc(strlen(disp) + 7);
@@ -356,7 +324,7 @@ void search_filename(bool forwards)
}
/* If the user typed an answer, remember it. */
if (*answer != '\0') {
if (*answer) {
last_search = mallocstrcpy(last_search, answer);
#ifdef ENABLE_HISTORIES
update_history(&search_history, answer, PRUNE_DUPLICATE);
@@ -373,7 +341,7 @@ void research_filename(bool forwards)
{
#ifdef ENABLE_HISTORIES
/* If nothing was searched for yet, take the last item from history. */
if (*last_search == '\0' && searchbot->prev != NULL)
if (*last_search == '\0' && searchbot->prev)
last_search = mallocstrcpy(last_search, searchbot->prev->data);
#endif
@@ -385,13 +353,13 @@ void research_filename(bool forwards)
}
}
/* Select the first file in the list -- called by ^W^Y. */
/* Select the first file in the list -- called directly by ^W^Y. */
void to_first_file(void)
{
selected = 0;
}
/* Select the last file in the list -- called by ^W^V. */
/* Select the last file in the list -- called directly by ^W^V. */
void to_last_file(void)
{
selected = list_length - 1;
@@ -404,7 +372,7 @@ char *strip_last_component(const char *path)
char *copy = copy_of(path);
char *last_slash = strrchr(copy, '/');
if (last_slash != NULL)
if (last_slash)
*last_slash = '\0';
return copy;
@@ -419,7 +387,7 @@ char *browse(char *path)
* were in before backing up to "..". */
size_t old_selected;
/* The number of the selected file before the current selected file. */
DIR *dir;
DIR *dir = NULL;
/* The directory whose contents we are showing. */
char *chosen = NULL;
/* The name of the file that the user picked, or NULL if none. */
@@ -429,7 +397,7 @@ char *browse(char *path)
path = free_and_assign(path, get_full_path(path));
if (path != NULL)
if (path)
dir = opendir(path);
if (path == NULL || dir == NULL) {
@@ -446,20 +414,23 @@ char *browse(char *path)
present_name = mallocstrcpy(present_name, filelist[selected]);
}
if (dir != NULL) {
/* Get the file list, and set longest and piles in the process. */
if (dir) {
/* Get the file list, and set gauge and piles in the process. */
read_the_list(path, dir);
closedir(dir);
dir = NULL;
}
/* If given, reselect the present_name and then discard it. */
if (present_name != NULL) {
browser_select_dirname(present_name);
#ifndef NANO_TINY
resized_for_browser = FALSE;
#endif
/* If something was selected before, reselect it;
* otherwise, just select the first item (..). */
if (present_name) {
reselect(present_name);
free(present_name);
present_name = NULL;
/* Otherwise, select the first file or directory in the list. */
} else
selected = 0;
@@ -469,8 +440,11 @@ char *browse(char *path)
titlebar(path);
while (TRUE) {
functionptrtype func;
if (list_length == 0) {
statusline(ALERT, _("No entries"));
napms(1200);
} else while (TRUE) {
functionptrtype function;
int kbinput;
lastmessage = VACUUM;
@@ -484,20 +458,20 @@ char *browse(char *path)
old_selected = selected;
kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR));
kbinput = get_kbinput(midwin, ISSET(SHOW_CURSOR));
#ifdef ENABLE_MOUSE
if (kbinput == KEY_MOUSE) {
int mouse_x, mouse_y;
/* When the user clicked in the file list, select a filename. */
if (get_mouseinput(&mouse_y, &mouse_x, TRUE) == 0 &&
wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
if (get_mouseinput(&mouse_y, &mouse_x) == 0 &&
wmouse_trafo(midwin, &mouse_y, &mouse_x, FALSE)) {
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. */
if (mouse_x > piles * (longest + 2))
if (mouse_x > piles * (gauge + 2))
selected--;
/* When beyond end-of-list, select the last filename. */
@@ -513,74 +487,65 @@ char *browse(char *path)
continue;
}
#endif /* ENABLE_MOUSE */
#ifndef NANO_TINY
if (bracketed_paste || kbinput == BRACKETED_PASTE_MARKER) {
beep();
continue;
}
#endif
func = interpret(&kbinput);
if (func == full_refresh) {
full_refresh();
#ifndef NANO_TINY
/* Simulate a terminal resize to force a directory reread. */
kbinput = KEY_WINCH;
#endif
} else if (func == do_help) {
function = interpret(kbinput);
if (function == 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) {
else if (function == full_refresh) {
#ifdef NANO_TINY
full_refresh();
#else
kbinput = THE_WINDOW_RESIZED;
} else if (function == do_toggle && get_shortcut(kbinput)->toggle == NO_HELP) {
TOGGLE(NO_HELP);
window_init();
kbinput = KEY_WINCH;
kbinput = THE_WINDOW_RESIZED;
#endif
} else if (func == do_search_backward) {
} else if (function == do_search_backward) {
search_filename(BACKWARD);
} else if (func == do_search_forward) {
} else if (function == do_search_forward) {
search_filename(FORWARD);
} else if (func == do_findprevious) {
} else if (function == do_findprevious) {
research_filename(BACKWARD);
} else if (func == do_findnext) {
} else if (function == do_findnext) {
research_filename(FORWARD);
} else if (func == do_left) {
} else if (function == do_left) {
if (selected > 0)
selected--;
} else if (func == do_right) {
} else if (function == do_right) {
if (selected < list_length - 1)
selected++;
} else if (func == to_prev_word) {
} else if (function == to_prev_word) {
selected -= (selected % piles);
} else if (func == to_next_word) {
} else if (function == to_next_word) {
selected += piles - 1 - (selected % piles);
if (selected >= list_length)
selected = list_length - 1;
} else if (func == do_up) {
} else if (function == do_up) {
if (selected >= piles)
selected -= piles;
} else if (func == do_down) {
} else if (function == do_down) {
if (selected + piles <= list_length - 1)
selected += piles;
} else if (func == to_prev_block) {
} else if (function == to_prev_block) {
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
selected % piles;
} else if (func == to_next_block) {
} else if (function == to_next_block) {
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
selected % piles + usable_rows * piles - piles;
if (selected >= list_length)
selected = (list_length / piles) * piles + selected % piles;
if (selected >= list_length)
selected -= piles;
} else if (func == do_page_up) {
} else if (function == do_page_up) {
if (selected < piles)
selected = 0;
else if (selected < usable_rows * piles)
selected = selected % piles;
else
selected -= usable_rows * piles;
} else if (func == do_page_down) {
} else if (function == do_page_down) {
if (selected + piles >= list_length - 1)
selected = list_length - 1;
else if (selected + usable_rows * piles >= list_length)
@@ -588,35 +553,32 @@ char *browse(char *path)
list_length - piles;
else
selected += usable_rows * piles;
} else if (func == to_first_file) {
selected = 0;
} else if (func == to_last_file) {
selected = list_length - 1;
} else if (func == goto_dir) {
} else if (function == to_first_file || function == to_last_file) {
function();
} else if (function == goto_dir) {
/* Ask for the directory to go to. */
if (do_prompt(MGOTODIR, "", NULL,
/* TRANSLATORS: This is a prompt. */
browser_refresh, _("Go To Directory")) < 0) {
statusbar(_("Cancelled"));
continue;
goto testresize;
}
path = free_and_assign(path, real_dir_from_tilde(answer));
path = free_and_assign(path, expand_leading_tilde(answer));
/* If the given path is relative, join it with the current path. */
if (*path != '/') {
path = nrealloc(path, strlen(present_path) +
strlen(answer) + 1);
path = nrealloc(path, strlen(present_path) + strlen(answer) + 1);
sprintf(path, "%s%s", present_path, answer);
}
#ifdef ENABLE_OPERATINGDIR
if (outside_of_confinement(path, FALSE)) {
if (operating_dir && outside_of_confinement(path, FALSE)) {
/* TRANSLATORS: This refers to the confining effect of
* the option --operatingdir, not of --restricted. */
statusline(ALERT, _("Can't go outside of %s"), operating_dir);
path = mallocstrcpy(path, present_path);
continue;
goto testresize;
}
#endif
/* Snip any trailing slashes, so the name can be compared. */
@@ -631,7 +593,7 @@ char *browse(char *path)
/* Try opening and reading the specified directory. */
goto read_directory_contents;
} else if (func == do_enter) {
} else if (function == do_enter) {
struct stat st;
/* It isn't possible to move up from the root directory. */
@@ -644,13 +606,13 @@ char *browse(char *path)
/* Note: The selected file can be outside the operating
* directory if it's ".." or if it's a symlink to a
* directory outside the operating directory. */
if (outside_of_confinement(filelist[selected], FALSE)) {
if (operating_dir && outside_of_confinement(filelist[selected], FALSE)) {
statusline(ALERT, _("Can't go outside of %s"), operating_dir);
continue;
}
#endif
/* If for some reason the file is inaccessible, complain. */
if (stat(filelist[selected], &st) == -1) {
if (stat(filelist[selected], &st) < 0) {
statusline(ALERT, _("Error reading %s: %s"),
filelist[selected], strerror(errno));
continue;
@@ -671,21 +633,26 @@ char *browse(char *path)
path = mallocstrcpy(path, filelist[selected]);
goto read_directory_contents;
#ifdef ENABLE_NANORC
} else if (func == (functionptrtype)implant) {
implant(first_sc_for(MBROWSER, func)->expansion);
} else if (function == (functionptrtype)implant) {
implant(first_sc_for(MBROWSER, function)->expansion);
#endif
#ifndef NANO_TINY
} else if (kbinput == KEY_WINCH) {
} else if (kbinput == START_OF_PASTE) {
while (get_kbinput(midwin, BLIND) != END_OF_PASTE)
;
statusline(AHEM, _("Paste is ignored"));
} else if (kbinput == THE_WINDOW_RESIZED) {
; /* Gets handled below. */
#endif
} else if (func == do_exit) {
} else if (function == do_exit) {
break;
} else
unbound_key(kbinput);
testresize:
#ifndef NANO_TINY
/* If the terminal resized (or might have), refresh the file list. */
if (kbinput == KEY_WINCH) {
if (kbinput == THE_WINDOW_RESIZED || resized_for_browser) {
/* Remember the selected file, to be able to reselect it. */
present_name = copy_of(filelist[selected]);
goto read_directory_contents;
@@ -709,23 +676,19 @@ char *browse(char *path)
* start browsing in that directory, otherwise in the current directory. */
char *browse_in(const char *inpath)
{
char *path = real_dir_from_tilde(inpath);
char *path = expand_leading_tilde(inpath);
struct stat fileinfo;
/* If path is not a directory, try to strip a filename from it; if then
* still not a directory, use the current working directory instead. */
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
if (stat(path, &fileinfo) < 0 || !S_ISDIR(fileinfo.st_mode)) {
path = free_and_assign(path, strip_last_component(path));
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
char *currentdir = nmalloc(PATH_MAX + 1);
path = free_and_assign(path, getcwd(currentdir, PATH_MAX + 1));
if (stat(path, &fileinfo) < 0 || !S_ISDIR(fileinfo.st_mode)) {
path = free_and_assign(path, realpath(".", NULL));
if (path == NULL) {
statusline(MILD, _("The working directory has disappeared"));
free(currentdir);
beep();
statusline(ALERT, _("The working directory has disappeared"));
napms(1200);
return NULL;
}
@@ -733,9 +696,9 @@ char *browse_in(const char *inpath)
}
#ifdef ENABLE_OPERATINGDIR
/* If the resulting path isn't in the operating directory, use
* the operating directory instead. */
if (outside_of_confinement(path, FALSE))
/* If the resulting path isn't in the operating directory,
* use the operating directory instead. */
if (operating_dir && outside_of_confinement(path, FALSE))
path = mallocstrcpy(path, operating_dir);
#endif

View File

@@ -1,7 +1,7 @@
/**************************************************************************
* chars.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2016-2021 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -23,26 +23,10 @@
#include <ctype.h>
#include <string.h>
#ifdef ENABLE_UTF8
#include <wchar.h>
#include <wctype.h>
static bool use_utf8 = FALSE;
/* Whether we've enabled UTF-8 support. */
/* Enable UTF-8 support. */
void utf8_init(void)
{
use_utf8 = TRUE;
}
/* Is UTF-8 support enabled? */
bool using_utf8(void)
{
return use_utf8;
}
#endif /* ENABLE_UTF8 */
#endif
#ifdef ENABLE_SPELLER
/* Return TRUE when the given character is some kind of letter. */
@@ -98,12 +82,12 @@ bool is_blank_char(const char *c)
bool is_cntrl_char(const char *c)
{
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8)
return ((c[0] & 0xE0) == 0 || c[0] == DEL_CODE ||
((signed char)c[0] == -62 && (signed char)c[1] < -96));
} else
#endif
return ((*c & 0x60) == 0 || *c == DEL_CODE);
return ((*c & 0x60) == 0 || *c == DEL_CODE);
}
/* Return TRUE when the given character is a punctuation character. */
@@ -134,14 +118,15 @@ bool is_word_char(const char *c, bool allow_punct)
if (allow_punct && is_punct_char(c))
return TRUE;
if (word_chars != NULL && *word_chars != '\0') {
if (word_chars && *word_chars) {
char symbol[MAXCHARLEN + 1];
int symlen = collect_char(c, symbol);
symbol[symlen] = '\0';
return (strstr(word_chars, symbol) != NULL);
} else
return FALSE;
}
return FALSE;
}
/* Return the visible representation of control character c. */
@@ -153,8 +138,8 @@ char control_rep(const signed char c)
return '=';
else if (c < 0)
return c + 224;
else
return c + 64;
return c + 64;
}
/* Return the visible representation of multibyte control character c. */
@@ -165,14 +150,15 @@ char control_mbrep(const char *c, bool isdata)
return '@';
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8) {
if ((unsigned char)c[0] < 128)
return control_rep(c[0]);
else
return control_rep(c[1]);
} else
}
#endif
return control_rep(*c);
return control_rep(*c);
}
#ifdef ENABLE_UTF8
@@ -180,9 +166,9 @@ char control_mbrep(const char *c, bool isdata)
* the number of bytes in the sequence, or -1 for an invalid sequence. */
int mbtowide(wchar_t *wc, const char *c)
{
if ((signed char)*c < 0 && use_utf8) {
unsigned char v1 = (unsigned char)c[0];
unsigned char v2 = (unsigned char)c[1] ^ 0x80;
if ((signed char)*c < 0 && using_utf8) {
unsigned char v1 = c[0];
unsigned char v2 = c[1] ^ 0x80;
if (v2 > 0x3F || v1 < 0xC2)
return -1;
@@ -192,7 +178,7 @@ int mbtowide(wchar_t *wc, const char *c)
return 2;
}
unsigned char v3 = (unsigned char)c[2] ^ 0x80;
unsigned char v3 = c[2] ^ 0x80;
if (v3 > 0x3F)
return -1;
@@ -206,7 +192,7 @@ int mbtowide(wchar_t *wc, const char *c)
return -1;
}
unsigned char v4 = (unsigned char)c[3] ^ 0x80;
unsigned char v4 = c[3] ^ 0x80;
if (v4 > 0x3F || v1 > 0xF4)
return -1;
@@ -229,7 +215,7 @@ bool is_doublewidth(const char *ch)
wchar_t wc;
/* Only from U+1100 can code points have double width. */
if ((unsigned char)*ch < 0xE1 || !use_utf8)
if ((unsigned char)*ch < 0xE1 || !using_utf8)
return FALSE;
if (mbtowide(&wc, ch) < 0)
@@ -244,7 +230,7 @@ bool is_zerowidth(const char *ch)
wchar_t wc;
/* Only from U+0300 can code points have zero width. */
if ((unsigned char)*ch < 0xCC || !use_utf8)
if ((unsigned char)*ch < 0xCC || !using_utf8)
return FALSE;
if (mbtowide(&wc, ch) < 0)
@@ -264,9 +250,9 @@ bool is_zerowidth(const char *ch)
int char_length(const char *pointer)
{
#ifdef ENABLE_UTF8
if ((unsigned char)*pointer > 0xC1 && use_utf8) {
unsigned char c1 = (unsigned char)pointer[0];
unsigned char c2 = (unsigned char)pointer[1];
if ((unsigned char)*pointer > 0xC1 && using_utf8) {
unsigned char c1 = pointer[0];
unsigned char c2 = pointer[1];
if ((c2 ^ 0x80) > 0x3F)
return 1;
@@ -294,7 +280,8 @@ int char_length(const char *pointer)
return 4;
}
#endif
return 1;
return 1;
}
/* Return the number of (multibyte) characters in the given string. */
@@ -302,7 +289,7 @@ size_t mbstrlen(const char *pointer)
{
size_t count = 0;
while (*pointer != '\0') {
while (*pointer) {
pointer += char_length(pointer);
count++;
}
@@ -327,7 +314,7 @@ int collect_char(const char *string, char *thechar)
int advance_over(const char *string, size_t *column)
{
#ifdef ENABLE_UTF8
if ((signed char)*string < 0 && use_utf8) {
if ((signed char)*string < 0 && using_utf8) {
/* A UTF-8 upper control code has two bytes and takes two columns. */
if (((unsigned char)string[0] == 0xC2 && (signed char)string[1] < -96)) {
*column += 2;
@@ -371,7 +358,7 @@ int advance_over(const char *string, size_t *column)
size_t step_left(const char *buf, size_t pos)
{
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8) {
size_t before, charlen = 0;
if (pos < 4)
@@ -400,9 +387,10 @@ size_t step_left(const char *buf, size_t pos)
}
return before - charlen;
} else
}
#endif
return (pos == 0 ? 0 : pos - 1);
return (pos == 0 ? 0 : pos - 1);
}
/* Return the index in buf of the beginning of the multibyte character
@@ -422,10 +410,10 @@ int mbstrcasecmp(const char *s1, const char *s2)
int mbstrncasecmp(const char *s1, const char *s2, size_t n)
{
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8) {
wchar_t wc1, wc2;
while (*s1 != '\0' && *s2 != '\0' && n > 0) {
while (*s1 && *s2 && n > 0) {
if ((signed char)*s1 >= 0 && (signed char)*s2 >= 0) {
if ('A' <= (*s1 & 0x5F) && (*s1 & 0x5F) <= 'Z') {
if ('A' <= (*s2 & 0x5F) && (*s2 & 0x5F) <= 'Z') {
@@ -464,19 +452,20 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
}
return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0;
} else
}
#endif
return strncasecmp(s1, s2, n);
return strncasecmp(s1, s2, n);
}
/* This function is equivalent to strcasestr() for multibyte strings. */
char *mbstrcasestr(const char *haystack, const char *needle)
{
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8) {
size_t needle_len = mbstrlen(needle);
while (*haystack != '\0') {
while (*haystack) {
if (mbstrncasecmp(haystack, needle, needle_len) == 0)
return (char *)haystack;
@@ -484,9 +473,10 @@ char *mbstrcasestr(const char *haystack, const char *needle)
}
return NULL;
} else
}
#endif
return (char *)strcasestr(haystack, needle);
return (char *)strcasestr(haystack, needle);
}
/* This function is equivalent to strstr(), except in that it scans the
@@ -535,7 +525,7 @@ char *mbrevstrcasestr(const char *haystack, const char *needle,
const char *pointer)
{
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8) {
size_t needle_len = mbstrlen(needle);
size_t tail_len = mbstrlen(pointer);
@@ -554,17 +544,18 @@ char *mbrevstrcasestr(const char *haystack, const char *needle,
pointer = haystack + step_left(haystack, pointer - haystack);
}
} else
}
#endif
return revstrcasestr(haystack, needle, pointer);
return revstrcasestr(haystack, needle, pointer);
}
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
/* This function is equivalent to strchr() for multibyte strings. */
char *mbstrchr(const char *string, const char *chr)
const char *mbstrchr(const char *string, const char *chr)
{
#ifdef ENABLE_UTF8
if (use_utf8) {
if (using_utf8) {
bool bad_s = FALSE, bad_c = FALSE;
wchar_t ws, wc;
@@ -573,7 +564,7 @@ char *mbstrchr(const char *string, const char *chr)
bad_c = TRUE;
}
while (*string != '\0') {
while (*string) {
int symlen = mbtowide(&ws, string);
if (symlen < 0) {
@@ -591,9 +582,10 @@ char *mbstrchr(const char *string, const char *chr)
return NULL;
return (char *)string;
} else
}
#endif
return strchr(string, *chr);
return strchr(string, *chr);
}
#endif /* !NANO_TINY || ENABLE_JUSTIFY */
@@ -602,8 +594,8 @@ char *mbstrchr(const char *string, const char *chr)
* the characters in accept, searching forward. */
char *mbstrpbrk(const char *string, const char *accept)
{
while (*string != '\0') {
if (mbstrchr(accept, string) != NULL)
while (*string) {
if (mbstrchr(accept, string))
return (char *)string;
string += char_length(string);
@@ -623,7 +615,7 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer)
}
while (TRUE) {
if (mbstrchr(accept, pointer) != NULL)
if (mbstrchr(accept, pointer))
return (char *)pointer;
/* If we've reached the head of the string, we found nothing. */
@@ -639,7 +631,7 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer)
/* Return TRUE if the given string contains at least one blank character. */
bool has_blank_char(const char *string)
{
while (*string != '\0' && !is_blank_char(string))
while (*string && !is_blank_char(string))
string += char_length(string);
return *string;
@@ -649,8 +641,17 @@ bool has_blank_char(const char *string)
/* Return TRUE when the given string is empty or consists of only blanks. */
bool white_string(const char *string)
{
while (*string != '\0' && (is_blank_char(string) || *string == '\r'))
while (*string && (is_blank_char(string) || *string == '\r'))
string += char_length(string);
return !*string;
}
#if defined(ENABLE_SPELLER) || defined(ENABLE_COLOR)
/* Remove leading whitespace from the given string. */
void strip_leading_blanks_from(char *string)
{
while (string && (*string == ' ' || *string == '\t'))
memmove(string, string + 1, strlen(string));
}
#endif

View File

@@ -1,7 +1,7 @@
/**************************************************************************
* color.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2014-2017, 2020, 2021 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -44,7 +44,7 @@ void set_interface_colorpairs(void)
for (size_t index = 0; index < NUMBER_OF_ELEMENTS; index++) {
colortype *combo = color_combo[index];
if (combo != NULL) {
if (combo) {
if (!defaults_allowed) {
if (combo->fg == THE_DEFAULT)
combo->fg = COLOR_WHITE;
@@ -53,6 +53,7 @@ void set_interface_colorpairs(void)
}
init_pair(index + 1, combo->fg, combo->bg);
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
rescind_colors = FALSE;
} else {
if (index == FUNCTION_TAG || index == SCROLL_BAR)
interface_color_pair[index] = A_NORMAL;
@@ -66,12 +67,24 @@ void set_interface_colorpairs(void)
else if (index == ERROR_MESSAGE) {
init_pair(index + 1, COLOR_WHITE, COLOR_RED);
interface_color_pair[index] = COLOR_PAIR(index + 1) | A_BOLD;
} else
} else if (index == FOLDED_LINE) {
if (COLORS > 15)
init_pair(index + 1, COLOR_BLACK + 8, COLOR_BLACK);
else
init_pair(index + 1, COLOR_WHITE, COLOR_BLACK);
interface_color_pair[index] = COLOR_PAIR(index + 1);
} else {
interface_color_pair[index] = hilite_attribute;
}
}
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
@@ -137,7 +150,7 @@ void find_and_prime_applicable_syntax(void)
return;
/* If we specified a syntax-override string, use it. */
if (syntaxstr != NULL) {
if (syntaxstr) {
/* An override of "none" is like having no syntax at all. */
if (strcmp(syntaxstr, "none") == 0)
return;
@@ -197,7 +210,7 @@ void find_and_prime_applicable_syntax(void)
}
/* Now try and find a syntax that matches the magic string. */
if (magicstring != NULL) {
if (magicstring) {
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
if (found_in_list(sntx->magics, magicstring))
break;
@@ -216,7 +229,7 @@ void find_and_prime_applicable_syntax(void)
}
/* When the syntax isn't loaded yet, parse it and initialize its colors. */
if (sntx != NULL && sntx->filename != NULL) {
if (sntx && sntx->filename) {
parse_one_include(sntx->filename, sntx);
set_syntax_colorpairs(sntx);
}
@@ -234,7 +247,7 @@ void check_the_multis(linestruct *line)
char *afterstart;
/* If there is no syntax or no multiline regex, there is nothing to do. */
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
if (!openfile->syntax || openfile->syntax->multiscore == 0)
return;
if (line->multidata == NULL) {
@@ -255,12 +268,13 @@ void check_the_multis(linestruct *line)
if (line->multidata[ink->id] == NOTHING) {
if (!astart)
continue;
} else if (line->multidata[ink->id] & (WHOLELINE|WOULDBE)) {
if (!astart && !anend)
} else if (line->multidata[ink->id] == WHOLELINE) {
/* 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;
} else if (line->multidata[ink->id] == JUSTONTHIS) {
if (astart && anend && regexec(ink->start, line->data + endmatch.rm_eo,
1, &startmatch, 0) != 0)
if (astart && anend && regexec(ink->start, line->data + startmatch.rm_eo +
endmatch.rm_eo, 1, &startmatch, 0) != 0)
continue;
} else if (line->multidata[ink->id] == STARTSHERE) {
if (astart && !anend)
@@ -272,6 +286,7 @@ void check_the_multis(linestruct *line)
/* There is a mismatch, so something changed: repaint. */
refresh_needed = TRUE;
perturbed = TRUE;
return;
}
}
@@ -284,7 +299,7 @@ void precalc_multicolorinfo(void)
regmatch_t startmatch, endmatch;
linestruct *line, *tailline;
if (!openfile->syntax || openfile->syntax->nmultis == 0 || ISSET(NO_SYNTAX))
if (!openfile->syntax || openfile->syntax->multiscore == 0 || ISSET(NO_SYNTAX))
return;
//#define TIMEPRECALC 123
@@ -296,7 +311,7 @@ void precalc_multicolorinfo(void)
/* For each line, allocate cache space for the multiline-regex info. */
for (line = openfile->filetop; line != NULL; line = line->next)
if (!line->multidata)
line->multidata = nmalloc(openfile->syntax->nmultis * sizeof(short));
line->multidata = nmalloc(openfile->syntax->multiscore * sizeof(short));
for (ink = openfile->syntax->color; ink != NULL; ink = ink->next) {
/* If this is not a multi-line regex, skip it. */
@@ -338,25 +353,20 @@ void precalc_multicolorinfo(void)
/* Look for an end match on later lines. */
tailline = line->next;
while (tailline && regexec(ink->end, tailline->data,
1, &endmatch, 0) != 0)
while (tailline && regexec(ink->end, tailline->data, 1, &endmatch, 0) != 0)
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;
// Note that this also advances the line in the main loop.
for (line = line->next; line != tailline; line = line->next)
line->multidata[ink->id] = WHOLELINE;
if (tailline == NULL) {
line = openfile->filebot;
break;
}
tailline->multidata[ink->id] = ENDSHERE;
/* Look for a possible new start after the end match. */
@@ -366,7 +376,7 @@ void precalc_multicolorinfo(void)
}
#ifdef TIMEPRECALC
statusline(INFO, "Precalculation: %.1f ms", 1000 * (double)(clock() - start) / CLOCKS_PER_SEC);
statusline(NOTICE, "Precalculation: %.1f ms", 1000 * (double)(clock() - start) / CLOCKS_PER_SEC);
napms(1200);
#endif
}

128
src/cut.c
View File

@@ -1,7 +1,7 @@
/**************************************************************************
* cut.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2014 Mark Majeres *
* Copyright (C) 2016, 2018-2020 Benno Schulenberg *
* *
@@ -16,7 +16,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -24,13 +24,14 @@
#include <string.h>
/* Delete the character under the cursor. */
void do_deletion(undo_type action)
/* Delete the character at the current position, and
* add or update an undo item for the given action. */
void expunge(undo_type action)
{
openfile->placewewant = xplustabs();
/* When in the middle of a line, delete the current character. */
if (openfile->current->data[openfile->current_x] != '\0') {
if (openfile->current->data[openfile->current_x]) {
int charlen = char_length(openfile->current->data + openfile->current_x);
size_t line_len = strlen(openfile->current->data + openfile->current_x);
#ifndef NANO_TINY
@@ -48,23 +49,28 @@ void do_deletion(undo_type action)
memmove(&openfile->current->data[openfile->current_x],
&openfile->current->data[openfile->current_x + charlen],
line_len - charlen + 1);
UNFOLD_SEGMENT(openfile->current);
#ifndef NANO_TINY
/* When softwrapping, a changed number of chunks requires a refresh. */
if (ISSET(SOFTWRAP) && extra_chunks_in(openfile->current) != old_amount)
refresh_needed = TRUE;
/* When panning, and we have come near edge of the viewport... */
else if (united_sidescroll && openfile->placewewant < openfile->brink + CUSHION)
refresh_needed = TRUE;
/* Adjust the mark if it is after the cursor on the current line. */
if (openfile->mark == openfile->current &&
openfile->mark_x > openfile->current_x)
if (openfile->mark == openfile->current && openfile->mark_x > openfile->current_x)
openfile->mark_x -= charlen;
#endif
/* Otherwise, when not at end of buffer, join this line with the next. */
} else if (openfile->current != openfile->filebot) {
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 (joining == openfile->filebot && openfile->current_x != 0 &&
!ISSET(NO_NEWLINES)) {
if (joining == openfile->filebot && openfile->current_x != 0 && !ISSET(NO_NEWLINES)) {
#ifndef NANO_TINY
if (action == BACK)
add_undo(BACK, NULL);
@@ -97,6 +103,13 @@ void do_deletion(undo_type action)
/* We're at the end-of-file: nothing to do. */
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. */
openfile->totsize--;
#ifndef NANO_TINY
@@ -105,7 +118,8 @@ void do_deletion(undo_type action)
set_modified();
}
/* Delete the character under the cursor. */
/* Delete the character under the cursor plus any succeeding zero-widths,
* or, when the mark is on and --zap is active, delete the marked region. */
void do_delete(void)
{
#ifndef NANO_TINY
@@ -114,17 +128,18 @@ void do_delete(void)
else
#endif
{
do_deletion(DEL);
expunge(DEL);
#ifdef ENABLE_UTF8
while (openfile->current->data[openfile->current_x] != '\0' &&
while (openfile->current->data[openfile->current_x] &&
is_zerowidth(openfile->current->data + openfile->current_x))
do_deletion(DEL);
expunge(DEL);
#endif
}
}
/* Backspace over one character. That is, move the cursor left one
* character, and then delete the character under the cursor. */
* character, and then delete the character under the cursor. Or,
* when mark is on and --zap is active, delete the marked region. */
void do_backspace(void)
{
#ifndef NANO_TINY
@@ -134,10 +149,16 @@ void do_backspace(void)
#endif
if (openfile->current_x > 0) {
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
do_deletion(BACK);
expunge(BACK);
} else if (openfile->current != openfile->filetop) {
do_left();
do_deletion(BACK);
#ifdef ENABLE_FOLDING
if (openfile->current->prev->folded) {
openfile->current = openfile->current->prev;
openfile->current_x = strlen(openfile->current->data);
} else
#endif
do_left();
expunge(BACK);
}
}
@@ -173,8 +194,8 @@ bool is_cuttable(bool test_cliff)
void chop_word(bool forward)
{
/* Remember the current cursor position. */
linestruct *is_current = openfile->current;
size_t is_current_x = openfile->current_x;
linestruct *was_current = openfile->current;
size_t was_x = openfile->current_x;
/* Remember where the cutbuffer is, then make it seem blank. */
linestruct *is_cutbuffer = cutbuffer;
@@ -185,30 +206,30 @@ void chop_word(bool forward)
* on the edge of the original line, then put the cursor on that
* edge instead, so that lines will not be joined unexpectedly. */
if (!forward) {
do_prev_word();
if (openfile->current != is_current) {
if (is_current_x > 0) {
openfile->current = is_current;
do_prev_word(ALLOW_FOLDED);
if (openfile->current != was_current) {
if (was_x > 0) {
openfile->current = was_current;
openfile->current_x = 0;
} else
openfile->current_x = strlen(openfile->current->data);
}
} else {
do_next_word(ISSET(AFTER_ENDS));
if (openfile->current != is_current &&
is_current->data[is_current_x] != '\0') {
openfile->current = is_current;
openfile->current_x = strlen(is_current->data);
do_next_word(ISSET(AFTER_ENDS), ALLOW_FOLDED);
if (openfile->current != was_current && was_current->data[was_x]) {
openfile->current = was_current;
openfile->current_x = strlen(was_current->data);
}
}
UNFOLD_SEGMENT(openfile->current);
/* Set the mark at the start of that word. */
openfile->mark = openfile->current;
openfile->mark_x = openfile->current_x;
/* Put the cursor back where it was, so an undo will put it there too. */
openfile->current = is_current;
openfile->current_x = is_current_x;
openfile->current = was_current;
openfile->current_x = was_x;
/* Now kill the marked region and a word is gone. */
add_undo(CUT, NULL);
@@ -255,9 +276,13 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
if (top == bot && top_x == bot_x)
return;
if (top != bot)
for (linestruct *line = top->next; line != bot->next; line = line->next)
if (top != bot) {
UNFOLD_SEGMENT(top);
for (linestruct *line = top->next; line != bot->next; line = line->next) {
UNFOLD_SEGMENT(line);
had_anchor |= line->has_anchor;
}
}
#endif
if (top == bot) {
@@ -325,7 +350,7 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
cutbottom->next = taken->next;
delete_node(taken);
if (cutbottom->next != NULL) {
if (cutbottom->next) {
cutbottom->next->prev = cutbottom;
cutbottom = last;
}
@@ -353,7 +378,7 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
}
/* If the text doesn't end with a newline, and it should, add one. */
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0])
new_magicline();
}
@@ -371,7 +396,9 @@ void ingraft_buffer(linestruct *topline)
#endif
linestruct *botline = topline;
while (botline->next != NULL)
UNFOLD_SEGMENT(line);
while (botline->next)
botline = botline->next;
/* Add the size of the text to be grafted to the buffer size. */
@@ -428,16 +455,26 @@ void ingraft_buffer(linestruct *topline)
renumber_from(line);
/* If the text doesn't end with a newline, and it should, add one. */
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0])
new_magicline();
}
/* Meld a copy of the given buffer into the current file buffer. */
void copy_from_buffer(linestruct *somebuffer)
{
#ifdef ENABLE_COLOR
size_t threshold = openfile->edittop->lineno + editwinrows - 1;
#endif
linestruct *the_copy = copy_buffer(somebuffer);
ingraft_buffer(the_copy);
#ifdef ENABLE_COLOR
if (openfile->current->lineno > threshold || ISSET(SOFTWRAP))
recook = TRUE;
else
perturbed = TRUE;
#endif
}
#ifndef NANO_TINY
@@ -485,7 +522,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
* the cutbuffer. Otherwise, when not at the end of the buffer,
* move just the "line separator" into the cutbuffer. */
if (openfile->current_x < strlen(openfile->current->data))
if (line->data[openfile->current_x])
extract_segment(line, openfile->current_x, line, strlen(line->data));
else if (openfile->current != openfile->filebot) {
extract_segment(line, openfile->current_x, line->next, 0);
@@ -509,6 +546,9 @@ void do_snip(bool marked, bool until_eof, bool append)
set_modified();
refresh_needed = TRUE;
#ifdef ENABLE_COLOR
perturbed = TRUE;
#endif
}
/* Move text from the current buffer into the cutbuffer. */
@@ -614,6 +654,7 @@ void copy_marked_region(void)
botline->data[bot_x] = saved_byte;
botline->next = afterline;
}
#endif /* !NANO_TINY */
/* Copy text from the current buffer into the cutbuffer. The text is either
* the marked region, the whole line, the text from cursor to end-of-line,
@@ -626,17 +667,24 @@ void copy_text(void)
linestruct *was_current = openfile->current;
linestruct *addition;
if (openfile->mark || openfile->last_action != COPY || !keep_cutbuffer) {
#ifndef NANO_TINY
if (openfile->mark || openfile->last_action != COPY)
keep_cutbuffer = FALSE;
#endif
if (!keep_cutbuffer) {
free_lines(cutbuffer);
cutbuffer = NULL;
}
wipe_statusbar();
#ifndef NANO_TINY
if (openfile->mark) {
copy_marked_region();
return;
}
#endif
/* When at the very end of the buffer, there is nothing to do. */
if (openfile->current->next == NULL && at_eol && (ISSET(CUT_FROM_CURSOR) ||
@@ -686,10 +734,11 @@ void copy_text(void)
edit_redraw(was_current, FLOWING);
#ifndef NANO_TINY
openfile->last_action = COPY;
#endif
keep_cutbuffer = TRUE;
}
#endif /* !NANO_TINY */
/* Copy text from the cutbuffer into the current buffer. */
void paste_text(void)
@@ -708,6 +757,7 @@ void paste_text(void)
statusline(AHEM, _("Cutbuffer is empty"));
return;
}
UNFOLD_SEGMENT(openfile->current);
#ifndef NANO_TINY
add_undo(PASTE, NULL);

View File

@@ -1,8 +1,8 @@
/**************************************************************************
* definitions.h -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2014-2017 Benno Schulenberg *
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2014-2017, 2020-2022, 2024 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -41,6 +41,11 @@
#define ROOT_UID 0
#endif
#if defined(__APPLE__) && !defined(st_atim)
#define st_atim st_atimespec
#define st_mtim st_mtimespec
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -60,10 +65,7 @@
#include <stdlib.h>
#include <sys/stat.h>
/* Prefer wide ncurses over normal ncurses over curses. */
#if defined(HAVE_NCURSESW_NCURSES_H)
#include <ncursesw/ncurses.h>
#elif defined(HAVE_NCURSES_H)
#ifdef HAVE_NCURSES_H
#include <ncurses.h>
#else
#include <curses.h>
@@ -108,6 +110,14 @@
#define BACKWARD FALSE
#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 VISIBLE TRUE
@@ -115,11 +125,6 @@
#define REPLACING 1
#define INREGION 2
#define NORMAL TRUE
#define SPECIAL FALSE
#define TEMPORARY FALSE
#define ANNOTATE TRUE
#define NONOTES FALSE
#define PRUNE_DUPLICATE TRUE
@@ -138,6 +143,9 @@
/* The default number of columns from end of line where wrapping occurs. */
#define COLUMNS_FROM_EOL 8
/* The number of columns the cursor should stay away from the edge. */
#define CUSHION 3
/* The default comment character when a syntax does not specify any. */
#define GENERAL_COMMENT_CHARACTER "#"
@@ -162,8 +170,6 @@
/* The start regex matches on an earlier line, the end regex on this one. */
#define JUSTONTHIS (1<<5)
/* 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
/* Basic control codes. */
@@ -189,6 +195,8 @@
#define ALT_RIGHT 0x422
#define ALT_UP 0x423
#define ALT_DOWN 0x424
#define ALT_HOME 0x425
#define ALT_END 0x426
#define ALT_PAGEUP 0x427
#define ALT_PAGEDOWN 0x428
#define ALT_INSERT 0x42C
@@ -197,8 +205,6 @@
#define SHIFT_ALT_RIGHT 0x432
#define SHIFT_ALT_UP 0x433
#define SHIFT_ALT_DOWN 0x434
//#define SHIFT_LEFT 0x451
//#define SHIFT_RIGHT 0x452
#define SHIFT_UP 0x453
#define SHIFT_DOWN 0x454
#define SHIFT_HOME 0x455
@@ -208,11 +214,28 @@
#define SHIFT_DELETE 0x45D
#define SHIFT_TAB 0x45F
/* A special keycode for when <Tab> is pressed while the mark is on. */
#define INDENT_KEY 0x4F1
#define FOCUS_IN 0x491
#define FOCUS_OUT 0x499
/* A special keycode to signal the beginning and end of a bracketed paste. */
#define BRACKETED_PASTE_MARKER 0x4FB
/* Custom keycodes for signaling the start and end of a bracketed paste. */
#define START_OF_PASTE 0x4B5
#define END_OF_PASTE 0x4BE
/* 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
#ifndef NANO_TINY
/* A special keycode for Ctrl + the central key on the numeric keypad. */
#define KEY_CENTER 0x4F0
/* A special keycode for when we get a SIGWINCH (a window resize). */
#define THE_WINDOW_RESIZED 0x4F7
#endif
/* A special keycode for when a key produces an unknown escape sequence. */
#define FOREIGN_SEQUENCE 0x4FC
@@ -221,9 +244,6 @@
#define KEY_FRESH 0x4FE
#ifndef NANO_TINY
/* A special keycode for when we get a SIGWINCH (a window resize). */
#define KEY_WINCH -2
/* Some extra flags for the undo function. */
#define WAS_BACKSPACE_AT_EOF (1<<1)
#define WAS_WHOLE_LINE (1<<2)
@@ -259,9 +279,18 @@
#define MSOME MMAIN|MBROWSER
#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. */
typedef enum {
UNSPECIFIED, NIX_FILE, DOS_FILE, MAC_FILE
UNSPECIFIED, NIX_FILE, DOS_FILE
} format_type;
typedef enum {
@@ -269,8 +298,8 @@ typedef enum {
} message_type;
typedef enum {
OVERWRITE, APPEND, PREPEND
} kind_of_writing_type;
OVERWRITE, APPEND, PREPEND, SPECIAL
} writing_type;
typedef enum {
CENTERING, FLOWING, STATIONARY
@@ -304,6 +333,7 @@ enum {
ERROR_MESSAGE,
KEY_COMBO,
FUNCTION_TAG,
FOLDED_LINE,
NUMBER_OF_ELEMENTS
};
@@ -313,7 +343,6 @@ enum {
CASE_SENSITIVE,
CONSTANT_SHOW,
NO_HELP,
SUSPENDABLE,
NO_WRAP,
AUTOINDENT,
VIEW_MODE,
@@ -322,7 +351,7 @@ enum {
SAVE_ON_EXIT,
CUT_FROM_CURSOR,
BACKWARDS_SEARCH,
MULTIBUFFER,
NEW_BUFFER,
REBIND_DELETE,
RAW_SEQUENCES,
NO_CONVERT,
@@ -355,12 +384,21 @@ enum {
EMPTY_LINE,
INDICATOR,
BOOKSTYLE,
COLON_PARSING,
STATEFLAGS,
USE_MAGIC,
MINIBAR,
ZERO
ZERO,
MODERN_BINDINGS,
SOLO_SIDESCROLL
};
typedef enum {
FOUND_BRACKET = 0,
NOT_FOUND_BRACKET,
NOT_A_BRACKET
} bracket_search_result;
/* Structure types. */
#ifdef ENABLE_COLOR
typedef struct colortype {
@@ -419,7 +457,7 @@ typedef struct syntaxtype {
/* The command with which to lint this type of file. */
char *formatter;
/* 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. */
#ifdef ENABLE_COMMENT
char *comment;
@@ -427,7 +465,7 @@ typedef struct syntaxtype {
#endif
colortype *color;
/* The colors and their regexes used in this syntax. */
short nmultis;
short multiscore;
/* How many multiline regex strings this syntax has. */
struct syntaxtype *next;
/* Next syntax. */
@@ -467,6 +505,10 @@ typedef struct linestruct {
bool has_anchor;
/* Whether the user has placed an anchor at this line. */
#endif
#ifdef ENABLE_FOLDING
bool folded;
/* Whether or not this line is in a fold segment */
#endif
} linestruct;
#ifndef NANO_TINY
@@ -510,16 +552,18 @@ typedef struct undostruct {
#endif /* !NANO_TINY */
#ifdef ENABLE_HISTORIES
typedef struct poshiststruct {
typedef struct positionstruct {
char *filename;
/* The full path plus name of the file. */
ssize_t linenumber;
/* The line where the cursor was when we closed the file. */
/* The line where the cursor was when the file was closed. */
ssize_t columnnumber;
/* The column where the cursor was. */
struct poshiststruct *next;
/* The next item of position history. */
} poshiststruct;
char *anchors;
/* The line numbers where anchors were placed, in string form. */
struct positionstruct *next;
/* The next item in the positions register. */
} positionstruct;
#endif
typedef struct openfilestruct {
@@ -541,9 +585,11 @@ typedef struct openfilestruct {
size_t current_x;
/* The file's x-coordinate position. */
size_t placewewant;
/* The file's x position we would like. */
ssize_t current_y;
/* The file's y-coordinate position. */
/* The preferred column for the cursor. */
size_t brink;
/* From which column the edit window is drawn (when panning). */
ssize_t cursor_row;
/* The row in the edit window that the cursor is on. */
struct stat *statinfo;
/* The file's stat information from when it was opened or last saved. */
#ifdef ENABLE_WRAPPING
@@ -558,7 +604,7 @@ typedef struct openfilestruct {
bool softmark;
/* Whether a marked region was made by holding Shift. */
format_type fmt;
/* The file's format -- Unix or DOS or Mac. */
/* The file's format -- Unix or DOS. */
char *lock_filename;
/* The path of the lockfile, if we created one. */
undostruct *undotop;
@@ -622,17 +668,14 @@ typedef struct keystruct {
typedef struct funcstruct {
void (*func)(void);
/* The actual function to call. */
const char *desc;
/* The function's short description, for example "Where Is". */
const char *tag;
/* The function's help-line label, for example "Where Is". */
#ifdef ENABLE_HELP
const char *help;
/* The help-screen text for this function. */
const char *phrase;
/* The function's description for in the help viewer. */
bool blank_after;
/* Whether there should be a blank line after the help text
* for this function. */
/* Whether to distance this function from the next in the help viewer. */
#endif
bool viewok;
/* Is this function allowed when in view mode? */
int menus;
/* In what menus this function applies. */
struct funcstruct *next;

File diff suppressed because it is too large Load Diff

158
src/folding.c Normal file
View File

@@ -0,0 +1,158 @@
/**************************************************************************
* folding.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2023 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 <string.h>
#ifdef ENABLE_FOLDING
/* Unfold a folded segment containing the given line. */
void unfold_folded_segment(linestruct *line)
{
line = get_start_of_folded_segment(line);
if (line != NULL)
refresh_needed = TRUE;
for (; line != NULL && line->folded; line = line->next)
line->folded = FALSE;
}
/* Get the first line 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 line 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 number of lines in 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;
}
/* Unfolds a folded segment containing line, or if line is not folded
* does nothing. Returns true if any segments are unfolded. */
bool do_unfold_segment(linestruct *line)
{
/* If current line is folded, just unfold and finish. */
if (line->folded) {
unfold_folded_segment(line);
return TRUE;
}
/* If all else fails, attempt to find the next folded line in the file. */
for (line = openfile->current; line != NULL; line = line->next) {
if (line->folded) {
unfold_folded_segment(line);
openfile->current = line;
if (line->prev)
do_up();
else
move_cursor_to_proper_column();
return TRUE;
}
}
return FALSE;
}
/* Fold the currently selected lines unless the current line is
* a folded lines. In that case, remove unfold the lines. */
void do_fold_segment(void)
{
linestruct *top, *bot, *line;
get_range(&top, &bot);
size_t top_pos, bot_pos;
bool region_found = (top != bot);
if (top == bot) {
/* First try to unfold if this line/bracketed region is folded. */
if (top->folded) {
unfold_folded_segment(top);
return;
}
/* When no selection is made, attempt to find the next line
* ending with an opening bracket as the top bound. */
for (; find_terminus_of_bracketed_region(&top, &top_pos, get_matchbrackets_halfway(), FALSE)
; top = top->next) {
bot = top;
bot_pos = top_pos;
if (find_matching_bracket_pos(&bot, &bot_pos) == FOUND_BRACKET
&& bot->lineno - top->lineno >= 2) {
top = top->next;
bot = bot->prev;
/* Unfold if already folded. */
region_found = !top->folded;
break;
}
}
}
if (region_found == TRUE) {
for (line = top; line != bot->next; line = line->next)
line->folded = TRUE;
/* Place the cursor after the new fold, accounting for possible
* fold concatenations occurring. */
openfile->current = get_end_of_folded_segment(bot);
if (bot->next)
do_down();
else
move_cursor_to_proper_column();
if (top->lineno < openfile->edittop->lineno &&
bot->lineno > openfile->edittop->lineno)
openfile->edittop = top;
openfile->mark = NULL;
refresh_needed = TRUE;
} else
if (!do_unfold_segment(openfile->current))
statusline(AHEM, _("No valid region found for automatic fold"));
}
#endif /* ENABLE_FOLDING */

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/**************************************************************************
* help.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2000-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2000-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2017 Rishabh Dave *
* Copyright (C) 2014-2019 Benno Schulenberg *
* *
@@ -16,7 +16,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -50,7 +50,7 @@ void help_init(void)
char *ptr;
/* 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 "
"Enter the words or characters you would like to "
"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 "
"available in Search mode:\n\n");
htx[2] = NULL;
} else if (currmenu == MREPLACEWITH) {
htx[0] = N_("=== Replacement ===\n\n "
"Type the characters that should replace what 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) {
htx[0] = N_("Go To Line Help Text\n\n "
"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 "
"Enter without entering any text will perform the "
"previous search.\n\n");
htx[1] = N_(" The following function keys are available in "
"Browser Search mode:\n\n");
htx[1] = N_(" The following function keys "
"are available at this prompt:\n\n");
htx[2] = NULL;
} else if (currmenu == MGOTODIR) {
htx[0] = N_("Browser Go To Directory Help Text\n\n "
@@ -143,16 +150,14 @@ void help_init(void)
#endif /* ENABLE_BROWSER */
#ifdef ENABLE_SPELLER
else if (currmenu == MSPELL) {
htx[0] = N_("Spell Check Help Text\n\n "
"The spell checker checks the spelling of all text in "
"the current file. When an unknown word is "
"encountered, it is highlighted and a replacement can "
"be edited. It will then prompt to replace every "
"instance of the given misspelled word in the current "
"file, or, if you have selected text with the mark, in "
"the selected text.\n\n The following function keys "
"are available in Spell Check mode:\n\n");
htx[1] = NULL;
htx[0] = N_("=== Spelling correction ===\n\n "
"The spell checker has examined the spelling of all text "
"in the current buffer or marked region. An unknown word "
"has been encountered -- it is highlighted and a replacement "
"can now be edited. After this you will be asked whether "
"to replace each instance of that unknown word.\n\n");
htx[1] = N_(" The following function keys "
"are available at this prompt:\n\n");
htx[2] = NULL;
}
#endif /* ENABLE_SPELLER */
@@ -167,8 +172,8 @@ void help_init(void)
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 "
"large piece of the buffer, or put the editor to sleep.\n\n");
htx[2] = N_(" The following function keys are "
"available in Execute Command mode:\n\n");
htx[2] = N_(" The following function keys "
"are available at this prompt:\n\n");
} else if (currmenu == MLINTER) {
htx[0] = N_("=== Linter ===\n\n "
"In this mode, the status bar shows an error message or "
@@ -208,15 +213,15 @@ void help_init(void)
}
htx[0] = _(htx[0]);
if (htx[1] != NULL)
if (htx[1])
htx[1] = _(htx[1]);
if (htx[2] != NULL)
if (htx[2])
htx[2] = _(htx[2]);
allocsize += strlen(htx[0]);
if (htx[1] != NULL)
if (htx[1])
allocsize += strlen(htx[1]);
if (htx[2] != NULL)
if (htx[2])
allocsize += strlen(htx[2]);
/* Calculate the length of the descriptions of the shortcuts.
@@ -224,7 +229,7 @@ void help_init(void)
* plus translated text, plus one or two \n's. */
for (f = allfuncs; f != NULL; f = f->next)
if (f->menus & currmenu)
allocsize += strlen(_(f->help)) + 21;
allocsize += strlen(_(f->phrase)) + 21;
#ifndef NANO_TINY
/* If we're on the main list, we also count the toggle help text.
@@ -244,9 +249,9 @@ void help_init(void)
/* Now add the text we want. */
strcpy(help_text, htx[0]);
if (htx[1] != NULL)
if (htx[1])
strcat(help_text, htx[1]);
if (htx[2] != NULL)
if (htx[2])
strcat(help_text, htx[2]);
/* Remember this end-of-introduction, start-of-shortcuts. */
@@ -267,10 +272,10 @@ void help_init(void)
if (++tally == 1) {
sprintf(ptr, "%s ", s->keystr);
/* Unicode arrows take three bytes instead of one. */
ptr += (strstr(s->keystr, "\xE2") != NULL ? 9 : 7);
ptr += (strstr(s->keystr, "\xE2") ? 9 : 7);
} else {
sprintf(ptr, "(%s) ", s->keystr);
ptr += (strstr(s->keystr, "\xE2") != NULL ? 12 : 10);
ptr += (strstr(s->keystr, "\xE2") ? 12 : 10);
break;
}
}
@@ -282,7 +287,7 @@ void help_init(void)
ptr += 10;
/* The shortcut's description. */
ptr += sprintf(ptr, "%s\n", _(f->help));
ptr += sprintf(ptr, "%s\n", _(f->phrase));
if (f->blank_after)
ptr += sprintf(ptr, "\n");
@@ -317,10 +322,10 @@ void help_init(void)
/* Hard-wrap the concatenated help text, and write it into a new buffer. */
void wrap_help_text_into_buffer(void)
{
size_t sum = 0;
/* 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) - sidebar;
const char *ptr = start_of_body;
size_t sum = 0;
make_new_buffer();
@@ -332,12 +337,12 @@ void wrap_help_text_into_buffer(void)
}
/* Copy the help text into the just-created new buffer. */
while (*ptr != '\0') {
while (*ptr) {
int length, shim;
char *oneline;
if (ptr == end_of_intro)
wrapping_point = ((COLS < 40) ? 40 : COLS) - thebar;
wrapping_point = ((COLS < 40) ? 40 : COLS) - sidebar;
if (ptr < end_of_intro || *(ptr - 1) == '\n') {
length = break_line(ptr, wrapping_point, TRUE);
@@ -345,7 +350,7 @@ void wrap_help_text_into_buffer(void)
shim = (*(ptr + length - 1) == ' ') ? 0 : 1;
snprintf(oneline, length + shim, "%s", ptr);
} else {
length = break_line(ptr, ((COLS < 40) ? 22 : COLS - 18) - thebar, TRUE);
length = break_line(ptr, ((COLS < 40) ? 22 : COLS - 18) - sidebar, TRUE);
oneline = nmalloc(length + 5);
snprintf(oneline, length + 5, "\t\t %s", ptr);
}
@@ -389,7 +394,7 @@ void wrap_help_text_into_buffer(void)
void show_help(void)
{
int kbinput = ERR;
functionptrtype func;
functionptrtype function;
/* The function of the key the user typed in. */
int oldmenu = currmenu;
/* The menu we were called from. */
@@ -397,10 +402,13 @@ void show_help(void)
int was_margin = margin;
#endif
ssize_t was_tabsize = tabsize;
#ifndef NANO_TINY
bool was_lighted = spotlighted;
#endif
#ifdef ENABLE_COLOR
char *was_syntax = syntaxstr;
#endif
char *saved_answer = (answer != NULL) ? copy_of(answer) : NULL;
char *saved_answer = (answer) ? copy_of(answer) : NULL;
/* The current answer when the user invokes help at the prompt. */
unsigned stash[sizeof(flags) / sizeof(flags[0])];
/* A storage place for the current flag settings. */
@@ -426,10 +434,13 @@ void show_help(void)
UNSET(WHITESPACE_DISPLAY);
#ifdef ENABLE_LINENUMBERS
editwincols = COLS - thebar;
editwincols = COLS - sidebar;
margin = 0;
#endif
tabsize = 8;
#ifndef NANO_TINY
spotlighted = FALSE;
#endif
#ifdef ENABLE_COLOR
syntaxstr = "nanohelp";
#endif
@@ -463,51 +474,50 @@ void show_help(void)
focusing = TRUE;
/* 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;
#ifndef NANO_TINY
spotlighted = FALSE;
if (bracketed_paste || kbinput == BRACKETED_PASTE_MARKER) {
beep();
continue;
}
#endif
func = interpret(&kbinput);
function = interpret(kbinput);
if (func == full_refresh) {
full_refresh();
} else if (ISSET(SHOW_CURSOR) && (func == do_left || func == do_right ||
func == do_up || func == do_down)) {
func();
} else if (func == do_up || func == do_scroll_up) {
if (ISSET(SHOW_CURSOR) && (function == do_left || function == do_right ||
function == do_up || function == do_down)) {
function();
} else if (function == do_up || function == 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)
do_scroll_down();
} else if (func == do_page_up || func == do_page_down ||
func == to_first_line || func == to_last_line) {
func();
} else if (func == do_search_backward || func == do_search_forward ||
func == do_findprevious || func == do_findnext) {
func();
} else if (function == do_page_up || function == do_page_down ||
function == to_first_line || function == to_last_line) {
function();
} else if (function == do_search_backward || function == do_search_forward ||
function == do_findprevious || function == do_findnext) {
function();
bottombars(MHELP);
#ifdef ENABLE_NANORC
} else if (func == (functionptrtype)implant) {
implant(first_sc_for(MHELP, func)->expansion);
} else if (function == (functionptrtype)implant) {
implant(first_sc_for(MHELP, function)->expansion);
#endif
#ifdef ENABLE_MOUSE
} else if (kbinput == KEY_MOUSE) {
int dummy_row, dummy_col;
get_mouseinput(&dummy_row, &dummy_col, TRUE);
get_mouseinput(&dummy_row, &dummy_col);
#endif
#ifndef NANO_TINY
} else if (kbinput == KEY_WINCH) {
} else if (kbinput == START_OF_PASTE) {
while (get_kbinput(midwin, BLIND) != END_OF_PASTE)
;
statusline(AHEM, _("Paste is ignored"));
} else if (kbinput == THE_WINDOW_RESIZED) {
; /* Nothing to do. */
#endif
} else if (func == do_exit) {
} else if (function == full_refresh) {
full_refresh();
} else if (function == do_exit) {
break;
} else
unbound_key(kbinput);
@@ -532,9 +542,12 @@ void show_help(void)
#ifdef ENABLE_LINENUMBERS
margin = was_margin;
editwincols = COLS - margin - thebar;
editwincols = COLS - margin - sidebar;
#endif
tabsize = was_tabsize;
#ifndef NANO_TINY
spotlighted = was_lighted;
#endif
#ifdef ENABLE_COLOR
syntaxstr = was_syntax;
have_palette = FALSE;
@@ -557,7 +570,7 @@ void show_help(void)
bottombars(oldmenu);
#ifdef ENABLE_BROWSER
if (oldmenu & (MBROWSER|MWHEREISFILE|MGOTODIR))
if (oldmenu & (MBROWSER|MGOTODIR|MWHEREISFILE))
browser_refresh();
else
#endif

View File

@@ -1,8 +1,8 @@
/**************************************************************************
* history.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2003-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
* Copyright (C) 2003-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2017, 2019, 2025 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -36,12 +36,12 @@
static bool history_changed = FALSE;
/* Whether any of the history lists has changed. */
static char *poshistname = NULL;
/* The name of the positions-history file. */
static char *registername = NULL;
/* The name of the positions-register file. */
static time_t latest_timestamp = 942927132;
/* The last time the positions-history file was written. */
static poshiststruct *position_history = NULL;
/* The list of filenames with their last cursor positions. */
/* The last time the positions-register file was written. */
static positionstruct *positions_register = NULL;
/* A list of recently opened files with their last cursor position. */
/* Initialize the lists of historical search and replace strings
* and the list of historical executed commands. */
@@ -114,29 +114,30 @@ void update_history(linestruct **item, const char *text, bool avoid_duplicates)
/* If an identical string was found, delete that item. */
if (thesame) {
linestruct *after = thesame->next;
/* If the string is at the head of the list, move the head. */
if (thesame == *htop)
*htop = after;
*htop = thesame->next;
else
thesame->prev->next = thesame->next;
thesame->next->prev = thesame->prev;
unlink_node(thesame);
renumber_from(after);
free(thesame->data);
free(thesame);
(*hbot)->lineno--;
}
/* If the history is full, delete the oldest item (the one at the
* head of the list), to make room for a new item at the end. */
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
linestruct *oldest = *htop;
if ((*hbot)->lineno > MAX_SEARCH_HISTORY) {
*htop = (*htop)->next;
unlink_node(oldest);
renumber_from(*htop);
free((*htop)->prev->data);
free((*htop)->prev);
(*htop)->prev = NULL;
(*hbot)->lineno--;
}
/* Store the fresh string in the last item, then create a new item. */
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
splice_node(*hbot, make_new_node(*hbot));
(*hbot)->next = make_new_node(*hbot);
*hbot = (*hbot)->next;
(*hbot)->data = copy_of("");
@@ -172,7 +173,7 @@ char *get_history_completion(linestruct **here, char *string, size_t len)
* for a match of len characters. Skip over an exact match. */
item = find_in_history((*here)->prev, htop, string, len);
while (item != NULL && strcmp(item->data, string) == 0)
while (item && strcmp(item->data, string) == 0)
item = find_in_history(item->prev, htop, string, len);
if (item) {
@@ -183,7 +184,7 @@ char *get_history_completion(linestruct **here, char *string, size_t len)
/* Now search from the bottom of the list to the original position. */
item = find_in_history(hbot, *here, string, len);
while (item != NULL && strcmp(item->data, string) == 0)
while (item && strcmp(item->data, string) == 0)
item = find_in_history(item->prev, *here, string, len);
if (item) {
@@ -204,11 +205,11 @@ bool have_statedir(void)
get_homedir();
if (homedir != NULL) {
if (homedir) {
statedir = concatenate(homedir, "/.nano/");
if (stat(statedir, &dirinfo) == 0 && S_ISDIR(dirinfo.st_mode)) {
poshistname = concatenate(statedir, POSITION_HISTORY);
registername = concatenate(statedir, POSITION_HISTORY);
return TRUE;
}
}
@@ -219,21 +220,21 @@ bool have_statedir(void)
if (homedir == NULL && xdgdatadir == NULL)
return FALSE;
if (xdgdatadir != NULL)
if (xdgdatadir)
statedir = concatenate(xdgdatadir, "/nano/");
else
statedir = concatenate(homedir, "/.local/share/nano/");
if (stat(statedir, &dirinfo) == -1) {
if (stat(statedir, &dirinfo) < 0) {
if (xdgdatadir == NULL) {
char *statepath = concatenate(homedir, "/.local");
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
mkdir(statepath, S_IRWXU);
free(statepath);
statepath = concatenate(homedir, "/.local/share");
mkdir(statepath, S_IRWXU);
free(statepath);
}
if (mkdir(statedir, S_IRWXU) == -1) {
if (mkdir(statedir, S_IRWXU) < 0) {
jot_error(N_("Unable to create directory %s: %s\n"
"It is required for saving/loading "
"search history or cursor positions.\n"),
@@ -248,49 +249,49 @@ bool have_statedir(void)
return FALSE;
}
poshistname = concatenate(statedir, POSITION_HISTORY);
registername = concatenate(statedir, POSITION_HISTORY);
return TRUE;
}
/* Load the histories for Search, Replace With, and Execute Command. */
void load_history(void)
{
char *histname = concatenate(statedir, SEARCH_HISTORY);
FILE *histfile = fopen(histname, "rb");
char *historyname = concatenate(statedir, SEARCH_HISTORY);
FILE *histories = fopen(historyname, "rb");
/* If reading an existing file failed, don't save history when we quit. */
if (histfile == NULL && errno != ENOENT) {
jot_error(N_("Error reading %s: %s"), histname, strerror(errno));
if (histories == NULL && errno != ENOENT) {
jot_error(N_("Error reading %s: %s"), historyname, strerror(errno));
UNSET(HISTORYLOG);
}
if (histfile == NULL) {
free(histname);
if (histories == NULL) {
free(historyname);
return;
}
linestruct **history = &search_history;
linestruct **list = &search_history;
char *stanza = NULL;
size_t dummy = 0;
ssize_t read;
/* Load the three history lists (first search, then replace, then execute)
* from oldest entry to newest. Between two lists there is an empty line. */
while ((read = getline(&stanza, &dummy, histfile)) > 0) {
while ((read = getline(&stanza, &dummy, histories)) > 0) {
stanza[--read] = '\0';
if (read > 0) {
recode_NUL_to_LF(stanza, read);
update_history(history, stanza, IGNORE_DUPLICATES);
} else if (history == &search_history)
history = &replace_history;
update_history(list, stanza, IGNORE_DUPLICATES);
} else if (list == &search_history)
list = &replace_history;
else
history = &execute_history;
list = &execute_history;
}
if (fclose(histfile) == EOF)
jot_error(N_("Error reading %s: %s"), histname, strerror(errno));
if (fclose(histories) == EOF)
jot_error(N_("Error reading %s: %s"), historyname, strerror(errno));
free(histname);
free(historyname);
free(stanza);
/* Reading in the lists has marked them as changed; undo this side effect. */
@@ -299,19 +300,17 @@ void load_history(void)
/* Write the lines of a history list, starting at head, from oldest to newest,
* to the given file. Return TRUE if writing succeeded, and FALSE otherwise. */
bool write_list(const linestruct *head, FILE *histfile)
bool write_list(const linestruct *head, FILE *histories)
{
const linestruct *item;
for (item = head; item != NULL; item = item->next) {
size_t length = strlen(item->data);
/* 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, histories) < length)
return FALSE;
if (putc('\n', histfile) == EOF)
if (putc('\n', histories) == EOF)
return FALSE;
}
@@ -321,66 +320,108 @@ bool write_list(const linestruct *head, FILE *histfile)
/* Save the histories for Search, Replace With, and Execute Command. */
void save_history(void)
{
char *histname;
FILE *histfile;
/* If the histories are unchanged, don't bother saving them. */
if (!history_changed)
return;
histname = concatenate(statedir, SEARCH_HISTORY);
histfile = fopen(histname, "wb");
char *historyname = concatenate(statedir, SEARCH_HISTORY);
FILE *histories = fopen(historyname, "wb");
if (histfile == NULL) {
jot_error(N_("Error writing %s: %s"), histname, strerror(errno));
free(histname);
if (histories == NULL) {
jot_error(N_("Error writing %s: %s"), historyname, strerror(errno));
free(historyname);
return;
}
/* Don't allow others to read or write the history file. */
if (chmod(histname, S_IRUSR | S_IWUSR) < 0)
jot_error(N_("Cannot limit permissions on %s: %s"), histname, strerror(errno));
if (chmod(historyname, S_IRUSR | S_IWUSR) < 0)
jot_error(N_("Cannot limit permissions on %s: %s"), historyname, strerror(errno));
if (!write_list(searchtop, histfile) || !write_list(replacetop, histfile) ||
!write_list(executetop, histfile))
jot_error(N_("Error writing %s: %s"), histname, strerror(errno));
if (!write_list(searchtop, histories) || !write_list(replacetop, histories) ||
!write_list(executetop, histories))
jot_error(N_("Error writing %s: %s"), historyname, strerror(errno));
if (fclose(histfile) == EOF)
jot_error(N_("Error writing %s: %s"), histname, strerror(errno));
if (fclose(histories) == EOF)
jot_error(N_("Error writing %s: %s"), historyname, strerror(errno));
free(histname);
free(historyname);
}
/* Load the recorded cursor positions for files that were edited. */
void load_poshistory(void)
/* Return as a string... the line numbers of the lines with an anchor. */
char *stringify_anchors(void)
{
FILE *histfile = fopen(poshistname, "rb");
char *string = copy_of("");
#ifndef NANO_TINY
char number[24];
/* If reading an existing file failed, don't save history when we quit. */
if (histfile == NULL && errno != ENOENT) {
jot_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
for (linestruct *line = openfile->filetop; line != NULL; line = line->next)
if (line->has_anchor) {
sprintf(number, "%zi ", line->lineno);
string = nrealloc(string, strlen(string) + strlen(number) + 1);
strcat(string, number);
}
#endif
return string;
}
/* Set an anchor for each line number in the given string. */
void restore_anchors(char *string)
{
#ifndef NANO_TINY
linestruct *line = openfile->filetop;
ssize_t number;
char *space;
while (*string) {
if ((space = strchr(string, ' ')) == NULL)
return;
*space = '\0';
number = atoi(string);
*space = ' ';
string = space + 1;
while (line->lineno < number)
if ((line = line->next) == NULL)
return;
line->has_anchor = TRUE;
}
#endif
}
/* Load the recorded cursor positions for files that were opened. */
void load_positions_register(void)
{
FILE *registry = fopen(registername, "rb");
/* If reading an existing file failed, don't save the register when we quit. */
if (registry == NULL && errno != ENOENT) {
jot_error(N_("Error reading %s: %s"), registername, strerror(errno));
UNSET(POSITIONLOG);
}
if (histfile == NULL)
if (registry == NULL)
return;
poshiststruct *lastitem = NULL;
poshiststruct *newitem;
char *lineptr, *columnptr;
char *stanza = NULL;
positionstruct *lastitem = NULL;
positionstruct *newitem;
char *stanza, *lineptr, *columnptr;
char *phrase = NULL;
struct stat fileinfo;
size_t dummy = 0;
ssize_t count = 0;
ssize_t read;
int count = 0;
ssize_t length;
/* Read and parse each line, and store the extracted data. */
while ((read = getline(&stanza, &dummy, histfile)) > 5) {
while (count++ < 200 && (length = getline(&phrase, &dummy, registry)) > 1) {
stanza = strchr(phrase, '/');
length -= (stanza ? stanza - phrase : 0);
/* Decode NULs as embedded newlines. */
recode_NUL_to_LF(stanza, read);
recode_NUL_to_LF(stanza, length);
/* Find the spaces before column number and line number. */
columnptr = revstrstr(stanza, " ", stanza + read - 3);
columnptr = revstrstr(stanza, " ", stanza + length - 3);
if (columnptr == NULL)
continue;
lineptr = revstrstr(stanza, " ", columnptr - 2);
@@ -392,197 +433,167 @@ void load_poshistory(void)
*(lineptr++) = '\0';
/* Create a new position record. */
newitem = nmalloc(sizeof(poshiststruct));
newitem = nmalloc(sizeof(positionstruct));
newitem->filename = copy_of(stanza);
newitem->linenumber = atoi(lineptr);
newitem->columnnumber = atoi(columnptr);
newitem->anchors = (phrase == stanza) ? NULL : measured_copy(phrase, stanza - phrase);
newitem->next = NULL;
/* Add the record to the list. */
if (position_history == NULL)
position_history = newitem;
if (positions_register == NULL)
positions_register = newitem;
else
lastitem->next = newitem;
lastitem = newitem;
/* Impose a limit, so the file will not grow indefinitely. */
if (++count > 200) {
poshiststruct *drop_record = position_history;
position_history = position_history->next;
free(drop_record->filename);
free(drop_record);
}
}
if (fclose(histfile) == EOF)
jot_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
if (fclose(registry) == EOF)
jot_error(N_("Error reading %s: %s"), registername, strerror(errno));
free(stanza);
free(phrase);
if (stat(poshistname, &fileinfo) == 0)
if (stat(registername, &fileinfo) == 0)
latest_timestamp = fileinfo.st_mtime;
}
/* Save the recorded cursor positions for files that were edited. */
void save_poshistory(void)
/* Save the recorded cursor positions for files that were opened. */
void save_positions_register(void)
{
FILE *histfile = fopen(poshistname, "wb");
FILE *registry = fopen(registername, "wb");
struct stat fileinfo;
poshiststruct *item;
positionstruct *item;
int count = 0;
if (histfile == NULL) {
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
if (registry == NULL) {
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
return;
}
/* Don't allow others to read or write the history file. */
if (chmod(poshistname, S_IRUSR | S_IWUSR) < 0)
jot_error(N_("Cannot limit permissions on %s: %s"), poshistname, strerror(errno));
/* Don't allow others to read or write the positions-register file. */
if (chmod(registername, S_IRUSR | S_IWUSR) < 0)
jot_error(N_("Cannot limit permissions on %s: %s"), registername, strerror(errno));
for (item = position_history; item != NULL; item = item->next) {
for (item = positions_register; item != NULL && count++ < 200; item = item->next) {
char *path_and_place;
size_t length;
size_t length = (item->anchors == NULL) ? 0 : strlen(item->anchors);
/* First write the string of line numbers with anchors, if any. */
if (length && fwrite(item->anchors, 1, length, registry) < length)
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
/* Assume 20 decimal positions each for line and column number,
* plus two spaces, plus the line feed, plus the null byte. */
path_and_place = nmalloc(strlen(item->filename) + 44);
sprintf(path_and_place, "%s %zd %zd\n",
item->filename, item->linenumber, item->columnnumber);
length = strlen(path_and_place);
/* 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. */
path_and_place[length - 1] = '\n';
if (fwrite(path_and_place, sizeof(char), length, histfile) < length)
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
if (fwrite(path_and_place, 1, length, registry) < length)
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
free(path_and_place);
}
if (fclose(histfile) == EOF)
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
if (fclose(registry) == EOF)
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
if (stat(poshistname, &fileinfo) == 0)
if (stat(registername, &fileinfo) == 0)
latest_timestamp = fileinfo.st_mtime;
}
/* Reload the position history file if it has been modified since last load. */
/* Reload the positions-register file if it has been modified since last load. */
void reload_positions_if_needed(void)
{
poshiststruct *item, *nextone;
positionstruct *item, *nextone;
struct stat fileinfo;
if (stat(poshistname, &fileinfo) != 0 || fileinfo.st_mtime == latest_timestamp)
if (stat(registername, &fileinfo) < 0 || fileinfo.st_mtime == latest_timestamp)
return;
for (item = position_history; item != NULL; item = nextone) {
for (item = positions_register; item != NULL; item = nextone) {
nextone = item->next;
free(item->filename);
free(item->anchors);
free(item);
}
position_history = NULL;
positions_register = NULL;
load_poshistory();
load_positions_register();
}
/* Update the recorded last file positions with the current position in the
* current buffer. If no existing entry is found, add a new one at the end. */
void update_poshistory(void)
* current buffer. If no existing entry is found, add a new one at the top. */
void update_positions_register(void)
{
char *fullpath = get_full_path(openfile->filename);
poshiststruct *previous = NULL;
poshiststruct *item, *theone;
positionstruct *previous = NULL;
positionstruct *item;
if (fullpath == NULL || openfile->filename[0] == '\0') {
free(fullpath);
if (fullpath == NULL)
return;
}
reload_positions_if_needed();
/* Look for a matching filename in the list. */
for (item = position_history; item != NULL; item = item->next) {
for (item = positions_register; item != NULL; item = item->next) {
if (!strcmp(item->filename, fullpath))
break;
previous = item;
}
/* Don't record files that have the default cursor position. */
if (openfile->current->lineno == 1 && openfile->current_x == 0) {
if (item != NULL) {
if (previous == NULL)
position_history = item->next;
else
previous->next = item->next;
free(item->filename);
free(item);
save_poshistory();
}
free(fullpath);
return;
/* If no match was found, make a new node; otherwise, unlink the match. */
if (item == NULL) {
item = nmalloc(sizeof(positionstruct));
item->filename = copy_of(fullpath);
item->anchors = NULL;
} else if (previous)
previous->next = item->next;
/* Place the found or new node at the beginning, if not already there. */
if (item != positions_register) {
item->next = positions_register;
positions_register = item;
}
theone = item;
/* If we didn't find it, make a new node; otherwise, if we're
* not at the end, move the matching one to the end. */
if (theone == NULL) {
theone = nmalloc(sizeof(poshiststruct));
theone->filename = copy_of(fullpath);
if (position_history == NULL)
position_history = theone;
else
previous->next = theone;
} else if (item->next != NULL) {
if (previous == NULL)
position_history = item->next;
else
previous->next = item->next;
while (item->next != NULL)
item = item->next;
item->next = theone;
}
/* Store the last cursor position. */
theone->linenumber = openfile->current->lineno;
theone->columnnumber = xplustabs() + 1;
theone->next = NULL;
/* Record the last cursor position and any anchors. */
item->linenumber = openfile->current->lineno;
item->columnnumber = xplustabs() + 1;
free(item->anchors);
item->anchors = stringify_anchors();
free(fullpath);
save_poshistory();
save_positions_register();
}
/* Check whether the given file matches an existing entry in the recorded
* last file positions. If not, return FALSE. If yes, return TRUE and
* set line and column to the retrieved values. */
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
/* Check whether the current filename matches an entry in the list of
* recorded positions. If yes, restore the relevant cursor position. */
void restore_cursor_position_if_any(void)
{
char *fullpath = get_full_path(file);
poshiststruct *item;
char *fullpath = get_full_path(openfile->filename);
positionstruct *item;
if (fullpath == NULL)
return FALSE;
return;
reload_positions_if_needed();
item = position_history;
while (item != NULL && strcmp(item->filename, fullpath) != 0)
item = positions_register;
while (item && strcmp(item->filename, fullpath) != 0)
item = item->next;
free(fullpath);
if (item == NULL)
return FALSE;
*line = item->linenumber;
*column = item->columnnumber;
return TRUE;
if (item && item->anchors)
restore_anchors(item->anchors);
if (item)
goto_line_and_column(item->linenumber, item->columnnumber, TRUE);
}
#endif /* ENABLE_HISTORIES */

View File

@@ -1,8 +1,8 @@
/**************************************************************************
* move.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2014-2018 Benno Schulenberg *
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2014-2018, 2020, 2024, 2026 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -37,13 +37,22 @@ void to_first_line(void)
void to_last_line(void)
{
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();
/* Set the last line of the screen as the target for the cursor. */
openfile->current_y = editwinrows - 1;
openfile->cursor_row = editwinrows - 1;
refresh_needed = TRUE;
#ifdef ENABLE_COLOR
recook |= perturbed;
#endif
focusing = FALSE;
}
@@ -80,7 +89,7 @@ size_t proper_x(linestruct *line, size_t *leftedge, bool forward,
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
index++;
if (shifted != NULL)
if (shifted)
*shifted = TRUE;
}
@@ -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. */
void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
{
bool shifted = FALSE;
size_t was_edge = *leftedge;
bool shifted = FALSE;
openfile->current_x = proper_x(openfile->current, leftedge, forward,
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;
}
/* 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. */
void do_page_up(void)
{
@@ -121,7 +139,7 @@ void do_page_up(void)
if (ISSET(JUMPY_SCROLLING)) {
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
openfile->current_y = 0;
openfile->cursor_row = 0;
target_column = 0;
} else
#endif
@@ -153,7 +171,7 @@ void do_page_down(void)
if (ISSET(JUMPY_SCROLLING)) {
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
openfile->current_y = 0;
openfile->cursor_row = 0;
target_column = 0;
} else
#endif
@@ -173,11 +191,68 @@ void do_page_down(void)
refresh_needed = TRUE;
}
#ifndef NANO_TINY
/* Place the cursor on the first row in the viewport. */
void to_top_row(void)
{
size_t leftedge, offset;
get_edge_and_target(&leftedge, &offset);
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
set_proper_index_and_pww(&leftedge, offset, FALSE);
refresh_needed = (openfile->mark != NULL);
}
/* Place the cursor on the last row in the viewport, when possible. */
void to_bottom_row(void)
{
size_t leftedge, offset;
get_edge_and_target(&leftedge, &offset);
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
go_forward_chunks(editwinrows - 1, &openfile->current, &leftedge);
set_proper_index_and_pww(&leftedge, offset, TRUE);
refresh_needed = (openfile->mark != NULL);
}
/* Put the cursor line at the center, then the top, then the bottom. */
void do_cycle(void)
{
if (cycling_aim == 0)
adjust_viewport(CENTERING);
else {
openfile->cursor_row = (cycling_aim == 1) ? 0 : editwinrows - 1;
adjust_viewport(STATIONARY);
}
cycling_aim = (cycling_aim + 1) % 3;
draw_all_subwindows();
full_refresh();
}
/* Scroll the line with the cursor to the center of the screen. */
void do_center(void)
{
adjust_viewport(CENTERING);
draw_all_subwindows();
full_refresh();
}
#endif /* !NANO_TINY */
#ifdef ENABLE_JUSTIFY
/* Move to the first beginning of a paragraph before the current line. */
void do_para_begin(linestruct **line)
{
if ((*line)->prev != NULL)
if ((*line)->prev)
*line = (*line)->prev;
while (!begpar(*line, 0))
@@ -187,11 +262,10 @@ void do_para_begin(linestruct **line)
/* Move down to the last line of the first found paragraph. */
void do_para_end(linestruct **line)
{
while ((*line)->next != NULL && !inpar(*line))
while ((*line)->next && !inpar(*line))
*line = (*line)->next;
while ((*line)->next != NULL && inpar((*line)->next) &&
!begpar((*line)->next, 0))
while ((*line)->next && inpar((*line)->next) && !begpar((*line)->next, 0))
*line = (*line)->next;
}
@@ -215,13 +289,16 @@ void to_para_end(void)
/* Step beyond the last line of the paragraph, if possible;
* otherwise, move to the end of the line. */
if (openfile->current->next != NULL) {
if (openfile->current->next) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
} else
openfile->current_x = strlen(openfile->current->data);
edit_redraw(was_current, CENTERING);
#ifdef ENABLE_COLOR
recook |= perturbed;
#endif
}
#endif /* ENABLE_JUSTIFY */
@@ -229,19 +306,28 @@ void to_para_end(void)
void to_prev_block(void)
{
linestruct *was_current = openfile->current;
linestruct *line_step = get_prev_visible_line(openfile->current);
bool is_text = FALSE, seen_text = FALSE;
/* Skip backward until first blank line after some nonblank line(s). */
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
openfile->current = openfile->current->prev;
while (line_step && (!seen_text || is_text)) {
openfile->current = line_step;
line_step = get_prev_visible_line(line_step);
#ifdef ENABLE_FOLDING
/* Skip over the visibly drawn line of the folded segment */
if (openfile->current->folded)
continue;
#endif
is_text = !white_string(openfile->current->data);
seen_text = seen_text || is_text;
}
/* Step forward one line again if we passed text but this line is blank. */
if (seen_text && openfile->current->next != NULL &&
white_string(openfile->current->data))
openfile->current = openfile->current->next;
line_step = get_next_visible_line(openfile->current);
if (seen_text && line_step && white_string(openfile->current->data)) {
openfile->current = line_step;
line_step = get_next_visible_line(line_step);
}
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
@@ -251,39 +337,64 @@ void to_prev_block(void)
void to_next_block(void)
{
linestruct *was_current = openfile->current;
linestruct *line_step = get_next_visible_line(openfile->current);
bool is_white = white_string(openfile->current->data);
bool seen_white = is_white;
/* Skip forward until first nonblank line after some blank line(s). */
while (openfile->current->next != NULL && (!seen_white || is_white)) {
openfile->current = openfile->current->next;
while (line_step && (!seen_white || is_white)) {
openfile->current = line_step;
line_step = get_next_visible_line(line_step);
#ifdef ENABLE_FOLDING
/* Skip over the visibly drawn line of the folded segment */
if (openfile->current->folded)
continue;
#endif
is_white = white_string(openfile->current->data);
seen_white = seen_white || is_white;
}
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
#ifdef ENABLE_COLOR
recook |= perturbed;
#endif
}
/* Move to the previous word. */
void do_prev_word(void)
/* Move to the previous word.
* When allow_folded is 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 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. */
while (TRUE) {
/* If at the head of a line, move to the end of the preceding one. */
if (openfile->current_x == 0) {
if (openfile->current->prev == NULL)
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);
}
/* Step back one character. */
openfile->current_x = step_left(openfile->current->data,
openfile->current_x);
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
if (is_word_char(openfile->current->data + openfile->current_x,
punctuation_as_letters)) {
@@ -304,13 +415,14 @@ void do_prev_word(void)
if (step_forward)
/* Move one character forward again to sit on the start of the word. */
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
UNFOLD_SEGMENT(openfile->current);
}
/* 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. */
bool do_next_word(bool after_ends)
* instead of at their beginnings. If allow_folded is true, go to next word
* 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 started_on_word = is_word_char(openfile->current->data +
@@ -320,6 +432,12 @@ bool do_next_word(bool after_ends)
bool seen_word = started_on_word;
#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. */
while (TRUE) {
/* If at the end of a line, move to the beginning of the next one. */
@@ -327,13 +445,23 @@ bool do_next_word(bool after_ends)
/* When at end of file, stop. */
if (openfile->current->next == NULL)
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 folded 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;
seen_space = TRUE;
} else {
/* Step forward one character. */
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
}
#ifndef NANO_TINY
@@ -367,6 +495,8 @@ bool do_next_word(bool after_ends)
}
}
UNFOLD_SEGMENT(openfile->current);
return started_on_word;
}
@@ -375,7 +505,7 @@ void to_prev_word(void)
{
linestruct *was_current = openfile->current;
do_prev_word();
do_prev_word(DISALLOW_FOLDED);
edit_redraw(was_current, FLOWING);
}
@@ -386,7 +516,7 @@ void to_next_word(void)
{
linestruct *was_current = openfile->current;
do_next_word(ISSET(AFTER_ENDS));
do_next_word(ISSET(AFTER_ENDS), DISALLOW_FOLDED);
edit_redraw(was_current, FLOWING);
}
@@ -401,25 +531,30 @@ void do_home(void)
bool moved_off_chunk = TRUE;
#ifndef NANO_TINY
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)) {
leftedge = leftedge_for(was_column, openfile->current);
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
NULL);
left_x = proper_x(openfile->current, &leftedge, FALSE, leftedge, NULL);
}
if (ISSET(SMART_HOME)) {
size_t indent_x = indent_length(openfile->current->data);
if (openfile->current->data[indent_x] != '\0') {
if (openfile->current->data[indent_x]) {
/* If we're exactly on the indent, move fully home. Otherwise,
* when not softwrapping or not after the first nonblank chunk,
* move to the first nonblank character. */
if (openfile->current_x == indent_x) {
openfile->current_x = 0;
moved = TRUE;
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
} else if (left_x <= indent_x) {
openfile->current_x = indent_x;
moved = TRUE;
}
@@ -429,10 +564,10 @@ void do_home(void)
if (!moved && ISSET(SOFTWRAP)) {
/* If already at the left edge of the screen, move fully home.
* Otherwise, move to the left edge. */
if (openfile->current_x == leftedge_x)
if (openfile->current_x == left_x)
openfile->current_x = 0;
else {
openfile->current_x = leftedge_x;
openfile->current_x = left_x;
openfile->placewewant = leftedge;
moved_off_chunk = FALSE;
}
@@ -461,13 +596,19 @@ void do_end(void)
size_t line_len = strlen(openfile->current->data);
bool moved_off_chunk = TRUE;
#ifdef ENABLE_FOLDING
if (openfile->current->folded)
return;
#endif
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
bool kickoff = TRUE;
bool last_chunk = FALSE;
size_t leftedge = leftedge_for(was_column, openfile->current);
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
leftedge, &last_chunk);
size_t rightedge_x;
leftedge, &kickoff, &last_chunk);
size_t right_x;
/* 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
@@ -476,14 +617,14 @@ void do_end(void)
if (!last_chunk)
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
* 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;
else {
openfile->current_x = rightedge_x;
openfile->current_x = right_x;
openfile->placewewant = rightedge;
moved_off_chunk = FALSE;
}
@@ -516,7 +657,8 @@ void do_up(void)
set_proper_index_and_pww(&leftedge, target_column, FALSE);
if (openfile->current_y == 0 && !ISSET(JUMPY_SCROLLING))
if (openfile->cursor_row == 0 && !ISSET(JUMPY_SCROLLING) &&
(tabsize < editwincols || !ISSET(SOFTWRAP)))
edit_scroll(BACKWARD);
else
edit_redraw(was_current, FLOWING);
@@ -539,7 +681,8 @@ void do_down(void)
set_proper_index_and_pww(&leftedge, target_column, TRUE);
if (openfile->current_y == editwinrows - 1 && !ISSET(JUMPY_SCROLLING))
if (openfile->cursor_row == editwinrows - 1 && !ISSET(JUMPY_SCROLLING) &&
(tabsize < editwincols || !ISSET(SOFTWRAP)))
edit_scroll(FORWARD);
else
edit_redraw(was_current, FLOWING);
@@ -556,7 +699,7 @@ void do_scroll_up(void)
if (openfile->edittop->prev == NULL && openfile->firstcolumn == 0)
return;
if (openfile->current_y == editwinrows - 1)
if (openfile->cursor_row == editwinrows - 1)
do_up();
if (editwinrows > 1)
@@ -566,10 +709,10 @@ void do_scroll_up(void)
/* Scroll down one line or chunk without moving the cursor textwise. */
void do_scroll_down(void)
{
if (openfile->current_y == 0)
if (openfile->cursor_row == 0)
do_down();
if (editwinrows > 1 && (openfile->edittop->next != NULL
if (editwinrows > 1 && (openfile->edittop->next
#ifndef NANO_TINY
|| (ISSET(SOFTWRAP) && (extra_chunks_in(openfile->edittop) >
chunk_for(openfile->firstcolumn, openfile->edittop)))
@@ -577,14 +720,6 @@ void do_scroll_down(void)
))
edit_scroll(FORWARD);
}
/* Scroll the line with the cursor to the center of the screen. */
void do_center(void)
{
adjust_viewport(CENTERING);
draw_all_subwindows();
full_refresh();
}
#endif /* !NANO_TINY || ENABLE_HELP */
/* Move left one character. */
@@ -593,16 +728,14 @@ void do_left(void)
linestruct *was_current = openfile->current;
if (openfile->current_x > 0) {
openfile->current_x = step_left(openfile->current->data,
openfile->current_x);
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
#ifdef ENABLE_UTF8
while (openfile->current_x > 0 &&
is_zerowidth(openfile->current->data + openfile->current_x))
openfile->current_x = step_left(openfile->current->data,
openfile->current_x);
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
#endif
} 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);
}
@@ -614,19 +747,82 @@ void do_right(void)
{
linestruct *was_current = openfile->current;
if (openfile->current->data[openfile->current_x] != '\0') {
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
#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]) {
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
#ifdef ENABLE_UTF8
while (openfile->current->data[openfile->current_x] != '\0' &&
while (openfile->current->data[openfile->current_x] &&
is_zerowidth(openfile->current->data + openfile->current_x))
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
#endif
} else if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current = get_next_visible_line(openfile->current);
openfile->current_x = 0;
}
edit_redraw(was_current, FLOWING);
}
#ifndef NANO_TINY
/* Scroll the viewport horizontally to the left. */
void do_scroll_left(void)
{
size_t frame_x;
if (ISSET(SOFTWRAP) || ISSET(SOLO_SIDESCROLL)) {
/* TRANSLATORS: The %s is the name of an option. */
statusline(AHEM, _("Not possible with '%s'"), ISSET(SOFTWRAP) ? "--softwrap" : "--solo");
return;
}
openfile->brink -= (openfile->brink < tabsize) ? openfile->brink : (tabsize < 2) ? 2 : tabsize;
frame_x = actual_x(openfile->current->data, openfile->brink + editwincols - CUSHION - 1);
if (openfile->current_x > frame_x) {
openfile->current_x = frame_x;
openfile->placewewant = xplustabs();
}
refresh_needed = TRUE;
}
/* Scroll the viewport horizontally to the right. */
void do_scroll_right(void)
{
size_t sill = openfile->edittop->lineno + editwinrows;
linestruct *line = openfile->current;
size_t frame_x;
if (ISSET(SOFTWRAP) || ISSET(SOLO_SIDESCROLL)) {
statusline(AHEM, _("Not possible with '%s'"), ISSET(SOFTWRAP) ? "--softwrap" : "--solo");
return;
}
openfile->brink += (tabsize < 2) ? 2 : tabsize;
/* If the current line does not allow further scrolling, seek
* in the viewport an earlier or later line that does allow it. */
while (line != openfile->edittop && breadth(line->data) < openfile->brink + CUSHION)
line = line->prev;
while (line->lineno < sill && breadth(line->data) < openfile->brink + CUSHION && line->next)
line = line->next;
if (line->lineno < sill && breadth(line->data) >= openfile->brink + CUSHION)
openfile->current = line;
frame_x = actual_x(openfile->current->data, openfile->brink + CUSHION);
if (openfile->current_x < frame_x) {
openfile->current_x = frame_x;
openfile->placewewant = xplustabs();
}
refresh_needed = TRUE;
}
#endif /* !NANO_TINY */

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/**************************************************************************
* prompt.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2018, 2020 Benno Schulenberg *
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2018, 2020-2022, 2025 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -41,6 +41,33 @@ void do_statusbar_end(void)
}
#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. */
void do_statusbar_next_word(void)
{
@@ -49,7 +76,7 @@ void do_statusbar_next_word(void)
/* Move forward until we reach either the end or the start of a word,
* depending on whether the AFTER_ENDS flag is set or not. */
while (answer[typing_x] != '\0') {
while (answer[typing_x]) {
typing_x = step_right(answer, typing_x);
if (ISSET(AFTER_ENDS)) {
@@ -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 */
/* Move left one character in the answer. */
@@ -122,30 +122,15 @@ void do_statusbar_left(void)
/* Move right one character in the answer. */
void do_statusbar_right(void)
{
if (answer[typing_x] != '\0') {
if (answer[typing_x]) {
typing_x = step_right(answer, typing_x);
#ifdef ENABLE_UTF8
while (answer[typing_x] != '\0' && is_zerowidth(answer + typing_x))
while (answer[typing_x] && is_zerowidth(answer + typing_x))
typing_x = step_right(answer, typing_x);
#endif
}
}
/* Delete one character in the answer. */
void do_statusbar_delete(void)
{
if (answer[typing_x] != '\0') {
int charlen = char_length(answer + typing_x);
memmove(answer + typing_x, answer + typing_x + charlen,
strlen(answer) - typing_x - charlen + 1);
#ifdef ENABLE_UTF8
if (is_zerowidth(answer + typing_x))
do_statusbar_delete();
#endif
}
}
/* Backspace over one character in the answer. */
void do_statusbar_backspace(void)
{
@@ -157,48 +142,71 @@ void do_statusbar_backspace(void)
}
}
/* Zap some or all text from the answer. */
void do_statusbar_cut_text(void)
/* Delete one character in the answer. */
void do_statusbar_delete(void)
{
if (!ISSET(CUT_FROM_CURSOR))
if (answer[typing_x]) {
int charlen = char_length(answer + typing_x);
memmove(answer + typing_x, answer + typing_x + charlen,
strlen(answer) - typing_x - charlen + 1);
#ifdef ENABLE_UTF8
if (is_zerowidth(answer + typing_x))
do_statusbar_delete();
#endif
}
}
/* Zap the part of the answer after the cursor, or the whole answer. */
void lop_the_answer(void)
{
if (answer[typing_x] == '\0')
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. */
void paste_into_answer(void)
{
size_t pastelen = strlen(cutbuffer->data);
char *fusion = nmalloc(strlen(answer) + pastelen + 1);
/* Concatenate: the current answer before the cursor, the first line
* of the cutbuffer, plus the rest of the current answer. */
strncpy(fusion, answer, typing_x);
strncpy(fusion + typing_x, cutbuffer->data, pastelen);
strcpy(fusion + typing_x + pastelen, answer + typing_x);
answer = nrealloc(answer, strlen(answer) + pastelen + 1);
memmove(answer + typing_x + pastelen, answer + typing_x, strlen(answer) - typing_x + 1);
strncpy(answer + typing_x, cutbuffer->data, pastelen);
free(answer);
answer = fusion;
typing_x += pastelen;
}
#endif
#ifdef ENABLE_MOUSE
/* Handle a mouse click on the status-bar prompt or the shortcut list. */
int do_statusbar_mouse(void)
/* Handle a mouse click in the prompt bar or the help lines. */
int process_prompt_click(void)
{
int click_row, click_col;
int retval = get_mouseinput(&click_row, &click_col, TRUE);
int retval = get_mouseinput(&click_row, &click_col); /* Handles shortcuts. */
/* We can click on the status-bar window text to move the cursor. */
if (retval == 0 && wmouse_trafo(bottomwin, &click_row, &click_col, FALSE)) {
/* When the click is in the prompt bar, position the cursor. */
if (retval == 0 && wmouse_trafo(footwin, &click_row, &click_col, FALSE)) {
size_t start_col = breadth(prompt) + 2;
/* Move to where the click occurred. */
if (click_row == 0 && click_col >= start_col)
typing_x = actual_x(answer,
get_statusbar_page_start(start_col, start_col +
wideness(answer, typing_x)) + click_col - start_col);
if (click_col >= start_col)
typing_x = actual_x(answer, get_statusbar_page_start(start_col, start_col +
wideness(answer, typing_x)) + click_col - start_col);
else
typing_x = 0;
}
return retval;
@@ -214,9 +222,8 @@ void inject_into_answer(char *burst, size_t count)
burst[index] = '\n';
answer = nrealloc(answer, strlen(answer) + count + 1);
memmove(answer + typing_x + count, answer + typing_x,
strlen(answer) - typing_x + 1);
strncpy(answer + typing_x, burst , count);
memmove(answer + typing_x + count, answer + typing_x, strlen(answer) - typing_x + 1);
strncpy(answer + typing_x, burst, count);
typing_x += count;
}
@@ -227,7 +234,7 @@ void do_statusbar_verbatim_input(void)
size_t count = 1;
char *bytes;
bytes = get_verbatim_kbinput(bottomwin, &count);
bytes = get_verbatim_kbinput(footwin, &count);
if (0 < count && count < 999)
inject_into_answer(bytes, count);
@@ -237,127 +244,90 @@ void do_statusbar_verbatim_input(void)
free(bytes);
}
/* Read in a keystroke, interpret it if it is a shortcut or toggle, and
* return it. Set finished to TRUE if we're done after running
* or trying to run a function associated with a shortcut key. */
int do_statusbar_input(bool *finished)
/* Add the given input to the input buffer when it's a normal byte,
* and inject the gathered bytes into the answer when ready. */
void absorb_character(int input, functionptrtype function)
{
int input;
/* The character we read in. */
static char *puddle = NULL;
/* The input buffer. */
static size_t capacity = 8;
/* The size of the input buffer; gets doubled whenever needed. */
static size_t depth = 0;
/* 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.
* 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. */
if (shortcut == NULL) {
if (input < 0x20 || input > 0xFF || meta_key)
if (!function) {
if ((input < 0x20 && input != '\t') || meta_key || input > 0xFF)
beep();
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
openfile->filename[0] == '\0') {
puddle = nrealloc(puddle, depth + 2);
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE || openfile->filename[0] == '\0') {
/* 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;
}
}
/* If we got a shortcut, or if there aren't any other keystrokes waiting,
* it's time to insert all characters in the input buffer (if not empty)
* into the answer, and then clear the input buffer. */
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
/* If there are gathered bytes and we have a command or no other key codes
* are waiting, it's time to insert these bytes into the answer. */
if (depth > 0 && (function || waiting_keycodes() == 0)) {
puddle[depth] = '\0';
inject_into_answer(puddle, depth);
free(puddle);
puddle = NULL;
depth = 0;
}
}
if (shortcut) {
if (shortcut->func == do_tab || shortcut->func == do_enter)
;
#ifdef ENABLE_HISTORIES
else if (shortcut->func == get_older_item ||
shortcut->func == get_newer_item)
;
#endif
else if (shortcut->func == do_left)
do_statusbar_left();
else if (shortcut->func == do_right)
do_statusbar_right();
/* Handle any editing shortcut, and return TRUE when handled. */
bool handle_editing(functionptrtype function)
{
if (function == do_left)
do_statusbar_left();
else if (function == do_right)
do_statusbar_right();
#ifndef NANO_TINY
else if (shortcut->func == to_prev_word)
do_statusbar_prev_word();
else if (shortcut->func == to_next_word)
do_statusbar_next_word();
else if (function == to_prev_word)
do_statusbar_prev_word();
else if (function == to_next_word)
do_statusbar_next_word();
#endif
else if (shortcut->func == do_home)
do_statusbar_home();
else if (shortcut->func == do_end)
do_statusbar_end();
/* When in restricted mode at the "Write File" prompt and the
* filename isn't blank, disallow any input and deletion. */
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
openfile->filename[0] != '\0' &&
(shortcut->func == do_verbatim_input ||
shortcut->func == cut_text ||
shortcut->func == paste_text ||
shortcut->func == do_delete ||
shortcut->func == do_backspace))
;
#ifdef ENABLE_NANORC
else if (shortcut->func == (functionptrtype)implant)
implant(shortcut->expansion);
#endif
else if (shortcut->func == do_verbatim_input)
do_statusbar_verbatim_input();
else if (shortcut->func == cut_text)
do_statusbar_cut_text();
else if (shortcut->func == do_delete)
do_statusbar_delete();
else if (shortcut->func == do_backspace)
do_statusbar_backspace();
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;
}
else if (function == do_home)
do_statusbar_home();
else if (function == do_end)
do_statusbar_end();
/* When in restricted mode at the "Write File" prompt and the
* filename isn't blank, disallow any input and deletion. */
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE && openfile->filename[0] &&
(function == do_verbatim_input ||
function == do_delete || function == do_backspace ||
function == cut_text || function == paste_text))
;
else if (function == do_verbatim_input)
do_statusbar_verbatim_input();
else if (function == do_delete)
do_statusbar_delete();
else if (function == do_backspace)
do_statusbar_backspace();
else if (function == cut_text)
lop_the_answer();
#ifndef NANO_TINY
else if (function == copy_text)
copy_the_answer();
else if (function == paste_text) {
if (cutbuffer)
paste_into_answer();
}
#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
@@ -392,47 +362,48 @@ void draw_the_promptbar(void)
end_page = get_statusbar_page_start(base, base + breadth(answer) - 1);
/* Color the prompt bar over its full width. */
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
wattron(footwin, interface_color_pair[PROMPT_BAR]);
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
mvwaddstr(bottomwin, 0, 0, prompt);
waddch(bottomwin, ':');
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
mvwaddstr(footwin, 0, 0, prompt);
waddch(footwin, ':');
waddch(footwin, (the_page == 0) ? ' ' : '<');
expanded = display_string(answer, the_page, COLS - base, FALSE, TRUE);
waddstr(bottomwin, expanded);
waddstr(footwin, expanded);
free(expanded);
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)
/* Work around a cursor-misplacement bug -- https://sv.gnu.org/bugs/?59808. */
if (ISSET(NO_HELP)) {
wmove(bottomwin, 0, 0);
wrefresh(bottomwin);
wmove(footwin, 0, 0);
wrefresh(footwin);
}
#endif
/* Place the cursor at the right spot. */
wmove(bottomwin, 0, column - the_page);
wnoutrefresh(bottomwin);
wmove(footwin, 0, column - the_page);
wnoutrefresh(footwin);
}
#ifndef NANO_TINY
/* Remove or add the pipe character at the answer's head. */
void add_or_remove_pipe_symbol_from_answer(void)
{
if (answer[0] == '|') {
if (*answer == '|') {
memmove(answer, answer + 1, strlen(answer));
if (typing_x > 0)
typing_x--;
} else {
answer = nrealloc(answer, strlen(answer) + 2);
memmove(answer + 1, answer, strlen(answer) + 1);
answer[0] = '|';
*answer = '|';
typing_x++;
}
}
@@ -442,9 +413,6 @@ void add_or_remove_pipe_symbol_from_answer(void)
functionptrtype acquire_an_answer(int *actual, bool *listed,
linestruct **history_list, void (*refresh_func)(void))
{
int kbinput = ERR;
bool finished;
functionptrtype func;
#ifdef ENABLE_HISTORIES
char *stored_string = NULL;
/* Whatever the answer was before the user foraged into history. */
@@ -454,7 +422,13 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
size_t fragment_length = 0;
/* The length of the fragment that the user tries to tab complete. */
#endif
#endif /* ENABLE_HISTORIES */
#endif
#ifndef NANO_TINY
bool bracketed_paste = FALSE;
#endif
const keystruct *shortcut;
functionptrtype function;
int input;
if (typing_x > strlen(answer))
typing_x = strlen(answer);
@@ -462,35 +436,61 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
while (TRUE) {
draw_the_promptbar();
kbinput = do_statusbar_input(&finished);
/* Read in one keystroke. */
input = get_kbinput(footwin, VISIBLE);
#ifndef NANO_TINY
/* If the window size changed, go reformat the prompt string. */
if (kbinput == KEY_WINCH) {
refresh_func();
*actual = KEY_WINCH;
if (input == THE_WINDOW_RESIZED) {
*actual = THE_WINDOW_RESIZED;
#ifdef ENABLE_HISTORIES
free(stored_string);
#endif
return NULL;
}
#endif /* !NANO_TINY */
if (input == START_OF_PASTE || input == END_OF_PASTE)
bracketed_paste = (input == START_OF_PASTE);
#endif
#ifdef ENABLE_MOUSE
/* For a click on a shortcut, read in the resulting keycode. */
if (input == KEY_MOUSE && process_prompt_click() == 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);
#ifndef NANO_TINY
/* Tabs in an external paste are not commands. */
if (input == '\t' && bracketed_paste)
function = NULL;
#endif
/* When it's a normal character, add it to the answer. */
absorb_character(input, function);
if (func == do_cancel || func == do_enter)
#ifndef NANO_TINY
/* Ignore any commands inside an external paste. */
if (bracketed_paste) {
if (function && function != do_nothing)
beep();
continue;
}
#endif
if (function == do_cancel || function == do_enter)
break;
#ifdef ENABLE_TABCOMP
if (func == do_tab) {
if (function == do_tab) {
#ifdef ENABLE_HISTORIES
if (history_list != NULL) {
if (history_list) {
if (!previous_was_tab)
fragment_length = strlen(answer);
if (fragment_length > 0) {
answer = get_history_completion(history_list,
answer, fragment_length);
answer = get_history_completion(history_list, answer, fragment_length);
typing_x = strlen(answer);
}
} else
@@ -499,9 +499,9 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
if ((currmenu & (MINSERTFILE|MWRITEFILE|MGOTODIR)) && !ISSET(RESTRICTED))
answer = input_tab(answer, &typing_x, refresh_func, listed);
} else
#endif /* ENABLE_TABCOMP */
#endif
#ifdef ENABLE_HISTORIES
if (func == get_older_item && history_list != NULL) {
if (function == get_older_item && history_list) {
/* If this is the first step into history, start at the bottom. */
if (stored_string == NULL)
reset_history_pointer_for(*history_list);
@@ -511,14 +511,14 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
stored_string = mallocstrcpy(stored_string, answer);
/* If there is an older item, move to it and copy its string. */
if ((*history_list)->prev != NULL) {
if ((*history_list)->prev) {
*history_list = (*history_list)->prev;
answer = mallocstrcpy(answer, (*history_list)->data);
typing_x = strlen(answer);
}
} else if (func == get_newer_item && history_list != NULL) {
} else if (function == get_newer_item && history_list) {
/* If there is a newer item, move to it and copy its string. */
if ((*history_list)->next != NULL) {
if ((*history_list)->next) {
*history_list = (*history_list)->next;
answer = mallocstrcpy(answer, (*history_list)->data);
typing_x = strlen(answer);
@@ -531,43 +531,57 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
}
} else
#endif /* ENABLE_HISTORIES */
/* If we ran a function that should not exit from the prompt... */
if (func == do_help || func == full_refresh)
finished = FALSE;
if (function == do_help || function == full_refresh)
function();
#ifndef NANO_TINY
else if (func == do_nothing)
finished = FALSE;
else if (func == do_toggle) {
else if (function == do_toggle && shortcut->toggle == NO_HELP) {
TOGGLE(NO_HELP);
window_init();
focusing = FALSE;
refresh_func();
bottombars(currmenu);
finished = FALSE;
}
} else if (function == do_nothing)
;
#endif
/* If we have a shortcut with an associated function, break out if
* we're finished after running or trying to run the function. */
if (finished)
break;
#ifdef ENABLE_NANORC
else if (function == (functionptrtype)implant)
implant(shortcut->expansion);
#endif
else if (function && !handle_editing(function)) {
/* When it's a permissible shortcut, run it and done. */
if (!ISSET(VIEW_MODE) || !changes_something(function)) {
#ifndef NANO_TINY
/* When invoking a tool at the Execute prompt, stash an "answer". */
if (currmenu == MEXECUTE)
foretext = mallocstrcpy(foretext, answer);
#endif
function();
break;
} else
beep();
}
#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP)
previous_was_tab = (func == do_tab);
previous_was_tab = (function == do_tab);
#endif
}
#ifndef NANO_TINY
/* When an external command was run, clear a possibly stashed answer. */
if (currmenu == MEXECUTE && function == do_enter)
*foretext = '\0';
#endif
#ifdef ENABLE_HISTORIES
/* If the history pointer was moved, point it at the bottom again. */
if (stored_string != NULL) {
if (stored_string) {
reset_history_pointer_for(*history_list);
free(stored_string);
}
#endif
*actual = kbinput;
*actual = input;
return func;
return function;
}
/* Ask a question on the status bar. Return 0 when text was entered,
@@ -577,10 +591,10 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
int do_prompt(int menu, const char *provided, linestruct **history_list,
void (*refresh_func)(void), const char *msg, ...)
{
functionptrtype function = NULL;
bool listed = FALSE;
va_list ap;
int retval;
functionptrtype func = NULL;
bool listed = FALSE;
/* Save a possible current status-bar x position and prompt. */
size_t was_typing_x = typing_x;
char *saved_prompt = prompt;
@@ -602,25 +616,27 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
lastmessage = VACUUM;
func = acquire_an_answer(&retval, &listed, history_list, refresh_func);
function = acquire_an_answer(&retval, &listed, history_list, refresh_func);
free(prompt);
prompt = saved_prompt;
#ifndef NANO_TINY
if (retval == KEY_WINCH)
if (retval == THE_WINDOW_RESIZED)
goto redo_theprompt;
#endif
/* If we're done with this prompt, restore the x position to what
* it was at a possible previous prompt. */
if (func == do_cancel || func == do_enter)
/* Restore a possible previous prompt and maybe the typing position. */
prompt = saved_prompt;
if (function == do_cancel || function == do_enter ||
#ifdef ENABLE_BROWSER
function == to_first_file || function == to_last_file ||
#endif
function == to_first_line || function == to_last_line)
typing_x = was_typing_x;
/* If we left the prompt via Cancel or Enter, set the return value
* properly. */
if (func == do_cancel)
/* Set the proper return value for Cancel and Enter. */
if (function == do_cancel)
retval = -1;
else if (func == do_enter)
else if (function == do_enter)
retval = (*answer == '\0') ? -2 : 0;
if (lastmessage == VACUUM)
@@ -635,20 +651,24 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
return retval;
}
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
* 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. */
int do_yesno_prompt(bool all, const char *msg)
#define UNDECIDED -2
/* Ask a simple Yes/No (and optionally All) question on the status bar
* 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
* 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. */
const char *yesstr = _("Yy");
const char *nostr = _("Nn");
const char *allstr = _("Aa");
const keystruct *shortcut;
functionptrtype function;
while (choice == -2) {
while (choice == UNDECIDED) {
#ifdef ENABLE_NLS
char letter[MAXCHARLEN + 1];
int index = 0;
@@ -669,42 +689,45 @@ int do_yesno_prompt(bool all, const char *msg)
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
sprintf(shortstr, " %c", yesstr[0]);
wmove(bottomwin, 1, 0);
wmove(footwin, 1, 0);
post_one_key(shortstr, _("Yes"), width);
shortstr[1] = nostr[0];
wmove(bottomwin, 2, 0);
wmove(footwin, 2, 0);
post_one_key(shortstr, _("No"), width);
if (all) {
if (withall) {
shortstr[1] = allstr[0];
wmove(bottomwin, 1, width);
wmove(footwin, 1, width);
post_one_key(shortstr, _("All"), width);
}
wmove(bottomwin, 2, width);
wmove(footwin, 2, width);
post_one_key(cancelshortcut->keystr, _("Cancel"), width);
}
/* Color the prompt bar over its full width and display the question. */
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
wnoutrefresh(bottomwin);
wattron(footwin, interface_color_pair[PROMPT_BAR]);
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
mvwaddnstr(footwin, 0, 0, question, actual_x(question, COLS - 1));
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
wnoutrefresh(footwin);
currmenu = MYESNO;
/* When not replacing, show the cursor while waiting for a key. */
kbinput = get_kbinput(bottomwin, !all);
kbinput = get_kbinput(footwin, !withall);
#ifndef NANO_TINY
if (kbinput == KEY_WINCH)
if (kbinput == THE_WINDOW_RESIZED)
continue;
/* Accept the first character of an external paste. */
if (bracketed_paste && kbinput == BRACKETED_PASTE_MARKER)
kbinput = get_kbinput(bottomwin, BLIND);
/* Accept first character of an external paste and ignore the rest. */
if (kbinput == START_OF_PASTE) {
kbinput = get_kbinput(footwin, BLIND);
while (get_kbinput(footwin, BLIND) != END_OF_PASTE)
;
}
#endif
#ifdef ENABLE_NLS
@@ -712,60 +735,43 @@ int do_yesno_prompt(bool all, const char *msg)
#ifdef ENABLE_UTF8
/* If the received code is a UTF-8 starter byte, get also the
* continuation bytes and assemble them into one letter. */
if (using_utf8() && 0xC0 <= kbinput && kbinput <= 0xF7) {
if (0xC0 <= kbinput && kbinput <= 0xF7 && using_utf8) {
int extras = (kbinput / 16) % 4 + (kbinput <= 0xCF ? 1 : 0);
while (extras <= get_key_buffer_len() && extras-- > 0)
letter[index++] = (unsigned char)get_kbinput(bottomwin, !all);
while (extras <= waiting_keycodes() && extras-- > 0)
letter[index++] = (unsigned char)get_kbinput(footwin, !withall);
}
#endif
letter[index] = '\0';
/* See if the typed letter is in the Yes, No, or All strings. */
if (strstr(yesstr, letter) != NULL)
choice = 1;
else if (strstr(nostr, letter) != NULL)
choice = 0;
else if (all && strstr(allstr, letter) != NULL)
choice = 2;
if (strstr(yesstr, letter))
choice = YES;
else if (strstr(nostr, letter))
choice = NO;
else if (withall && strstr(allstr, letter))
choice = ALL;
else
#endif /* ENABLE_NLS */
if (strchr("Yy", kbinput) != NULL)
choice = 1;
else if (strchr("Nn", kbinput) != NULL)
choice = 0;
else if (all && strchr("Aa", kbinput) != NULL)
choice = 2;
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;
if (strchr("Yy", kbinput))
choice = YES;
else if (strchr("Nn", kbinput))
choice = NO;
else if (withall && strchr("Aa", kbinput))
choice = ALL;
/* x == 0 means Yes or No, y == 0 means Yes or All. */
choice = -2 * x * y + x - y + 1;
if (choice != UNDECIDED)
break;
if (choice == 2 && !all)
choice = -2;
}
}
#endif
else if (func_from_key(&kbinput) == full_refresh)
shortcut = get_shortcut(kbinput);
function = (shortcut ? shortcut->func : NULL);
if (function == do_cancel)
choice = CANCEL;
else if (function == full_refresh)
full_refresh();
#ifndef NANO_TINY
else if (func_from_key(&kbinput) == do_toggle) {
else if (function == do_toggle && shortcut->toggle == NO_HELP) {
TOGGLE(NO_HELP);
window_init();
titlebar(NULL);
@@ -773,15 +779,38 @@ int do_yesno_prompt(bool all, const char *msg)
edit_refresh();
focusing = TRUE;
}
#endif
/* Interpret ^N as "No", to allow exiting in anger, and ^Q or ^X too. */
else if (kbinput == '\x0E' || (kbinput == '\x11' && !ISSET(MODERN_BINDINGS)) ||
(kbinput == '\x18' && ISSET(MODERN_BINDINGS))) {
choice = NO;
if (kbinput != '\x0E') /* ^X^Q makes nano exit with an error. */
final_status = 2;
/* Also, interpret ^Y as "Yes, and ^A as "All". */
} else if (kbinput == '\x19')
choice = YES;
else if (kbinput == '\x01' && withall)
choice = ALL;
#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) == 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
else
beep();
#ifndef NANO_TINY
/* Ignore the rest of an external paste. */
while (bracketed_paste)
kbinput = get_kbinput(bottomwin, BLIND);
#endif
}
return choice;

View File

@@ -1,7 +1,7 @@
/**************************************************************************
* prototypes.h -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -14,7 +14,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -24,24 +24,31 @@
#ifndef NANO_TINY
extern volatile sig_atomic_t the_window_resized;
extern volatile sig_atomic_t resized_for_browser;
#endif
extern bool on_a_vt;
extern bool using_utf8;
extern bool shifted_metas;
extern bool meta_key;
extern bool shift_held;
extern bool mute_modifiers;
extern bool bracketed_paste;
extern bool we_are_running;
extern bool more_than_one;
extern bool report_size;
extern bool ran_a_tool;
extern char *foretext;
extern int final_status;
extern bool inhelp;
extern char *title;
extern bool united_sidescroll;
extern bool focusing;
extern bool as_an_at;
@@ -68,18 +75,19 @@ extern int controlup, controldown;
extern int controlhome, controlend;
#ifndef NANO_TINY
extern int controldelete, controlshiftdelete;
extern int shiftleft, shiftright;
extern int shiftup, shiftdown;
extern int shiftcontrolleft, shiftcontrolright;
extern int shiftcontrolup, shiftcontroldown;
extern int shiftcontrolhome, shiftcontrolend;
extern int altleft, altright;
extern int altup, altdown;
extern int althome, altend;
extern int altpageup, altpagedown;
extern int altinsert, altdelete;
extern int shiftaltleft, shiftaltright;
extern int shiftaltup, shiftaltdown;
#endif
extern int mousefocusin, mousefocusout;
#ifdef ENABLED_WRAPORJUSTIFY
extern ssize_t fill;
@@ -87,15 +95,16 @@ extern size_t wrap_at;
#endif
extern WINDOW *topwin;
extern WINDOW *edit;
extern WINDOW *bottomwin;
extern WINDOW *midwin;
extern WINDOW *footwin;
extern int editwinrows;
extern int editwincols;
extern int margin;
extern int thebar;
extern int sidebar;
#ifndef NANO_TINY
extern int *bardata;
extern ssize_t stripe_column;
extern int cycling_aim;
#endif
extern linestruct *cutbuffer;
@@ -141,6 +150,9 @@ extern char *alt_speller;
extern syntaxtype *syntaxes;
extern char *syntaxstr;
extern bool have_palette;
extern bool rescind_colors;
extern bool perturbed;
extern bool recook;
#endif
extern bool refresh_needed;
@@ -178,6 +190,9 @@ extern char *startup_problem;
#endif
#ifdef ENABLE_NANORC
extern char *custom_nanorc;
extern char *commandname;
extern keystruct *planted_shortcut;
#endif
extern bool spotlighted;
@@ -195,10 +210,6 @@ void to_last_file(void);
#endif
/* Most functions in chars.c. */
#ifdef ENABLE_UTF8
void utf8_init(void);
bool using_utf8(void);
#endif
bool is_alpha_char(const char *c);
bool is_blank_char(const char *c);
bool is_cntrl_char(const char *c);
@@ -221,7 +232,7 @@ char *mbstrcasestr(const char *haystack, const char *needle);
char *revstrstr(const char *haystack, const char *needle, const char *pointer);
char *mbrevstrcasestr(const char *haystack, const char *needle, const char *pointer);
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
char *mbstrchr(const char *string, const char *chr);
const char *mbstrchr(const char *string, const char *chr);
#endif
#ifndef NANO_TINY
char *mbstrpbrk(const char *string, const char *accept);
@@ -231,6 +242,9 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer);
bool has_blank_char(const char *string);
#endif
bool white_string(const char *string);
#if defined(ENABLE_SPELLER) || defined(ENABLE_COLOR)
void strip_leading_blanks_from(char *string);
#endif
/* Most functions in color.c. */
#ifdef ENABLE_COLOR
@@ -242,6 +256,7 @@ void precalc_multicolorinfo(void);
#endif
/* Most functions in cut.c. */
void expunge(undo_type action);
void do_delete(void);
void do_backspace(void);
#ifndef NANO_TINY
@@ -260,8 +275,8 @@ void cut_text(void);
void cut_till_eof(void);
void zap_text(void);
void copy_marked_region(void);
void copy_text(void);
#endif
void copy_text(void);
void paste_text(void);
/* Most functions in files.c. */
@@ -295,16 +310,14 @@ bool outside_of_confinement(const char *currpath, bool allow_tabcomp);
void init_backup_dir(void);
#endif
int copy_file(FILE *inn, FILE *out, bool close_out);
bool write_file(const char *name, FILE *thefile, bool normal,
kind_of_writing_type method, bool annotate);
bool write_file(const char *name, FILE *thefile, writing_type method, bool annotate);
#ifndef NANO_TINY
bool write_region_to_file(const char *name, FILE *stream, bool normal,
kind_of_writing_type method);
bool write_region_to_file(const char *name, FILE *stream, writing_type method);
#endif
int write_it_out(bool exiting, bool withprompt);
void do_writeout(void);
void do_savefile(void);
char *real_dir_from_tilde(const char *path);
char *expand_leading_tilde(const char *path);
#if defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
int diralphasort(const void *va, const void *vb);
#endif
@@ -313,12 +326,12 @@ char *input_tab(char *buf, size_t *place, void (*refresh_func)(void), bool *list
#endif
/* 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);
const keystruct *get_shortcut(int *keycode);
functionptrtype func_from_key(int *keycode);
const keystruct *get_shortcut(const int keycode);
functionptrtype func_from_key(const int keycode);
#if defined(ENABLE_BROWSER) || defined(ENABLE_HELP)
functionptrtype interpret(int *keycode);
functionptrtype interpret(const int keycode);
#endif
int keycode_from_string(const char *keystring);
void shortcut_init(void);
@@ -341,9 +354,9 @@ char *get_history_completion(linestruct **h, char *s, size_t len);
bool have_statedir(void);
void load_history(void);
void save_history(void);
void load_poshistory(void);
void update_poshistory(void);
bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
void load_positions_register(void);
void update_positions_register(void);
void restore_cursor_position_if_any(void);
#endif
/* Most functions in move.c. */
@@ -351,6 +364,12 @@ void to_first_line(void);
void to_last_line(void);
void do_page_up(void);
void do_page_down(void);
#ifndef NANO_TINY
void to_top_row(void);
void to_bottom_row(void);
void do_cycle(void);
void do_center(void);
#endif
#ifdef ENABLE_JUSTIFY
void do_para_begin(linestruct **line);
void do_para_end(linestruct **line);
@@ -359,8 +378,8 @@ void to_para_end(void);
#endif
void to_prev_block(void);
void to_next_block(void);
void do_prev_word(void);
bool do_next_word(bool after_ends);
void do_prev_word(bool allow_folded);
bool do_next_word(bool after_ends, bool allow_folded);
void to_prev_word(void);
void to_next_word(void);
void do_home(void);
@@ -370,10 +389,14 @@ void do_down(void);
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
void do_scroll_up(void);
void do_scroll_down(void);
void do_center(void);
#endif
void do_left(void);
void do_right(void);
void move_cursor_to_proper_column(void);
#ifndef NANO_TINY
void do_scroll_left(void);
void do_scroll_right(void);
#endif
/* Most functions in nano.c. */
linestruct *make_new_node(linestruct *prevnode);
@@ -421,7 +444,8 @@ void terminal_init(void);
void confirm_margin(void);
#endif
void unbound_key(int code);
bool okay_for_view(const keystruct *shortcut);
bool changes_something(functionptrtype f);
void suck_up_input_and_paste_it(void);
void inject(char *burst, size_t count);
/* Most functions in prompt.c. */
@@ -430,7 +454,7 @@ void put_cursor_at_end_of_answer(void);
void add_or_remove_pipe_symbol_from_answer(void);
int do_prompt(int menu, const char *provided, linestruct **history_list,
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. */
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
@@ -438,6 +462,7 @@ void display_rcfile_errors(void);
void jot_error(const char *msg, ...);
#endif
#ifdef ENABLE_NANORC
keystruct *strtosc(const char *input);
#ifdef ENABLE_COLOR
void parse_one_include(char *file, syntaxtype *syntax);
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
@@ -462,11 +487,18 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
const linestruct *real_current, size_t *real_current_x);
void do_replace(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_and_column(ssize_t line, ssize_t column, bool retain_answer,
bool interactive);
#endif
void do_gotolinecolumn(void);
void ask_for_line_and_column(char *provided);
void goto_line_and_column(ssize_t line, ssize_t column, bool hugfloor);
#ifndef NANO_TINY
size_t get_matchbrackets_halfway(void);
int find_matching_bracket_pos(linestruct **line, size_t *xpos);
bool find_terminus_of_bracketed_region(linestruct **line, size_t *xpos, size_t bracket_half, bool reverse);
bool find_bracketed_region(linestruct *in_region,
linestruct **top, linestruct **bot);
void do_find_bracket(void);
void put_or_lift_anchor(void);
void to_prev_anchor(void);
@@ -513,15 +545,19 @@ void do_full_justify(void);
#ifdef ENABLE_SPELLER
void do_spell(void);
#endif
#ifdef ENABLE_COLOR
#ifdef ENABLE_LINTER
void do_linter(void);
#endif
#ifdef ENABLE_FORMATTER
void do_formatter(void);
#endif
#ifndef NANO_TINY
void count_lines_words_and_characters(void);
#endif
void do_verbatim_input(void);
#ifdef ENABLE_WORDCOMPLETION
void complete_a_word(void);
#endif
/* All functions in utils.c. */
void get_homedir(void);
@@ -531,7 +567,7 @@ int digits(ssize_t n);
bool parse_num(const char *str, ssize_t *result);
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_LF_to_NUL(char *string);
size_t recode_LF_to_NUL(char *string);
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
void free_chararray(char **array, size_t len);
#endif
@@ -542,15 +578,15 @@ const char *strstrwrapper(const char *haystack, const char *needle,
const char *start);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
char *measured_copy(const char *string, size_t count);
char *mallocstrcpy(char *dest, const char *src);
char *measured_copy(const char *string, size_t count);
char *copy_of(const char *string);
char *free_and_assign(char *dest, char *src);
size_t get_page_start(size_t column);
size_t xplustabs(void);
size_t actual_x(const char *text, size_t column);
size_t wideness(const char *text, size_t maxlen);
size_t wideness(const char *text, size_t count);
size_t breadth(const char *text);
size_t xplustabs(void);
void new_magicline(void);
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
void remove_magicline(void);
@@ -561,28 +597,33 @@ void get_region(linestruct **top, size_t *top_x, linestruct **bot, size_t *bot_x
void get_range(linestruct **top, linestruct **bot);
#endif
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);
#endif
/* 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 run_macro(void);
size_t get_key_buffer_len(void);
#endif
size_t waiting_keycodes(void);
void put_back(int keycode);
#ifdef ENABLE_NANORC
void implant(const char *string);
#endif
int parse_kbinput(WINDOW *win);
int get_input(WINDOW *win);
int get_kbinput(WINDOW *win, bool showcursor);
char *get_verbatim_kbinput(WINDOW *win, size_t *count);
#ifdef ENABLE_MOUSE
int get_mouseinput(int *mouse_y, int *mouse_x, bool allow_shortcuts);
int get_mouseinput(int *mouse_y, int *mouse_x);
#endif
void blank_edit(void);
void blank_statusbar(void);
void wipe_statusbar(void);
void blank_bottombars(void);
void check_statusblank(void);
void blank_it_when_expired(void);
void set_blankdelay_to_one(void);
char *display_string(const char *buf, size_t column, size_t span,
bool isdata, bool isprompt);
@@ -594,6 +635,7 @@ void warn_and_briefly_pause(const char *msg);
void bottombars(int menu);
void post_one_key(const char *keystroke, const char *tag, int width);
void place_the_cursor(void);
int update_line_at(linestruct *line, size_t index, int row);
int update_line(linestruct *line, size_t index);
#ifndef NANO_TINY
int update_softwrapped_line(linestruct *line);
@@ -604,8 +646,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);
void edit_scroll(bool direction);
#ifndef NANO_TINY
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
bool *end_of_line);
size_t get_softwrap_breakpoint(const char *linedata, size_t leftedge,
bool *kickoff, bool *end_of_line);
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 leftedge_for(size_t column, linestruct *line);
@@ -645,7 +687,6 @@ void goto_dir(void);
void do_nothing(void);
void do_toggle(void);
void dos_format(void);
void mac_format(void);
void append_it(void);
void prepend_it(void);
void back_it_up(void);
@@ -658,3 +699,12 @@ void flip_newbuffer(void);
#endif
void discard_buffer(void);
void do_cancel(void);
/* Most functions in folding.c. */
#ifdef ENABLE_FOLDING
void do_fold_segment(void);
void unfold_folded_segment(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

View File

@@ -1,10 +1,10 @@
/**************************************************************************
* rcfile.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2014 Mike Frysinger *
* Copyright (C) 2019 Brand Huntsman *
* Copyright (C) 2014-2020 Benno Schulenberg *
* Copyright (C) 2014-2021, 2024 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -17,7 +17,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -64,12 +64,13 @@ static const rcoption rcopts[] = {
{"mouse", USE_MOUSE},
#endif
#ifdef ENABLE_MULTIBUFFER
{"multibuffer", MULTIBUFFER},
{"multibuffer", NEW_BUFFER}, /* Deprecated; remove in 2031. */
{"newbuffer", NEW_BUFFER},
#endif
{"nohelp", NO_HELP},
{"nonewlines", NO_NEWLINES},
#ifdef ENABLE_WRAPPING
{"nowrap", NO_WRAP}, /* Deprecated; remove in 2024. */
{"nowrap", NO_WRAP}, /* Deprecated; remove in 2027. */
#endif
#ifdef ENABLE_OPERATINGDIR
{"operatingdir", 0},
@@ -90,9 +91,6 @@ static const rcoption rcopts[] = {
#ifdef ENABLE_SPELLER
{"speller", 0},
#endif
{"suspend", SUSPENDABLE}, /* Deprecated; remove in 2022. */
{"suspendable", SUSPENDABLE}, /* Obsolete; remove in 2022. */
{"tempfile", SAVE_ON_EXIT}, /* Deprecated; remove in 2022. */
#ifndef NANO_TINY
{"afterends", AFTER_ENDS},
{"allow_insecure_backup", INSECURE_BACKUP},
@@ -101,6 +99,7 @@ static const rcoption rcopts[] = {
{"backup", MAKE_BACKUP},
{"backupdir", 0},
{"bookstyle", BOOKSTYLE},
{"colonparsing", COLON_PARSING},
{"cutfromcursor", CUT_FROM_CURSOR},
{"emptyline", EMPTY_LINE},
{"guidestripe", 0},
@@ -113,12 +112,14 @@ static const rcoption rcopts[] = {
{"showcursor", SHOW_CURSOR},
{"smarthome", SMART_HOME},
{"softwrap", SOFTWRAP},
{"solosidescroll", SOLO_SIDESCROLL},
{"stateflags", STATEFLAGS},
{"tabsize", 0},
{"tabstospaces", TABS_TO_SPACES},
{"trimblanks", TRIM_BLANKS},
{"unix", MAKE_IT_UNIX},
{"whitespace", 0},
{"whitespacedisplay", WHITESPACE_DISPLAY},
{"wordbounds", WORD_BOUNDS},
{"wordchars", 0},
{"zap", LET_THEM_ZAP},
@@ -137,6 +138,7 @@ static const rcoption rcopts[] = {
{"errorcolor", 0},
{"keycolor", 0},
{"functioncolor", 0},
{"foldedcolor", 0},
#endif
{NULL, 0}
};
@@ -156,18 +158,6 @@ static bool seen_color_command = FALSE;
static colortype *lastcolor = NULL;
/* The end of the color list for the current syntax. */
#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 */
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
@@ -200,7 +190,7 @@ void jot_error(const char *msg, ...)
if (startup_problem == NULL) {
#ifdef ENABLE_NANORC
if (nanorc != NULL) {
if (nanorc) {
snprintf(textbuf, MAXSIZE, _("Mistakes in '%s'"), nanorc);
startup_problem = copy_of(textbuf);
} else
@@ -209,8 +199,7 @@ void jot_error(const char *msg, ...)
}
#ifdef ENABLE_NANORC
if (lineno > 0)
length = snprintf(textbuf, MAXSIZE, _("Error in %s on line %zu: "),
nanorc, lineno);
length = snprintf(textbuf, MAXSIZE, _("Error in %s on line %zu: "), nanorc, lineno);
#endif
va_start(ap, msg);
length += vsnprintf(textbuf + length, MAXSIZE - length, _(msg), ap);
@@ -260,6 +249,8 @@ keystruct *strtosc(const char *input)
s->func = do_replace;
else if (!strcmp(input, "cut"))
s->func = cut_text;
else if (!strcmp(input, "copy"))
s->func = copy_text;
else if (!strcmp(input, "paste"))
s->func = paste_text;
#ifndef NANO_TINY
@@ -267,8 +258,6 @@ keystruct *strtosc(const char *input)
s->func = do_execute;
else if (!strcmp(input, "cutrestoffile"))
s->func = cut_till_eof;
else if (!strcmp(input, "copy"))
s->func = copy_text;
else if (!strcmp(input, "zap"))
s->func = zap_text;
else if (!strcmp(input, "mark"))
@@ -279,14 +268,15 @@ keystruct *strtosc(const char *input)
!strcmp(input, "speller"))
s->func = do_spell;
#endif
#ifdef ENABLE_COLOR
#ifdef ENABLE_LINTER
else if (!strcmp(input, "linter"))
s->func = do_linter;
#endif
#ifdef ENABLE_FORMATTER
else if (!strcmp(input, "formatter"))
s->func = do_formatter;
#endif
else if (!strcmp(input, "location") ||
!strcmp(input, "curpos")) /* Deprecated; remove in 2022. */
else if (!strcmp(input, "location"))
s->func = report_cursor_position;
else if (!strcmp(input, "gotoline"))
s->func = do_gotolinecolumn;
@@ -335,6 +325,8 @@ keystruct *strtosc(const char *input)
s->func = do_undo;
else if (!strcmp(input, "redo"))
s->func = do_redo;
else if (!strcmp(input, "suspend"))
s->func = do_suspend;
#endif
else if (!strcmp(input, "left") ||
!strcmp(input, "back"))
@@ -348,13 +340,17 @@ keystruct *strtosc(const char *input)
else if (!strcmp(input, "down") ||
!strcmp(input, "nextline"))
s->func = do_down;
#ifndef NANO_TINY
else if (!strcmp(input, "scrollleft"))
s->func = do_scroll_left;
else if (!strcmp(input, "scrollright"))
s->func = do_scroll_right;
#endif
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
else if (!strcmp(input, "scrollup"))
s->func = do_scroll_up;
else if (!strcmp(input, "scrolldown"))
s->func = do_scroll_down;
else if (!strcmp(input, "center"))
s->func = do_center;
#endif
else if (!strcmp(input, "prevword"))
s->func = to_prev_word;
@@ -368,6 +364,16 @@ keystruct *strtosc(const char *input)
s->func = to_prev_block;
else if (!strcmp(input, "nextblock"))
s->func = to_next_block;
#ifndef NANO_TINY
else if (!strcmp(input, "toprow"))
s->func = to_top_row;
else if (!strcmp(input, "bottomrow"))
s->func = to_bottom_row;
else if (!strcmp(input, "center"))
s->func = do_center;
else if (!strcmp(input, "cycle"))
s->func = do_cycle;
#endif
else if (!strcmp(input, "pageup") ||
!strcmp(input, "prevpage"))
s->func = do_page_up;
@@ -396,10 +402,6 @@ keystruct *strtosc(const char *input)
s->func = do_backspace;
else if (!strcmp(input, "refresh"))
s->func = full_refresh;
#ifndef NANO_TINY
else if (!strcmp(input, "suspend"))
s->func = do_suspend;
#endif
else if (!strcmp(input, "casesens"))
s->func = case_sens_void;
else if (!strcmp(input, "regexp"))
@@ -408,8 +410,6 @@ keystruct *strtosc(const char *input)
s->func = backwards_void;
else if (!strcmp(input, "flipreplace"))
s->func = flip_replace;
else if (!strcmp(input, "flipgoto"))
s->func = flip_goto;
#ifdef ENABLE_HISTORIES
else if (!strcmp(input, "older"))
s->func = get_older_item;
@@ -419,8 +419,6 @@ keystruct *strtosc(const char *input)
#ifndef NANO_TINY
else if (!strcmp(input, "dosformat"))
s->func = dos_format;
else if (!strcmp(input, "macformat"))
s->func = mac_format;
else if (!strcmp(input, "append"))
s->func = append_it;
else if (!strcmp(input, "prepend"))
@@ -477,8 +475,7 @@ keystruct *strtosc(const char *input)
else if (!strcmp(input, "cutfromcursor"))
s->toggle = CUT_FROM_CURSOR;
#ifdef ENABLE_WRAPPING
else if (!strcmp(input, "breaklonglines") ||
!strcmp(input, "nowrap")) /* Deprecated; remove in 2024. */
else if (!strcmp(input, "breaklonglines"))
s->toggle = BREAK_LONG_LINES;
#endif
else if (!strcmp(input, "tabstospaces"))
@@ -497,6 +494,18 @@ keystruct *strtosc(const char *input)
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. */
int name_to_menu(const char *name)
{
@@ -506,7 +515,7 @@ int name_to_menu(const char *name)
if (strcmp(name, menunames[index]) == 0)
return menusymbols[index];
return -1;
return 0;
}
/* Return the name that corresponds to the given menu symbol. */
@@ -521,12 +530,12 @@ char *menu_to_name(int menu)
return "boooo";
}
/* Parse the next word from the string, null-terminate it, and return
* a pointer to the first character after the null terminator. The
* returned pointer will point to '\0' if we hit the end of the line. */
/* Parse the next word from the string (if any), null-terminate it,
* and return a pointer to the next word. The returned pointer will
* point to '\0' when end-of-line was reached. */
char *parse_next_word(char *ptr)
{
while (!isblank((unsigned char)*ptr) && *ptr != '\0')
while (*ptr && !isblank((unsigned char)*ptr))
ptr++;
if (*ptr == '\0')
@@ -541,25 +550,23 @@ char *parse_next_word(char *ptr)
return ptr;
}
/* Parse an argument, with optional quotes, after a keyword that takes
* one. If the next word starts with a ", we say that it ends with the
* last " of the line. Otherwise, we interpret it as usual, so that the
* arguments can contain "'s too. */
/* Parse an argument (optionally enveloped in double quotes). When the
* argument starts with a ", then the last " of the line indicates its
* end -- meaning that an argument can contain "'s either way. */
char *parse_argument(char *ptr)
{
const char *ptr_save = ptr;
const char *the_start = ptr;
char *last_quote = NULL;
if (*ptr != '"')
return parse_next_word(ptr);
while (*ptr != '\0') {
while (*ptr)
if (*++ptr == '"')
last_quote = ptr;
}
if (last_quote == NULL) {
jot_error(N_("Argument '%s' has an unterminated \""), ptr_save);
jot_error(N_("Argument '%s' has an unterminated \""), the_start);
return NULL;
}
@@ -586,8 +593,7 @@ char *parse_next_regex(char *ptr)
/* Continue until the end of the line, or until a double quote followed
* by end-of-line or a blank. */
while (*ptr != '\0' && (*ptr != '"' ||
(ptr[1] != '\0' && !isblank((unsigned char)ptr[1]))))
while (*ptr && (*ptr != '"' || (ptr[1] && !isblank((unsigned char)ptr[1]))))
ptr++;
if (*ptr == '\0') {
@@ -676,12 +682,12 @@ void begin_new_syntax(char *ptr)
live_syntax->magics = NULL;
live_syntax->linter = NULL;
live_syntax->formatter = NULL;
live_syntax->tab = NULL;
live_syntax->tabstring = NULL;
#ifdef ENABLE_COMMENT
live_syntax->comment = copy_of(GENERAL_COMMENT_CHARACTER);
#endif
live_syntax->color = NULL;
live_syntax->nmultis = 0;
live_syntax->multiscore = 0;
/* Hook the new syntax in at the top of the list. */
live_syntax->next = syntaxes;
@@ -691,13 +697,13 @@ void begin_new_syntax(char *ptr)
seen_color_command = FALSE;
/* The default syntax should have no associated extensions. */
if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') {
if (*ptr && strcmp(live_syntax->name, "default") == 0) {
jot_error(N_("The \"default\" syntax does not accept extensions"));
return;
}
/* If there seem to be extension regexes, pick them up. */
if (*ptr != '\0')
if (*ptr)
grab_and_store("extension", ptr, &live_syntax->extensions);
}
#endif /* ENABLE_COLOR */
@@ -734,9 +740,11 @@ bool is_universal(void (*func)(void))
/* Bind or unbind a key combo, to or from a function. */
void parse_binding(char *ptr, bool dobind)
{
char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
int keycode, menu, mask = 0;
char *keycopy, *keyptr, *menuptr;
keystruct *newsc = NULL;
char *funcptr = NULL;
int keycode, menu;
int mask = 0;
check_for_nonempty_syntax();
@@ -750,12 +758,13 @@ void parse_binding(char *ptr, bool dobind)
keycopy = copy_of(keyptr);
/* Uppercase either the second or the first character of the key name. */
if (keycopy[0] == '^')
keycopy[1] = toupper((unsigned char)keycopy[1]);
else
keycopy[0] = toupper((unsigned char)keycopy[0]);
if (keycopy[0] == '^') {
if ('a' <= keycopy[1] && keycopy[1] <= 'z')
keycopy[1] &= 0x5F;
} else if ('a' <= keycopy[0] && keycopy[0] <= 'z')
keycopy[0] &= 0x5F;
/* Verify that the key name is not too short, to allow the next call. */
/* Verify that the key name is not too short. */
if (keycopy[1] == '\0' || (keycopy[0] == 'M' && keycopy[2] == '\0')) {
jot_error(N_("Key name %s is invalid"), keycopy);
goto free_things;
@@ -780,12 +789,17 @@ void parse_binding(char *ptr, bool dobind)
}
menuptr = ptr;
ptr = parse_next_word(ptr);
parse_next_word(ptr);
if (menuptr[0] == '\0') {
/* TRANSLATORS: Do not translate the word "all". */
jot_error(N_("Must specify a menu (or \"all\") "
"in which to bind/unbind the key"));
jot_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key"));
goto free_things;
}
menu = name_to_menu(menuptr);
if (menu == 0) {
jot_error(N_("Unknown menu: %s"), menuptr);
goto free_things;
}
@@ -803,17 +817,11 @@ void parse_binding(char *ptr, bool dobind)
newsc = strtosc(funcptr);
if (newsc == NULL) {
jot_error(N_("Cannot map name \"%s\" to a function"), funcptr);
jot_error(N_("Unknown function: %s"), funcptr);
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. */
for (keystruct *s = sclist; s != NULL; s = s->next)
if ((s->menus & menu) && s->keycode == keycode)
@@ -848,8 +856,7 @@ void parse_binding(char *ptr, bool dobind)
if (!menu) {
if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE))
jot_error(N_("Function '%s' does not exist in menu '%s'"),
funcptr, menuptr);
jot_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr);
goto free_things;
}
@@ -886,14 +893,14 @@ bool is_good_file(char *file)
struct stat rcinfo;
/* First check that the file exists and is readable. */
if (access(file, R_OK) != 0)
if (access(file, R_OK) < 0)
return FALSE;
/* If the thing exists, it may be neither a directory nor a device. */
if (stat(file, &rcinfo) != -1 && (S_ISDIR(rcinfo.st_mode) ||
if (stat(file, &rcinfo) == 0 && (S_ISDIR(rcinfo.st_mode) ||
S_ISCHR(rcinfo.st_mode) || S_ISBLK(rcinfo.st_mode))) {
jot_error(S_ISDIR(rcinfo.st_mode) ? N_("\"%s\" is a directory") :
N_("\"%s\" is a device file"), file);
jot_error(S_ISDIR(rcinfo.st_mode) ? N_("'%s' is a directory") :
N_("'%s' is a device file"), file);
return FALSE;
} else
return TRUE;
@@ -901,7 +908,7 @@ bool is_good_file(char *file)
#ifdef ENABLE_COLOR
/* 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)
{
char *was_nanorc = nanorc;
@@ -910,7 +917,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
FILE *rcstream;
/* 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;
rcstream = fopen(file, "rb");
@@ -942,7 +949,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
extra = syntax->augmentations;
/* Apply any stored extendsyntax commands. */
while (extra != NULL) {
while (extra) {
char *keyword = extra->data;
char *therest = parse_next_word(extra->data);
@@ -955,6 +962,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
extra = extra->next;
}
/* Indicate that this syntax has been loaded. */
free(syntax->filename);
syntax->filename = NULL;
@@ -974,11 +982,16 @@ void parse_includes(char *ptr)
pattern = ptr;
if (*pattern == '"')
pattern++;
ptr = parse_argument(ptr);
parse_argument(ptr);
if (strlen(pattern) > PATH_MAX) {
jot_error(N_("Path is too long"));
return;
}
/* Expand a tilde first, then try to match the globbing pattern. */
expanded = real_dir_from_tilde(pattern);
result = glob(expanded, GLOB_ERR, NULL, &files);
expanded = expand_leading_tilde(pattern);
result = glob(expanded, GLOB_ERR|GLOB_NOCHECK, NULL, &files);
/* If there are matches, process each of them. Otherwise, only
* report an error if it's something other than zero matches. */
@@ -993,16 +1006,22 @@ void parse_includes(char *ptr)
}
/* 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)
{
/* 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 };
if (COLORS == 256)
return (36 * level[red] + 6 * level[green] + level[blue] + 16);
else
/* Translation table, from 14 intended gray levels to 24 available levels. */
static const short gray[] = { 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 18, 21, 23 };
if (COLORS != 256)
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
@@ -1032,12 +1051,12 @@ short indices[COLORCOUNT] = { COLOR_RED, COLOR_GREEN, COLOR_BLUE,
* vivid to TRUE for a lighter color, and thick for a heavier typeface. */
short color_to_short(const char *colorname, bool *vivid, bool *thick)
{
if (strncmp(colorname, "bright", 6) == 0 && colorname[6] != '\0') {
/* Prefix "bright" is deprecated; remove in 2024. */
if (strncmp(colorname, "bright", 6) == 0 && colorname[6]) {
/* Prefix "bright" is deprecated; remove in 2027. */
*vivid = TRUE;
*thick = TRUE;
colorname += 6;
} else if (strncmp(colorname, "light", 5) == 0 && colorname[5] != '\0') {
} else if (strncmp(colorname, "light", 5) == 0 && colorname[5]) {
*vivid = TRUE;
*thick = FALSE;
colorname += 5;
@@ -1075,40 +1094,40 @@ short color_to_short(const char *colorname, bool *vivid, bool *thick)
/* Parse the color name (or pair of color names) in the given string.
* Return FALSE when any color name is invalid; otherwise return TRUE. */
bool parse_combination(char *combostr, short *fg, short *bg, int *attributes)
bool parse_combination(char *combotext, short *fg, short *bg, int *attributes)
{
bool vivid, thick;
char *comma;
*attributes = A_NORMAL;
if (strncmp(combostr, "bold", 4) == 0) {
if (strncmp(combotext, "bold", 4) == 0) {
*attributes |= A_BOLD;
if (combostr[4] != ',') {
if (combotext[4] != ',') {
jot_error(N_("An attribute requires a subsequent comma"));
return FALSE;
}
combostr += 5;
combotext += 5;
}
if (strncmp(combostr, "italic", 6) == 0) {
if (strncmp(combotext, "italic", 6) == 0) {
#ifdef A_ITALIC
*attributes |= A_ITALIC;
#endif
if (combostr[6] != ',') {
if (combotext[6] != ',') {
jot_error(N_("An attribute requires a subsequent comma"));
return FALSE;
}
combostr += 7;
combotext += 7;
}
comma = strchr(combostr, ',');
comma = strchr(combotext, ',');
if (comma)
*comma = '\0';
if (!comma || comma > combostr) {
*fg = color_to_short(combostr, &vivid, &thick);
if (!comma || comma > combotext) {
*fg = color_to_short(combotext, &vivid, &thick);
if (*fg == BAD_COLOR)
return FALSE;
if (vivid && !thick && COLORS > 8)
@@ -1155,7 +1174,7 @@ void parse_rule(char *ptr, int rex_flags)
return;
}
while (*ptr != '\0') {
while (*ptr) {
regex_t *start_rgx = NULL, *end_rgx = NULL;
/* Intermediate storage for compiled regular expressions. */
colortype *newcolor = NULL;
@@ -1214,22 +1233,22 @@ void parse_rule(char *ptr, int rex_flags)
/* For a multiline rule, give it a number and increase the count. */
if (expectend) {
newcolor->id = live_syntax->nmultis;
live_syntax->nmultis++;
newcolor->id = live_syntax->multiscore;
live_syntax->multiscore++;
}
}
}
/* Parse the argument of an interface color option. */
colortype *parse_interface_color(char *combostr)
/* Set the colors for the given interface element to the given combination. */
void set_interface_color(int element, char *combotext)
{
colortype *trio = nmalloc(sizeof(colortype));
if (!parse_combination(combostr, &trio->fg, &trio->bg, &trio->attributes)) {
free(trio);
return NULL;
if (parse_combination(combotext, &trio->fg, &trio->bg, &trio->attributes)) {
free(color_combo[element]);
color_combo[element] = trio;
} else
return trio;
free(trio);
}
/* Read regex strings enclosed in double quotes from the line pointed at
@@ -1245,7 +1264,7 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
}
/* The default syntax doesn't take any file matching stuff. */
if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') {
if (*ptr && strcmp(live_syntax->name, "default") == 0) {
jot_error(N_("The \"default\" syntax does not accept '%s' regexes"), kind);
return;
}
@@ -1258,11 +1277,11 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
lastthing = *storage;
/* If there was an earlier command, go to the last of those regexes. */
while (lastthing != NULL && lastthing->next != NULL)
while (lastthing && lastthing->next)
lastthing = lastthing->next;
/* Now gather any valid regexes and add them to the linked list. */
while (*ptr != '\0') {
while (*ptr) {
regex_t *packed_rgx = NULL;
regexstring = ++ptr;
@@ -1289,7 +1308,7 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
}
}
/* Gather and store the string after a comment/linter command. */
/* Gather and store the string after a comment/linter/formatter/tabgives command. */
void pick_up_name(const char *kind, char *ptr, char **storage)
{
if (*ptr == '\0') {
@@ -1327,20 +1346,22 @@ bool parse_syntax_commands(char *keyword, char *ptr)
pick_up_name("comment", ptr, &live_syntax->comment);
#endif
} else if (strcmp(keyword, "tabgives") == 0) {
pick_up_name("tabgives", ptr, &live_syntax->tab);
} else if (strcmp(keyword, "linter") == 0)
pick_up_name("tabgives", ptr, &live_syntax->tabstring);
} else if (strcmp(keyword, "linter") == 0) {
pick_up_name("linter", ptr, &live_syntax->linter);
else if (strcmp(keyword, "formatter") == 0)
strip_leading_blanks_from(live_syntax->linter);
} else if (strcmp(keyword, "formatter") == 0) {
pick_up_name("formatter", ptr, &live_syntax->formatter);
else
strip_leading_blanks_from(live_syntax->formatter);
} else
return FALSE;
return TRUE;
}
#endif /* ENABLE_COLOR */
/* Verify that the user has not unmapped every shortcut for a
* function that we consider 'vital' (such as "Exit"). */
/* Verify that the user has not unmapped every shortcut for
* a function that we consider 'vital' (such as "Exit"). */
static void check_vitals_mapped(void)
{
#define VITALS 4
@@ -1349,10 +1370,10 @@ static void check_vitals_mapped(void)
for (int v = 0; v < VITALS; v++) {
for (funcstruct *f = allfuncs; f != NULL; f = f->next) {
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) {
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 "
"to adjust your nanorc settings.\n"));
} else
@@ -1364,7 +1385,7 @@ static void check_vitals_mapped(void)
/* Parse the rcfile, once it has been opened successfully at rcstream,
* and close it afterwards. If just_syntax is TRUE, allow the file to
* to contain only color syntax commands. */
* contain only color syntax commands. */
void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
{
char *buffer = NULL;
@@ -1443,9 +1464,9 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
newitem->data = argument;
newitem->next = NULL;
if (sntx->augmentations != NULL) {
if (sntx->augmentations) {
extra = sntx->augmentations;
while (extra->next != NULL)
while (extra->next)
extra = extra->next;
extra->next = newitem;
} else
@@ -1477,8 +1498,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
strcmp(keyword, "include") == 0 ||
strcmp(keyword, "extendsyntax") == 0)) {
if (intros_only)
jot_error(N_("Command \"%s\" not allowed in included file"),
keyword);
jot_error(N_("Command \"%s\" not allowed in included file"), keyword);
else
break;
} else if (intros_only && (strcmp(keyword, "color") == 0 ||
@@ -1488,8 +1508,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
strcmp(keyword, "linter") == 0 ||
strcmp(keyword, "formatter") == 0)) {
if (!opensyntax)
jot_error(N_("A '%s' command requires a preceding "
"'syntax' command"), keyword);
jot_error(N_("A '%s' command requires a preceding 'syntax' command"), keyword);
if (strstr("icolor", keyword))
seen_color_command = TRUE;
continue;
@@ -1534,7 +1553,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
}
if (rcopts[i].name == NULL) {
jot_error(N_("Unknown option \"%s\""), option);
jot_error(N_("Unknown option: %s"), option);
continue;
}
@@ -1561,40 +1580,42 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
argument = ptr;
if (*argument == '"')
argument++;
ptr = parse_argument(ptr);
parse_argument(ptr);
#ifdef ENABLE_UTF8
/* When in a UTF-8 locale, ignore arguments with invalid sequences. */
if (using_utf8() && mbstowcs(NULL, argument, 0) == (size_t)-1) {
if (using_utf8 && mbstowcs(NULL, argument, 0) == (size_t)-1) {
jot_error(N_("Argument is not a valid multibyte string"));
continue;
}
#endif
#ifdef ENABLE_COLOR
if (strcmp(option, "titlecolor") == 0)
color_combo[TITLE_BAR] = parse_interface_color(argument);
set_interface_color(TITLE_BAR, argument);
else if (strcmp(option, "numbercolor") == 0)
color_combo[LINE_NUMBER] = parse_interface_color(argument);
set_interface_color(LINE_NUMBER, argument);
else if (strcmp(option, "stripecolor") == 0)
color_combo[GUIDE_STRIPE] = parse_interface_color(argument);
set_interface_color(GUIDE_STRIPE, argument);
else if (strcmp(option, "scrollercolor") == 0)
color_combo[SCROLL_BAR] = parse_interface_color(argument);
set_interface_color(SCROLL_BAR, argument);
else if (strcmp(option, "selectedcolor") == 0)
color_combo[SELECTED_TEXT] = parse_interface_color(argument);
set_interface_color(SELECTED_TEXT, argument);
else if (strcmp(option, "spotlightcolor") == 0)
color_combo[SPOTLIGHTED] = parse_interface_color(argument);
set_interface_color(SPOTLIGHTED, argument);
else if (strcmp(option, "minicolor") == 0)
color_combo[MINI_INFOBAR] = parse_interface_color(argument);
set_interface_color(MINI_INFOBAR, argument);
else if (strcmp(option, "promptcolor") == 0)
color_combo[PROMPT_BAR] = parse_interface_color(argument);
set_interface_color(PROMPT_BAR, argument);
else if (strcmp(option, "statuscolor") == 0)
color_combo[STATUS_BAR] = parse_interface_color(argument);
set_interface_color(STATUS_BAR, argument);
else if (strcmp(option, "errorcolor") == 0)
color_combo[ERROR_MESSAGE] = parse_interface_color(argument);
set_interface_color(ERROR_MESSAGE, argument);
else if (strcmp(option, "keycolor") == 0)
color_combo[KEY_COMBO] = parse_interface_color(argument);
set_interface_color(KEY_COMBO, argument);
else if (strcmp(option, "functioncolor") == 0)
color_combo[FUNCTION_TAG] = parse_interface_color(argument);
set_interface_color(FUNCTION_TAG, argument);
else if (strcmp(option, "foldedcolor") == 0)
set_interface_color(FOLDED_LINE, argument);
else
#endif
#ifdef ENABLE_OPERATINGDIR
@@ -1686,12 +1707,13 @@ void parse_one_nanorc(void)
/* If opening the file succeeded, parse it. Otherwise, only
* complain if the file actually exists. */
if (rcstream != NULL)
if (rcstream)
parse_rcfile(rcstream, FALSE, TRUE);
else if (errno != ENOENT)
jot_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
}
/* Return TRUE when path-plus-name denotes a readable, normal file. */
bool have_nanorc(const char *path, const char *name)
{
if (path == NULL)
@@ -1709,18 +1731,18 @@ void do_rcfiles(void)
{
if (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"));
} else
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
if (is_good_file(nanorc))
parse_one_nanorc();
} else {
const char *xdgconfdir;
if (is_good_file(nanorc))
parse_one_nanorc();
if (custom_nanorc == NULL) {
const char *xdgconfdir = getenv("XDG_CONFIG_HOME");
if (have_nanorc(SYSCONFDIR, "/nanorc"))
parse_one_nanorc();
get_homedir();
xdgconfdir = getenv("XDG_CONFIG_HOME");
/* Now try to find a nanorc file in the user's home directory or in the
* XDG configuration directories, and process the first one found. */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/**************************************************************************
* utils.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2017, 2019, 2020, 2026 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -15,7 +15,7 @@
* 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/. *
* along with this program. If not, see https://gnu.org/licenses/. *
* *
**************************************************************************/
@@ -28,27 +28,25 @@
#include <string.h>
#include <unistd.h>
/* Return the user's home directory. We use $HOME, and if that fails,
* we fall back on the home directory of the effective user ID. */
/* Set global variable `homedir` to the user's home directory. First try
* $HOME, otherwise consult the password database for the current UID. */
void get_homedir(void)
{
if (homedir == NULL) {
const char *homenv = getenv("HOME");
#ifdef HAVE_PWD_H
/* When HOME isn't set, or when we're root, get the home directory
* from the password file instead. */
/* When $HOME is unset, or when we're root, try the database. */
if (homenv == NULL || geteuid() == ROOT_UID) {
const struct passwd *userage = getpwuid(geteuid());
if (userage != NULL)
if (userage)
homenv = userage->pw_dir;
}
#endif
/* Only set homedir if some home directory could be determined,
* otherwise keep homedir NULL. */
if (homenv != NULL && *homenv != '\0')
/* Only set `homedir` if a home directory could be determined. */
if (homenv && *homenv)
homedir = copy_of(homenv);
}
}
@@ -118,7 +116,7 @@ bool parse_num(const char *string, ssize_t *result)
value = (ssize_t)strtol(string, &excess, 10);
if (errno == ERANGE || *string == '\0' || *excess != '\0')
if (errno == ERANGE || *string == '\0' || *excess)
return FALSE;
*result = value;
@@ -126,29 +124,30 @@ bool parse_num(const char *string, ssize_t *result)
return TRUE;
}
/* Read two numbers, separated by a comma, from str, and store them in
* *line and *column. Return FALSE on error, and TRUE otherwise. */
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
/* Read one number (or two numbers separated by comma, period, or colon)
* from the given string and store the number(s) in *line (and *column).
* Return FALSE on a failed parsing, and TRUE otherwise. */
bool parse_line_column(const char *string, ssize_t *line, ssize_t *column)
{
bool retval;
char *firstpart;
const char *comma;
char *firstpart;
bool retval;
while (*str == ' ')
str++;
while (*string == ' ')
string++;
comma = strpbrk(str, "m,. /;");
comma = strpbrk(string, ",.:");
if (comma == NULL)
return parse_num(str, line);
return parse_num(string, line);
retval = parse_num(comma + 1, column);
if (comma == str)
if (comma == string)
return retval;
firstpart = copy_of(str);
firstpart[comma - str] = '\0';
firstpart = copy_of(string);
firstpart[comma - string] = '\0';
retval = parse_num(firstpart, line) && retval;
@@ -168,14 +167,19 @@ void recode_NUL_to_LF(char *string, size_t length)
}
}
/* In the given string, recode each embedded newline as a NUL. */
void recode_LF_to_NUL(char *string)
/* In the given string, recode each embedded newline as a NUL,
* and return the number of bytes in the string. */
size_t recode_LF_to_NUL(char *string)
{
while (*string != '\0') {
char *beginning = string;
while (*string) {
if (*string == '\n')
*string = '\0';
string++;
}
return (string - beginning);
}
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
@@ -193,16 +197,13 @@ void free_chararray(char **array, size_t len)
#endif
#ifdef ENABLE_SPELLER
/* Is the word starting at the given position in 'text' and of the given
/* Is the word starting at the given position in `text` and of the given
* length a separate word? That is: is it not part of a longer word? */
bool is_separate_word(size_t position, size_t length, const char *text)
{
const char *before = text + step_left(text, position);
const char *after = text + position + length;
/* If the word starts at the beginning of the line OR the character before
* the word isn't a letter, and if the word ends at the end of the line OR
* the character after the word isn't a letter, we have a whole word. */
return ((position == 0 || !is_alpha_char(before)) &&
(*after == '\0' || !is_alpha_char(after)));
}
@@ -213,8 +214,7 @@ bool is_separate_word(size_t position, size_t length, const char *text)
* than the given start; otherwise, we find the first match starting no earlier
* than start. If we are doing a regexp search, and we find a match, we fill
* in the global variable regmatches with at most 9 subexpression matches. */
const char *strstrwrapper(const char *haystack, const char *needle,
const char *start)
const char *strstrwrapper(const char *haystack, const char *needle, const char *start)
{
if (ISSET(USE_REGEXP)) {
if (ISSET(BACKWARDS_SEARCH)) {
@@ -244,16 +244,14 @@ const char *strstrwrapper(const char *haystack, const char *needle,
next_rung = step_right(haystack, last_find);
regmatches[0].rm_so = next_rung;
regmatches[0].rm_eo = far_end;
if (regexec(&search_regexp, haystack, 1, regmatches,
REG_STARTEND) != 0)
if (regexec(&search_regexp, haystack, 1, regmatches, REG_STARTEND) != 0)
break;
}
/* Find the last match again, to get possible submatches. */
regmatches[0].rm_so = floor;
regmatches[0].rm_eo = far_end;
if (regexec(&search_regexp, haystack, 10, regmatches,
REG_STARTEND) != 0)
if (regexec(&search_regexp, haystack, 10, regmatches, REG_STARTEND) != 0)
return NULL;
return haystack + regmatches[0].rm_so;
@@ -262,8 +260,7 @@ const char *strstrwrapper(const char *haystack, const char *needle,
/* Do a forward regex search from the starting point. */
regmatches[0].rm_so = start - haystack;
regmatches[0].rm_eo = strlen(haystack);
if (regexec(&search_regexp, haystack, 10, regmatches,
REG_STARTEND) != 0)
if (regexec(&search_regexp, haystack, 10, regmatches, REG_STARTEND) != 0)
return NULL;
else
return haystack + regmatches[0].rm_so;
@@ -282,34 +279,26 @@ const char *strstrwrapper(const char *haystack, const char *needle,
return mbstrcasestr(start, needle);
}
/* This is a wrapper for the malloc() function that properly handles
* things when we run out of memory. */
/* Allocate the given amount of memory and return a pointer to it. */
void *nmalloc(size_t howmuch)
{
void *r = malloc(howmuch);
void *section = malloc(howmuch);
if (howmuch == 0)
die("Allocating zero bytes. Please report a bug.\n");
if (r == NULL)
if (section == NULL)
die(_("Nano is out of memory!\n"));
return r;
return section;
}
/* This is a wrapper for the realloc() function that properly handles
* things when we run out of memory. */
void *nrealloc(void *ptr, size_t howmuch)
/* Reallocate the given section of memory to have the given size. */
void *nrealloc(void *section, size_t howmuch)
{
void *r = realloc(ptr, howmuch);
section = realloc(section, howmuch);
if (howmuch == 0)
die("Allocating zero bytes. Please report a bug.\n");
if (r == NULL)
if (section == NULL)
die(_("Nano is out of memory!\n"));
return r;
return section;
}
/* Return an appropriately reallocated dest string holding a copy of src.
@@ -354,6 +343,22 @@ char *free_and_assign(char *dest, char *src)
* displayed in the edit window when the cursor is at the given column. */
size_t get_page_start(size_t column)
{
#ifndef NANO_TINY
if (united_sidescroll) {
if (column < CUSHION)
return 0;
else if (column < openfile->brink + CUSHION) {
if (ISSET(JUMPY_SCROLLING))
return (column > editwincols / 2) ? column - editwincols / 2 : 0;
else
return column - CUSHION;
} else if (column > openfile->brink + editwincols - CUSHION - 1)
return column - editwincols + (ISSET(JUMPY_SCROLLING) ? editwincols / 2 : CUSHION) + 1;
else
return openfile->brink;
}
#endif
if (column == 0 || column + 2 < editwincols || ISSET(SOFTWRAP))
return 0;
else if (editwincols > 8)
@@ -362,15 +367,8 @@ size_t get_page_start(size_t column)
return column - (editwincols - 2);
}
/* Return the placewewant associated with current_x, i.e. the zero-based
* column position of the cursor. */
size_t xplustabs(void)
{
return wideness(openfile->current->data, openfile->current_x);
}
/* Return the index in text of the character that (when displayed) will
* not overshoot the given column. */
/* Return the index in the given text of the character that (when displayed)
* will not overshoot the given column. */
size_t actual_x(const char *text, size_t column)
{
const char *start = text;
@@ -378,7 +376,7 @@ size_t actual_x(const char *text, size_t column)
size_t width = 0;
/* The current accumulated span, in columns. */
while (*text != '\0') {
while (*text) {
int charlen = advance_over(text, &width);
if (width > column)
@@ -390,22 +388,21 @@ size_t actual_x(const char *text, size_t column)
return (text - start);
}
/* A strnlen() with tabs and multicolumn characters factored in:
* how many columns wide are the first maxlen bytes of text? */
size_t wideness(const char *text, size_t maxlen)
/* Return the number of columns that the first count bytes of text occupy. */
size_t wideness(const char *text, size_t count)
{
size_t width = 0;
if (maxlen == 0)
if (count == 0)
return 0;
while (*text != '\0') {
while (*text) {
size_t charlen = advance_over(text, &width);
if (maxlen <= charlen)
if (count <= charlen)
break;
maxlen -= charlen;
count -= charlen;
text += charlen;
}
@@ -417,12 +414,18 @@ size_t breadth(const char *text)
{
size_t span = 0;
while (*text != '\0')
while (*text)
text += advance_over(text, &span);
return span;
}
/* Return the (zero-based) column position of the cursor. */
size_t xplustabs(void)
{
return wideness(openfile->current->data, openfile->current_x);
}
/* Append a new magic line to the end of the buffer. */
void new_magicline(void)
{
@@ -437,8 +440,9 @@ void new_magicline(void)
* it isn't the only line in the file. */
void remove_magicline(void)
{
if (openfile->filebot->data[0] == '\0' &&
openfile->filebot != openfile->filetop) {
if (openfile->filebot->data[0] == '\0' && openfile->filebot != openfile->filetop) {
if (openfile->current == openfile->filebot)
openfile->current = openfile->current->prev;
openfile->filebot = openfile->filebot->prev;
delete_node(openfile->filebot->next);
openfile->filebot->next = NULL;
@@ -492,7 +496,9 @@ void get_range(linestruct **top, linestruct **bot)
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. */
linestruct *line_from_number(ssize_t number)
{
@@ -507,7 +513,7 @@ linestruct *line_from_number(ssize_t number)
return line;
}
#endif /* !NANO_TINY */
#endif
/* Count the number of characters from begin to end, and return it. */
size_t number_of_characters_in(const linestruct *begin, const linestruct *end)

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,6 @@ pkgdata_DATA = asm.nanorc \
c.nanorc \
css.nanorc \
default.nanorc \
elisp.nanorc \
email.nanorc \
go.nanorc \
groff.nanorc \

View File

@@ -1,15 +1,18 @@
## Syntax highlighting for assembler.
## Original author: Mike Frysinger
## License: GPL version 3 or newer
syntax asm "\.(S|s|asm)$"
magic "assembler source"
comment "//"
color red "\<[A-Z_]{2,}\>"
color brightgreen "\.(data|subsection|text)"
color green "\.(align|file|globl|global|hidden|section|size|type|weak)"
color brightyellow "\.(ascii|asciz|byte|double|float|hword|int|long|short|single|struct|word)"
color brightred "^[[:blank:]]*[.0-9A-Za-z_]*:"
color brightcyan "^[[:blank:]]*#[[:blank:]]*(define|undef|include|ifn?def|endif|elif|else|if|warning|error)"
color red "\<[[:alpha:]_]{2,}\>"
color brightgreen "\.(data|subsection|text)\>"
color green "\.(align|file|globl|global|hidden|section|size|type|weak)\>"
color brightyellow "\.(ascii|asciz|byte|double|float|hword|int|long|short|single|struct|word)\>"
color brightred "^[[:blank:]]*[[:alnum:]_.]*:"
color brightcyan "^[[:blank:]]*#[[:blank:]]*(define|undef|include|ifn?def|endif|elif|else|if|warning|error)\>"
# Strings and names of included files.
color brightyellow ""([^"\]|\\.)*"|<[^= ]*>"

View File

@@ -7,11 +7,11 @@ syntax autoconf "\.(ac|m4)$"
comment "#"
# Keywords:
color yellow "\<(if|test|then|elif|else|fi|for|in|do|done)\>"
color yellow "\<(if|test|then|elif|else|fi|case|esac|ifelse|for|in|do|done)\>"
color yellow "=|!=|&&|\|\|"
# Macros:
color cyan "\<[[:upper:]_[:digit:]]+\>"
color cyan "\<[[:upper:][:digit:]_]+\>"
# Version numbers:
color red "\<[-_.0-9]+\>"
@@ -29,7 +29,7 @@ color brightred "^[[:blank:]]*\*\*\*.*"
color magenta "\[|\]|\(|\)"
# Comments:
color blue "^[[:blank:]]*#.*" "\<dnl.*"
color blue "^[[:blank:]]*#.*|\<dnl.*"
# Trailing whitespace:
color ,green "[[:space:]]+$"

View File

@@ -1,20 +1,22 @@
## Syntax highlighting for AWK scripts.
## Original author: Donnie Berkholz
syntax awk "\.awk$"
header "^#!.*awk"
magic "awk script"
comment "#"
# Records.
color brightred "\$[0-9A-Za-z_!@#$*?-]+"
color brightred "\$[[:alnum:]_!@#$*?-]+"
# Awk-set variables.
color red "\<(ARGC|ARGIND|ARGV|BINMODE|CONVFMT|ENVIRON|ERRNO|FIELDWIDTHS)\>"
color red "\<(FILENAME|FNR|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS)\>"
color red "\<(PROCINFO|RS|RT|RSTART|RLENGTH|SUBSEP|TEXTDOMAIN)\>"
# Function declarations and special patterns.
color brightgreen "\<(function|extension|BEGIN|END)\>"
# Operators.
color green "\{|\}|\(|\)|\;|\[|\]|\\|<|>|!|=|&|\+|-|\*|%|/|\?:|\^|\|"
# Operators and brackets/braces/slashes/parentheses.
color green "[][!%&()*+/:;<=>?\^{|}~-]"
# Flow control.
color brightyellow "\<(for|if|while|do|else|in|delete|exit)\>"
color brightyellow "\<(break|continue|return)\>"
@@ -30,6 +32,8 @@ color magenta "\<(bindtextdomain|dcgettext|dcngettext)\>"
# Strings.
color brightyellow ""([^"\]|\\.)*""
# Escape sequences.
color brick "\\([abfnrtv\/"]|[0-7]{1,3}|x[[:xdigit:]]{1,2}|u[[:xdigit:]]{1,8})"
# Comments.
color brightblue "(^|[[:blank:]])#.*"

View File

@@ -6,37 +6,41 @@ magic "^(C|C\+\+) (source|program)"
comment "//"
# Constants.
color brightred "\<[A-Z_][0-9A-Z_]*\>"
color brightred "\<[[:upper:]_][[:upper:][:digit:]_]*\>"
# Labels.
color brightmagenta "^[[:blank:]]*[A-Z_a-z][0-9A-Z_a-z]*:[[:blank:]]*$"
color brightmagenta "^[[:blank:]]*[[:alpha:]_][[:alnum:]_]*:[[:blank:]]*$"
color normal ":[[:blank:]]*$"
# Types and related keywords.
color green "\<(auto|bool|char|const|double|enum|extern|float|inline|int|long|restrict|short|signed|sizeof|static|struct|typedef|union|unsigned|void)\>"
color green "\<([[:lower:]][[:lower:]_]*|(u_?)?int(8|16|32|64))_t\>"
color green "\<(_(Alignas|Alignof|Atomic|Bool|Complex|Generic|Imaginary|Noreturn|Static_assert|Thread_local))\>"
color green "\<(class|explicit|friend|mutable|namespace|override|private|protected|public|register|template|this|typename|using|virtual|volatile)\>"
color green "\<(bool|char|double|enum|float|int|short|(un)?signed|struct|union|void|((u_?)?int(8|16|32|64)|[[:lower:]][[:lower:]_]*)_t)\>"
color green "\<(align(as|of)|auto|const(eval|expr|init)?|extern|inline|register|restrict|sizeof|static(_assert)?|thread_local|typedef|typeof(_unqual)?|volatile)\>"
color green "\<(_(Align(as|of)|Atomic|BitInt|Bool|Complex|Decimal(32|64|128)|Generic|Imaginary|Noreturn|Static_assert|Thread_local))\>"
color green "\<(class|explicit|final|friend|mutable|namespace|override|private|protected|public|template|this|typename|using|virtual)\>"
color green "\<(char(8|16|32)_t|wchar_t|(const|dynamic|reinterpret|static)_cast|decltype|export|import|module|noexcept|requires|typeid)\>"
# Flow control.
color brightyellow "\<(if|else|for|while|do|switch|case|default)\>"
color brightyellow "\<(try|throw|catch|operator|new|delete)\>"
color magenta "\<(break|continue|goto|return)\>"
color magenta "\<(break|continue|goto|(co_)?return)\>"
# Single-quoted stuff (characters, backslash escapes, hex and octal byte codes).
color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'"
# Hexadecimal, binary, and boolean values.
color pink "\<(0[Xx][[:xdigit:]]['[:xdigit:]]*|0[Bb][01]['01]*|true|false|nullptr)\>"
# 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.
color brightyellow ""([^"]|\\")*"" "#[[:blank:]]*include[[:blank:]]*<[^>]+>"
color brightyellow ""([^"]|\\")*"|#[[:blank:]]*include[[:blank:]]*<[^>]+>"
# Preprocessor directives.
color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$"
color brightcyan "^[[:blank:]]*#[[:blank:]]*((define|else|endif|include(_next)?|line|undef)\>|$)"
color brightcyan start="^[[:blank:]]*#[[:blank:]]*((el)?if(n?def)?|error|pragma|warning)\>" end="(\`|[^\])$"
color brightcyan "^[[:blank:]]*#[[:blank:]]*((define|else|embed|endif|include(_next)?|line|undef)\>|$)"
# Comments.
color brightblue "//.*"
color brightblue "//[^"]*$|(^|[[:blank:]])//.*"
color brightblue start="/\*" end="\*/"
# Reminders.

View File

@@ -8,24 +8,24 @@ syntax changelog "Change[Ll]og[^/]*$"
# Author lines.
color green "^(19|20).*"
# Dates.
color red "^(19|20)[0-9-]{8}"
color red "^(19|20)[[:digit:]-]{8}"
# Email addresses.
color yellow "<[^>]*@[^>]*>"
# Command-line options.
color cyan "[[:blank:]]-[a-zA-Z\$]|--[8a-z-]+"
color cyan "[[:blank:]]-[[:alpha:]$]|--[[:lower:]8-]+"
# Bug and patch numbers.
color cyan "(BZ|bug|patch)[ ]#[0-9]+|PR [[:alnum:]]+/[0-9]+"
color cyan "(BZ|bug|patch) #[[:digit:]]+|PR [[:alnum:]]+/[[:digit:]]+"
# Probable constants, for variety.
color brightred "\<[A-Z_][0-9A-Z_]+\>"
color brightred "\<[[:upper:]_][[:upper:][:digit:]_]+\>"
# Key sequences.
color brightblue "\^[A-Z^\]|\<M-.|\<F1?[0-9]|(\^|M-)Space"
color brightblue "\^[[:upper:]\^_]|\<M-.|\<F1?[[:digit:]]|(\^|M-)Space"
# Changed files.
color magenta start="^( | {8})\* " end="(:( |$)|^$)"
# Release markers.
color brightblue "^(GNU )?nano[- ][0-9]\.[0-9]\.[^ ]+"
color brightblue "^(GNU )?nano[- ][[:digit:]]\.[[:digit:]]\.[^ ]+"
# Trailing whitespace.
color ,green "[[:space:]]+$"

View File

@@ -1,9 +1,11 @@
## Syntax highlighting for CMake files.
## Original author: Felipe Bugno
syntax cmake "(CMakeLists\.txt|\.cmake)$"
comment "#"
color green "^[[:blank:]]*[0-9A-Za-z_]+"
color green "^[[:blank:]]*[[:alnum:]_]+"
icolor brightyellow "^[[:blank:]]*(include|include_directories|include_external_msproject)\>"
icolor brightgreen "^[[:blank:]]*((else|end)?if|else|(end)?while|(end)?foreach|break)\>"

View File

@@ -1,5 +1,7 @@
## Syntax highlighting for CSS files.
## Original author: Simon Rupf
syntax css "\.css$"
comment "/*|*/"

View File

@@ -8,8 +8,8 @@ comment "#"
color ,red " + +"
# Nano's release motto, then name plus version.
color italic,lime "\<[Nn]ano [1-6]\.[0-9][-.[:alnum:]]* "[^"]+""
color brightred "\<(GNU )?[Nn]ano [1-6]\.[0-9][-.[:alnum:]]*\>"
color italic,lime "\<[Nn]ano [1-9]\.[0-9][-.[:alnum:]]* "[^"]+""
color brightred "\<(GNU )?[Nn]ano [1-9]\.[0-9][-.[:alnum:]]*\>"
# Dates
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,}>"
# URLs.
color lightblue "\<https?://\S+\.\S+[^[:space:],.)]"
color lightblue "\<https?://\S+\.\S+[^])>[:space:],.]"
# Bracketed captions in certain config files.
color brightgreen "^\[[^][]+\]$"
@@ -26,5 +26,8 @@ color brightgreen "^\[[^][]+\]$"
# Comments.
color cyan "^[[:blank:]]*#.*"
# Make hard (non-breaking) spaces noticeable.
color ,#444 " "
# Control codes.
color orange "[[:cntrl:]]"

View File

@@ -1,33 +0,0 @@
## Syntax highlighting for Emacs Lisp.
syntax elisp "\.el$"
magic "Lisp/Scheme program"
comment ";"
# Basic functions/macros
color brightcyan "\<(if|when|unless|cond|and|or|lambda|let|progn|while|dolist|dotimes)\>"
color brightcyan "\<save-((window-)?excursion|restriction)\>"
color brightcyan "\<eval-(and|when)-compile\>"
# Defining functions
color brightcyan "\<def(un|macro|subst|generic|alias)\>"
color brightcyan "\<cl-def(un|macro|subst|generic|struct|type)\>"
color brightcyan "\<define-(derived|minor|generic)-mode\>"
# Defining variables
color brightcyan "\<def(class|const|var(-local|alias)?)\>"
# Customization functions
color brightcyan "\<def(custom|face|group|theme)\>"
# Setting values
color brightcyan "\<(setq(-default|-local)?|setf|push|pop|declare(-function)?)\>"
# Feature functions
color brightcyan "\<(require|provide)\>"
# Quoted symbols
color brightyellow "#?'\<(\w|-)+\>"
# Booleans
color brightred "\<(t|nil)\>"
# Keywords
color blue ":(\w|[?-])+"
# Strings
color yellow start="^[[:blank:]]+"" end="[^\]""
color yellow ""([^"\]|\\.)*""
# Comments
color cyan "(^|[[:blank:]]);.*"

View File

@@ -1,5 +1,7 @@
## Syntax highlighting for Fortran 90/95.
## Original author: Pascal Gentil
syntax fortran "\.(f|for|f90|f95)$"
comment "!"
@@ -10,7 +12,7 @@ icolor green "\<(append|asis|assign|assignment|associated|character|common)\>"
icolor green "\<(complex|data|default|delim|dimension|double precision)\>"
icolor green "\<(elemental|epsilon|external|file|fmt|form|format|huge)\>"
icolor green "\<(implicit|include|index|inquire|integer|intent|interface)\>"
icolor green "\<(intrinsic|iostat|kind|logical|module|none|null|only)>"
icolor green "\<(intrinsic|iostat|kind|logical|module|none|null|only)\>"
icolor green "\<(operator|optional|pack|parameter|pointer|position|private)\>"
icolor green "\<(program|public|real|recl|recursive|selected_int_kind)\>"
icolor green "\<(selected_real_kind|subroutine|status)\>"

View File

@@ -1,5 +1,7 @@
## Syntax highlighting for POV-Ray files.
## Original author: Donnie Berkholz
syntax pov "\.(pov|POV|povray|POVRAY)$"
comment "//"

View File

@@ -1,5 +1,7 @@
## Syntax highlighting for RPM spec files.
## Original author: Asterios Dramis
syntax spec "\.spec(\.[^/]+)?$"
comment "#"
@@ -12,7 +14,9 @@ color brightblue "\<(AutoReq|AutoProv|AutoReqProv)[[:space:]]*:"
color brightblue "\<(License|Copyright|Distribution|Vendor|Packager)[[:space:]]*:"
color brightblue "\<((Source|Patch)[0-9]*|Nosource|Nopatch)[[:space:]]*:"
# Architectures.
color brightred "\<(i386|i486|i586|i686|athlon|ia64|alpha|alphaev5|alphaev56|alphapca56|alphaev6|alphaev67|sparc|sparcv9|sparc64armv3l|armv4b|armv4lm|ips|mipsel|ppc|ppciseries|ppcpseries|ppc64|m68k|m68kmint|Sgi|rs6000|i370|s390x?|noarch)\>"
color brightred "\<((a|loong)arch64|alpha(ev(56?|67?)|pca56)?|amd64|armv(3l|4b|4l|5t(ej?)?l|6h?l|7(hn?)?l|8h?l)|athlon|em64t|geode|i370|i(3|4|5|6)86|ia32e|ia64|m68k(mint)?|mips(64)?(el|r6|r6el)?)\>"
color brightred "\<(pentium(3|4)|ppc(32dy4|8260|8560)?|ppc64(le|p7)?|ppc(64)?(i|p)series|riscv64|rs6000|s390x?|sgi|sh(3|4|4a)?|sparc(64v?|v8|v9v?)?|x86_64(_v2|_v3|_v4)?|xtensa)\>"
# Architecture and OS conditionals.
color brightred "%(ifarch|elifarch|ifnarch|ifos|elifos|ifnos)\>"
# %* strings.

View File

@@ -42,7 +42,7 @@ color brightblue "//.*"
color brightblue start="/\*" end="\*/"
# Special comments.
color brightcyan "//[[:blank:]]*\+build[[:blank:]]+(([a-zA-Z_0-9]+[[:blank:]]*)+,[[:blank:]]*)*[a-zA-Z_0-9]+"
color brightcyan "//[[:blank:]]*\+build[[:blank:]]+(([[:alnum:]_]+[[:blank:]]*)+,[[:blank:]]*)*[[:alnum:]_]+"
# Trailing whitespace.
color ,green "[[:space:]]+$"

View File

@@ -1,26 +1,28 @@
## Syntax highlighting for groff.
syntax groff "\.(m[ems]|rof|tmac)$|/tmac\.[^/]+$"
## Original author: Robert D. Goulding
syntax groff "\.(me|mm|mom|ms|roff|tmac)$|/tmac\.[^/]+$"
comment ".\""
# The argument of .ds or .nr
# The setting of a string or register
color cyan "^\.(ds|nr) [^[:space:]]*"
# Single-character escapes
color brightmagenta "\\."
# The argument of \f or \s in the same color
color brightmagenta "\\f(.|\(..)" "\\s(\+|\-)?[0-9]"
# Newlines
color brightmagenta "\\f(.|\(..)|\\s(\+|\-)?[0-9]"
# References to registers
color cyan "\\(\\)?n(.|\(..)"
color cyan start="\\(\\)?n\[" end="]"
# Requests
color brightgreen "^\.[[:blank:]]*[^[:space:]]*"
# Comments
color yellow "^\.\\".*"
# Strings
color yellow "(^\\#|(^\.)?\\").*"
# References to strings
color green "\\(\\)?\*(.|\(..)"
color green start="\\(\\)?\*\[" end="]"
# Characters
# Special characters
color brightred "\\\(.."
color brightred start="\\\[" end="]"
# Macro arguments
color brightcyan "\\\\\$[1-9]"
color brightcyan "\\\\\$[0-9]"

View File

@@ -1,23 +1,30 @@
## Syntax highlighting for Guile Scheme.
syntax guile "\.scm$"
## Original authors: Mark Oteiza and Benno Schulenberg
## License: GPL version 3 or newer
syntax guile "\.(scm|sld|sls|ss)$"
header "^#!.*guile"
comment ";"
# Basic scheme functions
color green "\<(do|if|lambda|let(rec)?|map|unless|when)\>"
# Basic syntax
color lightgreen "\<((and|begin|case|cond|do|else|if|lambda|let(rec)?|or|quote|unless|when)\>|let\*|set!)"
# Basic procedures
color lightcyan "\<((append|apply|c[ad]{1,4}r|cons|display|for-each|list|map|newline)\>|reverse(\>|!)|set-c[ad]r!)"
color lightcyan "\<(boolean|char(-ci)?[<>]?=?|complex|eqv?|even|integer|list|nan|negative|null|number|odd|pair|positive|rational|real|string|symbol|vector|zero)\?"
color lightcyan "\<(abs|a?(cos|sin|tan)|ceiling|exp|floor|max|min|modulo|not|random|round|quotient|sqrt|square|truncate)\>"
# Defining things
color brightcyan "\<define(-macro|-module|-public|-syntax)?\>"
color brightgreen "\<define(-macro|-module|-public|-syntax)?\>"
# Quoted symbols
color brightyellow "'\<(\w|-)+\>"
# Chars
color lightyellow "'(\w|[!$%&*+/:<=>?@^_~])(\w|[!$%&*+/:<=>?@^_~.0-9-])*"
# Characters
color brightmagenta "#\\(.|\w+)"
# Booleans
color brightred "(#t|#f)\>"
color brightred "#(t|true|f|false)\>"
# Keywords
color blue "#?:(\w|[?-])+"
color lagoon "#?:(\w|[?-])+"
# Strings
color yellow start="^[[:blank:]]+"" end="[^\]""
color yellow start="^[[:blank:]]*"([^"\]|\\.)*$" end="(^|[^\]|[^\]\\\\)""
color yellow ""([^"\]|\\.)*""
# Comments
color cyan "(^|[[:blank:]]);.*"
color italic,#aaa "(^|[[:blank:]]);.*"

View File

@@ -8,8 +8,8 @@ formatter tidy -m -q
# Tags:
color cyan "<[[:alpha:]/!?][^>]*>"
# Bold, italic, and underlined:
color brightmagenta "</?[biu]>"
# Bold, italic, underlined, emphasis, and importance:
color brightmagenta "</?(b|i|u|em|strong)>"
# Named character references:
color red "&[^;[:space:]]*;"

Some files were not shown because too many files have changed in this diff Show More