1
1

new feature: comment/uncomment current line or selected lines

This allows for commenting or uncommenting a line or a bunch of lines
with a single keystroke (default binding: M-3).  The characters used
for commenting/uncommenting are specified by the active syntax file.

Reviewed-by: Benno Schulenberg <bensberg@justemail.net>
Signed-off-by: Mike Scalora <mike@scalora.org>
Этот коммит содержится в:
Mike Scalora 2016-05-25 22:13:50 +02:00 коммит произвёл Benno Schulenberg
родитель d3bd855c9d
Коммит 6a2032f5b0
49 изменённых файлов: 416 добавлений и 5 удалений

Просмотреть файл

@ -84,6 +84,22 @@ else
fi
fi
AC_ARG_ENABLE(comment,
AS_HELP_STRING([--disable-comment], [Disable comment/uncomment functions]))
if test "x$enable_tiny" = xyes; then
if test "x$enable_comment" = xyes; then
AC_MSG_ERROR([--enable-comment cannot work with --enable-tiny])
else
# Disabling nanorc silently disables comment support.
enable_comment=no
fi
fi
if test "x$disable_comment" != xyes; then
if test "x$enable_comment" != xno; then
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to disable the comment/uncomment functionality.])
fi
fi
AC_ARG_ENABLE(extra,
AS_HELP_STRING([--disable-extra], [Disable extra features, currently only easter eggs]))
if test "x$enable_extra" = xno; then

Просмотреть файл

@ -302,6 +302,16 @@ syntax should be used for that file. This
functionality only works when \fBlibmagic\fP is installed on the
system and will be silently ignored otherwise.
.TP
.BI comment " string"
Use the given string for commenting and uncommenting lines. A vertical bar or
pipe character (|) designates bracket-style comments; for example, "/*|*/" for
CSS files. The characters before the pipe are prepended to the line and the
characters after the pipe are appended at the end of the line. If no pipe
character is present, the entire string is prepended; for example, "#" for
Python files. If empty double quotes are specified, the comment/uncomment
function is disabled; for example, "" for JSON. Double quotes or backslashes
may be escaped with a backslash; for example, ".\\"" for man page source.
.TP
.B color \fIfgcolor\fR,\fIbgcolor\fR """\fIregex\fR""" ...
Display all pieces of text that match
the extended regular expression \fIregex\fP with foreground color
@ -336,7 +346,7 @@ to \fBicolor\fP.
.BI extendsyntax " str directive " \fR[ "arg " \fR...]
Extend the syntax previously defined as \fIstr\fP to include
new information. This allows you to add a new \fBcolor\fP, \fBicolor\fP,
\fBheader\fP, \fBmagic\fP, \fBlinter\fP, or \fBformatter\fP directive
\fBheader\fP, \fBmagic\fP, \fBcomment\fP, \fBlinter\fP, or \fBformatter\fP directive
to an already defined syntax -- useful when you want to
slightly improve a syntax defined in one of the system-installed
files (which are normally not writable)
@ -455,6 +465,10 @@ Indents (shifts to the right) the currently marked text.
.B unindent
Unindents (shifts to the left) the currently marked text.
.TP
.B comment
Comments or uncomments the current line or marked lines, using the comment
style specified in the active syntax.
.TP
.B left
Goes left one position (in the editor or browser).
.TP

Просмотреть файл

@ -2,6 +2,7 @@
syntax "asm" "\.(S|s|asm)$"
magic "[Aa]ssembl(y|er)"
comment "//"
color red "\<[A-Z_]{2,}\>"
color brightgreen "\.(data|subsection|text)"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Autoconf.
syntax "autoconf" "\.(ac|m4)$"
comment "#"
# Keywords:
color yellow "\<(if|test|then|elif|else|fi|for|in|do|done)\>"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "awk" "\.awk$"
magic "awk.*script text"
comment "#"
# Records.
icolor brightred "\$[0-9A-Z_!@#$*?-]+"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "c" "\.(c(c|pp|xx|\+\+)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$"
magic "(ASCII|UTF-8 Unicode) C(\+\+)? program text"
comment "//"
color brightred "\<[A-Z_][0-9A-Z_]+\>"
color green "\<(float|double|bool|char|int|short|long|sizeof|enum|void|auto|static|const|struct|union|typedef|extern|(un)?signed|inline)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Syntax highlighting for CMake files.
syntax "cmake" "(CMakeLists\.txt|\.cmake)$"
comment "#"
icolor green "^[[:space:]]*[A-Z0-9_]+"
icolor brightyellow "^[[:space:]]*(include|include_directories|include_external_msproject)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for CSS files.
syntax "css" "\.css$"
comment "/*|*/"
color brightred "."
color brightyellow start="\{" end="\}"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for apt's sources.list.
syntax "sources.list" "sources\.list(~|\.old|\.save)?$" "sources\.list\.d/.*\.list(~|\.old|\.save)?$"
comment "#"
# Coloring the deb lines, working from tail to head. First the
# components -- well, everything, and thus also the components.

