[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Nano-devel] [PATCH] restored feature: a per-syntax 'fixer' command that
From: |
Benno Schulenberg |
Subject: |
[Nano-devel] [PATCH] restored feature: a per-syntax 'fixer' command that processes the buffer |
Date: |
Thu, 10 Oct 2019 19:17:38 +0200 |
The command can be used to run some kind of formatter or corrector or
arranging tool on the buffer. By default the command is bound to M-F.
The formatter/corrector/arranging program must be non-interactive.
This addresses https://savannah.gnu.org/bugs/?55365,
and addresses https://savannah.gnu.org/bugs/?54651.
---
src/files.c | 7 ++---
src/global.c | 12 +++++++--
src/nano.h | 2 ++
src/proto.h | 4 ++-
src/rcfile.c | 6 ++++-
src/text.c | 76 +++++++++++++++++++++++++++++++++++++++++++---------
6 files changed, 88 insertions(+), 19 deletions(-)
diff --git a/src/files.c b/src/files.c
index 5f687645..ebf361f6 100644
--- a/src/files.c
+++ b/src/files.c
@@ -513,7 +513,8 @@ bool open_buffer(const char *filename, bool new_buffer)
#ifdef ENABLE_SPELLER
/* Open the specified file, and if that succeeds, remove the text of the marked
* region or of the entire buffer and read the file contents into its place. */
-bool replace_buffer(const char *filename, undo_type action, bool marked)
+bool replace_buffer(const char *filename, undo_type action, bool marked,
+ const char *operation)
{
linestruct *was_cutbuffer = cutbuffer;
int descriptor;
@@ -525,7 +526,7 @@ bool replace_buffer(const char *filename, undo_type action,
bool marked)
return FALSE;
#ifndef NANO_TINY
- add_undo(COUPLE_BEGIN, "spelling correction");
+ add_undo(COUPLE_BEGIN, operation);
#endif
/* When nothing is marked, start at the top of the buffer. */
@@ -550,7 +551,7 @@ bool replace_buffer(const char *filename, undo_type action,
bool marked)
read_file(f, descriptor, filename, TRUE);
#ifndef NANO_TINY
- add_undo(COUPLE_END, "spelling correction");
+ add_undo(COUPLE_END, operation);
#endif
return TRUE;
}
diff --git a/src/global.c b/src/global.c
index c8b01c7e..b3a3c40e 100644
--- a/src/global.c
+++ b/src/global.c
@@ -693,6 +693,8 @@ void shortcut_init(void)
const char *lint_gist = N_("Invoke the linter, if available");
const char *prevlint_gist = N_("Go to previous linter msg");
const char *nextlint_gist = N_("Go to next linter msg");
+ const char *fixer_gist =
+ N_("Invoke a program to manipulate the buffer, if available");
#endif
#endif /* ENABLE_HELP */
@@ -1001,9 +1003,12 @@ void shortcut_init(void)
N_("Zap Text"), WITHORSANS(zap_gist), BLANKAFTER, NOVIEW);
#ifdef ENABLE_COLOR
- if (!ISSET(RESTRICTED))
+ if (!ISSET(RESTRICTED)) {
add_to_funcs(do_linter, MMAIN,
- N_("To Linter"), WITHORSANS(lint_gist),
BLANKAFTER, NOVIEW);
+ N_("To Linter"), WITHORSANS(lint_gist),
TOGETHER, NOVIEW);
+ add_to_funcs(do_fixer, MMAIN,
+ N_("Manipulate"), WITHORSANS(fixer_gist),
BLANKAFTER, NOVIEW);
+ }
#endif
#endif
add_to_funcs(do_savefile, MMAIN,
@@ -1124,6 +1129,7 @@ void shortcut_init(void)
#endif
#ifdef ENABLE_COLOR
add_to_sclist(MMAIN, "M-B", 0, do_linter, 0);
+ add_to_sclist(MMAIN, "M-F", 0, do_fixer, 0);
#endif
add_to_sclist(MMAIN, "^C", 0, do_cursorpos_void, 0);
add_to_sclist(MMAIN, "^_", 0, do_gotolinecolumn_void, 0);
@@ -1502,6 +1508,8 @@ keystruct *strtosc(const char *input)
#ifdef ENABLE_COLOR
else if (!strcasecmp(input, "linter"))
s->func = do_linter;
+ else if (!strcasecmp(input, "fixer"))
+ s->func = do_fixer;
#endif
else if (!strcasecmp(input, "curpos"))
s->func = do_cursorpos_void;
diff --git a/src/nano.h b/src/nano.h
index 373ce5c2..f25e5382 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -234,6 +234,8 @@ typedef struct syntaxtype {
/* The list of libmagic results that this syntax applies to. */
char *linter;
/* The command with which to lint this type of file. */
+ char *fixer;
+ /* The command with which to "fix"/format/modify this type of
file. */
char *tab;
/* What the Tab key should produce; NULL for default behavior.
*/
#ifdef ENABLE_COMMENT
diff --git a/src/proto.h b/src/proto.h
index 14e4d139..c97cd863 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -276,7 +276,8 @@ void make_new_buffer(void);
void set_modified(void);
bool open_buffer(const char *filename, bool new_buffer);
#ifdef ENABLE_SPELLER
-bool replace_buffer(const char *filename, undo_type action, bool marked);
+bool replace_buffer(const char *filename, undo_type action, bool marked,
+ const char *operation);
#endif
void prepare_for_display(void);
#ifdef ENABLE_MULTIBUFFER
@@ -551,6 +552,7 @@ void do_spell(void);
#endif
#ifdef ENABLE_COLOR
void do_linter(void);
+void do_fixer(void);
#endif
#ifndef NANO_TINY
void do_wordlinechar_count(void);
diff --git a/src/rcfile.c b/src/rcfile.c
index eb8e842d..4a5d294e 100644
--- a/src/rcfile.c
+++ b/src/rcfile.c
@@ -333,6 +333,7 @@ void begin_new_syntax(char *ptr)
live_syntax->headers = NULL;
live_syntax->magics = NULL;
live_syntax->linter = NULL;
+ live_syntax->fixer = NULL;
live_syntax->tab = NULL;
#ifdef ENABLE_COMMENT
live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER);
@@ -955,6 +956,8 @@ bool parse_syntax_commands(char *keyword, char *ptr)
#endif
} else if (strcasecmp(keyword, "linter") == 0)
pick_up_name("linter", ptr, &live_syntax->linter);
+ else if (strcasecmp(keyword, "fixer") == 0)
+ pick_up_name("fixer", ptr, &live_syntax->fixer);
else
return FALSE;
@@ -1110,7 +1113,8 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool
intros_only)
strcasecmp(keyword, "icolor") == 0 ||
strcasecmp(keyword, "comment") == 0 ||
strcasecmp(keyword, "tabgives") == 0 ||
-
strcasecmp(keyword, "linter") == 0)) {
+
strcasecmp(keyword, "linter") == 0 ||
+
strcasecmp(keyword, "fixer") == 0)) {
if (!opensyntax)
jot_error(N_("A '%s' command requires a
preceding "
"'syntax' command"), keyword);
diff --git a/src/text.c b/src/text.c
index 7921eac7..295a6095 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2534,28 +2534,31 @@ const char *do_int_speller(const char *tempfile_name)
}
/* Execute the given program, with the given temp file as last argument. */
-const char *treat(char *tempfile_name, char *theprogram)
+const char *treat(char *tempfile_name, char *theprogram, bool spelling)
{
ssize_t lineno_save = openfile->current->lineno;
size_t current_x_save = openfile->current_x;
size_t pww_save = openfile->placewewant;
bool was_at_eol = (openfile->current->data[openfile->current_x] ==
'\0');
+ const char *msg = (spelling ? N_("spelling correction") :
N_("manipulation"));
struct stat fileinfo;
- time_t timestamp;
+ long timestamp_sec, timestamp_nsec;
static char **arguments = NULL;
pid_t thepid;
int program_status;
/* Get the timestamp and the size of the temporary file. */
stat(tempfile_name, &fileinfo);
- timestamp = fileinfo.st_mtime;
+ timestamp_sec = (long)fileinfo.st_mtim.tv_sec;
+ timestamp_nsec = (long)fileinfo.st_mtim.tv_nsec;
/* If the number of bytes to check is zero, get out. */
if (fileinfo.st_size == 0)
return NULL;
- /* Exit from curses mode. */
- endwin();
+ /* The spell checker needs the screen, so exit from curses mode. */
+ if (spelling)
+ endwin();
construct_argument_list(&arguments, theprogram, tempfile_name);
@@ -2574,9 +2577,11 @@ const char *treat(char *tempfile_name, char *theprogram)
wait(&program_status);
block_sigwinch(FALSE);
- /* Set the desired terminal state again, and reenter curses mode. */
- terminal_init();
- doupdate();
+ /* When needed, restore the terminal state and reenter curses mode. */
+ if (spelling) {
+ terminal_init();
+ doupdate();
+ }
if (!WIFEXITED(program_status) || WEXITSTATUS(program_status) != 0)
return invocation_error(theprogram);
@@ -2585,7 +2590,8 @@ const char *treat(char *tempfile_name, char *theprogram)
stat(tempfile_name, &fileinfo);
/* Read in the temporary file only when it changed. */
- if (fileinfo.st_mtime != timestamp) {
+ if ((long)fileinfo.st_mtim.tv_sec != timestamp_sec ||
+ (long)fileinfo.st_mtim.tv_nsec !=
timestamp_nsec) {
bool replaced = FALSE;
#ifndef NANO_TINY
/* Replace the marked text (or entire text) with the corrected
text. */
@@ -2595,7 +2601,7 @@ const char *treat(char *tempfile_name, char *theprogram)
openfile->mark_x < openfile->current_x));
ssize_t was_mark_lineno = openfile->mark->lineno;
- replaced = replace_buffer(tempfile_name, CUT, TRUE);
+ replaced = replace_buffer(tempfile_name, CUT, TRUE,
msg);
/* Adjust the end point of the marked region for any
change in
* length of the region's last line. */
@@ -2608,7 +2614,7 @@ const char *treat(char *tempfile_name, char *theprogram)
openfile->mark = line_from_number(was_mark_lineno);
} else
#endif
- replaced = replace_buffer(tempfile_name, CUT_TO_EOF,
FALSE);
+ replaced = replace_buffer(tempfile_name, CUT_TO_EOF,
FALSE, msg);
/* Go back to the old position. */
goto_line_posx(lineno_save, current_x_save);
@@ -2667,7 +2673,10 @@ void do_spell(void)
blank_bottombars();
- result_msg = (alt_speller ? treat(temp, alt_speller) :
do_int_speller(temp));
+ if (alt_speller)
+ result_msg = treat(temp, alt_speller, TRUE);
+ else
+ result_msg = do_int_speller(temp);
unlink(temp);
free(temp);
@@ -3031,6 +3040,49 @@ void do_linter(void)
currmenu = MMOST;
titlebar(NULL);
}
+
+#ifdef ENABLE_SPELLER
+/* Run a manipulation program on the contents of the buffer. */
+void do_fixer(void)
+{
+ FILE *stream;
+ char *temp_name;
+ bool okay = FALSE;
+ const char *result_msg;
+
+ if (in_restricted_mode())
+ return;
+
+ if (!openfile->syntax || !openfile->syntax->fixer) {
+ statusbar(_("No fixer is defined for this type of file"));
+ return;
+ }
+
+ temp_name = safe_tempfile(&stream);
+
+ if (temp_name != NULL)
+ okay = write_file(temp_name, stream, TRUE, OVERWRITE, TRUE);
+
+ if (!okay) {
+ statusline(ALERT, _("Error writing temp file: %s"),
strerror(errno));
+ free(temp_name);
+ return;
+ }
+
+ /* Manipulation always happens on the whole buffer. */
+ openfile->mark = NULL;
+
+ result_msg = treat(temp_name, openfile->syntax->fixer, FALSE);
+
+ if (result_msg != NULL)
+ statusline(ALERT, result_msg);
+ else
+ statusbar(_("Buffer has been processed"));
+
+ unlink(temp_name);
+ free(temp_name);
+}
+#endif /* ENABLE_SPELLER */
#endif /* ENABLE_COLOR */
#ifndef NANO_TINY
--
2.23.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Nano-devel] [PATCH] restored feature: a per-syntax 'fixer' command that processes the buffer,
Benno Schulenberg <=