fix completion bug, added namespace-based completion (forgot to commit these files last time)

svn: r6137
This commit is contained in:
Eli Barzilay 2007-05-04 06:07:54 +00:00
parent 9bf2deaa49
commit 943967a4ce
2 changed files with 55 additions and 10 deletions

View File

@ -5,7 +5,7 @@
add-history add-history-bytes add-history add-history-bytes
set-completion-function!) set-completion-function!)
;; libtermcap maybe needed ;; libtermcap needed on some platforms
(define libtermcap (with-handlers ([exn:fail? void]) (ffi-lib "libtermcap"))) (define libtermcap (with-handlers ([exn:fail? void]) (ffi-lib "libtermcap")))
(define libreadline (ffi-lib "libreadline")) (define libreadline (ffi-lib "libreadline"))
@ -42,25 +42,29 @@
(define add-history-bytes (define add-history-bytes
(get-ffi-obj "add_history" libreadline (_fun _bytes -> _void))) (get-ffi-obj "add_history" libreadline (_fun _bytes -> _void)))
;; Simple completion: use this with a (string -> list-of string) function that ;; Simple completion: use this with a (string -> (list-of string)) function
;; returns the completions for a given string. (should clean up bytes/string) ;; that returns the completions for a given string (can be used with other
;; input string types too, depending on the `type' argument). Use #f to remove
;; a completion function that was previously set.
(define set-completion-function! (define set-completion-function!
(case-lambda (case-lambda
[(func) (set-completion-function! _string)] [(func) (set-completion-function! func _string)]
[(func type) [(func type)
(if func (if func
(set-ffi-obj! "rl_completion_entry_function" libreadline (set-ffi-obj! "rl_completion_entry_function" libreadline
(_fun type _int -> _pointer) (_fun type _int -> _pointer)
(completion-function func)) (completion-function func))
(set-ffi-obj! "rl_completion_entry_function" libreadline _pointer #f))])) (set-ffi-obj! "rl_completion_entry_function" libreadline _pointer #f))]))
(define (completion-function func) (define (completion-function func)
(let ([cur '()]) (let ([cur '()])
(define (complete str state) (define (complete str state)
(if (zero? state) (if (zero? state)
(begin (set! cur (func str)) (complete str 1)) (begin (set! cur (func str)) (complete #f 1))
(and (pair? cur) (and (pair? cur)
(begin0 (malloc (add1 (bytes-length (car cur))) (car cur) 'raw) (let* ([cur (begin0 (car cur) (set! cur (cdr cur)))]
(set! cur (cdr cur)))))) [cur (if (string? cur) (string->bytes/utf-8 cur) cur)])
(malloc (add1 (bytes-length cur)) cur 'raw)))))
complete)) complete))
(set-ffi-obj! "rl_readline_name" libreadline _bytes #"mzscheme") (set-ffi-obj! "rl_readline_name" libreadline _bytes #"mzscheme")

View File

@ -1,7 +1,10 @@
(module pread mzscheme (module pread mzscheme
(require (lib "readline.ss" "readline") (lib "file.ss")) (require (lib "readline.ss" "readline") (lib "file.ss")
(lib "list.ss") (lib "string.ss"))
;; --------------------------------------------------------------------------
;; Configuration
;; configuration
(define current-prompt (make-parameter #"> ")) (define current-prompt (make-parameter #"> "))
(define show-all-prompts (make-parameter #t)) (define show-all-prompts (make-parameter #t))
(define max-history (make-parameter 100)) (define max-history (make-parameter 100))
@ -10,6 +13,40 @@
(provide current-prompt show-all-prompts (provide current-prompt show-all-prompts
max-history keep-duplicates keep-blanks) max-history keep-duplicates keep-blanks)
;; --------------------------------------------------------------------------
;; Simple namespace-based completion
;; efficiently convert symbols to byte strings
(define symbol->bstring
(let ([t (make-hash-table 'weak)])
(lambda (sym)
(or (hash-table-get t sym #f)
(let ([bstr (string->bytes/utf-8 (symbol->string sym))])
(hash-table-put! t sym bstr)
bstr)))))
;; get a list of byte strings for current bindings, cache last result
(define get-namespace-bstrings
(let ([last-syms #f] [last-bstrs #f])
(lambda ()
(let ([syms (namespace-mapped-symbols)])
(unless (equal? syms last-syms)
(set! last-syms syms)
(set! last-bstrs (sort! (map symbol->bstring syms) bytes<?)))
last-bstrs))))
(define (namespace-completion pat)
(let* ([pat (if (string? pat) (string->bytes/utf-8 pat) pat)]
[pat (regexp-quote pat)]
[pat (regexp-replace* #px#"(\\w)\\b" pat #"\\1\\\\w*")]
[pat (byte-pregexp (bytes-append #"^" pat))])
(filter (lambda (bstr) (regexp-match pat bstr))
(get-namespace-bstrings))))
(set-completion-function! namespace-completion)
;; --------------------------------------------------------------------------
;; History management ;; History management
(define local-history (define local-history
@ -45,7 +82,8 @@
(let ([old (exit-handler)]) (let ([old (exit-handler)])
(lambda (v) (save-history) (old v)))) (lambda (v) (save-history) (old v))))
;; implement an input port that goes through readline ;; --------------------------------------------------------------------------
;; An input port that goes through readline
;; readline-prompt can be ;; readline-prompt can be
;; #f: no prompt (normal state), ;; #f: no prompt (normal state),
@ -106,6 +144,9 @@
(add1 left)]))]))) (add1 left)]))])))
(make-input-port 'readline reader #f close!))) (make-input-port 'readline reader #f close!)))
;; --------------------------------------------------------------------------
;; Reading functions
;; like read-syntax, but waits until valid input is ready ;; like read-syntax, but waits until valid input is ready
(define read-complete-syntax (define read-complete-syntax
(let ([leftovers '()] (let ([leftovers '()]