Initial import
This commit is contained in:
248
third_party/editline/ChangeLog.md
vendored
Normal file
248
third_party/editline/ChangeLog.md
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
Change Log
|
||||
==========
|
||||
|
||||
All notable changes to the project are documented in this file.
|
||||
|
||||
|
||||
[1.16.1] - 2019-06-07
|
||||
---------------------
|
||||
|
||||
### Changes
|
||||
- Major updates to the `editline.3` man page
|
||||
- Cleanup of examples `cli.c` and `fileman.c`
|
||||
- Add example of hidden input prompt to `cli.c`
|
||||
|
||||
### Fixes
|
||||
- Fix #20: `configure --disable-eof` does not bite
|
||||
- Fix #23: Make Ctrl-L clear the screan instead of starting a new line
|
||||
Like Ctrl-D, which exits, Ctrl-L only clears the screen when the line
|
||||
is empty and the cursor is at the start of the line, otherwise Ctrl-L
|
||||
will redraw/refresh the current line.
|
||||
- Fix #24: Fix behavior when TTY is narrower than column width, by Will Dietz
|
||||
- Fix #25: Avoid continuously duplicate commands in history
|
||||
- Fix #31: Aborting i-search with Ctrl-C should not generate signal
|
||||
|
||||
|
||||
[1.16.0][] - 2018-09-16
|
||||
-----------------------
|
||||
|
||||
Event loop callback support.
|
||||
|
||||
### Changes
|
||||
- `rl_unintialize()`, new function to free all memory, by Claus Fischer
|
||||
- `rl_insert_text()`, new GNU Readline compat function
|
||||
- `rl_refresh_line()`, new GNU Readline compat function
|
||||
- `rl_callback_*()`, alternate interface to plain `readline()` for event
|
||||
loops. Modeled after the GNU Readline API
|
||||
- `rl_completion_entry_function`, and `rl_attempted_completion_function`
|
||||
are two new GNU Readline compat user hooks for the completion framework
|
||||
- `rl_completion_matches()` and `rl_filename_completion_function()`
|
||||
are two new GNU Readline compat functions
|
||||
- Add new example: `fileman.c` from GNU Readline to demonstrate the
|
||||
level of compatibility of the revamped completion framework
|
||||
- Add support for Ctrl-Right and Ctrl-Left, forward/backward word
|
||||
- Add .deb package to official release target
|
||||
|
||||
### Fixes
|
||||
- Fixed header guards, avoid using leading `__`
|
||||
- Spell check fixes
|
||||
- Remove duplicate code in history check
|
||||
- Use `NULL` instead of `0`, and `-1` instead of `NULL`, where applicable
|
||||
- Misc. minor Coverity Scan fixes
|
||||
- Misc. minor fixes to `testit.c` example code
|
||||
- Add `-Wextra` to std `CFLAGS`
|
||||
- Check `fclose()` return value in in `write_history()` and `read_history()`
|
||||
- Initialize global variables and reset to `NULL` on `free()`
|
||||
- Fix off-by-one in forward kill word, avoid deleting too much
|
||||
- Skip (or kill) leading whitespace when skipping (or killing) forwards
|
||||
|
||||
|
||||
[1.15.3][] - 2017-09-07
|
||||
-----------------------
|
||||
|
||||
Bug fix release.
|
||||
|
||||
### Changes
|
||||
- Refactor all enable/disable configure options, same problem as in #7
|
||||
|
||||
### Fixes
|
||||
- Fix #7: `--enable-termcap` configure option does not work. The script
|
||||
enabled termcap by default rather than the other way around.
|
||||
|
||||
Also, check for terminfo as well, when `--enable-termcap` is selected.
|
||||
|
||||
|
||||
[1.15.2][] - 2016-06-06
|
||||
-----------------------
|
||||
|
||||
Bug fixes and minor feature creep in `pkg-config` support.
|
||||
|
||||
### Changes
|
||||
- Prevent mangling of symbols when linking with C++. Patch courtesy of
|
||||
Jakub Pawlowski
|
||||
- Add `libeditline.pc` for `pkg-config`
|
||||
|
||||
### Fixes
|
||||
- Do not assume a termcap library exists, check for `tgetent()` in
|
||||
curses, ncurses, tinfo and termcap libraries
|
||||
- Call `tty_flush()` when user calls `rl_forced_update_display()`
|
||||
to prevent screen becoming garbled. Patch by Jakub Pawlowski
|
||||
|
||||
|
||||
[1.15.1][] - 2015-11-16
|
||||
-----------------------
|
||||
|
||||
Bug fixes only.
|
||||
|
||||
### Changes
|
||||
- Update README with origin of this version of editline
|
||||
|
||||
### Fixes
|
||||
- Fix build system, don't force automake v1.11, require at least v1.11
|
||||
- Fix build problem with examples using `--enable-termcap`
|
||||
|
||||
|
||||
[1.15.0][] - 2015-09-10
|
||||
-----------------------
|
||||
|
||||
### Changes
|
||||
- Add support for `--disable-eof` and `--disable-sigint` to disable
|
||||
default Ctrl-D and Ctrl-C behavior
|
||||
- Add support for `el_no_hist` to disable access to and auto-save of history
|
||||
- GNU readline compat functions for prompt handling and redisplay
|
||||
- Refactor: replace variables named 'new' with non-reserved word
|
||||
- Add support for [Travis-CI][], continuous integration with GitHub
|
||||
- Add support for [Coverity Scan][], the best static code analyzer,
|
||||
integrated with [Travis-CI][] -- scan runs for each push to master
|
||||
- Rename NEWS.md --> ChangeLog.md, with symlinks for <kbd>make install</kbd>
|
||||
- Attempt to align with http://keepachangelog.com/ for this file
|
||||
- Cleanup and improve Markdown syntax in [README.md][]
|
||||
- Add API and example to [README.md][], inspired by [libuEv][]
|
||||
- Removed generated files from version control. Use `./autogen.sh`
|
||||
to generate the `configure` script when working from GIT. This
|
||||
does not affect distributed tarballs
|
||||
|
||||
### Fixes
|
||||
- Fix issue #2, regression in Ctrl-D (EOF) behavior. Regression
|
||||
introduced in [1.14.1][]. Fixed by @TobyGoodwin
|
||||
- Fix memory leak in completion handler. Found by [Coverity Scan][].
|
||||
- Fix suspicious use of `sizeof(char **)`, same as `sizeof(char *)` but
|
||||
non-portable. Found by [Coverity Scan][]
|
||||
- Fix out-of-bounds access in user key binding routines
|
||||
Found by [Coverity Scan][].
|
||||
- Fix invisible example code in man page
|
||||
|
||||
|
||||
[1.14.2][] - 2014-09-14
|
||||
-----------------------
|
||||
|
||||
Bug fixes only.
|
||||
|
||||
### Fixes
|
||||
- Fix `el_no_echo` bug causing secrets to leak when disabling no-echo
|
||||
- Handle `EINTR` in syscalls better
|
||||
|
||||
|
||||
[1.14.1][] - 2014-09-14
|
||||
-----------------------
|
||||
|
||||
Minor fixes and additions.
|
||||
|
||||
### Changes
|
||||
- Don't print status message on `stderr` in key binding funcions
|
||||
- Export `el_del_char()`
|
||||
- Check for and return pending signals when detected
|
||||
- Allow custom key bindings ...
|
||||
|
||||
### Fixes
|
||||
- Bug fixes ...
|
||||
|
||||
|
||||
[1.14.0][] - 2010-08-10
|
||||
-----------------------
|
||||
|
||||
Major cleanups and further merges with Debian editline package.
|
||||
|
||||
### Changes
|
||||
- Merge in changes to `debian/` from `editline_1.12-6.debian.tar.gz`
|
||||
- Migrate to use libtool
|
||||
- Make `UNIQUE_HISTORY` configurable
|
||||
- Make scrollback history (`HIST_SIZE`) configurable
|
||||
- Configure options for toggling terminal bell and `SIGSTOP` (Ctrl-Z)
|
||||
- Configure option for using termcap to read/control terminal size
|
||||
- Rename Signal to `el_intr_pending`, from Festival speech-tools
|
||||
- Merge support for capitalizing words (`M-c`) from Festival
|
||||
speech-tools by Alan W Black <mailto:awb()cstr!ed!ac!uk>
|
||||
- Fallback backspace handling, in case `tgetstr("le")` fails
|
||||
|
||||
### Fixes
|
||||
- Cleanups and fixes thanks to the Sparse static code analysis tool
|
||||
- Merge `el_no_echo` patch from Festival speech-tools
|
||||
- Merge fixes from Heimdal project
|
||||
- Completely refactor `rl_complete()` and `rl_list_possib()` with
|
||||
fixes from the Heimdal project. Use `rl_set_complete_func()` and
|
||||
`rl_set_list_possib_func()`. Default completion callbacks are now
|
||||
available as a configure option `--enable-default-complete`
|
||||
- Memory leak fixes
|
||||
- Actually fix 8-bit handling by reverting old Debian patch
|
||||
- Merge patch to improve compatibility with GNU readline, thanks to
|
||||
Steve Tell from way back in 1997 and 1998
|
||||
|
||||
|
||||
[1.13.0][] - 2010-03-09
|
||||
-----------------------
|
||||
|
||||
Adaptations to Debian editline package.
|
||||
|
||||
### Changes
|
||||
- Major version number bump, adapt to Jim Studt's v1.12
|
||||
- Import `debian/` directory and adapt it to configure et al.
|
||||
- Change library name to libeditline to distinguish it from BSD libedit
|
||||
|
||||
|
||||
[0.3.0][] - 2009-02-08
|
||||
----------------------
|
||||
|
||||
### Changes
|
||||
- Support for ANSI arrow keys using <kbd>configure --enable-arrow-keys</kbd>
|
||||
|
||||
|
||||
[0.2.3][] - 2008-12-02
|
||||
----------------------
|
||||
|
||||
### Changes
|
||||
- Patches from Debian package merged
|
||||
- Support for custom command completion
|
||||
|
||||
|
||||
[0.1.0][] - 2008-06-07
|
||||
----------------------
|
||||
|
||||
### Changes
|
||||
- First version, forked from Minix current 2008-06-06
|
||||
|
||||
|
||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/1.16.0...HEAD
|
||||
[1.16.1]: https://github.com/troglobit/finit/compare/1.16.0...1.16.1
|
||||
[1.16.0]: https://github.com/troglobit/finit/compare/1.15.3...1.16.0
|
||||
[1.15.3]: https://github.com/troglobit/finit/compare/1.15.2...1.15.3
|
||||
[1.15.2]: https://github.com/troglobit/finit/compare/1.15.1...1.15.2
|
||||
[1.15.1]: https://github.com/troglobit/finit/compare/1.15.0...1.15.1
|
||||
[1.15.0]: https://github.com/troglobit/finit/compare/1.14.2...1.15.0
|
||||
[1.14.2]: https://github.com/troglobit/finit/compare/1.14.1...1.14.2
|
||||
[1.14.1]: https://github.com/troglobit/finit/compare/1.14.0...1.14.1
|
||||
[1.14.0]: https://github.com/troglobit/finit/compare/1.13.0...1.14.0
|
||||
[1.13.0]: https://github.com/troglobit/finit/compare/0.3.0...1.13.0
|
||||
[0.3.0]: https://github.com/troglobit/finit/compare/0.2.3...0.3.0
|
||||
[0.2.3]: https://github.com/troglobit/finit/compare/0.1.0...0.2.3
|
||||
[0.1.0]: https://github.com/troglobit/finit/compare/0.0.0...0.1.0
|
||||
[libuEv]: http://github.com/troglobit/libuev
|
||||
[Travis-CI]: https://travis-ci.org/troglobit/uftpd
|
||||
[Coverity Scan]: https://scan.coverity.com/projects/2947
|
||||
[README.md]: https://github.com/troglobit/editline/blob/master/README.md
|
||||
|
||||
<!--
|
||||
-- Local Variables:
|
||||
-- mode: markdown
|
||||
-- End:
|
||||
-->
|
||||
18
third_party/editline/LICENSE
vendored
Normal file
18
third_party/editline/LICENSE
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright 1992,1993 Simmule Turner and Rich Salz
|
||||
All rights reserved.
|
||||
|
||||
This software is not subject to any license of the American Telephone
|
||||
and Telegraph Company or of the Regents of the University of California.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose on
|
||||
any computer system, and to alter it and redistribute it freely, subject
|
||||
to the following restrictions:
|
||||
1. The authors are not responsible for the consequences of use of this
|
||||
software, no matter how awful, even if they arise from flaws in it.
|
||||
2. The origin of this software must not be misrepresented, either by
|
||||
explicit claim or by omission. Since few users ever read sources,
|
||||
credits must appear in the documentation.
|
||||
3. Altered versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software. Since few users
|
||||
ever read sources, credits must appear in the documentation.
|
||||
4. This notice may not be removed or altered.
|
||||
362
third_party/editline/complete.c
vendored
Normal file
362
third_party/editline/complete.c
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/editline/editline.h"
|
||||
#include "third_party/editline/internal.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
Cosmopolitan Linenoise (BSD-like license)\\n\
|
||||
Copyright 2019 Justine Alexandra Roberts Tunney\\n\
|
||||
Copyright 1992,1993 Simmule Turner and Rich Salz\\n\
|
||||
All rights reserved.\\n\
|
||||
\\n\
|
||||
This software is not subject to any license of the American Telephone\\n\
|
||||
and Telegraph Company or of the Regents of the University of California.\\n\
|
||||
\\n\
|
||||
Permission is granted to anyone to use this software for any purpose on\\n\
|
||||
any computer system, and to alter it and redistribute it freely, subject\\n\
|
||||
to the following restrictions:\\n\
|
||||
1. The authors are not responsible for the consequences of use of this\\n\
|
||||
software, no matter how awful, even if they arise from flaws in it.\\n\
|
||||
2. The origin of this software must not be misrepresented, either by\\n\
|
||||
explicit claim or by omission. Since few users ever read sources,\\n\
|
||||
credits must appear in the documentation.\\n\
|
||||
3. Altered versions must be plainly marked as such, and must not be\\n\
|
||||
misrepresented as being the original software. Since few users\\n\
|
||||
ever read sources, credits must appear in the documentation.\\n\
|
||||
4. This notice may not be removed or altered.\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
#define MAX_TOTAL_MATCHES (256 << sizeof(char *))
|
||||
|
||||
int rl_attempted_completion_over = 0;
|
||||
rl_completion_func_t *rl_attempted_completion_function = NULL;
|
||||
rl_compentry_func_t *rl_completion_entry_function = NULL;
|
||||
|
||||
/* Wrap strcmp() for qsort() -- weird construct to pass -Wcast-qual */
|
||||
static int compare(const void *p1, const void *p2) {
|
||||
char *const *v1 = (char *const *)p1;
|
||||
char *const *v2 = (char *const *)p2;
|
||||
return strcmp(*v1, *v2);
|
||||
}
|
||||
|
||||
/* Fill in *avp with an array of names that match file, up to its length.
|
||||
* Ignore . and .. . */
|
||||
static int FindMatches(char *dir, char *file, char ***avp) {
|
||||
char **av;
|
||||
char **word;
|
||||
char *p;
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
size_t ac;
|
||||
size_t len;
|
||||
size_t choices;
|
||||
size_t total;
|
||||
if ((dp = opendir(dir)) == NULL) return 0;
|
||||
av = NULL;
|
||||
ac = 0;
|
||||
len = strlen(file);
|
||||
choices = 0;
|
||||
total = 0;
|
||||
while ((ep = readdir(dp)) != NULL) {
|
||||
p = ep->d_name;
|
||||
if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
|
||||
continue;
|
||||
if (len && strncmp(p, file, len) != 0) continue;
|
||||
choices++;
|
||||
if ((total += strlen(p)) > MAX_TOTAL_MATCHES) {
|
||||
/* This is a bit too much. */
|
||||
while (ac > 0) free(av[--ac]);
|
||||
continue;
|
||||
}
|
||||
if ((ac % MEM_INC) == 0) {
|
||||
word = malloc(sizeof(char *) * (ac + MEM_INC));
|
||||
if (!word) {
|
||||
total = 0;
|
||||
break;
|
||||
}
|
||||
if (ac) {
|
||||
memcpy(word, av, ac * sizeof(char *));
|
||||
free(av);
|
||||
}
|
||||
*avp = av = word;
|
||||
}
|
||||
if ((av[ac] = strdup(p)) == NULL) {
|
||||
if (ac == 0) free(av);
|
||||
total = 0;
|
||||
break;
|
||||
}
|
||||
ac++;
|
||||
}
|
||||
/* Clean up and return. */
|
||||
closedir(dp);
|
||||
if (total > MAX_TOTAL_MATCHES) {
|
||||
char many[sizeof(total) * 3];
|
||||
p = many + sizeof(many);
|
||||
*--p = '\0';
|
||||
while (choices > 0) {
|
||||
*--p = '0' + choices % 10;
|
||||
choices /= 10;
|
||||
}
|
||||
while (p > many + sizeof(many) - 8) *--p = ' ';
|
||||
if ((p = strdup(p)) != NULL) av[ac++] = p;
|
||||
if ((p = strdup("choices")) != NULL) av[ac++] = p;
|
||||
} else {
|
||||
if (ac) qsort(av, ac, sizeof(char *), compare);
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
/* Split a pathname into allocated directory and trailing filename parts. */
|
||||
static int SplitPath(const char *path, char **dirpart, char **filepart) {
|
||||
static char DOT[] = ".";
|
||||
char *dpart;
|
||||
char *fpart;
|
||||
if ((fpart = strrchr(path, '/')) == NULL) {
|
||||
if ((dpart = strdup(DOT)) == NULL) return -1;
|
||||
if ((fpart = strdup(path)) == NULL) {
|
||||
free(dpart);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if ((dpart = strdup(path)) == NULL) return -1;
|
||||
dpart[fpart - path + 1] = '\0';
|
||||
if ((fpart = strdup(fpart + 1)) == NULL) {
|
||||
free(dpart);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*dirpart = dpart;
|
||||
*filepart = fpart;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rl_complete_func_t *el_complete_func = NULL;
|
||||
|
||||
/* For compatibility with the Heimdal project. */
|
||||
rl_complete_func_t *rl_set_complete_func(rl_complete_func_t *func) {
|
||||
rl_complete_func_t *old = el_complete_func;
|
||||
el_complete_func = func;
|
||||
return old;
|
||||
}
|
||||
|
||||
/* Attempt to complete the pathname, returning an allocated copy.
|
||||
* Fill in *match if we completed it, or set it to 0 if ambiguous. */
|
||||
char *el_filename_complete(char *pathname, int *match) {
|
||||
char **av;
|
||||
char *dir;
|
||||
char *file;
|
||||
char *path;
|
||||
char *p;
|
||||
size_t ac;
|
||||
size_t end;
|
||||
size_t i;
|
||||
size_t j;
|
||||
size_t len;
|
||||
if (SplitPath((const char *)pathname, &dir, &file) < 0) return NULL;
|
||||
if ((ac = FindMatches(dir, file, &av)) == 0) {
|
||||
free(dir);
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
p = NULL;
|
||||
len = strlen(file);
|
||||
if (ac == 1) {
|
||||
/* Exactly one match -- finish it off. */
|
||||
*match = 1;
|
||||
j = strlen(av[0]) - len + 2;
|
||||
p = malloc(sizeof(char) * (j + 1));
|
||||
if (p) {
|
||||
memcpy(p, av[0] + len, j);
|
||||
len = strlen(dir) + strlen(av[0]) + 2;
|
||||
path = malloc(sizeof(char) * len);
|
||||
if (path) {
|
||||
snprintf(path, len, "%s/%s", dir, av[0]);
|
||||
rl_add_slash(path, p);
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*match = 0;
|
||||
if (len) {
|
||||
/* Find largest matching substring. */
|
||||
for (i = len, end = strlen(av[0]); i < end; i++) {
|
||||
for (j = 1; j < ac; j++) {
|
||||
if (av[0][i] != av[j][i]) goto breakout;
|
||||
}
|
||||
}
|
||||
breakout:
|
||||
if (i > len) {
|
||||
j = i - len + 1;
|
||||
p = malloc(sizeof(char) * j);
|
||||
if (p) {
|
||||
memcpy(p, av[0] + len, j);
|
||||
p[j - 1] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Clean up and return. */
|
||||
free(dir);
|
||||
free(file);
|
||||
for (i = 0; i < ac; i++) free(av[i]);
|
||||
free(av);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *rl_filename_completion_function(const char *text, int state) {
|
||||
char *dir;
|
||||
char *file;
|
||||
static char **av;
|
||||
static size_t i, ac;
|
||||
if (!state) {
|
||||
if (SplitPath(text, &dir, &file) < 0) return NULL;
|
||||
ac = FindMatches(dir, file, &av);
|
||||
free(dir);
|
||||
free(file);
|
||||
if (!ac) return NULL;
|
||||
i = 0;
|
||||
}
|
||||
if (i < ac) return av[i++];
|
||||
do {
|
||||
free(av[--i]);
|
||||
} while (i > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Similar to el_find_word(), but used by GNU Readline API */
|
||||
static char *rl_find_token(size_t *len) {
|
||||
char *ptr;
|
||||
int pos;
|
||||
for (pos = rl_point; pos < rl_end; pos++) {
|
||||
if (isspace(rl_line_buffer[pos])) {
|
||||
if (pos > 0) pos--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr = &rl_line_buffer[pos];
|
||||
while (pos >= 0 && !isspace(rl_line_buffer[pos])) {
|
||||
if (pos == 0) break;
|
||||
pos--;
|
||||
}
|
||||
if (ptr != &rl_line_buffer[pos]) {
|
||||
*len = (size_t)(ptr - &rl_line_buffer[pos]);
|
||||
return &rl_line_buffer[pos];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* "uses an application-supplied generator function to generate the list
|
||||
* of possible matches, and then returns the array of these matches. The
|
||||
* caller should place the address of its generator function in
|
||||
* rl_completion_entry_function"
|
||||
*/
|
||||
char **rl_completion_matches(const char *token,
|
||||
rl_compentry_func_t *generator) {
|
||||
int state = 0, num = 0;
|
||||
char **array, *entry;
|
||||
if (!generator) {
|
||||
generator = rl_completion_entry_function;
|
||||
if (!generator) generator = rl_filename_completion_function;
|
||||
}
|
||||
if (!generator) return NULL;
|
||||
array = malloc(512 * sizeof(char *));
|
||||
if (!array) return NULL;
|
||||
while (num < 511 && (entry = generator(token, state))) {
|
||||
state = 1;
|
||||
array[num++] = entry;
|
||||
}
|
||||
array[num] = NULL;
|
||||
if (!num) {
|
||||
free(array);
|
||||
return NULL;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
static char *complete(char *token, int *match) {
|
||||
size_t len = 0;
|
||||
char *word, **words = NULL;
|
||||
int start, end;
|
||||
word = rl_find_token(&len);
|
||||
if (!word) goto fallback;
|
||||
start = word - rl_line_buffer;
|
||||
end = start + len;
|
||||
word = strndup(word, len);
|
||||
if (!word) goto fallback;
|
||||
rl_attempted_completion_over = 0;
|
||||
words = rl_attempted_completion_function(word, start, end);
|
||||
if (!rl_attempted_completion_over && !words)
|
||||
words = rl_completion_matches(word, NULL);
|
||||
if (words) {
|
||||
int i = 0;
|
||||
free(word);
|
||||
word = NULL;
|
||||
if (words[0]) word = strdup(words[0] + len);
|
||||
while (words[i]) free(words[i++]);
|
||||
free(words);
|
||||
if (word) return word;
|
||||
}
|
||||
fallback:
|
||||
return el_filename_complete(token, match);
|
||||
}
|
||||
|
||||
/*
|
||||
* First check for editline specific custom completion function, then
|
||||
* for any GNU Readline compat, then fallback to filename completion.
|
||||
*/
|
||||
char *rl_complete(char *token, int *match) {
|
||||
if (el_complete_func) return el_complete_func(token, match);
|
||||
if (rl_attempted_completion_function) return complete(token, match);
|
||||
return el_filename_complete(token, match);
|
||||
}
|
||||
|
||||
static rl_list_possib_func_t *el_list_possib_func = NULL;
|
||||
|
||||
/* For compatibility with the Heimdal project. */
|
||||
rl_list_possib_func_t *rl_set_list_possib_func(rl_list_possib_func_t *func) {
|
||||
rl_list_possib_func_t *old = el_list_possib_func;
|
||||
el_list_possib_func = func;
|
||||
return old;
|
||||
}
|
||||
|
||||
/* Default possible completions. */
|
||||
int el_filename_list_possib(char *pathname, char ***av) {
|
||||
char *dir;
|
||||
char *file;
|
||||
int ac;
|
||||
if (SplitPath(pathname, &dir, &file) < 0) return 0;
|
||||
ac = FindMatches(dir, file, av);
|
||||
free(dir);
|
||||
free(file);
|
||||
return ac;
|
||||
}
|
||||
|
||||
/* Return all possible completions. */
|
||||
int rl_list_possib(char *token, char ***av) {
|
||||
if (el_list_possib_func) return el_list_possib_func(token, av);
|
||||
return el_filename_list_possib(token, av);
|
||||
}
|
||||
274
third_party/editline/editline.3
vendored
Normal file
274
third_party/editline/editline.3
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
.Dd April 27, 2019
|
||||
.Dt "THIRD_PARTY_EDITLINE" 30 "Cosmopolitan Field Manual"
|
||||
.Os COSMOPOLITAN
|
||||
.Sh NAME
|
||||
.Nm "THIRD_PARTY_EDITLINE"
|
||||
.Nd command-line editing library with history
|
||||
.Sh SYNOPSIS
|
||||
.Pp
|
||||
.Sy #include "third_party/editline/editline.h"
|
||||
.Pp
|
||||
.Fn "char *readline" "const char *prompt"
|
||||
.Fn "void add_history" "const char *line"
|
||||
.Fn "int read_history" "const char *filename"
|
||||
.Fn "int write_history" "const char *filename"
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a library that provides n line-editing interface with history. It
|
||||
is intended to be functionally equivalent with the
|
||||
.Nm readline
|
||||
library provided by the Free Software Foundation, but much smaller. The
|
||||
bulk of this manual page describes the basic user interface. More APIs,
|
||||
both native and for
|
||||
.Nm readline
|
||||
compatibility ,
|
||||
are also available. See the
|
||||
.Cm editline.h
|
||||
header file for details.
|
||||
.Pp
|
||||
The
|
||||
.Fn readline
|
||||
function displays the given
|
||||
.Fa prompt
|
||||
on stdout, waits for user input on stdin and then returns a line of text
|
||||
with the trailing newline removed. The data is returned in a buffer
|
||||
allocated with
|
||||
.Xr malloc 3 ,
|
||||
so the space should be released with
|
||||
.Xr free 3
|
||||
when the calling program is done with it.
|
||||
.Pp
|
||||
Each line returned is automatically saved in the internal history list,
|
||||
unless it happens to be equal to the previous line. This is
|
||||
configurable if you are building editline from source, i.e. if you would
|
||||
rather like to call
|
||||
.Fn add_history
|
||||
manually.
|
||||
.Pp
|
||||
The
|
||||
.Fn read_history
|
||||
and
|
||||
.Fn write_history
|
||||
functions can be used to load and store the history of your application.
|
||||
.Em Note:
|
||||
these APIs do not do any tilde or environment variable expansion of the
|
||||
given filename.
|
||||
.Ss User Interface
|
||||
A program that uses this library provides a simple emacs-like editing
|
||||
interface to its users. A line may be edited before it is sent to the
|
||||
calling program by typing either control characters or escape sequences.
|
||||
A control character, shown as a caret followed by a letter, is typed by
|
||||
holding down the control key while the letter is typed. For example,
|
||||
.Cm ^A
|
||||
is a control-A. An escape sequence is entered by typing the escape key
|
||||
followed by one or more characters. The escape key is abbreviated as
|
||||
.Cm ESC .
|
||||
Note that unlike control keys, case matters in escape sequences;
|
||||
.Cm ESC F
|
||||
is not the same as
|
||||
.Cm ESC f .
|
||||
.Pp
|
||||
An editing command may be typed anywhere on the line, not just at the
|
||||
beginning. In addition, a return may also be typed anywhere on the
|
||||
line, not just at the end.
|
||||
.Pp
|
||||
Most editing commands may be given a repeat count,
|
||||
.Ar n ,
|
||||
where
|
||||
.Ar n
|
||||
is a number. To enter a repeat count, type the escape key, the number,
|
||||
and then the command to execute. For example,
|
||||
.Cm ESC 4 ^f
|
||||
moves forward four characters. If a command may be given a repeat count
|
||||
then the text
|
||||
.Cm [n]
|
||||
is given at the end of its description.
|
||||
.Pp
|
||||
The following control characters are accepted:
|
||||
.Pp
|
||||
.Bl -tag -width "ESC DEL " -compact
|
||||
.It ^A
|
||||
Move to the beginning of the line
|
||||
.It ^B
|
||||
Move left (backwards) [n]
|
||||
.It ^D
|
||||
Delete character [n]
|
||||
.It ^E
|
||||
Move to end of line
|
||||
.It ^F
|
||||
Move right (forwards) [n]
|
||||
.It ^G
|
||||
Ring the bell
|
||||
.It ^H
|
||||
Delete character before cursor (backspace key) [n]
|
||||
.It ^I
|
||||
Complete filename (tab key); see below
|
||||
.It ^J
|
||||
Done with line (return key)
|
||||
.It ^K
|
||||
Kill to end of line (or column [n])
|
||||
.It ^L
|
||||
Redisplay line
|
||||
.It ^M
|
||||
Done with line (alternate return key)
|
||||
.It ^N
|
||||
Get next line from history [n]
|
||||
.It ^P
|
||||
Get previous line from history [n]
|
||||
.It ^R
|
||||
Search backward (forward if [n]) through history for text; prefixing the
|
||||
string with a caret (^) forces it to match only at the beginning of a
|
||||
history line
|
||||
.It ^T
|
||||
Transpose characters
|
||||
.It ^V
|
||||
Insert next character, even if it is an edit command
|
||||
.It ^W
|
||||
Wipe to the mark
|
||||
.It ^X^X
|
||||
Exchange current location and mark
|
||||
.It ^Y
|
||||
Yank back last killed text
|
||||
.It ^[
|
||||
Start an escape sequence (escape key)
|
||||
.It ^]c
|
||||
Move forward to next character
|
||||
.Cm c
|
||||
.It ^?
|
||||
Delete character before cursor (delete key) [n]
|
||||
.Ed
|
||||
.Pp
|
||||
The following escape sequences are provided:
|
||||
.Pp
|
||||
.Bl -tag -width "ESC DEL " -compact
|
||||
.It ESC ^H
|
||||
Delete previous word (backspace key) [n]
|
||||
.It ESC DEL
|
||||
Delete previous word (delete key) [n]
|
||||
.It ESC SP
|
||||
Set the mark (space key); see ^X^X and ^Y above
|
||||
.It ESC\ .
|
||||
Get the last (or [n]'th) word from previous line
|
||||
.It ESC\ ?
|
||||
Show possible completions; see below
|
||||
.It ESC <
|
||||
Move to start of history
|
||||
.It ESC >
|
||||
Move to end of history
|
||||
.It ESC b
|
||||
Move backward a word [n]
|
||||
.It ESC d
|
||||
Delete word under cursor [n]
|
||||
.It ESC f
|
||||
Move forward a word [n]
|
||||
.It ESC l
|
||||
Make word lowercase [n]
|
||||
.It ESC m
|
||||
Toggle if 8bit chars display normally or with an
|
||||
.Ar M-
|
||||
prefix
|
||||
.It ESC u
|
||||
Make word uppercase [n]
|
||||
.It ESC y
|
||||
Yank back last killed text
|
||||
.It ESC v
|
||||
Show library version
|
||||
.It ESC w
|
||||
Make area up to mark yankable
|
||||
.It ESC nn
|
||||
Set repeat count to the number nn
|
||||
.It ESC C
|
||||
Read from environment variable
|
||||
.Ar $C ,
|
||||
where
|
||||
.Ar C
|
||||
is an uppercase letter
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
library has a small macro facility. If you type the escape key followed
|
||||
by an uppercase letter,
|
||||
.Ar C ,
|
||||
then the contents of the environment variable
|
||||
.Ar $C
|
||||
are read in as if you had typed them at the keyboard. For example, if
|
||||
the variable
|
||||
.Ar $L
|
||||
contains the following:
|
||||
.Pp
|
||||
.Dl ^A^Kecho '^V^[[H^V^[[2J'^M
|
||||
.Pp
|
||||
Then typing
|
||||
.Cm ESC L
|
||||
will move to the beginning of the line, kill the entire line, enter the
|
||||
echo command needed to clear the terminal (if your terminal is like a
|
||||
VT-100), and send the line back to the shell.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
library also does filename completion. Suppose the root directory has
|
||||
the following files in it:
|
||||
.Pp
|
||||
.Dl bin vmunix
|
||||
.Dl core vmunix.old
|
||||
.Pp
|
||||
If you type
|
||||
.Cm rm /v
|
||||
and then the tab key,
|
||||
.Nm
|
||||
will then finish off as much of the name as possible by adding
|
||||
.Ar munix .
|
||||
Because the name is not unique, it will then beep. If you type the
|
||||
escape key and a question mark, it will display the two choices. If you
|
||||
then type a period and a tab, the library will finish off the filename
|
||||
for you:
|
||||
.Pp
|
||||
.Bd -ragged -offset indent
|
||||
rm /v[TAB]
|
||||
.Em munix
|
||||
\&.[TAB]
|
||||
.Em old
|
||||
.Ed
|
||||
.Pp
|
||||
The tab key is shown by [TAB] and the automatically-entered text
|
||||
is shown in italics, or underline.
|
||||
.Sh USAGE
|
||||
To include
|
||||
.Nm
|
||||
in your program, call it as you do any other function and link your
|
||||
program with
|
||||
.Ar -leditline .
|
||||
.Ss Example
|
||||
The following brief example lets you enter a line and edit it, then displays it.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <editline.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while ((p = readline("CLI> "))) {
|
||||
puts(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
The original editline library was posted to comp.sources.unix newsgroup
|
||||
by created by Simmule R. Turner and Rich Salz in 1992. It now exists in
|
||||
several forks: Debian, Minix, Heimdal, Festival speech tools, Mozilla,
|
||||
Google Gadgets for Linux, and many other places. The original manual
|
||||
page was made by David W. Sanderson.
|
||||
.Pp
|
||||
This version was originally based on the Minix 2 sources, but has since
|
||||
evolved to include patches from all relevant forks. It is currently
|
||||
maintained by Joachim Nilsson at GitHub,
|
||||
.Aq http://github.com/troglobit/editline
|
||||
.Sh BUGS
|
||||
Does not handle multiple lines well.
|
||||
1557
third_party/editline/editline.c
vendored
Normal file
1557
third_party/editline/editline.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
91
third_party/editline/editline.h
vendored
Normal file
91
third_party/editline/editline.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef COSMOPOLITAN_THIRD_PARTY_EDITLINE_EDITLINE_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_EDITLINE_EDITLINE_H_
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
#define CTL(x) ((x)&0x1F)
|
||||
#define ISCTL(x) ((x) && (x) < ' ')
|
||||
#define UNCTL(x) ((x) + 64)
|
||||
#define META(x) ((x) | 0x80)
|
||||
#define ISMETA(x) ((x)&0x80)
|
||||
#define UNMETA(x) ((x)&0x7F)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef enum {
|
||||
CSdone = 0, /* OK */
|
||||
CSeof, /* Error, or EOF */
|
||||
CSmove,
|
||||
CSdispatch,
|
||||
CSstay,
|
||||
CSsignal
|
||||
} el_status_t;
|
||||
|
||||
typedef int rl_list_possib_func_t(char *, char ***);
|
||||
typedef el_status_t el_keymap_func_t(void);
|
||||
typedef int rl_hook_func_t(void);
|
||||
typedef int rl_getc_func_t(void);
|
||||
typedef void rl_voidfunc_t(void);
|
||||
typedef void rl_vintfunc_t(int);
|
||||
typedef void rl_vcpfunc_t(char *);
|
||||
compatfn typedef char *rl_complete_func_t(char *, int *);
|
||||
compatfn typedef char *rl_compentry_func_t(const char *, int);
|
||||
compatfn typedef char **rl_completion_func_t(const char *, int, int);
|
||||
|
||||
extern int rl_point;
|
||||
extern int rl_mark;
|
||||
extern int rl_end;
|
||||
extern int rl_inhibit_complete;
|
||||
extern char *rl_line_buffer;
|
||||
extern const char *rl_readline_name;
|
||||
extern FILE *rl_instream; /* The stdio stream from which input is read. Defaults
|
||||
to stdin if NULL - Not supported yet! */
|
||||
extern FILE *rl_outstream; /* The stdio stream to which output is flushed.
|
||||
Defaults to stdout if NULL - Not supported yet! */
|
||||
extern int el_no_echo; /* E.g under emacs, don't echo except prompt */
|
||||
extern int el_no_hist; /* Disable auto-save of and access to history -- e.g. for
|
||||
password prompts or wizards */
|
||||
extern int el_hist_size; /* size of history scrollback buffer, default: 15 */
|
||||
extern int rl_meta_chars; /* Display 8-bit chars "as-is" or as `M-x'? Toggle
|
||||
with M-m. (Default:0 - "as-is") */
|
||||
extern rl_completion_func_t *rl_attempted_completion_function;
|
||||
|
||||
char **rl_completion_matches(const char *, rl_compentry_func_t *);
|
||||
char *el_find_word(void);
|
||||
char *readline(const char *);
|
||||
char *rl_complete(char *, int *);
|
||||
char *rl_filename_completion_function(const char *, int);
|
||||
const char *el_next_hist(void);
|
||||
const char *el_prev_hist(void);
|
||||
el_status_t el_bind_key(int, el_keymap_func_t);
|
||||
el_status_t el_bind_key_in_metamap(int, el_keymap_func_t);
|
||||
el_status_t el_del_char(void);
|
||||
el_status_t el_ring_bell(void);
|
||||
int read_history(const char *);
|
||||
int rl_getc(void);
|
||||
int rl_insert_text(const char *);
|
||||
int rl_list_possib(char *, char ***);
|
||||
int rl_refresh_line(int, int);
|
||||
int write_history(const char *);
|
||||
rl_complete_func_t *rl_set_complete_func(rl_complete_func_t *);
|
||||
rl_getc_func_t *rl_set_getc_func(rl_getc_func_t *);
|
||||
rl_list_possib_func_t *rl_set_list_possib_func(rl_list_possib_func_t *);
|
||||
void add_history(const char *);
|
||||
void el_print_columns(int, char **);
|
||||
void rl_callback_handler_install(const char *, rl_vcpfunc_t *);
|
||||
void rl_callback_handler_remove(void);
|
||||
void rl_callback_read_char(void);
|
||||
void rl_clear_message(void);
|
||||
void rl_deprep_terminal(void);
|
||||
void rl_forced_update_display(void);
|
||||
void rl_initialize(void);
|
||||
void rl_prep_terminal(int);
|
||||
void rl_reset_terminal(const char *);
|
||||
void rl_restore_prompt(void);
|
||||
void rl_save_prompt(void);
|
||||
void rl_set_prompt(const char *);
|
||||
void rl_uninitialize(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_EDITLINE_EDITLINE_H_ */
|
||||
57
third_party/editline/editline.mk
vendored
Normal file
57
third_party/editline/editline.mk
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += THIRD_PARTY_EDITLINE
|
||||
|
||||
THIRD_PARTY_EDITLINE_ARTIFACTS += THIRD_PARTY_EDITLINE_A
|
||||
THIRD_PARTY_EDITLINE = $(THIRD_PARTY_EDITLINE_A_DEPS) $(THIRD_PARTY_EDITLINE_A)
|
||||
THIRD_PARTY_EDITLINE_A = o/$(MODE)/third_party/editline/editline.a
|
||||
THIRD_PARTY_EDITLINE_A_FILES := $(wildcard third_party/editline/*)
|
||||
THIRD_PARTY_EDITLINE_A_HDRS = $(filter %.h,$(THIRD_PARTY_EDITLINE_A_FILES))
|
||||
THIRD_PARTY_EDITLINE_A_SRCS = $(filter %.c,$(THIRD_PARTY_EDITLINE_A_FILES))
|
||||
|
||||
THIRD_PARTY_EDITLINE_A_OBJS = \
|
||||
$(THIRD_PARTY_EDITLINE_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(THIRD_PARTY_EDITLINE_A_SRCS:%.c=o/$(MODE)/%.o)
|
||||
|
||||
THIRD_PARTY_EDITLINE_A_CHECKS = \
|
||||
$(THIRD_PARTY_EDITLINE_A).pkg
|
||||
|
||||
THIRD_PARTY_EDITLINE_A_DIRECTDEPS = \
|
||||
LIBC_ALG \
|
||||
LIBC_CALLS \
|
||||
LIBC_CALLS_HEFTY \
|
||||
LIBC_FMT \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV
|
||||
|
||||
THIRD_PARTY_EDITLINE_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(THIRD_PARTY_EDITLINE_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(THIRD_PARTY_EDITLINE_A): \
|
||||
third_party/editline/ \
|
||||
$(THIRD_PARTY_EDITLINE_A).pkg \
|
||||
$(THIRD_PARTY_EDITLINE_A_OBJS)
|
||||
|
||||
$(THIRD_PARTY_EDITLINE_A).pkg: \
|
||||
$(THIRD_PARTY_EDITLINE_A_OBJS) \
|
||||
$(foreach x,$(THIRD_PARTY_EDITLINE_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
THIRD_PARTY_EDITLINE_LIBS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_EDITLINE_SRCS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_EDITLINE_HDRS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_EDITLINE_BINS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)_BINS))
|
||||
THIRD_PARTY_EDITLINE_CHECKS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_EDITLINE_OBJS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)_OBJS))
|
||||
THIRD_PARTY_EDITLINE_TESTS = $(foreach x,$(THIRD_PARTY_EDITLINE_ARTIFACTS),$($(x)_TESTS))
|
||||
$(THIRD_PARTY_EDITLINE_OBJS): $(BUILD_FILES) third_party/editline/editline.mk
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/editline
|
||||
o/$(MODE)/third_party/editline: \
|
||||
$(THIRD_PARTY_EDITLINE) \
|
||||
$(THIRD_PARTY_EDITLINE_CHECKS)
|
||||
21
third_party/editline/internal.h
vendored
Normal file
21
third_party/editline/internal.h
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef COSMOPOLITAN_THIRD_PARTY_EDITLINE_INTERNAL_H_
|
||||
#define COSMOPOLITAN_THIRD_PARTY_EDITLINE_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define MEM_INC 64
|
||||
#define SCREEN_INC 256
|
||||
|
||||
extern int rl_eof;
|
||||
extern int rl_erase;
|
||||
extern int rl_intr;
|
||||
extern int rl_kill;
|
||||
extern int rl_quit;
|
||||
extern int rl_susp;
|
||||
|
||||
void rl_ttyset(int);
|
||||
void rl_add_slash(char *, char *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_THIRD_PARTY_EDITLINE_INTERNAL_H_ */
|
||||
112
third_party/editline/sysunix.c
vendored
Normal file
112
third_party/editline/sysunix.c
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "third_party/editline/editline.h"
|
||||
#include "third_party/editline/internal.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
Cosmopolitan Linenoise (BSD-like license)\\n\
|
||||
Copyright 2019 Justine Alexandra Roberts Tunney\\n\
|
||||
Copyright 1992,1993 Simmule Turner and Rich Salz\\n\
|
||||
All rights reserved.\\n\
|
||||
\\n\
|
||||
This software is not subject to any license of the American Telephone\\n\
|
||||
and Telegraph Company or of the Regents of the University of California.\\n\
|
||||
\\n\
|
||||
Permission is granted to anyone to use this software for any purpose on\\n\
|
||||
any computer system, and to alter it and redistribute it freely, subject\\n\
|
||||
to the following restrictions:\\n\
|
||||
1. The authors are not responsible for the consequences of use of this\\n\
|
||||
software, no matter how awful, even if they arise from flaws in it.\\n\
|
||||
2. The origin of this software must not be misrepresented, either by\\n\
|
||||
explicit claim or by omission. Since few users ever read sources,\\n\
|
||||
credits must appear in the documentation.\\n\
|
||||
3. Altered versions must be plainly marked as such, and must not be\\n\
|
||||
misrepresented as being the original software. Since few users\\n\
|
||||
ever read sources, credits must appear in the documentation.\\n\
|
||||
4. This notice may not be removed or altered.\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
/* Wrapper for tcgetattr */
|
||||
static int getattr(int fd, struct termios *arg) {
|
||||
int result, retries = 3;
|
||||
while (-1 == (result = tcgetattr(fd, arg)) && retries > 0) {
|
||||
retries--;
|
||||
if (EINTR == errno) continue;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wrapper for tcgetattr */
|
||||
static int setattr(int fd, int opt, const struct termios *arg) {
|
||||
int result, retries = 3;
|
||||
while (-1 == (result = tcsetattr(fd, opt, arg)) && retries > 0) {
|
||||
retries--;
|
||||
if (EINTR == errno) continue;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void rl_ttyset(int Reset) {
|
||||
static struct termios old;
|
||||
struct termios new;
|
||||
if (!Reset) {
|
||||
if (-1 == getattr(0, &old)) {
|
||||
perror("Failed tcgetattr()");
|
||||
}
|
||||
rl_erase = old.c_cc[VERASE];
|
||||
rl_kill = old.c_cc[VKILL];
|
||||
rl_eof = old.c_cc[VEOF];
|
||||
rl_intr = old.c_cc[VINTR];
|
||||
rl_quit = old.c_cc[VQUIT];
|
||||
#ifdef CONFIG_SIGSTOP
|
||||
rl_susp = old.c_cc[VSUSP];
|
||||
#endif
|
||||
new = old;
|
||||
new.c_lflag &= ~(ECHO | ICANON | ISIG);
|
||||
new.c_iflag &= ~INPCK;
|
||||
if (rl_meta_chars)
|
||||
new.c_iflag |= ISTRIP;
|
||||
else
|
||||
new.c_iflag &= ~ISTRIP;
|
||||
new.c_cc[VMIN] = 1;
|
||||
new.c_cc[VTIME] = 0;
|
||||
if (-1 == setattr(0, TCSADRAIN, &new)) {
|
||||
perror("Failed tcsetattr(TCSADRAIN)");
|
||||
}
|
||||
} else {
|
||||
if (-1 == setattr(0, TCSADRAIN, &old)) {
|
||||
perror("Failed tcsetattr(TCSADRAIN)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rl_add_slash(char *path, char *p) {
|
||||
struct stat Sb;
|
||||
if (stat(path, &Sb) >= 0) strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ");
|
||||
}
|
||||
Reference in New Issue
Block a user