74 Commits

Author SHA1 Message Date
Joachim Nilsson
59fa265d91 Update ChangeLog and bump version for v1.16.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
5f86c20c87 debian/control: Bump .so/ABI version
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
237014f7d9 Bump ABI version
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
bbd0621da8 debian/control: Set upstream author as maintainer
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
1a5541256b debian/source/format: Add missing file
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
d4bef671b6 Minor, update .gitignore files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
054891f032 Add .deb package to official release target
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 10:10:03 +02:00
Joachim Nilsson
6fb3365893 docs/HACKING.md: Add release checklist and maintenance doc
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 09:35:27 +02:00
Joachim Nilsson
14b6dd37d6 Fix off-by-one in forward kill word
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 09:29:48 +02:00
Joachim Nilsson
89d2fefbc6 Skip leading whitespace when skipping or killing forwards
When the point is on whitespace between two words skipping forward, or
killing forward, should result in the new point being moved to the next
word:

     foo    bar fox gnu
         ^
=>
     foo    bar fox gnu
                ^

Before this patch the point moved to 'b'.  After this patch the point
moves to the first letter of the next word, 'f'.  Kill forward word now
properly kills 'bar' and moves to the first whitespace letter after
'bar'.  Both are now behaving like FSF Readline.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 09:29:48 +02:00
Joachim Nilsson
ac522cd749 Fix potential memory leak, found by Coverity Scan
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-16 08:29:01 +02:00
Joachim Nilsson
9a16999f0e Remove GNU Readline rl_complete() prototype, for now
We should add a configure option --enable-readline-compat, or sth, so
rl_complete2() (removed in this commit) becomes the new rl_complete(),
and the current rl_complete() becomes el_complete().

The current implementation of rl_complete2() was is incomplete and also
not working properly.  To eliminate any confusion on the matter this
patch removes it.  To restore functionality we should, at the very
least, merge with complete() and possibly also refactor rl_find_token()
to share code with the legacy el_find_word().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-13 19:06:05 +02:00
Joachim Nilsson
e962b9582a Update ChangeLog, mention new fileman.c from GNU Readline
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-12 17:12:40 +02:00
Joachim Nilsson
29b24dcf83 Clarify comment about future --enable-readline-compat interface
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-12 17:12:19 +02:00
Joachim Nilsson
097fde5267 Merge branch 'master' of github.com:troglobit/editline 2018-09-11 19:57:25 +02:00
Joachim Nilsson
05ed94047b Update ChangeLog and fix description of bug #7 in earlier entry
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-11 19:56:05 +02:00
Joachim Nilsson
77d531f5b5 Refactor completion handling and add FSF Readline callbacks
Still a bit raw, but the basic building blocks are there, waiting to be
cleaned up and released.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-09-11 19:55:43 +02:00
Joachim Nilsson
405f091888 Merge pull request #19 from jmjatlanta/jmj_sigsev
Fix sementation violation when displaying options
2018-07-12 10:50:04 +02:00
jmjatlanta
d2418161ad Fix sementation violation when displaying options 2018-07-11 18:01:48 -05:00
Joachim Nilsson
b2f1cfbbcc fileman: New example, from libedit, and from GNU Readline originally
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-06-17 21:13:02 +02:00
Joachim Nilsson
76039b458b Fix #17: Fix off-by-one problem with strdup() replacement
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-06-14 21:59:18 +02:00
Joachim Nilsson
a5aaf51530 Minor, update project description
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-06-11 22:32:36 +02:00
Joachim Nilsson
bd5ae42b4b Remove configure option --disable-default-complete
The filename completion handler fallback will now be enabled by default.
To disable it a new GNU Readline function pointer will be added.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-04-02 22:08:43 +02:00
Joachim Nilsson
41bbb304b1 Export internal el_next_hist() and el_prev_hist()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-04-01 16:10:10 +02:00
Joachim Nilsson
f40a2a6a2c TODO: custom completion handlers verified in examples/cli.c
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-31 14:42:10 +02:00
Joachim Nilsson
534b3897b8 Minor update
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-31 01:23:41 +02:00
Joachim Nilsson
b4cf343342 Unify on docs/ directory, which is de facto standard on GitHub
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-31 01:21:12 +02:00
Joachim Nilsson
4c55280864 Update ChangeLog for upcoming v1.16.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-29 21:17:20 +02:00
Joachim Nilsson
78eabbde39 man: Minor update
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-24 19:35:16 +01:00
Joachim Nilsson
bc510b320e Follow-up #15: Clean up TODO, event loop callback now supported
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-24 19:34:19 +01:00
Joachim Nilsson
3cf0e89a68 Merge branch 'dev' 2018-03-22 16:06:19 +01:00
Joachim Nilsson
5b43c028c9 Revert "Travis-CI: Disable CLANG temporarily for Coverity Scan"
This reverts commit 6a7483532c.
2018-03-22 16:06:04 +01:00
Joachim Nilsson
1657da4f2e README: Minor whitespace changes
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 13:16:07 +01:00
Joachim Nilsson
fdda4f5cae README: Add license badge and add Wikipedia link to C News
The C News sources are referenced in the Wikipedia article, which is
useful to follow-up the license origins.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 10:49:49 +01:00
Joachim Nilsson
f8c6b7f208 Update .gitignore
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 10:49:39 +01:00
Joachim Nilsson
9e9f8b03d8 Fix Coverity Scan findings, missing return and bad strcpy()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 10:31:50 +01:00
Joachim Nilsson
0bfaf351aa Add support for Ctrl+Right and Ctrl+Left, forward/back word
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 08:42:32 +01:00
Joachim Nilsson
2ce0be942e Minor, reorder functions
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 08:38:04 +01:00
Joachim Nilsson
6a7483532c Travis-CI: Disable CLANG temporarily for Coverity Scan
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-22 08:17:03 +01:00
Joachim Nilsson
ad3b1c8a07 ChangeLog: Fix missing Markdown link to v1.15.3
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-03-09 20:29:52 +01:00
Joachim Nilsson
5be965deec Simplify and clarify example
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-27 14:01:54 +01:00
Joachim Nilsson
791508a3a1 Minor fix, whitespace
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-27 13:27:59 +01:00
Joachim Nilsson
6de69a406b Update example with build instructions, put it before API listing
This update should help with issues like that described in #16, "how do
I use this library?"

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-27 13:15:52 +01:00
Joachim Nilsson
197f3e1c32 Minor fixes, grammar + whitespace
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-27 13:15:02 +01:00
Joachim Nilsson
6adf0e98bb README: Add alternate interface docu
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-11 08:55:12 +01:00
Joachim Nilsson
bc7fc7e5c0 Fix #15: Alternate interface to plain readline(), for event loops
This rather big patch adds support for the GNU Readline alternate
interface, for use with event loops:

    void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler);
    void rl_callback_read_char       (void);
    void rl_callback_handler_remove  (void);

The code has been tested using the testit and excallback examples.
Both regular editing and searching works as intended.

Also, the problem with lingering artefacts on screen when scrolling
through the history has been fixed.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-11 08:43:43 +01:00
Joachim Nilsson
935895bbf1 testit: Don't add history, readline() already does this
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-11 08:43:03 +01:00
Joachim Nilsson
2ec55cc9f1 Minor, simplify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-11 08:42:33 +01:00
Joachim Nilsson
7f7bb5b45c Minor, use NULL not 0, and -1 not NULL
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-11 01:45:25 +01:00
Joachim Nilsson
9b7b3121c5 configure: Check for unistd.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 21:15:17 +01:00
Joachim Nilsson
53b160f6a1 examples: Define EDITLINE_LIBRARY when building locally
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 21:14:49 +01:00
Joachim Nilsson
779db8817e rl_refresh_line(): new (undocumented) readline compat fn
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 21:14:14 +01:00
Joachim Nilsson
29a71a53d0 rl_insert_text(): new readline compat fn
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 21:13:39 +01:00
Joachim Nilsson
a9824655ee excallback.c: Fix compilation errors against readline
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 18:54:29 +01:00
Joachim Nilsson
69d9e549a0 examples/excallback.c: Jeff Solomon's alternate interface example
This patch adds the unmodified excallback.c from readline.  It was
originally contributed by Jeff Solomon as an example of the alternate
interface to readline.

