[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemacs-commit] qemacs shell.c
From: |
Charlie Gordon |
Subject: |
[Qemacs-commit] qemacs shell.c |
Date: |
Fri, 29 Nov 2013 00:32:52 +0000 |
CVSROOT: /sources/qemacs
Module name: qemacs
Changes by: Charlie Gordon <chqrlie> 13/11/29 00:32:52
Modified files:
. : shell.c
Log message:
improved man command:
- fixed bug on OS/X to force unlimited lines in shell output buffers
- added pager mode
- made output buffer read only, allow shell output to read only buffer
improved shell mode:
- set buffer encoding from LANG environment variable: utf8 or vt100
- special cased utf8 support for shell output
- handle charset in shell input
- enter / exit shell interactive mode with C-a and C-e (home and end)
- reset error offset upon enter key
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/shell.c?cvsroot=qemacs&r1=1.63&r2=1.64
Patches:
Index: shell.c
===================================================================
RCS file: /sources/qemacs/qemacs/shell.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -b -r1.63 -r1.64
--- shell.c 2 May 2008 16:04:10 -0000 1.63
+++ shell.c 29 Nov 2013 00:32:52 -0000 1.64
@@ -2,7 +2,7 @@
* Shell mode for QEmacs.
*
* Copyright (c) 2001, 2002 Fabrice Bellard.
- * Copyright (c) 2002-2008 Charlie Gordon.
+ * Copyright (c) 2002-2013 Charlie Gordon.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -39,12 +39,13 @@
/* XXX: bold & italic ? */
/* XXX: send real cursor position (CSI n) */
-static ModeDef shell_mode;
+static ModeDef shell_mode, pager_mode;
#define MAX_ESC_PARAMS 3
enum TTYState {
TTY_STATE_NORM,
+ TTY_STATE_UTF8,
TTY_STATE_ESC,
TTY_STATE_ESC2,
TTY_STATE_CSI,
@@ -65,6 +66,8 @@
int shifted;
int cset, charset[2];
int grab_keys;
+ unsigned char utf8_buf[8];
+ int utf8_len, utf8_pos;
EditBuffer *b;
EditBuffer *b_color; /* color buffer, one byte per char */
int is_shell; /* only used to display final message */
@@ -83,6 +86,11 @@
/* move to mode */
static int shell_launched = 0;
+/* CG: these variables should move to mode data */
+static int error_offset = -1;
+static int last_line_num = -1;
+static char last_filename[MAX_FILENAME_SIZE];
+
#define PTYCHAR1 "pqrstuvwxyzabcde"
#define PTYCHAR2 "0123456789abcdef"
@@ -174,6 +182,7 @@
/* open pseudo tty for standard i/o */
if (is_shell == 2) {
/* non interactive colored output: input from /dev/null */
+ setenv("LINES", "10000", 1);
open("/dev/null", O_RDONLY);
open(tty_name, O_RDWR);
dup(0);
@@ -787,7 +796,27 @@
c += 32;
}
/* write char (should factorize with do_char() code */
- len = unicode_to_charset(buf1, c, s->b->charset);
+ /* CG: Charset support is inherently broken here because
+ * bytes are inserted one at a time and charset conversion
+ * should not be performed between shell output and buffer
+ * contents. UTF8 is special cased, other charsets need work.
+ */
+ /* CG: further improvement direction includes automatic
+ * conversion from ISO-8859-1 to UTF-8 for invalid UTF-8
+ * byte sequences.
+ */
+ if (s->b->charset == &charset_utf8) {
+ s->utf8_len = utf8_length[c];
+ if (s->utf8_len > 1) {
+ s->utf8_buf[0] = c;
+ s->utf8_pos = 1;
+ s->state = TTY_STATE_UTF8;
+ break;
+ }
+ }
+ //len = unicode_to_charset(buf1, c, s->b->charset);
+ buf1[0] = c;
+ len = 1;
c1 = eb_nextc(s->b, s->cur_offset, &offset);
/* Should simplify with tty_put_char */
if (c1 == '\n') {
@@ -807,6 +836,29 @@
break;
}
break;
+ case TTY_STATE_UTF8:
+ s->utf8_buf[s->utf8_pos++] = c;
+ if (s->utf8_pos >= s->utf8_len) {
+ int c1, cur_len, len;
+
+ len = s->utf8_len;
+ c1 = eb_nextc(s->b, s->cur_offset, &offset);
+ if (c1 == '\n') {
+ /* insert */
+ eb_insert(s->b, s->cur_offset, s->utf8_buf, len);
+ } else {
+ cur_len = offset - s->cur_offset;
+ if (cur_len == len) {
+ eb_write(s->b, s->cur_offset, s->utf8_buf, len);
+ } else {
+ eb_delete(s->b, s->cur_offset, cur_len);
+ eb_insert(s->b, s->cur_offset, s->utf8_buf, len);
+ }
+ }
+ s->cur_offset += len;
+ s->state = TTY_STATE_NORM;
+ }
+ break;
case TTY_STATE_ESC:
if (c == '[') {
for (i = 0; i < MAX_ESC_PARAMS; i++) {
@@ -1194,9 +1246,16 @@
if (qs->trace_buffer)
eb_trace_bytes(buf, len, EB_TRACE_SHELL);
+ {
+ /* Suspend BF_READONLY flag to allow shell output to readonly buffer */
+ int save_readonly = s->b->flags & BF_READONLY;
+ s->b->flags &= ~BF_READONLY;
+
for (i = 0; i < len; i++)
tty_emulate(s, buf[i]);
+ s->b->flags |= save_readonly;
+ }
/* now we do some refresh */
edit_display(qs);
dpy_flush(qs->screen);
@@ -1214,7 +1273,7 @@
if (s->is_shell == 1) {
snprintf(buf, sizeof(buf), "\nProcess shell finished\n");
} else
- if (s->is_shell == 0) {
+ if (s->is_shell == 3) {
time_t ti;
char *time_str;
@@ -1232,7 +1291,16 @@
status, time_str);
}
}
+ {
+ /* Flush output to buffer, bypassing readonly flag */
+ int save_readonly = s->b->flags & BF_READONLY;
+ s->b->flags &= ~BF_READONLY;
+
eb_write(b, b->total_size, buf, strlen(buf));
+
+ s->b->flags |= save_readonly;
+ }
+
set_pid_handler(s->pid, NULL, NULL);
s->pid = -1;
/* no need to leave the pty opened */
@@ -1286,6 +1354,7 @@
{
ShellState *s;
EditBuffer *b, *b_color;
+ const char *lang;
int rows, cols;
b = b0;
@@ -1294,6 +1363,11 @@
if (!b)
return NULL;
eb_set_buffer_name(b, name); /* ensure that the name is unique */
+
+ /* Select shell output buffer encoding from LANG setting */
+ if ((lang = getenv("LANG")) != NULL && strstr(lang, "UTF-8"))
+ eb_set_charset(b, &charset_utf8);
+ else
eb_set_charset(b, &charset_vt100);
s = qe_mallocz(ShellState);
@@ -1415,9 +1489,9 @@
if (!b)
return;
+ b->flags |= BF_READONLY;
switch_to_buffer(s, b);
- edit_set_mode(s, &shell_mode, NULL);
- s->interactive = 0;
+ edit_set_mode(s, &pager_mode, NULL);
}
static void shell_move_left_right(EditState *e, int dir)
@@ -1461,6 +1535,9 @@
static void shell_move_bol(EditState *e)
{
+ /* XXX: exit shell interactive mode on home / ^A */
+ e->interactive = 0;
+
if (e->interactive) {
ShellState *s = e->b->priv_data;
tty_write(s, "\001", 1); /* Control-A */
@@ -1471,28 +1548,33 @@
static void shell_move_eol(EditState *e)
{
- if (e->interactive) {
ShellState *s = e->b->priv_data;
+
+ if (e->interactive) {
tty_write(s, "\005", 1); /* Control-E */
} else {
text_move_eol(e);
+ /* XXX: restore shell interactive mode on end / ^E */
+ e->interactive = (e->offset == s->cur_offset);
}
}
static void shell_write_char(EditState *e, int c)
{
- char buf[2], *p;
+ char buf[10];
+ int len;
if (e->interactive) {
ShellState *s = e->b->priv_data;
- p = buf;
- *p++ = c;
if (c >= KEY_META(0) && c <= KEY_META(0xff)) {
- p[-1] = '\033';
- *p++ = c - KEY_META(0);
+ buf[0] = '\033';
+ buf[1] = c - KEY_META(0);
+ len = 2;
+ } else {
+ len = unicode_to_charset(buf, c, e->b->charset);
}
- tty_write(s, buf, p - buf);
+ tty_write(s, buf, len);
} else {
/* Should dispatch as in fundamental mode */
switch (c) {
@@ -1525,6 +1607,11 @@
break;
}
}
+ if (c == '\r') {
+ /* skip errors from previous commands */
+ error_offset = e->offset;
+ last_line_num = -1;
+ }
}
static void do_shell_toggle_input(EditState *e)
@@ -1543,11 +1630,6 @@
#endif
}
-/* CG: these variables should move to mode structure */
-static int error_offset = -1;
-static int last_line_num = -1;
-static char last_filename[MAX_FILENAME_SIZE];
-
static void do_compile(EditState *e, const char *cmd)
{
const char *argv[4];
@@ -1564,17 +1646,23 @@
error_offset = -1;
last_line_num = -1;
+ if (!cmd || !*cmd)
+ cmd = "make";
+
/* create new buffer */
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = (char *)cmd;
argv[3] = NULL;
- b = new_shell_buffer(NULL, "*compilation*", "/bin/sh", argv, 0);
+ b = new_shell_buffer(NULL, "*compilation*", "/bin/sh", argv, 3);
if (!b)
return;
/* XXX: try to split window if necessary */
switch_to_buffer(e, b);
+ /* XXX: pager_mode for colorized output, text mode should support color
buffer */
+ /* XXX: compilation_buffer should handle error skipping with RET */
+ edit_set_mode(e, &pager_mode, NULL);
}
static void do_compile_error(EditState *s, int dir)
@@ -1673,7 +1761,7 @@
/* CG: Should put_message of error text */
}
-/* specific shell commands */
+/* shell mode specific commands */
static CmdDef shell_commands[] = {
CMD0( KEY_CTRL('o'), KEY_NONE,
"shell-toggle-input", do_shell_toggle_input)
@@ -1701,8 +1789,21 @@
CMD_DEF_END,
};
-/* compilation commands */
-static CmdDef compile_commands[] = {
+/* pager mode specific commands */
+static CmdDef pager_commands[] = {
+ CMD1( KEY_DEL, KEY_NONE,
+ "scroll-down", do_scroll_up_down, -2 ) /* u? */
+ CMD1( KEY_SPC, KEY_NONE,
+ "scroll-up", do_scroll_up_down, 2 ) /* u? */
+ CMD3( '/', KEY_NONE,
+ "search-forward", do_search_string, ESsi, 1,
+ "s{/}|search|"
+ "v")
+ CMD_DEF_END,
+};
+
+/* shell global commands */
+static CmdDef shell_global_commands[] = {
CMD2( KEY_CTRLXRET('\r'), KEY_NONE,
"shell", do_shell, ESi, "ui")
CMD2( KEY_CTRLX(KEY_CTRL('e')), KEY_NONE,
@@ -1725,7 +1826,16 @@
{
s->tab_size = 8;
s->wrap = WRAP_TRUNCATE;
+ set_colorize_func(s, NULL);
+ s->get_colorized_line = shell_get_colorized_line;
s->interactive = 1;
+ return 0;
+}
+
+static int pager_mode_init(EditState *s, __unused__ ModeSavedData *saved_data)
+{
+ s->tab_size = 8;
+ s->wrap = WRAP_TRUNCATE;
set_colorize_func(s, NULL);
s->get_colorized_line = shell_get_colorized_line;
return 0;
@@ -1733,7 +1843,7 @@
static int shell_init(void)
{
- /* first register mode */
+ /* populate and register shell mode and commands */
memcpy(&shell_mode, &text_mode, sizeof(ModeDef));
shell_mode.name = "shell";
shell_mode.mode_probe = NULL;
@@ -1749,10 +1859,20 @@
shell_mode.mode_flags |= MODEF_NOCMD;
qe_register_mode(&shell_mode);
-
- /* commands and default keys */
qe_register_cmd_table(shell_commands, &shell_mode);
- qe_register_cmd_table(compile_commands, NULL);
+
+ /* populate and register pager mode and commands */
+ memcpy(&pager_mode, &text_mode, sizeof(ModeDef));
+ pager_mode.name = "pager";
+ pager_mode.mode_probe = NULL;
+ pager_mode.mode_init = pager_mode_init;
+ pager_mode.mode_flags |= MODEF_NOCMD;
+
+ qe_register_mode(&pager_mode);
+ qe_register_cmd_table(pager_commands, &pager_mode);
+
+ /* global shell related commands and default keys */
+ qe_register_cmd_table(shell_global_commands, NULL);
return 0;
}
- [Qemacs-commit] qemacs shell.c,
Charlie Gordon <=