Skip to content

Commit

Permalink
Simplified context block configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
houmain committed Jan 20, 2021
1 parent ecb8a59 commit 69de0ef
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 58 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ build >> F5
Additionally it can be mapped within a context block. These blocks define a context by system, window title or window class in which commands should be mapped to different output expressions. They are opened like:

```bash
[Window system="Windows" title="..." class="..."]
[system="Windows" title="..." class="..."]
```

and continue until the next block header (respectively the end of the file). e.g.:

```bash
[Window title="Visual Studio"]
[title="Visual Studio"]
build >> (Shift Control){B}
go_to_definition >> F12

[Window system="Linux" class="terminator"]
[system="Linux" class="terminator"]
...
```

Expand Down
22 changes: 11 additions & 11 deletions keymapper.conf
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@
!Boss (Win ShiftLeft){Tab} >> prev_tab
!Boss Win{C} >> open_console

# pass Windows-P unmapped (for Windows output configuration)
!Boss Win{P} >> P
# pass other Windows key combinations unmapped
!Boss Win{Any} >> Any

# colemak layout mapping (on german layout)
!Boss AltGr{I} >> !AltGr{BracketLeft} # ü
Expand Down Expand Up @@ -163,49 +163,49 @@
edit_rename >> F2

# application specific mappings for abstract commands
[Window system="Linux" title="File Manager"]
[system="Linux" title="File Manager"]
cursor_home >> Backspace
cursor_end >> Enter
open_console >> !Win (ShiftLeft ControlLeft){C}

[Window system="Linux" class="tilix"]
[system="Linux" class="tilix"]
close_window >> !Win (Shift Control){W}
edit_paste >> (Shift Control){V}
open_console >> !Win (Control Alt){A}

[Window title="Mozilla Firefox"]
[title="Mozilla Firefox"]
open_file >> Control{K}
navigate_escape >> Escape Control{F} Escape
go_to_definition >> Shift{Backslash}

[Window title="Chromium"]
[title="Chromium"]
open_file >> Control{L}
navigate_escape >> Control{L} F6

[Window title="Qt Creator"]
[title="Qt Creator"]
open_file >> Control{K}
go_to_definition >> F2
edit_redo >> (Control Shift){Y}
edit_rename >> (Control Shift){R}

[Window title="Visual Studio"]
[title="Visual Studio"]
go_to_definition >> F12
navigate_back >> Control{Slash}
navigate_fore >> (Control Shift){Slash}
build >> (Control Shift){B}

[Window system="Linux" title="Code - OSS"]
[system="Linux" title="Code - OSS"]
go_to_definition >> F12
navigate_back >> (Control Alt){Slash}
navigate_fore >> (Control Shift){Slash}
build >> (Control Shift){B}

[Window title="Visual Studio Code"]
[title="Visual Studio Code"]
go_to_definition >> F12
navigate_back >> Alt{ArrowLeft}
navigate_fore >> Alt{ArrowRight}
build >> (Control Shift){B}

[Window title="Geany"]
[title="Geany"]
go_to_definition >> (Control Shift){T}