The following set of patches modify it to work with editline.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 18:46:48 +01:00
Joachim Nilsson
94b1a78444 src/Makefile: Add -Wextra to CFLAGS
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-02 18:25:49 +01:00
Joachim Nilsson
a9d4247c09 Minor, header cleanup, whitespace fixes, comments
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-30 18:20:29 +01:00
Joachim Nilsson
a1f0a81a31 Add documentation for rl_deprep_term*() function and callback
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-30 07:45:38 +01:00
Joachim Nilsson
ea79fe70f9 write_history(), read_history(): Check fclose() return value
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 21:40:38 +01:00
Joachim Nilsson
621f126128 Reflow paragraphs, add link to original comp.sources.unix posting
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 17:58:42 +01:00
Joachim Nilsson
6137feacdf Add new rl_uninitialize() function to README
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 17:58:09 +01:00
Joachim Nilsson
2075dedc80 Remove leading (superfluous) comment
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 17:22:08 +01:00
Joachim Nilsson
54714631e2 Move All rights reserved to next line
All BSD style licenses put this text on a separate line, immediately
following the Copyright line.  The C-News license is confusing enough
to most people, so let's align at least a bit with the norm.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 17:20:21 +01:00
Joachim Nilsson
a70a933698 Modify header guards, __FILE_H__ is reserved for system headers
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 17:17:50 +01:00
Joachim Nilsson
b613db2afb Whitespace + coding style cleanup
- Use Emacs K&R style
- Add missing braces to for() loops
- Fix coding style issues in cli.c example
- Add empty lines to separate sections
- Simplify and de-indent code, check error case first + continue

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 16:40:10 +01:00
Joachim Nilsson
6021e54dbc Bump version for v1.16.0 relese cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 15:34:30 +01:00
Joachim Nilsson
1ace811722 rl_uninitialize(): also free old_search from previous i-search
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 15:32:59 +01:00
Claus Fischer
4b8333ad39 Remove duplicate unique history check
Signed-off-by: Claus Fischer <claus.fischer@clausfischer.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 15:03:01 +01:00
Joachim Nilsson
ed37cef412 Minor whitespace fixes/cleanup
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 15:01:22 +01:00
Joachim Nilsson
2a3b422137 Fix negative array index triggered by i-search
This is a fix to a bug reported by Claus Fischer.  When doing a reversed
i-search on the history, clear_line() sets rl_point to a negative value,
which is later used by ceol().  The intention is to clear the whole line
for the new Search: prompt, but indexing an array with a negative value
is strongly discouraged.

To prevent this negative indexing from happening we check in ceol() for
rl_point < 0, but we quickly notice another side effect: one lingering
character at the end of line when returning from i-search.  The problem
manifests itself more cleary when having a looooo000ooonong prompt.

The fix is to rub out the extra space, insert the i-search string, and
*then* call ceol() again.

Thanks to Claus for pointing this out!

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 14:53:14 +01:00
Claus Fischer
91937d970d testit: Test new rl_uninitialize() and load/store history
Signed-off-by: Claus Fischer <claus.fischer@clausfischer.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 14:51:29 +01:00
Claus Fischer
317b43e488 rl_unintialize(): New function, free all memory after use
Free all allocated internal memory and reset variables so
rl_initialize() or readline() may be called again later.

Signed-off-by: Claus Fischer <claus.fischer@clausfischer.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 14:44:24 +01:00
Claus Fischer
ed87f37409 Initialize global variables and reset to NULL on free()
Signed-off-by: Claus Fischer <claus.fischer@clausfischer.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-29 14:41:50 +01:00
Joachim Nilsson
b30c3479f5 Minor, spellcheck
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-09-07 01:32:17 +02:00
31 changed files with 1838 additions and 532 deletions

4
.gitignore vendored
View File

@@ -4,6 +4,10 @@
*.o
*.pc
.deps
.testit_history
GPATH
GRTAGS
GTAGS
Makefile
Makefile.in
aclocal.m4

View File

@@ -20,7 +20,7 @@ addons:
coverity_scan:
project:
name: "troglobit/editline"
description: "Minix editline"
description: "A small line editing library"
notification_email: troglobit@gmail.com
build_command_prepend: "./autogen.sh && ./configure --enable-sigstop --enable-terminal-bell"
build_command: "make -j5"

View File

