-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
example.lisp
104 lines (83 loc) · 3.17 KB
/
example.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
;;; Example for cl-readline.
;;;
;;; This file is to be run with
;;; sbcl --script example.lisp
;;;
(load #p"~/quicklisp/setup.lisp")
;;; Load some systems and define a package...
(asdf:load-system :str)
(asdf:load-system :cl-readline)
(cl:defpackage :example
(:use #:common-lisp
#:alexandria)
(:export #:run-example))
(in-package :example)
;;; Now let's define lists of verbs and fruits:
(defvar *verbs* '("eat" "get" "throw" "quit"))
(defvar *fruits* '("banana" "apple" "orange" "banana_two"))
;;; Define and register function that does custom completion: if user enters
;;; first word, it will be completed as a verb, second and later words will
;;; be completed as fruits.
(defun custom-complete (text start end)
(declare (ignore end))
(labels ((select-completions (list)
(let ((els (remove-if-not (lambda (it)
(str:starts-with? text it))
list)))
(if (cdr els)
(cons (str:prefix els) els)
els))))
(if (zerop start)
(select-completions *verbs*)
(select-completions *fruits*))))
#+test-readline-example
(assert (= 3 (length (custom-complete "ban" 2 2))))
(rl:register-function :complete #'custom-complete)
;;; Let's also create a custom command and bind it to some key sequence so
;;; user can invoke it. In this example user can automagically insert phrase
;;; 'inserted text' pressing Control-o.
(defun print-some-text (arg key)
(declare (ignore arg key))
(rl:insert-text "inserted text"))
(rl:bind-keyseq "\\C-o" #'print-some-text)
;;; Let's write novelty-check, so if the actual line is equal to the most
;;; recent history line it will not be added to the history.
(defun novelty-check (x y)
(string/= (string-trim " " x)
(string-trim " " y)))
;;; Finally, this is our main function. To exit from the loop, enter 'quit'.
(defun echo (text)
(format t "you said: ~a~&" text))
(defun insert-parens (count key)
"Insert two parenthesis and move the cursor in-between.
We bind this function to the ( key below."
;; count and key are mandatory arguments, sent by readline commands (not functions).
(declare (ignore count key))
(rl:insert-text "()")
(rl:backward-char))
(defun run-example ()
(rl:register-function :complete #'custom-complete)
(rl:bind-keyseq "\\C-o" #'print-some-text)
(rl:bind-keyseq "(" #'insert-parens)
(handler-case
(do ((i 0 (1+ i))
(text ""))
((or (string= "quit" (string-trim " " text))
;; C-d:
(string= "NIL" text)))
(setf text
(rl:readline :prompt (format nil "cl-readline ~a> " i)
:add-history t
:novelty-check #'novelty-check))
(echo text))
(#+sbcl sb-sys:interactive-interrupt
#+ccl ccl:interrupt-signal-condition
#+clisp system::simple-interrupt-condition
#+ecl ext:interactive-interrupt
#+allegro excl:interrupt-signal
() (progn
(format t "~&Bye!~&")
(uiop:quit)))
(error (c) (format t "Woops, an unknown error occured:~&~a~&" c))))
;; addition
(run-example)