stocks: Use ^ and $ to match the beginning/end of item names

Closes #624
develop
lethosor 2015-07-29 13:44:32 -04:00
parent 7fc682b199
commit 4e45cc5bbb
3 changed files with 166 additions and 33 deletions

@ -134,6 +134,29 @@ public:
}
}
virtual void tokenizeSearch (vector<string> *dest, const string search)
{
if (!search.empty())
split_string(dest, search, " ");
}
virtual bool showEntry(const ListEntry<T> *entry, const vector<string> &search_tokens)
{
if (!search_tokens.empty())
{
string item_string = toLower(entry->text);
for (auto si = search_tokens.begin(); si != search_tokens.end(); si++)
{
if (!si->empty() && item_string.find(*si) == string::npos &&
entry->keywords.find(*si) == string::npos)
{
return false;
}
}
}
return true;
}
void filterDisplay()
{
ListEntry<T> *prev_selected = (getDisplayListSize() > 0) ? display_list[highlighted_index] : NULL;
@ -141,29 +164,13 @@ public:
search_string = toLower(search_string);
vector<string> search_tokens;
if (!search_string.empty())
split_string(&search_tokens, search_string, " ");
tokenizeSearch(&search_tokens, search_string);
for (size_t i = 0; i < list.size(); i++)
{
ListEntry<T> *entry = &list[i];
bool include_item = true;
if (!search_string.empty())
{
string item_string = toLower(list[i].text);
for (auto si = search_tokens.begin(); si != search_tokens.end(); si++)
{
if (!si->empty() && item_string.find(*si) == string::npos &&
list[i].keywords.find(*si) == string::npos)
{
include_item = false;
break;
}
}
}
if (include_item)
if (showEntry(entry, search_tokens))
{
display_list.push_back(entry);
if (entry == prev_selected)
@ -347,14 +354,19 @@ public:
return list.size();
}
virtual bool validSearchInput (unsigned char c)
{
return (c >= 'a' && c <= 'z') || c == ' ';
}
bool feed(set<df::interface_key> *input)
{
feed_mouse_set_highlight = feed_changed_highlight = false;
if (input->count(interface_key::CURSOR_UP))
if (input->count(interface_key::STANDARDSCROLL_UP))
{
changeHighlight(-1);
}
else if (input->count(interface_key::CURSOR_DOWN))
else if (input->count(interface_key::STANDARDSCROLL_DOWN))
{
changeHighlight(1);
}
@ -383,7 +395,7 @@ public:
// Search query typing mode always on
df::interface_key last_token = get_string_key(input);
int charcode = Screen::keyToChar(last_token);
if ((charcode >= 96 && charcode <= 123) || charcode == 32)
if (charcode >= 0 && validSearchInput((unsigned char)charcode))
{
// Standard character
search_string += char(charcode);

@ -599,8 +599,115 @@ class StockListColumn : public ListColumn<T>
OutputString(color, x, y, get_quality_name(quality));
}
}
virtual bool validSearchInput (unsigned char c)
{
switch (c)
{
case '(':
case ')':
return true;
break;
default:
break;
}
string &search_string = ListColumn<T>::search_string;
if (c == '^' && !search_string.size())
return true;
else if (c == '$' && search_string.size())
{
if (search_string == "^")
return false;
if (search_string[search_string.size() - 1] != '$')
return true;
}
return ListColumn<T>::validSearchInput(c);
}
std::string getRawSearch(const std::string s)
{
string raw_search = s;
if (raw_search.size() && raw_search[0] == '^')
raw_search.erase(0, 1);
if (raw_search.size() && raw_search[raw_search.size() - 1] == '$')
raw_search.erase(raw_search.size() - 1, 1);
return toLower(raw_search);
}
virtual void tokenizeSearch (vector<string> *dest, const string search)
{
string raw_search = getRawSearch(search);
ListColumn<T>::tokenizeSearch(dest, raw_search);
}
virtual bool showEntry (const ListEntry<T> *entry, const vector<string> &search_tokens)
{
string &search_string = ListColumn<T>::search_string;
if (!search_string.size())
return true;
bool match_start = false, match_end = false;
string raw_search = getRawSearch(search_string);
if (search_string.size() && search_string[0] == '^')
match_start = true;
if (search_string.size() && search_string[search_string.size() - 1] == '$')
match_end = true;
if (!ListColumn<T>::showEntry(entry, search_tokens))
return false;
string item_name = toLower(Items::getDescription(entry->elem->entries[0], 0, false));
if ((match_start || match_end) && raw_search.size() > item_name.size())
return false;
if (match_start && item_name.compare(0, raw_search.size(), raw_search) != 0)
return false;
if (match_end && item_name.compare(item_name.size() - raw_search.size(), raw_search.size(), raw_search) != 0)
return false;
return true;
}
};
class search_help : public dfhack_viewscreen
{
public:
void feed (std::set<df::interface_key> *input)
{
if (input->count(interface_key::HELP))
return;
if (Screen::isDismissed(this))
return;
Screen::dismiss(this);
if (!input->count(interface_key::LEAVESCREEN) && !input->count(interface_key::SELECT))
parent->feed(input);
}
void render()
{
static std::string text =
"\7 Flag names can be\n"
" searched for - e.g. job,\n"
" inventory, dump, forbid\n"
"\n"
"\7 Use ^ to match the start\n"
" of a name, and/or $ to\n"
" match the end of a name";
if (Screen::isDismissed(this))
return;
parent->render();
int left_margin = gps->dimx - SIDEBAR_WIDTH;
int x = left_margin, y = 2;
Screen::fillRect(Screen::Pen(' ', 0, 0), left_margin - 1, 1, gps->dimx - 2, gps->dimy - 4);
Screen::fillRect(Screen::Pen(' ', 0, 0), left_margin - 1, 1, left_margin - 1, gps->dimy - 2);
OutputString(COLOR_WHITE, x, y, "Search help", true, left_margin);
++y;
vector<string> lines;
split_string(&lines, text, "\n");
for (auto line = lines.begin(); line != lines.end(); ++line)
OutputString(COLOR_WHITE, x, y, line->c_str(), true, left_margin);
}
std::string getFocusString() { return "stocks_view/search_help"; }
};
class ViewscreenStocks : public dfhack_viewscreen
{
@ -662,6 +769,10 @@ public:
Screen::dismiss(this);
return;
}
else if (input->count(interface_key::HELP))
{
Screen::show(new search_help);
}
bool key_processed = false;
switch (selected_column)
@ -921,19 +1032,18 @@ public:
++y;
OutputHotkeyString(x, y, "Clear All", "Shift-C", true, left_margin);
OutputHotkeyString(x, y, "Enable All", "Shift-E", true, left_margin);
OutputHotkeyString(x, y, "Toggle Grouping", "TAB", true, left_margin);
OutputHotkeyString(x, y, "Toggle Grouping", interface_key::CHANGETAB, true, left_margin);
++y;
OutputString(COLOR_WHITE, x, y, "Qual: ");
OutputHotkeyString(x, y, "Min: ", "-+");
OutputString(COLOR_BROWN, x, y, get_quality_name(min_quality), false, left_margin);
++x;
OutputHotkeyString(x, y, "Max: ", "/*");
OutputHotkeyString(x, y, "Min Qual: ", "-+");
OutputString(COLOR_BROWN, x, y, get_quality_name(min_quality), true, left_margin);
OutputHotkeyString(x, y, "Max Qual: ", "/*");
OutputString(COLOR_BROWN, x, y, get_quality_name(max_quality), true, left_margin);
OutputHotkeyString(x, y, "Min Wear: ", "Shift-W");
OutputString(COLOR_BROWN, x, y, int_to_string(min_wear), true, left_margin);
++y;
if (gps->dimy > 27)
++y;
OutputString(COLOR_BROWN, x, y, "Actions (");
OutputString(COLOR_LIGHTGREEN, x, y, int_to_string(items_column.getDisplayedListSize()));
OutputString(COLOR_BROWN, x, y, " Items)", true, left_margin);
@ -941,14 +1051,13 @@ public:
OutputHotkeyString(x, y, "Dump", "-D", true, left_margin);
OutputHotkeyString(x, y, "Forbid ", "Shift-F", false, left_margin);
OutputHotkeyString(x, y, "Melt", "-M", true, left_margin);
OutputHotkeyString(x, y, "Mark for Trade", "Shift-T", true, left_margin,
depot_info.canTrade() ? COLOR_WHITE : COLOR_DARKGREY);
OutputHotkeyString(x, y, "Apply to: ", "Shift-A");
OutputString(COLOR_BROWN, x, y, (apply_to_all) ? "Listed" : "Selected", true, left_margin);
if (depot_info.canTrade())
OutputHotkeyString(x, y, "Mark for Trade", "Shift-T", true, left_margin);
y = gps->dimy - 5;
OutputString(COLOR_LIGHTRED, x, y, "Flag names can also", true, left_margin);
OutputString(COLOR_LIGHTRED, x, y, "be searched for", true, left_margin);
y = gps->dimy - 4;
OutputHotkeyString(x, y, "Search help", interface_key::HELP, true, left_margin);
}
std::string getFocusString() { return "stocks_view"; }

