Snippets¶
This page shows small snippets that might be useful. Without further instructions they just need to be copied into the config of subtle.
Alt-Tab¶
This cycles through windows of view
Numbers: on /off 1 grab "A-Tab" do
2 clients = Subtlext::Client.visible
3
4 clients.last.instance_eval do
5 focus
6 raise
7 end
8 end
9
10 grab "A-S-Tab" do
11 clients = Subtlext::Client.visible
12
13 clients.first.instance_eval do
14 lower
15 end
16 clients.first.instance_eval do
17 focus
18 end
19 end
Extend view¶
Numbers: on /off 1 require "subtle/subtlext"
2
3 STORE ||= {}
4
5 module Subtlext
6 class View
7 def method_missing(meth, *args)
8 STORE[self.name] = { } unless(STORE.has_key?(self.name))
9
10 if meth.to_s.end_with?("=")
11 meth = meth.to_s.chop.to_sym
12
13 STORE[self.name][meth] = args[0]
14 else
15 STORE[self.name][meth]
16 end
17 end
18 end
19 end
Finally make some use of this like following hook:
Numbers: on /off1 on :view_jump do |v|
2 v.visits += 1 rescue v.visits = 1
3 puts "View %s, %d visits" % [ v.name, v.visits ]
4 end
Focus gravities¶
Focus window a specific gravities on view.
Numbers: on /off 1 {
2 "KP_7" => :top_left, "KP_8" => :top, "KP_9" => :top_right,
3 "KP_4" => :left, "KP_5" => :center, "KP_6" => :right,
4 "KP_1" => :bottom_left, "KP_2" => :bottom, "KP_3" => :bottom_right
5 }.each do |k, v|
6 grab "A-C-" + k, lambda {
7 c = Subtlext::View.current.clients.select { |c|
8 c.gravity.name.to_sym == v
9 }
10
11 c.first.focus unless(c.empty?)
12 }
13 end
Move windows¶
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.
Numbers: on /off 1 on :start do
2 # Create missing tags
3 views = Subtlext::View.all.map { |v| v.name }
4 tags = Subtlext::Tag.all.map { |t| t.name }
5
6 views.each do |v|
7 unless tags.include?(v)
8 t = Subtlext::Tag.new(v)
9 t.save
10 end
11 end
12 end
13
14 # Add nine C-< number> grabs
15 (1..9).each do |i|
16 grab "C-%d" % [ i ] do |c|
17 views = Subtlext::View.all
18 names = views.map { |v| v.name }
19
20 # Sanity check
21 if i <= views.size
22 # Tag client
23 tags = c.tags.reject { |t| names.include?(t.name) or "default" == t.name }
24 tags << names[i - 1]
25
26 c.tags = tags
27
28 # Tag view
29 views[i - 1].tag(names[i - 1])
30 end
31 end
32 end
Current view¶
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.
Numbers: on /off 1 on :start do
2 # Create missing tags
3 views = Subtlext::View.all.map { |v| v.name }
4 tags = Subtlext::Tag.all.map { |t| t.name }
5
6 views.each do |v|
7 unless tags.include?(v)
8 t = Subtlext::Tag.new(v)
9 t.save
10 end
11 end
12 end
13
14 # Assign tags to clients
15 on :client_create do |c|
16 view = Subtlext::View.current
17 tags = c.tags.map { |t| t.name }
18
19 # Add tag to view
20 view.tag(view.name) unless(view.tags.include?(view.name))
21
22 # Exclusive for clients with default tag only
23 if tags.include?("default") and 1 == tags.size
24 c.tags = [ view.name ]
25 end
26 end
Scratchpad¶
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, strips all tags and sets sticky. On the next press it just toggles sticky and blends the window in and out, like a scratchpad.
Numbers: on /off 1 grab "A-b" do
2 if (c = Subtlext::Client.first("scratch"))
3 c.toggle_stick
4 c.focus
5 elsif (c = Subtlext::Client.spawn("urxvt -name scratch"))
6 c.tags = []
7 c.flags = [ :stick ]
8 end
9 end
Scratchstack¶
Like the Scratchpad, this snippet can show and hide a client, but instead just one specific client, it can cycle through multiple running ones. There are basically three grabs:
- Win-Keypad+ Adds a client to the stack and initially hides it
- Win-Keypad- Removes a client fromt he stack and retags it
- Win-comma Cycles through the clients on the stack
Numbers: on /off 1 scratch_stack = []
2 scratch_current = 0
3
4 # Add window to stack
5 grab modkey + "-KP_Add" do |c|
6 unless scratch_stack.include?(c.win)
7 scratch_stack << c.win
8 c.tags = []
9 c.toggle_stick if c.is_stick?
10 end
11 end
12
13 # Remove window from stack
14 grab modkey + "-KP_Subtract" do |c|
15 if scratch_stack.include?(c.win)
16 c.retag
17 scratch_stack.delete(c.win)
18 end
19 end
20
21 # Cycle through stack windows
22 grab modkey + "-comma" do
23 # Get id of next window
24 if 0 < scratch_current
25 cur_idx = scratch_stack.index(scratch_current)
26
27 # Hide current window
28 cur_client = Subtlext::Client[scratch_current]
29 cur_client.toggle_stick
30
31 # Check whether cur is last window of stack
32 if cur_idx == scratch_stack.size - 1
33 scratch_current = 0
34
35 return
36 end
37
38 idx = cur_idx + 1
39 else
40 idx = 0
41 end
42
43 # Show next window
44 cur = Subtlext::Client[scratch_stack[idx]]
45
46 scratch_current = cur.win
47 cur.toggle_stick
48 end
Check config¶
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.
Numbers: on /off 1 # Make xmessage stick and urgent
2 tag "xmessage" do
3 match "xmessage"
4 float true
5 stick true
6 urgent true
7 end
8
9 # The actual grab
10 grab "A-C-r", <<SCRIPT
11 subtle -k &>/dev/null
12 reload=$?
13
14 if [ $reload -eq 1 ] ; then
15 xmessage 'Syntax error, reload anyway?' -center -buttons NO:1,YES:0
16 reload=$?
17 fi
18
19 [ $reload -eq 0 ] && subtler -r
20 SCRIPT
Switch view¶
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)
Numbers: on /off 1 def goto_next_view(vArr)
2 cindx = vArr.index(Subtlext::View.current);
3
4 #Find the next view beyond all existing
5 for i in 1..vArr.size do
6 cV = vArr[(i + cindx) % vArr.size];
7
8 # Verify that the potential next view isn't displayed on another screens
9 if (Subtlext::View.visible.index(cV) == nil) then
10 containsClients = false;
11 # Check if the view has clients and if those clients are not only sticky one.
12 cV.clients.each {|c|
13 containsClients = !(cV.tags & c.tags).empty?;
14 if(containsClients)
15 break;
16 end
17 }
18
19 if (containsClients) then
20 cV.jump;
21 break;
22 end;
23 end
24 end
25 end
26
27 grab "W-Right" do
28 goto_next_view(Subtlext::View[:all]);
29 end
30
31 grab "W-Left" do
32 goto_next_view(Subtlext::View[:all].reverse);
33 end
34