From f85001a368b57121b74cfbbfc2c8d668fd3cbab2 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Fri, 28 Apr 2006 13:19:56 +0000 Subject: [PATCH] add the ability to indent and unindent all marked lines of text, via Meta-[ (Meta-}) and Meta-] (Meta-}), per Chris' patch with some changes by me git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@3446 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 7 ++- src/global.c | 20 ++++++-- src/nano.h | 9 +++- src/proto.h | 5 ++ src/text.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 174 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index e122cf65..54fbc76c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -60,6 +60,11 @@ CVS code - when NANO_TINY is defined. New functions do_cut_text_void() and do_copy_text(); changes to do_cut_text(), shortcut_init(), and do_input(). (DLR, suggested by Ken Tyler) + - Add the ability to indent and unindent all marked lines of + text, via Meta-[ (Meta-}) and Meta-] (Meta-}). New functions + do_indent_marked(), do_indent_marked_void(), and + do_unindent_marked_void(); changes to shortcut_init(). (Chris + and DLR) - files.c: open_file() - Remove redundant wording in the error message when we try to @@ -101,7 +106,7 @@ CVS code - (DLR and Benno Schulenberg, suggested by Benno Schulenberg) - Tweak the descriptions of some shortcut keys to make them more uniform. (Benno Schulenberg, minor tweaks by DLR) - - Add Meta-} as an alias for Meta-]. (DLR) + - Change the shortcut to find the matching bracket to ^]. (DLR) toggle_init() - In the global toggle list, move the "Constant cursor position display" toggle up to after the "Use more space for editing" diff --git a/src/global.c b/src/global.c index f6af80a7..888aaca2 100644 --- a/src/global.c +++ b/src/global.c @@ -338,6 +338,8 @@ void shortcut_init(bool unjustify) const char *nano_whereis_next_msg = N_("Repeat last search"); const char *nano_copy_msg = N_("Copy the current line and store it in the cutbuffer"); + const char *nano_indentmarked_msg = N_("Indent marked text"); + const char *nano_unindentmarked_msg = N_("Unindent marked text"); #endif const char *nano_forward_msg = N_("Move forward one character"); const char *nano_back_msg = N_("Move back one character"); @@ -564,8 +566,18 @@ void shortcut_init(bool unjustify) NANO_WHEREIS_NEXT_FKEY, NANO_NO_KEY, VIEW, do_research); sc_init_one(&main_list, NANO_NO_KEY, N_("Copy Text"), - IFHELP(nano_copy_msg, TRUE), NANO_COPY_KEY, NANO_NO_KEY, + IFHELP(nano_copy_msg, FALSE), NANO_COPY_KEY, NANO_NO_KEY, NANO_COPY_ALTKEY, NOVIEW, do_copy_text); + + sc_init_one(&main_list, NANO_NO_KEY, N_("Indent Text"), + IFHELP(nano_indentmarked_msg, FALSE), NANO_INDENTMARKED_KEY, + NANO_NO_KEY, NANO_INDENTMARKED_ALTKEY, NOVIEW, + do_indent_marked_void); + + sc_init_one(&main_list, NANO_NO_KEY, N_("Unindent Text"), + IFHELP(nano_unindentmarked_msg, TRUE), NANO_UNINDENTMARKED_KEY, + NANO_NO_KEY, NANO_UNINDENTMARKED_ALTKEY, NOVIEW, + do_unindent_marked_void); #endif sc_init_one(&main_list, NANO_FORWARD_KEY, N_("Forward"), @@ -621,9 +633,9 @@ void shortcut_init(bool unjustify) NANO_NO_KEY, NANO_LASTLINE_ALTKEY2, VIEW, do_last_line); #ifndef NANO_TINY - sc_init_one(&main_list, NANO_NO_KEY, N_("Find Other Bracket"), - IFHELP(nano_bracket_msg, FALSE), NANO_BRACKET_KEY, NANO_NO_KEY, - NANO_BRACKET_ALTKEY, VIEW, do_find_bracket); + sc_init_one(&main_list, NANO_BRACKET_KEY, N_("Find Other Bracket"), + IFHELP(nano_bracket_msg, FALSE), NANO_NO_KEY, NANO_NO_KEY, + NANO_NO_KEY, VIEW, do_find_bracket); sc_init_one(&main_list, NANO_NO_KEY, N_("Scroll Up"), IFHELP(nano_scrollup_msg, FALSE), NANO_SCROLLUP_KEY, diff --git a/src/nano.h b/src/nano.h index 68f32550..234fc744 100644 --- a/src/nano.h +++ b/src/nano.h @@ -427,6 +427,7 @@ typedef struct rcoption { #define NANO_ALT_EQUALS '=' #define NANO_ALT_RCARET '>' #define NANO_ALT_QUESTION '?' +#define NANO_ALT_LBRACKET '[' #define NANO_ALT_BACKSLASH '\\' #define NANO_ALT_RBRACKET ']' #define NANO_ALT_CARET '^' @@ -457,6 +458,7 @@ typedef struct rcoption { #define NANO_ALT_X 'x' #define NANO_ALT_Y 'y' #define NANO_ALT_Z 'z' +#define NANO_ALT_LCURLYBRACKET '{' #define NANO_ALT_PIPE '|' #define NANO_ALT_RCURLYBRACKET '}' @@ -540,6 +542,10 @@ typedef struct rcoption { #define NANO_DELETE_KEY NANO_CONTROL_D #define NANO_BACKSPACE_KEY NANO_CONTROL_H #define NANO_TAB_KEY NANO_CONTROL_I +#define NANO_INDENTMARKED_KEY NANO_ALT_LBRACKET +#define NANO_INDENTMARKED_ALTKEY NANO_ALT_LCURLYBRACKET +#define NANO_UNINDENTMARKED_KEY NANO_ALT_RBRACKET +#define NANO_UNINDENTMARKED_ALTKEY NANO_ALT_RCURLYBRACKET #define NANO_SUSPEND_KEY NANO_CONTROL_Z #define NANO_ENTER_KEY NANO_CONTROL_M #define NANO_TOFILES_KEY NANO_CONTROL_T @@ -549,8 +555,7 @@ typedef struct rcoption { #define NANO_NEXTFILE_KEY NANO_ALT_RCARET #define NANO_PREVFILE_ALTKEY NANO_ALT_COMMA #define NANO_NEXTFILE_ALTKEY NANO_ALT_PERIOD -#define NANO_BRACKET_KEY NANO_ALT_RBRACKET -#define NANO_BRACKET_ALTKEY NANO_ALT_RCURLYBRACKET +#define NANO_BRACKET_KEY NANO_CONTROL_5 #define NANO_NEXTWORD_KEY NANO_CONTROL_SPACE #define NANO_PREVWORD_KEY NANO_ALT_SPACE #define NANO_WORDCOUNT_KEY NANO_ALT_D diff --git a/src/proto.h b/src/proto.h index 2fa044ea..642d599b 100644 --- a/src/proto.h +++ b/src/proto.h @@ -602,6 +602,11 @@ void do_mark(void); void do_delete(void); void do_backspace(void); void do_tab(void); +#ifndef NANO_TINY +void do_indent_marked(ssize_t len); +void do_indent_marked_void(void); +void do_unindent_marked_void(void); +#endif void do_enter(void); #ifndef NANO_TINY RETSIGTYPE cancel_command(int signal); diff --git a/src/text.c b/src/text.c index 3ab0f66b..495e985f 100644 --- a/src/text.c +++ b/src/text.c @@ -193,6 +193,146 @@ void do_tab(void) #endif } +#ifndef NANO_TINY +/* Indent or unindent all lines covered by the mark len characters, + * depending on whether len is positive or negative. If the + * TABS_TO_SPACES flag is set, indent/unindent by len spaces. + * Otherwise, indent/unindent by (len / tabsize) tabs and (len % + * tabsize) spaces. */ +void do_indent_marked(ssize_t len) +{ + bool indent_changed = FALSE; + /* Whether any indenting or unindenting was done. */ + bool unindent = FALSE; + /* Whether we're unindenting text. */ + char *line_indent; + /* The text added to each line in order to indent it. */ + size_t line_indent_len; + /* The length of the text added to each line in order to indent + * it. */ + filestruct *top, *bot, *f; + size_t top_x, bot_x; + + assert(openfile->current != NULL && openfile->current->data != NULL); + + check_statusblank(); + + /* If the mark isn't on, indicate it on the statusbar and get + * out. */ + if (!openfile->mark_set) { + statusbar(_("No lines selected, nothing to do!")); + return; + } + + /* If len is zero, get out. */ + if (len == 0) + return; + + /* If len is negative, make it positive and set unindent to TRUE. */ + if (len < 0) { + len = -len; + unindent = TRUE; + /* Otherwise, we're indenting, in which case the file will always be + * modified, so set indent_changed to TRUE. */ + } else + indent_changed = TRUE; + + /* Get the coordinates of the marked text. */ + mark_order((const filestruct **)&top, &top_x, + (const filestruct **)&bot, &bot_x, NULL); + + /* Set up the text we'll be using as indentation. */ + line_indent = charalloc(len + 1); + + if (ISSET(TABS_TO_SPACES)) { + /* Set the indentation to len spaces. */ + charset(line_indent, ' ', len); + line_indent_len = len; + } else { + /* Set the indentation to (len / tabsize) tabs and (len % + * tabsize) spaces. */ + size_t num_tabs = len / tabsize; + size_t num_spaces = len % tabsize; + + charset(line_indent, '\t', num_tabs); + charset(line_indent + num_tabs, ' ', num_spaces); + + line_indent_len = num_tabs + num_spaces; + } + + line_indent[line_indent_len] = '\0'; + + /* Go through each line of the marked text. */ + for (f = top; f != bot->next; f = f->next) { + size_t line_len = strlen(f->data); + + if (unindent) { + if (len <= strnlenpt(f->data, indent_length(f->data))) { + size_t indent_len = actual_x(f->data, len); + + /* If we're unindenting, and there's at least len + * columns' worth of indentation on this line, remove + * it. */ + charmove(f->data, &f->data[indent_len], line_len - + indent_len + 1); + null_at(&f->data, line_len - indent_len + 1); + openfile->totsize -= indent_len; + + /* If this is the current line, adjust the x-coordinate + * to compensate for the change in it. */ + if (f == openfile->current) + openfile->current_x -= indent_len; + + /* We've unindented, so set indent_changed to TRUE. */ + if (!indent_changed) + indent_changed = TRUE; + } + } else { + /* If we're indenting, add the characters in line_indent to + * the beginning of this line. */ + f->data = charealloc(f->data, line_len + + line_indent_len + 1); + charmove(&f->data[line_indent_len], f->data, line_len + 1); + strncpy(f->data, line_indent, line_indent_len); + openfile->totsize += line_indent_len; + + /* If this is the current line, adjust the x-coordinate to + * compensate for the change in it. */ + if (f == openfile->current) + openfile->current_x += line_indent_len; + + /* If the NO_NEWLINES flag isn't set, and this is the + * magicline, add a new magicline. */ + if (!ISSET(NO_NEWLINES) && openfile->current == + openfile->filebot) + new_magicline(); + } + } + + free(line_indent); + + if (indent_changed) { + /* Mark the file as modified. */ + set_modified(); + + /* Update the screen. */ + edit_refresh(); + } +} + +/* Indent all lines covered by the mark tabsize characters. */ +void do_indent_marked_void(void) +{ + do_indent_marked(tabsize); +} + +/* Unindent all lines covered by the mark tabsize characters. */ +void do_unindent_marked_void(void) +{ + do_indent_marked(-tabsize); +} +#endif /* !NANO_TINY */ + /* Someone hits Enter *gasp!* */ void do_enter(void) { -- 2.39.5