added ForEach key command
This commit is contained in:
parent
b90a7e21a9
commit
03dce043b7
5 changed files with 79 additions and 14 deletions
10
ChangeLog
10
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 {<command>} [{ [{<list opts>}] [<bool command>] }]
|
||||
- For example, the following command will shade all windows on the current
|
||||
workspace: ForEach {shade} {{groups} Matches (workspace=[current])}
|
||||
- <list opts> 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
|
||||
|
|
|
@ -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 <typename Container>
|
||||
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 <typename Container>
|
||||
static void
|
||||
|
|
|
@ -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<string> args;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "FbTk/KeyUtil.hh"
|
||||
#include "FbTk/ObjectRegistry.hh"
|
||||
#include "FbTk/stringstream.hh"
|
||||
#include "FbTk/StringUtil.hh"
|
||||
|
||||
#ifdef HAVE_CMATH
|
||||
#include <cmath>
|
||||
|
@ -43,30 +44,58 @@
|
|||
#endif
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
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<string> tokens;
|
||||
int opts;
|
||||
string pat;
|
||||
|
||||
FbTk::StringUtil::stringTokensBetween(tokens, args, pat, '{', '}');
|
||||
if (tokens.empty())
|
||||
return 0;
|
||||
|
||||
cmd = FbTk::ObjectRegistry<Command>::instance().parse(tokens[0], trusted);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
if (tokens.size() > 1) {
|
||||
FocusableList::parseArgs(tokens[1], opts, pat);
|
||||
|
||||
filter = FbTk::ObjectRegistry<BoolCommand>::instance().parse(pat,
|
||||
trusted);
|
||||
}
|
||||
|
||||
return new WindowListCmd(FbTk::RefCount<Command>(cmd), opts,
|
||||
FbTk::RefCount<BoolCommand>(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<void>::client();
|
||||
for (; it != it_end; ++it) {
|
||||
if (m_pat.match(**it) && (*it)->fbwindow()) {
|
||||
if (typeid(**it) == typeid(FluxboxWindow))
|
||||
WindowCmd<void>::setWindow((*it)->fbwindow());
|
||||
else if (typeid(**it) == typeid(WinClient))
|
||||
WindowCmd<void>::setClient(dynamic_cast<WinClient *>(*it));
|
||||
if (!*m_filter || m_filter->bool_execute())
|
||||
m_cmd->execute();
|
||||
}
|
||||
}
|
||||
WindowCmd<void>::setClient(old);
|
||||
}
|
||||
|
|
|
@ -36,14 +36,18 @@
|
|||
|
||||
class WindowListCmd: public FbTk::Command {
|
||||
public:
|
||||
WindowListCmd(FbTk::RefCount<FbTk::Command> cmd, const std::string &pat):
|
||||
m_cmd(cmd), m_pat(pat.c_str()) { }
|
||||
WindowListCmd(FbTk::RefCount<FbTk::Command> cmd, int opts,
|
||||
FbTk::RefCount<FbTk::BoolCommand> 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<FbTk::Command> m_cmd;
|
||||
ClientPattern m_pat;
|
||||
int m_opts;
|
||||
FbTk::RefCount<FbTk::BoolCommand> m_filter;
|
||||
};
|
||||
|
||||
class SomeCmd: public FbTk::BoolCommand {
|
||||
|
|
Loading…
Reference in a new issue