Compare commits

...

40 Commits

Author SHA1 Message Date
Joachim Wiberg
9df73e8670
Merge pull request #74 from tgree/macos_prototypes_fix
Fix function prototypes
2025-04-06 13:34:10 +02:00
Terry Greeniaus
f53bebdbe9 Fix function prototypes.
This allows it to compile on macOS 15.3.2 using the default command-line
tools (clang-1600.0.26.6).
2025-04-05 23:17:20 -06:00
Joachim Wiberg
50bde4b5c3 Constify
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-08 21:41:48 +01:00
Joachim Wiberg
651c0bf38b examples: update prompt in fileman to show cwd
This shows off the rl_set_prompt() API to provide a more dynamic prompt.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-08 21:36:12 +01:00
Joachim Wiberg
d1ea173949 Fix and make sure to use rl_set_prompt() API
Fixes #51

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-08 21:34:56 +01:00
Joachim Wiberg
2c0313a3b5 Move forward wordwise should move to end of current word
For a similar feel like GNU Readline we should not skip to the next word
but stop at the end of the current.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-08 08:22:27 +01:00
Joachim Wiberg
41d80b5b14 Calling Ctrl-U should delete from cursor to beginning
Fixes #71

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-08 08:12:19 +01:00
Joachim Wiberg
c7437c8ce3 Fix doube free in completion
When falling back to rl_filename_completion_fuction as compentry
generator, the complete() function caused double free because the
generator did not return a strdup'ed entry but one of its own that
it freed when done.

