Hi Antonio,
I'm not sure if you prefer a specific patch format, but I've attached a
git formatted patch for my changes. These are by no means finalised but
I'd like to get your feedback on it, I'm curious to know whether my
ideas are compatible with your vision for the project.
The gist of it is that not having the ability to edit commands before
executing them or have a command history is something that isn't really
expected of programs nowadays, so I've hooked GNU Readline into
get_stdin_line(). It's currently still missing some of the previous
error handling that was there.
Regards,
~Faissal
On 25/09/2020 16:04, Antonio Diaz Diaz wrote:
Hi Faissal,
Faissal Isslam Bensefia wrote:
Hi, I'm looking into making some modifications to The Standard Editor
and was just curious if there was a plan to move to Git at some point?
There are no plans to move to git, but if you plan to share your
modifications, a patch against the latest version is enough.
Best regards,
Antonio.
>From 6149455cdc7501ef30ce56431941e77e5795f8f9 Mon Sep 17 00:00:00 2001
From: Faissal Bensefia <faissa...@gmail.com>
Date: Fri, 25 Sep 2020 16:57:52 +0100
Subject: [PATCH] Improve text entry UX with GNU Readline
---
.gitignore | 5 ++++
Makefile.in | 2 +-
buffer.c | 2 +-
configure | 7 +++--
ed.h | 4 ++-
io.c | 84 ++++++++++++++++++++++++++++++-----------------------
main.c | 3 +-
main_loop.c | 6 ++--
regex.c | 2 +-
9 files changed, 68 insertions(+), 47 deletions(-)
create mode 100644 .gitignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea0fdbb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+ed
+red
+Makefile
+*.o
+config.status
diff --git a/Makefile.in b/Makefile.in
index 18be552..b6359aa 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -20,7 +20,7 @@ objs = buffer.o carg_parser.o global.o io.o main.o main_loop.o regex.o signal.o
all : $(progname) r$(progname)
$(progname) : $(objs)
- $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(objs)
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(objs) $(LIBS)
r$(progname) : r$(progname).in
cat $(VPATH)/r$(progname).in > $@
diff --git a/buffer.c b/buffer.c
index 0a000be..f806d06 100644
--- a/buffer.c
+++ b/buffer.c
@@ -115,7 +115,7 @@ bool append_lines( const char ** const ibufpp, const int addr,
{
if( !isglobal )
{
- *ibufpp = get_stdin_line( &size );
+ *ibufpp = get_stdin_line( &size, true );
if( !*ibufpp ) return false; /* error */
if( size <= 0 ) return true; /* EOF */
}
diff --git a/configure b/configure
index 4594825..0d38d67 100755
--- a/configure
+++ b/configure
@@ -6,7 +6,7 @@
# to copy, distribute, and modify it.
pkgname=ed
-pkgversion=1.16
+pkgversion=1.16-readline
progname=ed
srctrigger=doc/${pkgname}.texi
@@ -24,8 +24,8 @@ program_prefix=
CC=gcc
CPPFLAGS=
CFLAGS='-Wall -W -O2'
-LDFLAGS=
-
+LDFLAGS=''
+LIBS='-lreadline'
# checking whether we are using GNU C.
/bin/sh -c "${CC} --version" > /dev/null 2>&1 ||
{
@@ -196,6 +196,7 @@ CC = ${CC}
CPPFLAGS = ${CPPFLAGS}
CFLAGS = ${CFLAGS}
LDFLAGS = ${LDFLAGS}
+LIBS= ${LIBS}
EOF
cat "${srcdir}/Makefile.in" >> Makefile
diff --git a/ed.h b/ed.h
index dafe674..a3e4ad3 100644
--- a/ed.h
+++ b/ed.h
@@ -96,9 +96,11 @@ bool set_active_node( const line_t * const lp );
void unset_active_nodes( const line_t * bp, const line_t * const ep );
/* defined in io.c */
+void configure_input();
+
bool get_extended_line( const char ** const ibufpp, int * const lenp,
const bool strip_escaped_newlines );
-const char * get_stdin_line( int * const sizep );
+const char * get_stdin_line( int * const sizep, const bool appending_lines );
int linenum( void );
bool print_lines( int from, const int to, const int pflags );
int read_file( const char * const filename, const int addr );
diff --git a/io.c b/io.c
index 4e5da2e..96b23b1 100644
--- a/io.c
+++ b/io.c
@@ -2,6 +2,7 @@
/* GNU ed - The GNU line editor.
Copyright (C) 1993, 1994 Andrew Moore, Talke Studio
Copyright (C) 2006-2020 Antonio Diaz Diaz.
+ Copyright (C) 2020 Faissal Isslam Bensefia.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,6 +21,10 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <malloc.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
#include "ed.h"
@@ -126,7 +131,7 @@ bool get_extended_line( const char ** const ibufpp, int * const lenp,
while( true )
{
int len2;
- const char * const s = get_stdin_line( &len2 );
+ const char * const s = get_stdin_line( &len2, true );
if( !s ) return false; /* error */
if( len2 <= 0 ) return false; /* EOF */
if( !resize_buffer( &buf, &bufsz, len + len2 + 1 ) ) return false;
@@ -143,46 +148,51 @@ bool get_extended_line( const char ** const ibufpp, int * const lenp,
}
+void configure_input() {
+ rl_bind_key('\t', rl_insert);
+ stifle_history(1000); //We should have an .edrc at some point to change this
+}
/* Read a line of text from stdin.
Incomplete lines (lacking the trailing newline) are discarded.
Returns pointer to buffer and line size (including trailing newline),
or 0 if error, or *sizep = 0 if EOF */
-const char * get_stdin_line( int * const sizep )
- {
- static char * buf = 0;
- static int bufsz = 0;
- int i = 0;
-
- while( true )
- {
- const int c = getchar();
- if( !resize_buffer( &buf, &bufsz, i + 2 ) ) { *sizep = 0; return 0; }
- if( c == EOF )
- {
- if( ferror( stdin ) )
- {
- show_strerror( "stdin", errno );
- set_error_msg( "Cannot read stdin" );
- clearerr( stdin );
- *sizep = 0; return 0;
- }
- if( feof( stdin ) )
- {
- set_error_msg( "Unexpected end-of-file" );
- clearerr( stdin );
- buf[0] = 0; *sizep = 0; if( i > 0 ) ++linenum_; /* discard line */
- return buf;
- }
- }
- else
- {
- buf[i++] = c; if( !c ) set_binary(); if( c != '\n' ) continue;
- ++linenum_; buf[i] = 0; *sizep = i;
- return buf;
- }
- }
- }
-
+const char * get_stdin_line( int * const sizep, const bool appending_lines )
+ {
+ static char* buf;
+ static char* historical_buffer;
+ //free what was previously allocated to buf, GNU readline will allocate a new appropriately sized buffer
+ free(buf);
+
+ const char* input_prefix;
+ if (appending_lines) {
+ input_prefix = "> ";
+ } else {
+ input_prefix = "[ed] ";
+ }
+ buf = readline(input_prefix);
+
+ if (buf != NULL) {
+ historical_buffer = malloc(strlen(buf)+1);
+ strcpy(historical_buffer, buf);
+ add_history(historical_buffer);
+
+ //Add a new line because the rest of the program was built with the assumption
+ //that this string would be newline terminated and changing that would be
+ //a nightmare
+ *sizep = strlen(buf)+1;
+ buf[(*sizep)-1]='\n';
+ } else {
+ *sizep = 0;
+ }
+
+ /*
+ if (*sizep > 0) {
+ We should only add the version of the string without the newline here
+
+ }
+ */
+ return buf;
+ }
/* Read a line of text from a stream.
Returns pointer to buffer and line size (including trailing newline
diff --git a/main.c b/main.c
index 6436f77..1eb70e0 100644
--- a/main.c
+++ b/main.c
@@ -92,7 +92,8 @@ static void show_version( void )
{
printf( "GNU %s %s\n", program_name, PROGVERSION );
printf( "Copyright (C) 1994 Andrew L. Moore.\n"
- "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
+ "Copyright (C) %s Antonio Diaz Diaz.\n"
+ "Copyright (C) 2020 Faissal Isslam Bensefia.\n", program_year );
printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n" );
diff --git a/main_loop.c b/main_loop.c
index 66858af..a1c626c 100644
--- a/main_loop.c
+++ b/main_loop.c
@@ -664,7 +664,7 @@ static bool exec_global( const char ** const ibufpp, const int pflags,
int len = 0;
if( !print_lines( current_addr(), current_addr(), pflags ) )
return false;
- *ibufpp = get_stdin_line( &len );
+ *ibufpp = get_stdin_line( &len, false );
if( !*ibufpp ) return false; /* error */
if( len <= 0 ) return false; /* EOF */
if( len == 1 && strcmp( *ibufpp, "\n" ) == 0 ) continue;
@@ -700,6 +700,8 @@ int main_loop( const bool loose )
disable_interrupts();
set_signals();
+ configure_input();
+
status = setjmp( jmp_state );
if( !status ) enable_interrupts();
else { status = -1; fputs( "\n?\n", stdout ); set_error_msg( "Interrupt" ); }
@@ -709,7 +711,7 @@ int main_loop( const bool loose )
fflush( stdout ); fflush( stderr );
if( status < 0 && verbose ) { printf( "%s\n", errmsg ); fflush( stdout ); }
if( prompt_on ) { fputs( prompt_str, stdout ); fflush( stdout ); }
- ibufp = get_stdin_line( &len );
+ ibufp = get_stdin_line( &len, false );
if( !ibufp ) return 2; /* an error happened */
if( len <= 0 ) /* EOF on stdin ('q') */
{
diff --git a/regex.c b/regex.c
index cd4eb15..421753a 100644
--- a/regex.c
+++ b/regex.c
@@ -238,7 +238,7 @@ bool extract_replacement( const char ** const ibufpp, const bool isglobal )
{
/* not reached if isglobal; in command-list, newlines are unescaped */
int size = 0;
- *ibufpp = get_stdin_line( &size );
+ *ibufpp = get_stdin_line( &size, true );
if( !*ibufpp ) return false; /* error */
if( size <= 0 ) return false; /* EOF */
}
--
2.25.1