Snippets » History » Version 46
Christoph Kappel, 01/23/2018 12:23 PM
1 | 46 | Christoph Kappel | h1. Snippets |
---|---|---|---|
2 | 46 | Christoph Kappel | |
3 | 46 | Christoph Kappel | This page shows small snippets that might be useful. Without further instructions they just need to be copied into the config of [[subtle]]. |
4 | 46 | Christoph Kappel | |
5 | 46 | Christoph Kappel | {{>toc}} |
6 | 46 | Christoph Kappel | |
7 | 46 | Christoph Kappel | h2. Alt-Tab |
8 | 46 | Christoph Kappel | |
9 | 46 | Christoph Kappel | This cycles through windows of view |
10 | 46 | Christoph Kappel | |
11 | 46 | Christoph Kappel | <pre><code class="ruby"> |
12 | 46 | Christoph Kappel | grab "A-Tab" do |
13 | 46 | Christoph Kappel | clients = Subtlext::Client.visible |
14 | 46 | Christoph Kappel | |
15 | 46 | Christoph Kappel | clients.last.instance_eval do |
16 | 46 | Christoph Kappel | focus |
17 | 46 | Christoph Kappel | raise |
18 | 46 | Christoph Kappel | end |
19 | 46 | Christoph Kappel | end |
20 | 46 | Christoph Kappel | |
21 | 46 | Christoph Kappel | grab "A-S-Tab" do |
22 | 46 | Christoph Kappel | clients = Subtlext::Client.visible |
23 | 46 | Christoph Kappel | |
24 | 46 | Christoph Kappel | clients.first.instance_eval do |
25 | 46 | Christoph Kappel | lower |
26 | 46 | Christoph Kappel | end |
27 | 46 | Christoph Kappel | clients.first.instance_eval do |
28 | 46 | Christoph Kappel | focus |
29 | 46 | Christoph Kappel | end |
30 | 46 | Christoph Kappel | end |
31 | 46 | Christoph Kappel | </code></pre> |
32 | 46 | Christoph Kappel | |
33 | 46 | Christoph Kappel | h2. Extend view |
34 | 46 | Christoph Kappel | |
35 | 46 | Christoph Kappel | <pre><code class="ruby"> |
36 | 46 | Christoph Kappel | require "subtle/subtlext" |
37 | 46 | Christoph Kappel | |
38 | 46 | Christoph Kappel | STORE ||= {} |
39 | 46 | Christoph Kappel | |
40 | 46 | Christoph Kappel | module Subtlext |
41 | 46 | Christoph Kappel | class View |
42 | 46 | Christoph Kappel | def method_missing(meth, *args) |
43 | 46 | Christoph Kappel | STORE[self.name] = { } unless(STORE.has_key?(self.name)) |
44 | 46 | Christoph Kappel | |
45 | 46 | Christoph Kappel | if meth.to_s.end_with?("=") |
46 | 46 | Christoph Kappel | meth = meth.to_s.chop.to_sym |
47 | 46 | Christoph Kappel | |
48 | 46 | Christoph Kappel | STORE[self.name][meth] = args[0] |
49 | 46 | Christoph Kappel | else |
50 | 46 | Christoph Kappel | STORE[self.name][meth] |
51 | 46 | Christoph Kappel | end |
52 | 46 | Christoph Kappel | end |
53 | 46 | Christoph Kappel | end |
54 | 46 | Christoph Kappel | end |
55 | 46 | Christoph Kappel | </code></pre> |
56 | 46 | Christoph Kappel | |
57 | 46 | Christoph Kappel | Finally make some use of this like following hook: |
58 | 46 | Christoph Kappel | |
59 | 46 | Christoph Kappel | <pre><code class="ruby"> |
60 | 46 | Christoph Kappel | on :view_jump do |v| |
61 | 46 | Christoph Kappel | v.visits += 1 rescue v.visits = 1 |
62 | 46 | Christoph Kappel | puts "View %s, %d visits" % [ v.name, v.visits ] |
63 | 46 | Christoph Kappel | end |
64 | 46 | Christoph Kappel | </code></pre> |
65 | 46 | Christoph Kappel | |
66 | 46 | Christoph Kappel | h2. Focus gravities |
67 | 46 | Christoph Kappel | |
68 | 46 | Christoph Kappel | Focus window a specific gravities on view. |
69 | 46 | Christoph Kappel | |
70 | 46 | Christoph Kappel | <pre><code class="ruby"> |
71 | 46 | Christoph Kappel | { |
72 | 46 | Christoph Kappel | "KP_7" => :top_left, "KP_8" => :top, "KP_9" => :top_right, |
73 | 46 | Christoph Kappel | "KP_4" => :left, "KP_5" => :center, "KP_6" => :right, |
74 | 46 | Christoph Kappel | "KP_1" => :bottom_left, "KP_2" => :bottom, "KP_3" => :bottom_right |
75 | 46 | Christoph Kappel | }.each do |k, v| |
76 | 46 | Christoph Kappel | grab "A-C-" + k, lambda { |
77 | 46 | Christoph Kappel | c = Subtlext::View.current.clients.select { |c| |
78 | 46 | Christoph Kappel | c.gravity.name.to_sym == v |
79 | 46 | Christoph Kappel | } |
80 | 46 | Christoph Kappel | |
81 | 46 | Christoph Kappel | c.first.focus unless(c.empty?) |
82 | 46 | Christoph Kappel | } |
83 | 46 | Christoph Kappel | end |
84 | 46 | Christoph Kappel | </code></pre> |
85 | 46 | Christoph Kappel | |
86 | 46 | Christoph Kappel | h2. Move windows |
87 | 46 | Christoph Kappel | |
88 | 46 | Christoph Kappel | This snippet adds nine [[grabs]] to move windows on the fly to nine defined views. It uses [[tagging]] for this, creates [[tags]] based on the view names and applies them when needed. |
89 | 46 | Christoph Kappel | |
90 | 46 | Christoph Kappel | <pre><code class="ruby"> |
91 | 46 | Christoph Kappel | on :start do |
92 | 46 | Christoph Kappel | # Create missing tags |
93 | 46 | Christoph Kappel | views = Subtlext::View.all.map { |v| v.name } |
94 | 46 | Christoph Kappel | tags = Subtlext::Tag.all.map { |t| t.name } |
95 | 46 | Christoph Kappel | |
96 | 46 | Christoph Kappel | views.each do |v| |
97 | 46 | Christoph Kappel | unless tags.include?(v) |
98 | 46 | Christoph Kappel | t = Subtlext::Tag.new(v) |
99 | 46 | Christoph Kappel | t.save |
100 | 46 | Christoph Kappel | end |
101 | 46 | Christoph Kappel | end |
102 | 46 | Christoph Kappel | end |
103 | 46 | Christoph Kappel | |
104 | 46 | Christoph Kappel | # Add nine C-< number> grabs |
105 | 46 | Christoph Kappel | (1..9).each do |i| |
106 | 46 | Christoph Kappel | grab "C-%d" % [ i ] do |c| |
107 | 46 | Christoph Kappel | views = Subtlext::View.all |
108 | 46 | Christoph Kappel | names = views.map { |v| v.name } |
109 | 46 | Christoph Kappel | |
110 | 46 | Christoph Kappel | # Sanity check |
111 | 46 | Christoph Kappel | if i <= views.size |
112 | 46 | Christoph Kappel | # Tag client |
113 | 46 | Christoph Kappel | tags = c.tags.reject { |t| names.include?(t.name) or "default" == t.name } |
114 | 46 | Christoph Kappel | tags << names[i - 1] |
115 | 46 | Christoph Kappel | |
116 | 46 | Christoph Kappel | c.tags = tags |
117 | 46 | Christoph Kappel | |
118 | 46 | Christoph Kappel | # Tag view |
119 | 46 | Christoph Kappel | views[i - 1].tag(names[i - 1]) |
120 | 46 | Christoph Kappel | end |
121 | 46 | Christoph Kappel | end |
122 | 46 | Christoph Kappel | end |
123 | 46 | Christoph Kappel | </code></pre> |
124 | 46 | Christoph Kappel | |
125 | 46 | Christoph Kappel | h2. Current view |
126 | 46 | Christoph Kappel | |
127 | 46 | Christoph Kappel | This snippet works similar to the previous, it adds tags based on the view names. When there is an untagged window (a window with the default tag only) it adds the name of the current view as tag, which effectively moves the window to the current view. |
128 | 46 | Christoph Kappel | |
129 | 46 | Christoph Kappel | <pre><code class="ruby"> |
130 | 46 | Christoph Kappel | on :start do |
131 | 46 | Christoph Kappel | # Create missing tags |
132 | 46 | Christoph Kappel | views = Subtlext::View.all.map { |v| v.name } |
133 | 46 | Christoph Kappel | tags = Subtlext::Tag.all.map { |t| t.name } |
134 | 46 | Christoph Kappel | |
135 | 46 | Christoph Kappel | views.each do |v| |
136 | 46 | Christoph Kappel | unless tags.include?(v) |
137 | 46 | Christoph Kappel | t = Subtlext::Tag.new(v) |
138 | 46 | Christoph Kappel | t.save |
139 | 46 | Christoph Kappel | end |
140 | 46 | Christoph Kappel | end |
141 | 46 | Christoph Kappel | end |
142 | 46 | Christoph Kappel | |
143 | 46 | Christoph Kappel | # Assign tags to clients |
144 | 46 | Christoph Kappel | on :client_create do |c| |
145 | 46 | Christoph Kappel | view = Subtlext::View.current |
146 | 46 | Christoph Kappel | tags = c.tags.map { |t| t.name } |
147 | 46 | Christoph Kappel | |
148 | 46 | Christoph Kappel | # Add tag to view |
149 | 46 | Christoph Kappel | view.tag(view.name) unless(view.tags.include?(view.name)) |
150 | 46 | Christoph Kappel | |
151 | 46 | Christoph Kappel | # Exclusive for clients with default tag only |
152 | 46 | Christoph Kappel | if tags.include?("default") and 1 == tags.size |
153 | 46 | Christoph Kappel | c.tags = [ view.name ] |
154 | 46 | Christoph Kappel | end |
155 | 46 | Christoph Kappel | end |
156 | 46 | Christoph Kappel | </code></pre> |
157 | 46 | Christoph Kappel | |
158 | 46 | Christoph Kappel | h2. Scratchpad |
159 | 46 | Christoph Kappel | |
160 | 46 | Christoph Kappel | The scratchpad snippet is just a small hack of the tagging. Normally [[subtle]] doesn't allow to create a window without tags, so that it's never visible. This grab just creates a "urxvt":http://software.schmorp.de/pkg/rxvt-unicode.html, strips all [[tagging|tags]] and sets sticky. On the next press it just toggles sticky and blends the window in and out, like a scratchpad. |
161 | 46 | Christoph Kappel | |
162 | 46 | Christoph Kappel | <pre><code class="ruby">grab "A-b" do |
163 | 46 | Christoph Kappel | if (c = Subtlext::Client.first("scratch")) |
164 | 46 | Christoph Kappel | c.toggle_stick |
165 | 46 | Christoph Kappel | c.focus |
166 | 46 | Christoph Kappel | elsif (c = Subtlext::Client.spawn("urxvt -name scratch")) |
167 | 46 | Christoph Kappel | c.tags = [] |
168 | 46 | Christoph Kappel | c.flags = [ :stick ] |
169 | 46 | Christoph Kappel | end |
170 | 46 | Christoph Kappel | end |
171 | 46 | Christoph Kappel | </code></pre> |
172 | 46 | Christoph Kappel | |
173 | 46 | Christoph Kappel | h2. Scratchstack |
174 | 46 | Christoph Kappel | |
175 | 46 | Christoph Kappel | Like the [[snippets#Scratchpad|Scratchpad]], this [[snippets|snippet]] can show and hide a [[client]], but instead just one specific [[clients|client]], it can cycle through multiple running ones. There are basically three [[grabs]]: |
176 | 46 | Christoph Kappel | |
177 | 46 | Christoph Kappel | # *Win-Keypad+* Adds a [[clients|client]] to the stack and initially hides it |
178 | 46 | Christoph Kappel | # *Win-Keypad-* Removes a [[clients|client]] fromt he stack and retags it |
179 | 46 | Christoph Kappel | # *Win-comma* Cycles through the [[clients]] on the stack |
180 | 46 | Christoph Kappel | |
181 | 46 | Christoph Kappel | <pre><code class="ruby"> |
182 | 46 | Christoph Kappel | scratch_stack = [] |
183 | 46 | Christoph Kappel | scratch_current = 0 |
184 | 46 | Christoph Kappel | |
185 | 46 | Christoph Kappel | # Add window to stack |
186 | 46 | Christoph Kappel | grab modkey + "-KP_Add" do |c| |
187 | 46 | Christoph Kappel | unless scratch_stack.include?(c.win) |
188 | 46 | Christoph Kappel | scratch_stack << c.win |
189 | 46 | Christoph Kappel | c.tags = [] |
190 | 46 | Christoph Kappel | c.toggle_stick if c.is_stick? |
191 | 46 | Christoph Kappel | end |
192 | 46 | Christoph Kappel | end |
193 | 46 | Christoph Kappel | |
194 | 46 | Christoph Kappel | # Remove window from stack |
195 | 46 | Christoph Kappel | grab modkey + "-KP_Subtract" do |c| |
196 | 46 | Christoph Kappel | if scratch_stack.include?(c.win) |
197 | 46 | Christoph Kappel | c.retag |
198 | 46 | Christoph Kappel | scratch_stack.delete(c.win) |
199 | 46 | Christoph Kappel | end |
200 | 46 | Christoph Kappel | end |
201 | 46 | Christoph Kappel | |
202 | 46 | Christoph Kappel | # Cycle through stack windows |
203 | 46 | Christoph Kappel | grab modkey + "-comma" do |
204 | 46 | Christoph Kappel | # Get id of next window |
205 | 46 | Christoph Kappel | if 0 < scratch_current |
206 | 46 | Christoph Kappel | cur_idx = scratch_stack.index(scratch_current) |
207 | 46 | Christoph Kappel | |
208 | 46 | Christoph Kappel | # Hide current window |
209 | 46 | Christoph Kappel | cur_client = Subtlext::Client[scratch_current] |
210 | 46 | Christoph Kappel | cur_client.toggle_stick |
211 | 46 | Christoph Kappel | |
212 | 46 | Christoph Kappel | # Check whether cur is last window of stack |
213 | 46 | Christoph Kappel | if cur_idx == scratch_stack.size - 1 |
214 | 46 | Christoph Kappel | scratch_current = 0 |
215 | 46 | Christoph Kappel | |
216 | 46 | Christoph Kappel | return |
217 | 46 | Christoph Kappel | end |
218 | 46 | Christoph Kappel | |
219 | 46 | Christoph Kappel | idx = cur_idx + 1 |
220 | 46 | Christoph Kappel | else |
221 | 46 | Christoph Kappel | idx = 0 |
222 | 46 | Christoph Kappel | end |
223 | 46 | Christoph Kappel | |
224 | 46 | Christoph Kappel | # Show next window |
225 | 46 | Christoph Kappel | cur = Subtlext::Client[scratch_stack[idx]] |
226 | 46 | Christoph Kappel | |
227 | 46 | Christoph Kappel | scratch_current = cur.win |
228 | 46 | Christoph Kappel | cur.toggle_stick |
229 | 46 | Christoph Kappel | end |
230 | 46 | Christoph Kappel | </code></pre> |
231 | 46 | Christoph Kappel | |
232 | 46 | Christoph Kappel | h2. Check config |
233 | 46 | Christoph Kappel | |
234 | 46 | Christoph Kappel | In case you keep forgetting to run @subtle -k@ after changing the config this might be handy for you. It checks the config, displays a message via xmessage or just reloads the config. |
235 | 46 | Christoph Kappel | |
236 | 46 | Christoph Kappel | <pre><code class="ruby"># Make xmessage stick and urgent |
237 | 46 | Christoph Kappel | tag "xmessage" do |
238 | 46 | Christoph Kappel | match "xmessage" |
239 | 46 | Christoph Kappel | float true |
240 | 46 | Christoph Kappel | stick true |
241 | 46 | Christoph Kappel | urgent true |
242 | 46 | Christoph Kappel | end |
243 | 46 | Christoph Kappel | |
244 | 46 | Christoph Kappel | # The actual grab |
245 | 46 | Christoph Kappel | grab "A-C-r", <<SCRIPT |
246 | 46 | Christoph Kappel | subtle -k &>/dev/null |
247 | 46 | Christoph Kappel | reload=$? |
248 | 46 | Christoph Kappel | |
249 | 46 | Christoph Kappel | if [ $reload -eq 1 ] ; then |
250 | 46 | Christoph Kappel | xmessage 'Syntax error, reload anyway?' -center -buttons NO:1,YES:0 |
251 | 46 | Christoph Kappel | reload=$? |
252 | 46 | Christoph Kappel | fi |
253 | 46 | Christoph Kappel | |
254 | 46 | Christoph Kappel | [ $reload -eq 0 ] && subtler -r |
255 | 46 | Christoph Kappel | SCRIPT |
256 | 46 | Christoph Kappel | </code></pre> |
257 | 46 | Christoph Kappel | |
258 | 46 | Christoph Kappel | h2. Switch view |
259 | 46 | Christoph Kappel | |
260 | 46 | Christoph Kappel | Allow you to go to the next non-empty view. very useful when you don't want :ViewNext to go into hidden views (Mostly with dynamic views) |
261 | 46 | Christoph Kappel | |
262 | 46 | Christoph Kappel | <pre><code class="ruby"> |
263 | 46 | Christoph Kappel | def goto_next_view(vArr) |
264 | 46 | Christoph Kappel | cindx = vArr.index(Subtlext::View.current); |
265 | 46 | Christoph Kappel | |
266 | 46 | Christoph Kappel | #Find the next view beyond all existing |
267 | 46 | Christoph Kappel | for i in 1..vArr.size do |
268 | 46 | Christoph Kappel | cV = vArr[(i + cindx) % vArr.size]; |
269 | 46 | Christoph Kappel | |
270 | 46 | Christoph Kappel | # Verify that the potential next view isn't displayed on another screens |
271 | 46 | Christoph Kappel | if (Subtlext::View.visible.index(cV) == nil) then |
272 | 46 | Christoph Kappel | containsClients = false; |
273 | 46 | Christoph Kappel | # Check if the view has clients and if those clients are not only sticky one. |
274 | 46 | Christoph Kappel | cV.clients.each {|c| |
275 | 46 | Christoph Kappel | containsClients = !(cV.tags & c.tags).empty?; |
276 | 46 | Christoph Kappel | if(containsClients) |
277 | 46 | Christoph Kappel | break; |
278 | 46 | Christoph Kappel | end |
279 | 46 | Christoph Kappel | } |
280 | 46 | Christoph Kappel | |
281 | 46 | Christoph Kappel | if (containsClients) then |
282 | 46 | Christoph Kappel | cV.jump; |
283 | 46 | Christoph Kappel | break; |
284 | 46 | Christoph Kappel | end; |
285 | 46 | Christoph Kappel | end |
286 | 46 | Christoph Kappel | end |
287 | 46 | Christoph Kappel | end |
288 | 46 | Christoph Kappel | |
289 | 46 | Christoph Kappel | grab "W-Right" do |
290 | 46 | Christoph Kappel | goto_next_view(Subtlext::View[:all]); |
291 | 46 | Christoph Kappel | end |
292 | 46 | Christoph Kappel | |
293 | 46 | Christoph Kappel | grab "W-Left" do |
294 | 46 | Christoph Kappel | goto_next_view(Subtlext::View[:all].reverse); |
295 | 46 | Christoph Kappel | end |
296 | 46 | Christoph Kappel | |
297 | 46 | Christoph Kappel | |
298 | 46 | Christoph Kappel | </code></pre> |