@ -112,6 +112,12 @@ static void OutputHotkeyString(int &x, int &y, const char *text, const char *hot
OutputString(text_color, x, y, display, newline, left_margin);
}
static void OutputHotkeyString(int &x, int &y, const char *text, df::interface_key hotkey,
bool newline = false, int left_margin = 0, int8_t text_color = COLOR_WHITE, int8_t hotkey_color = COLOR_LIGHTGREEN)
{
OutputHotkeyString(x, y, text, DFHack::Screen::getKeyDisplay(hotkey).c_str(), newline, left_margin, text_color, hotkey_color);
}
static void OutputLabelString(int &x, int &y, const char *text, const char *hotkey, const string &label, bool newline = false,
int left_margin = 0, int8_t text_color = COLOR_WHITE, int8_t hotkey_color = COLOR_LIGHTGREEN)
{
@ -142,6 +148,12 @@ static void OutputToggleString(int &x, int &y, const char *text, const char *hot
OutputString(COLOR_GREY, x, y, "Off", newline, left_margin);
}
static void OutputToggleString(int &x, int &y, const char *text, df::interface_key hotkey, bool state, bool newline = true,
int left_margin = 0, int8_t color = COLOR_WHITE, int8_t hotkey_color = COLOR_LIGHTGREEN)
{
OutputToggleString(x, y, text, DFHack::Screen::getKeyDisplay(hotkey).c_str(), state, newline, left_margin, color, hotkey_color);
}
inline string int_to_string(const int n)
{
return static_cast<ostringstream*>( &(ostringstream() << n) )->str();