@@ -4,6 +4,40 @@ Change Log
All notable changes to the project are documented in this file.
[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
-----------------------
@@ -13,10 +47,10 @@ Bug fix release.
- Refactor all enable/disable configure options, same problem as in #7
### Fixes
- Fix #7: `--enable-termcap` configure option does not work, wrongly
enables termcap by default.
- Fix #7: `--enable-termcap` configure option does not work. The script
enabled termcap by default rather than the other way around.
Also, check for termino as well, when `--enable-termcap` is selected.
Also, check for terminfo as well, when `--enable-termcap` is selected.
[1.15.2][] - 2016-06-06
@@ -169,7 +203,9 @@ Adaptations to Debian editline package.
- First version, forked from Minix current 2008-06-06
[UNRELEASED]: https://github.com/troglobit/finit/compare/1.15.1...HEAD
[UNRELEASED]: https://github.com/troglobit/finit/compare/1.16.0...HEAD
[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

View File

@@ -1,4 +1,5 @@
Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
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.

View File

@@ -6,13 +6,14 @@ SUBDIRS = src include man examples
## Generate .deb package
package build-deb:
@dpkg-buildpackage -uc -us -B
@dpkg-buildpackage -uc -us
## Generate MD5 checksum file
MD5 = md5sum
md5-dist:
@for file in $(DIST_ARCHIVES); do \
$(MD5) $$file > $$file.md5; \
$(MD5) $$file > ../$$file.md5; \
mv $$file ../; \
done
## Check if tagged in git
@@ -33,10 +34,19 @@ release-hook:
echo; \
fi
# lintian --profile debian -i -I --show-overrides ../$PKG.changes
package:
dpkg-buildpackage -uc -us -B
## Target to run when building a release
release: distcheck release-hook md5-dist
release: distcheck release-hook md5-dist package
@echo
@echo "Resulting release files:"
@echo "========================================================================="
@for file in $(DIST_ARCHIVES); do \
printf "$$file \tDistribution tarball\n"; \
printf "$$file.md5\t"; cat $$file.md5 | cut -f1 -d' '; \
mv $$file* ../; \
printf "%-40s Distribution tarball\n" $$file; \
printf "%-40s " $$file.md5; cat ../$$file.md5 | cut -f1 -d' '; \
done
@for file in `cd ..; ls *$(PACKAGE)*_$(subst _,.,$(VERSION))*`; do \
printf "%-40s Debian/Ubuntu package file\n" $$file; \
done

286
README.md
View File

@@ -1,6 +1,6 @@
Editline
========
[![Travis Status]][Travis] [![Coverity Status]][Coverity Scan]
[![License Badge][]][License] [![Travis Status]][Travis] [![Coverity Status]][Coverity Scan]
Table of Contents
@@ -16,96 +16,48 @@ Table of Contents
Introduction
------------
This is a small [line editing][] library. It can be linked into almost
any program to provide command line editing and history functions. It
This is a small [line editing][] library. It can be linked into almost
any program to provide command line editing and history functions. It
is call compatible with the [FSF readline][] library, but at a fraction
of the size, and as a result fewer features. It is also distributed
under a much more liberal [LICENSE][].
of the size, and as a result fewer features. It is also distributed
under a much more liberal [License][].
The small size (<30k), lack of dependencies (no ncurses needed!), and
the free license should make this library interesting to many embedded
The small size (<30k), lack of dependencies (ncurses not needed!), and
the free license should make this library interesting to many embedded
developers.
Editline has several optional build-time features that can be enabled by
by supplying different options to the GNU configure script. See the
output from <kbd>configure --help</kbd> for details. In the `examples/`
directory you can find some small code snippets used for testing.
supplying different options to the GNU configure script. See the output
from <kbd>configure --help</kbd> for details. Some useful hints on how
to use the library is available in the `examples/` directory.
Editline is maintained collaboratively at [GitHub][].
API
---
Here is the interface to editline. It has a small compatibility layer
to [FSF readline][], which may not be entirely up-to-date.
```C
/* Editline specific global variables. */
int el_no_echo; /* Do not echo input characters */
int el_no_hist; /* Disable auto-save of and access to history,
* e.g. for password prompts or wizards */
int el_hist_size; /* Size of history scrollback buffer, default: 15 */
/* Editline specific functions. */
char * el_find_word(void);
void el_print_columns(int ac, char **av);
el_status_t el_ring_bell(void);
el_status_t el_del_char(void);
/* Callback function for key binding */
typedef el_status_t el_keymap_func_t(void);
/* Bind key to a callback, use CTL('f') to change Ctrl-F, for example */
el_status_t el_bind_key(int key, el_keymap_func_t function);
el_status_t el_bind_key_in_metamap(int key, el_keymap_func_t function);
/* For compatibility with FSF readline. */
int rl_point;
int rl_mark;
int rl_end;
int rl_inhibit_complete;
char *rl_line_buffer;
const char *rl_readline_name;
void rl_initialize(void);
void rl_reset_terminal(const char *terminal_name);
void rl_save_prompt(void);
void rl_restore_prompt(void);
void rl_set_prompt(const char *prompt);
void rl_clear_message(void);
void rl_forced_update_display(void);
/* Main function to use, saves history by default */
char *readline(const char *prompt);
/* Use to save a read line to history, when el_no_hist is set */
void add_history(const char *line);
/* Load and save editline history from/to a file. */
int read_history(const char *filename);
int write_history(const char *filename);
/* Magic completion API, see examples/cli.c for more info */
rl_complete_func_t *rl_set_complete_func(rl_complete_func_t *func);
rl_list_possib_func_t *rl_set_list_possib_func(rl_list_possib_func_t *func);
```
Example
-------
Here is a very brief example to illustrate how one can use Editline to
create a simple CLI. More examples are availble in the source tree.
create a simple CLI, use Ctrl-D to exit the program. More examples are
availble in the source tree.
1. Build and install the library, preferably using a [release tarball][]
The configure script defaults to a `/usr/local` prefix.
tar xf editline-1.15.3.tar.xz
cd editline-1.15.3/
./configure --prefix=/usr
make all
sudo make install
2. Place the below source code in a separate project directory,
e.g. `~/src/example.c`
```C
#include <stdlib.h>
#include <editline.h>
extern char *readline(char *prompt);
int main (void)
int main(void)
{
char *p;
@@ -118,63 +70,191 @@ create a simple CLI. More examples are availble in the source tree.
}
```
3. Compile the example:
cd ~/src/
make LDLIBS=-leditline example
Here I use `make` and rely on its implicit (built-in) rules to handle
all the compiler magic, but you may want to create your own Makefile for
the project. In particular if you don't change the default prefix
(above), because then you need to specify the search path for the
include file(s) and the library manually.
A simple `~/src/Makefile` could look like this:
CFLAGS = -I/usr/local/include
LDFLAGS = -L/usr/local/lib
LDLIBS = -leditline
EXEC = example
OBJS = example.o
all: $(EXEC)
$(EXEC): $(OBJS)
clean:
$(RM) $(OBJS) $(EXEC)
distclean: clean
$(RM) *.o *~ *.bak
Then simply type `make` from your `~/src/` directory. You can also use
`pkg-config` for your `~/src/Makefile`, replace the following lines:
CFLAGS = $(shell pkg-config --cflags libeditline)
LDFLAGS = $(shell pkg-config --libs-only-L libeditline)
LDLIBS = $(shell pkg-config --libs-only-l libeditline)
Then simply type <kbd>make</kbd>, like above.
However, most `.rpm` based distributions `pkg-config` doesn't search in
`/usr/local` anymore, so you need to call make like this:
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig make
Debian/Ubuntu based systems do not have this problem.
API
---
Here is the libeditline interfaces. It has a small compatibility layer
to [FSF readline][], which may not be entirely up-to-date.
```C
/* Editline specific global variables. */
int el_no_echo; /* Do not echo input characters */
int el_no_hist; /* Disable auto-save of and access to history,
* e.g. for password prompts or wizards */
int el_hist_size; /* Size of history scrollback buffer, default: 15 */
/* Editline specific functions. */
char * el_find_word (void);
void el_print_columns (int ac, char **av);
el_status_t el_ring_bell (void);
el_status_t el_del_char (void);
/* Callback function for key binding */
typedef el_status_t el_keymap_func_t(void);
/* Bind key to a callback, use CTL('f') to change Ctrl-F, for example */
el_status_t el_bind_key (int key, el_keymap_func_t function);
el_status_t el_bind_key_in_metamap (int key, el_keymap_func_t function);
/* For compatibility with FSF readline. */
int rl_point;
int rl_mark;
int rl_end;
int rl_inhibit_complete;
char *rl_line_buffer;
const char *rl_readline_name;
void (*rl_deprep_term_function)(void);
void rl_deprep_terminal (void);
void rl_reset_terminal (const char *terminal_name);
void rl_initialize (void);
void rl_uninitialize (void); /* Free all internal memory */
void rl_save_prompt (void);
void rl_restore_prompt (void);
void rl_set_prompt (const char *prompt);
void rl_clear_message (void);
void rl_forced_update_display (void);
/* Main function to use, saves history by default */
char *readline (const char *prompt);
/* Use to save a read line to history, when el_no_hist is set */
void add_history (const char *line);
/* Load and save editline history from/to a file. */
int read_history (const char *filename);
int write_history (const char *filename);
/* Magic completion API, see examples/cli.c for more info */
rl_complete_func_t *rl_set_complete_func (rl_complete_func_t *func);
rl_list_possib_func_t *rl_set_list_possib_func (rl_list_possib_func_t *func);
/* Alternate interface to plain readline(), for event loops */
void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler);
void rl_callback_read_char (void);
void rl_callback_handler_remove (void);
```
Build & Install
---------------
Editline was originally designed for older UNIX systems and Plan 9. The
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
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!
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>
The `$DESTDIR` environment variable is honored at install. See
<kbd>./configure --help</kbd> for more options.
The `$DESTDIR` environment variable is honored at install. For more
options, see <kbd>./configure --help</kbd>
Remember to run `ldconfig` after install to update the linker cache. If
you've installed to a non-standard location (`--prefix`) you may also
have to update your `/etc/ld.so.conf`, or use `pkg-confg` to build your
application (above).
**NOTE:** RedHat/Fedora/CentOS and other `.rpm`-based distributions do
not consider `/usr/local` as standard path anymore. So make sure to
`./configure --prefix=/usr`, otherwise the build system use the GNU
default, which is `/usr/local`. The Debian based distributions, like
Ubuntu, do not have this problem.
Origin & References
--------------------
This [line editing][] library was created by Simmule Turner and
[Rich Salz][upstream] in in 1992. It is distributed under a “C
News-like” license, similar to the [BSD license][]. Rich's latest
version is however under the Apache license. For details on the
licensing terms of this version of the software, see [LICENSE][].
This [line editing][] library was created by [Rich Salz][] and Simmule
Turner and in 1992. It is distributed with a “[C News][]-like” license,
similar to the [BSD license][]. Rich's current version is however under
the Apache license. For details on the licensing terms of this version
of the software, see [License][].
This version of the editline library was forked from the [Minix 3][]
source tree and is *not* related to the similarily named NetBSD version
that [Jess Thrysøe][jess] disitributes to the world outside BSD. The
libraries have much in common, but the latter is heavily refactored and
also relies on libtermcap (usually supplied by ncurses), whereas this
This version of the editline library was forked from the [Minix 3][]
source tree and is *not* related to the similarily named NetBSD version
that [Jess Thrysøe][jess] disitributes to the world outside *BSD. The
libraries have much in common, but the latter is heavily refactored and
also relies on libtermcap (usually supplied by ncurses), whereas this
library only uses termios from the standard C library.
Patches and bug fixes from the following forks, all based on the
original comp.sources.unix posting, have been merged:
Patches and bug fixes from the following forks, based on the original
[comp.sources.unix][] posting, have been merged:
* Debian [libeditline][]
* [Heimdal][]
* [Festival][] speech-tools
* [Steve Tell][]'s editline patches
The version numbering scheme today follows that of the Debian version,
which can be seen in the [ChangeLog.md][]. The Debian version was
unknown to the current [maintainer][] for quite some time, so a
different name and different versioning scheme was used. In June 2009
this was changed to line up alongside Debian, with the intent is to
eventually merge the efforts.
The version numbering scheme today follows that of the Debian version,
details available in the [ChangeLog.md][]. The current [maintainer][]
was unaware of the Debian version for quite some time, so a different
name and versioning scheme was used. In June 2009 this was changed to
line up alongside Debian, with the intent is to eventually merge the
efforts.
Outstanding issues are listed in the [TODO.md][] file.
[GitHub]: https://github.com/troglobit/editline
[line editing]: https://github.com/troglobit/editline/blob/master/doc/README
[line editing]: https://github.com/troglobit/editline/blob/master/docs/README
[release tarball]: https://github.com/troglobit/editline/releases
[maintainer]: http://troglobit.com
[LICENSE]: https://github.com/troglobit/editline/blob/master/LICENSE
[TODO.md]: https://github.com/troglobit/editline/blob/master/TODO.md
[C News]: https://en.wikipedia.org/wiki/C_News
[TODO.md]: https://github.com/troglobit/editline/blob/master/docs/TODO.md
[ChangeLog.md]: https://github.com/troglobit/editline/blob/master/ChangeLog.md
[FSF readline]: http://www.gnu.org/software/readline/
[upstream]: https://github.com/richsalz/editline/
[Rich Salz]: https://github.com/richsalz/editline/
[comp.sources.unix]: http://ftp.cs.toronto.edu/pub/white/pub/rc/editline.shar
[Minix 3]: http://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/lib/editline/
[jess]: http://thrysoee.dk/editline/
[BSD license]: http://en.wikipedia.org/wiki/BSD_licenses
@@ -182,13 +262,9 @@ Outstanding issues are listed in the [TODO.md][] file.
[Heimdal]: http://www.h5l.org
[Festival]: http://festvox.org/festival/
[Steve Tell]: http://www.cs.unc.edu/~tell/dist.html
[License]: https://github.com/troglobit/editline/blob/master/LICENSE
[License Badge]: https://img.shields.io/badge/License-C%20News-orange.svg
[Travis]: https://travis-ci.org/troglobit/editline
[Travis Status]: https://travis-ci.org/troglobit/editline.png?branch=master
[Coverity Scan]: https://scan.coverity.com/projects/2982
[Coverity Status]: https://scan.coverity.com/projects/2982/badge.svg
<!--
-- Local Variables:
-- mode: markdown
-- End:
-->

68
TODO.md
View File

@@ -1,68 +0,0 @@
TODO
====
Issues in need of work. Mostly compatibility with GNU readline, BSD
[libedit][], and usability improvements.
Remember, the general idea is to keep this library editline small with
no external dependencies, except a C library.
Add support for running in an event loop
----------------------------------------
To be able to use libeditline from within an event loop like [libuEv][]
there are few things to do:
- Refactor `editinput()` and `readline()`. Break out the active code
used for set up and teardown, and the character input logic
- Add bare necessities for external callbacks so that an event loop
that monitors `el_infd` has something to call on events
- GNU Readline has its [alternate interface][gnu] which we should
probably implement
Example usecase of the GNU alternate interface can be found here:
http://www.mcld.co.uk/blog/blog.php?274
Verify custom completion handlers
---------------------------------
Verify for v1.14.0 that custom completion handlers still work After
reverting a "fix" in v0.2.2 that made `rl_complete()` a function pointer
we need to make sure the same functionality is still available with the
new infrastructure. Which is more inspired by BSD libedit and GNU
readline.
Check what's needed to run the fileman example
----------------------------------------------
The BSD libedit library has imported the GNU readline "fileman" example
into its tree to demonstrate the abilities of that library. This would
also be quite useful for this library!
The first task is to investigate the depependencies and form TODO list
items detailing what is missing and, if possible, proposals how to
implement including any optional configure flags.
Other minor TODO's
------------------
- Instead of supporting multiline input, try the Emacs approach, line
scrolling.
- Add support for `rl_bind_key()`, currently only en editline specific
`el_bind_key()` exists.
- Make `char *rl_prompt;` globally visible.
- Add support for `rl_set_prompt()`
- Add support for `--enable-utf8` to configure script
- Use `strcmp(nl_langinfo(CODESET), "UTF-8")` to look for utf8 capable
terminal
- Implement simple UTF-8 parser according to
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
[gnu]: http://www.delorie.com/gnu/docs/readline/rlman_41.html#IDX288
[libuEv]: https://github.com/troglobit/libuev/
[libedit]: http://www.thrysoee.dk/editline/

View File

@@ -1,4 +1,4 @@
AC_INIT(editline, 1.15.3, https://github.com/troglobit/editline/issues)
AC_INIT(editline, 1.16.0, https://github.com/troglobit/editline/issues)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
AM_SILENT_RULES([yes])
@@ -20,7 +20,7 @@ AC_HEADER_STAT
AC_HEADER_STDC
# Check for malloc.h instead of AC_FUNC_MALLOC/REALLOC AIX and others
# mess up the traditional malloc check.
AC_CHECK_HEADERS([malloc.h signal.h stdlib.h string.h termcap.h termio.h termios.h sgtty.h])
AC_CHECK_HEADERS([malloc.h signal.h stdlib.h string.h termcap.h termio.h termios.h sgtty.h unistd.h])
# In termios.h or in sys/ioctl.g?
AC_HEADER_TIOCGWINSZ
@@ -42,9 +42,6 @@ AC_ARG_ENABLE(unique-history,
[AS_HELP_STRING([--disable-unique-history],
[Disable uniqify of scrollback. Default: duplicate entries are ignored. Use this to save dupes.])])
AC_ARG_ENABLE(default-complete,
[AS_HELP_STRING([--disable-default-complete], [Disable default (filename) completion handler.])])
AC_ARG_ENABLE(arrow-keys,
[AS_HELP_STRING([--disable-arrow-keys], [Disable ANSI arrow keys.])])
@@ -69,9 +66,6 @@ AC_ARG_ENABLE(termcap,
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_default_complete" != "xno"],
AC_DEFINE(CONFIG_DEFAULT_COMPLETE, 1, [Define to enable the default completion handler.]))
AS_IF([test "x$enable_terminal_bell" != "xno"],
AC_DEFINE(CONFIG_ANSI_ARROWS, 1, [Define to include ANSI arrow keys support.]))

7
debian/.gitignore vendored
View File

@@ -1,5 +1,10 @@
*.log
*.debhelper
*.substvars
autoreconf.*
debhelper-build-stamp
files
tmp/*
tmp/*
libeditline-dev/*
libeditline0/*
libeditline1/*

11
debian/changelog vendored
View File

@@ -1,3 +1,14 @@
editline (1.16.0) unstable; urgency=medium
* New upstream release, v1.60.0
+ Event loop support
+ New GNU Readline compat functions and callbacks
+ Minor compat fixes for movement and deletion
* Bump .so/ABI version => libeditline1
* New maintainer, upstream author
-- Joachim Nilsson <troglobit@gmail.com> Sun, 16 Sep 2018 09:45:53 +0200
editline (1.15.3-1) unstable; urgency=medium
* New upstream bug fix release, v1.15.3

6
debian/control vendored
View File

@@ -2,13 +2,13 @@ Source: editline
Section: devel
Priority: optional
Build-Depends: debhelper (>= 5.0), libtool
Maintainer: Sam Hocevar <sho@debian.org>
Maintainer: Joachim Nilsson <troglobit@gmail.com>
Standards-Version: 3.8.3
Package: libeditline-dev
Architecture: any
Section: libdevel
Depends: libeditline0 (= ${binary:Version}), ${misc:Depends}
Depends: libeditline1 (= ${binary:Version}), ${misc:Depends}
Description: development files for libeditline
This is a line-editing library. It can be linked into almost any program
to provide command-line editing and recall. It is call-compatible with a
@@ -18,7 +18,7 @@ Description: development files for libeditline
This package contains the developer files: static libraries, headers,
manpages.
Package: libeditline0
Package: libeditline1
Architecture: any
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (native)

106
docs/HACKING.md Normal file
View File

@@ -0,0 +1,106 @@
Maintenance and Release Checklist
=================================
Maintenance
-----------
* Encourage contributors to write tests, in particular for new features
* Run tests regularly, use Travis-CI to do this automatically
* Leverage GitHub issues for milestone planning
* Reference issues from GitHub pull requests to alert issue subscribers
* Bump library ABI version just before release!
Release Checklist
-----------------
* Update ChangeLog, follow http://keepachangelog.com/ loosely
- Inform users in a plain language of changes and bug fixes
- Do *not* copy-paste GIT commit logs!
- Order entries according to importance, most relevant first
* Run unit tests: `make check`
* Make at least one `-rcN` release and test it in an actual real project
* **REMEMBER:** bump ABI version according to below rules
* Tag
* Push last commit(s) *and* tags to GitHub
* Make release
make distclean
./autogen.sh
./configure
make release
* Create new release in GitHub releases page
* Copy and paste ChangeLog entry, check any stale links!
* Upload release tarball and MD5 files
Library Versioning
------------------
Editline relies on GNU Libtool for building the library. For a user of
the library it is important to maintain a clear ABI versioning scheme.
This is not the same as the Editline version, but rather the library
"compatibility level".
The Editline ABI version is specified in `src/Makefile.am` and looks
like this:
libeditline_la_LDFLAGS = -version-info 0:0:0
\ \ `-- age
\ `--- revision
`---- current
It must be updated according to the [GNU Libtool recommendations][1]:
1. Start with version information of `0:0:0` for each libtool library.
2. Update the version information only immediately before a public
release of your software. More frequent updates are unnecessary, and
only guarantee that the current interface number gets larger faster.
3. If the library *source code has changed at all* since the last update,
then increment revision (`c:r:a` becomes `c:r+1:a`).
4. If any *interfaces have been added, removed, or changed* since the
last update, increment current, and set revision to 0.
5. If any *interfaces have been added* since the last public release,
then increment age.
6. If any *interfaces have been removed or changed* since the last
public release, then set age to 0.
The libtool ABI versioning logic is very confusing but works if you just
disable your brain and follow the rules, one by one.
**Example #1:** a new function has been added, none of the existing ones
have changed. The initial version is 1:0:0, we follow the rules above to
the letter: increase revision, increase current and set revision to zero,
and finally increase age. This, rather confusingly, gives us 2:0:1 which
libtool then translates to `libeditline.so.1.1.0`.
**Example #2:** some existing functions are changed, they now return an
`int` instead of `void`. The initial version is 0:0:0, and we follow the
rules again: increment revision, increment current and set revision to
zero, set age to zero. This gives us 1:0:0, which is then translated to
`libeditline.so.1.0.0`.
### Note
Usually, non-developers have no interest in running development versions
(releases are frequent enough), and developers are expected to know how
to juggle versions. In such an ideal world, it is good enough to bump
the library version just prior to a release, point 2.
However, if releases are few and far between, distributors may start to
use snapshots. When a distributor uses a snapshot, the distributor has
to handle the library version manually. Things can get ugly when the
distributor has released an intermediate version with a bumped library
version, and when the official release is bumped to that version, the
distributor will then have to bump the library version for the official
release, and it can be confusing if someone reports bugs on versions
that you didn't even know existed.
The problem with bumping the version with every change is that if your
interface is not finished, the version number might run away, and it
looks pretty bad if a library is at version 262. It kind of tells the
user that the library interface is volatile, which is not good for
business.
[1]: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html

41
docs/TODO.md Normal file
View File

@@ -0,0 +1,41 @@
TODO
====
Issues in need of work. Mostly compatibility with GNU readline,
BSD [libedit][], and usability improvements.
Remember, the general idea is to keep this library small with no
external dependencies, except for a generic C library.
Check what's needed to run the fileman example
----------------------------------------------
The BSD libedit library has imported the GNU readline "fileman" example
into its tree to demonstrate the abilities of that library. This would
also be quite useful for this library!
The first task is to investigate the depependencies and form TODO list
items detailing what is missing and, if possible, proposals how to
implement including any optional configure flags.
Other minor TODO's
------------------
- Instead of supporting multiline input, try the Emacs approach, line
scrolling.
- Add support for `rl_bind_key()`, currently only en editline specific
`el_bind_key()` exists.
- Make `char *rl_prompt;` globally visible.
- Add support for `rl_set_prompt()`
- Add support for `--enable-utf8` to configure script
- Use `strcmp(nl_langinfo(CODESET), "UTF-8")` to look for utf8 capable
terminal
- Implement simple UTF-8 parser according to
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
[gnu]: http://www.delorie.com/gnu/docs/readline/rlman_41.html#IDX288
[libuEv]: https://github.com/troglobit/libuev/
[libedit]: http://www.thrysoee.dk/editline/

2
examples/.gitignore vendored
View File

@@ -1,3 +1,5 @@
*.o
cli
testit
excallback
fileman

View File

@@ -1,4 +1,5 @@
noinst_PROGRAMS = testit cli
noinst_PROGRAMS = testit cli excallback fileman
LDADD = $(top_builddir)/src/libeditline.la
AM_CPPFLAGS = -DEDITLINE_LIBRARY
AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include
AM_LDFLAGS = -static

View File

@@ -25,59 +25,55 @@
#define HISTORY "/tmp/.cli-history"
static char *list[] = {
"foo ", "bar ", "bsd ", "cli ", "ls ", "cd ", "malloc ", "tee ", NULL
"foo ", "bar ", "bsd ", "cli ", "ls ", "cd ", "malloc ", "tee ", NULL
};
/* Attempt to complete the pathname, returning an allocated copy.
* Fill in *unique if we completed it, or set it to 0 if ambiguous. */
static char *my_rl_complete(char *token, int *match)
{
int i;
int index = -1;
int matchlen = 0;
int count = 0;
int i;
int index = -1;
int matchlen = 0;
int count = 0;
for (i = 0; list[i]; i++)
{
int partlen = strlen (token); /* Part of token */
for (i = 0; list[i]; i++) {
int partlen = strlen (token); /* Part of token */
if (!strncmp (list[i], token, partlen))
{
index = i;
matchlen = partlen;
count ++;
}
}
if (!strncmp (list[i], token, partlen)) {
index = i;
matchlen = partlen;
count ++;
}
}
if (count == 1)
{
*match = 1;
return strdup (list[index] + matchlen);
}
if (count == 1) {
*match = 1;
return strdup (list[index] + matchlen);
}
return NULL;
return NULL;
}
/* Return all possible completions. */
static int my_rl_list_possib(char *token, char ***av)
{
int i, num, total = 0;
char **copy;
int i, num, total = 0;
char **copy;
for (num = 0; list[num]; num++)
;
copy = (char **) malloc (num * sizeof(char *));
for (i = 0; i < num; i++)
{
if (!strncmp (list[i], token, strlen (token)))
{
copy[total] = strdup (list[i]);
total ++;
}
}
*av = copy;
for (num = 0; list[num]; num++)
;
return total;
copy = (char **) malloc (num * sizeof(char *));
for (i = 0; i < num; i++) {
if (!strncmp (list[i], token, strlen (token))) {
copy[total] = strdup (list[i]);
total ++;
}
}
*av = copy;
return total;
}
el_status_t list_possible(void)
@@ -104,42 +100,49 @@ el_status_t list_possible(void)
el_status_t do_break(void)
{
puts("Breakout!");
return CSeof;
puts("Breakout!");
return CSeof;
}
el_status_t do_exit(void)
{
puts("Bye bye!");
return CSeof;
puts("Bye bye!");
return CSeof;
}
el_status_t do_suspend(void)
{
puts("Abort!");
return CSstay;
puts("Abort!");
return CSstay;
}
int main(int ac __attribute__ ((unused)), char *av[] __attribute__ ((unused)))
int main(void)
{
char *line;
char *prompt = "cli> ";
char *line;
char *prompt = "cli> ";
/* Setup callbacks */
rl_set_complete_func(&my_rl_complete);
rl_set_list_possib_func(&my_rl_list_possib);
el_bind_key('?', list_possible);
el_bind_key(CTL('C'), do_break);
el_bind_key(CTL('D'), do_exit);
el_bind_key(CTL('Z'), do_suspend);
read_history(HISTORY);
/* Setup callbacks */
rl_set_complete_func(&my_rl_complete);
rl_set_list_possib_func(&my_rl_list_possib);
el_bind_key('?', list_possible);
el_bind_key(CTL('C'), do_break);
el_bind_key(CTL('D'), do_exit);
el_bind_key(CTL('Z'), do_suspend);
read_history(HISTORY);
while ((line = readline(prompt)) != NULL) {
printf("\t\t\t|%s|\n", line);
free(line);
}
while ((line = readline(prompt)) != NULL) {
printf("\t\t\t|%s|\n", line);
free(line);
}
write_history(HISTORY);
write_history(HISTORY);
return 0;
return 0;
}
/**
* Local Variables:
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

195
examples/excallback.c Normal file
View File

@@ -0,0 +1,195 @@
/*
From: Jeff Solomon <jsolomon@stanford.edu>
Date: Fri, 9 Apr 1999 10:13:27 -0700 (PDT)
To: chet@po.cwru.edu
Subject: new readline example
Message-ID: <14094.12094.527305.199695@mrclean.Stanford.EDU>
Chet,
I've been using readline 4.0. Specifically, I've been using the perl
version Term::ReadLine::Gnu. It works great.
Anyway, I've been playing around the alternate interface and I wanted
to contribute a little C program, callback.c, to you that you could
use as an example of the alternate interface in the /examples
directory of the readline distribution.
My example shows how, using the alternate interface, you can
interactively change the prompt (which is very nice imo). Also, I
point out that you must roll your own terminal setting when using the
alternate interface because readline depreps (using your parlance) the
terminal while in the user callback. I try to demostrate what I mean
with an example. I've included the program below.
To compile, I just put the program in the examples directory and made
the appropriate changes to the EXECUTABLES and OBJECTS line and added
an additional target 'callback'.
I compiled on my Sun Solaris2.6 box using Sun's cc.
Let me know what you think.
Jeff
*/
#if defined (HAVE_CONFIG_H)
#include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <termios.h> /* xxx - should make this more general */
#ifdef EDITLINE_LIBRARY
# include "editline.h"
#else
# include <readline/readline.h>
#endif
/* This little examples demonstrates the alternate interface to using readline.
* In the alternate interface, the user maintains control over program flow and
* only calls readline when STDIN is readable. Using the alternate interface,
* you can do anything else while still using readline (like talking to a
* network or another program) without blocking.
*
* Specifically, this program highlights two importants features of the
* alternate interface. The first is the ability to interactively change the
* prompt, which can't be done using the regular interface since rl_prompt is
* read-only.
*
* The second feature really highlights a subtle point when using the alternate
* interface. That is, readline will not alter the terminal when inside your
* callback handler. So let's so, your callback executes a user command that
* takes a non-trivial amount of time to complete (seconds). While your
* executing the command, the user continues to type keystrokes and expects them
* to be re-echoed on the new prompt when it returns. Unfortunately, the default
* terminal configuration doesn't do this. After the prompt returns, the user
* must hit one additional keystroke and then will see all of his previous
* keystrokes. To illustrate this, compile and run this program. Type "sleep" at
* the prompt and then type "bar" before the prompt returns (you have 3
* seconds). Notice how "bar" is re-echoed on the prompt after the prompt
* returns? This is what you expect to happen. Now comment out the 4 lines below
* the line that says COMMENT LINE BELOW. Recompile and rerun the program and do
* the same thing. When the prompt returns, you should not see "bar". Now type
* "f", see how "barf" magically appears? This behavior is un-expected and not
* desired.
*/
void process_line(char *line);
int change_prompt(void);
char *get_prompt(void);
int prompt = 1;
char prompt_buf[40], line_buf[256];
tcflag_t old_lflag;
cc_t old_vtime;
struct termios term;
int
main()
{
fd_set fds;
/* Adjust the terminal slightly before the handler is installed. Disable
* canonical mode processing and set the input character time flag to be
* non-blocking.
*/
if( tcgetattr(STDIN_FILENO, &term) < 0 ) {
perror("tcgetattr");
exit(1);
}
old_lflag = term.c_lflag;
old_vtime = term.c_cc[VTIME];
term.c_lflag &= ~ICANON;
term.c_cc[VTIME] = 1;
/* COMMENT LINE BELOW - see above */
if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) {
perror("tcsetattr");
exit(1);
}
// rl_add_defun("change-prompt", change_prompt, CTRL('t'));
rl_callback_handler_install(get_prompt(), process_line);
while(1) {
FD_ZERO(&fds);
FD_SET(fileno(stdin), &fds);
if( select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) {
perror("select");
exit(1);
}
if( FD_ISSET(fileno(stdin), &fds) ) {
rl_callback_read_char();
}
}
return 0;
}
void
process_line(char *line)
{
if( line == NULL ) {
fprintf(stderr, "\n");
/* reset the old terminal setting before exiting */
term.c_lflag = old_lflag;
term.c_cc[VTIME] = old_vtime;
if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) {
perror("tcsetattr");
exit(1);
}
exit(0);
}
if( strcmp(line, "sleep") == 0 ) {
sleep(3);
} else {
fprintf(stderr, "|%s|\n", line);
}
free (line);
}
int
change_prompt(void)
{
/* toggle the prompt variable */
prompt = !prompt;
/* save away the current contents of the line */
strncpy(line_buf, rl_line_buffer, sizeof(line_buf));
line_buf[sizeof(line_buf) - 1] = 0;
/* install a new handler which will change the prompt and erase the current line */
rl_callback_handler_install(get_prompt(), process_line);
/* insert the old text on the new line */
rl_insert_text(line_buf);
/* redraw the current line - this is an undocumented function. It invokes the
* redraw-current-line command.
*/
return rl_refresh_line(0, 0);
}
char *
get_prompt(void)
{
/* The prompts can even be different lengths! */
sprintf(prompt_buf, "%s",
prompt ? "Hit ctrl-t to toggle prompt> " : "Pretty cool huh?> ");
return prompt_buf;
}

487
examples/fileman.c Normal file
View File

@@ -0,0 +1,487 @@
/* fileman.c -- A tiny application which demonstrates how to use the
GNU Readline library. This application interactively allows users
to manipulate files and their modes.
NOTE: this was taken from the GNU Readline documentation and ported
to libedit. A command to output the history list was added.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
#include <time.h>
#include "editline.h"
void * xmalloc (size_t size);
void too_dangerous (char *caller);
void initialize_readline ();
int execute_line (char *line);
int valid_argument (char *caller, char *arg);
typedef int rl_icpfunc_t (char *);
/* The names of functions that actually do the manipulation. */
int com_list (char *);
int com_view (char *);
int com_history (char *);
int com_rename(char *);
int com_stat(char *);
int com_pwd(char *);
int com_delete(char *);
int com_help(char *);
int com_cd(char *);
int com_quit(char *);
/* A structure which contains information on the commands this program
can understand. */
typedef struct {
char *name; /* User printable name of the function. */
rl_icpfunc_t *func; /* Function to call to do the job. */
char *doc; /* Documentation for this function. */
} COMMAND;
COMMAND commands[] = {
{ "cd", com_cd, "Change to directory DIR" },
{ "delete", com_delete, "Delete FILE" },
{ "help", com_help, "Display this text" },
{ "?", com_help, "Synonym for `help'" },
{ "list", com_list, "List files in DIR" },
{ "ls", com_list, "Synonym for `list'" },
{ "pwd", com_pwd, "Print the current working directory" },
{ "quit", com_quit, "Quit using Fileman" },
{ "rename", com_rename, "Rename FILE to NEWNAME" },
{ "stat", com_stat, "Print out statistics on FILE" },
{ "view", com_view, "View the contents of FILE" },
{ "history", com_history, "List editline history" },
{ (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL }
};
/* Forward declarations. */
char *stripwhite ();
COMMAND *find_command ();
/* The name of this program, as taken from argv[0]. */
char *progname;
/* When non-zero, this means the user is done using this program. */
int done;
char *
dupstr (char* s)
{
char *r;
r = xmalloc (strlen (s) + 1);
strcpy (r, s);
return (r);
}
int
main (int argc __attribute__((__unused__)), char **argv)
{
char *line, *s;
progname = argv[0];
setlocale(LC_CTYPE, "");
initialize_readline(); /* Bind our completer. */
/* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("FileMan: ");
if (!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite(line);
#if 0
if (*s) {
char* expansion;
int result;
result = history_expand(s, &expansion);
if (result < 0 || result == 2) {
fprintf(stderr, "%s\n", expansion);
} else {
add_history(expansion);
execute_line(expansion);
}
free(expansion);
}
#else
execute_line(s);
#endif
free(line);
}
exit (0);
return 0;
}
/* Execute a command line. */
int
execute_line (char *line)
{
register int i;
COMMAND *command;
char *word;
/* Isolate the command word. */
i = 0;
while (line[i] && isspace (line[i]))
i++;
word = line + i;
while (line[i] && !isspace (line[i]))
i++;
if (line[i])
line[i++] = '\0';
command = find_command (word);
if (!command)
{
fprintf (stderr, "%s: No such command for FileMan.\n", word);
return (-1);
}
/* Get argument to command, if any. */
while (isspace (line[i]))
i++;
word = line + i;
/* Call the function. */
return ((*(command->func)) (word));
}
/* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
COMMAND *
find_command (char *name)
{
register int i;
for (i = 0; commands[i].name; i++)
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]);
return ((COMMAND *)NULL);
}
/* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (char *string)
{
register char *s, *t;
for (s = string; isspace (*s); s++)
;
if (*s == 0)
return (s);
t = s + strlen (s) - 1;
while (t > s && isspace (*t))
t--;
*++t = '\0';
return s;
}
/* **************************************************************** */
/* */
/* Interface to Readline Completion */
/* */
/* **************************************************************** */
char *command_generator(const char *, int);
char **fileman_completion(const char *, int, int);
/* 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 ()
{
/* 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;
}
/* Attempt to complete on the contents of TEXT. START and END
bound the region of rl_line_buffer that contains the word to
complete. TEXT is the word to complete. We can use the entire
contents of rl_line_buffer in case we want to do some simple
parsing. Returnthe array of matches, or NULL if there aren't any. */
char **
fileman_completion (const char* text, int start, int end __attribute__((__unused__)))
{
char **matches;
matches = (char **)NULL;
/* If this word is at the start of the line, then it is a command
to complete. Otherwise it is the name of a file in the current
directory. */
if (start == 0)
matches = rl_completion_matches (text, command_generator);
return (matches);
}
/* Generator function for command completion. STATE lets us
know whether to start from scratch; without any state
(i.e. STATE == 0), then we start at the top of the list. */
char *
command_generator (text, state)
const char *text;
int state;
{
static int list_index, len;
char *name;
/* If this is a new word to complete, initialize now. This
includes saving the length of TEXT for efficiency, and
initializing the index variable to 0. */
if (!state)
{
list_index = 0;
len = strlen (text);
}
/* Return the next name which partially matches from the
command list. */
while ((name = commands[list_index].name))
{
list_index++;
if (strncmp (name, text, len) == 0)
return (dupstr(name));
}
/* If no names matched, then return NULL. */
return ((char *)NULL);
}
/* **************************************************************** */
/* */
/* FileMan Commands */
/* */
/* **************************************************************** */
/* String to pass to system (). This is for the LIST, VIEW and RENAME
commands. */
static char syscom[1024];
/* List the file(s) named in arg. */
int
com_list (char *arg)
{
if (!arg)
arg = "";
sprintf (syscom, "ls -FClg %s", arg);
return (system (syscom));
}
int
com_view (char *arg)
{
if (!valid_argument ("view", arg))
return 1;
sprintf (syscom, "more %s", arg);
return (system (syscom));
}
int
com_history(char* arg __attribute__((__unused__)))
{
const char *he;
/* rewind history */
while (el_prev_hist())
;
for (he = el_next_hist(); he != NULL; he = el_next_hist())
printf("%s\n", he);
return 0;
}
int
com_rename (char *arg __attribute__((__unused__)))
{
too_dangerous ("rename");
return (1);
}
int
com_stat (char *arg)
{
struct stat finfo;
if (!valid_argument ("stat", arg))
return (1);
if (stat (arg, &finfo) == -1)
{
perror (arg);
return (1);
}
printf ("Statistics for `%s':\n", arg);
printf ("%s has %ld link%s, and is %lld byte%s in length.\n", arg,
(long) finfo.st_nlink,
(finfo.st_nlink == 1) ? "" : "s",
(long long) finfo.st_size,
(finfo.st_size == 1) ? "" : "s");
printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
printf (" Last access at: %s", ctime (&finfo.st_atime));
printf (" Last modified at: %s", ctime (&finfo.st_mtime));
return (0);
}
int
com_delete (char *arg __attribute__((__unused__)))
{
too_dangerous ("delete");
return (1);
}
/* Print out help for ARG, or for all of the commands if ARG is
not present. */
int
com_help (char *arg)
{
register int i;
int printed = 0;
for (i = 0; commands[i].name; i++)
{
if (!*arg || (strcmp (arg, commands[i].name) == 0))
{
printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
printed++;
}
}
if (!printed)
{
printf ("No commands match `%s'. Possibilties are:\n", arg);
for (i = 0; commands[i].name; i++)
{
/* Print in six columns. */
if (printed == 6)
{
printed = 0;
printf ("\n");
}
printf ("%s\t", commands[i].name);
printed++;
}
if (printed)
printf ("\n");
}
return (0);
}
/* Change to the directory ARG. */
int
com_cd (char *arg)
{
if (chdir (arg) == -1)
{
perror (arg);
return 1;
}
com_pwd ("");
return (0);
}
/* Print out the current working directory. */
int
com_pwd (char* ignore __attribute__((__unused__)))
{
char dir[1024], *s;
s = (char*)getcwd(dir, sizeof(dir) - 1);
if (s == 0)
{
printf ("Error getting pwd: %s\n", dir);
return 1;
}
printf ("Current directory is %s\n", dir);
return 0;
}
/* The user wishes to quit using this program. Just set DONE
non-zero. */
int
com_quit (char *arg __attribute__((__unused__)))
{
done = 1;
return (0);
}
/* Function which tells you that you can't do this. */
void
too_dangerous (char *caller)
{
fprintf (stderr,
"%s: Too dangerous for me to distribute.\n",
caller);
fprintf (stderr, "Write it yourself.\n");
}
/* Return non-zero if ARG is a valid argument for CALLER,
else print an error message and return zero. */
int
valid_argument (char *caller, char *arg)
{
if (!arg || !*arg)
{
fprintf (stderr, "%s: Argument required.\n", caller);
return (0);
}
return (1);
}
void *
xmalloc (size_t size)
{
register void *value = (void*)malloc(size);
if (value == 0)
fprintf(stderr, "virtual memory exhausted");
return value;
}

View File

@@ -45,9 +45,11 @@ int main(int argc, char *argv[] __attribute__ ((unused)))
int doit;
char *prompt, *p;
read_history(".testit_history");
doit = argc == 1;
if ((prompt = getenv("TESTPROMPT")) == NULL)
prompt = "testit> ";
prompt = "testit> ";
while ((p = readline(prompt)) != NULL) {
printf("\t\t\t|%s|\n", p);
@@ -59,18 +61,18 @@ int main(int argc, char *argv[] __attribute__ ((unused)))
perror(p);
}
}
add_history(p);
free(p);
}
write_history(".testit_history");
rl_uninitialize();
return 0;
}
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "ellemtel"
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

View File

@@ -1,6 +1,6 @@
/* Minix editline
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
/*
* Copyright (c) 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.
@@ -18,8 +18,8 @@
* ever read sources, credits must appear in the documentation.
* 4. This notice may not be removed or altered.
*/
#ifndef __EDITLINE_H__
#define __EDITLINE_H__
#ifndef EDITLINE_H_
#define EDITLINE_H_
/* Handy macros when binding keys. */
#define CTL(x) ((x) & 0x1F)
@@ -44,13 +44,18 @@ typedef enum {
} el_status_t;
/* Editline specific types, despite rl_ prefix. From Heimdal project. */
typedef char* rl_complete_func_t(char*, int*);
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 *);
/* FSF Readline compat tupes */
typedef char *rl_complete_func_t (char *, int*);
typedef char *rl_compentry_func_t (const char *, int);
typedef char **rl_completion_func_t (const char *, int, int);
/* Display 8-bit chars "as-is" or as `M-x'? Toggle with M-m. (Default:0 - "as-is") */
extern int rl_meta_chars;
@@ -64,8 +69,13 @@ extern el_status_t el_del_char(void);
extern el_status_t el_bind_key(int key, el_keymap_func_t function);
extern el_status_t el_bind_key_in_metamap(int key, el_keymap_func_t function);
extern const char *el_next_hist(void);
extern const char *el_prev_hist(void);
extern char *rl_complete(char *token, int *match);
extern int rl_list_possib(char *token, char ***av);
extern char **rl_completion_matches(const char *token, rl_compentry_func_t *generator);
extern char *rl_filename_completion_function(const char *text, int state);
/* For compatibility with FSF readline. */
extern int rl_point;
@@ -80,32 +90,41 @@ 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 void rl_initialize(void);
extern void rl_reset_terminal(const char *terminal_name);
extern void rl_initialize (void);
extern void rl_reset_terminal (const char *terminal_name);
extern void rl_uninitialize (void);
void rl_save_prompt(void);
void rl_restore_prompt(void);
void rl_set_prompt(const char *prompt);
extern void rl_save_prompt (void);
extern void rl_restore_prompt (void);
extern void rl_set_prompt (const char *prompt);
void rl_clear_message(void);
void rl_forced_update_display(void);
extern void rl_clear_message (void);
extern void rl_forced_update_display(void);
extern char *readline(const char *prompt);
extern void add_history(const char *line);
extern void rl_prep_terminal (int meta_flag);
extern void rl_deprep_terminal (void);
extern int read_history(const char *filename);
extern int write_history(const char *filename);
extern int rl_getc(void);
extern int rl_insert_text (const char *text);
extern int rl_refresh_line (int ignore1, int ignore2);
rl_complete_func_t *rl_set_complete_func(rl_complete_func_t *func);
rl_list_possib_func_t *rl_set_list_possib_func(rl_list_possib_func_t *func);
extern char *readline (const char *prompt);
void rl_prep_terminal(int meta_flag);
void rl_deprep_terminal(void);
extern void add_history (const char *line);
extern int read_history (const char *filename);
extern int write_history (const char *filename);
int rl_getc(void);
extern rl_completion_func_t *rl_attempted_completion_function;
extern rl_complete_func_t *rl_set_complete_func (rl_complete_func_t *func);
extern rl_list_possib_func_t *rl_set_list_possib_func (rl_list_possib_func_t *func);
/* Alternate interface to plain readline(), for event loops */
extern void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler);
extern void rl_callback_read_char (void);
extern void rl_callback_handler_remove (void);
#ifdef __cplusplus
}
#endif
#endif /* __EDITLINE_H__ */
#endif /* EDITLINE_H_ */