Fixes #56

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-07 10:38:57 +01:00
Joachim Wiberg
22bdb0478c Minor, update maintainer last name
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-12-07 08:33:54 +01:00
Joachim Wiberg
fb4d7268de
Merge pull request #70 from 9999years/recognize-meta-arrows
Recognize `Meta+Left` and `Meta+Right` for word navigation
2024-12-07 08:32:55 +01:00
Rebecca Turner
4c4455353a
Add support for \e[1;3C and \e[1;3D 2024-09-09 09:44:44 -07:00
Rebecca Turner
d0f2a5bc23
Recognize Meta+Left and Meta+Right
I'm not sure exactly where to find canonical documentation for these
codes, but this seems to match what my terminal produces (macOS + iTerm2
+ Fish + Tmux).

It might also be nice to have some more support for editing the bindings
for these characters; sequences of more than one character are not
supported by `el_bind_key` and similar.
2024-09-08 19:32:28 -07:00
Joachim Wiberg
ac81ca6d4b
Merge pull request #69 from vikrrrr/missing-global
Add rl_attempted_completion_over global to header

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2024-09-07 11:02:46 +02:00
Arthur Michas
93d952291f
Add rl_attempted_completion_over global to header
Signed-off-by: Arthur Michas <vikr@protonmail.com>
2024-09-07 02:53:08 +02:00
Joachim Wiberg
caf4b3c0ce
Merge pull request #67 from Feoramund/respect-hist-size 2024-05-27 17:44:43 +02:00
Joachim Wiberg
6207edfe95
Merge pull request #68 from Feoramund/respect-default-prompt 2024-05-27 17:44:05 +02:00
Feoramund
e0f686506a
Respect default prompt
A prompt `"? "` is set in `rl_initialize`, but it is never seen, because
this line was replacing it with `NILSTR`.
2024-05-26 04:13:29 -04:00
Feoramund
aefda06a0c
Respect el_hist_size
It was previously subject to a sort of off-by-one error, because of the
addition of `NILSTR` in `el_prep`. This should allow a history size of 1
to function correctly now.
2024-05-26 03:38:04 -04:00
Joachim Wiberg
425584840c
Merge pull request #64 from trofi/autoconf-2.72-fix 2023-12-24 03:45:37 +01:00
Sergei Trofimovich
2b788be1c8 configure.ac: add second parameter quoting around the rest of AS_IF for consistency 2023-12-23 19:17:19 +00:00
Sergei Trofimovich
f444a316f5 configure.ac: fix autoconf-2.72 compatibility
`autoconf-2.72` slightly changed `AS_IF`/`AC_CHECL_LIB` definitions and
exposed the bug of missng quoting around the arguments:

    editline> ./configure: line 13944: syntax error near unexpected token `;;'
    editline> ./configure: line 13944: ` ;;'

The change adds quoting as suggested by https://savannah.gnu.org/support/index.php?110990
2023-12-23 19:13:52 +00:00
Joachim Wiberg
7633fbceee
Merge pull request #63 from nobody5050/patch-1
fix filename inaccuracy

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-01-29 06:47:11 +01:00
nobody5050
d903a940a5
fix filename inaccuracy 2023-01-28 12:44:44 -06:00
Joachim Wiberg
3ccc3a5120
Merge pull request #62 from al20878/master
Fix #61: gcc sign extension warnings

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-10-23 15:14:18 +02:00
Tony Lawrence
c50d4c34d8 Avoid using (char) in <ctype.h> macros (#61) 2022-10-22 20:02:23 -04:00
Tony Lawrence
70c80ac22e Mention autoconf.sh in build instructions (#61) 2022-10-22 20:02:16 -04:00
Joachim Wiberg
9fa05ba384 Add early notice on Windows not being supported
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-02-19 22:41:32 +01:00
Joachim Wiberg
9d4c6f7042 Drop orig. effort to support WIN32
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2022-02-19 22:38:55 +01:00
Joachim Wiberg
fc866f60d6
Merge pull request #57 from rcombs/patch-1
Include stdio.h from editline.h
2022-02-19 22:09:15 +01:00
rcombs
f7b58d3c0d
Include stdio.h from editline.h
Fixes `#include <editline.h>` without first including `<stdio.h>`, which previously errored at the missing typedef for `FILE`.
2022-02-17 17:59:40 -06:00
Joachim Wiberg
36e0921c71
Merge pull request #54 from tejing1/master
handle home and end keys in urxvt
2021-07-06 08:23:08 +02:00
Jeff Huffman
ec62e11a72
handle home and end keys in urxvt 2021-06-27 22:44:30 -04:00
Joachim Wiberg
0f4f5b0228
Merge pull request #53 from oxalica/fix/tmux-home-end
Fix Home (\e[1~) and End (\e[4~) in tmux
2021-05-29 15:22:18 +02:00
oxalica
265c1fb6a0
Fix Home (\e[1~) and End (\e[4~) in tmux 2021-05-29 14:30:05 +08:00
Joachim Wiberg
69c7e86967 Merge branch 'mlundh-bufferOverrunFix'
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-25 10:51:58 +01:00
Martin Lundh
3acd6a8b60 Fixed buffer overrun issue detected by address sanitizer. 2021-02-25 10:22:50 +01:00
Joachim Nilsson
62bba78258 Fix #41: add missing include in example
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-08-02 02:15:37 +02:00
Joachim Nilsson
63b94d2089 configure: Add --enable-examples option to build examples/
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-06-08 18:47:17 +02:00
Joachim Nilsson
2ebe9058a1
Merge pull request #40 from gh-fork-dump/master
POSIX recommends <sys/select.h> for select()
2020-06-08 18:43:27 +02:00
Stephen Gregoratto
d4b25ca85e include <sys/select.h> in excallback
Fixes an build issue when cross-compiling for SerenityOS[1]

[1] https://github.com/SerenityOS/serenity
2020-06-09 00:21:11 +10:00
11 changed files with 224 additions and 119 deletions

View File

@ -2,7 +2,11 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libeditline.pc
doc_DATA = README.md LICENSE
EXTRA_DIST = README.md LICENSE ChangeLog.md INSTALL.md
SUBDIRS = src include man examples
SUBDIRS = src include man
if ENABLE_EXAMPLES
SUBDIRS += examples
endif
## Generate MD5 checksum file
MD5 = md5sum

View File

@ -33,6 +33,8 @@ to use the library is available in the `examples/` directory.
Editline is maintained collaboratively at [GitHub][].
> **Note:** Windows is not a supported target for editline.
Example
-------
@ -56,6 +58,7 @@ sub-directory.
e.g. `~/src/example.c`
```C
#include <stdio.h>
#include <stdlib.h>
#include <editline.h>
@ -195,6 +198,7 @@ current maintainer works exclusively on GNU/Linux systems, so it may use
GCC and GNU Make specific extensions here and there. This is not on
purpose and patches or pull requests to correct this are most welcome!
0. Call <kbd>./autogen.sh</kbd> if you build from git
1. Configure editline with default features: <kbd>./configure</kbd>
2. Build the library and examples: <kbd>make all</kbd>
3. Install using <kbd>make install</kbd>

View File

@ -61,29 +61,35 @@ AC_ARG_ENABLE(terminal-bell,
AC_ARG_ENABLE(termcap,
AS_HELP_STRING([--enable-termcap], [Use termcap library to query terminal size.]))
AC_ARG_ENABLE([examples],
[AC_HELP_STRING([--enable-examples], [Build examples/ directory])],
[], [enable_examples=no])
#
# Check what features have been enabled
#
AS_IF([test "x$enable_unique_history" != "xno"],
AC_DEFINE(CONFIG_UNIQUE_HISTORY, 1, [Define to skip duplicate lines in the scrollback history.]))
AS_IF([test "x$enable_unique_history" != "xno"], [
AC_DEFINE(CONFIG_UNIQUE_HISTORY, 1, [Define to skip duplicate lines in the scrollback history.])])
AS_IF([test "x$enable_terminal_bell" != "xno"],
AC_DEFINE(CONFIG_ANSI_ARROWS, 1, [Define to include ANSI arrow keys support.]))
AS_IF([test "x$enable_terminal_bell" != "xno"], [
AC_DEFINE(CONFIG_ANSI_ARROWS, 1, [Define to include ANSI arrow keys support.])])
AS_IF([test "x$enable_eof" != "xno"],
AC_DEFINE(CONFIG_EOF, 1, [Define to enable EOF (Ctrl-D) key.]))
AS_IF([test "x$enable_eof" != "xno"], [
AC_DEFINE(CONFIG_EOF, 1, [Define to enable EOF (Ctrl-D) key.])])
AS_IF([test "x$enable_sigint" != "xno"],
AC_DEFINE(CONFIG_SIGINT, 1, [Define to enable SIGINT (Ctrl-C) key.]))
AS_IF([test "x$enable_sigint" != "xno"], [
AC_DEFINE(CONFIG_SIGINT, 1, [Define to enable SIGINT (Ctrl-C) key.])])
AS_IF([test "x$enable_sigstop" = "xyes"],
AC_DEFINE(CONFIG_SIGSTOP, 1, [Define to enable SIGSTOP (Ctrl-Z) key.]))
AS_IF([test "x$enable_sigstop" = "xyes"], [
AC_DEFINE(CONFIG_SIGSTOP, 1, [Define to enable SIGSTOP (Ctrl-Z) key.])])
AS_IF([test "x$enable_terminal_bell" = "xyes"],
AC_DEFINE(CONFIG_TERMINAL_BELL, 1, [Define to enable terminal bell on completion.]))
AS_IF([test "x$enable_terminal_bell" = "xyes"], [
AC_DEFINE(CONFIG_TERMINAL_BELL, 1, [Define to enable terminal bell on completion.])])
AM_CONDITIONAL([ENABLE_EXAMPLES], [test "$enable_examples" = yes])
# Check for a termcap compatible library if enabled
AS_IF([test "x$enable_termcap" = "xyes"],
AS_IF([test "x$enable_termcap" = "xyes"], [
AC_DEFINE(CONFIG_USE_TERMCAP, 1, [Define to use the termcap library for terminal size.])
AC_CHECK_LIB(terminfo, tgetent, , [
AC_CHECK_LIB(termcap, tgetent, , [
@ -94,7 +100,7 @@ AS_IF([test "x$enable_termcap" = "xyes"],
])
])
])
]))
])])
# Generate all files
AC_OUTPUT

2
debian/control vendored
View File

@ -2,7 +2,7 @@ Source: editline
Section: devel
Priority: optional
Build-Depends: debhelper (>= 10), libtool
Maintainer: Joachim Nilsson <troglobit@gmail.com>
Maintainer: Joachim Wiberg <troglobit@gmail.com>
Standards-Version: 4.3.0
Package: libeditline-dev

4
debian/copyright vendored
View File

@ -1,6 +1,6 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: editline
Upstream-Contact: Joachim Nilsson <troglobit@gmail.com>
Upstream-Contact: Joachim Wiberg <troglobit@gmail.com>
Source: http://github.com/troglobit/editline
Comment: This package was originally debianized by Jim Studt <jim@federated.com>
on Fri, 5 May 2000 13:25:51 -0500. It was received from, then upstream
@ -11,7 +11,7 @@ Copyright: 1992,1993 Simmule Turner and Rich Salz.
License: C-News
Files: debian/*
Copyright: 2010-2020 Joachim Nilsson <troglobit@gmail.com>
Copyright: 2010-2020 Joachim Wiberg <troglobit@gmail.com>
License: BSD-2-clause
License: C-News

View File

@ -39,6 +39,7 @@ Jeff
#include <stdio.h>
#include <sys/types.h>
#include <sys/select.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>

View File

@ -7,6 +7,7 @@
*/
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
@ -22,7 +23,7 @@
#include "editline.h"
void too_dangerous(char *caller);
void initialize_readline();
void initialize_readline(const char *prompt);
int execute_line(char *line);
int valid_argument(char *caller, char *arg);
@ -61,8 +62,15 @@ struct cmd commands[] = {
};
/* Forward declarations. */
char *stripwhite();
struct cmd *find_command();
char *stripwhite(char *string);
struct cmd *find_command(char *name);
/* ~/.fileman_history */
char *fileman_history;
/* Prompt base and current */
const char *prompt_init;
char *prompt_curr;
/* When non-zero, this means the user is done using this program. */
int done;
@ -72,12 +80,11 @@ int main(int argc, char **argv)
char *line, *s;
setlocale(LC_CTYPE, "");
initialize_readline(); /* Bind our completer. */
initialize_readline("(FileMan)");
/* Loop reading and executing lines until the user quits. */
for (; done == 0;) {
line = readline("FileMan: ");
line = readline(NULL);
if (!line)
break;
@ -107,6 +114,10 @@ int main(int argc, char **argv)
free(line);
}
puts("");
write_history(fileman_history);
free(fileman_history);
return 0;
}
@ -188,19 +199,58 @@ char *stripwhite(char *string)
char *command_generator(const char *, int);
char **fileman_completion(const char *, int, int);
void fileman_prompt(void);
/*
* Tell the GNU Readline library how to complete. We want to try to
* complete on command names if this is the first word in the line, or
* on filenames if not.
*/
void initialize_readline(void)
void initialize_readline(const char *prompt)
{
const char *home;
size_t len;
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = fileman_completion;
/* Restore command history */
home = getenv("HOME");
len = (home ? strlen(home) : 0) + 14;
fileman_history = malloc(len);
assert(fileman_history);
snprintf(fileman_history, len, "%s/.fileman_history", home ? home : ".");
read_history(fileman_history);
/* Prompt is updated when moving around in the tree */
prompt_init = prompt;
fileman_prompt();
}
/*
* Update prompt when changing directory. Use an allocated string to
* show off the rl_set_prompt() API for issue #51.
*/
void fileman_prompt(void)
{
char cwd[1024];
size_t len;
if (prompt_curr)
free(prompt_curr);
assert(getcwd(cwd, sizeof(cwd)));
len = strlen(prompt_init) + strlen(cwd) + 10;
prompt_curr = malloc(len);
assert(prompt_curr);
snprintf(prompt_curr, len, "%s %s/> ", prompt_init, cwd);
rl_set_prompt(prompt_curr);
}
/*
@ -377,7 +427,8 @@ int com_cd(char *arg)
return 1;
}
com_pwd("");
//com_pwd("");
fileman_prompt();
return 0;
}

View File

@ -21,6 +21,8 @@
#ifndef EDITLINE_H_
#define EDITLINE_H_
#include <stdio.h>
/* Handy macros when binding keys. */
#define CTL(x) ((x) & 0x1F)
#define ISCTL(x) ((x) && (x) < ' ')
@ -82,6 +84,7 @@ extern int rl_point;
extern int rl_mark;
extern int rl_end;
extern int rl_inhibit_complete;
extern int rl_attempted_completion_over;
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! */

View File

@ -275,12 +275,13 @@ int main(void)
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.
Google Gadgets for Linux, and many others. 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
This version stems from the Minix 2 sources, but has since evolved to
include patches from all relevant forks. It is currently maintained by
.An Joachim Wiberg
at
.Lk https://github.com/troglobit/editline "GitHub" .
.Sh BUGS
Does not handle multiple lines or unicode characters well.

View File

@ -40,7 +40,7 @@ static int compare(const void *p1, const void *p2)
/* 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)
static int FindMatches(const char *dir, const char *file, char ***avp)
{
char **av;
char **word;
@ -128,7 +128,7 @@ static int FindMatches(char *dir, char *file, char ***avp)
/* Split a pathname into allocated directory and trailing filename parts. */
static int SplitPath(const char *path, char **dirpart, char **filepart)
{
static char DOT[] = ".";
static const char DOT[] = ".";
char *dpart;
char *fpart;
@ -197,14 +197,14 @@ char *el_filename_complete(char *pathname, int *match)
if (ac == 1) {
/* Exactly one match -- finish it off. */
*match = 1;
j = strlen(av[0]) - len + 2;
p = malloc(sizeof(char) * (j + 1));
j = strlen(av[0]) - len + 1;
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);
len = strlen(dir) + strlen(av[0]) + 2;
path = malloc(sizeof(char) * len);
if (path) {
snprintf(path, len, "%s/%s", dir, av[0]);
snprintf(path, len, "%s/%s", dir, av[0]);
rl_add_slash(path, p);
free(path);
}
@ -243,9 +243,7 @@ char *el_filename_complete(char *pathname, int *match)
char *rl_filename_completion_function(const char *text, int state)
{
char *dir;
char *file;
static char **av;
static char **av, *dir, *file;
static size_t i, ac;
if (!state) {
@ -253,32 +251,47 @@ char *rl_filename_completion_function(const char *text, int state)
return NULL;
ac = FindMatches(dir, file, &av);
free(dir);
free(file);
if (!ac)
if (!ac) {
free(dir);
free(file);
return NULL;
}
i = 0;
}
if (i < ac)
return av[i++];
if (i < ac) {
size_t len = (dir ? strlen(dir) : 0) + strlen(av[i]) + 3;
char *ptr = malloc(len);
if (ptr) {
snprintf(ptr, len, "%s%s", dir, av[i++]);
if (ac == 1)
rl_add_slash(ptr, ptr);
return ptr;
}
}
do {
free(av[--i]);
} while (i > 0);
free(av);
free(dir);
free(file);
return NULL;
}
/* Similar to el_find_word(), but used by GNU Readline API */
static char *rl_find_token(size_t *len)
{
char *ptr;
const char *ptr;
int pos;
for (pos = rl_point; pos < rl_end; pos++) {
if (isspace(rl_line_buffer[pos])) {
if (isspace((unsigned char) rl_line_buffer[pos])) {
if (pos > 0)
pos--;
break;
@ -286,7 +299,7 @@ static char *rl_find_token(size_t *len)
}
ptr = &rl_line_buffer[pos];
while (pos >= 0 && !isspace(rl_line_buffer[pos])) {
while (pos >= 0 && !isspace((unsigned char) rl_line_buffer[pos])) {
if (pos == 0)
break;
@ -367,8 +380,12 @@ static char *complete(char *token, int *match)
free(word);
word = NULL;
if (words[0])
/* Exactly one match -- finish it off. */
if (words[0] && !words[1]) {
*match = 1;
word = strdup(words[0] + len);
}
while (words[i])
free(words[i++]);
@ -378,6 +395,9 @@ static char *complete(char *token, int *match)
return word;
}
if (word)
free(word);
fallback:
return el_filename_complete(token, match);
}

View File

@ -115,7 +115,7 @@ static const char *old_prompt = NULL;
static rl_vcpfunc_t *line_handler = NULL;
static char *line_up = "\x1b[A";
static char *line_down = "\x1b[B";
int prompt_len = 0;
static int prompt_len = 0;
int el_no_echo = 0; /* e.g., under Emacs */
int el_no_hist = 0;
@ -125,6 +125,7 @@ int rl_end;
int rl_meta_chars = 0; /* Display 8-bit chars as the actual char(0) or as `M-x'(1)? */
int rl_inhibit_complete = 0;
char *rl_line_buffer = NULL;
static const char *rl_saved_prompt = NULL;
const char *rl_prompt = NULL;
const char *rl_readline_name = NULL; /* Set by calling program, for conditional parsing of ~/.inputrc - Not supported yet! */
FILE *rl_instream = NULL; /* The stdio stream from which input is read. Defaults to stdin if NULL */
@ -210,7 +211,7 @@ static void tty_show(unsigned char c)
}
}
static void tty_string(char *p)
static void tty_string(const char *p)
{
int i = rl_point + prompt_len + 1;
@ -463,12 +464,6 @@ static el_status_t do_forward(el_status_t move)
right(CSstay);
}
/* Skip to next word, or skip leading white space if outside a word. */
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
if (move == CSmove)
right(CSstay);
}
if (rl_point == rl_end)
break;
} while (++i < Repeat);
@ -494,10 +489,10 @@ static el_status_t do_case(el_case_t type)
for (i = rl_point, p = &rl_line_buffer[i]; rl_point < end; p++) {
if ((type == TOupper) || (type == TOcapitalize && rl_point == i)) {
if (islower(*p))
*p = toupper(*p);
} else if (isupper(*p)) {
*p = tolower(*p);
if (islower((unsigned char)(*p)))
*p = toupper((unsigned char)(*p));
} else if (isupper((unsigned char)(*p))) {
*p = tolower((unsigned char)(*p));
}
right(CSmove);
}
@ -778,7 +773,7 @@ static const char *search_hist(const char *search, const char *(*move)(void))
static el_status_t h_search_end(const char *p)
{
rl_prompt = old_prompt;
rl_set_prompt(old_prompt);
Searching = 0;
if (el_intr_pending > 0) {
@ -805,8 +800,8 @@ static el_status_t h_search(void)
clear_line();
old_prompt = rl_prompt;
rl_prompt = "Search: ";
tty_puts(rl_prompt);
rl_set_prompt("Search: ");
reposition(EOF);
search_move = Repeat == NO_ARG ? el_prev_hist : el_next_hist;
if (line_handler) {
@ -1034,6 +1029,30 @@ static el_status_t meta(void)
return CSeof;
#ifdef CONFIG_ANSI_ARROWS
/* See: https://en.wikipedia.org/wiki/ANSI_escape_code */
/* Recognize ANSI escapes for `Meta+Left` and `Meta+Right`. */
if (c == '\e') {
switch (tty_get()) {
case '[':
{
switch (tty_get()) {
/* \e\e[C = Meta+Left */
case 'C': return fd_word();
/* \e\e[D = Meta+Right */
case 'D': return bk_word();
default:
break;
}
return el_ring_bell();
}
default:
break;
}
return el_ring_bell();
}
/* Also include VT-100 arrows. */
if (c == '[' || c == 'O') {
switch (tty_get()) {
@ -1041,21 +1060,31 @@ static el_status_t meta(void)
case '1':
{
char seq[4] = { 0 };
seq[0] = tty_get();
for (c = 0; c < 3; c++)
/* \e[1~ */
if (seq[0] == '~')
return beg_line(); /* Home */
for (c = 1; c < 3; c++)
seq[c] = tty_get();
if (!strncmp(seq, ";5C", 3))
return fd_word(); /* Ctrl+Right */
if (!strncmp(seq, ";5D", 3))
return bk_word(); /* Ctrl+Left */
if (!strncmp(seq, ";5C", 3)
|| !strncmp(seq, ";3C", 3))
return fd_word(); /* \e[1;5C = Ctrl+Right */
if (!strncmp(seq, ";5D", 3)
|| !strncmp(seq, ";3D", 3))
return bk_word(); /* \e[1;5D = Ctrl+Left */
break;
}
case '2': tty_get(); return CSstay; /* Insert */
case '3': tty_get(); return del_char(); /* Delete */
case '4': tty_get(); return end_line(); /* End */
case '5': tty_get(); return CSstay; /* PgUp */
case '6': tty_get(); return CSstay; /* PgDn */
case '7': tty_get(); return beg_line(); /* Home (urxvt) */
case '8': tty_get(); return end_line(); /* End (urxvt) */
case 'A': return h_prev(); /* Up */
case 'B': return h_next(); /* Down */
case 'C': return fd_char(); /* Left */
@ -1125,6 +1154,8 @@ static el_status_t emacs(int c)
static el_status_t tty_special(int c)
{
el_status_t rc;
#ifdef CONFIG_SIGINT
if (c == rl_intr) {
el_intr_pending = SIGINT;
@ -1149,14 +1180,10 @@ static el_status_t tty_special(int c)
return bk_del_char();
if (c == rl_kill) {
if (rl_point != 0) {
old_point = rl_point;
rl_point = 0;
reposition(c);
}
Repeat = NO_ARG;
return kill_line();
Repeat = rl_point;
rc = bk_del_char();
Repeat = NO_ARG;
return rc;
}
#ifdef CONFIG_EOF
@ -1222,7 +1249,7 @@ static char *editinput(int complete)
static void hist_alloc(void)
{
if (!H.Lines)
H.Lines = calloc(el_hist_size, sizeof(char *));
H.Lines = calloc(1 + el_hist_size, sizeof(char *));
}
static void hist_add(const char *p)
@ -1239,11 +1266,11 @@ static void hist_add(const char *p)
if (s == NULL)
return;
if (H.Size < el_hist_size) {
if (H.Size <= el_hist_size) {
H.Lines[H.Size++] = s;
} else {
free(H.Lines[0]);
for (i = 0; i < el_hist_size - 1; i++)
for (i = 0; i < el_hist_size; i++)
H.Lines[i] = H.Lines[i + 1];
H.Lines[i] = s;
}
@ -1255,7 +1282,7 @@ static char *read_redirected(void)
int size = MEM_INC;
char *p;
char *line;
char *end;
const char *end;
p = line = malloc(sizeof(char) * size);
if (!p)
@ -1337,10 +1364,28 @@ void rl_reset_terminal(const char *terminal_name)
}
}
void rl_set_prompt(const char *prompt)
{
if (prompt)
rl_prompt = prompt;
prompt_len = strlen(rl_prompt);
}
void rl_save_prompt(void)
{
rl_saved_prompt = rl_prompt;
}
void rl_restore_prompt(void)
{
if (rl_saved_prompt)
rl_set_prompt(rl_saved_prompt);
}
void rl_initialize(void)
{
if (!rl_prompt)
rl_prompt = "? ";
rl_set_prompt("? ");
hist_alloc();
@ -1359,7 +1404,7 @@ void rl_uninitialize(void)
/* Uninitialize the history */
if (H.Lines) {
for (i = 0; i < el_hist_size; i++) {
for (i = 0; i <= el_hist_size; i++) {
if (H.Lines[i])
free(H.Lines[i]);
H.Lines[i] = NULL;
@ -1381,29 +1426,12 @@ void rl_uninitialize(void)
Length = 0;
}
static const char *rl_saved_prompt = NULL;
void rl_save_prompt(void)
{
rl_saved_prompt = rl_prompt;
}
void rl_restore_prompt(void)
{
if (rl_saved_prompt)
rl_prompt = rl_saved_prompt;
}
void rl_set_prompt(const char *prompt)
{
rl_prompt = prompt;
}
void rl_clear_message(void)
{
/* Nothing to do atm. */
}
void rl_forced_update_display()
void rl_forced_update_display(void)
{
redisplay(0);
tty_flush();
@ -1428,8 +1456,7 @@ static int el_prep(const char *prompt)
if (!Screen)
return -1;
rl_prompt = prompt ? prompt : NILSTR;
prompt_len = strlen(rl_prompt);
rl_set_prompt(prompt);
if (el_no_echo) {
int old = el_no_echo;
@ -1746,14 +1773,6 @@ static el_status_t accept_line(void)
return CSdone;
}
#ifdef SYSTEM_IS_WIN32
static el_status_t end_of_input(void)
{
rl_line_buffer[rl_end] = '\0';
return CSeof;
}
#endif
static el_status_t transpose(void)
{
char c;
@ -1876,14 +1895,14 @@ static int argify(char *line, char ***avp)
if (!p)
return 0;
for (c = line; isspace(*c); c++)
for (c = line; isspace((unsigned char)(*c)); c++)
continue;
if (*c == '\n' || *c == '\0')
return 0;
for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
if (!isspace(*c)) {
if (!isspace((unsigned char)(*c))) {
c++;
continue;
}
@ -1965,11 +1984,7 @@ static el_keymap_t Map[64] = {
{ CTL('W'), bk_kill_word },
{ CTL('X'), exchange },
{ CTL('Y'), yank },
#ifdef SYSTEM_IS_WIN32
{ CTL('Z'), end_of_input },
#else
{ CTL('Z'), el_ring_bell },
#endif
{ CTL('['), meta },
{ CTL(']'), move_to_char },
{ CTL('^'), el_ring_bell },