From 446aa12e021a1cd7a2e198e7158d5655f7dad033 Mon Sep 17 00:00:00 2001 From: Charlie Gordon Date: Fri, 4 Apr 2008 13:16:09 +0000 Subject: [PATCH] added crude support for terminal size in xterm buffer fixed spurious \n insertions in shell unlimited line xterm mode prevent tty input for non-interactive xterm buffers force TERM variable to xterm in process buffers reset PAGER to enable man colored output with default 'less' pager added 'make' command on C-x m added man command --- shell.c | 120 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 27 deletions(-) diff --git a/shell.c b/shell.c index c25561c..86e634f 100644 --- a/shell.c +++ b/shell.c @@ -109,8 +109,13 @@ static int get_pty(char *tty_str) return -1; } +#define TTY_XSIZE 80 +#define TTY_YSIZE 25 +#define TTY_YSIZE_INFINITE 10000 + static int run_process(const char *path, const char **argv, - int *fd_ptr, int *pid_ptr) + int *fd_ptr, int *pid_ptr, + int cols, int rows, int is_shell) { int pty_fd, pid, i, nb_fds; char tty_name[32]; @@ -122,9 +127,10 @@ static int run_process(const char *path, const char **argv, return -1; } fcntl(pty_fd, F_SETFL, O_NONBLOCK); + /* set dummy screen size */ - ws.ws_col = 80; - ws.ws_row = 25; + ws.ws_col = cols; + ws.ws_row = rows; ws.ws_xpixel = ws.ws_col; ws.ws_ypixel = ws.ws_row; ioctl(pty_fd, TIOCSWINSZ, &ws); @@ -140,13 +146,21 @@ static int run_process(const char *path, const char **argv, for (i = 0; i < nb_fds; i++) close(i); /* open pseudo tty for standard i/o */ - open(tty_name, O_RDWR); - dup(0); - dup(0); + if (is_shell == 2) { + /* non interactive colored output: input from /dev/null */ + open("/dev/null", O_RDONLY); + open(tty_name, O_RDWR); + dup(0); + } else { + open(tty_name, O_RDWR); + dup(0); + dup(0); + } setsid(); - //setenv("TERM", "linux", 1); + setenv("TERM", "xterm", 1); + unsetenv("PAGER"); //setenv("QELEVEL", "1", 1); execv(path, (char *const*)argv); @@ -160,8 +174,6 @@ static int run_process(const char *path, const char **argv, /* VT100 emulation */ -#define TTY_YSIZE 25 - static void tty_init(ShellState *s) { char *term; @@ -363,7 +375,7 @@ static void tty_goto_xy(ShellState *s, int x, int y, int relative) if (relative & 2) y += cur_line; } - if (y < 0) + if (y < 0 || y >= TTY_YSIZE_INFINITE - 1) y = 0; else if (y >= TTY_YSIZE) @@ -818,17 +830,22 @@ static void tty_emulate(ShellState *s, int c) if (s->esc_params[0] == 1047 || s->esc_params[0] == 1048 || s->esc_params[0] == 1049) { - s->grab_keys = 1; - qe_grab_keys(shell_key, s); - /* Should also clear screen */ + if (s->is_shell == 1) { + /* only grab keys in interactive tty buffers */ + s->grab_keys = 1; + qe_grab_keys(shell_key, s); + /* Should also clear screen */ + } } break; case ESC2('?','l'): /* reset terminal mode */ if (s->esc_params[0] == 1047 || s->esc_params[0] == 1048 || s->esc_params[0] == 1049) { - qe_ungrab_keys(); - s->grab_keys = 0; + if (s->is_shell == 1) { + qe_ungrab_keys(); + s->grab_keys = 0; + } } break; case ESC2('=','F'): /* select SCO foreground color */ @@ -1047,9 +1064,11 @@ static void shell_pid_cb(void *opaque, int status) EditState *e; char buf[1024]; - if (s->is_shell) { + *buf = 0; + if (s->is_shell == 1) { snprintf(buf, sizeof(buf), "\nProcess shell finished\n"); - } else { + } else + if (s->is_shell == 0) { time_t ti; char *time_str; @@ -1120,6 +1139,7 @@ EditBuffer *new_shell_buffer(EditBuffer *b0, const char *name, { ShellState *s; EditBuffer *b, *b_color; + int rows, cols; b = b0; if (!b) @@ -1161,7 +1181,10 @@ EditBuffer *new_shell_buffer(EditBuffer *b0, const char *name, } /* launch shell */ - if (run_process(path, argv, &s->pty_fd, &s->pid) < 0) { + cols = TTY_XSIZE; + rows = (is_shell == 1) ? TTY_YSIZE : TTY_YSIZE_INFINITE; + + if (run_process(path, argv, &s->pty_fd, &s->pid, cols, rows, is_shell) < 0) { if (!b0) eb_free(b); return NULL; @@ -1172,11 +1195,26 @@ EditBuffer *new_shell_buffer(EditBuffer *b0, const char *name, return b; } -static void do_shell(EditState *s, int force) +static EditBuffer *try_show_buffer(EditState *s, const char *bufname) { QEmacsState *qs = s->qe_state; EditState *e; EditBuffer *b; + + b = eb_find(bufname); + if (b) { + e = edit_find(b); + if (e) + qs->active_window = e; + else + switch_to_buffer(s, b); + } + return b; +} + +static void do_shell(EditState *s, int force) +{ + EditBuffer *b; const char *argv[3]; const char *shell_path; @@ -1185,15 +1223,8 @@ static void do_shell(EditState *s, int force) */ /* find shell buffer if any */ if (!force || force == NO_ARG) { - b = eb_find("*shell*"); - if (b) { - e = edit_find(b); - if (e) - qs->active_window = e; - else - switch_to_buffer(s, b); + if (try_show_buffer(s, "*shell*")) return; - } } /* find shell name */ @@ -1215,6 +1246,33 @@ static void do_shell(EditState *s, int force) shell_launched = 1; } +static void do_man(EditState *s, const char *arg) +{ + const char *man_path; + const char *argv[3]; + char bufname[32]; + EditBuffer *b; + + /* Assume standard man command */ + man_path = "/usr/bin/man"; + + snprintf(bufname, sizeof(bufname), "*man %s*", arg); + if (try_show_buffer(s, bufname)) + return; + + /* create new buffer */ + argv[0] = man_path; + argv[1] = arg; + argv[2] = NULL; + b = new_shell_buffer(NULL, bufname, man_path, argv, 2); + if (!b) + return; + + switch_to_buffer(s, b); + edit_set_mode(s, &shell_mode, NULL); + s->interactive = 0; +} + static void shell_move_left_right(EditState *e, int dir) { if (e->interactive) { @@ -1387,6 +1445,7 @@ static void do_compile_error(EditState *s, int dir) offset = 0; goto find_error; } + /* CG: should use higher level parsing */ for (;;) { if (dir > 0) { @@ -1474,6 +1533,7 @@ static CmdDef shell_commands[] = { "shell-kill-line", shell_write_char, 11) CMD1( KEY_CTRL('y'), KEY_NONE, "shell-yank", shell_write_char, 25) + /* Should have KEY_CTRL('c') -> shell_kill */ CMD_DEF_END, }; @@ -1484,6 +1544,12 @@ static CmdDef compile_commands[] = { CMD_( KEY_CTRLX(KEY_CTRL('e')), KEY_NONE, "compile", do_compile, ESs, "s{Compile command: }|compile|") + CMD_( KEY_CTRLX('m'), KEY_NONE, + "make", do_compile, ESs, + "S{make}") + CMD_( KEY_NONE, KEY_NONE, + "man", do_man, ESs, + "s{Show man page for: }|man|") CMD1( KEY_CTRLX(KEY_CTRL('p')), KEY_NONE, "previous-error", do_compile_error, -1) /* u */ CMD1( KEY_CTRLX(KEY_CTRL('n')), KEY_CTRLX('`'),