Просмотреть файл

@ -2,6 +2,7 @@
## for files that do not match any other syntax.
syntax "default"
comment "#"
# Spaces in front of tabs.
color ,red " + +"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Emacs Lisp.
syntax "elisp" "\.el$"
comment ";"
# Basic functions/macros
color brightcyan "\<(if|when|unless|cond|and|or|lambda|let|progn|while|dolist|dotimes)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Fortran 90/95.
syntax "fortran" "\.(f|f90|f95)$"
comment "!"
color red "\<[0-9]+\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Gentoo ebuilds/eclasses.
syntax "ebuild" "\.e(build|class)$"
comment "#"
## All the standard portage functions
color brightgreen "(^|\<default_)src_(unpack|prepare|configure|compile|install|test)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Go.
syntax "go" "\.go$"
comment "//"
# Set up a formatter since spelling is probably useless...
formatter gofmt -w

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for groff.
syntax "groff" "\.m[ems]$" "\.rof" "\.tmac$" "^tmac."
comment ".\""
# The argument of .ds or .nr
color cyan "^\.(ds|nr) [^[:space:]]*"

Просмотреть файл

@ -3,6 +3,7 @@
syntax "guile" "\.scm$"
header "^#!.*guile"
magic "guile"
comment ";"
# Basic scheme functions
color green "\<(do|if|lambda|let(rec)?|map|unless|when)\>"

Просмотреть файл

@ -2,7 +2,10 @@
syntax "html" "\.html?$"
magic "HTML document text"
comment "<!--|-->"
color cyan start="<" end=">"
color red "&[^;[:space:]]*;"
color green ""(\\.|[^"])*""
color yellow start="<!--" end="-->"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "java" "\.java$"
magic "Java "
comment "//"
color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>"
color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Javascript.
syntax "javascript" "\.js$"
comment "//"
color brightred "\<[A-Z_][0-9A-Z_]+\>"
color green "\<(const|function|let|this|typeof|var|void)\>"

Просмотреть файл

@ -5,6 +5,8 @@
# License: GPLv3 or newer
syntax "json" "\.json$"
# No comments are permitted in JSON.
comment ""
# Numbers (used as value).
color green ":[[:space:]]*\-?(0|[1-9][0-9]*)(\.[0-9]+)?([Ee]?[-+]?[0-9]+)?"

Просмотреть файл

@ -5,6 +5,7 @@
## Version: 2011-05-05
syntax "lua" "\.lua$"
comment "--"
color brightwhite "\[\[.*\]\]"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for Makefiles.
syntax "makefile" "Makefile[^/]*$" "\.(make|mk)$"
comment "#"
color red "[:=]"
color magenta "\<(if|ifeq|else|endif)\>"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "man" "\.[1-9]x?$"
magic "troff or preprocessor input text"
comment ".\""
color green "\.(SH|SS|TH) .*$"
color brightgreen "\.(SH|SS|TH) " "\.([HIT]P)"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "mgp" "\.mgp$"
header "^%include.*"
comment "#"
icolor green "^%[a-z].*$"
color cyan "(^|[[:space:]])#.*$"

Просмотреть файл

@ -1,9 +1,10 @@
## Here is an example for nanorc files.
syntax "nanorc" "\.?nanorc$"
comment "#"
# Possible errors and parameters
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|linter|i?color|extendsyntax).*$"
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|comment|magic|linter|i?color|extendsyntax).*$"
# Keywords
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|autoindent|backup|backwards|boldtext|casesensitive|const(antshow)?|cut|fill|historylog|justifytrim|locking|morespace|mouse|multibuffer|noconvert|nohelp|nonewlines|nowrap|pos(ition)?log|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|smarthome|smooth|softwrap|suspend|tabsize|tabstospaces|tempfile|unix|view|wordbounds)\>"
@ -11,8 +12,8 @@ icolor yellow "^[[:space:]]*set[[:space:]]+(functioncolor|keycolor|statuscolor|t
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|operatingdir|punct|quotestr|speller|statuscolor|titlecolor|whitespace)[[:space:]]+"
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^|M-)([[:alpha:]]|space|[]]|[0-9^_=+{}|;:'\",./<>\?-])|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(2|with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^|M-)([[:alpha:]]|space|[]]|[0-9^_=+{}|;:'\",./<>\?-])|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(2|with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|linter|formatter)[[:space:]]+.*$"
icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|linter|formatter|extendsyntax)\>"
icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|comment|linter|formatter)[[:space:]]+.*$"
icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|extendsyntax)\>"
# Colors
icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "nftables" "\.(nft|nftables)$"
header "^#!.*(nft|nftables)"
comment "#"
# Objects and operations
color green "\<(chain|hook|policy|priority|ruleset|set|table|type|v?map)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for C/C++/Obj-C.
syntax "m" "\.m$"
comment "//"
# Stuffs,
color brightwhite "\<[A-Z_][0-9A-Z_]+\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Syntax highlighting for OCaml.
syntax "ocaml" "\.mli?$"
comment "(*|*)"
# Uid:
color red "\<[A-Z][0-9a-z_]{2,}\>"

Просмотреть файл

@ -2,6 +2,8 @@
syntax "patch" "\.(patch|diff|debdiff)$"
magic "diff output text"
# There is no official support for comments in patch files.
comment ""
# Added lines.
color brightgreen "^\+.*"

Просмотреть файл

@ -3,6 +3,7 @@
syntax "perl" "\.p[lm]$"
header "^#!.*perl[-0-9._]*"
magic "Perl script text"
comment "#"
color red "\<(accept|alarm|atan2|bin(d|mode)|c(aller|h(dir|mod|op|own|root)|lose(dir)?|onnect|os|rypt)|d(bm(close|open)|efined|elete|ie|o|ump)|e(ach|of|val|x(ec|ists|it|p))|f(cntl|ileno|lock|ork))\>" "\<(get(c|login|peername|pgrp|ppid|priority|pwnam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport)|([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|gmtime|goto|grep|hex|index|int|ioctl|join)\>" "\<(keys|kill|last|length|link|listen|local(time)?|log|lstat|m|mkdir|msg(ctl|get|snd|rcv)|next|oct|open(dir)?|ord|pack|pipe|pop|printf?|push|q|qq|qx|rand|re(ad(dir|link)?|cv|do|name|quire|set|turn|verse|winddir)|rindex|rmdir|s|scalar|seek(dir)?)\>" "\<(se(lect|mctl|mget|mop|nd|tpgrp|tpriority|tsockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|spli(ce|t)|sprintf|sqrt|srand|stat|study|substr|symlink|sys(call|read|tem|write)|tell(dir)?|time|tr(y)?|truncate|umask)\>" "\<(un(def|link|pack|shift)|utime|values|vec|wait(pid)?|wantarray|warn|write)\>"
color magenta "\<(continue|else|elsif|do|for|foreach|if|unless|until|while|eq|ne|lt|gt|le|ge|cmp|x|my|sub|use|package|can|isa)\>"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "php" "\.php[2345s~]?$"
magic "PHP script text"
comment "//"
# PHP markings.
color brightgreen "(<\?(php)?|\?>)"

Просмотреть файл

@ -1,6 +1,7 @@
## Colouring for PO files.
syntax "po" "\.pot?$"
comment "#"
# Comments.
color green "^#.*$"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "sql" "\.sql[2345s~]?$"
magic "PostgreSQL script text"
comment "-- "
# Functions.
color white "\<[a-z_]*\("

Просмотреть файл

@ -1,6 +1,7 @@
## Here is an example for POV-Ray.
syntax "pov" "\.(pov|POV|povray|POVRAY)$"
comment "//"
color brightcyan "^[[:space:]]*#[[:space:]]*(declare)"
color brightyellow "\<(sphere|cylinder|translate|matrix|rotate|scale)\>"

Просмотреть файл

@ -3,6 +3,7 @@
syntax "python" "\.py$"
header "^#!.*python[-0-9._]*"
linter pyflakes
comment "#"
# Function definitions.
icolor brightblue "def [0-9A-Z_]+"

Просмотреть файл

@ -3,6 +3,7 @@
syntax "ruby" "\.rb$"
header "^#!.*ruby[-0-9._]*"
linter ruby -w -c
comment "#"
# Reserved words.
color yellow "\<(BEGIN|END|alias|and|begin|break|case|class|def|defined\?|do|else|elsif|end|ensure|false|for|if|in|module)\>"

Просмотреть файл

@ -4,6 +4,7 @@ syntax "sh" "\.sh$"
header "^#!.*((ba|da|k|pdk)?sh[-0-9_]*|openrc-run|runscript)"
magic "(POSIX|Bourne.*) shell script text"
linter dash -n
comment "#"
icolor brightgreen "^[0-9A-Z_]+\(\)"
color green "\<(break|case|continue|do|done|elif|else|esac|exit|fi|for|function|if|in|read|return|select|shift|then|time|until|while)\>"

Просмотреть файл

@ -1,6 +1,7 @@
## Syntax highlighting for RPM spec files.
syntax "spec" "\.(spec$|spec\.*)"
comment "#"
# Main tags.
color brightblue "((Icon|ExclusiveOs|ExcludeOs)[[:space:]]*:)"

Просмотреть файл

@ -1,6 +1,7 @@
## Syntax highlighting for Tcl files.
syntax "tcl" "\.tcl$"
comment "#"
# Standard Tcl [info commands]:
color green "\<(after|append|array|auto_execok|auto_import|auto_load|auto_load_index|auto_qualify|binary|break|case|catch|cd|clock|close|concat|continue|encoding|eof|error|eval|exec|exit|expr|fblocked|fconfigure|fcopy|file|fileevent|flush|for|foreach|format|gets|glob|global|history|if|incr|info|interp|join|lappend|lindex|linsert|list|llength|load|lrange|lreplace|lsearch|lset|lsort|namespace|open|package|pid|puts|pwd|read|regexp|regsub|rename|return|scan|seek|set|socket|source|split|string|subst|switch|tclLog|tell|time|trace|unknown|unset|update|uplevel|upvar|variable|vwait|while)\>"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "tex" "\.tex$"
linter chktex -v0 -q -I
comment "%"
icolor green "\\.|\\[A-Z]*"
color magenta "[{}]"

Просмотреть файл

@ -3,6 +3,7 @@
syntax "texinfo" "\.texi$"
header "^\\input texinfo"
magic "Texinfo source text"
comment "@c "
# Command arguments, trailing and enclosed.
color cyan "^@[a-z]+[[:space:]]+.*$"

Просмотреть файл

@ -2,6 +2,7 @@
syntax "xml" "\.([jrsx]html?|jnlp|mml|pom|rng|sgml?|svg|w[as]dl|wsdd|xjb|xml|xs(d|lt?)|xul)$"
magic "(XML|SGML) (sub)?document text"
comment "<!--|-->"
# The entire content of the tag:
color green start="<" end=">"

Просмотреть файл

