Improve indentation commands
* add `find_indent` and `make_indent` ancillary functions * add `untabulate` on `S-TAB` to remove one indentation level * rename `do_tab` as `do_tabulate` for consistency * `tabulate` indents the region one level if visible * add `indent-rigidly` commands: indent block interactively
This commit is contained in:
parent
9fde8fd9b9
commit
1d3cabeaa2
6 changed files with 169 additions and 14 deletions
8
TODO.md
8
TODO.md
|
|
@ -5,8 +5,6 @@
|
|||
## Current work
|
||||
|
||||
* pass `indent` to `ColorizeFunc`.
|
||||
* `S-TAB` -> untabify
|
||||
* `TAB` and `S-TAB` with selected block -> indent, unindent block
|
||||
* `TAB` -> complete function name etc.
|
||||
* add parametric syntax definitions (nanorc files).
|
||||
* should implement a maximum macro length and abort macro learning mode if reached
|
||||
|
|
@ -128,7 +126,6 @@ both in `strtokey`
|
|||
* fix `eb_prev_char` to handle non self-synchronizing charsets
|
||||
* auto/mixed eol mode
|
||||
* `set-eol-type` should take a string: auto/binary/dos/unix/mac/0/1/2...
|
||||
* display `^L` as horizontal line and consider as linebreak character
|
||||
* handle zero width codepoints:
|
||||
cp="200B" na="ZERO WIDTH SPACE" alias="ZWSP"
|
||||
cp="200C" na="ZERO WIDTH NON-JOINER" alias="ZWNJ"
|
||||
|
|
@ -156,6 +153,7 @@ both in `strtokey`
|
|||
* fix current position when changing buffer attached to window
|
||||
* fix default wrap setting mess
|
||||
* display: add screen dump command and format
|
||||
* display `^L` as horizontal line and consider as linebreak character
|
||||
* colorize extra `^M` and `^Z` as preproc at end of line prior to calling the syntax highlighter (same as BOM)
|
||||
* colorizer bug on **/comp/projects/fractal/fractint/ORGFORM/NOEL-2.FRM** (triple `^M`)
|
||||
* display bug on **~/comp/projects/fractal/fractint/ORGFORM/BAILOUT.FRM** (double `^M`)
|
||||
|
|
@ -211,6 +209,9 @@ insert_window_left() deletes some left-most windows
|
|||
* fix column computation based on display properties:
|
||||
(variable pitch, tabs, ^x and \uxxxx stuff -- emacs behaviour) ?
|
||||
|
||||
* tag left-view with electric navigation
|
||||
* expand / collapse region
|
||||
|
||||
## X11 display / graphics
|
||||
|
||||
* handle X11 window manager close window event and exit cleanly
|
||||
|
|
@ -278,7 +279,6 @@ insert_window_left() deletes some left-most windows
|
|||
* `what-cursor-position` with universal prefix: show popup with long description
|
||||
* `compare-windows` should resync from the end of line.
|
||||
* `elastic-tabs`
|
||||
* `indent-rigidly`
|
||||
* `show-matching-delimiters`
|
||||
* blink-and-insert on `) } ] >`
|
||||
* `set-gosmacs-bindings` -> `set_emulation("gosmacs")`
|
||||
|
|
|
|||
83
extras.c
83
extras.c
|
|
@ -724,12 +724,75 @@ static void do_indent_region(EditState *s, int start, int end)
|
|||
(s->mode->indent_func)(s, eb_goto_pos(s->b, line1, 0));
|
||||
} else {
|
||||
s->offset = eb_goto_pos(s->b, line1, 0);
|
||||
do_tab(s, 1);
|
||||
do_tabulate(s, 1);
|
||||
}
|
||||
}
|
||||
s->offset = eb_goto_eol(s->b, s->offset);
|
||||
}
|
||||
|
||||
void do_indent_rigidly(EditState *s, int start, int end, int argval)
|
||||
{
|
||||
int col_num, line1, line2;
|
||||
|
||||
if (argval == NO_ARG) {
|
||||
// enter interactive mode
|
||||
QEmacsState *qs = s->qe_state;
|
||||
if (!qs->first_transient_key) {
|
||||
s->region_style = QE_STYLE_REGION_HILITE;
|
||||
put_status(s, "indent the region interactively with TAB, left, right, S-left, S-right");
|
||||
qe_register_transient_binding(qs, "indent-rigidly-left", "left");
|
||||
qe_register_transient_binding(qs, "indent-rigidly-right", "right");
|
||||
qe_register_transient_binding(qs, "indent-rigidly-left-to-tab-stop", "S-left, S-TAB");
|
||||
qe_register_transient_binding(qs, "indent-rigidly-right-to-tab-stop", "S-right, TAB");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Swap point and mark so mark <= point */
|
||||
if (end < start) {
|
||||
int tmp = start;
|
||||
end = start;
|
||||
start = tmp;
|
||||
}
|
||||
/* We do it with lines to avoid offset variations during indenting */
|
||||
eb_get_pos(s->b, &line1, &col_num, start);
|
||||
eb_get_pos(s->b, &line2, &col_num, end);
|
||||
|
||||
if (col_num == 0)
|
||||
line2--;
|
||||
|
||||
/* Iterate over all lines inside block */
|
||||
//s->b->mark = eb_goto_bol(s->b, start);
|
||||
for (; line1 <= line2; line1++) {
|
||||
int offset = eb_goto_pos(s->b, line1, 0);
|
||||
int off1, off2;
|
||||
int indent = find_indent(s, offset, 0, &off1);
|
||||
int new_indent = max_int(0, indent + argval);
|
||||
if (eb_nextc(s->b, off1, &off2) == '\n')
|
||||
new_indent = 0;
|
||||
make_indent(s, offset, off1, 0, new_indent);
|
||||
}
|
||||
//s->offset = eb_goto_eol(s->b, s->offset);
|
||||
}
|
||||
|
||||
static void do_indent_rigidly_to_tab_stop(EditState *s, int start, int end, int dir) {
|
||||
int tw = s->b->tab_width > 0 ? s->b->tab_width : DEFAULT_TAB_WIDTH;
|
||||
int indent = s->indent_size > 0 ? s->indent_size : tw;
|
||||
|
||||
do_indent_rigidly(s, start, end, indent * dir);
|
||||
}
|
||||
|
||||
static void do_untabulate(EditState *s) {
|
||||
if (s->region_style) {
|
||||
do_indent_rigidly_to_tab_stop(s, s->b->mark, s->offset, -1);
|
||||
} else {
|
||||
// FIXME: should decrease indentation at s->offset
|
||||
int start = eb_goto_bol(s->b, s->offset);
|
||||
int end = eb_goto_eol(s->b, s->offset);
|
||||
do_indent_rigidly_to_tab_stop(s, start, end, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void do_show_date_and_time(EditState *s, int argval)
|
||||
{
|
||||
time_t t = argval;
|
||||
|
|
@ -2612,6 +2675,24 @@ static const CmdDef extra_commands[] = {
|
|||
CMD2( "indent-buffer", "",
|
||||
"Indent each nonblank line in the buffer",
|
||||
do_indent_region, ESii, "*" "ze")
|
||||
CMD2( "indent-rigidly", "C-x TAB",
|
||||
"Indent the region interactively",
|
||||
do_indent_rigidly, ESiii, "*" "md" "P")
|
||||
CMD3( "indent-rigidly-left", "",
|
||||
"Decrease the region indentation",
|
||||
do_indent_rigidly, ESiii, "*" "md" "v", -1)
|
||||
CMD3( "indent-rigidly-right", "",
|
||||
"Increase the region indentation",
|
||||
do_indent_rigidly, ESiii, "*" "md" "v", +1)
|
||||
CMD3( "indent-rigidly-left-to-tab-stop", "",
|
||||
"Decrease the region indentation by one tab",
|
||||
do_indent_rigidly_to_tab_stop, ESiii, "*" "md" "v", -1)
|
||||
CMD3( "indent-rigidly-right-to-tab-stop", "",
|
||||
"Increase the region indentation by one tab",
|
||||
do_indent_rigidly_to_tab_stop, ESiii, "*" "md" "v", +1)
|
||||
CMD2( "untabulate", "S-TAB",
|
||||
"Decrease indentation",
|
||||
do_untabulate, ES, "*")
|
||||
|
||||
CMD2( "show-date-and-time", "C-x t",
|
||||
"Show current date and time",
|
||||
|
|
|
|||
|
|
@ -1121,11 +1121,12 @@ done:
|
|||
|
||||
static void do_c_indent(EditState *s)
|
||||
{
|
||||
if (eb_is_in_indentation(s->b, s->offset)
|
||||
if (!s->region_style
|
||||
&& eb_is_in_indentation(s->b, s->offset)
|
||||
&& s->qe_state->last_cmd_func != (CmdFunc)do_c_indent) {
|
||||
c_indent_line(s, s->offset);
|
||||
} else {
|
||||
do_tab(s, 1);
|
||||
do_tabulate(s, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3157,6 +3157,7 @@ static void do_shell_tabulate(EditState *e)
|
|||
if (e->interactive) {
|
||||
shell_write_char(e, 9);
|
||||
} else {
|
||||
//do_tabulate(s, 1);
|
||||
text_write_char(e, 9);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
81
qe.c
81
qe.c
|
|
@ -1042,7 +1042,7 @@ void do_backspace(EditState *s, int argval)
|
|||
if (argval == NO_ARG) {
|
||||
// XXX: this does not work for c-mode
|
||||
// XXX: should implement backward-delete-char-untabify instead
|
||||
if (s->qe_state->last_cmd_func == (CmdFunc)do_tab
|
||||
if (s->qe_state->last_cmd_func == (CmdFunc)do_tabulate
|
||||
&& !s->indent_tabs_mode && !s->multi_cursor_active) {
|
||||
/* Delete tab or indentation? */
|
||||
do_undo(s);
|
||||
|
|
@ -1926,17 +1926,86 @@ void do_overwrite_mode(EditState *s, int argval) {
|
|||
put_status(s, "Overwrite mode is %s", s->overwrite ? "on" : "off");
|
||||
}
|
||||
|
||||
void do_tab(EditState *s, int argval)
|
||||
/* get the indentation width at a given offset */
|
||||
int find_indent(EditState *s, int offset, int pos, int *offsetp) {
|
||||
int tw = s->b->tab_width > 0 ? s->b->tab_width : 8;
|
||||
int offset1;
|
||||
for (;; offset = offset1) {
|
||||
char32_t c = eb_nextc(s->b, offset, &offset1);
|
||||
if (c == '\t')
|
||||
pos += tw - (pos % tw);
|
||||
else if (c == ' ')
|
||||
pos++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
*offsetp = offset;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void get_indent_chars(EditState *s, int pos, int target,
|
||||
int *ptabs, int *pspaces)
|
||||
{
|
||||
int tabs = 0, spaces = 0;
|
||||
if (target > pos) {
|
||||
if (s->indent_tabs_mode) {
|
||||
int tw = s->b->tab_width > 0 ? s->b->tab_width : 8;
|
||||
while (target >= pos + tw - pos % tw) {
|
||||
tabs++;
|
||||
pos += tw - pos % tw;
|
||||
}
|
||||
}
|
||||
spaces = target - pos;
|
||||
}
|
||||
*ptabs = tabs;
|
||||
*pspaces = spaces;
|
||||
}
|
||||
|
||||
/* replace characters in region with specified TABs and spaces */
|
||||
static int replace_indent(EditState *s, int offset, int end, int tabs, int spaces) {
|
||||
int offset1;
|
||||
while (offset < end) {
|
||||
char32_t c = eb_nextc(s->b, offset, &offset1);
|
||||
if (tabs && c == '\t') {
|
||||
tabs--;
|
||||
} else
|
||||
if (spaces && c == ' ') {
|
||||
spaces--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
offset = offset1;
|
||||
}
|
||||
eb_delete_range(s->b, offset, end);
|
||||
offset += eb_insert_char32_n(s->b, offset, '\t', tabs);
|
||||
offset += eb_insert_char32_n(s->b, offset, ' ', spaces);
|
||||
return offset;
|
||||
}
|
||||
|
||||
int make_indent(EditState *s, int offset, int end, int pos, int target) {
|
||||
int tabs, spaces;
|
||||
get_indent_chars(s, pos, target, &tabs, &spaces);
|
||||
return replace_indent(s, offset, end, tabs, spaces);
|
||||
}
|
||||
|
||||
void do_tabulate(EditState *s, int argval)
|
||||
{
|
||||
int tw = s->b->tab_width > 0 ? s->b->tab_width : DEFAULT_TAB_WIDTH;
|
||||
int indent = s->indent_size > 0 ? s->indent_size : tw;
|
||||
|
||||
/* CG: should do smart complete, smart indent, insert tab */
|
||||
#ifndef CONFIG_TINY
|
||||
if (s->region_style) {
|
||||
do_indent_rigidly(s, s->b->mark, s->offset, indent);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (s->indent_tabs_mode) {
|
||||
do_char(s, '\t', argval);
|
||||
} else {
|
||||
int offset = s->offset;
|
||||
int offset0 = eb_goto_bol(s->b, offset);
|
||||
int col = 0;
|
||||
int tw = s->b->tab_width > 0 ? s->b->tab_width : DEFAULT_TAB_WIDTH;
|
||||
int indent = s->indent_size > 0 ? s->indent_size : tw;
|
||||
|
||||
while (offset0 < offset) {
|
||||
char32_t c = eb_nextc(s->b, offset0, &offset0);
|
||||
|
|
@ -10330,10 +10399,10 @@ static const CmdDef basic_commands[] = {
|
|||
do_char, ESii, "*"
|
||||
"n{Insert char: }[charname]|charvalue|"
|
||||
"p")
|
||||
/* do_tab will not change read only buffer */
|
||||
/* do_tabulate will not change read only buffer */
|
||||
CMD2( "tabulate", "TAB",
|
||||
"Insert a TAB or spaces according to indent-tabs-mode",
|
||||
do_tab, ESi, "p")
|
||||
do_tabulate, ESi, "p")
|
||||
//CMD2( "space", "SPC", "Insert a space", do_space, ESi, "*" "P")
|
||||
CMD2( "quoted-insert", "C-q",
|
||||
"Read next input character and insert it",
|
||||
|
|
|
|||
5
qe.h
5
qe.h
|
|
@ -1502,7 +1502,7 @@ void do_newline(EditState *s);
|
|||
void do_open_line(EditState *s);
|
||||
void do_backspace(EditState *s, int argval);
|
||||
void do_delete_char(EditState *s, int argval);
|
||||
void do_tab(EditState *s, int argval);
|
||||
void do_tabulate(EditState *s, int argval);
|
||||
EditBuffer *new_yank_buffer(QEmacsState *qs, EditBuffer *base);
|
||||
void do_append_next_kill(EditState *s);
|
||||
void do_kill(EditState *s, int p1, int p2, int dir, int keep);
|
||||
|
|
@ -1585,6 +1585,8 @@ void do_toggle_truncate_lines(EditState *s);
|
|||
void do_word_wrap(EditState *s);
|
||||
void do_count_lines(EditState *s);
|
||||
void do_what_cursor_position(EditState *s);
|
||||
int find_indent(EditState *s, int offset, int pos, int *offsetp);
|
||||
int make_indent(EditState *s, int offset, int end, int pos, int target);
|
||||
void do_set_tab_width(EditState *s, int tab_width);
|
||||
void do_set_indent_width(EditState *s, int indent_width);
|
||||
void do_set_indent_tabs_mode(EditState *s, int val);
|
||||
|
|
@ -1762,6 +1764,7 @@ void do_compare_windows(EditState *s, int argval);
|
|||
void do_compare_files(EditState *s, const char *filename, int bflags);
|
||||
void do_delete_horizontal_space(EditState *s);
|
||||
void do_show_date_and_time(EditState *s, int argval);
|
||||
void do_indent_rigidly(EditState *s, int start, int end, int argval);
|
||||
|
||||
enum {
|
||||
CMD_TRANSPOSE_CHARS = 1,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue