bindings: add support for defining and executing commands
This commit is contained in:
21
doc/bindings
21
doc/bindings
@@ -95,6 +95,24 @@
|
|||||||
## selected_items_adder, server_info, song_info,
|
## selected_items_adder, server_info, song_info,
|
||||||
## sort_playlist_dialog, tiny_tag_editor.
|
## sort_playlist_dialog, tiny_tag_editor.
|
||||||
##
|
##
|
||||||
|
## 5) In addition to binding to a key, you can also bind actions
|
||||||
|
## or chains of actions to a command. If it comes to commands,
|
||||||
|
## syntax is very similar to defining keys. Here goes example
|
||||||
|
## definition of a command:
|
||||||
|
##
|
||||||
|
## def_command "quit" [deferred]
|
||||||
|
## stop
|
||||||
|
## quit
|
||||||
|
##
|
||||||
|
## If you execute the above command (which can be done by
|
||||||
|
## invoking action execute_command, typing 'quit' and pressing
|
||||||
|
## enter), ncmpcpp will stop the player and then quit. Note the
|
||||||
|
## presence of word 'deferred' enclosed in square brackets. It
|
||||||
|
## tells ncmpcpp to wait for confirmation (ie. pressing enter)
|
||||||
|
## after you typed quit. Instead of 'deferred', 'immediate'
|
||||||
|
## could be used. Then ncmpcpp will not wait for confirmation
|
||||||
|
## (enter) and will execute the command the moment it sees it.
|
||||||
|
##
|
||||||
## Note: Both 'backspace' and 'backspace_2' are used because some
|
## Note: Both 'backspace' and 'backspace_2' are used because some
|
||||||
## terminals interpret backspace using keycode of 'backspace'
|
## terminals interpret backspace using keycode of 'backspace'
|
||||||
## and some the one of 'backspace_2'. You can get away with
|
## and some the one of 'backspace_2'. You can get away with
|
||||||
@@ -191,6 +209,9 @@
|
|||||||
#def_key "-"
|
#def_key "-"
|
||||||
# volume_down
|
# volume_down
|
||||||
#
|
#
|
||||||
|
#def_key ":"
|
||||||
|
# execute_command
|
||||||
|
#
|
||||||
#def_key "tab"
|
#def_key "tab"
|
||||||
# next_screen
|
# next_screen
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -972,6 +972,27 @@ void Stop::Run()
|
|||||||
Mpd.Stop();
|
Mpd.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExecuteCommand::Run()
|
||||||
|
{
|
||||||
|
using Global::wFooter;
|
||||||
|
Statusbar::lock();
|
||||||
|
Statusbar::put() << NC::fmtBold << ":" << NC::fmtBoldEnd;
|
||||||
|
wFooter->setGetStringHelper(Statusbar::Helpers::TryExecuteImmediateCommand());
|
||||||
|
std::string name = wFooter->getString();
|
||||||
|
wFooter->setGetStringHelper(Statusbar::Helpers::getString);
|
||||||
|
Statusbar::unlock();
|
||||||
|
if (name.empty())
|
||||||
|
return;
|
||||||
|
auto cmd = Bindings.findCommand(name);
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
|
Statusbar::msg(1, "Executing %s...", name.c_str());
|
||||||
|
cmd->binding().execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Statusbar::msg("No command named \"%s\"", name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
bool MoveSortOrderUp::canBeRun() const
|
bool MoveSortOrderUp::canBeRun() const
|
||||||
{
|
{
|
||||||
return myScreen == mySortPlaylistDialog;
|
return myScreen == mySortPlaylistDialog;
|
||||||
@@ -2576,6 +2597,7 @@ void populateActions()
|
|||||||
insertAction(new NextSong());
|
insertAction(new NextSong());
|
||||||
insertAction(new Pause());
|
insertAction(new Pause());
|
||||||
insertAction(new Stop());
|
insertAction(new Stop());
|
||||||
|
insertAction(new ExecuteCommand());
|
||||||
insertAction(new SavePlaylist());
|
insertAction(new SavePlaylist());
|
||||||
insertAction(new MoveSortOrderUp());
|
insertAction(new MoveSortOrderUp());
|
||||||
insertAction(new MoveSortOrderDown());
|
insertAction(new MoveSortOrderDown());
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ enum ActionType
|
|||||||
aDummy, aMouseEvent, aScrollUp, aScrollDown, aScrollUpArtist, aScrollUpAlbum, aScrollDownArtist,
|
aDummy, aMouseEvent, aScrollUp, aScrollDown, aScrollUpArtist, aScrollUpAlbum, aScrollDownArtist,
|
||||||
aScrollDownAlbum, aPageUp, aPageDown, aMoveHome, aMoveEnd, aToggleInterface, aJumpToParentDirectory,
|
aScrollDownAlbum, aPageUp, aPageDown, aMoveHome, aMoveEnd, aToggleInterface, aJumpToParentDirectory,
|
||||||
aPressEnter, aPressSpace, aPreviousColumn, aNextColumn, aMasterScreen, aSlaveScreen, aVolumeUp,
|
aPressEnter, aPressSpace, aPreviousColumn, aNextColumn, aMasterScreen, aSlaveScreen, aVolumeUp,
|
||||||
aVolumeDown, aDeletePlaylistItems, aDeleteStoredPlaylist, aDeleteBrowserItems, aReplaySong, aPrevious, aNext, aPause, aStop, aSavePlaylist,
|
aVolumeDown, aDeletePlaylistItems, aDeleteStoredPlaylist, aDeleteBrowserItems, aReplaySong, aPrevious, aNext, aPause, aStop, aExecuteCommand, aSavePlaylist,
|
||||||
aMoveSortOrderUp, aMoveSortOrderDown, aMoveSelectedItemsUp, aMoveSelectedItemsDown,
|
aMoveSortOrderUp, aMoveSortOrderDown, aMoveSelectedItemsUp, aMoveSelectedItemsDown,
|
||||||
aMoveSelectedItemsTo, aAdd, aSeekForward, aSeekBackward, aToggleDisplayMode, aToggleSeparatorsBetweenAlbums,
|
aMoveSelectedItemsTo, aAdd, aSeekForward, aSeekBackward, aToggleDisplayMode, aToggleSeparatorsBetweenAlbums,
|
||||||
aToggleLyricsFetcher, aToggleFetchingLyricsInBackground, aTogglePlayingSongCentering, aUpdateDatabase,
|
aToggleLyricsFetcher, aToggleFetchingLyricsInBackground, aTogglePlayingSongCentering, aUpdateDatabase,
|
||||||
@@ -361,6 +361,14 @@ protected:
|
|||||||
virtual void Run();
|
virtual void Run();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExecuteCommand : public Action
|
||||||
|
{
|
||||||
|
ExecuteCommand() : Action(aExecuteCommand, "execute_command") { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void Run();
|
||||||
|
};
|
||||||
|
|
||||||
struct SavePlaylist : public Action
|
struct SavePlaylist : public Action
|
||||||
{
|
{
|
||||||
SavePlaylist() : Action(aSavePlaylist, "save_playlist") { }
|
SavePlaylist() : Action(aSavePlaylist, "save_playlist") { }
|
||||||
|
|||||||
@@ -189,53 +189,110 @@ Key Key::read(NC::Window &w)
|
|||||||
|
|
||||||
bool BindingsConfiguration::read(const std::string &file)
|
bool BindingsConfiguration::read(const std::string &file)
|
||||||
{
|
{
|
||||||
|
enum class InProgress { None, Command, Key };
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
std::ifstream f(file);
|
std::ifstream f(file);
|
||||||
if (!f.is_open())
|
if (!f.is_open())
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
// shared variables
|
||||||
|
InProgress in_progress = InProgress::None;
|
||||||
size_t line_no = 0;
|
size_t line_no = 0;
|
||||||
bool key_def_in_progress = false;
|
std::string line;
|
||||||
Key key = Key::noOp;
|
|
||||||
Binding::ActionChain actions;
|
Binding::ActionChain actions;
|
||||||
std::string line, strkey;
|
|
||||||
|
// def_key specific variables
|
||||||
|
Key key = Key::noOp;
|
||||||
|
std::string strkey;
|
||||||
|
|
||||||
|
// def_command specific variables
|
||||||
|
bool cmd_immediate = false;
|
||||||
|
std::string cmd_name;
|
||||||
|
|
||||||
auto error = [&]() -> std::ostream & {
|
auto error = [&]() -> std::ostream & {
|
||||||
std::cerr << file << ":" << line_no << ": ";
|
std::cerr << file << ":" << line_no << ": error: ";
|
||||||
key_def_in_progress = false;
|
in_progress = InProgress::None;
|
||||||
result = false;
|
result = false;
|
||||||
return std::cerr;
|
return std::cerr;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto bind_key_def = [&]() -> bool {
|
auto bind_in_progress = [&]() -> bool {
|
||||||
if (!actions.empty())
|
if (in_progress == InProgress::Command)
|
||||||
{
|
{
|
||||||
bind(key, actions);
|
if (!actions.empty())
|
||||||
actions.clear();
|
{
|
||||||
return true;
|
m_commands.insert(std::make_pair(cmd_name, Command(actions, cmd_immediate)));
|
||||||
|
actions.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error() << "definition of command '" << cmd_name << "' cannot be empty\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (in_progress == InProgress::Key)
|
||||||
{
|
{
|
||||||
error() << "definition of key '" << strkey << "' cannot be empty.\n";
|
if (!actions.empty())
|
||||||
return false;
|
{
|
||||||
|
bind(key, actions);
|
||||||
|
actions.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error() << "definition of key '" << strkey << "' cannot be empty\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char def_command[] = "def_command";
|
||||||
|
const char def_key[] = "def_key";
|
||||||
|
|
||||||
while (!f.eof() && ++line_no)
|
while (!f.eof() && ++line_no)
|
||||||
{
|
{
|
||||||
getline(f, line);
|
getline(f, line);
|
||||||
if (line.empty() || line[0] == '#')
|
if (line.empty() || line[0] == '#')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!line.compare(0, 7, "def_key")) // beginning of key definition
|
// beginning of command definition
|
||||||
|
if (!line.compare(0, const_strlen(def_command), def_command))
|
||||||
{
|
{
|
||||||
if (key_def_in_progress)
|
if (!bind_in_progress())
|
||||||
|
break;
|
||||||
|
in_progress = InProgress::Command;
|
||||||
|
cmd_name = getEnclosedString(line, '"', '"', 0);
|
||||||
|
if (cmd_name.empty())
|
||||||
{
|
{
|
||||||
if (!bind_key_def())
|
error() << "command must have non-empty name\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
key_def_in_progress = true;
|
if (m_commands.find(cmd_name) != m_commands.end())
|
||||||
|
{
|
||||||
|
error() << "redefinition of command '" << cmd_name << "'\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::string cmd_type = getEnclosedString(line, '[', ']', 0);
|
||||||
|
if (cmd_type == "immediate")
|
||||||
|
cmd_immediate = true;
|
||||||
|
else if (cmd_type == "deferred")
|
||||||
|
cmd_immediate = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error() << "invalid type of command: '" << cmd_type << "'\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// beginning of key definition
|
||||||
|
else if (!line.compare(0, const_strlen(def_key), def_key))
|
||||||
|
{
|
||||||
|
if (!bind_in_progress())
|
||||||
|
break;
|
||||||
|
in_progress = InProgress::Key;
|
||||||
strkey = getEnclosedString(line, '"', '"', 0);
|
strkey = getEnclosedString(line, '"', '"', 0);
|
||||||
key = stringToKey(strkey);
|
key = stringToKey(strkey);
|
||||||
if (key == Key::noOp)
|
if (key == Key::noOp)
|
||||||
@@ -262,8 +319,7 @@ bool BindingsConfiguration::read(const std::string &file)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key_def_in_progress)
|
bind_in_progress();
|
||||||
bind_key_def();
|
|
||||||
f.close();
|
f.close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -318,6 +374,8 @@ void BindingsConfiguration::generateDefaults()
|
|||||||
}
|
}
|
||||||
if (notBound(k = stringToKey("-")))
|
if (notBound(k = stringToKey("-")))
|
||||||
bind(k, aVolumeDown);
|
bind(k, aVolumeDown);
|
||||||
|
if (notBound(k = stringToKey(":")))
|
||||||
|
bind(k, aExecuteCommand);
|
||||||
if (notBound(k = stringToKey("tab")))
|
if (notBound(k = stringToKey("tab")))
|
||||||
bind(k, aNextScreen);
|
bind(k, aNextScreen);
|
||||||
if (notBound(k = stringToKey("shift_tab")))
|
if (notBound(k = stringToKey("shift_tab")))
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#define _BINDINGS_H
|
#define _BINDINGS_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <unordered_map>
|
||||||
#include "actions.h"
|
#include "actions.h"
|
||||||
#include "macro_utilities.h"
|
#include "macro_utilities.h"
|
||||||
|
|
||||||
@@ -85,6 +86,20 @@ struct Binding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool execute() const {
|
||||||
|
bool result = false;
|
||||||
|
if (m_is_single) {
|
||||||
|
assert(m_action);
|
||||||
|
result = m_action->Execute();
|
||||||
|
} else {
|
||||||
|
for (auto it = m_chain->begin(); it != m_chain->end(); ++it)
|
||||||
|
if (!(*it)->Execute())
|
||||||
|
break;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool isSingle() const {
|
bool isSingle() const {
|
||||||
return m_is_single;
|
return m_is_single;
|
||||||
}
|
}
|
||||||
@@ -105,16 +120,41 @@ private:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Keybindings configuration
|
/// Represents executable command
|
||||||
struct BindingsConfiguration
|
struct Command
|
||||||
{
|
{
|
||||||
|
Command(const Binding &binding_, bool immediate_)
|
||||||
|
: m_binding(binding_), m_immediate(immediate_) { }
|
||||||
|
|
||||||
|
const Binding &binding() const { return m_binding; }
|
||||||
|
bool immediate() const { return m_immediate; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Binding m_binding;
|
||||||
|
bool m_immediate;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Keybindings configuration
|
||||||
|
class BindingsConfiguration
|
||||||
|
{
|
||||||
|
typedef std::unordered_map<std::string, Command> CommandsSet;
|
||||||
typedef std::multimap<Key, Binding> BindingsMap;
|
typedef std::multimap<Key, Binding> BindingsMap;
|
||||||
|
|
||||||
|
public:
|
||||||
typedef BindingsMap::iterator BindingIterator;
|
typedef BindingsMap::iterator BindingIterator;
|
||||||
typedef BindingsMap::const_iterator ConstBindingIterator;
|
typedef BindingsMap::const_iterator ConstBindingIterator;
|
||||||
|
|
||||||
bool read(const std::string &file);
|
bool read(const std::string &file);
|
||||||
void generateDefaults();
|
void generateDefaults();
|
||||||
|
|
||||||
|
const Command *findCommand(const std::string &name) {
|
||||||
|
const Command *ptr = 0;
|
||||||
|
auto it = m_commands.find(name);
|
||||||
|
if (it != m_commands.end())
|
||||||
|
ptr = &it->second;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<BindingIterator, BindingIterator> get(const Key &k) {
|
std::pair<BindingIterator, BindingIterator> get(const Key &k) {
|
||||||
return m_bindings.equal_range(k);
|
return m_bindings.equal_range(k);
|
||||||
}
|
}
|
||||||
@@ -132,6 +172,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
BindingsMap m_bindings;
|
BindingsMap m_bindings;
|
||||||
|
CommandsSet m_commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BindingsConfiguration Bindings;
|
extern BindingsConfiguration Bindings;
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ void Help::GetKeybindings()
|
|||||||
KeyDesc(aSetCrossfade, "Set crossfade");
|
KeyDesc(aSetCrossfade, "Set crossfade");
|
||||||
KeyDesc(aUpdateDatabase, "Start music database update");
|
KeyDesc(aUpdateDatabase, "Start music database update");
|
||||||
w << '\n';
|
w << '\n';
|
||||||
|
KeyDesc(aExecuteCommand, "Execute command");
|
||||||
KeyDesc(aApplyFilter, "Apply filter");
|
KeyDesc(aApplyFilter, "Apply filter");
|
||||||
KeyDesc(aFindItemForward, "Find item forward");
|
KeyDesc(aFindItemForward, "Find item forward");
|
||||||
KeyDesc(aFindItemBackward, "Find item backward");
|
KeyDesc(aFindItemBackward, "Find item backward");
|
||||||
|
|||||||
@@ -237,7 +237,6 @@ int main(int argc, char **argv)
|
|||||||
drawHeader();
|
drawHeader();
|
||||||
past = Timer;
|
past = Timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// header stuff end
|
// header stuff end
|
||||||
|
|
||||||
if (input != Key::noOp)
|
if (input != Key::noOp)
|
||||||
@@ -249,22 +248,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
auto k = Bindings.get(input);
|
auto k = Bindings.get(input);
|
||||||
for (; k.first != k.second; ++k.first)
|
for (; k.first != k.second; ++k.first)
|
||||||
{
|
if (k.first->second.execute())
|
||||||
Binding &b = k.first->second;
|
|
||||||
if (b.isSingle())
|
|
||||||
{
|
|
||||||
if (b.action()->Execute())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto chain = b.chain();
|
|
||||||
for (auto it = chain->begin(); it != chain->end(); ++it)
|
|
||||||
if (!(*it)->Execute())
|
|
||||||
break;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myScreen == myPlaylist)
|
if (myScreen == myPlaylist)
|
||||||
myPlaylist->EnableHighlighting();
|
myPlaylist->EnableHighlighting();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "statusbar.h"
|
#include "statusbar.h"
|
||||||
|
#include "bindings.h"
|
||||||
|
|
||||||
using Global::wFooter;
|
using Global::wFooter;
|
||||||
|
|
||||||
@@ -186,12 +187,13 @@ void Statusbar::Helpers::mpd()
|
|||||||
Mpd.OrderDataFetching();
|
Mpd.OrderDataFetching();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Statusbar::Helpers::getString(const std::wstring &)
|
bool Statusbar::Helpers::getString(const std::wstring &)
|
||||||
{
|
{
|
||||||
Status::trace();
|
Status::trace();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Statusbar::Helpers::ApplyFilterImmediately::operator()(const std::wstring &ws)
|
bool Statusbar::Helpers::ApplyFilterImmediately::operator()(const std::wstring &ws)
|
||||||
{
|
{
|
||||||
using Global::myScreen;
|
using Global::myScreen;
|
||||||
// if input queue is not empty, we don't want to update filter since next
|
// if input queue is not empty, we don't want to update filter since next
|
||||||
@@ -209,4 +211,19 @@ void Statusbar::Helpers::ApplyFilterImmediately::operator()(const std::wstring &
|
|||||||
}
|
}
|
||||||
Status::trace();
|
Status::trace();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Statusbar::Helpers::TryExecuteImmediateCommand::operator()(const std::wstring &ws)
|
||||||
|
{
|
||||||
|
bool continue_ = true;
|
||||||
|
if (m_ws != ws)
|
||||||
|
{
|
||||||
|
m_ws = ws;
|
||||||
|
auto cmd = Bindings.findCommand(ToString(m_ws));
|
||||||
|
if (cmd && cmd->immediate())
|
||||||
|
continue_ = false;
|
||||||
|
}
|
||||||
|
Status::trace();
|
||||||
|
return continue_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace Helpers {//
|
|||||||
void mpd();
|
void mpd();
|
||||||
|
|
||||||
/// called each time user types another character while inside Window::getString
|
/// called each time user types another character while inside Window::getString
|
||||||
void getString(const std::wstring &);
|
bool getString(const std::wstring &);
|
||||||
|
|
||||||
/// called each time user changes current filter (while being inside Window::getString)
|
/// called each time user changes current filter (while being inside Window::getString)
|
||||||
struct ApplyFilterImmediately
|
struct ApplyFilterImmediately
|
||||||
@@ -79,13 +79,21 @@ struct ApplyFilterImmediately
|
|||||||
ApplyFilterImmediately(Filterable *f, const std::wstring &filter)
|
ApplyFilterImmediately(Filterable *f, const std::wstring &filter)
|
||||||
: m_f(f), m_ws(filter) { }
|
: m_f(f), m_ws(filter) { }
|
||||||
|
|
||||||
void operator()(const std::wstring &ws);
|
bool operator()(const std::wstring &ws);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Filterable *m_f;
|
Filterable *m_f;
|
||||||
std::wstring m_ws;
|
std::wstring m_ws;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TryExecuteImmediateCommand
|
||||||
|
{
|
||||||
|
bool operator()(const std::wstring &ws);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::wstring m_ws;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -552,7 +552,10 @@ std::string Window::getString(const std::string &base, size_t length_, size_t wi
|
|||||||
mvwhline(m_window, y, minx, '*', maxx-minx);
|
mvwhline(m_window, y, minx, '*', maxx-minx);
|
||||||
|
|
||||||
if (m_get_string_helper)
|
if (m_get_string_helper)
|
||||||
m_get_string_helper(*tmp);
|
{
|
||||||
|
if (!m_get_string_helper(*tmp))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
wmove(m_window, y, x);
|
wmove(m_window, y, x);
|
||||||
prefresh(m_window, 0, 0, m_start_y, m_start_x, m_start_y+m_height-1, m_start_x+m_width-1);
|
prefresh(m_window, 0, 0, m_start_y, m_start_x, m_start_y+m_height-1, m_start_x+m_width-1);
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ enum Where { wUp, wDown, wPageUp, wPageDown, wHome, wEnd };
|
|||||||
/// Helper function that is invoked each time one will want
|
/// Helper function that is invoked each time one will want
|
||||||
/// to obtain string from Window::getString() function
|
/// to obtain string from Window::getString() function
|
||||||
/// @see Window::getString()
|
/// @see Window::getString()
|
||||||
typedef std::function<void(const std::wstring &)> GetStringHelper;
|
typedef std::function<bool(const std::wstring &)> GetStringHelper;
|
||||||
|
|
||||||
/// Initializes curses screen and sets some additional attributes
|
/// Initializes curses screen and sets some additional attributes
|
||||||
/// @param window_title title of the window (has an effect only if pdcurses lib is used)
|
/// @param window_title title of the window (has an effect only if pdcurses lib is used)
|
||||||
|
|||||||
Reference in New Issue
Block a user