Writing sublets » History » Version 3
« Previous -
Version 3/13
(diff) -
Next » -
Current version
Anonymous, 01/08/2011 01:53 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. Configure\015\012\015\012A sublet starts with the configure block, which tells subtle the name and does basic initialization like the interval time if it's used. Assignment of instance variables must be done like s.value = "something"
or otherwise the DSL can't keep track of it.\015\012\015\012{{hide}}configure :sublet do |s|\015\012 s.interval = 60\015\012 s.variable = "something"\015\012end
\015\012\015\012h3. 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. Helper\015\012\015\012Custom methods need to be written inside of a helper block to be used a instance method. Inside of this helpers, instance variables must be accessed via the self keyword:\015\012\015\012{{hide}}helper do\015\012 def something(test)\015\012 self.variable = test\015\012 self.data = test\015\012 end\015\012end
\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
configure :sublet do |s|\015\012 s.interval = 60\015\012 s.variable = "something"\015\012end
helper do\015\012 def something(test)\015\012 self.variable = test\015\012 self.data = test\015\012 end\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