rules.hh (4811B)
1 #ifndef __RULES_H_GUARD__ 2 #define __RULES_H_GUARD__ 3 4 #include "../winsys/geometry.hh" 5 #include "client.hh" 6 #include "defaults.hh" 7 8 #include <optional> 9 #include <vector> 10 #include <iostream> 11 12 struct Rules 13 { 14 Rules() 15 : do_focus(std::nullopt), 16 do_float(std::nullopt), 17 do_center(std::nullopt), 18 do_fullscreen(std::nullopt), 19 to_partition(std::nullopt), 20 to_context(std::nullopt), 21 to_workspace(std::nullopt), 22 snap_edges(std::nullopt) 23 {} 24 25 ~Rules() = default; 26 27 std::optional<bool> do_focus; 28 std::optional<bool> do_float; 29 std::optional<bool> do_center; 30 std::optional<bool> do_fullscreen; 31 std::optional<Index> to_partition; 32 std::optional<Index> to_context; 33 std::optional<Index> to_workspace; 34 std::optional<std::vector<winsys::Edge>> snap_edges; 35 36 static Rules 37 parse_rules(std::string_view rule, bool ignore_prefix = false) 38 { 39 static std::string prefix = WM_NAME + ":"; 40 static auto snapedge_list_handler = [](Rules& rules, auto iter) { 41 switch (*iter) { 42 case 'l': rules.snap_edges->push_back(winsys::Edge::Left); return; 43 case 't': rules.snap_edges->push_back(winsys::Edge::Top); return; 44 case 'r': rules.snap_edges->push_back(winsys::Edge::Right); return; 45 case 'b': rules.snap_edges->push_back(winsys::Edge::Bottom); return; 46 default: return; 47 } 48 }; 49 50 Rules rules{}; 51 52 if (!ignore_prefix && rule.size() <= prefix.size()) 53 return rules; 54 55 auto res = std::mismatch( 56 prefix.begin(), 57 prefix.end(), 58 rule.begin() 59 ); 60 61 if (ignore_prefix || res.first == prefix.end()) { 62 bool invert = false; 63 bool next_partition = false; 64 bool next_context = false; 65 bool next_workspace = false; 66 67 std::optional<decltype(snapedge_list_handler)> list_handler = std::nullopt; 68 69 for (auto iter = res.second; iter != rule.end(); ++iter) { 70 if (*iter == '.') { 71 list_handler = std::nullopt; 72 continue; 73 } 74 75 if (list_handler) { 76 (*list_handler)(rules, iter); 77 continue; 78 } 79 80 if (*iter == '!') { 81 invert = true; 82 continue; 83 } 84 85 if (*iter == 'P') { 86 next_partition = true; 87 continue; 88 } 89 90 if (*iter == 'C') { 91 next_context = true; 92 continue; 93 } 94 95 if (*iter == 'W') { 96 next_workspace = true; 97 continue; 98 } 99 100 if (*iter == '@') 101 rules.do_focus = !invert; 102 103 if (*iter == 'f') 104 rules.do_float = !invert; 105 106 if (*iter == 'F') 107 rules.do_fullscreen = !invert; 108 109 if (*iter == 'c') 110 rules.do_center = !invert; 111 112 if (*iter >= '0' && *iter <= '9') { 113 if (next_partition) 114 rules.to_partition = *iter - '0'; 115 116 if (next_context) 117 rules.to_context = *iter - '0'; 118 119 if (next_workspace) 120 rules.to_workspace = *iter - '0'; 121 } 122 123 if (*iter == 'S') { 124 if (!rules.snap_edges) 125 rules.snap_edges = std::vector<winsys::Edge>{}; 126 127 list_handler = snapedge_list_handler; 128 } 129 130 invert = false; 131 next_partition = false; 132 next_context = false; 133 next_workspace = false; 134 } 135 } 136 137 return rules; 138 } 139 140 static Rules 141 merge_rules(Rules const& base, Rules const& merger) 142 { 143 Rules rules = base; 144 145 if (merger.do_focus) 146 rules.do_focus = merger.do_focus; 147 148 if (merger.do_float) 149 rules.do_float = merger.do_float; 150 151 if (merger.do_center) 152 rules.do_center = merger.do_center; 153 154 if (merger.do_fullscreen) 155 rules.do_fullscreen = merger.do_fullscreen; 156 157 if (merger.to_partition) 158 rules.to_partition = merger.to_partition; 159 160 if (merger.to_context) 161 rules.to_context = merger.to_context; 162 163 if (merger.to_workspace) 164 rules.to_workspace = merger.to_workspace; 165 166 if (merger.snap_edges) 167 rules.snap_edges = merger.snap_edges; 168 169 return rules; 170 } 171 }; 172 173 #endif//__RULES_H_GUARD__