From cb2a285f50a6a0bf54a9d7e65579cb6edcda008b Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Wed, 6 Jun 2001 22:49:25 +0000 Subject: command history and tab completion added --- NEWS | 15 +++ mixgtk/mixgtk.glade | 33 ++--- mixgtk/mixgtk_cmd_dispatcher.c | 274 +++++++++++++++++------------------------ 3 files changed, 144 insertions(+), 178 deletions(-) diff --git a/NEWS b/NEWS index 2785fb6..775e4e5 100644 --- a/NEWS +++ b/NEWS @@ -17,13 +17,28 @@ Please send mdk bug reports to bug-mdk@gnu.org. external programs used can be configured using the menu entry Settings->External programs. +** The commands 'edit' and 'compile' can be now executed without + argument (both in mixvm and gmixvm). When no argument is given, the + MIXAL source file corresponding to the currently loaded MIX program + is edited/compiled. + ** Bug in CON fixed : 'CON wexpr' didn't compile correctly unless wexpr represented a valid instruction; now, wexpr can evaluate to an arbitrary value (Vasilij Ozmetelenko). +** The completion key for the gmixvm command prompt is now TAB + (instead of RETURN). + +** The gmixvm command prompt maintains now a history of previously + typed commands, which can be visited using the arrow keys (UP for + previous commands, DOWN for next). + ** When a file is reloaded by the virtual machine (both in mixvm and gmixvm), the currently set breakpoints are conserved. +** When compiling a source file which is not in the current directory, the + correct path is now stored in the compiled file. + --------------------------------------------------------------------------- * Version 0.3.2 (10/04/01) diff --git a/mixgtk/mixgtk.glade b/mixgtk/mixgtk.glade index a0dcfcf..5a74485 100644 --- a/mixgtk/mixgtk.glade +++ b/mixgtk/mixgtk.glade @@ -1220,7 +1220,7 @@ GtkScrolledWindow mixlog_scrolledwindow - GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC GTK_POLICY_ALWAYS GTK_UPDATE_CONTINUOUS GTK_UPDATE_CONTINUOUS @@ -1245,9 +1245,10 @@ True True - activate - on_mixvm_cmd_entry_activate - Thu, 22 Feb 2001 23:26:28 GMT + key_press_event + on_command_prompt_key_press_event + True + Wed, 06 Jun 2001 06:46:05 GMT True True @@ -2519,7 +2520,7 @@ GtkDialog external_dialog - 235 + 285 210 False @@ -2636,23 +2637,23 @@ editor_entry 48 40 - 160 + 220 24 True True True 0 - vi %s + xterm -e vi %s GtkLabel label234 - 16 + 3 16 - 176 + 223 16 - + GTK_JUSTIFY_LEFT False 0.5 @@ -2676,23 +2677,23 @@ mixasm_entry 48 40 - 158 + 220 22 True True True 0 - mixasm -g + mixasm -g %s GtkLabel label235 - 11 - 8 - 168 + 0 + 16 + 278 16 - + GTK_JUSTIFY_LEFT False 0.5 diff --git a/mixgtk/mixgtk_cmd_dispatcher.c b/mixgtk/mixgtk_cmd_dispatcher.c index bb1d4db..5076727 100644 --- a/mixgtk/mixgtk_cmd_dispatcher.c +++ b/mixgtk/mixgtk_cmd_dispatcher.c @@ -29,6 +29,13 @@ #include #include +#include + +#ifdef HAVE_LIBHISTORY +# include +#endif + +#include #include #include "mixgtk_mixvm.h" #include "mixgtk_mixal.h" @@ -51,21 +58,18 @@ typedef struct mixgtk_dispatch_ static struct mixgtk_dispatch_ dis_data_ = {NULL}; -/* local commands stuff */ -static const gchar *EDITOR_ = NULL; -static const gchar *MIXASM_ = NULL; -static const gchar *EDITOR_KEY_ = "Editor"; -static const gchar *MIXASM_KEY_ = "Mixasm"; - -typedef gboolean (*local_handler_t) (mixgtk_dispatch_data_t *, - const gchar *); - static void log_command_ (mixgtk_dispatch_data_t *dis, const gchar *cmd) { gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL,"MIX> ", -1); gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL, cmd, -1); gtk_text_insert (GTK_TEXT (dis->log), NULL, NULL, NULL, "\n", -1); + +#ifdef HAVE_LIBHISTORY + add_history ((char *)cmd); +/* history_search ((char *)cmd, 0); */ + history_set_pos (history_base + history_length - 1); +#endif } static void @@ -85,90 +89,6 @@ flush_log_ (mixgtk_dispatch_data_t *dis) } } -static gboolean -exec_ (mixgtk_dispatch_data_t *dis, const gchar *cmd, const gchar *arg) -{ - gchar *fullcmd = NULL; - gboolean r = FALSE; - fullcmd = g_strdup_printf (cmd, arg); - r = !system (fullcmd); - flush_log_ (dis); - g_free (fullcmd); - return r; -} - -static const gchar * -get_src_file_path_ (mixgtk_dispatch_data_t *dis) -{ - static gchar *PATH = NULL; - - const mix_vm_t *vm = mix_vm_cmd_dispatcher_get_vm (dis->dispatcher); - const mix_src_file_t *f = mix_vm_get_src_file (vm); - - if (PATH) - { - g_free (PATH); - PATH = NULL; - } - - if (f) - PATH = mix_file_complete_name (mix_src_file_get_path (f), MIX_SRC_DEFEXT); - - return PATH; -} - -static gboolean -edit_handler_ (mixgtk_dispatch_data_t *dis, const gchar *arg) -{ - if (!arg) arg = get_src_file_path_ (dis); - if (!arg) return FALSE; - return exec_ (dis, EDITOR_, arg); -} - -static gboolean -compile_handler_ (mixgtk_dispatch_data_t *dis, const gchar *arg) -{ - if (!arg) arg = get_src_file_path_ (dis); - if (!arg) return FALSE; - return exec_ (dis, MIXASM_, arg); -} - -static const gchar* local_cmds_[] = { - "edit", "compile" -}; - -static const local_handler_t handlers_[] = { - edit_handler_, compile_handler_ -}; - -#define LOCAL_NO_ (sizeof (local_cmds_) / sizeof (local_cmds_[0])) - -static gboolean -dispatch_local_command_ (mixgtk_dispatch_data_t *dis, const gchar *cmd) -{ - int k = 0; - - g_return_val_if_fail (dis != NULL, FALSE); - g_return_val_if_fail (cmd != NULL, FALSE); - - for (k = 0; k < LOCAL_NO_; ++k) - { - if (!strncmp (local_cmds_[k], cmd, strlen (local_cmds_[k]))) - { - int j = 0; - const gchar *arg = NULL; - while (cmd[j] && !isspace (cmd[j])) ++j; - if (cmd[j]) arg = cmd + j; - log_command_ (dis, cmd); - handlers_[k](dis, arg); - return TRUE; - } - } - - return FALSE; -} - - /* completions */ static void init_completions_ (void) @@ -179,37 +99,9 @@ init_completions_ (void) dis_data_.completions = g_completion_new (NULL); for (k = 0; k < MIX_CMD_INVALID; ++k) cmds = g_list_append (cmds, (gpointer) mix_vm_command_to_string (k)); - for (k = 0; k < sizeof (local_cmds_) / sizeof (local_cmds_[0]); ++k) - cmds = g_list_append (cmds, (gpointer)local_cmds_[k]); g_completion_add_items (dis_data_.completions, cmds); } -/* global hooks for the command dispatcher -static void -global_pre_hook_ (mix_vm_cmd_dispatcher_t *dis, - mix_vm_command_t cmd, const gchar *arg, gpointer data) -{ - if (cmd < MIX_CMD_INVALID) - { - gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, - "MIX> ", -1); - gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, - mix_vm_command_to_string (cmd), -1); - gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, - " ", -1); - gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, - arg, -1); - gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, - "\n", -1); - } - else - { - gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL, - _("\n*** Invalid command ***\n"), -1); - } -} -*/ - static void global_post_hook_ (mix_vm_cmd_dispatcher_t *dis, mix_vm_command_t cmd, const gchar *arg, gpointer data) @@ -309,19 +201,44 @@ install_hooks_ (void) } /* configuration stuff */ +static const gchar *EDITOR_KEY_ = "Editor"; +static const gchar *MIXASM_KEY_ = "Mixasm"; +static const gchar *HISTORY_FILE_KEY_ = "History.file"; +static const gchar *MAX_HISTORY_KEY_ = "History.size"; +static const gchar *HISTORY_FILE_ = NULL; +static int MAX_HISTORY_ = 50; + static void read_config_ (void) { - EDITOR_ = mixgtk_config_get (EDITOR_KEY_); - if (!EDITOR_) + const gchar *editor = mixgtk_config_get (EDITOR_KEY_); + const gchar *assem = mixgtk_config_get (MIXASM_KEY_); + +#ifdef HAVE_LIBHISTORY + const gchar *mh = mixgtk_config_get (MAX_HISTORY_KEY_); + if (mh) MAX_HISTORY_ = atoi (mh); + if (MAX_HISTORY_ <= 0) MAX_HISTORY_ = 50; + HISTORY_FILE_ = mixgtk_config_get (HISTORY_FILE_KEY_); +#endif + + if (!editor) { static const gchar *ENV[] = {"MDK_EDITOR", "X_EDITOR", NULL}; + gchar *edit = NULL; int k = 0; - while (!EDITOR_ && ENV[k]) EDITOR_ = getenv (ENV[k++]); - if (EDITOR_) EDITOR_ = g_strconcat (EDITOR_, " %s", NULL); + while (!edit && ENV[k]) edit = getenv (ENV[k++]); + if (edit) edit = g_strconcat (edit, " %s", NULL); + else edit = g_strdup ("xterm -e vi %s"); + mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, edit); + g_free (edit); } - MIXASM_ = mixgtk_config_get (MIXASM_KEY_); - if (!MIXASM_) MIXASM_ = "mixasm -g %s"; + else + { + mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, editor); + } + if (!assem) assem = "mixasm -g %s"; + mix_vm_cmd_dispatcher_set_assembler (dis_data_.dispatcher, assem); + } static GtkWidget *ext_dlg_ = NULL; @@ -345,8 +262,11 @@ on_external_programs_activate () (MIXGTK_EXTERNPROG_DIALOG, ASM_NAME_); g_assert (asm_entry_); } - gtk_entry_set_text (GTK_ENTRY (ed_entry_), EDITOR_); - gtk_entry_set_text (GTK_ENTRY (asm_entry_), MIXASM_); + gtk_entry_set_text (GTK_ENTRY (ed_entry_), + mix_vm_cmd_dispatcher_get_editor (dis_data_.dispatcher)); + gtk_entry_set_text (GTK_ENTRY (asm_entry_), + mix_vm_cmd_dispatcher_get_assembler + (dis_data_.dispatcher)); gtk_widget_show (ext_dlg_); } @@ -359,10 +279,12 @@ on_extern_cancel_button_clicked () void on_extern_ok_button_clicked () { - EDITOR_ = gtk_entry_get_text (GTK_ENTRY (ed_entry_)); - MIXASM_ = gtk_entry_get_text (GTK_ENTRY (asm_entry_)); - mixgtk_config_update (EDITOR_KEY_, EDITOR_); - mixgtk_config_update (MIXASM_KEY_, MIXASM_); + const gchar *value = gtk_entry_get_text (GTK_ENTRY (ed_entry_)); + mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, value); + mixgtk_config_update (EDITOR_KEY_, value); + value = gtk_entry_get_text (GTK_ENTRY (asm_entry_)); + mix_vm_cmd_dispatcher_set_assembler (dis_data_.dispatcher, value); + mixgtk_config_update (MIXASM_KEY_, value); gtk_widget_hide (ext_dlg_); } @@ -411,6 +333,11 @@ mixgtk_cmd_dispatcher_init (void) if (!dis_data_.completions) init_completions_ (); read_config_ (); + +#ifdef HAVE_LIBHISTORY + using_history (); + stifle_history (MAX_HISTORY_); +#endif return TRUE; } @@ -423,7 +350,9 @@ mixgtk_cmd_dispatcher_dispatch (const gchar *command) g_return_if_fail (command != NULL); g_assert (entry != NULL); gtk_entry_set_text (GTK_ENTRY (entry), command); - on_mixvm_cmd_entry_activate (entry, NULL); + log_command_ (&dis_data_, command); + mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, command); + gtk_entry_set_text (GTK_ENTRY (entry), ""); } /* get times */ @@ -445,34 +374,18 @@ mixgtk_cmd_dispatcher_get_vm (void) return (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (dis_data_.dispatcher); } -/* process new command */ +/* process commands */ void -on_mixvm_cmd_entry_activate (GtkWidget *w, gpointer e) +complete_command_ (void) { - gchar *text; - GList *cmds = NULL; + GtkEntry *entry = GTK_ENTRY (dis_data_.prompt); gchar *prefix = NULL; - - text = g_strchomp (gtk_entry_get_text (GTK_ENTRY (w))); - - if (mix_vm_command_from_string (text) != MIX_CMD_INVALID) - { - mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text); - gtk_entry_set_text (GTK_ENTRY (w), ""); - return; - } - - if (dispatch_local_command_ (&dis_data_, text)) - { - gtk_entry_set_text (GTK_ENTRY (w), ""); - return; - } - - cmds = g_completion_complete (dis_data_.completions, text, &prefix); + gchar *text = g_strchomp (gtk_entry_get_text (entry)); + GList *cmds = g_completion_complete (dis_data_.completions, text, &prefix); if (prefix != NULL) { - gtk_entry_set_text (GTK_ENTRY (w), prefix); + gtk_entry_set_text (entry, prefix); g_free (prefix); if (g_list_length (cmds) > 1) { @@ -498,14 +411,51 @@ on_mixvm_cmd_entry_activate (GtkWidget *w, gpointer e) NULL, NULL, NULL, "\n", -1); } else - gtk_entry_append_text (GTK_ENTRY (w), " "); + gtk_entry_append_text (entry, " "); } - else +} + + +int +on_command_prompt_key_press_event (GtkEntry *w, GdkEventKey *e, gpointer d) +{ + guint key = e->keyval; + +#ifdef HAVE_LIBHISTORY + HIST_ENTRY *entry = NULL; + if (key == GDK_Up) { - log_command_ (&dis_data_, text); - mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text); - gtk_entry_set_text (GTK_ENTRY (w), ""); + entry = previous_history (); + if (entry && entry->line) + gtk_entry_set_text (w, entry->line); + return TRUE; } -} + if (key == GDK_Down) + { + entry = next_history (); + if (entry && entry->line) + gtk_entry_set_text (w, entry->line); + return TRUE; + } +#endif + if (key == GDK_Tab) + { + complete_command_ (); + return TRUE; + } + if (key == GDK_Return) + { + gchar *text = gtk_entry_get_text (w); + if (text && *text) + { + log_command_ (&dis_data_, text); + mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text); + gtk_entry_set_text (w, ""); + } + return TRUE; + } + + return FALSE; +} -- cgit v1.2.3