Writing sublets » History » Version 2
« Previous -
Version 2/13
(diff) -
Next » -
Current version
Anonymous, 01/02/2011 03:48 PM
Writing sublets\015\012\015\012{{>toc}}\015\012\015\012h2. Hello world\015\012\015\012Starting a sublet from scratch is really easy, just create an empty sublet with sur: sur template hello
\015\012\015\012This will create a folder hello with two files:\015\012\015\012| hello.rb | The sublet file with the minimal required code |\015\012| hello.spec | The specification file with basic information for sur about the sublet |\015\012\015\012h3. Say hello\015\012\015\012Per default, the new sublet will do nothing and we need to add something do the data field:\015\012\015\012{{hide}}# Hello sublet file\015\012# Created with sur-0.2\015\012configure :hello do |s|\015\012 s.interval = 60\015\012end\015\012\015\012on :run do |s|\015\012 s.data = "Hello, world!"\015\012end
\015\012\015\012h3. Test your sublet\015\012\015\012sur comes with a tester for sublet to ease the whole thing: sur test hello/hello.rb\015\012\015\012The output looks like this:\015\012\015\012
\015\012\015\012The lines starting with @ show the defined instanced variables, the lines with (1) the callable methods.\015\012\015\012h3. Install and submit\015\012\015\012Once you are satisfied with your work you need to build your sublet: @sur build hello/hello.spec\015\012\015\012This will create a hello-0.0.sublet file that can either be installed locally sur install ./hello-0.0.sublet
or uploaded to the sur repository sur submit ./hello-0.0.sublet
and installed from there.\015\012\015\012h2. Types\015\012\015\012Generally there are two different types of Sublets:\015\012\015\012* sublets that are updated by given interval in seconds (default 60s)\015\012* sublets that are updated when a file is modified (via inotify) or via socket\015\012* sublets that are updated via SUBTLE_SUBLET_DATA client message\015\012\015\012The sublet data must be of type String, everything else will be ignored.\015\012\015\012h2. Events\015\012\015\012Sublets are event driven, so there are some specific events only for sublets:\015\012\015\012| :mouse_over | Whenever the pointer is over the sublet |\015\012| :mouse_down | Whenever the pointer is pressed on the sublet. Can have three arguments: x, y, button. |\015\012| :mouse_out | Whenever the pointer leaves the sublet |\015\012| :run | Whenever either the interval time is expired |\015\012| :watch | Whenever the watched file is modified/socket has data ready |\015\012| :data | Whenever subtle receives a SUBTLE_SUBLET_DATA client message for this sublet |\015\012| :unload | Whenever the sublet is unloaded |\015\012\015\012h2. Hooks\015\012\015\012Sublets can use all hooks that are useable in the main config too, the syntax is almost the same:\015\012\015\012{{hide}}on :client_create do |s, c|\015\012 puts s.name #< Name of the sublet\015\012 puts c.name #< Name of the client\015\012end
\015\012\015\012h2. Grabs\015\012\015\012Since r2204 sublets can use grabs in a similar way as in the main config. \015\012\015\012{{hide}}\015\012configure :grabby do |s|\015\012 s.interval = 5\015\012end\015\012\015\012grab "A-b" do |s, c|\015\012 puts "sublet name: %s" % [ s.name ]\015\012 puts "pressed on : %s" % [ c.name ]\015\012end\015\012
\015\012\015\012_Please note that there is no checking if the newly created grab already exists, last one wins._\015\012\015\012h2. Configuration\015\012\015\012Sublets can either be configured by editing the sublet file or by a special DSL command in the main config (since r2148) of subtle. The latter can be done via Subtle::Subtle#config, this returns a hash and can be used as in the following example:\015\012\015\012h3. Inside of the config\015\012\015\012{{hide}}sublet :configured do\015\012 interval 50\015\012 some_string "#00ff00"\015\012end
\015\012\015\012h3. Inside of the sublet\015\012\015\012{{hide}}configure :configured do |s|\015\012 s.interval = s.config[:interval] || 30\015\012 s.some_string = s.config[:some_string] || "default"\015\012\015\012 # Works with colors too\015\012 s.red = Subtlext::Color.new(s.config[:red] || "#ff0000")\015\012end\015\012\015\012on :run do\015\012 s.data = s.red + s.some_string\015\012end
\015\012\015\012h2. Customization\015\012\015\012h3. Colors\015\012\015\012The color of the ouput of a Sublets can be changed in this way:\015\012\015\012{{hide}}configure :colorful do |s|\015\012 s.red = Subtlext::Color.new("#ff0000")\015\012 s.green = Subtlext::Color.new("#00ff00")\015\012 s.blue = Subtlext::Color.new("#0000ff")\015\012 s.background = "#303030"\015\012end\015\012\015\012on :run do\015\012 s.data = s.red + "su" + s.green + "bt" + s.blue + "le"\015\012end
\015\012\015\012h3. Icons\015\012\015\012There is also a way to add a X bitmap to a sublet:\015\012\015\012{{hide}}configure :iconized do |s|\015\012 s.icon = Subtlext::Icon.new("/usr/share/icons/subtle.xbm")\015\012end\015\012\015\012on :run do |s|\015\012 s.data = @icon + "subtle"\015\012end
\015\012\015\012A nice collection of this pixmap can be found Subtle" class="external">here</a> will add a padding of 3px left and right of the pixmap, so keep that in mind when using the click hooks._\015\012\015\012h2. Examples\015\012\015\012Below is the code of a shipped sublets that displays the time. It should be really straight forward:\015\012\015\012{{hide}}configure :clock do |s|\015\012 s.interval = 60 #< Set interval time\015\012end\015\012\015\012on :run do |s|\015\012 s.data = Time.now.strftime("%d%m%y%H%M") #< Set data\015\012end
\015\012\015\012Another example for the inotify sublet which is also included within subtle:\015\012\015\012{{hide}}configure :notify do |s|\015\012 s.file = "/tmp/watch"\015\012 s.watch(s.file)\015\012end\015\012\015\012on :run do\015\012 begin\015\012 self.data = IO.readlines(@file).first.chop #< Read data and strip\015\012 rescue => err #< Catch error\015\012 puts err\015\012 self.data = "subtle"\015\012 end\015\012end
\015\012\015\012The watch command also works with Ruby sockets, but be aware of blocking I/O:\015\012\015\012{{hide}}configure :socket do |s|\015\012 s.socket = TCPSocket.open("localhost", 6600)\015\012 s.watch(s.socket)\015\012end\015\012\015\012on :watch do |s|\015\012 begin\015\012 s.data = s.socket.readline.chop #< Read data and strip\015\012 rescue => err #< Catch error\015\012 puts err\015\012 s.data = "subtle"\015\012 end\015\012end\015\012\015\012on :run do |s|\015\012 # Do nothing\015\012end
\015\012\015\012_Subtle will automatically set sockets to O_NONBLOCK._\015\012\015\012And finally an example with a click callback:\015\012\015\012{{hide}}configure :click do |s|\015\012 s.interval = 999 #< Do nothing\015\012end\015\012\015\012on :mouse_down do |s, x, y, button|\015\012 Subtlext::Client["xterm"].raise\015\012 puts x, y, button\015\012end\015\012\015\012on :run do |s|\015\012 # Do nothing here\015\012end
¶
# Hello sublet file\015\012# Created with sur-0.2\015\012configure :hello do |s|\015\012 s.interval = 60\015\012end\015\012\015\012on :run do |s|\015\012 s.data = "Hello, world!"\015\012end
on :client_create do |s, c|\015\012 puts s.name #< Name of the sublet\015\012 puts c.name #< Name of the client\015\012end
\015\012configure :grabby do |s|\015\012 s.interval = 5\015\012end\015\012\015\012grab "A-b" do |s, c|\015\012 puts "sublet name: %s" % [ s.name ]\015\012 puts "pressed on : %s" % [ c.name ]\015\012end\015\012
sublet :configured do\015\012 interval 50\015\012 some_string "#00ff00"\015\012end
configure :configured do |s|\015\012 s.interval = s.config[:interval] || 30\015\012 s.some_string = s.config[:some_string] || "default"\015\012\015\012 # Works with colors too\015\012 s.red = Subtlext::Color.new(s.config[:red] || "#ff0000")\015\012end\015\012\015\012on :run do\015\012 s.data = s.red + s.some_string\015\012end
configure :colorful do |s|\015\012 s.red = Subtlext::Color.new("#ff0000")\015\012 s.green = Subtlext::Color.new("#00ff00")\015\012 s.blue = Subtlext::Color.new("#0000ff")\015\012 s.background = "#303030"\015\012end\015\012\015\012on :run do\015\012 s.data = s.red + "su" + s.green + "bt" + s.blue + "le"\015\012end
configure :iconized do |s|\015\012 s.icon = Subtlext::Icon.new("/usr/share/icons/subtle.xbm")\015\012end\015\012\015\012on :run do |s|\015\012 s.data = @icon + "subtle"\015\012end
configure :clock do |s|\015\012 s.interval = 60 #< Set interval time\015\012end\015\012\015\012on :run do |s|\015\012 s.data = Time.now.strftime("%d%m%y%H%M") #< Set data\015\012end
configure :notify do |s|\015\012 s.file = "/tmp/watch"\015\012 s.watch(s.file)\015\012end\015\012\015\012on :run do\015\012 begin\015\012 self.data = IO.readlines(@file).first.chop #< Read data and strip\015\012 rescue => err #< Catch error\015\012 puts err\015\012 self.data = "subtle"\015\012 end\015\012end
configure :socket do |s|\015\012 s.socket = TCPSocket.open("localhost", 6600)\015\012 s.watch(s.socket)\015\012end\015\012\015\012on :watch do |s|\015\012 begin\015\012 s.data = s.socket.readline.chop #< Read data and strip\015\012 rescue => err #< Catch error\015\012 puts err\015\012 s.data = "subtle"\015\012 end\015\012end\015\012\015\012on :run do |s|\015\012 # Do nothing\015\012end
configure :click do |s|\015\012 s.interval = 999 #< Do nothing\015\012end\015\012\015\012on :mouse_down do |s, x, y, button|\015\012 Subtlext::Client["xterm"].raise\015\012 puts x, y, button\015\012end\015\012\015\012on :run do |s|\015\012 # Do nothing here\015\012end