mirror of
https://github.com/louisrubet/rpn
synced 2025-01-18 10:26:57 +01:00
First attempt: autocompletion and history
This commit is contained in:
parent
56371b58a4
commit
4eb7c132ca
4 changed files with 90 additions and 43 deletions
|
@ -1,6 +1,7 @@
|
||||||
AUTOMAKE_OPTIONS = subdir-objects
|
AUTOMAKE_OPTIONS = subdir-objects
|
||||||
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
|
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
|
|
||||||
bin_PROGRAMS = rpn
|
bin_PROGRAMS = rpn
|
||||||
rpn_SOURCES = src/rpn.cpp \
|
rpn_SOURCES = src/rpn.cpp \
|
||||||
src/rpn-branch.h \
|
src/rpn-branch.h \
|
||||||
|
@ -15,4 +16,6 @@ rpn_SOURCES = src/rpn.cpp \
|
||||||
src/rpn-trig.h \
|
src/rpn-trig.h \
|
||||||
src/stack.h
|
src/stack.h
|
||||||
|
|
||||||
|
rpn_LDFLAGS = -lreadline
|
||||||
|
|
||||||
dist_noinst_SCRIPTS = autogen.sh
|
dist_noinst_SCRIPTS = autogen.sh
|
||||||
|
|
103
src/parse.h
103
src/parse.h
|
@ -266,30 +266,89 @@ static ret_value parse(const string& entry, program& prog)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ret_value parse_line(const string& entry, program& prog)
|
// interactive entry and decoding
|
||||||
|
static ret_value entry(program& prog)
|
||||||
{
|
{
|
||||||
vector<string> entries;
|
char *buf;
|
||||||
ret_value ret = ret_ok;
|
ret_value ret;
|
||||||
cmd_type_t type;
|
|
||||||
unsigned int obj_size;
|
|
||||||
object* obj;
|
|
||||||
|
|
||||||
//1. cut global entry string into shorter strings
|
// declare completion fn
|
||||||
if (_cut(entry, entries))
|
rl_attempted_completion_function = entry_completion;
|
||||||
|
|
||||||
|
// get user entry
|
||||||
|
buf = readline(prompt);
|
||||||
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
//2. make an object from each entry, and add it to the program
|
string entry = buf;
|
||||||
for (vector<string>::iterator it = entries.begin(); it != entries.end(); it++)
|
|
||||||
{
|
|
||||||
if(_obj_from_string((*it), obj, obj_size, type))
|
|
||||||
{
|
|
||||||
prog.push_back(obj, obj_size, type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no syntax error for now, an unknown obj form is considered as a symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
//enable auto-complete
|
||||||
|
rl_bind_key('\t',rl_complete);
|
||||||
|
|
||||||
|
// parse it
|
||||||
|
ret = parse(entry, prog);
|
||||||
|
|
||||||
|
// keep history
|
||||||
|
if (buf[0]!=0)
|
||||||
|
add_history(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = ret_internal;
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char** entry_completion(const char* text, int start, int end)
|
||||||
|
{
|
||||||
|
char** matches;
|
||||||
|
|
||||||
|
matches = (char**)NULL;
|
||||||
|
|
||||||
|
if (start == 0)
|
||||||
|
matches = rl_completion_matches((char*)text, &entry_completion_generator);
|
||||||
|
else
|
||||||
|
rl_bind_key('\t',rl_abort);
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* entry_completion_generator(const char* text, int state)
|
||||||
|
{
|
||||||
|
static int list_index, len, too_far;
|
||||||
|
char* name;
|
||||||
|
|
||||||
|
if (!state)
|
||||||
|
{
|
||||||
|
list_index = 0;
|
||||||
|
too_far = 0;
|
||||||
|
len = strlen(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(too_far == 0)
|
||||||
|
{
|
||||||
|
if (_keywords[list_index].fn == NULL)
|
||||||
|
{
|
||||||
|
if (_keywords[list_index].comment.size() == 0)
|
||||||
|
too_far = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_index++;
|
||||||
|
|
||||||
|
// mpo ! ne pas stocker c_str
|
||||||
|
name = (char*)_keywords[list_index].name.c_str();
|
||||||
|
if (strncmp(name, text, len) == 0)
|
||||||
|
return entry_completion_dupstr(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no names matched, then return NULL. */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* entry_completion_dupstr(char* s)
|
||||||
|
{
|
||||||
|
char* r = (char*)malloc((strlen(s)+1));
|
||||||
|
if (r != NULL)
|
||||||
|
strcpy(r, s);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
26
src/rpn.cpp
26
src/rpn.cpp
|
@ -29,12 +29,16 @@
|
||||||
#endif
|
#endif
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#include <readline/history.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
//#include <regex>
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
|
@ -538,26 +542,6 @@ public:
|
||||||
|
|
||||||
ret_value get_err(void) { return _err; }
|
ret_value get_err(void) { return _err; }
|
||||||
|
|
||||||
// interactive entry and decoding
|
|
||||||
static ret_value entry(program& prog)
|
|
||||||
{
|
|
||||||
ret_value ret;
|
|
||||||
string entry;
|
|
||||||
|
|
||||||
// show cursor
|
|
||||||
cout<<g_cursor;
|
|
||||||
|
|
||||||
// get user line
|
|
||||||
getline(cin, entry);
|
|
||||||
if (cin.good())
|
|
||||||
// parse it
|
|
||||||
ret = parse(entry, prog);
|
|
||||||
else
|
|
||||||
ret = ret_internal;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
|
||||||
static void show_stack(stack& st, const string& separator = g_show_stack_separator)
|
static void show_stack(stack& st, const string& separator = g_show_stack_separator)
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
static const char version[] = "1.1";
|
static const char version[] = "1.1";
|
||||||
static const char uname[] = "rpn v1.1, (c) 2013 <louis@rubet.fr>";
|
static const char uname[] = "rpn v1.1, (c) 2013 <louis@rubet.fr>";
|
||||||
|
static const char prompt[] = "rpn> ";
|
||||||
|
|
Loading…
Reference in a new issue