View File

@@ -173,7 +173,7 @@ The following brief example lets you enter a line and edit it, then displays it.
.B ""
.B extern char *readline(char *prompt);
.B ""
.B int main (void)
.B int main(void)
.B {
.RS
.B char *p;
@@ -189,12 +189,12 @@ The following brief example lets you enter a line and edit it, then displays it.
.RE
.B }
.fi
.SH BUGS AND LIMITATIONS
Does not handle multiple lines or unicode characters well. See the TODO
file in the distribution if you want to help out.
.SH AUTHORS
The original editline library was created by Simmule R. Turner and Rich
$alz. It now exists in several forks: Heimdal, Festival speech tools,
Salz. It now exists in several forks: Heimdal, Festival speech tools,
Mozilla, Google Gadgets for Linux, and many other places. The original
manual page was made by David W. Sanderson. Currently maintained by
Joachim Nilsson at http://github.com/troglobit/editline
manual page was made by David W. Sanderson. This version is maintained
by Joachim Nilsson at GitHub,
.Aq http://github.com/troglobit/editline
.SH BUGS
Does not handle multiple lines or unicode characters well.

View File

@@ -1,6 +1,6 @@
lib_LTLIBRARIES = libeditline.la
libeditline_la_SOURCES = editline.c editline.h complete.c sysunix.c unix.h
libeditline_la_CFLAGS = -std=gnu99
libeditline_la_CFLAGS += -W -Wall -Wundef -Wunused -Wstrict-prototypes
libeditline_la_CFLAGS += -W -Wall -Wextra -Wundef -Wunused -Wstrict-prototypes
libeditline_la_CFLAGS += -Werror-implicit-function-declaration -Wshadow -Wcast-qual
libeditline_la_LDFLAGS = $(AM_LDFLAGS) -version-info 0:0:0
libeditline_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0

