mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-11 00:36:20 +02:00
Add basic variable name completion
This commit is contained in:
parent
cf4c29d90a
commit
0abdf4beaa
1 changed files with 87 additions and 42 deletions
129
nix-repl.cc
129
nix-repl.cc
|
@ -29,9 +29,15 @@ struct NixRepl
|
||||||
StaticEnv staticEnv;
|
StaticEnv staticEnv;
|
||||||
Env * env;
|
Env * env;
|
||||||
int displ;
|
int displ;
|
||||||
|
StringSet varNames;
|
||||||
|
|
||||||
|
StringSet completions;
|
||||||
|
StringSet::iterator curCompletion;
|
||||||
|
|
||||||
NixRepl();
|
NixRepl();
|
||||||
void mainLoop(const Strings & args);
|
void mainLoop(const Strings & args);
|
||||||
|
void completePrefix(string prefix);
|
||||||
|
bool getLine(string & line);
|
||||||
void processLine(string line);
|
void processLine(string line);
|
||||||
void loadFile(const Path & path);
|
void loadFile(const Path & path);
|
||||||
void addAttrsToScope(Value & attrs);
|
void addAttrsToScope(Value & attrs);
|
||||||
|
@ -47,48 +53,6 @@ void printHelp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Apparently, the only way to get readline() to return on Ctrl-C
|
|
||||||
(SIGINT) is to use siglongjmp(). That's fucked up... */
|
|
||||||
static sigjmp_buf sigintJmpBuf;
|
|
||||||
|
|
||||||
|
|
||||||
static void sigintHandler(int signo)
|
|
||||||
{
|
|
||||||
siglongjmp(sigintJmpBuf, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool getLine(string & line)
|
|
||||||
{
|
|
||||||
struct sigaction act, old;
|
|
||||||
act.sa_handler = sigintHandler;
|
|
||||||
sigfillset(&act.sa_mask);
|
|
||||||
act.sa_flags = 0;
|
|
||||||
if (sigaction(SIGINT, &act, &old))
|
|
||||||
throw SysError("installing handler for SIGINT");
|
|
||||||
|
|
||||||
if (sigsetjmp(sigintJmpBuf, 1))
|
|
||||||
line = "";
|
|
||||||
else {
|
|
||||||
char * s = readline("nix-repl> ");
|
|
||||||
if (!s) return false;
|
|
||||||
line = chomp(string(s));
|
|
||||||
free(s);
|
|
||||||
if (line != "") {
|
|
||||||
add_history(line.c_str());
|
|
||||||
append_history(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_isInterrupted = 0;
|
|
||||||
|
|
||||||
if (sigaction(SIGINT, &old, 0))
|
|
||||||
throw SysError("restoring handler for SIGINT");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
string removeWhitespace(string s)
|
string removeWhitespace(string s)
|
||||||
{
|
{
|
||||||
s = chomp(s);
|
s = chomp(s);
|
||||||
|
@ -143,6 +107,86 @@ void NixRepl::mainLoop(const Strings & args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Apparently, the only way to get readline() to return on Ctrl-C
|
||||||
|
(SIGINT) is to use siglongjmp(). That's fucked up... */
|
||||||
|
static sigjmp_buf sigintJmpBuf;
|
||||||
|
|
||||||
|
|
||||||
|
static void sigintHandler(int signo)
|
||||||
|
{
|
||||||
|
siglongjmp(sigintJmpBuf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Oh, if only g++ had nested functions... */
|
||||||
|
NixRepl * curRepl;
|
||||||
|
|
||||||
|
char * completerThunk(const char * s, int state)
|
||||||
|
{
|
||||||
|
string prefix(s);
|
||||||
|
|
||||||
|
/* If the prefix has a slash in it, use readline's builtin filename
|
||||||
|
completer. */
|
||||||
|
if (prefix.find('/') != string::npos)
|
||||||
|
return rl_filename_completion_function(s, state);
|
||||||
|
|
||||||
|
/* Otherwise, return all symbols that start with the prefix. */
|
||||||
|
if (state == 0) {
|
||||||
|
curRepl->completePrefix(s);
|
||||||
|
curRepl->curCompletion = curRepl->completions.begin();
|
||||||
|
}
|
||||||
|
if (curRepl->curCompletion == curRepl->completions.end()) return 0;
|
||||||
|
return strdup((curRepl->curCompletion++)->c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NixRepl::getLine(string & line)
|
||||||
|
{
|
||||||
|
struct sigaction act, old;
|
||||||
|
act.sa_handler = sigintHandler;
|
||||||
|
sigfillset(&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
if (sigaction(SIGINT, &act, &old))
|
||||||
|
throw SysError("installing handler for SIGINT");
|
||||||
|
|
||||||
|
if (sigsetjmp(sigintJmpBuf, 1))
|
||||||
|
line = "";
|
||||||
|
else {
|
||||||
|
curRepl = this;
|
||||||
|
rl_completion_entry_function = completerThunk;
|
||||||
|
|
||||||
|
char * s = readline("nix-repl> ");
|
||||||
|
if (!s) return false;
|
||||||
|
line = chomp(string(s));
|
||||||
|
free(s);
|
||||||
|
if (line != "") {
|
||||||
|
add_history(line.c_str());
|
||||||
|
append_history(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_isInterrupted = 0;
|
||||||
|
|
||||||
|
if (sigaction(SIGINT, &old, 0))
|
||||||
|
throw SysError("restoring handler for SIGINT");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NixRepl::completePrefix(string prefix)
|
||||||
|
{
|
||||||
|
completions.clear();
|
||||||
|
|
||||||
|
StringSet::iterator i = varNames.lower_bound(prefix);
|
||||||
|
while (i != varNames.end()) {
|
||||||
|
if (string(*i, 0, prefix.size()) != prefix) break;
|
||||||
|
completions.insert(*i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void NixRepl::processLine(string line)
|
void NixRepl::processLine(string line)
|
||||||
{
|
{
|
||||||
if (line == "") return;
|
if (line == "") return;
|
||||||
|
@ -227,6 +271,7 @@ void NixRepl::addVarToScope(const Symbol & name, Value * v)
|
||||||
{
|
{
|
||||||
staticEnv.vars[name] = displ;
|
staticEnv.vars[name] = displ;
|
||||||
env->values[displ++] = v;
|
env->values[displ++] = v;
|
||||||
|
varNames.insert((string) name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue