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)
|
(Format: Year/Month/Day)
|
||||||
Changes for 1.0.1:
|
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:
|
*07/12/19:
|
||||||
* Don't let transient windows steal focus from other programs (Mark)
|
* Don't let transient windows steal focus from other programs (Mark)
|
||||||
Window.cc
|
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
|
/// splits input at first non-leading whitespace and returns both parts
|
||||||
void getFirstWord(const std::string &in, std::string &first, std::string &rest);
|
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
|
/// Breaks a string into tokens
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -38,10 +38,11 @@ using std::vector;
|
||||||
|
|
||||||
void FocusableList::parseArgs(const string &in, int &opts, string &pat) {
|
void FocusableList::parseArgs(const string &in, int &opts, string &pat) {
|
||||||
string options;
|
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
|
// 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
|
// now parse the options
|
||||||
vector<string> args;
|
vector<string> args;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "FbTk/KeyUtil.hh"
|
#include "FbTk/KeyUtil.hh"
|
||||||
#include "FbTk/ObjectRegistry.hh"
|
#include "FbTk/ObjectRegistry.hh"
|
||||||
#include "FbTk/stringstream.hh"
|
#include "FbTk/stringstream.hh"
|
||||||
|
#include "FbTk/StringUtil.hh"
|
||||||
|
|
||||||
#ifdef HAVE_CMATH
|
#ifdef HAVE_CMATH
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -43,30 +44,58 @@
|
||||||
#endif
|
#endif
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using FbTk::Command;
|
using FbTk::Command;
|
||||||
using FbTk::BoolCommand;
|
using FbTk::BoolCommand;
|
||||||
|
|
||||||
void WindowListCmd::execute() {
|
REGISTER_OBJECT_PARSER(map, WindowListCmd::parse, Command);
|
||||||
if (m_pat.error()) {
|
REGISTER_OBJECT_PARSER(foreach, WindowListCmd::parse, Command);
|
||||||
m_cmd->execute();
|
|
||||||
return;
|
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();
|
BScreen *screen = Fluxbox::instance()->keyScreen();
|
||||||
if (screen != 0) {
|
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(),
|
FocusableList::Focusables::iterator it = win_list.begin(),
|
||||||
it_end = win_list.end();
|
it_end = win_list.end();
|
||||||
// save old value, so we can restore it later
|
// save old value, so we can restore it later
|
||||||
WinClient *old = WindowCmd<void>::client();
|
WinClient *old = WindowCmd<void>::client();
|
||||||
for (; it != it_end; ++it) {
|
for (; it != it_end; ++it) {
|
||||||
if (m_pat.match(**it) && (*it)->fbwindow()) {
|
if (typeid(**it) == typeid(FluxboxWindow))
|
||||||
WindowCmd<void>::setWindow((*it)->fbwindow());
|
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();
|
m_cmd->execute();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
WindowCmd<void>::setClient(old);
|
WindowCmd<void>::setClient(old);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,18 @@
|
||||||
|
|
||||||
class WindowListCmd: public FbTk::Command {
|
class WindowListCmd: public FbTk::Command {
|
||||||
public:
|
public:
|
||||||
WindowListCmd(FbTk::RefCount<FbTk::Command> cmd, const std::string &pat):
|
WindowListCmd(FbTk::RefCount<FbTk::Command> cmd, int opts,
|
||||||
m_cmd(cmd), m_pat(pat.c_str()) { }
|
FbTk::RefCount<FbTk::BoolCommand> filter):
|
||||||
|
m_cmd(cmd), m_opts(opts), m_filter(filter) { }
|
||||||
|
|
||||||
void execute();
|
void execute();
|
||||||
|
static FbTk::Command *parse(const std::string &command,
|
||||||
|
const std::string &args, bool trusted);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FbTk::RefCount<FbTk::Command> m_cmd;
|
FbTk::RefCount<FbTk::Command> m_cmd;
|
||||||
ClientPattern m_pat;
|
int m_opts;
|
||||||
|
FbTk::RefCount<FbTk::BoolCommand> m_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SomeCmd: public FbTk::BoolCommand {
|
class SomeCmd: public FbTk::BoolCommand {
|
||||||
|
|
Loading…
Reference in a new issue