View File

@@ -1,6 +1,7 @@
/* History and file completion functions for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
* Copyright (c) 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.
@@ -19,10 +20,15 @@
* 4. This notice may not be removed or altered.
*/
#include <ctype.h>
#include "editline.h"
#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)
{
@@ -74,6 +80,7 @@ static int FindMatches(char *dir, char *file, char ***avp)
total = 0;
break;
}
if (ac) {
memcpy(word, av, ac * sizeof(char *));
free(av);
@@ -94,15 +101,22 @@ static int FindMatches(char *dir, char *file, char ***avp)
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;
*--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;
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);
@@ -112,7 +126,7 @@ static int FindMatches(char *dir, char *file, char ***avp)
}
/* Split a pathname into allocated directory and trailing filename parts. */
static int SplitPath(char *path, char **dirpart, char **filepart)
static int SplitPath(const char *path, char **dirpart, char **filepart)
{
static char DOT[] = ".";
char *dpart;
@@ -121,6 +135,7 @@ static int SplitPath(char *path, char **dirpart, char **filepart)
if ((fpart = strrchr(path, '/')) == NULL) {
if ((dpart = strdup(DOT)) == NULL)
return -1;
if ((fpart = strdup(path)) == NULL) {
free(dpart);
return -1;
@@ -128,6 +143,7 @@ static int SplitPath(char *path, char **dirpart, char **filepart)
} else {
if ((dpart = strdup(path)) == NULL)
return -1;
dpart[fpart - path + 1] = '\0';
if ((fpart = strdup(fpart + 1)) == NULL) {
free(dpart);
@@ -147,6 +163,7 @@ 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;
}
@@ -165,7 +182,7 @@ char *el_filename_complete(char *pathname, int *match)
size_t j;
size_t len;
if (SplitPath(pathname, &dir, &file) < 0)
if (SplitPath((const char *)pathname, &dir, &file) < 0)
return NULL;
if ((ac = FindMatches(dir, file, &av)) == 0) {
@@ -196,11 +213,13 @@ char *el_filename_complete(char *pathname, int *match)
*match = 0;
if (len) {
/* Find largest matching substring. */
for (i = len, end = strlen(av[0]); i < end; i++)
for (j = 1; j < ac; j++)
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:
}
}
breakout:
if (i > len) {
j = i - len + 1;
p = malloc(sizeof(char) * j);
@@ -222,16 +241,160 @@ char *el_filename_complete(char *pathname, int *match)
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);
#ifdef CONFIG_DEFAULT_COMPLETE
if (rl_attempted_completion_function)
return complete(token, match);
return el_filename_complete(token, match);
#else
return NULL;
#endif
}
static rl_list_possib_func_t *el_list_possib_func = NULL;
@@ -267,18 +430,13 @@ int rl_list_possib(char *token, char ***av)
if (el_list_possib_func)
return el_list_possib_func(token, av);
#ifdef CONFIG_DEFAULT_COMPLETE
return el_filename_list_possib(token, av);
#else
return 0;
#endif
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "ellemtel"
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
/* Internal header file for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
* Copyright (c) 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.
@@ -19,8 +20,8 @@
* 4. This notice may not be removed or altered.
*/
#ifndef __PRIVATE_EDITLINE_H__
#define __PRIVATE_EDITLINE_H__
#ifndef EDITLINE_PRIVATE_H_
#define EDITLINE_PRIVATE_H_
#include <config.h>
#include <stdio.h>
@@ -95,4 +96,4 @@ extern char *strdup(const char *s);
#endif
#include "../include/editline.h"
#endif /* __PRIVATE_EDITLINE_H__ */
#endif /* EDITLINE_PRIVATE_H_ */

View File

@@ -1,6 +1,7 @@
/* Editline system header file for OS-9 (on 68k).
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
* Copyright (c) 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.

View File

@@ -1,6 +1,7 @@
/* OS-9 (on 68k) system-dependant routines for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
* Copyright (c) 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.
@@ -57,8 +58,7 @@ void rl_add_slash(char *path, char *p)
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "ellemtel"
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

View File

@@ -1,6 +1,7 @@
/* Unix system-dependant routines for editline library.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
* Copyright (c) 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.
@@ -87,6 +88,7 @@ void rl_ttyset(int Reset)
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];
@@ -124,6 +126,7 @@ void rl_ttyset(int Reset)
if (!Reset) {
if (-1 == ioctl_wrap(0, TCGETA, &old))
perror("Failed ioctl(TCGETA)");
rl_erase = old.c_cc[VERASE];
rl_kill = old.c_cc[VKILL];
rl_eof = old.c_cc[VEOF];
@@ -167,19 +170,22 @@ void rl_ttyset(int Reset)
if (!Reset) {
if (-1 == ioctl_wrap(0, TIOCGETP, &old_sgttyb))
perror("Failed TIOCGETP");
rl_erase = old_sgttyb.sg_erase;
rl_kill = old_sgttyb.sg_kill;
if (-1 == ioctl_wrap(0, TIOCGETC, &old_tchars))
perror("Failed TIOCGETC");
rl_eof = old_tchars.t_eofc;
rl_eof = old_tchars.t_eofc;
rl_intr = old_tchars.t_intrc;
rl_quit = old_tchars.t_quitc;
#ifdef CONFIG_SIGSTOP
if (-1 == ioctl_wrap(0, TIOCGLTC, &old_ltchars))
perror("Failed TIOCGLTC");
rl_susp = old_ltchars.t_suspc;
rl_susp = old_ltchars.t_suspc;
#endif
new_sgttyb = old_sgttyb;
@@ -189,9 +195,11 @@ void rl_ttyset(int Reset)
new_sgttyb.sg_flags &= ~PASS8;
else
new_sgttyb.sg_flags |= PASS8;
if (-1 == ioctl_wrap(0, TIOCSETP, &new_sgttyb))
if (-1 == ioctl_wrap(0, TIOCSETP, &new_sgttyb))
perror("Failed TIOCSETP");
new_tchars = old_tchars;
new_tchars = old_tchars;
new_tchars.t_intrc = -1;
new_tchars.t_quitc = -1;
if (-1 == ioctl_wrap(0, TIOCSETC, &new_tchars))
@@ -199,7 +207,8 @@ void rl_ttyset(int Reset)
} else {
if (-1 == ioctl_wrap(0, TIOCSETP, &old_sgttyb))
perror("Failed TIOCSETP");
if (-1 == ioctl_wrap(0, TIOCSETC, &old_tchars))
if (-1 == ioctl_wrap(0, TIOCSETC, &old_tchars))
perror("Failed TIOCSETC");
}
}
@@ -209,14 +218,18 @@ void rl_ttyset(int Reset)
#ifndef HAVE_STRDUP
/* Return an allocated copy of a string. */
char *strdup(const char *p)
char *strdup(const char *s)
{
char *new = malloc(sizeof(char) * strlen(p));
size_t len;
char *ptr;
if (new) {
strcpy(new, p);
return new;
}
if (!s)
return NULL;
len = strlen(s) + 1;
ptr = malloc(len);
if (ptr)
return memcpy(ptr, s, len);
return NULL;
}
@@ -232,8 +245,7 @@ void rl_add_slash(char *path, char *p)
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "ellemtel"
* c-file-style: "k&r"
* c-basic-offset: 4
* End:
*/

View File

@@ -1,6 +1,7 @@
/* Editline system header file for Unix.
*
* Copyright (c) 1992, 1993 Simmule Turner and Rich Salz. All rights reserved.
* Copyright (c) 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.
@@ -19,8 +20,8 @@
* 4. This notice may not be removed or altered.
*/
#ifndef __EDITLINE_UNIX_H__
#define __EDITLINE_UNIX_H__
#ifndef EDITLINE_UNIX_H_
#define EDITLINE_UNIX_H_
#define CRLF "\r\n"
#define FORWARD STATIC
@@ -32,4 +33,4 @@
#include <dirent.h>
typedef struct dirent DIRENTRY;
#endif /* __EDITLINE_UNIX_H__ */
#endif /* EDITLINE_UNIX_H_ */