emacs.d/clones/lisp/www.cliki.net/cl-readline.html
2022-10-07 15:47:14 +02:00

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]&gt; "</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&#32;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&amp;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&#32;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>