aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2011-12-06 08:56:35 +1000
committerSteve Bennett <steveb@workware.net.au>2011-12-09 12:10:33 +1000
commit8e90299b82be4dc6c8c86dbd206db9e0efdbffc6 (patch)
treebf75cde4346bec5000f5566cc4421703e912d53a
parenta2fe8bd6794e017117986dfa11619fbf00b62239 (diff)
downloadjimtcl-8e90299b82be4dc6c8c86dbd206db9e0efdbffc6.zip
jimtcl-8e90299b82be4dc6c8c86dbd206db9e0efdbffc6.tar.gz
jimtcl-8e90299b82be4dc6c8c86dbd206db9e0efdbffc6.tar.bz2
Add the history command
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--auto.def2
-rw-r--r--examples/jtclsh.tcl36
-rw-r--r--jim-history.c117
3 files changed, 155 insertions, 0 deletions
diff --git a/auto.def b/auto.def
index 6c241d7..7eb00ca 100644
--- a/auto.def
+++ b/auto.def
@@ -26,6 +26,7 @@ options {
exec - Tcl-compatible exec command
file - Tcl-compatible file command
glob - Tcl-compatible glob command
+ history - Tcl access to interactive history
readdir - Required for glob
package - Package management with the package command
load - Load binary extensions at runtime with load or package
@@ -195,6 +196,7 @@ dict set extdb attrs {
exec { static }
file {}
glob { tcl }
+ history {}
load { static }
mk { cpp optional }
oo { tcl optional full }
diff --git a/examples/jtclsh.tcl b/examples/jtclsh.tcl
new file mode 100644
index 0000000..dc92bca
--- /dev/null
+++ b/examples/jtclsh.tcl
@@ -0,0 +1,36 @@
+# Simple example of how the history extension
+# can be used to provide line editing and history
+
+# Build jimsh with the history extension and enable line editing (the default)
+# ./configure --with-ext=history
+
+package require history
+
+set histfile [env HOME]/.jtclsh
+history load $histfile
+while 1 {
+ if {[history getline "jim> " cmd] < 0} {
+ break
+ }
+ if {$cmd eq "h"} {
+ history show
+ continue
+ }
+ # Don't bother adding single char commands to the history
+ if {[string length $cmd] > 1} {
+ history add $cmd
+ history save $histfile
+ }
+ # jimsh also does:
+ # - check for a complete command: [info complete]
+ # - handle other non-error return codes and changes the prompt: [info returncodes]
+ # - displays the complete error message: [errorInfo]
+ try {
+ set result [eval $cmd]
+ if {$result ne {}} {
+ puts $result
+ }
+ } on error msg {
+ puts $msg
+ }
+}
diff --git a/jim-history.c b/jim-history.c
new file mode 100644
index 0000000..d46ed7f
--- /dev/null
+++ b/jim-history.c
@@ -0,0 +1,117 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "jim.h"
+#include "jimautoconf.h"
+#include "jim-subcmd.h"
+
+static int history_cmd_getline(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_Obj *objPtr;
+ char *line = Jim_HistoryGetline(Jim_String(argv[0]));
+
+ /* On EOF returns -1 if varName was specified, or the empty string. */
+ if (line == NULL) {
+ if (argc == 2) {
+ Jim_SetResultInt(interp, -1);
+ }
+ return JIM_OK;
+ }
+
+ objPtr = Jim_NewStringObjNoAlloc(interp, line, -1);
+
+ /* Returns the length of the string if varName was specified */
+ if (argc == 2) {
+ if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) {
+ Jim_FreeNewObj(interp, objPtr);
+ return JIM_ERR;
+ }
+ Jim_SetResultInt(interp, Jim_Length(objPtr));
+ }
+ else {
+ Jim_SetResult(interp, objPtr);
+ }
+ return JIM_OK;
+}
+
+static int history_cmd_load(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_HistoryLoad(Jim_String(argv[0]));
+ return JIM_OK;
+}
+
+static int history_cmd_save(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_HistorySave(Jim_String(argv[0]));
+ return JIM_OK;
+}
+
+static int history_cmd_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_HistoryAdd(Jim_String(argv[0]));
+ return JIM_OK;
+}
+
+static int history_cmd_show(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_HistoryShow();
+ return JIM_OK;
+}
+
+static const jim_subcmd_type history_command_table[] = {
+ { "getline",
+ "prompt ?varname?",
+ history_cmd_getline,
+ 1,
+ 2,
+ /* Description: Reads one line from the user. Similar to gets. */
+ },
+ { "load",
+ "filename",
+ history_cmd_load,
+ 1,
+ 1,
+ /* Description: Loads history from the given file, if possible */
+ },
+ { "save",
+ "filename",
+ history_cmd_save,
+ 1,
+ 1,
+ /* Description: Saves history to the given file */
+ },
+ { "add",
+ "line",
+ history_cmd_add,
+ 1,
+ 1,
+ /* Description: Adds the line to the history ands saves */
+ },
+ { "show",
+ NULL,
+ history_cmd_show,
+ 0,
+ 0,
+ /* Description: Displays the history */
+ },
+ { NULL }
+};
+
+static int JimHistorySubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, history_command_table, argc, argv), argc, argv);
+}
+
+int Jim_historyInit(Jim_Interp *interp)
+{
+ void **history;
+ if (Jim_PackageProvide(interp, "history", "1.0", JIM_ERRMSG))
+ return JIM_ERR;
+
+ history = Jim_Alloc(sizeof(*history));
+ *history = NULL;
+
+ Jim_CreateCommand(interp, "history", JimHistorySubCmdProc, history, NULL);
+ return JIM_OK;
+}