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 17:34:41 -0400
User-agent: Thunderbird 1.5 (X11/20051201)

Chris Allegretta wrote:
> Hello,
>
>     I believe this may be the first thing I thought of that
> someone hadn't already implemented in the 1.3 series, so I figured I
> would throw this out there:
>
> This patch allowed you to insert tabsize # spaces at the beginning of
> each line of marked text by hitting tab, and it will also allow you to
> delete the same number of spaces as long as they are whitespace chars
> by hitting shift+tab.

Two minor problems with the keys.  First, since Tab is a typing key as
opposed to just an ordinary control key, it seems odd to use it for
something else.  Second, shift-tab (or back-tab as some documentation
calls it) isn't always guaranteed to work.  Slang doesn't define a key
for it at all, VT100, VT220, AND VT320 don't define an escape sequence
for it at all, and the Linux console defines it to be the same value as
Tab(?!).

> Just throwing it out there for discussion before I put more work into
> it, right now it looks ugly and is probably not even close to I18N
> compatible....

I'm not sure what you mean here.  If you mean handling
NLS-specific/UTF-8-specific spacing characters, indent_length() will do
that without the need for a loop using isspace().

> Should we insert spaces if -E is used and otherwise just add a tab to
> each line?

Sounds good to me.

> Other comments?

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?

Thanks in advance.

diff -ur nano/ChangeLog nano-fixed/ChangeLog
--- nano/ChangeLog      2006-04-26 13:24:46.000000000 -0400
+++ nano-fixed/ChangeLog        2006-04-26 16:06:52.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 16:06:52.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 16:06:52.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 16:06:52.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 16:08:06.000000000 -0400
@@ -193,6 +193,145 @@
 #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);
+
+               /* 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);
+
+           /* 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]