@ -886,6 +886,16 @@ to be edited, to determine whether this syntax should be used for that
file. This functionality only works when libmagic is installed on the
system and will be silently ignored otherwise.
@item comment "string"
Use the given string for commenting and uncommenting lines. A vertical bar or
pipe character (|) designates bracket-style comments; for example, "/*|*/" for
CSS files. The characters before the pipe are prepended to the line and the
characters after the pipe are appended at the end of the line. If no pipe
character is present, the entire string is prepended; for example, "#" for
Python files. If empty double quotes are specified, the comment/uncomment
functions are disabled; for example, "" for JSON. Double quotes or backslashes
may be escaped with a backslash; for example, ".\\"" for man page source.
@item color fgcolor,bgcolor "regex" @dots{}
Display all pieces of text that match the
extended regular expression "regex" with foreground color "fgcolor" and
@ -918,7 +928,7 @@ to @code{icolor}.
@item extendsyntax str directive [arg @dots{}]
Extend the syntax previously defined as str to include new information.
This allows you to add a new @code{color}, @code{icolor}, @code{header},
@code{magic}, @code{linter}, or @code{formatter} directive to an already
@code{magic}, @code{comment}, @code{linter}, or @code{formatter} directive to an already
defined syntax --- useful when you want to slightly improve a syntax defined
in one of the system-installed files (which are normally not writable).
@ -1043,6 +1053,10 @@ Indents (shifts to the right) the currently marked text.
@item unindent
Unindents (shifts to the left) the currently marked text.
@item comment
Comments or uncomments the current line or marked lines, using the comment
style specified in the active syntax.
@item left
Goes left one position (in the editor or browser).

Просмотреть файл

