Expression-oriented readline history
[bpt/guile.git] / guile-readline / ice-9 / readline.scm
index 96af69e..36f805f 100644 (file)
@@ -1,6 +1,6 @@
 ;;;; readline.scm --- support functions for command-line editing
 ;;;;
-;;;;   Copyright (C) 1997, 1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc.
+;;;;   Copyright (C) 1997, 1999, 2000, 2001, 2002, 2006, 2009, 2010 Free Software Foundation, Inc.
 ;;;; 
 ;;;; This program is free software; you can redistribute it and/or modify
 ;;;; it under the terms of the GNU General Public License as published by
 \f
 
 (define-module (ice-9 readline)
-  :use-module (ice-9 session)
-  :use-module (ice-9 regex)
-  :use-module (ice-9 buffered-input)
-  :no-backtrace
-  :export (filename-completion-function))
+  #:use-module (ice-9 session)
+  #:use-module (ice-9 regex)
+  #:use-module (ice-9 buffered-input)
+  #:no-backtrace
+  #:export (filename-completion-function
+           add-history
+           read-history
+           write-history
+           clear-history))
 
 \f
 
 (define read-hook #f)
 
 (define (make-readline-port)
-  (make-line-buffered-input-port (lambda (continuation?)
-                                   (let* ((prompt (if continuation?
-                                                      continuation-prompt
-                                                      new-input-prompt))
-                                          (str (%readline (if (string? prompt)
-                                                              prompt
-                                                              (prompt))
-                                                          input-port
-                                                          output-port
-                                                          read-hook)))
-                                     (or (eof-object? str)
-                                         (string=? str "")
-                                         (add-history str))
-                                     str))))
+  (let ((history-buffer #f))
+    (make-line-buffered-input-port (lambda (continuation?)
+                                     ;; When starting a new read, add
+                                     ;; the previously read expression
+                                     ;; to the history.
+                                     (if (and (not continuation?)
+                                              history-buffer)
+                                         (begin
+                                           (add-history history-buffer)
+                                           (set! history-buffer #f)))
+                                     ;; Set up prompts and read a line.
+                                     (let* ((prompt (if continuation?
+                                                        continuation-prompt
+                                                        new-input-prompt))
+                                            (str (%readline (if (string? prompt)
+                                                                prompt
+                                                                (prompt))
+                                                            input-port
+                                                            output-port
+                                                            read-hook)))
+                                       (or (eof-object? str)
+                                           (string=? str "")
+                                           (set! history-buffer
+                                                 (if history-buffer
+                                                     (string-append history-buffer
+                                                                    " "
+                                                                    str)
+                                                     str)))
+                                       str)))))
 
 ;;; We only create one readline port.  There's no point in having
 ;;; more, since they would all share the tty and history ---
        (lambda ()
          (set! *readline-completion-function* old-completer)))))
 
+(define readline-repl-reader
+  (let ((boot-9-repl-reader repl-reader))
+    (lambda* (repl-prompt #:optional (reader (fluid-ref current-reader)))
+      (let ((port (current-input-port)))
+        (if (eq? port (readline-port))
+            (let ((outer-new-input-prompt new-input-prompt)
+                  (outer-continuation-prompt continuation-prompt)
+                  (outer-read-hook read-hook))
+              (dynamic-wind
+                (lambda ()
+                  (set-buffered-input-continuation?! port #f)
+                  (set-readline-prompt! repl-prompt "... ")
+                  (set-readline-read-hook! (lambda ()
+                                             (run-hook before-read-hook))))
+                (lambda () ((or reader read) port))
+                (lambda ()
+                  (set-readline-prompt! outer-new-input-prompt
+                                        outer-continuation-prompt)
+                  (set-readline-read-hook! outer-read-hook))))
+            (boot-9-repl-reader repl-prompt reader))))))
+
 (define-public (activate-readline)
-  (if (and (isatty? (current-input-port))
-          (not (let ((guile-user-module (resolve-module '(guile-user))))
-                 (and (module-defined? guile-user-module 'use-emacs-interface)
-                      (module-ref guile-user-module 'use-emacs-interface)))))
-      (let ((repl-read-hook (lambda () (run-hook before-read-hook))))
-       (set-current-input-port (readline-port))
-       (set! repl-reader
-             (lambda (repl-prompt)
-               (let ((outer-new-input-prompt new-input-prompt)
-                     (outer-continuation-prompt continuation-prompt)
-                     (outer-read-hook read-hook))
-                 (dynamic-wind
-                     (lambda ()
-                       (set-buffered-input-continuation?! (readline-port) #f)
-                       (set-readline-prompt! repl-prompt "... ")
-                       (set-readline-read-hook! repl-read-hook))
-                     (lambda () ((or (fluid-ref current-reader) read)))
-                     (lambda ()
-                       (set-readline-prompt! outer-new-input-prompt outer-continuation-prompt)
-                       (set-readline-read-hook! outer-read-hook))))))
-       (set! (using-readline?) #t))))
+  (if (isatty? (current-input-port))
+      (begin
+        (set-current-input-port (readline-port))
+        (set! repl-reader readline-repl-reader)
+        (set! (using-readline?) #t))))
 
 (define-public (make-completion-function strings)
   "Construct and return a completion function for a list of strings.