nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Nano-devel] PATCH: indent/un-indent marked text with tab/shift+tab


From: David Lawrence Ramsey
Subject: Re: [Nano-devel] PATCH: indent/un-indent marked text with tab/shift+tab
Date: Wed, 26 Apr 2006 19:40:20 -0400
User-agent: Thunderbird 1.5 (X11/20051201)

David Lawrence Ramsey wrote:

<snip>

> I've tried cleaning it up a bit, as well as implementing your above
> suggestion about tabs versus spaces, and I have the attached patch so
> far (using Meta-' for indenting and Meta-` for unindenting for the
> time being).  How does it compare to what you need?

I just noticed that it doesn't maintain totsize properly.  The attached
version fixes this.

diff -ur nano/ChangeLog nano-fixed/ChangeLog
--- nano/ChangeLog      2006-04-26 13:24:46.000000000 -0400
+++ nano-fixed/ChangeLog        2006-04-26 19:31:50.000000000 -0400
@@ -60,6 +60,11 @@
          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
diff -ur nano/src/global.c nano-fixed/src/global.c
--- nano/src/global.c   2006-04-26 13:24:46.000000000 -0400
+++ nano-fixed/src/global.c     2006-04-26 19:31:50.000000000 -0400
@@ -394,6 +394,8 @@
        N_("Count the number of words, lines, and characters");
     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_refresh_msg =
        N_("Refresh (redraw) the current screen");
@@ -686,6 +688,16 @@
     sc_init_one(&main_list, NANO_NO_KEY, N_("Copy Text"),
        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, FALSE), NANO_UNINDENTMARKED_KEY,
+       NANO_NO_KEY, NANO_UNINDENTMARKED_ALTKEY, NOVIEW,
+       do_unindent_marked_void);
 #endif
 
     sc_init_one(&main_list, NANO_REFRESH_KEY, refresh_msg
diff -ur nano/src/nano.h nano-fixed/src/nano.h
--- nano/src/nano.h     2006-04-26 14:27:35.000000000 -0400
+++ nano-fixed/src/nano.h       2006-04-26 19:31:50.000000000 -0400
@@ -413,6 +413,8 @@
 #define NANO_CONTROL_8 127
 
 #define NANO_ALT_SPACE ' '
+#define NANO_ALT_DOUBLEQUOTE '"'
+#define NANO_ALT_APOSTROPHE '\''
 #define NANO_ALT_LPARENTHESIS '('
 #define NANO_ALT_RPARENTHESIS ')'
 #define NANO_ALT_PLUS '+'
@@ -431,6 +433,7 @@
 #define NANO_ALT_RBRACKET ']'
 #define NANO_ALT_CARET '^'
 #define NANO_ALT_UNDERSCORE '_'
+#define NANO_ALT_GRAVEACCENT '`'
 #define NANO_ALT_A 'a'
 #define NANO_ALT_B 'b'
 #define NANO_ALT_C 'c'
@@ -459,6 +462,7 @@
 #define NANO_ALT_Z 'z'
 #define NANO_ALT_PIPE '|'
 #define NANO_ALT_RCURLYBRACKET '}'
+#define NANO_ALT_TILDE '~'
 
 /* Some semi-changeable keybindings; don't play with these unless you're
  * sure you know what you're doing.  Assume ERR is defined as -1. */
@@ -540,6 +544,10 @@
 #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_APOSTROPHE
+#define NANO_INDENTMARKED_ALTKEY       NANO_ALT_DOUBLEQUOTE
+#define NANO_UNINDENTMARKED_KEY                NANO_ALT_GRAVEACCENT
+#define NANO_UNINDENTMARKED_ALTKEY     NANO_ALT_TILDE
 #define NANO_SUSPEND_KEY               NANO_CONTROL_Z
 #define NANO_ENTER_KEY                 NANO_CONTROL_M
 #define NANO_TOFILES_KEY               NANO_CONTROL_T
diff -ur nano/src/proto.h nano-fixed/src/proto.h
--- nano/src/proto.h    2006-04-24 22:23:28.000000000 -0400
+++ nano-fixed/src/proto.h      2006-04-26 19:31:50.000000000 -0400
@@ -602,6 +602,11 @@
 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 -ur nano/src/text.c nano-fixed/src/text.c
--- nano/src/text.c     2006-04-26 14:33:50.000000000 -0400
+++ nano-fixed/src/text.c       2006-04-26 19:33:39.000000000 -0400
@@ -193,6 +193,147 @@
 #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;
+    }
+
+    /* 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;
+
+               /* Indicate that we've unindented. */
+               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();
+
+           /* Indicate that we've indented. */
+           if (!indent_changed)
+               indent_changed = TRUE;
+       }
+    }
+
+    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)
 {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]