Project

General

Profile

unexist.dev

/

subtle

Assorted tidbits and projects

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>