Project

General

Profile

unexist.dev

subtle

Assorted tidbits and projects

Snippets » History » Version 44

Fran├žois-Xavier LdM, 12/27/2013 04:24 PM

1 44 Fran├žois-Xavier LdM
h1. Snippets\015\012\015\012This page shows small snippets that might be useful. Without further instructions they just need to be copied into the config of [[subtle]].\015\012\015\012{{>toc}}\015\012\015\012h2. Alt-Tab\015\012\015\012This cycles through windows of view\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012grab "A-Tab" do\015\012  clients = Subtlext::Client.visible\015\012\015\012  clients.last.instance_eval do\015\012    focus\015\012    raise\015\012  end\015\012end\015\012\015\012grab "A-S-Tab" do \015\012clients = Subtlext::Client.visible\015\012\015\012  clients.first.instance_eval do                                                 \015\012    lower                                                                        \015\012  end\015\012  clients.first.instance_eval do\015\012    focus\015\012  end                                                                            \015\012end\015\012</code></pre>\015\012\015\012h2. Extend view\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012require "subtle/subtlext"\015\012\015\012STORE ||= {}\015\012\015\012module Subtlext\015\012  class View\015\012    def method_missing(meth, *args)\015\012      STORE[self.name] = { } unless(STORE.has_key?(self.name))\015\012\015\012      if meth.to_s.end_with?("=")\015\012        meth = meth.to_s.chop.to_sym\015\012\015\012        STORE[self.name][meth] = args[0]\015\012      else\015\012        STORE[self.name][meth]\015\012      end\015\012    end\015\012  end\015\012end\015\012</code></pre>\015\012\015\012Finally make some use of this like following hook:\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012on :view_jump do |v|\015\012  v.visits += 1 rescue v.visits = 1\015\012  puts "View %s, %d visits" % [ v.name, v.visits ]\015\012end\015\012</code></pre>\015\012\015\012h2. Focus gravities\015\012\015\012Focus window a specific gravities on view.\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012{\015\012  "KP_7" => :top_left,    "KP_8" => :top,    "KP_9" => :top_right,\015\012  "KP_4" => :left,        "KP_5" => :center, "KP_6" => :right,\015\012  "KP_1" => :bottom_left, "KP_2" => :bottom, "KP_3" => :bottom_right\015\012}.each do |k, v|\015\012  grab "A-C-" + k, lambda {\015\012    c = Subtlext::View.current.clients.select { |c|\015\012      c.gravity.name.to_sym == v\015\012    }\015\012  \015\012    c.first.focus unless(c.empty?)\015\012  }\015\012end\015\012</code></pre>\015\012\015\012h2. Move windows\015\012\015\012This 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.\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012on :start do\015\012  # Create missing tags\015\012  views = Subtlext::View.all.map { |v| v.name }\015\012  tags  = Subtlext::Tag.all.map { |t| t.name }\015\012\015\012  views.each do |v|\015\012    unless tags.include?(v)\015\012      t = Subtlext::Tag.new(v)\015\012      t.save\015\012    end\015\012  end\015\012end\015\012\015\012# Add nine C-< number> grabs\015\012(1..9).each do |i|\015\012 grab "C-%d" % [ i ] do |c|\015\012   views = Subtlext::View.all\015\012   names = views.map { |v| v.name }\015\012\015\012   # Sanity check\015\012   if i <= views.size\015\012     # Tag client\015\012     tags = c.tags.reject { |t| names.include?(t.name) or "default" == t.name }\015\012     tags << names[i - 1]\015\012\015\012     c.tags = tags\015\012\015\012     # Tag view\015\012     views[i - 1].tag(names[i - 1])\015\012   end\015\012 end\015\012end\015\012</code></pre>\015\012\015\012h2. Current view\015\012\015\012This 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.\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012on :start do\015\012  # Create missing tags\015\012  views = Subtlext::View.all.map { |v| v.name }\015\012  tags  = Subtlext::Tag.all.map { |t| t.name }\015\012\015\012  views.each do |v|\015\012    unless tags.include?(v)\015\012      t = Subtlext::Tag.new(v)\015\012      t.save\015\012    end\015\012  end\015\012end\015\012\015\012# Assign tags to clients\015\012on :client_create do |c|\015\012  view = Subtlext::View.current\015\012  tags = c.tags.map { |t| t.name }\015\012\015\012  # Add tag to view\015\012  view.tag(view.name) unless(view.tags.include?(view.name))\015\012\015\012  # Exclusive for clients with default tag only\015\012  if tags.include?("default") and 1 == tags.size\015\012    c.tags = [ view.name ]\015\012  end\015\012end\015\012</code></pre>\015\012\015\012h2. Scratchpad\015\012\015\012The 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.\015\012\015\012<pre>{{hide}}<code class="ruby">grab "A-b" do\015\012  if (c = Subtlext::Client.first("scratch"))\015\012    c.toggle_stick\015\012    c.focus\015\012  elsif (c = Subtlext::Client.spawn("urxvt -name scratch"))\015\012    c.tags  = [] \015\012    c.flags = [ :stick ]\015\012  end\015\012end\015\012</code></pre>\015\012\015\012h2. Scratchstack\015\012\015\012Like 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]]:\015\012\015\012# *Win-Keypad+* Adds a [[clients|client]] to the stack and initially hides it\015\012# *Win-Keypad-* Removes a [[clients|client]] fromt he stack and retags it\015\012# *Win-comma* Cycles through the [[clients]] on the stack\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012scratch_stack   = []\015\012scratch_current = 0\015\012\015\012# Add window to stack\015\012grab modkey + "-KP_Add" do |c|\015\012  unless scratch_stack.include?(c.win)\015\012    scratch_stack << c.win\015\012    c.tags = []\015\012    c.toggle_stick if c.is_stick?\015\012  end\015\012end\015\012\015\012# Remove window from stack\015\012grab modkey + "-KP_Subtract" do |c|\015\012  if scratch_stack.include?(c.win)\015\012    c.retag\015\012    scratch_stack.delete(c.win)\015\012  end\015\012end\015\012\015\012# Cycle through stack windows\015\012grab modkey + "-comma" do\015\012  # Get id of next window\015\012  if 0 < scratch_current\015\012    cur_idx = scratch_stack.index(scratch_current)\015\012\015\012    # Hide current window\015\012    cur_client = Subtlext::Client[scratch_current]\015\012    cur_client.toggle_stick\015\012\015\012    # Check whether cur is last window of stack\015\012    if cur_idx == scratch_stack.size - 1\015\012      scratch_current = 0\015\012\015\012      return\015\012    end\015\012\015\012    idx = cur_idx + 1\015\012  else\015\012    idx = 0\015\012  end\015\012\015\012  # Show next window\015\012  cur = Subtlext::Client[scratch_stack[idx]]\015\012\015\012  scratch_current = cur.win\015\012  cur.toggle_stick\015\012end\015\012</code></pre>\015\012\015\012h2. Check config\015\012\015\012In 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.\015\012\015\012<pre>{{hide}}<code class="ruby"># Make xmessage stick and urgent\015\012tag "xmessage" do\015\012  match  "xmessage"\015\012  float  true\015\012  stick  true\015\012  urgent true\015\012end\015\012\015\012# The actual grab\015\012grab "A-C-r", <<SCRIPT\015\012subtle -k &>/dev/null\015\012reload=$?\015\012\015\012if [ $reload -eq 1 ] ; then\015\012  xmessage 'Syntax error, reload anyway?' -center -buttons NO:1,YES:0\015\012  reload=$?\015\012fi\015\012\015\012[ $reload -eq 0 ] && subtler -r\015\012SCRIPT\015\012</code></pre>\015\012\015\012h2. Switch view\015\012\015\012Allow 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)\015\012\015\012<pre>{{hide}}<code class="ruby">\015\012def goto_next_view(vArr)\015\012    cindx = vArr.index(Subtlext::View.current);\015\012\015\012    #Find the next view beyond all existing\015\012    for i in 1..vArr.size do\015\012        cV = vArr[(i + cindx) % vArr.size];\015\012\015\012        # Verify that the potential next view isn't display in another screen\015\012        if (Subtlext::View.visible.index(cV) == nil) then\015\012            containsClients = false;\015\012            # Check if the view has clients and if there are not only sticky on.\015\012            cV.clients.each {|c|\015\012                containsClients = !(cV.tags & c.tags).empty?;\015\012                if(containsClients)\015\012                    break;\015\012                end\015\012            }\015\012\015\012            if (containsClients) then\015\012                cV.jump;\015\012                break;\015\012            end;\015\012        end\015\012    end\015\012end\015\012\015\012grab "W-Right" do\015\012    goto_next_view(Subtlext::View[:all]);\015\012end\015\012\015\012grab "W-Left" do\015\012    goto_next_view(Subtlext::View[:all].reverse);\015\012end\015\012\015\012\015\012</code></pre>