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
|
||||
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
|
||||
|
||||
|
||||
bin_PROGRAMS = rpn
|
||||
rpn_SOURCES = src/rpn.cpp \
|
||||
src/rpn-branch.h \
|
||||
|
@ -15,4 +16,6 @@ rpn_SOURCES = src/rpn.cpp \
|
|||
src/rpn-trig.h \
|
||||
src/stack.h
|
||||
|
||||
rpn_LDFLAGS = -lreadline
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static ret_value parse_line(const string& entry, program& prog)
|
||||
// interactive entry and decoding
|
||||
static ret_value entry(program& prog)
|
||||
{
|
||||
vector<string> entries;
|
||||
ret_value ret = ret_ok;
|
||||
cmd_type_t type;
|
||||
unsigned int obj_size;
|
||||
object* obj;
|
||||
char *buf;
|
||||
ret_value ret;
|
||||
|
||||
//1. cut global entry string into shorter strings
|
||||
if (_cut(entry, entries))
|
||||
// declare completion fn
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
string entry = buf;
|
||||
|
||||
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
|
||||
#include <math.h>
|
||||
|
||||
extern "C" {
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
//#include <regex>
|
||||
using namespace std;
|
||||
|
||||
#include "stack.h"
|
||||
|
@ -538,26 +542,6 @@ public:
|
|||
|
||||
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"
|
||||
|
||||
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 uname[] = "rpn v1.1, (c) 2013 <louis@rubet.fr>";
|
||||
static const char prompt[] = "rpn> ";
|
||||
|
|
Loading…
Reference in a new issue