*** empty log message ***
[bpt/guile.git] / guile-readline / readline.scm
CommitLineData
b18c7b77
MV
1;;;; readline.scm --- support functions for command-line editing
2;;;;
ebfa2cd5 3;;;; Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc.
b18c7b77
MV
4;;;;
5;;;; This program is free software; you can redistribute it and/or modify
6;;;; it under the terms of the GNU General Public License as published by
7;;;; the Free Software Foundation; either version 2, or (at your option)
8;;;; any later version.
9;;;;
10;;;; This program is distributed in the hope that it will be useful,
11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13;;;; GNU General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU General Public License
16;;;; along with this software; see the file COPYING. If not, write to
17;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18;;;; Boston, MA 02111-1307 USA
19;;;;
20;;;; Contributed by Daniel Risacher <risacher@worldnet.att.net>.
21;;;; Extensions based upon code by
22;;;; Andrew Archibald <aarchiba@undergrad.math.uwaterloo.ca>.
23
24(define-module (ice-9 readline)
25 :use-module (ice-9 session)
c8fac0c3
MD
26 :use-module (ice-9 regex)
27 :no-backtrace)
b18c7b77 28
acb0207f
MV
29;;; Dynamically link the glue code for accessing the readline library,
30;;; but only when it isn't already present.
b18c7b77 31
acb0207f
MV
32(if (not (feature? 'readline))
33 (dynamic-call "scm_init_readline" (dynamic-link "libguilereadline.so")))
b18c7b77 34
c8fac0c3
MD
35(if (not (feature? 'readline))
36 (scm-error 'misc-error
37 #f
38 "readline is not provided in this Guile installation"
39 '()
40 '()))
41
b18c7b77
MV
42;;; MDJ 980513 <djurfeldt@nada.kth.se>:
43;;; There should probably be low-level support instead of this code.
44
45(define prompt "")
46(define prompt2 "")
47(define input-port (current-input-port))
48(define output-port (current-output-port))
49(define read-hook #f)
50
51(define (make-readline-port)
52 (let ((read-string "")
53 (string-index -1))
54 (letrec ((get-character
55 (lambda ()
56 (cond
57 ((eof-object? read-string)
58 read-string)
59 ((>= string-index (string-length read-string))
60 (begin
61 (set! string-index -1)
62 #\nl))
63 ((= string-index -1)
64 (begin
65 (set! read-string
66 (%readline (if (string? prompt)
67 prompt
68 (prompt))
69 input-port
70 output-port
71 read-hook))
72 (set! string-index 0)
73 (if (not (eof-object? read-string))
74 (begin
75 (or (string=? read-string "")
76 (begin
77 (add-history read-string)
78 (set! prompt prompt2)))
79 (get-character))
80 read-string)))
81 (else
82 (let ((res (string-ref read-string string-index)))
83 (set! string-index (+ 1 string-index))
84 res))))))
85 (make-soft-port
86 (vector write-char display #f get-character #f)
87 "rw"))))
88
89;;; We only create one readline port. There's no point in having
90;;; more, since they would all share the tty and history ---
91;;; everything except the prompt. And don't forget the
92;;; compile/load/run phase distinctions. Also, the readline library
93;;; isn't reentrant.
94(define the-readline-port #f)
95
96(define history-variable "GUILE_HISTORY")
97(define history-file (string-append (getenv "HOME") "/.guile_history"))
98
99(define-public readline-port
100 (let ((do (lambda (r/w)
101 (if (memq 'history-file (readline-options-interface))
102 (r/w (or (getenv history-variable)
103 history-file))))))
104 (lambda ()
105 (if (not the-readline-port)
106 (begin
107 (do read-history)
108 (set! the-readline-port (make-readline-port))
109 (add-hook! exit-hook (lambda () (do write-history)))))
110 the-readline-port)))
111
112;;; The user might try to use readline in his programs. It then
113;;; becomes very uncomfortable that the current-input-port is the
114;;; readline port...
115;;;
116;;; Here, we detect this situation and replace it with the
117;;; underlying port.
118;;;
119;;; %readline is the low-level readline procedure.
120
121(define-public (readline . args)
122 (let ((prompt prompt)
123 (inp input-port))
124 (cond ((not (null? args))
125 (set! prompt (car args))
126 (set! args (cdr args))
127 (cond ((not (null? args))
128 (set! inp (car args))
129 (set! args (cdr args))))))
130 (apply %readline
131 prompt
132 (if (eq? inp the-readline-port)
133 input-port
134 inp)
135 args)))
136
137(define-public (set-readline-prompt! p . rest)
138 (set! prompt p)
139 (if (not (null? rest))
140 (set! prompt2 (car rest))))
141
142(define-public (set-readline-input-port! p)
143 (set! input-port p))
144
145(define-public (set-readline-output-port! p)
146 (set! output-port p))
147
148(define-public (set-readline-read-hook! h)
149 (set! read-hook h))
150
ebfa2cd5
MD
151(if (feature? 'regex)
152 (begin
153 (define-public apropos-completion-function
154 (let ((completions '()))
155 (lambda (text cont?)
156 (if (not cont?)
157 (set! completions
158 (map symbol->string
159 (apropos-internal
160 (string-append "^" (regexp-quote text))))))
161 (if (null? completions)
162 #f
163 (let ((retval (car completions)))
164 (begin (set! completions (cdr completions))
165 retval))))))
166
167 (set! *readline-completion-function* apropos-completion-function)
168 ))
b18c7b77
MV
169
170(define-public (activate-readline)
171 (if (and (isatty? (current-input-port))
172 (not (and (module-defined? the-root-module
173 'use-emacs-interface)
174 use-emacs-interface)))
175 (let ((read-hook (lambda () (run-hook before-read-hook))))
176 (set-current-input-port (readline-port))
177 (set! repl-reader
178 (lambda (prompt)
179 (dynamic-wind
180 (lambda ()
181 (set-readline-prompt! prompt "... ")
182 (set-readline-read-hook! read-hook))
183 (lambda () (read))
184 (lambda ()
185 (set-readline-prompt! "" "")
6373eb6f
MD
186 (set-readline-read-hook! #f)))))
187 (set! (using-readline?) #t))))