prompt: rework tu support arrows and completion cycling

This commit is contained in:
Maxime Coste 2011-09-14 19:15:09 +00:00
parent b59ad6a174
commit 635e76eb4c
2 changed files with 60 additions and 16 deletions

View File

@ -15,6 +15,9 @@ struct Completions
size_t start; size_t start;
size_t end; size_t end;
Completions()
: start(0), end(0) {}
Completions(size_t start, size_t end) Completions(size_t start, size_t end)
: start(start), end(end) {} : start(start), end(end) {}
}; };

View File

@ -106,6 +106,12 @@ std::string prompt(const std::string& text,
clrtoeol(); clrtoeol();
std::string result; std::string result;
size_t cursor_pos = 0;
Completions completions;
int current_completion = -1;
std::string text_before_completion;
while(true) while(true)
{ {
char c = getch(); char c = getch();
@ -113,36 +119,71 @@ std::string prompt(const std::string& text,
{ {
case '\r': case '\r':
return result; return result;
case 4:
if (cursor_pos > 0)
--cursor_pos;
break;
case 5:
if (cursor_pos < result.length())
++cursor_pos;
break;
case 7: case 7:
if (not result.empty()) if (cursor_pos != 0)
{ {
move(max_y - 1, text.length() + result.length() - 1); result = result.substr(0, cursor_pos - 1)
addch(' '); + result.substr(cursor_pos, std::string::npos);
result.resize(result.length() - 1);
move(max_y - 1, text.length() + result.length()); --cursor_pos;
refresh();
} }
current_completion = -1;
break; break;
case 27: case 27:
throw prompt_aborted(); throw prompt_aborted();
case '\t': case '\t':
{ {
Completions completions = completer(result, result.length()); if (current_completion == -1)
if (not completions.candidates.empty())
{ {
const std::string& completion = completions.candidates[0]; completions = completer(result, result.length());
if (completions.candidates.empty())
break;
text_before_completion = result.substr(completions.start,
completions.end - completions.start);
}
++current_completion;
std::string completion;
if (current_completion >= completions.candidates.size())
{
if (current_completion == completions.candidates.size() and
std::find(completions.candidates.begin(), completions.candidates.end(), text_before_completion) == completions.candidates.end())
completion = text_before_completion;
else
{
current_completion = 0;
completion = completions.candidates[0];
}
}
else
completion = completions.candidates[current_completion];
move(max_y-1, text.length()); move(max_y-1, text.length());
result = result.substr(0, completions.start) + completion; result = result.substr(0, completions.start) + completion;
addstr(result.c_str()); cursor_pos = completions.start + completion.length();
refresh();
}
break; break;
} }
default: default:
result += c; current_completion = -1;
addch(c); result = result.substr(0, cursor_pos) + c + result.substr(cursor_pos, std::string::npos);
refresh(); ++cursor_pos;
} }
move(max_y - 1, text.length());
clrtoeol();
addstr(result.c_str());
move(max_y - 1, text.length() + cursor_pos);
refresh();
} }
return result; return result;
} }