From 03dce043b78103a977bd6c48b81bb1b462aaac5f Mon Sep 17 00:00:00 2001 From: Mark Tiefenbruck Date: Thu, 20 Dec 2007 12:23:56 -0800 Subject: added ForEach key command --- ChangeLog | 10 ++++++++++ src/FbTk/StringUtil.hh | 21 +++++++++++++++++++++ src/FocusableList.cc | 5 +++-- src/WorkspaceCmd.cc | 47 ++++++++++++++++++++++++++++++++++++++--------- src/WorkspaceCmd.hh | 10 +++++++--- 5 files changed, 79 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc74024..91975b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ (Format: Year/Month/Day) Changes for 1.0.1: +*07/12/20: + * Added new key command :ForEach (or :Map) (Mark) + - :ForEach {} [{ [{}] [] }] + - For example, the following command will shade all windows on the current + workspace: ForEach {shade} {{groups} Matches (workspace=[current])} + - can be any combination of `static' and `groups' where static + means windows are listed in creation order, and groups means individual + tabs are not considered separately + - This replaces syntax such as `:Minimize (layer)', which no longer works + WorkspaceCmd.cc/hh *07/12/19: * Don't let transient windows steal focus from other programs (Mark) Window.cc diff --git a/src/FbTk/StringUtil.hh b/src/FbTk/StringUtil.hh index d3c131e..bca48bc 100644 --- a/src/FbTk/StringUtil.hh +++ b/src/FbTk/StringUtil.hh @@ -67,6 +67,27 @@ std::string::size_type removeTrailingWhitespace(std::string &str); /// splits input at first non-leading whitespace and returns both parts void getFirstWord(const std::string &in, std::string &first, std::string &rest); +template +static void stringTokensBetween(Container &container, const std::string &in, + std::string &rest, char first, char last, + const char *ok_chars = " \t\n", bool allow_nesting = true) { + + std::string token; + int err = 0, pos = 0; + + while (true) { + err = getStringBetween(token, in.c_str() + pos, first, last, ok_chars, + allow_nesting); + if (err == 0) + break; + container.push_back(token); + pos += err; + } + + rest = in.c_str() + pos; + +} + /// Breaks a string into tokens template static void diff --git a/src/FocusableList.cc b/src/FocusableList.cc index 8c43181..366ef8a 100644 --- a/src/FocusableList.cc +++ b/src/FocusableList.cc @@ -38,10 +38,11 @@ using std::vector; void FocusableList::parseArgs(const string &in, int &opts, string &pat) { string options; - int err = FbTk::StringUtil::getStringBetween(options, in.c_str(), '{', '}'); + int err = FbTk::StringUtil::getStringBetween(options, in.c_str(), '{', '}', + " \t\n"); // the rest of the string is a ClientPattern - pat = in.c_str() + err; + pat = in.c_str() + (err > 0 ? err : 0); // now parse the options vector args; diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 2d2964e..bb1537e 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc @@ -35,6 +35,7 @@ #include "FbTk/KeyUtil.hh" #include "FbTk/ObjectRegistry.hh" #include "FbTk/stringstream.hh" +#include "FbTk/StringUtil.hh" #ifdef HAVE_CMATH #include @@ -43,30 +44,58 @@ #endif #include #include +#include using std::string; using FbTk::Command; using FbTk::BoolCommand; -void WindowListCmd::execute() { - if (m_pat.error()) { - m_cmd->execute(); - return; +REGISTER_OBJECT_PARSER(map, WindowListCmd::parse, Command); +REGISTER_OBJECT_PARSER(foreach, WindowListCmd::parse, Command); + +FbTk::Command *WindowListCmd::parse(const string &command, const string &args, + bool trusted) { + FbTk::Command *cmd = 0; + FbTk::BoolCommand *filter = 0; + std::vector tokens; + int opts; + string pat; + + FbTk::StringUtil::stringTokensBetween(tokens, args, pat, '{', '}'); + if (tokens.empty()) + return 0; + + cmd = FbTk::ObjectRegistry::instance().parse(tokens[0], trusted); + if (!cmd) + return 0; + + if (tokens.size() > 1) { + FocusableList::parseArgs(tokens[1], opts, pat); + + filter = FbTk::ObjectRegistry::instance().parse(pat, + trusted); } + return new WindowListCmd(FbTk::RefCount(cmd), opts, + FbTk::RefCount(filter)); +} + +void WindowListCmd::execute() { BScreen *screen = Fluxbox::instance()->keyScreen(); if (screen != 0) { - FocusControl::Focusables win_list(screen->focusControl().creationOrderWinList().clientList()); + FocusableList::Focusables win_list(FocusableList::getListFromOptions(*screen, m_opts)->clientList()); - FocusControl::Focusables::iterator it = win_list.begin(), - it_end = win_list.end(); + FocusableList::Focusables::iterator it = win_list.begin(), + it_end = win_list.end(); // save old value, so we can restore it later WinClient *old = WindowCmd::client(); for (; it != it_end; ++it) { - if (m_pat.match(**it) && (*it)->fbwindow()) { + if (typeid(**it) == typeid(FluxboxWindow)) WindowCmd::setWindow((*it)->fbwindow()); + else if (typeid(**it) == typeid(WinClient)) + WindowCmd::setClient(dynamic_cast(*it)); + if (!*m_filter || m_filter->bool_execute()) m_cmd->execute(); - } } WindowCmd::setClient(old); } diff --git a/src/WorkspaceCmd.hh b/src/WorkspaceCmd.hh index fa8cb58..13adec3 100644 --- a/src/WorkspaceCmd.hh +++ b/src/WorkspaceCmd.hh @@ -36,14 +36,18 @@ class WindowListCmd: public FbTk::Command { public: - WindowListCmd(FbTk::RefCount cmd, const std::string &pat): - m_cmd(cmd), m_pat(pat.c_str()) { } + WindowListCmd(FbTk::RefCount cmd, int opts, + FbTk::RefCount filter): + m_cmd(cmd), m_opts(opts), m_filter(filter) { } void execute(); + static FbTk::Command *parse(const std::string &command, + const std::string &args, bool trusted); private: FbTk::RefCount m_cmd; - ClientPattern m_pat; + int m_opts; + FbTk::RefCount m_filter; }; class SomeCmd: public FbTk::BoolCommand { -- cgit v0.11.2