Added a comment re: a warning.
[bpt/guile.git] / guile-readline / readline.scm
CommitLineData
b18c7b77
MV
1;;;; readline.scm --- support functions for command-line editing
2;;;;
a4bfce11 3;;;; Copyright (C) 1997, 1999 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)
26 :use-module (ice-9 regex))
27
acb0207f
MV
28;;; Dynamically link the glue code for accessing the readline library,
29;;; but only when it isn't already present.
b18c7b77 30
acb0207f
MV
31(if (not (feature? 'readline))
32 (dynamic-call "scm_init_readline" (dynamic-link "libguilereadline.so")))
b18c7b77
MV
33
34;;; MDJ 980513 <djurfeldt@nada.kth.se>:
35;;; There should probably be low-level support instead of this code.
36
37(define prompt "")
38(define prompt2 "")
39(define input-port (current-input-port))
40(define output-port (current-output-port))
41(define read-hook #f)
42
43(define (make-readline-port)
44 (let ((read-string "")
45 (string-index -1))
46 (letrec ((get-character
47 (lambda ()
48 (cond
49 ((eof-object? read-string)
50 read-string)
51 ((>= string-index (string-length read-string))
52 (begin
53 (set! string-index -1)
54 #\nl))
55 ((= string-index -1)
56 (begin
57 (set! read-string
58 (%readline (if (string? prompt)
59 prompt
60 (prompt))
61 input-port
62 output-port
63 read-hook))
64 (set! string-index 0)
65 (if (not (eof-object? read-string))
66 (begin
67 (or (string=? read-string "")
68 (begin
69 (add-history read-string)
70 (set! prompt prompt2)))
71 (get-character))
72 read-string)))
73 (else
74 (let ((res (string-ref read-string string-index)))
75 (set! string-index (+ 1 string-index))
76 res))))))
77 (make-soft-port
78 (vector write-char display #f get-character #f)
79 "rw"))))
80
81;;; We only create one readline port. There's no point in having
82;;; more, since they would all share the tty and history ---
83;;; everything except the prompt. And don't forget the
84;;; compile/load/run phase distinctions. Also, the readline library
85;;; isn't reentrant.
86(define the-readline-port #f)
87
88(define history-variable "GUILE_HISTORY")
89(define history-file (string-append (getenv "HOME") "/.guile_history"))
90
91(define-public readline-port
92 (let ((do (lambda (r/w)
93 (if (memq 'history-file (readline-options-interface))
94 (r/w (or (getenv history-variable)
95 history-file))))))
96 (lambda ()
97 (if (not the-readline-port)
98 (begin
99 (do read-history)
100 (set! the-readline-port (make-readline-port))
101 (add-hook! exit-hook (lambda () (do write-history)))))
102 the-readline-port)))
103
104;;; The user might try to use readline in his programs. It then
105;;; becomes very uncomfortable that the current-input-port is the
106;;; readline port...
107;;;
108;;; Here, we detect this situation and replace it with the
109;;; underlying port.
110;;;
111;;; %readline is the low-level readline procedure.
112
113(define-public (readline . args)
114 (let ((prompt prompt)
115 (inp input-port))
116 (cond ((not (null? args))
117 (set! prompt (car args))
118 (set! args (cdr args))
119 (cond ((not (null? args))
120 (set! inp (car args))
121 (set! args (cdr args))))))
122 (apply %readline
123 prompt
124 (if (eq? inp the-readline-port)
125 input-port
126 inp)
127 args)))
128
129(define-public (set-readline-prompt! p . rest)
130 (set! prompt p)
131 (if (not (null? rest))
132 (set! prompt2 (car rest))))
133
134(define-public (set-readline-input-port! p)
135 (set! input-port p))
136
137(define-public (set-readline-output-port! p)
138 (set! output-port p))
139
140(define-public (set-readline-read-hook! h)
141 (set! read-hook h))
142
143(define-public apropos-completion-function
144 (let ((completions '()))
145 (lambda (text cont?)
146 (if (not cont?)
147 (set! completions
148 (map symbol->string
149 (apropos-internal (string-append "^"
150 (regexp-quote text))))))
151 (if (null? completions)
152 #f
153 (let ((retval (car completions)))
154 (begin (set! completions (cdr completions))
155 retval))))))
156
157(set! *readline-completion-function* apropos-completion-function)
158
159(define-public (activate-readline)
160 (if (and (isatty? (current-input-port))
161 (not (and (module-defined? the-root-module
162 'use-emacs-interface)
163 use-emacs-interface)))
164 (let ((read-hook (lambda () (run-hook before-read-hook))))
165 (set-current-input-port (readline-port))
166 (set! repl-reader
167 (lambda (prompt)
168 (dynamic-wind
169 (lambda ()
170 (set-readline-prompt! prompt "... ")
171 (set-readline-read-hook! read-hook))
172 (lambda () (read))
173 (lambda ()
174 (set-readline-prompt! "" "")
6373eb6f
MD
175 (set-readline-read-hook! #f)))))
176 (set! (using-readline?) #t))))