1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-08 22:50:27 +02:00
guile/ice-9/readline.scm
1998-06-14 15:07:51 +00:00

137 lines
4.1 KiB
Scheme

;;;; readline.scm --- support functions for command-line editing
;;;;
;;;; Copyright (C) 1997 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
;;;; the Free Software Foundation; either version 2, or (at your option)
;;;; any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this software; see the file COPYING. If not, write to
;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;;;;
;;;; Contributed by Daniel Risacher <risacher@worldnet.att.net>.
;;;; Extensions based upon code by
;;;; Andrew Archibald <aarchiba@undergrad.math.uwaterloo.ca>.
(define-module (ice-9 readline)
:use-module (ice-9 session)
:use-module (ice-9 regex))
;;; MDJ 980513 <djurfeldt@nada.kth.se>:
;;; There should probably be low-level support instead of this code.
(define prompt "")
(define input-port (current-input-port))
(define output-port (current-output-port))
(define read-hook #f)
(define (make-readline-port)
(let ((read-string "")
(string-index -1))
(letrec ((get-character
(lambda ()
(cond
((eof-object? read-string)
read-string)
((>= string-index (string-length read-string))
(begin
(set! string-index -1)
#\nl))
((= string-index -1)
(begin
(set! read-string
(%readline (if (string? prompt)
prompt
(prompt))
input-port
output-port
read-hook))
(set! string-index 0)
(if (not (eof-object? read-string))
(begin
(or (string=? read-string "")
(add-history read-string))
(get-character))
read-string)))
(else
(let ((res (string-ref read-string string-index)))
(set! string-index (+ 1 string-index))
res))))))
(make-soft-port
(vector write-char display #f get-character #f)
"rw"))))
;;; We only create one readline port. There's no point in having
;;; more, since they would all share the tty and history ---
;;; everything except the prompt. And don't forget the
;;; compile/load/run phase distinctions. Also, the readline library
;;; isn't reentrant.
(define the-readline-port #f)
(define-public (readline-port)
(if (not the-readline-port)
(set! the-readline-port (make-readline-port)))
the-readline-port)
;;; The user might try to use readline in his programs. It then
;;; becomes very uncomfortable that the current-input-port is the
;;; readline port...
;;;
;;; Here, we detect this situation and replace it with the
;;; underlying port.
;;;
;;; %readline is the orginal readline procedure.
(if (not (defined? '%readline))
(begin
(define-public %readline readline)
(variable-set! (builtin-variable 'readline)
(lambda args
(let ((prompt prompt)
(inp input-port))
(cond ((not (null? args))
(set! prompt (car args))
(set! args (cdr args))
(cond ((not (null? args))
(set! inp (car args))
(set! args (cdr args))))))
(apply %readline
prompt
(if (eq? inp the-readline-port)
input-port
inp)
args))))))
(define-public (set-readline-prompt! p)
(set! prompt p))
(define-public (set-readline-input-port! p)
(set! input-port p))
(define-public (set-readline-output-port! p)
(set! output-port p))
(define-public (set-readline-read-hook! h)
(set! read-hook h))
(define-public apropos-completion-function
(let ((completions '()))
(lambda (text cont?)
(if (not cont?)
(set! completions
(map symbol->string
(apropos-internal (string-append "^"
(regexp-quote text))))))
(if (null? completions)
#f
(let ((retval (car completions)))
(begin (set! completions (cdr completions))
retval))))))
(set! *readline-completion-function* apropos-completion-function)