shell: improve shell mode
* add `BF_ERROR` to identify error source buffers and use it with `next-error`.
* show `HELP` and `ERROR` buffer flags in `describe-buffer`.
* add a dedicated compilation mode with the following bindings:
* `next-error` on `n`, `M-n`
* `previous-error` on `p`, `M-p`
* `scroll-up` on `SPC`
* `scroll-down` on `DEL`
* `search-forward` on `/`
and the following new commands:
* `goto-error` on `RET`, `LF`
* `kill-compilation` on `C-c C-k`
* use `compilation` mode instead of `pager` mode for
`do-compile`, and switch interactive shell buffers to
`compilation` mode when the shell exits (if `shell_buffer_read_only` is set)
* refine popup/sidepane closing in `next-error`:
* remove unnecessary popup check, as the command cannot
be invoked if a popup window is present.
* use `do_delete_window` to close side pane to avoid
screen gap bug with `edit_close`.
This commit is contained in:
parent
807339b3c8
commit
f71fc6f25b
3 changed files with 123 additions and 33 deletions
4
extras.c
4
extras.c
|
|
@ -2055,6 +2055,10 @@ static void do_describe_buffer(EditState *s, int argval)
|
|||
buf_puts(desc, " DIRED");
|
||||
if (b->flags & BF_SHELL)
|
||||
buf_puts(desc, " SHELL");
|
||||
if (b->flags & BF_HELP)
|
||||
buf_puts(desc, " HELP");
|
||||
if (b->flags & BF_ERROR)
|
||||
buf_puts(desc, " ERROR");
|
||||
if (b->flags & BF_UTF8)
|
||||
buf_puts(desc, " UTF8");
|
||||
if (b->flags & BF_RAW)
|
||||
|
|
|
|||
151
modes/shell.c
151
modes/shell.c
|
|
@ -42,7 +42,7 @@
|
|||
/* XXX: better tab handling */
|
||||
/* XXX: send real cursor position (CSI n) */
|
||||
|
||||
static ModeDef shell_mode, pager_mode;
|
||||
static ModeDef shell_mode, pager_mode, compilation_mode;
|
||||
|
||||
#define MAX_CSI_PARAMS 16
|
||||
#define MAX_OSC_SIZE 512 + MAX_FILENAME_SIZE
|
||||
|
|
@ -2750,7 +2750,7 @@ static void shell_close(ShellState *s)
|
|||
qe_set_next_mode(e, 0, 0);
|
||||
if (qs->shell_buffer_read_only) {
|
||||
if (s->shell_flags & SF_INTERACTIVE)
|
||||
edit_set_mode(e, &pager_mode);
|
||||
edit_set_mode(e, &compilation_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2994,6 +2994,7 @@ static void do_shell(EditState *e, int argval)
|
|||
if (!b)
|
||||
return;
|
||||
|
||||
b->flags |= BF_ERROR;
|
||||
b->default_mode = &shell_mode;
|
||||
switch_to_buffer(e, b);
|
||||
/* force interactive mode if restarting */
|
||||
|
|
@ -3088,7 +3089,6 @@ static void do_man(EditState *s, const char *arg)
|
|||
return;
|
||||
|
||||
b->data_type_name = "man";
|
||||
b->flags |= BF_READONLY;
|
||||
s = shell_target_window(s, b);
|
||||
edit_set_mode(s, &pager_mode);
|
||||
}
|
||||
|
|
@ -3154,7 +3154,6 @@ void qe_diff_buffer_with_file(EditState *s, EditBuffer *b)
|
|||
snprintf(cmd, sizeof(cmd), "Diff buffer %s", fname);
|
||||
|
||||
b1->data_type_name = "diff";
|
||||
b1->flags |= BF_READONLY;
|
||||
e = show_popup(s, b1, cmd);
|
||||
// XXX: Should use patch mode
|
||||
edit_set_mode(e, &pager_mode);
|
||||
|
|
@ -3862,7 +3861,6 @@ static void do_shell_command(EditState *e, const char *cmd)
|
|||
if (!b)
|
||||
return;
|
||||
|
||||
b->flags |= BF_READONLY;
|
||||
e = shell_target_window(e, b);
|
||||
edit_set_mode(e, &pager_mode);
|
||||
}
|
||||
|
|
@ -3919,10 +3917,9 @@ static void do_compile(EditState *s, const char *cmd)
|
|||
if (!b)
|
||||
return;
|
||||
|
||||
b->flags |= BF_READONLY;
|
||||
b->data_type_name = "compile";
|
||||
s = shell_target_window(s, b);
|
||||
edit_set_mode(s, &pager_mode);
|
||||
edit_set_mode(s, &compilation_mode);
|
||||
set_error_offset(b, 0);
|
||||
}
|
||||
|
||||
|
|
@ -4028,18 +4025,23 @@ static void do_next_error(EditState *s, int arg, int dir)
|
|||
set_error_offset(s->b, s->offset);
|
||||
}
|
||||
|
||||
/* CG: should have a buffer flag for error source.
|
||||
* first check if current buffer is an error source.
|
||||
* if not, then scan for appropriate error source
|
||||
* in buffer least recently used order
|
||||
*/
|
||||
|
||||
if ((b = qe_find_buffer_name(qs, error_state.buffer)) == NULL) {
|
||||
if ((b = qe_find_buffer_name(qs, "*compilation*")) == NULL
|
||||
&& (b = qe_find_buffer_name(qs, "*shell*")) == NULL
|
||||
&& (b = qe_find_buffer_name(qs, "*errors*")) == NULL) {
|
||||
put_error(s, "No compilation buffer");
|
||||
return;
|
||||
if (s->b->flags & BF_ERROR) {
|
||||
b = s->b;
|
||||
} else {
|
||||
EditBuffer *b1;
|
||||
int atime = -1;
|
||||
|
||||
for (b1 = qs->first_buffer; b1 != NULL; b1 = b1->next) {
|
||||
if ((b1->flags & BF_ERROR) && b1->atime > atime) {
|
||||
b = b1;
|
||||
atime = b1->atime;
|
||||
}
|
||||
}
|
||||
if (b == NULL && (b = qe_find_buffer_name(qs, "*errors*")) == NULL) {
|
||||
put_error(s, "No compilation buffer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_error_offset(b, -1);
|
||||
}
|
||||
|
|
@ -4081,11 +4083,8 @@ static void do_next_error(EditState *s, int arg, int dir)
|
|||
return;
|
||||
}
|
||||
|
||||
for (e = qs->first_window; e != NULL; e = e_next) {
|
||||
e_next = e->next_window;
|
||||
if (e->flags & (WF_POPUP | WF_POPLEFT))
|
||||
edit_close(&e);
|
||||
}
|
||||
if ((e = get_next_window(s, WF_POPLEFT, WF_POPLEFT)))
|
||||
do_delete_window(e, 0);
|
||||
|
||||
/* find a window showing the error source
|
||||
buffer, split a new one if none is found */
|
||||
|
|
@ -4571,8 +4570,24 @@ static int pager_mode_init(EditState *e, EditBuffer *b, int flags)
|
|||
{
|
||||
if (e) {
|
||||
e->b->tab_width = 8;
|
||||
/* XXX: should come from mode.default_wrap */
|
||||
e->wrap = WRAP_TRUNCATE;
|
||||
e->wrap = pager_mode.default_wrap;
|
||||
}
|
||||
if (b) {
|
||||
b->modified = 0;
|
||||
b->flags |= BF_READONLY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compilation_mode_init(EditState *e, EditBuffer *b, int flags)
|
||||
{
|
||||
if (e) {
|
||||
e->b->tab_width = 8;
|
||||
e->wrap = compilation_mode.default_wrap;
|
||||
}
|
||||
if (b) {
|
||||
b->modified = 0;
|
||||
b->flags |= BF_ERROR | BF_READONLY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4583,15 +4598,16 @@ static void do_pager_abort(EditState *e)
|
|||
|
||||
if (e->mode != &pager_mode) {
|
||||
put_error(e, "Not a %s buffer", pager_mode.name);
|
||||
return;
|
||||
}
|
||||
|
||||
b1 = qe_check_buffer(e->qs, &e->last_buffer);
|
||||
if (b1 != NULL) {
|
||||
switch_to_buffer(e, NULL);
|
||||
e->last_buffer = NULL;
|
||||
switch_to_buffer(e, b1);
|
||||
} else {
|
||||
b1 = qe_check_buffer(e->qs, &e->last_buffer);
|
||||
if (b1 != NULL) {
|
||||
switch_to_buffer(e, NULL);
|
||||
e->last_buffer = NULL;
|
||||
switch_to_buffer(e, b1);
|
||||
} else {
|
||||
do_delete_window(e, 0);
|
||||
}
|
||||
do_delete_window(e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4609,6 +4625,60 @@ static const char * const pager_bindings[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void do_kill_compilation(EditState *e)
|
||||
{
|
||||
ShellState *s;
|
||||
EditBuffer *b = e->b;
|
||||
QEmacsState *qs = e->qs;
|
||||
|
||||
if (e->mode != &compilation_mode) {
|
||||
if (!(b = qe_find_buffer_name(qs, "*compilation*"))) {
|
||||
put_error(e, "No compilation buffer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((s = qe_get_buffer_mode_data(b, &shell_mode, NULL)) && s->pid > 0)
|
||||
kill(s->pid, SIGKILL);
|
||||
else
|
||||
put_error(e, "Compilation process is not running");
|
||||
}
|
||||
|
||||
static void do_goto_error(EditState *s)
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (!(s->b->flags & BF_ERROR)) {
|
||||
put_error(s, "Not an error source buffer");
|
||||
return;
|
||||
}
|
||||
offset = eb_goto_bol(s->b, s->offset);
|
||||
if (!match_error(s->b, offset, NULL)) {
|
||||
put_error(s, "No error here");
|
||||
} else {
|
||||
set_error_offset(s->b, offset);
|
||||
do_next_error(s, NO_ARG, +1);
|
||||
}
|
||||
}
|
||||
|
||||
static const CmdDef compilation_commands[] = {
|
||||
CMD0( "goto-error", "RET, LF", // XXX: mouse click ?
|
||||
"Move to the error matching the current error message at point",
|
||||
do_goto_error)
|
||||
CMD0( "kill-compilation", "C-c C-k",
|
||||
"kill compilation process",
|
||||
do_kill_compilation)
|
||||
};
|
||||
|
||||
static const char * const compilation_bindings[] = {
|
||||
"n, M-n", "next-error",
|
||||
"p, M-p", "previous-error",
|
||||
"DEL", "scroll-down",
|
||||
"SPC", "scroll-up",
|
||||
"/", "search-forward",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int shell_init(QEmacsState *qs)
|
||||
{
|
||||
/* populate and register shell mode and commands */
|
||||
|
|
@ -4647,10 +4717,25 @@ static int shell_init(QEmacsState *qs)
|
|||
pager_mode.mode_init = pager_mode_init;
|
||||
pager_mode.bindings = pager_bindings;
|
||||
pager_mode.colorize_func = shell_colorize_line;
|
||||
pager_mode.default_wrap = WRAP_LINE;
|
||||
|
||||
qe_register_mode(qs, &pager_mode, MODEF_NOCMD | MODEF_VIEW);
|
||||
qe_register_commands(qs, &pager_mode, pager_commands, countof(pager_commands));
|
||||
|
||||
/* populate and register compilation mode and commands */
|
||||
// XXX: remove this mess: should just inherit with fallback
|
||||
memcpy(&compilation_mode, &text_mode, offsetof(ModeDef, first_key));
|
||||
compilation_mode.name = "compilation";
|
||||
compilation_mode.flags |= MODEF_NO_TRAILING_BLANKS;
|
||||
compilation_mode.mode_probe = NULL;
|
||||
compilation_mode.mode_init = compilation_mode_init;
|
||||
compilation_mode.bindings = compilation_bindings;
|
||||
compilation_mode.colorize_func = shell_colorize_line;
|
||||
compilation_mode.default_wrap = WRAP_LINE;
|
||||
|
||||
qe_register_mode(qs, &compilation_mode, MODEF_NOCMD | MODEF_VIEW);
|
||||
qe_register_commands(qs, &compilation_mode, compilation_commands, countof(compilation_commands));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
1
qe.h
1
qe.h
|
|
@ -385,6 +385,7 @@ typedef struct EditBufferDataType {
|
|||
#define BF_IS_LOG 0x10000 /* buffer is a log buffer */
|
||||
#define BF_SHELL 0x20000 /* buffer is a shell buffer */
|
||||
#define BF_HELP 0x40000 /* buffer is a help buffer */
|
||||
#define BF_ERROR 0x80000 /* buffer is an error source buffer */
|
||||
/* buffer creation flags */
|
||||
#define BC_REUSE 0x100000 /* reuse existing buffer with same name */
|
||||
#define BC_CLEAR 0x200000 /* reuse existing buffer and clear it */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue