139 lines
No EOL
18 KiB
HTML
139 lines
No EOL
18 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<title>CLiki: CL-READLINE</title>
|
|
<link rel="alternate" type="application/atom+xml" title="ATOM feed of edits to current article"
|
|
href="https://www.cliki.net/site/feed/article.atom?title=CL-READLINE">
|
|
<link rel="stylesheet" href="static/css/style.css">
|
|
<link rel="stylesheet" href="static/css/colorize.css">
|
|
</head>
|
|
|
|
<body>
|
|
<span class="hidden">CLiki - CL-READLINE</span>
|
|
<div id="content"><div id="content-area"><div id="article-title">CL-READLINE</div><div id="article">Common
|
|
Lisp bindings to <a href="http://directory.fsf.org/wiki/Readline">GNU Readline
|
|
library</a>.<p>The Readline library provides a set of functions for use by applications
|
|
that allow users to edit command lines as they are typed in. Both Emacs
|
|
and vi editing modes are available. The Readline library includes
|
|
additional functions to maintain a list of previously-entered command
|
|
lines, to recall and perhaps reedit those lines, and perform csh-like
|
|
history expansion on previous commands.<p>These bindings provide Lispy interface to GNU Readline somewhat reducing
|
|
its hair. Some minor features are omitted, they may be added by
|
|
request. <a href="https://github.com/vindarel/cl-readline/issues">Open an
|
|
issue</a> if you have any propositions.<p>GitHub repository: <a href="https://github.com/vindarel/cl-readline">https://github.com/vindarel/cl-readline</a><p>You
|
|
can install it via Quicklisp:<p><div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen">ql:quickload <span class="string">"cl-readline"</span></span>)</span>
|
|
</span></div><p>I created this bindings because <a href="Linedit.html" class="internal">Linedit</a> didn't work for me. Also, <a href="Linedit.html" class="internal">Linedit</a> doesn't have decent documentation,
|
|
that README file describing 4 functions doesn't count. So I did my best
|
|
to write <a href="https://vindarel.github.io/cl-readline/">proper documentation</a> too.<p>Here is an example of cl-readline in action:<p><div class="code"><span class="nonparen"><span class="comment">;;; Load some systems and define a package...
|
|
</span>
|
|
<span class="paren1">(<span class="nonparen">asdf:load-system <span class="keyword">:alexandria</span></span>)</span>
|
|
<span class="paren1">(<span class="nonparen">asdf:load-system <span class="keyword">:cl-readline</span></span>)</span>
|
|
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defpackage.html" class="symbol"><i><span class="symbol">cl:defpackage</span></i></a> <span class="keyword">:example</span>
|
|
<span class="paren2">(<span class="nonparen"><span class="keyword">:use</span> <span class="keyword">#:common-lisp</span>
|
|
<span class="keyword">#:alexandria</span></span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><span class="keyword">:export</span> <span class="keyword">#:run-example</span></span>)</span></span>)</span>
|
|
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_in-package.html" class="symbol">in-package</a> <span class="keyword">:example</span></span>)</span>
|
|
|
|
<span class="comment">;;; Now let's define lists of verbs and fruits:
|
|
</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defparametercm_defvar.html" class="symbol"><i><span class="symbol">defvar</span></i></a> <span class="special">*verbs*</span> '<span class="paren2">(<span class="nonparen"><span class="string">"eat"</span> <span class="string">"get"</span> <span class="string">"throw"</span> <span class="string">"quit"</span></span>)</span></span>)</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defparametercm_defvar.html" class="symbol"><i><span class="symbol">defvar</span></i></a> <span class="special">*fruits*</span> '<span class="paren2">(<span class="nonparen"><span class="string">"banana"</span> <span class="string">"apple"</span> <span class="string">"orange"</span> <span class="string">"banana_two"</span></span>)</span></span>)</span>
|
|
|
|
<span class="comment">;;; Define and register function that does custom completion: if user enters
|
|
</span><span class="comment">;;; first word, it will be completed as a verb, second and later words will
|
|
</span><span class="comment">;;; be completed as fruits.
|
|
</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> custom-complete <span class="paren2">(<span class="nonparen">text start end</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/sym_declare.html" class="symbol">declare</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/dec_ignorecm_ignorable.html" class="symbol">ignore</a> end</span>)</span></span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_fletcm_scm_macrolet.html" class="symbol"><i><span class="symbol">labels</span></i></a> <span class="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen">common-prefix <span class="paren5">(<span class="nonparen">items</span>)</span>
|
|
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_subseq.html" class="symbol">subseq</a>
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> items</span>)</span> 0
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_positionc_ition-if-not.html" class="symbol">position</a>
|
|
<a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_mapccm_ma_istcm_mapcon.html" class="symbol">mapcar</a>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren3">(<span class="nonparen">i</span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_everycm_s_erycm_notany.html" class="symbol">every</a> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren5">(<span class="nonparen">x</span>)</span>
|
|
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_chareqcm__ar-not-lessp.html" class="symbol">char=</a> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_charcm_schar.html" class="symbol">char</a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> items</span>)</span> i</span>)</span>
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_charcm_schar.html" class="symbol">char</a> x i</span>)</span></span>)</span></span>)</span>
|
|
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cdr</a> items</span>)</span></span>)</span></span>)</span>
|
|
<span class="paren2">(<span class="nonparen">iota <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_reduce.html" class="symbol">reduce</a> #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_maxcm_min.html" class="symbol">min</a> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_mapccm_ma_istcm_mapcon.html" class="symbol">mapcar</a> #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_length.html" class="symbol">length</a> items</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
<span class="paren4">(<span class="nonparen">select-completions <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_list.html" class="symbol">list</a></span>)</span>
|
|
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_letcm_letst.html" class="symbol"><i><span class="symbol">let</span></i></a> <span class="paren6">(<span class="nonparen"><span class="paren1">(<span class="nonparen">els <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_removecm__elete-if-not.html" class="symbol">remove-if-not</a> <span class="paren3">(<span class="nonparen">curry #'starts-with-subseq text</span>)</span>
|
|
<a href="https://www.cliki.net/site/HyperSpec/Body/any_list.html" class="symbol">list</a></span>)</span></span>)</span></span>)</span>
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cdr</a> els</span>)</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> <span class="paren2">(<span class="nonparen">common-prefix els</span>)</span> els</span>)</span>
|
|
els</span>)</span></span>)</span></span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_zerop.html" class="symbol">zerop</a> start</span>)</span>
|
|
<span class="paren4">(<span class="nonparen">select-completions <span class="special">*verbs*</span></span>)</span>
|
|
<span class="paren4">(<span class="nonparen">select-completions <span class="special">*fruits*</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
|
|
<span class="paren1">(<span class="nonparen">rl:register-function <span class="keyword">:complete</span> #'custom-complete</span>)</span>
|
|
|
|
<span class="comment">;;; Let's also create a custom command and bind it to some key sequence so
|
|
</span><span class="comment">;;; user can invoke it. In this example user can automagically insert phrase
|
|
</span><span class="comment">;;; 'inserted text' pressing Control-o.
|
|
</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> print-some-text <span class="paren2">(<span class="nonparen">arg key</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/sym_declare.html" class="symbol">declare</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/dec_ignorecm_ignorable.html" class="symbol">ignore</a> arg key</span>)</span></span>)</span>
|
|
<span class="paren2">(<span class="nonparen">rl:insert-text <span class="string">"inserted text"</span></span>)</span></span>)</span>
|
|
|
|
<span class="paren1">(<span class="nonparen">rl:bind-keyseq <span class="string">"</span><span class="string">\\</span><span class="string">C-o"</span> #'print-some-text</span>)</span>
|
|
|
|
<span class="comment">;;; Let's write novelty-check, so if the actual line is equal to the most
|
|
</span><span class="comment">;;; recent history line it will not be added to the history.
|
|
</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> novelty-check <span class="paren2">(<span class="nonparen">x y</span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_stringeqc_ng-not-lessp.html" class="symbol">string/=</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_string-tr_g-right-trim.html" class="symbol">string-trim</a> <span class="string">" "</span> x</span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_string-tr_g-right-trim.html" class="symbol">string-trim</a> <span class="string">" "</span> y</span>)</span></span>)</span></span>)</span>
|
|
|
|
<span class="comment">;;; Finally, this is our main function. To exit from the loop, enter 'quit'.
|
|
</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> run-example <span class="paren2">(<span class="nonparen"></span>)</span>
|
|
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_docm_dost.html" class="symbol">do</a> <span class="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen">i 0 <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1+</a> i</span>)</span></span>)</span>
|
|
<span class="paren4">(<span class="nonparen">text <span class="string">""</span></span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_stringeqc_ng-not-lessp.html" class="symbol">string=</a> <span class="string">"quit"</span> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_string-tr_g-right-trim.html" class="symbol">string-trim</a> <span class="string">" "</span> text</span>)</span></span>)</span></span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> text
|
|
<span class="paren4">(<span class="nonparen">rl:readline <span class="keyword">:prompt</span> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_format.html" class="symbol">format</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a> <span class="string">"[~a]> "</span> i</span>)</span>
|
|
<span class="keyword">:add-history</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a>
|
|
<span class="keyword">:novelty-check</span> #'novelty-check</span>)</span></span>)</span></span>)</span></span>)</span>
|
|
</span></div><p><a href="cl-readline.html" class="internal">cl-readline</a> is written and maintained by <a href="Mark Karpov.html" class="internal">Mark Karpov</a>.<p>It's distributed under <a href="GNU.html" class="internal">GNU</a> <a href="GPL.html" class="internal">GPL</a>.<p><hr><p>Relevant topics: <a href="library.html" class="category">library</a>, <a href="text.html" class="category">text</a>, <a href="console.html" class="category">console</a></div></div>
|
|
<div id="footer" class="buttonbar"><ul><li><a href="CL-READLINE.html">Current version</a></li>
|
|
<li><a href="https://www.cliki.net/site/history?article=CL-READLINE">History</a></li>
|
|
<li><a href="https://www.cliki.net/site/backlinks?article=CL-READLINE">Backlinks</a></li><li><a href="https://www.cliki.net/site/edit-article?title=CL-READLINE&from-revision=3769786115">Edit</a></li><li><a href="https://www.cliki.net/site/edit-article?create=t">Create</a></li></ul></div>
|
|
</div>
|
|
<div id="header-buttons" class="buttonbar">
|
|
<ul>
|
|
<li><a href="https://www.cliki.net/">Home</a></li>
|
|
<li><a href="https://www.cliki.net/site/recent-changes">Recent Changes</a></li>
|
|
<li><a href="CLiki.html">About</a></li>
|
|
<li><a href="Text Formatting.html">Text Formatting</a></li>
|
|
<li><a href="https://www.cliki.net/site/tools">Tools</a></li>
|
|
</ul>
|
|
<div id="search">
|
|
<form action="https://www.cliki.net/site/search">
|
|
<label for="search_query" class="hidden">Search CLiki</label>
|
|
<input type="text" name="query" id="search_query" value="" />
|
|
<input type="submit" value="search" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div id="pageheader">
|
|
<div id="header">
|
|
<span id="logo">CLiki</span>
|
|
<span id="slogan">the common lisp wiki</span>
|
|
<div id="login"><form method="post" action="https://www.cliki.net/site/login">
|
|
<label for="login_name" class="hidden">Account name</label>
|
|
<input type="text" name="name" id="login_name" class="login_input" />
|
|
<label for= "login_password" class="hidden">Password</label>
|
|
<input type="password" name="password" id="login_password" class="login_input" />
|
|
<input type="submit" name="login" value="login" id="login_submit" /><br />
|
|
<div id="register"><a href="https://www.cliki.net/site/register">register</a></div>
|
|
<input type="submit" name="reset-pw" value="reset password" id="reset_pw" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body></html> |