@ -554,6 +554,9 @@ void shortcut_init(void)
N_("Copy the current line and store it in the cutbuffer");
const char *nano_indent_msg = N_("Indent the current line");
const char *nano_unindent_msg = N_("Unindent the current line");
#ifdef ENABLE_COMMENT
const char *nano_comment_msg = N_("Comment/uncomment the current line or marked lines");
#endif
const char *nano_undo_msg = N_("Undo the last operation");
const char *nano_redo_msg = N_("Redo the last undone operation");
#endif
@ -937,6 +940,10 @@ void shortcut_init(void)
add_to_funcs(do_suspend_void, MMAIN,
N_("Suspend"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW);
#ifdef ENABLE_COMMENT
add_to_funcs(do_comment, MMAIN,
N_("Comment Lines"), IFSCHELP(nano_comment_msg), BLANKAFTER, NOVIEW);
#endif
#ifndef NANO_TINY
add_to_funcs(do_savefile, MMAIN,
N_("Save"), IFSCHELP(nano_savefile_msg), BLANKAFTER, NOVIEW);
@ -1103,6 +1110,9 @@ void shortcut_init(void)
add_to_sclist(MMAIN, "M-{", do_unindent, 0);
add_to_sclist(MMAIN, "M-U", do_undo, 0);
add_to_sclist(MMAIN, "M-E", do_redo, 0);
#endif
#ifdef ENABLE_COMMENT
add_to_sclist(MMAIN, "M-3", do_comment, 0);
#endif
add_to_sclist(MMOST, "^B", do_left, 0);
add_to_sclist(MMOST, "Left", do_left, 0);
@ -1419,6 +1429,10 @@ sc *strtosc(const char *input)
else if (!strcasecmp(input, "endpara"))
s->scfunc = do_para_end_void;
#endif
#ifdef ENABLE_COMMENT
else if (!strcasecmp(input, "comment"))
s->scfunc = do_comment;
#endif
#ifndef NANO_TINY
else if (!strcasecmp(input, "indent"))
s->scfunc = do_indent_void;

Просмотреть файл

@ -996,6 +996,9 @@ void version(void)
#ifdef DISABLE_COLOR
printf(" --disable-color");
#endif
#ifndef ENABLE_COMMENT
printf(" --disable-comment");
#endif
#ifdef DISABLE_EXTRA
printf(" --disable-extra");
#endif

Просмотреть файл

@ -191,6 +191,9 @@ typedef enum {
ADD, DEL, BACK, CUT, CUT_EOF, REPLACE,
#ifndef DISABLE_WRAPPING
SPLIT_BEGIN, SPLIT_END,
#endif
#ifndef DISABLE_COMMENT
COMMENT, UNCOMMENT, PREFLIGHT,
#endif
JOIN, PASTE, INSERT, ENTER, OTHER
} undo_type;
@ -251,6 +254,8 @@ typedef struct syntaxtype {
/* The command with which to lint this type of file. */
char *formatter;
/* The formatting command (for programming languages mainly). */
char *comment;
/* The line comment prefix (and postfix) for this type of file. */
colortype *color;
/* The colors and their regexes used in this syntax. */
int nmultis;
@ -322,6 +327,14 @@ typedef struct partition {
} partition;
#ifndef NANO_TINY
typedef struct undo_group {
ssize_t top_line;
/* First line of group. */
ssize_t bottom_line;
/* Last line of group. */
struct undo_group *next;
} undo_group;
typedef struct undo {
ssize_t lineno;
undo_type type;
@ -336,6 +349,8 @@ typedef struct undo {
/* The file size after the action. */
int xflags;
/* Some flag data we need. */
undo_group *grouping;
/* Undo info specific to groups of lines. */
/* Cut-specific stuff we need. */
filestruct *cutbuffer;

Просмотреть файл

@ -653,6 +653,9 @@ void do_unindent(void);
void do_undo(void);
void do_redo(void);
#endif
#ifndef DISABLE_COMMENT
void do_comment(void);
#endif
void do_enter(void);
#ifndef NANO_TINY
RETSIGTYPE cancel_command(int signal);
@ -745,6 +748,11 @@ void mark_order(const filestruct **top, size_t *top_x, const filestruct
void discard_until(const undo *thisitem, openfilestruct *thefile);
void add_undo(undo_type action);
void update_undo(undo_type action);
#ifndef DISABLE_COMMENT
void add_comment_undo(undo_type action, const char *comment_seq, size_t undo_x);
void update_comment_undo(ssize_t lineno);
bool comment_line(undo_type action, filestruct *f, const char *comment_seq);
#endif
#endif
size_t get_totsize(const filestruct *begin, const filestruct *end);
filestruct *fsfromline(ssize_t lineno);

Просмотреть файл

@ -306,6 +306,7 @@ void parse_syntax(char *ptr)
live_syntax->magics = NULL;
live_syntax->linter = NULL;
live_syntax->formatter = NULL;
live_syntax->comment = NULL;
live_syntax->color = NULL;
lastcolor = NULL;
live_syntax->nmultis = 0;
@ -868,6 +869,24 @@ void pick_up_name(const char *kind, char *ptr, char **storage)
/* Allow unsetting the command by using an empty string. */
if (!strcmp(ptr, "\"\""))
*storage = NULL;
else if (*ptr == '"') {
*storage = mallocstrcpy(NULL, ++ptr);
char* q = *storage;
char* p = *storage;
/* Snip out the backslashes of escaped characters. */
while (*p != '"') {
if (*p == '\0') {
rcfile_error(N_("Argument of '%s' lacks closing \""), kind);
free(*storage);
*storage = NULL;
return;
} else if (*p == '\\' && *(p + 1) != '\0') {
p++;
}
*q++ = *p++;
}
*q = '\0';
}
else
*storage = mallocstrcpy(NULL, ptr);
}
@ -982,6 +1001,12 @@ void parse_rcfile(FILE *rcstream
grab_and_store("magic", ptr, &live_syntax->magics);
#else
;
#endif
else if (strcasecmp(keyword, "comment") == 0)
#ifdef ENABLE_COMMENT
pick_up_name("comment", ptr, &live_syntax->comment);
#else
;
#endif
else if (strcasecmp(keyword, "color") == 0)
parse_colors(ptr, NANO_REG_EXTENDED);

Просмотреть файл

@ -425,7 +425,194 @@ void do_unindent(void)
{
do_indent(-tabsize);
}
#endif /* !NANO_TINY */
#ifdef ENABLE_COMMENT
/* Test whether the string is empty or consists of only blanks. */
bool white_string(const char *s)
{
while (*s != '\0' && (is_blank_mbchar(s) || *s == '\r'))
s += move_mbright(s, 0);
return !*s;
}
/* Comment or uncomment the current line or the marked lines. */
void do_comment()
{
const char *comment_seq = "#";
undo_type action = UNCOMMENT;
filestruct *top, *bot, *f;
size_t top_x, bot_x, was_x;
bool empty, all_empty = TRUE;
bool file_changed = FALSE;
/* Whether any comment has been added or deleted. */
assert(openfile->current != NULL && openfile->current->data != NULL);
#ifndef DISABLE_COLOR
if (openfile->syntax && openfile->syntax->comment)
comment_seq = openfile->syntax->comment;
/* Does the syntax not allow comments? */
if (strlen(comment_seq) == 0) {
statusbar(_("Commenting is not supported for this file type"));
return;
}
#endif
/* Determine which lines to work on. */
if (openfile->mark_set)
mark_order((const filestruct **) &top, &top_x,
(const filestruct **) &bot, &bot_x, NULL);
else {
top = openfile->current;
bot = top;
}
/* Remember the cursor x position to be restored when undoing. */
was_x = openfile->current_x;
/* Figure out whether to comment or uncomment the selected line or lines. */
for (f = top; f != bot->next; f = f->next) {
empty = white_string(f->data);
/* If this line is not blank and not commented, we comment all. */
if (!empty && !comment_line(PREFLIGHT, f, comment_seq)) {
action = COMMENT;
break;
}
all_empty = all_empty && empty;
}
/* If all selected lines are blank, we comment them. */
action = all_empty ? COMMENT : action;
/* Process the selected line or lines. */
for (f = top; f != bot->next; f = f->next) {
if (comment_line(action, f, comment_seq)) {
if (!file_changed) {
/* Start building undo data on the first modified line. */
add_comment_undo(action, comment_seq, was_x);
file_changed = TRUE;
}
/* Add undo data for each modified line. */
update_comment_undo(f->lineno);
}
}
if (file_changed) {
set_modified();
refresh_needed = TRUE;
} else
statusbar(_("Cannot comment past end of file"));
}
/* Test whether the given line can be uncommented, or add or remove a comment,
* depending on action. Return TRUE if the line is uncommentable, or when
* anything was added or removed; FALSE otherwise. */
bool comment_line(undo_type action, filestruct *f, const char *comment_seq)
{
size_t comment_seq_len = strlen(comment_seq);
const char *post_seq = strchr(comment_seq, '|');
/* The postfix, if this is a bracketing type comment sequence. */
size_t pre_len = post_seq ? post_seq++ - comment_seq : comment_seq_len;
/* Length of prefix. */
size_t post_len = post_seq ? comment_seq_len - pre_len - 1 : 0;
/* Length of postfix. */
size_t line_len = strlen(f->data);
if (!ISSET(NO_NEWLINES) && f == openfile->filebot)
return FALSE;
if (action == COMMENT) {
/* Make room for the comment sequence(s), move the text right and
* copy them in. */
f->data = charealloc(f->data, line_len + pre_len + post_len + 1);
charmove(&f->data[pre_len], f->data, line_len);
charmove(f->data, comment_seq, pre_len);
if (post_len)
charmove(&f->data[pre_len + line_len], post_seq, post_len);
f->data[pre_len + line_len + post_len] = '\0';
openfile->totsize += pre_len + post_len;
/* If needed, adjust the position of the mark and of the cursor. */
if (openfile->mark_set && f == openfile->mark_begin)
openfile->mark_begin_x += pre_len;
if (f == openfile->current) {
openfile->current_x += pre_len;
openfile->placewewant = xplustabs();
}
return TRUE;
}
/* If the line is commented, report it as uncommentable, or uncomment it. */
if (strncmp(f->data, comment_seq, pre_len) == 0 && (post_len == 0 ||
strcmp(&f->data[line_len - post_len], post_seq) == 0)) {
if (action == PREFLIGHT)
return TRUE;
/* Erase the comment prefix by moving the non-comment part. */
charmove(f->data, &f->data[pre_len], line_len - pre_len);
/* Truncate the postfix if there was one. */
f->data[line_len - pre_len - post_len] = '\0';
openfile->totsize -= pre_len + post_len;
/* If needed, adjust the position of the mark and then the cursor. */
if (openfile->mark_set && f == openfile->mark_begin) {
if (openfile->mark_begin_x < pre_len)
openfile->mark_begin_x = 0;
else
openfile->mark_begin_x -= pre_len;
}
if (f == openfile->current) {
if (openfile->current_x < pre_len)
openfile->current_x = 0;
else
openfile->current_x -= pre_len;
openfile->placewewant = xplustabs();
}
return TRUE;
}
return FALSE;
}
/* Perform an undo or redo for a comment or uncomment action. */
void handle_comment_action(undo *u, bool undoing, bool add_comment)
{
undo_group *group = u->grouping;
/* When redoing, reposition the cursor and let the commenter adjust it. */
if (!undoing)
goto_line_posx(u->lineno, u->begin);
while (group) {
filestruct *f = fsfromline(group->top_line);
while (f && f->lineno <= group->bottom_line) {
comment_line(undoing ^ add_comment ?
COMMENT : UNCOMMENT, f, u->strdata);
f = f->next;
}
group = group->next;
}
/* When undoing, reposition the cursor to the recorded location. */
if (undoing)
goto_line_posx(u->lineno, u->begin);
refresh_needed = TRUE;
}
#endif /* ENABLE_COMMENT */
#ifndef NANO_TINY
#define redo_paste undo_cut
#define undo_paste redo_cut
@ -574,6 +761,16 @@ void do_undo(void)
unlink_node(f->next);
goto_line_posx(u->lineno, u->begin);
break;
#ifdef ENABLE_COMMENT
case COMMENT:
handle_comment_action(u, TRUE, TRUE);
undidmsg = _("comment");
break;
case UNCOMMENT:
handle_comment_action(u, TRUE, FALSE);
undidmsg = _("uncomment");
break;
#endif
case INSERT:
undidmsg = _("text insert");
filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
@ -738,6 +935,16 @@ void do_redo(void)
free_filestruct(u->cutbuffer);
u->cutbuffer = NULL;
break;
#ifdef ENABLE_COMMENT
case COMMENT:
handle_comment_action(u, FALSE, TRUE);
redidmsg = _("comment");
break;
case UNCOMMENT:
handle_comment_action(u, FALSE, FALSE);
redidmsg = _("uncomment");
break;
#endif
default:
statusline(ALERT, _("Internal error: unknown type. "
"Please save your work."));
@ -909,11 +1116,20 @@ bool execute_command(const char *command)
void discard_until(const undo *thisitem, openfilestruct *thefile)
{
undo *dropit = thefile->undotop;
undo_group *group;
while (dropit != NULL && dropit != thisitem) {
thefile->undotop = dropit->next;
free(dropit->strdata);
free_filestruct(dropit->cutbuffer);
#ifdef ENABLE_COMMENT
group = dropit->grouping;
while (group != NULL) {
undo_group *next = group->next;
free(group);
group = next;
}
#endif
free(dropit);
dropit = thefile->undotop;
}
@ -969,6 +1185,7 @@ void add_undo(undo_type action)
u->mark_set = FALSE;
u->wassize = openfile->totsize;
u->xflags = 0;
u->grouping = NULL;
switch (u->type) {
/* We need to start copying data into the undo buffer
@ -1036,6 +1253,11 @@ void add_undo(undo_type action)
break;
case ENTER:
break;
#ifdef ENABLE_COMMENT
case COMMENT:
case UNCOMMENT:
break;
#endif
default:
statusline(ALERT, _("Internal error: unknown type. "
"Please save your work."));
@ -1049,6 +1271,42 @@ void add_undo(undo_type action)
openfile->last_action = action;
}
#ifdef ENABLE_COMMENT
/* Add a comment undo item. This should be called once for each use
* of the comment/uncomment feature that modifies the document. */
void add_comment_undo(undo_type action, const char *comment_seq, size_t was_x)
{
add_undo(action);
/* Store the comment sequence used for the operation, because it could
* change when the file name changes; we need to know what it was. */
openfile->current_undo->strdata = mallocstrcpy(NULL, comment_seq);
/* Remember the position of the cursor before the change was made. */
openfile->current_undo->begin = was_x;
}
/* Update a comment undo item. This should be called once for each line
* affected by the comment/uncomment feature. */
void update_comment_undo(ssize_t lineno)
{
undo *u = openfile->current_undo;
/* If there already is a group and the current line is contiguous with it,
* extend the group; otherwise, create a new group. */
if (u->grouping && u->grouping->bottom_line + 1 == lineno)
u->grouping->bottom_line++;
else {
undo_group *born = (undo_group *)nmalloc(sizeof(undo_group));
born->next = u->grouping;
u->grouping = born;
born->top_line = lineno;
born->bottom_line = lineno;
}
}
#endif /* ENABLE_COMMENT */
/* Update an undo item, or determine whether a new one is really needed
* and bounce the data to add_undo instead. The latter functionality
* just feels gimmicky and may just be more hassle than it's worth,