75 changes: 35 additions & 40 deletions src/config/ParseConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void ParseConfig::parse_line(It it, const It end) {
if (!skip_until(&it, end, "]"))
error("missing ']'");

parse_directive(begin, it-1);
parse_context(begin, it-1);
}
else {
const auto begin = it;
Expand Down Expand Up @@ -142,41 +142,46 @@ void ParseConfig::parse_line(It it, const It end) {
error("unexpected '" + std::string(it, end) + "'");
}

void ParseConfig::parse_directive(It it, const It end) {
void ParseConfig::parse_context(It it, const It end) {
skip_space(&it, end);
if (skip(&it, end, "window")) {
skip_space(&it, end);

auto class_filter = std::string();
auto title_filter = std::string();
auto system_filter_matched = true;
// TODO: for backward compatibility, remove
skip(&it, end, "window");
skip(&it, end, "Window");
skip_space(&it, end);

while (it != end) {
const auto attrib = read_ident(&it, end);
skip_space(&it, end);
if (!skip(&it, end, "="))
error("missing '='");
auto class_filter = std::string();
auto title_filter = std::string();
auto system_filter_matched = true;

auto value = read_value(&it, end);
if (attrib == "class") {
class_filter = std::move(value);
}
else if (attrib == "title") {
title_filter = std::move(value);
}
else if (attrib == "system") {
system_filter_matched = (to_lower(std::move(value)) == current_system);
}
else {
error("unexpected '" + attrib + "'");
}
skip_space(&it, end);
while (it != end) {
const auto attrib = read_ident(&it, end);
skip_space(&it, end);
if (!skip(&it, end, "="))
error("missing '='");

auto value = read_value(&it, end);
if (attrib == "class") {
class_filter = std::move(value);
}
begin_window(class_filter, title_filter, system_filter_matched);
}
else {
error("unexpected '" + std::string(it, end) + "'");
else if (attrib == "title") {
title_filter = std::move(value);
}
else if (attrib == "system") {
system_filter_matched = (to_lower(std::move(value)) == current_system);
}
else {
error("unexpected '" + attrib + "'");
}
skip_space(&it, end);
}

// simply set invalid class when system filter did not match
if (!system_filter_matched)
class_filter = "$";

m_config.contexts.push_back(
{ std::move(class_filter), std::move(title_filter) });
}

void ParseConfig::parse_mapping(std::string name, It begin, It end) {
Expand Down Expand Up @@ -286,16 +291,6 @@ void ParseConfig::add_mapping(KeySequence input, KeySequence output) {
m_config.commands.push_back({ "", std::move(input), std::move(output), {} });
}

void ParseConfig::begin_window(std::string class_filter,
std::string title_filter, bool system_filter_matched) {
// simply set invalid class when system filter did not match
if (!system_filter_matched)
class_filter = "$";

m_config.contexts.push_back(
{ std::move(class_filter), std::move(title_filter) });
}

void ParseConfig::add_mapping(std::string name, KeySequence output) {
assert(!name.empty());
const auto it = std::find_if(
Expand Down
4 changes: 1 addition & 3 deletions src/config/ParseConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ParseConfig {

[[noreturn]] void error(std::string message);
void parse_line(It begin, It end);
void parse_directive(It begin, It end);
void parse_context(It begin, It end);
void parse_macro(std::string name, It begin, It end);
void parse_mapping(std::string name, It begin, It end);
std::string parse_command_name(It begin, It end) const;
Expand All @@ -30,8 +30,6 @@ class ParseConfig {
bool has_command(const std::string& name) const;
void add_command(std::string name, KeySequence input);
void add_mapping(KeySequence input, KeySequence output);
void begin_window(std::string class_filter, std::string title_filter,
bool system_filter_matched);
void add_mapping(std::string name, KeySequence output);

int m_line_no{ };
Expand Down
2 changes: 1 addition & 1 deletion src/config/string_iteration.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ template<typename ForwardIt>
bool skip(ForwardIt* it, ForwardIt end, const char* str) {
auto it2 = *it;
while (*str) {
if (it2 == end || tolower(*str) != tolower(*it2))
if (it2 == end || *str != *it2)
return false;
++str;
++it2;
Expand Down
11 changes: 11 additions & 0 deletions src/test/test1_ParseConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,14 @@ TEST_CASE("Macros", "[ParseConfig]") {

//--------------------------------------------------------------------

TEST_CASE("Old and new context format", "[ParseConfig]") {
auto string = R"(
[window class='test' title=test]
[Window class='test' title=test]
[class='test' title=test]
)";
REQUIRE_NOTHROW(parse_config(string));
}

//--------------------------------------------------------------------

0 comments on commit 69de0ef

Please sign in to comment.