demonastery.org http://demonastery.org/ Blog of Zane Ashby en-us Fri, 11 May 2012 15:53:53 +1200 Fri, 11 May 2012 15:53:53 +1200 The Perfect Android Emulator http://demonastery.org/77/the-perfect-android-emulator/ Thu, 08 Mar 2012 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/77/the-perfect-android-emulator <p>I&#8217;ve recently been getting further into Android development and as most people that have touched the official SDK know, the Android emulator is giant pain in the ass to work with. The reason it is slow is a combination of many things (ARM - x86 conversion, slow screen updates), but fortunately thanks to the Androidx86 project, you don&#8217;t have to live with it any more.</p> <p><a href='http://i.imgur.com/1SnAM.png'><img alt='Android' src='http://i.imgur.com/1SnAMm.png' /></a></p> <p>The Androidx86 project aims to port AOSP to the x86 architecture and supply drivers for many common devices; it does this very well and is getting better with every release. I&#8217;m going to show you how to set up the perfect Android VM for development (this assumes you have the rest of the SDK working fine, including access to <code>adb</code> from the command-line).</p> <p>To start off we&#8217;re going to head over to <a href='http://code.google.com/p/android-x86/downloads/list'>http://code.google.com/p/android-x86/downloads/list</a> and download the iso labelled as <em>&#8220;android-x86-4.0-RC1-eeepc.iso&#8221;</em> (181MB). While this is downloading you will want to make sure you have a copy of <a href='http://virtualbox.org'>VirtualBox</a> for your platform of choice.</p> <p>Once this is finished downloading and VirtualBox is installed, fire up the VirtualBox Manager application and select the <em>&#8220;New&#8221;</em> button from the toolbar. This launches a wizard to guide you through creating a new VM, pretty simple really.</p> <p>Give the VM a name of your choice (I simply chose <em>&#8220;Android&#8221;</em>), select <em>&#8220;Linux&#8221;</em> as the Operating System, and <em>&#8220;Linux 2.6&#8221;</em> as the version. Next we&#8217;ll want to give the VM some memory. Choose whatever is suitable to your setup, but anything greater than 256MB should suffice. Then we&#8217;re on to setting up virtual hard disks, we can safely uncheck the <em>&#8220;Start-up Disk&#8221;</em> option (as we&#8217;re using a livecd) and continue to the next screen. Finally (after dismissing the warnings) you should have a brand new empty VM ready to use.</p> <p>We aren&#8217;t quite ready yet though, lets tweak a couple of options before continuing. Right click on your newly created VM and select <em>&#8220;Settings&#8221;</em>. From here navigate to the <em>&#8220;Storage&#8221;</em> category, and click on the <em>&#8220;Empty&#8221;</em> under <em>&#8220;IDE Controller&#8221;</em>. On the attributes pane to the right, check the <em>&#8220;Live CD/DVD&#8221;</em> box, then click on the CD icon and select <em>&#8220;Choose a virtual CD/DVD disk file&#8230;&#8221;</em>. Select the eeepc ISO downloaded earlier.</p> <p><a href='http://i.imgur.com/yO22w.png'><img alt='Android Storage Settings' src='http://i.imgur.com/yO22wm.png' /></a></p> <p>Next jump down to the <em>&#8220;Network category&#8221;</em>, click the <em>&#8220;Advanced&#8221;</em> dropdown, and change the Adapter Type to <em>&#8220;PCnet-FAST III&#8221;</em>. Now click on the <em>&#8220;Port Forwarding&#8221;</em> button and add a new entry, setting the Host and Guest port options to 5556. Finally you can close the settings dialog and return to the main screen.</p> <p><a href='http://i.imgur.com/mYaRa.png'><img alt='Android Network Settings' src='http://i.imgur.com/mYaRam.png' /></a></p> <p><a href='http://i.imgur.com/7fQ4b.png'><img alt='Android Port Forwarding Rules' src='http://i.imgur.com/7fQ4bm.png' /></a></p> <p>Now we&#8217;re going to set up a phone resolution (as by default Android-x86 boots in a conventional tablet resolution). To do this, right click on your VM and select <em>&#8220;Show in File Manager&#8221;</em> (or <em>&#8220;Show in Explorer&#8221;</em>). Close the VirtualBox Manager and open the .vbox file in your favourite editor and add the following lines under the <code>&lt;Machine&gt;</code> XML tag:</p> <div class='highlight'><pre><code class='xml'><span class='nt'>&lt;ExtraData&gt;</span> <span class='nt'>&lt;ExtraDataItem</span> <span class='na'>name=</span><span class='s'>&quot;CustomVideoMode1&quot;</span> <span class='na'>value=</span><span class='s'>&quot;320x480x16&quot;</span> <span class='nt'>/&gt;</span> <span class='nt'>&lt;/ExtraData&gt;</span> </code></pre> </div> <p>Save and close this file, and now we&#8217;re ready to launch our VM. Open up VirtualBox Manager again and hit start. Once presented with the boot menu, hit the TAB key. Now add <code>UVESA_MODE=320x480 vga=864</code> and hit enter to boot. Your VM should resize and boot up to a welcome screen. Press Right-ctrl + I to disable <em>&#8220;Host Mouse Integration&#8221;</em>. Now click inside the VM and work your way through the welcome screen. You can skip pretty much everything that it asks, so feel free to do that.</p> <p>Once at the home screen, open up the apps menu and scroll across to the right until you find <em>&#8220;Terminal Emulator&#8221;</em>. Open it up and then type the following commands:</p> <div class='highlight'><pre><code class='bash'>su <span class='o'>(</span>this will popup a dialog, hit Allow<span class='o'>)</span> netcfg eth0 dhcp setprop ro.kernel.android.ndns 1 setprop net.dns1 8.8.8.8 adb tcpip 5556 <span class='o'>(</span>or whatever port you used earlier<span class='o'>)</span> <span class='nb'>exit</span> <span class='nb'>exit</span> </code></pre> </div> <p>Your VM is now set up for network and ADB access. At this point I suggest taking a snapshot of the device by going to the <em>&#8220;Machine&#8221;</em> menu and selecting <em>&#8220;Take Snapshot&#8221;</em>. Also remember when powering off the VM to select <em>&#8220;Restore current snapshot &#8216;Snapshot Name&#8217;&#8221;</em>, so that your VM is always fresh.</p> <p>If you now open up a command-line on the host, you can type in <code>adb connect 127.0.0.1:5556</code> and you should successfully connect to your VM. You will have to do this each time you start your VM, but I don&#8217;t think it&#8217;s a big deal. Running your app within Eclipse will now work as expected and launch inside your VM, at much better speeds than before ;)</p> <p>Finally, to make this setup perfect, right click on your VM inside the Manager and select <em>&#8220;Create Shortcut on Desktop&#8221;</em>. Now you should be able to start a fresh Android VM in well under 10 seconds (takes about 3 on my PC) and be ready for development!</p> LogPixels DPI hack http://demonastery.org/76/logpixels-dpi-hack/ Wed, 04 Jan 2012 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/76/logpixels-dpi-hack <p>Here&#8217;s a handy tip for those netbook users out there in dire need of more screen estate. You can force a DPI value of lower than 96 by using the Windows registry. To do so open <code>regedit</code>, navigate to <code>HKEY_CURRENT_CONFIG/Software/Fonts/LogPixels</code> and change the decimal value from <code>96</code> to something lower such as <code>80</code>. Then log out and back in and you will see the changes. I&#8217;m using a value of 80 on my netbook and it is about the most that I will drop it while still keeping things (half) readable. You will notice that it really hinders the readability of fonts as well as having some strange bitmap scaling artifacts, but if you&#8217;re like me and can adjust to it then the extra screen space gained is well worth it :)</p> <p>You can view a side by side comparison of the my desktop with LogPixels at 80 and at 96 by viewing this <a href='http://imgur.com/a/9qYTk#0'>imgur album</a>.</p> <p><a href='http://i.imgur.com/DKnsW.jpg'><img alt='http://i.imgur.com/DKnsWm.jpg' src='http://i.imgur.com/DKnsWm.jpg' /></a> <a href='http://i.imgur.com/JHrJi.jpg'><img alt='http://i.imgur.com/JHrJim.jpg' src='http://i.imgur.com/JHrJim.jpg' /></a></p> Docstrings in my Chicken? http://demonastery.org/75/docstrings-in-my-chicken/ Sun, 13 Nov 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/75/docstrings-in-my-chicken <p>Here&#8217;s a little bit of amateur code to enable the use of <a href='http://en.wikipedia.org/wiki/Docstring'>docstrings</a> in Chicken Scheme. I haven&#8217;t written any Scheme in a few months and don&#8217;t have any formal training in the ninja art of <a href='http://en.wikipedia.org/wiki/Hygienic_macro#explicit_renaming'>explicit renaming macros</a> so I&#8217;d appreciate any feedback from Scheme veterans:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;;; Docstrings for Chicken!</span> <span class='c1'>;; The hash-table that will contain the procedures and their associated</span> <span class='c1'>;; documentation strings as well as their code for later use.</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>*documentation-hash-table*</span> <span class='p'>(</span><span class='nf'>make-hash-table</span><span class='p'>))</span> <span class='c1'>;; Documented define er-macro</span> <span class='p'>(</span><span class='k'>define-syntax </span><span class='p'>(</span><span class='nf'>define*</span> <span class='nv'>form</span> <span class='nv'>r</span> <span class='nv'>c</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>let* </span><span class='p'>((</span><span class='nf'>args-form</span> <span class='p'>(</span><span class='nf'>second</span> <span class='nv'>form</span><span class='p'>))</span> <span class='c1'>; (proc args)</span> <span class='p'>(</span><span class='nf'>proc-name</span> <span class='p'>(</span><span class='nf'>first</span> <span class='nv'>args-form</span><span class='p'>))</span> <span class='c1'>; proc</span> <span class='p'>(</span><span class='nf'>doc</span> <span class='p'>(</span><span class='nf'>third</span> <span class='nv'>form</span><span class='p'>))</span> <span class='c1'>; &quot;The docstring&quot;</span> <span class='p'>(</span><span class='nf'>body</span> <span class='p'>(</span><span class='nf'>drop</span> <span class='nv'>form</span> <span class='mi'>3</span><span class='p'>)))</span> <span class='c1'>; (everything else)</span> <span class='p'>(</span><span class='nf'>hash-table-set!</span> <span class='nv'>*documentation-hash-table*</span> <span class='nv'>proc-name</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>doc</span> <span class='nv'>body</span><span class='p'>))</span> <span class='c1'>; insert the doc and code body</span> <span class='o'>`</span><span class='p'>(</span><span class='o'>,</span><span class='p'>(</span><span class='nf'>r</span> <span class='ss'>&#39;define</span><span class='p'>)</span> <span class='o'>,</span><span class='nv'>args-form</span> <span class='o'>,@</span><span class='nv'>body</span><span class='p'>)))</span> <span class='c1'>; Define the procedure as normal</span> <span class='c1'>;; Example of a documented procedure, will print a nice-ish list of documented procedures</span> <span class='p'>(</span><span class='nf'>define*</span> <span class='p'>(</span><span class='nf'>print-docs</span><span class='p'>)</span> <span class='s'>&quot;Print a list of documented procedures&quot;</span> <span class='p'>(</span><span class='nf'>hash-table-walk</span> <span class='nv'>*documentation-hash-table*</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>key</span> <span class='nv'>val</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>printf</span> <span class='s'>&quot;~a =&gt; ~a~n ~a~n~n&quot;</span> <span class='nv'>key</span> <span class='p'>(</span><span class='nf'>first</span> <span class='nv'>val</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>second</span> <span class='nv'>val</span><span class='p'>)))))</span> </code></pre> </div> <p>Another example of why Scheme is such a fun language to work with :)</p> Twitter's Bootstrap http://demonastery.org/74/twitter-s-bootstrap/ Fri, 04 Nov 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/74/twitter-s-bootstrap <p>To me, one of the most annoying parts of prototyping a new web application is getting a presentable look and feel up quickly. When I&#8217;m prototyping stuff I love to have a good looking interface from the start, even if that interface will be changed before going live.</p> <p>Recently, Twitter released a wonderful CSS/JS framework named <a href='http://twitter.github.com/bootstrap/'>Bootstrap</a> for this exact purpose. As stated it is a toolkit &#8220;[&#8230;] designed to kickstart development of webapps and sites.&#8221;. It combines an aesthetically pleasing base styling (based somewhat off of Twitter itself) of HTML elements with an easy to use CSS grid, great browser compatibility, and various optional Javascript modules to extend functionality of things such as Drop-down menus and modal dialogs.</p> <p>As for the elements it offers, some of my favourites are:</p> <ul> <li>All typical HTML elements are styled, including decent typography</li> <li>A top bar to be used for menus and such, with drop-down menus to be activated easily with JS</li> <li>Tabs/Pills</li> <li>Ability to pretty-print code when used in conjunction with google-code-prettify</li> <li>Labels and buttons, with styles for success, warning, notice, etc</li> <li>Alert boxes, with corresponding styles, great for showing form submission status etc</li> </ul> <p>Bootstrap is built on top of the <a href='http://lesscss.org/'>LESS CSS preprocessor</a> for ease of extending and integrating into your apps. Personally I found that the precompiled stylesheet was more than enough to begin with however, and I&#8217;m more of a fan of the <a href='http://sass-lang.com/'>SASS preprocessor</a> anyway. The JS modules are also very easy to integrate with very little code needed to hook them up to their appropriate classes.</p> <p>I jumped into Bootstrap shortly after its release, and have been using it ever since for my internal prototypes and eventual applications, including an application in the process of being deployed. Bootstrap played an integral part in getting that project complete under it&#8217;s tight deadline.</p> <p>Highly recommended to all!</p> Das Keyboard Ultimate http://demonastery.org/73/das-keyboard-ultimate/ Wed, 12 Oct 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/73/das-keyboard-ultimate <p>I took the plunge recently and bought my first mechanical keyboard, the <a href='http://daskeyboard.com'>Das Keyboard Ultimate</a>. It was very hard to find someone that would ship one to NZ, but eventually I found <a href='http://auspcmarket.com.au'>AusPCMarket</a> that ships the Das as well as several other &#8220;clicky keyboards&#8221;. The Das is known for being a bit pricey.. the Ultimate set me back <em>$230NZD</em> (incl shipping and GST) at the current exchange rate and was delivered in just over a week. If you need to justify the price by thinking of it as an investment, then do :)</p> <p>With it being my first mechanical keyboard I&#8217;m unable to give a fair review in comparison to others of its kind. My previous keyboard was a <a href='http://www.microsoft.com/hardware/en-us/p/comfort-curve-keyboard-2000'>Microsoft Comfort Curve 2000</a> keyboard (a much cheaper <em>$40NZD</em>), a brilliant keyboard but of course based around <a href='http://en.wikipedia.org/wiki/Keyboard_technology#Dome-switch_keyboard'>rubber dome</a> technology.</p> <p>Anyway, it took me a while to adjust to the non-curved layout of the Das, but now that I have I feel that I am touch-typing much MUCH more efficiently than before. It feels great to type on, plus it sounds amazing! Personally I revel in the sound of the Das, and while I wouldn&#8217;t want to use one around sleeping people, it certainly won&#8217;t break through any music playing on your headphones and so far doesn&#8217;t seem to penetrate walls ;)</p> <p>Overall a definite thumbs-up from me. If you&#8217;re in NZ and looking to get a Das, I&#8217;d highly recommend also going through <a href='http://auspcmarket.com.au'>AusPCMarket</a> as their service was quick and no-bullshit.</p> <p><em>Since posting this <a href='http://www.mightyape.co.nz/search/?s=das+keyboard'>MightyApe.co.nz</a> has become an official Das Keyboard stockist, so NZers can save a few bucks by grabbing it from there. I also managed to pour coffee through my Das very shortly after getting it, but after flushing it out with water it is still clicking away like nothing ever happened, WIN!.</em></p> Tiny Memcached Wrapper http://demonastery.org/72/tiny-memcached-wrapper/ Fri, 12 Aug 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/72/tiny-memcached-wrapper <p>No posts in a while huh! Been pretty busy and haven&#8217;t thought of much to blog about lately. But I&#8217;ve been playing with <a href='http://memcached.org/'>Memcache</a> and wanted to share a tiny class I made to add easy caching to my PHP projects. This PHP class just provides a nice simple interface to use by extending the <code>Memcached</code> class:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='c1'>// Call the class whatever you want</span> <span class='k'>class</span> <span class='nc'>MyCache</span> <span class='k'>extends</span> <span class='nx'>\Memcached</span> <span class='p'>{</span> <span class='k'>function</span> <span class='nf'>cache</span><span class='p'>(</span><span class='nv'>$key</span><span class='p'>,</span> <span class='nv'>$time</span><span class='p'>,</span> <span class='nv'>$func</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>if</span> <span class='p'>((</span><span class='nv'>$val</span> <span class='o'>=</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>get</span><span class='p'>(</span><span class='nv'>$key</span><span class='p'>))</span> <span class='o'>===</span> <span class='k'>false</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$val</span> <span class='o'>=</span> <span class='nv'>$func</span><span class='p'>();</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>set</span><span class='p'>(</span><span class='nv'>$key</span><span class='p'>,</span> <span class='nv'>$val</span><span class='p'>,</span> <span class='nb'>strtotime</span><span class='p'>(</span><span class='nv'>$time</span><span class='p'>)</span> <span class='o'>-</span> <span class='nb'>time</span><span class='p'>());</span> <span class='p'>}</span> <span class='k'>return</span> <span class='nv'>$val</span><span class='p'>;</span> <span class='p'>}</span> <span class='p'>}</span> </code></pre> </div> <p>And now to use it, first you summon it in the same way as the regular class:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='nv'>$c</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>MyCache</span><span class='p'>;</span> <span class='nv'>$c</span><span class='o'>-&gt;</span><span class='na'>addServer</span><span class='p'>(</span><span class='s1'>&#39;127.0.0.1&#39;</span><span class='p'>,</span> <span class='mi'>11211</span><span class='p'>);</span> </code></pre> </div> <p>Then where you would like to begin caching (I&#8217;m using this very blog as an example, where GeSHi for syntax highlighting is the main bottle-neck for page generation), you call the class like so:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='c1'>// Example using my BLACK blog engine (http://github.com/ZaneA/BLACK)</span> <span class='c1'>// Here is the original line</span> <span class='nv'>$row</span><span class='p'>[</span><span class='s1'>&#39;body&#39;</span><span class='p'>]</span> <span class='o'>=</span> <span class='nx'>render</span><span class='p'>(</span><span class='nv'>$row</span><span class='p'>[</span><span class='s1'>&#39;body&#39;</span><span class='p'>]);</span> <span class='c1'>// And here is a cached version</span> <span class='c1'>// As you can see we have a KEY, a TIMEOUT, and a FUNCTION to call for a cache miss</span> <span class='nv'>$row</span><span class='p'>[</span><span class='s1'>&#39;body&#39;</span><span class='p'>]</span> <span class='o'>=</span> <span class='nv'>$c</span><span class='o'>-&gt;</span><span class='na'>cache</span><span class='p'>(</span><span class='s2'>&quot;blog_post_</span><span class='si'>{</span><span class='nv'>$row</span><span class='p'>[</span><span class='s1'>&#39;id&#39;</span><span class='p'>]</span><span class='si'>}</span><span class='s2'>&quot;</span><span class='p'>,</span> <span class='s1'>&#39;30 minutes&#39;</span><span class='p'>,</span> <span class='k'>function</span> <span class='p'>()</span> <span class='k'>use</span> <span class='p'>(</span><span class='nv'>$row</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='nx'>render</span><span class='p'>(</span><span class='nv'>$row</span><span class='p'>[</span><span class='s1'>&#39;body&#39;</span><span class='p'>]);</span> <span class='c1'>// Renders all the post filters, including syntax highlighting</span> <span class='p'>});</span> </code></pre> </div> <p>Awesome, for this small tweak on my local test blog (with 4 posts), this takes the page response time down from 14ms to 2ms. Quite a win I&#8217;d say :)</p> <p>Of course this code requires the <em>memcached</em> PHP extension and a running Memcache server ;)</p> Emacs Tip: Vimpulse http://demonastery.org/71/emacs-tip-vimpulse/ Thu, 07 Jul 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/71/emacs-tip-vimpulse <p>One thing I love about Emacs is that it is so extensible. I was an avid Vim user for a long time and it took me several tries to switch to Emacs, but I will never look back. With the <a href='http://gitorious.org/vimpulse'>Vimpulse</a> addon to the built-in <code>viper-mode</code>, Emacs becomes a powerful Vim impersonator, capable of being extended with Emacs-Lisp.</p> <p>A lot of my time is spent doing web development, and so strong HTML editing ability is essential in any editor I use. Vim has this amazing concept of <a href='http://vimdoc.sourceforge.net/htmldoc/motion.html#text-objects'>text objects</a> which allows you to be very efficient when transforming text; one of the most useful when doing web development is therefore the XML/HTML tag text object. I would use this all the time by invoking <code>cit</code> to change text between a pair of tags. To demonstrate, here&#8217;s a piece of text you might have sitting in a file:</p> <div class='highlight'><pre><code class='xml'><span class='nt'>&lt;title&gt;</span>Hello |World<span class='nt'>&lt;/title&gt;</span> </code></pre> </div> <p>Now with the cursor somewhere in between the tags (visualized above by the pipe, &#8217;|&#8217;) we can go into command mode and type <code>cit</code> and the above will be replaced with:</p> <div class='highlight'><pre><code class='xml'><span class='nt'>&lt;title&gt;</span>|<span class='nt'>&lt;/title&gt;</span> </code></pre> </div> <p>Ready to be edited!</p> <p>Well sadly, Vimpulse doesn&#8217;t have this feature by default, probably one of the very few parts of Vim that it doesn&#8217;t emulate in fact! (NB. <a href='http://gitorious.org/evil/pages/Home'>Evil</a> contains emulation for this already) But not to worry, we can just add it in! This is Emacs after all.</p> <p>So how do we instruct Vimpulse to recognise another text object? Turns out it&#8217;s <em>REALLY</em> easy:</p> <div class='highlight'><pre><code class='cl'><span class='p'>(</span><span class='nv'>vimpulse-define-text-object</span> <span class='nv'>vimpulse-tag</span> <span class='p'>(</span><span class='nv'>arg</span><span class='p'>)</span> <span class='s'>&quot;Select a tag&quot;</span> <span class='ss'>:keys</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='s'>&quot;at&quot;</span> <span class='s'>&quot;it&quot;</span><span class='p'>)</span> <span class='c1'>; The keys that will trigger this text object</span> <span class='p'>(</span><span class='nv'>vimpulse-inner-object-range</span> <span class='c1'>; We&#39;re basically defining a range on which to act upon</span> <span class='nv'>arg</span> <span class='p'>(</span><span class='k'>lambda</span> <span class='p'>(</span><span class='nv'>arg</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>search-backward</span> <span class='s'>&quot;&gt;&quot;</span> <span class='no'>nil</span> <span class='no'>nil</span> <span class='nv'>arg</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>forward-char</span><span class='p'>))</span> <span class='c1'>; Look to the left for a &quot;&gt;&quot; character</span> <span class='p'>(</span><span class='k'>lambda</span> <span class='p'>(</span><span class='nv'>arg</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>search-forward</span> <span class='s'>&quot;&lt;&quot;</span> <span class='no'>nil</span> <span class='no'>nil</span> <span class='nv'>arg</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>backward-char</span><span class='p'>))</span> <span class='c1'>; Look to the right for a &quot;&lt;&quot; character</span> <span class='p'>))</span> <span class='c1'>; and return the distance between them!</span> </code></pre> </div> <p>Note that this isn&#8217;t a perfect implementation, but for the purposes of this demonstration it will suffice! We can now <code>cit</code> and <code>dit</code> to our hearts content! Hail Emacs!</p> <p>For a more robust implementation it may be worth looking at using <code>sgml-skip-tag-backward</code> and <code>sgml-skip-tag-forward</code> for movement instead.</p> <p>Happy Hacking!</p> Org-mode Conky Colorizer http://demonastery.org/70/org-mode-conky-colorizer/ Sun, 05 Jun 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/70/org-mode-conky-colorizer <p>Just whipped up a little script to colorize my <a href='http://orgmode.org'>org-mode</a> todo lists for display via <a href='http://conky.sourceforge.net'>Conky</a>. It&#8217;s bound to be of use to someone so I thought I&#8217;d better share :)</p> <p>Here&#8217;s a <a href='http://i.imgur.com/mqYUG.png'>screenshot of it in action</a>, sitting in the corner of my desktop.</p> <p><a href='http://i.imgur.com/mqYUG.png'><img alt='http://i.imgur.com/mqYUGm.jpg' src='http://i.imgur.com/mqYUGm.jpg' /></a></p> <p>Source is below, to use, place <code>${execp /path/to/org-conky-parser.scm 30}</code> in to your conkyrc. Requires <a href='http://call-cc.org'>Chicken Scheme</a>, and remember to <code>chmod +x</code> the script first.</p> <div class='highlight'><pre><code class='scheme'><span class='o'>#</span><span class='nv'>!/usr/bin/csi</span> <span class='nv'>-script</span> <span class='c1'>;; org-conky-parser.scm</span> <span class='c1'>;; Run an org-mode file through some regexes and output colors</span> <span class='c1'>;; Suitable for Conky.</span> <span class='c1'>; File to read, could be easily grabbed from argv</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>*file*</span> <span class='s'>&quot;~/org/day.org&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>*font*</span> <span class='s'>&quot;Liberation Sans&quot;</span><span class='p'>)</span> <span class='c1'>;; Code below</span> <span class='p'>(</span><span class='nf'>use</span> <span class='nv'>regex-literals</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>set-read-syntax!</span> <span class='sc'>#\/</span> <span class='nv'>read-regex-literal</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>++</span> <span class='nv'>string-append</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>color</span> <span class='nv'>c</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>++</span> <span class='s'>&quot;${color &quot;</span> <span class='nv'>c</span> <span class='s'>&quot;}\\1${color}&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>font</span> <span class='nv'>f</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>++</span> <span class='s'>&quot;${font &quot;</span> <span class='nv'>f</span> <span class='s'>&quot;}\\1${font}&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>*replace-list*</span> <span class='p'>(</span><span class='nf'>list</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/^</span><span class='p'>(</span><span class='err'>\</span><span class='nv'>*+</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>color</span> <span class='s'>&quot;#555555&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/</span><span class='p'>(</span><span class='nf'>TODO</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>color</span> <span class='s'>&quot;#ffaa88&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/</span><span class='p'>(</span><span class='nf'>DONE</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>color</span> <span class='s'>&quot;#aaff88&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/</span><span class='p'>(</span><span class='nf'>TODO|DONE</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>font</span> <span class='p'>(</span><span class='nf'>++</span> <span class='nv'>*font*</span> <span class='s'>&quot;:style=bold:pixelsize=12&quot;</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/</span><span class='p'>(</span><span class='nf'>&lt;</span><span class='o'>.</span><span class='nv'>*&gt;</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>color</span> <span class='s'>&quot;#aaaaff&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/</span><span class='p'>(</span><span class='nf'>&lt;</span><span class='o'>.</span><span class='nv'>*&gt;</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>font</span> <span class='p'>(</span><span class='nf'>++</span> <span class='nv'>*font*</span> <span class='s'>&quot;:style=bold:pixelsize=14&quot;</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>/</span><span class='p'>(</span><span class='o'>.</span><span class='nv'>*list</span><span class='o'>.</span><span class='nv'>*</span><span class='p'>)</span><span class='nv'>/</span> <span class='p'>(</span><span class='nf'>font</span> <span class='p'>(</span><span class='nf'>++</span> <span class='nv'>*font*</span> <span class='s'>&quot;:style=bold:pixelsize=16&quot;</span><span class='p'>)))))</span> <span class='c1'>; Grab file contents into a list</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>*contents*</span> <span class='p'>(</span><span class='nb'>with-input-from-file </span><span class='nv'>*file*</span> <span class='nv'>read-lines</span><span class='p'>))</span> <span class='c1'>; Colorize a line using above regexes</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>colorize-line</span> <span class='nv'>line</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>for-each </span><span class='c1'>; Foreach regex/replacement</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>pair</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>set! </span><span class='nv'>line</span> <span class='p'>(</span><span class='nf'>string-substitute</span> <span class='p'>(</span><span class='nb'>car </span><span class='nv'>pair</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>cadr </span><span class='nv'>pair</span><span class='p'>)</span> <span class='nv'>line</span><span class='p'>)))</span> <span class='nv'>*replace-list*</span><span class='p'>)</span> <span class='nv'>line</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>print-colorized-line</span> <span class='p'>(</span><span class='nf'>compose</span> <span class='nv'>print</span> <span class='nv'>colorize-line</span><span class='p'>))</span> <span class='c1'>; Print colorized lines</span> <span class='p'>(</span><span class='nb'>for-each </span><span class='nv'>print-colorized-line</span> <span class='nv'>*contents*</span><span class='p'>)</span> </code></pre> </div> Adding FreeType to our Demo http://demonastery.org/69/adding-freetype-to-our-demo/ Sun, 05 Jun 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/69/adding-freetype-to-our-demo <p>Continuing on from my <a href='http://demonastery.org/60/chicken-scheme-and-opengl/'>Chicken Scheme, and OpenGL</a> tutorial, I&#8217;m going to show you how to extend it to render pretty FreeType text using the <a href='http://homepages.paradise.net.nz/henryj/code/'>FTGL</a> library. Follow the code below for details as always; it&#8217;s really easy! :)</p> <p>Users of ArchLinux can get <em>FTGL</em> with a simple <code>sudo pacman -S ftgl</code>. Debian should be something like <code>sudo apt-get install libftgl-dev</code>.</p> <p>Alright lets start by loading up the code from last time &#8230;</p> <p>&#8230; and scrolling down to the &#8220;(inline ..&#8221; call:</p> <div class='highlight'><pre><code class='c'><span class='p'>(</span><span class='kr'>inline</span> <span class='err'>#</span><span class='o'>&lt;&lt;</span><span class='n'>EOF</span> <span class='cp'>#ifndef CHICKEN</span> <span class='p'>...</span> <span class='cp'>#endif</span> <span class='c1'>// Here we&#39;re going to add the new stuff for FTGL!</span> <span class='c1'>// Define a constant we&#39;re going to use later</span> <span class='k'>const</span> <span class='kt'>int</span> <span class='n'>FTGL_RENDER_ALL</span> <span class='o'>=</span> <span class='mh'>0xffff</span><span class='p'>;</span> <span class='c1'>// And typedef FTGLfont as void so we can use it and pass it around</span> <span class='k'>typedef</span> <span class='kt'>void</span> <span class='n'>FTGLfont</span><span class='p'>;</span> <span class='c1'>// Notice however that I didn&#39;t include the ftgl header, because I</span> <span class='c1'>// want to define just the functions we&#39;re going to use to make</span> <span class='c1'>// things even easier</span> <span class='n'>FTGLfont</span><span class='o'>*</span> <span class='n'>ftglCreatePixmapFont</span><span class='p'>(</span><span class='k'>const</span> <span class='kt'>char</span><span class='o'>*</span><span class='p'>);</span> <span class='kt'>void</span> <span class='n'>ftglSetFontFaceSize</span><span class='p'>(</span><span class='n'>FTGLfont</span><span class='o'>*</span><span class='p'>,</span> <span class='kt'>int</span><span class='p'>,</span> <span class='kt'>int</span><span class='p'>);</span> <span class='kt'>void</span> <span class='n'>ftglRenderFont</span><span class='p'>(</span><span class='n'>FTGLfont</span><span class='o'>*</span><span class='p'>,</span> <span class='k'>const</span> <span class='kt'>char</span><span class='o'>*</span><span class='p'>,</span> <span class='kt'>int</span><span class='p'>);</span> <span class='kt'>void</span> <span class='n'>ftglDestroyFont</span><span class='p'>(</span><span class='n'>FTGLfont</span><span class='o'>*</span><span class='p'>);</span> <span class='c1'>// The above are the only ones we will be using for now, but these</span> <span class='c1'>// ones below may also be useful, along with the SimpleLayout class</span> <span class='c1'>// Also possible to use ftglCreateTextureFont and</span> <span class='c1'>// render as a plain texture too! Using the same render call</span> <span class='c1'>//FTGLfont* ftglCreatePixmapFont(const char*);</span> <span class='c1'>//float ftglGetFontLineHeight(FTGLfont*);</span> <span class='c1'>//void ftglGetFontBBox(FTGLfont*, const char*, int, float*);</span> <span class='c1'>// Done!</span> </code></pre> </div> <p>&#8230; Now skip down to the EOF part:</p> <div class='highlight'><pre><code class='scheme'><span class='nv'>EOF</span> <span class='s'>&quot;-lSOIL -lftgl&quot;</span> <span class='c1'>; Notice here we have added -lftgl to be linked</span> <span class='p'>)</span> </code></pre> </div> <p>&#8230; Now skip down to our old draw-text function, where we&#8217;re going to replace the GLUT code with our new FTGL render code:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>draw-text</span> <span class='nv'>text</span> <span class='nv'>x</span> <span class='nv'>y</span> <span class='o'>#</span><span class='nv'>!key</span> <span class='p'>(</span><span class='nf'>color</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='mi'>1</span> <span class='mi'>1</span> <span class='mi'>1</span> <span class='mi'>1</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>apply </span><span class='nv'>gl:Color4f</span> <span class='nv'>color</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:PushAttrib</span> <span class='nv'>gl:ENABLE_BIT</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Disable</span> <span class='nv'>gl:TEXTURE_2D</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:RasterPos2f</span> <span class='nv'>x</span> <span class='nv'>y</span><span class='p'>)</span> <span class='c1'>; This line has been replaced with a new one for FTGL</span> <span class='c1'>; FTGL even takes care of rendering for us!</span> <span class='p'>(</span><span class='nf'>ftglRenderFont</span> <span class='nv'>font</span> <span class='nv'>text</span> <span class='nv'>FTGL_RENDER_ALL</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:PopAttrib</span><span class='p'>))</span> </code></pre> </div> <p>&#8230; and down a bit further to where we loaded the texture last time:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='k'>define </span><span class='nv'>texture</span> <span class='p'>(</span><span class='nf'>LoadGLTexture</span> <span class='s'>&quot;circle_gradient.tga&quot;</span><span class='p'>))</span> <span class='c1'>; And add a new line for loading the font up</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>font</span> <span class='p'>(</span><span class='nf'>ftglCreatePixmapFont</span> <span class='s'>&quot;pathtoyourfont.ttf&quot;</span><span class='p'>))</span> <span class='c1'>; with minimal error checking</span> <span class='p'>(</span><span class='nf'>unless</span> <span class='nv'>font</span> <span class='p'>(</span><span class='nf'>error</span> <span class='s'>&quot;Couldn&#39;t load font!&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>exit</span> <span class='mi'>1</span><span class='p'>))</span> <span class='c1'>; now set the font size</span> <span class='p'>(</span><span class='nf'>ftglSetFontFaceSize</span> <span class='nv'>font</span> <span class='mi'>36</span> <span class='mi'>36</span><span class='p'>)</span> </code></pre> </div> <p>&#8230; Nearly done! down to the last line now:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='nf'>glut:MainLoop</span><span class='p'>)</span> <span class='c1'>; Add a call to destroy the font after we&#39;re done</span> <span class='p'>(</span><span class='nf'>ftglDestroyFont</span> <span class='nv'>font</span><span class='p'>)</span> </code></pre> </div> <p>And that&#8217;s it! Ah the joys of libraries and high level languages! If all went well you should have sweet anti-aliased variable-pitch text in place of the standard GLUT stuff before :D</p> Org-agenda-sms.el http://demonastery.org/67/org-agenda-sms-el/ Thu, 12 May 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/67/org-agenda-sms-el <p>So my warmup for today was to rewrite my old <a href='http://demonastery.org/25/automatic-agenda-notification/'>org-mode agenda notification code</a> to use Emacs lisp instead of Python. The aim of this code is to check your <a href='http://orgmode.org'>org-mode</a> agenda for any headings with DEADLINEs and create a vcalendar for each, and then send them to your phone via <a href='http://clickatell.com'>Clickatell</a>.</p> <p>To use it, save the code into your Emacs lib path, and then in your <em>.emacs</em> you&#8217;ll want something like:</p> <div class='highlight'><pre><code class='cl'><span class='p'>(</span><span class='nb'>require</span> <span class='ss'>&#39;org-agenda-sms</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>setq</span> <span class='nv'>org-agenda-sms-username</span> <span class='s'>&quot;&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>setq</span> <span class='nv'>org-agenda-sms-password</span> <span class='s'>&quot;hunter2&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>setq</span> <span class='nv'>org-agenda-sms-api-key</span> <span class='s'>&quot;&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>setq</span> <span class='nv'>org-agenda-sms-phone</span> <span class='s'>&quot;&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>run-at-time</span> <span class='s'>&quot;7am&quot;</span> <span class='no'>nil</span> <span class='ss'>&#39;org-agenda-sms</span><span class='p'>)</span> </code></pre> </div> <p>The contents of <em>org-agenda-sms.el</em> is below:</p> <div class='highlight'><pre><code class='cl'><span class='c1'>;;</span> <span class='c1'>;; Org-agenda-sms.el</span> <span class='c1'>;; Allows Emacs to SMS you a vcalendar of appointments each day</span> <span class='c1'>;; Written by Zane Ashby (http://www.demonastery.org)</span> <span class='c1'>;;</span> <span class='c1'>;; Usage: (run-at-time &quot;07am&quot; nil &#39;org-agenda-sms)</span> <span class='c1'>;;</span> <span class='p'>(</span><span class='nb'>defvar</span> <span class='nv'>org-agenda-sms-username</span> <span class='no'>nil</span> <span class='s'>&quot;Clickatell username for SMS&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>defvar</span> <span class='nv'>org-agenda-sms-password</span> <span class='no'>nil</span> <span class='s'>&quot;Clickatell password for SMS&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>defvar</span> <span class='nv'>org-agenda-sms-api-key</span> <span class='no'>nil</span> <span class='s'>&quot;Clickatell API key for SMS&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>defvar</span> <span class='nv'>org-agenda-sms-phone</span> <span class='no'>nil</span> <span class='s'>&quot;Phone number for SMS&quot;</span><span class='p'>)</span> <span class='c1'>;;;###autoload</span> <span class='p'>(</span><span class='nb'>defun</span> <span class='nv'>org-agenda-sms-build-vcal</span> <span class='p'>(</span><span class='nv'>header</span> <span class='nv'>timestamp</span><span class='p'>)</span> <span class='s'>&quot;Builds a vcalendar from a header and timestamp&quot;</span> <span class='p'>(</span><span class='k'>let</span> <span class='p'>((</span><span class='nv'>vcal-template</span> <span class='s'>&quot;BEGIN:VCALENDAR</span> <span class='s'>VERSION:1.0</span> <span class='s'>BEGIN:VEVENT</span> <span class='s'>CATEGORIES:APPOINTMENT</span> <span class='s'>DTSTART:%s</span> <span class='s'>DTEND:%s</span> <span class='s'>SUMMARY:%s</span> <span class='s'>DESCRIPTION:%s</span> <span class='s'>END:VEVENT</span> <span class='s'>END:VCALENDAR&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>time</span> <span class='p'>(</span><span class='nv'>format-time-string</span> <span class='s'>&quot;%Y-%m-%d %H%M&quot;</span> <span class='p'>(</span><span class='nb'>apply</span> <span class='ss'>&#39;encode-time</span> <span class='p'>(</span><span class='nv'>org-parse-time-string</span> <span class='nv'>timestamp</span><span class='p'>)))))</span> <span class='p'>(</span><span class='nb'>format</span> <span class='nv'>vcal-template</span> <span class='nb'>time</span> <span class='nb'>time</span> <span class='nv'>header</span> <span class='nv'>header</span><span class='p'>)))</span> <span class='c1'>;;;###autoload</span> <span class='p'>(</span><span class='nb'>defun</span> <span class='nv'>org-agenda-sms-send</span> <span class='p'>(</span><span class='nv'>text</span> <span class='k'>&amp;optional</span> <span class='k'>type</span><span class='p'>)</span> <span class='s'>&quot;Send an SMS vcalendar provided by \&quot;text\&quot;&quot;</span> <span class='p'>(</span><span class='k'>let*</span> <span class='p'>((</span><span class='nv'>text</span> <span class='p'>(</span><span class='nv'>url-hexify-string</span> <span class='nv'>text</span><span class='p'>))</span> <span class='p'>(</span><span class='nv'>url-format</span> <span class='s'>&quot;https://api.clickatell.com/http/sendmsg?user=%s&amp;password=%s&amp;api_id=%s&amp;to=%s&amp;msg_type=%s&amp;text=%s&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>url</span> <span class='p'>(</span><span class='nb'>format</span> <span class='nv'>url-format</span> <span class='nv'>org-agenda-sms-username</span> <span class='nv'>org-agenda-sms-password</span> <span class='nv'>org-agenda-sms-api-key</span> <span class='nv'>org-agenda-sms-phone</span> <span class='p'>(</span><span class='k'>if</span> <span class='k'>type</span> <span class='k'>type</span> <span class='s'>&quot;SMS_NOKIA_VCAL&quot;</span><span class='p'>)</span> <span class='nv'>text</span><span class='p'>)))</span> <span class='p'>(</span><span class='nv'>message</span> <span class='s'>&quot;Retrieving api.clickatell.com/http/sendmsg..&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>url-retrieve-synchronously</span> <span class='nv'>url</span><span class='p'>)))</span> <span class='c1'>;;;###autoload</span> <span class='p'>(</span><span class='nb'>defun</span> <span class='nv'>org-agenda-sms</span> <span class='p'>()</span> <span class='s'>&quot;Check for appointments in org-agenda and SMS as vcalendar to phone&quot;</span> <span class='p'>(</span><span class='nv'>org-map-entries</span> <span class='p'>(</span><span class='k'>lambda</span> <span class='p'>()</span> <span class='p'>(</span><span class='k'>let</span> <span class='p'>((</span><span class='nv'>heading</span> <span class='p'>(</span><span class='nv'>clean-org-heading</span> <span class='p'>(</span><span class='nb'>nth</span> <span class='mi'>4</span> <span class='p'>(</span><span class='nv'>org-heading-components</span><span class='p'>))))</span> <span class='p'>(</span><span class='nv'>props</span> <span class='p'>(</span><span class='nv'>org-entry-properties</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>cond</span> <span class='p'>((</span><span class='nb'>assoc</span> <span class='s'>&quot;DEADLINE&quot;</span> <span class='nv'>props</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>org-agenda-sms-send</span> <span class='p'>(</span><span class='nv'>org-agenda-sms-build-vcal</span> <span class='nv'>heading</span> <span class='p'>(</span><span class='nb'>cdr</span> <span class='p'>(</span><span class='nb'>assoc</span> <span class='s'>&quot;DEADLINE&quot;</span> <span class='nv'>props</span><span class='p'>)))))</span> <span class='p'>((</span><span class='nb'>assoc</span> <span class='s'>&quot;SCHEDULED&quot;</span> <span class='nv'>props</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>org-agenda-sms-send</span> <span class='p'>(</span><span class='nv'>org-agenda-sms-build-vcal</span> <span class='nv'>heading</span> <span class='p'>(</span><span class='nb'>cdr</span> <span class='p'>(</span><span class='nb'>assoc</span> <span class='s'>&quot;SCHEDULED&quot;</span> <span class='nv'>props</span><span class='p'>)))))</span> <span class='p'>((</span><span class='nb'>assoc</span> <span class='s'>&quot;TIMESTAMP&quot;</span> <span class='nv'>props</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>org-agenda-sms-send</span> <span class='p'>(</span><span class='nv'>org-agenda-sms-build-vcal</span> <span class='nv'>heading</span> <span class='p'>(</span><span class='nb'>cdr</span> <span class='p'>(</span><span class='nb'>assoc</span> <span class='s'>&quot;TIMESTAMP&quot;</span> <span class='nv'>props</span><span class='p'>))))))))</span> <span class='s'>&quot;TIMESTAMP&lt;=\&quot;&lt;+1d&gt;\&quot;|DEADLINE&lt;=\&quot;&lt;+1d&gt;\&quot;|SCHEDULED&lt;=\&quot;&lt;+1d&gt;\&quot;&quot;</span> <span class='ss'>&#39;agenda</span><span class='p'>))</span> <span class='p'>(</span><span class='nb'>provide</span> <span class='ss'>&#39;org-agenda-sms</span><span class='p'>)</span> </code></pre> </div> <p>Seems to work for me, but as always your mileage may vary ;)</p> More Practical Chicken http://demonastery.org/68/more-practical-chicken/ Thu, 12 May 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/68/more-practical-chicken <p>As I love sharing code on my blog, and I love <a href='http://call-cc.org'>Chicken Scheme</a>, I&#8217;m going to share a couple of handy and practical features that I&#8217;ve made use of recently.</p> <p>Anyone that has used C++ for longer than a few minutes has probably noticed that literal constants (<em>numbers and such</em>) often have a suffix attached to them. The most common place that you&#8217;ll see this is when writing floating-point decimals, ie. <strong>1.0f</strong>.</p> <p>They might seem a little pointless at first, but they have their uses; I swear that I once read of a way to add your own types into the language too.</p> <p>But anyway, I searched for a way to do this in Chicken too, and it turns out it&#8217;s really easy (of course!). Chicken provides a function called <a href='http://wiki.call-cc.org/man/4/Unit%20library#set-parameterized-read-syntax'>set-parameterized-read-syntax!</a> that can emulate this functionality quite nicely.</p> <p>Here&#8217;s a real world case that I used recently, I wanted to be able to convert from inches into pixels, based on a known DPI (in this case 180). The code to set this up looks like this:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; This lets you type #12i anywhere in your code and have it replaced with 2160</span> <span class='p'>(</span><span class='nf'>set-parameterized-read-syntax</span> <span class='sc'>#\i</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>port</span> <span class='nv'>n</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>* </span><span class='nv'>n</span> <span class='mi'>180</span><span class='p'>)))</span> </code></pre> </div> <p>Yeah that&#8217;s really it, isn&#8217;t Scheme wonderful :P</p> <p>The other really useful feature is the <a href='http://wiki.call-cc.org/eggref/4/regex-literals'>regex-literals</a> egg (download it with <code>sudo chicken-install regex-literals</code>), which gives Chicken Scheme the ability to use Ruby/Perl/Javascript style literal regexes; well almost, it allows you to type <strong>#/myregexhere/i</strong> (notice the leading #) and it will be converted into a <em>regexp</em> object. Luckily we can even take this a step further and remove the hash at the front. Code time!</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; Import the egg first of all</span> <span class='p'>(</span><span class='nf'>use</span> <span class='nv'>regex-literals</span><span class='p'>)</span> <span class='c1'>; Lucky for us, regex-literals provides us the function we need to read</span> <span class='c1'>; a full regex literal from a Scheme port, so all we have to do is just</span> <span class='c1'>; hook it up to the &quot;/&quot; character and it will work as expected!</span> <span class='p'>(</span><span class='nf'>set-read-syntax!</span> <span class='sc'>#\/</span> <span class='nv'>read-regex-literal</span><span class='p'>)</span> <span class='c1'>; Now we can write inline regex with a familiar syntax :D</span> <span class='p'>(</span><span class='nf'>pp</span> <span class='p'>(</span><span class='nf'>string-match</span> <span class='nv'>/</span><span class='o'>.</span><span class='nv'>*match</span><span class='err'>[</span><span class='nv'>A-Za-z</span><span class='err'>]</span><span class='nv'>+me</span><span class='o'>.</span><span class='nv'>*/i</span> <span class='s'>&quot;hello match world me :D&quot;</span><span class='p'>))</span> </code></pre> </div> <p>I know this a measly amount of code to be posting an entry for, but I hope that both of these features (among others) demonstrate just how practical Chicken Scheme can be in many situations, and shows that you don&#8217;t always have to write a large amount of code to get cool things done! Mint!</p> FileTools C++ Class http://demonastery.org/66/filetools-c-class/ Sun, 08 May 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/66/filetools-c-class <p>Here is the source for the FileTools C++ Class promised <a href='http://demonastery.org/63/c-eval-hell-yes/'>a few posts back</a>, which uses <a href='http://en.wikipedia.org/wiki/Inotify'>inotify</a> to monitor files for changes.</p> <p>Again we start off with the class header:</p> <div class='highlight'><pre><code class='cpp'><span class='c1'>// FileTools.cpp</span> <span class='cp'>#include &lt;stdio.h&gt;</span> <span class='cp'>#include &lt;stdlib.h&gt;</span> <span class='cp'>#include &lt;sys/inotify.h&gt;</span> <span class='k'>typedef</span> <span class='k'>class</span> <span class='nc'>FileTools</span> <span class='p'>{</span> <span class='k'>public</span><span class='o'>:</span> <span class='k'>static</span> <span class='kt'>int</span> <span class='n'>addWatch</span><span class='p'>(</span><span class='kt'>char</span> <span class='o'>*</span><span class='p'>,</span> <span class='p'>...);</span> <span class='k'>static</span> <span class='kt'>void</span> <span class='n'>removeWatch</span><span class='p'>(</span><span class='kt'>int</span><span class='p'>);</span> <span class='k'>static</span> <span class='kt'>bool</span> <span class='n'>hasChanged</span><span class='p'>(</span><span class='kt'>int</span><span class='p'>);</span> <span class='k'>private</span><span class='o'>:</span> <span class='k'>static</span> <span class='kt'>int</span> <span class='n'>fd</span><span class='p'>;</span> <span class='p'>}</span> <span class='o'>*</span><span class='n'>pFileTools</span><span class='p'>;</span> <span class='c1'>// Parse variable arguments into &#39;buffer&#39; character array</span> <span class='c1'>// This is just a macro I use often in my functions</span> <span class='cp'>#define parsevargs(buff, buffer) \</span> <span class='cp'> char buffer[128]; \</span> <span class='cp'> memset(buffer, 0, sizeof(buffer)); \</span> <span class='cp'> va_list ap; \</span> <span class='cp'> va_start(ap, buff); \</span> <span class='cp'> vsnprintf(buffer, sizeof(buffer), buff, ap); \</span> <span class='cp'> va_end(ap);</span> </code></pre> </div> <p>And on to the implementation:</p> <div class='highlight'><pre><code class='cpp'><span class='kt'>int</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='kt'>int</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>addWatch</span><span class='p'>(</span><span class='kt'>char</span> <span class='o'>*</span><span class='n'>path</span><span class='p'>,</span> <span class='p'>...)</span> <span class='p'>{</span> <span class='c1'>// Parse variable arguments into &quot;buffer&quot;</span> <span class='n'>parsevargs</span><span class='p'>(</span><span class='n'>path</span><span class='p'>,</span> <span class='n'>buffer</span><span class='p'>);</span> <span class='c1'>// Initialize inotify if need be</span> <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span><span class='p'>)</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span> <span class='o'>=</span> <span class='n'>inotify_init</span><span class='p'>();</span> <span class='n'>printf</span><span class='p'>(</span><span class='s'>&quot;Adding Watch for %s..</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>buffer</span><span class='p'>);</span> <span class='c1'>// Return a new watch handle</span> <span class='k'>return</span> <span class='n'>inotify_add_watch</span><span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span><span class='p'>,</span> <span class='n'>buffer</span><span class='p'>,</span> <span class='n'>IN_CLOSE_WRITE</span><span class='p'>);</span> <span class='p'>}</span> <span class='kt'>void</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>removeWatch</span><span class='p'>(</span><span class='kt'>int</span> <span class='n'>wd</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>printf</span><span class='p'>(</span><span class='s'>&quot;Removing Watch id = %i..</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>wd</span><span class='p'>);</span> <span class='n'>inotify_rm_watch</span><span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span><span class='p'>,</span> <span class='n'>wd</span><span class='p'>);</span> <span class='p'>}</span> <span class='cp'>#define EVENT_SIZE (sizeof(struct inotify_event))</span> <span class='cp'>#define BUF_LEN (1024 * (EVENT_SIZE + 16))</span> <span class='kt'>bool</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>hasChanged</span><span class='p'>(</span><span class='kt'>int</span> <span class='n'>wd</span><span class='p'>)</span> <span class='p'>{</span> <span class='kt'>bool</span> <span class='n'>ret</span> <span class='o'>=</span> <span class='kc'>false</span><span class='p'>;</span> <span class='c1'>// Return from select immediately if none available</span> <span class='k'>struct</span> <span class='n'>timeval</span> <span class='n'>time</span><span class='p'>;</span> <span class='n'>time</span><span class='p'>.</span><span class='n'>tv_sec</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='n'>time</span><span class='p'>.</span><span class='n'>tv_usec</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='n'>fd_set</span> <span class='n'>rfds</span><span class='p'>;</span> <span class='n'>FD_ZERO</span><span class='p'>(</span><span class='o'>&amp;</span><span class='n'>rfds</span><span class='p'>);</span> <span class='c1'>// Set up our fd_set with our inotify fd</span> <span class='n'>FD_SET</span><span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span><span class='p'>,</span> <span class='o'>&amp;</span><span class='n'>rfds</span><span class='p'>);</span> <span class='c1'>// Do the select</span> <span class='n'>select</span><span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span> <span class='o'>+</span> <span class='mi'>1</span><span class='p'>,</span> <span class='o'>&amp;</span><span class='n'>rfds</span><span class='p'>,</span> <span class='nb'>NULL</span><span class='p'>,</span> <span class='nb'>NULL</span><span class='p'>,</span> <span class='o'>&amp;</span><span class='n'>time</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>FD_ISSET</span><span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span><span class='p'>,</span> <span class='o'>&amp;</span><span class='n'>rfds</span><span class='p'>))</span> <span class='p'>{</span> <span class='kt'>int</span> <span class='n'>length</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='kt'>int</span> <span class='n'>i</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='kt'>char</span> <span class='n'>buffer</span><span class='p'>[</span><span class='n'>BUF_LEN</span><span class='p'>];</span> <span class='n'>length</span> <span class='o'>=</span> <span class='n'>read</span><span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>fd</span><span class='p'>,</span> <span class='n'>buffer</span><span class='p'>,</span> <span class='n'>BUF_LEN</span><span class='p'>);</span> <span class='k'>while</span> <span class='p'>(</span><span class='n'>i</span> <span class='o'>&lt;</span> <span class='n'>length</span><span class='p'>)</span> <span class='p'>{</span> <span class='c1'>// Got a match</span> <span class='k'>struct</span> <span class='n'>inotify_event</span> <span class='o'>*</span><span class='n'>event</span> <span class='o'>=</span> <span class='p'>(</span><span class='k'>struct</span> <span class='n'>inotify_event</span><span class='o'>*</span><span class='p'>)</span><span class='o'>&amp;</span><span class='n'>buffer</span><span class='p'>[</span><span class='n'>i</span><span class='p'>];</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>event</span><span class='o'>-&gt;</span><span class='n'>wd</span> <span class='o'>==</span> <span class='n'>wd</span> <span class='o'>&amp;&amp;</span> <span class='n'>event</span><span class='o'>-&gt;</span><span class='n'>mask</span> <span class='o'>&amp;</span> <span class='n'>IN_CLOSE_WRITE</span><span class='p'>)</span> <span class='p'>{</span> <span class='c1'>// It was a file we were monitoring!</span> <span class='n'>printf</span><span class='p'>(</span><span class='s'>&quot;Watched file %i has changed</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>wd</span><span class='p'>);</span> <span class='n'>ret</span> <span class='o'>=</span> <span class='kc'>true</span><span class='p'>;</span> <span class='p'>}</span> <span class='n'>i</span> <span class='o'>+=</span> <span class='n'>EVENT_SIZE</span> <span class='o'>+</span> <span class='n'>event</span><span class='o'>-&gt;</span><span class='n'>len</span><span class='p'>;</span> <span class='p'>}</span> <span class='p'>}</span> <span class='k'>return</span> <span class='n'>ret</span><span class='p'>;</span> <span class='p'>}</span> </code></pre> </div> <p>And that&#8217;s it! Use to your hearts content, this code and the CodeTools code before it are free to use for whatever purpose you want.</p> <p>Sorry for the short post, but I want to post more Scheme (and maybe PHP) instead of cluttering up my blog with C++ ;)</p> CodeTools C++ Class http://demonastery.org/65/codetools-c-class/ Sat, 07 May 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/65/codetools-c-class <p>As promised <a href='http://demonastery.org/63/c-eval-hell-yes/'>a couple of posts back</a>, I will present a C++ class to compile some arbitrary code using <a href='http://en.wikipedia.org/wiki/GNU_Compiler_Collection'>GCC</a> and load it into memory.</p> <p>The code is pretty simple, we start off with the class header:</p> <div class='highlight'><pre><code class='cpp'><span class='c1'>// CodeTools.hpp</span> <span class='cp'>#include &lt;stdio.h&gt;</span> <span class='cp'>#include &lt;stdlib.h&gt;</span> <span class='cp'>#include &lt;dlfcn.h&gt;</span> <span class='k'>typedef</span> <span class='k'>class</span> <span class='nc'>CodeTools</span> <span class='p'>{</span> <span class='k'>public</span><span class='o'>:</span> <span class='k'>static</span> <span class='kt'>bool</span> <span class='n'>compileString</span><span class='p'>(</span><span class='kt'>char</span><span class='o'>*</span><span class='p'>,</span> <span class='kt'>bool</span> <span class='p'>(</span><span class='o'>*</span><span class='n'>callback</span><span class='p'>)(</span><span class='kt'>void</span><span class='o'>*</span><span class='p'>));</span> <span class='k'>static</span> <span class='kt'>bool</span> <span class='n'>compileFile</span><span class='p'>(</span><span class='kt'>char</span><span class='o'>*</span><span class='p'>,</span> <span class='kt'>bool</span> <span class='p'>(</span><span class='o'>*</span><span class='n'>callback</span><span class='p'>)(</span><span class='kt'>void</span><span class='o'>*</span><span class='p'>));</span> <span class='k'>private</span><span class='o'>:</span> <span class='p'>}</span> <span class='o'>*</span><span class='n'>pCodeTools</span><span class='p'>;</span> </code></pre> </div> <p>And then on to the <code>compileString</code> method. This method actually just wraps compileFile to avoid code duplication, so it&#8217;s really just taking in a string and writing it to a temporary file before calling <code>compileFile</code>.</p> <p>Here we go:</p> <div class='highlight'><pre><code class='cpp'><span class='c1'>// CodeTools.cpp</span> <span class='kt'>bool</span> <span class='n'>CodeTools</span><span class='o'>::</span><span class='n'>compileString</span><span class='p'>(</span><span class='kt'>char</span><span class='o'>*</span> <span class='n'>code</span><span class='p'>,</span> <span class='kt'>bool</span> <span class='p'>(</span><span class='o'>*</span><span class='n'>callback</span><span class='p'>)(</span><span class='kt'>void</span><span class='o'>*</span><span class='p'>))</span> <span class='p'>{</span> <span class='c1'>// Generate a temporary file name</span> <span class='c1'>// (There are better ways to do this!)</span> <span class='kt'>char</span> <span class='n'>temp</span><span class='p'>[</span><span class='mi'>256</span><span class='p'>];</span> <span class='n'>sprintf</span><span class='p'>(</span><span class='n'>temp</span><span class='p'>,</span> <span class='s'>&quot;codetools_XXXXXX&quot;</span><span class='p'>);</span> <span class='kt'>char</span><span class='o'>*</span> <span class='n'>tmppath</span> <span class='o'>=</span> <span class='n'>mktemp</span><span class='p'>(</span><span class='n'>temp</span><span class='p'>);</span> <span class='c1'>// Open temporary file</span> <span class='n'>FILE</span><span class='o'>*</span> <span class='n'>fp</span> <span class='o'>=</span> <span class='n'>fopen</span><span class='p'>(</span><span class='n'>tmppath</span><span class='p'>,</span> <span class='s'>&quot;wb&quot;</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='n'>fp</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>fprintf</span><span class='p'>(</span><span class='n'>stderr</span><span class='p'>,</span> <span class='s'>&quot;Could not open temporary path %s</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>tmppath</span><span class='p'>);</span> <span class='k'>return</span> <span class='kc'>false</span><span class='p'>;</span> <span class='p'>}</span> <span class='c1'>// Write out string</span> <span class='n'>fwrite</span><span class='p'>(</span><span class='n'>code</span><span class='p'>,</span> <span class='n'>strlen</span><span class='p'>(</span><span class='n'>code</span><span class='p'>),</span> <span class='k'>sizeof</span><span class='p'>(</span><span class='kt'>char</span><span class='p'>),</span> <span class='n'>fp</span><span class='p'>);</span> <span class='n'>fclose</span><span class='p'>(</span><span class='n'>fp</span><span class='p'>);</span> <span class='c1'>// Call out to compileFile method</span> <span class='kt'>bool</span> <span class='n'>ret</span> <span class='o'>=</span> <span class='n'>compileFile</span><span class='p'>(</span><span class='n'>tmppath</span><span class='p'>,</span> <span class='n'>callback</span><span class='p'>);</span> <span class='c1'>// Remove temporary file</span> <span class='n'>unlink</span><span class='p'>(</span><span class='n'>tmppath</span><span class='p'>);</span> <span class='k'>return</span> <span class='n'>ret</span><span class='p'>;</span> <span class='p'>}</span> </code></pre> </div> <p>So again, just a small wrapper, which can be reimplemented to your liking.</p> <p>Now for the part that does the actual work, this can be cleaned up plenty but seems pretty stable for me:</p> <div class='highlight'><pre><code class='cpp'><span class='kt'>bool</span> <span class='n'>CodeTools</span><span class='o'>::</span><span class='n'>compileFile</span><span class='p'>(</span><span class='kt'>char</span><span class='o'>*</span> <span class='n'>path</span><span class='p'>,</span> <span class='kt'>bool</span> <span class='p'>(</span><span class='o'>*</span><span class='n'>callback</span><span class='p'>)(</span><span class='kt'>void</span><span class='o'>*</span><span class='p'>))</span> <span class='p'>{</span> <span class='c1'>// Increments each time this function is called.</span> <span class='c1'>// This is used for the .so path. If the .so path</span> <span class='c1'>// doesn&#39;t change then our new functions won&#39;t</span> <span class='c1'>// override the old ones.</span> <span class='k'>static</span> <span class='kt'>int</span> <span class='n'>count</span> <span class='o'>=</span> <span class='mi'>0</span><span class='p'>;</span> <span class='c1'>// A buffer to hold our command line</span> <span class='kt'>char</span> <span class='n'>buffer</span><span class='p'>[</span><span class='mi'>256</span><span class='p'>];</span> <span class='n'>memset</span><span class='p'>(</span><span class='n'>buffer</span><span class='p'>,</span> <span class='mi'>0</span><span class='p'>,</span> <span class='k'>sizeof</span><span class='p'>(</span><span class='n'>buffer</span><span class='p'>));</span> <span class='c1'>// The last path used</span> <span class='kt'>char</span> <span class='n'>sopathLast</span><span class='p'>[</span><span class='mi'>256</span><span class='p'>];</span> <span class='n'>memset</span><span class='p'>(</span><span class='n'>sopathLast</span><span class='p'>,</span> <span class='mi'>0</span> <span class='p'>,</span> <span class='k'>sizeof</span><span class='p'>(</span><span class='n'>sopathLast</span><span class='p'>));</span> <span class='c1'>// The current path to use</span> <span class='kt'>char</span> <span class='n'>sopath</span><span class='p'>[</span><span class='mi'>256</span><span class='p'>];</span> <span class='n'>memset</span><span class='p'>(</span><span class='n'>sopath</span><span class='p'>,</span> <span class='mi'>0</span> <span class='p'>,</span> <span class='k'>sizeof</span><span class='p'>(</span><span class='n'>sopath</span><span class='p'>));</span> <span class='n'>sprintf</span><span class='p'>(</span><span class='n'>sopathLast</span><span class='p'>,</span> <span class='s'>&quot;./%s.%i.so&quot;</span><span class='p'>,</span> <span class='n'>path</span><span class='p'>,</span> <span class='n'>count</span> <span class='o'>-</span> <span class='mi'>1</span><span class='p'>);</span> <span class='n'>sprintf</span><span class='p'>(</span><span class='n'>sopath</span><span class='p'>,</span> <span class='s'>&quot;./%s.%i.so&quot;</span><span class='p'>,</span> <span class='n'>path</span><span class='p'>,</span> <span class='n'>count</span><span class='o'>++</span><span class='p'>);</span> <span class='c1'>// Please change modify these to your liking! These are what I use</span> <span class='c1'>// for my livecoding playground</span> <span class='n'>sprintf</span><span class='p'>(</span><span class='n'>buffer</span><span class='p'>,</span> <span class='s'>&quot;g++ -shared -o %s -fPIC -fno-use-cxa-atexit -xc++ -include src/Global.hpp %s -Isrc -I/usr/include/freetype2&quot;</span><span class='p'>,</span> <span class='n'>sopath</span><span class='p'>,</span> <span class='n'>path</span><span class='p'>);</span> <span class='c1'>// Call it!</span> <span class='kt'>int</span> <span class='n'>ret</span> <span class='o'>=</span> <span class='n'>system</span><span class='p'>(</span><span class='n'>buffer</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>ret</span> <span class='o'>!=</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>fprintf</span><span class='p'>(</span><span class='n'>stderr</span><span class='p'>,</span> <span class='s'>&quot;Error in compilation: g++ returned %i</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>ret</span><span class='p'>);</span> <span class='k'>return</span> <span class='kc'>false</span><span class='p'>;</span> <span class='p'>}</span> <span class='c1'>// Cool, compile was successful!</span> <span class='c1'>// Now, try to get a handle to the last opened .so so we can close it</span> <span class='kt'>void</span><span class='o'>*</span> <span class='n'>handle</span> <span class='o'>=</span> <span class='n'>dlopen</span><span class='p'>(</span><span class='n'>sopathLast</span><span class='p'>,</span> <span class='n'>RTLD_LAZY</span> <span class='o'>|</span> <span class='n'>RTLD_NOLOAD</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>handle</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>fprintf</span><span class='p'>(</span><span class='n'>stderr</span><span class='p'>,</span> <span class='s'>&quot;Found current handle %s, closing first</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>sopathLast</span><span class='p'>);</span> <span class='n'>dlclose</span><span class='p'>(</span><span class='n'>handle</span><span class='p'>);</span> <span class='p'>}</span> <span class='c1'>// Open the new .so, LAZY load symbols for speed</span> <span class='n'>handle</span> <span class='o'>=</span> <span class='n'>dlopen</span><span class='p'>(</span><span class='n'>sopath</span><span class='p'>,</span> <span class='n'>RTLD_LAZY</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='n'>handle</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>fprintf</span><span class='p'>(</span><span class='n'>stderr</span><span class='p'>,</span> <span class='s'>&quot;Could not load compiled file into memory: %s</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>dlerror</span><span class='p'>());</span> <span class='n'>unlink</span><span class='p'>(</span><span class='n'>sopath</span><span class='p'>);</span> <span class='k'>return</span> <span class='kc'>false</span><span class='p'>;</span> <span class='p'>}</span> <span class='n'>printf</span><span class='p'>(</span><span class='s'>&quot;Loaded %s</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>sopath</span><span class='p'>);</span> <span class='c1'>// Remove temporary .so</span> <span class='n'>unlink</span><span class='p'>(</span><span class='n'>sopath</span><span class='p'>);</span> <span class='c1'>// Call the user supplied callback passing the .so handle to it</span> <span class='c1'>// From there it can load individual functions.</span> <span class='k'>return</span> <span class='n'>callback</span><span class='p'>(</span><span class='n'>handle</span><span class='p'>);</span> <span class='p'>}</span> </code></pre> </div> <p>And done. This should be all the code needed to use the CodeTools sample from the <a href='http://demonastery.org/63/c-eval-hell-yes/'>C++ Eval? Hell yes.</a> post. Have fun! I will be posting the FileTools class shortly too.</p> Fun with Renoise and Fluxus http://demonastery.org/64/fun-with-renoise-and-fluxus/ Mon, 02 May 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/64/fun-with-renoise-and-fluxus <p>Amidst my experimentations with livecoding I decided to purchase the amazing <a href='http://www.renoise.com'>Renoise</a> Tracker (and overall DAW) while it is on special (30% discount!). My intentions are to play around with Renoise to make music (online and off), and using the built in <a href='http://opensoundcontrol.org/introduction-osc'>OSC</a> and <a href='http://jackaudio.org/'>JACK</a> support, coordinate the music using <a href='http://www.pawfal.org/fluxus/'>Fluxus</a>, and of course be able to respond to it. I am also toying with the idea of using an <a href='http://arduino.cc'>Arduino</a> or two as input devices. Fun stuff I reckon :P</p> <p>For anyone wondering how to make Fluxus respond to the Renoise audio, it is simple using JACK:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; If I remember correctly you may need to connect the Renoise</span> <span class='c1'>; output to the Fluxus input using something like qjackctl first</span> <span class='p'>(</span><span class='nf'>start-audio</span> <span class='s'>&quot;renoise:output_01_left&quot;</span> <span class='mi'>1024</span> <span class='mi'>44100</span><span class='p'>)</span> <span class='c1'>; This will tell Fluxus to listen to the left channel..</span> <span class='p'>(</span><span class='nf'>gain</span> <span class='mi'>1</span><span class='p'>)</span> <span class='c1'>; .. and later in your render loop, using the &quot;gh&quot; function you can react to the sound</span> <span class='p'>(</span><span class='nf'>every-frame</span> <span class='p'>(</span><span class='nf'>begin</span> <span class='p'>(</span><span class='nf'>scale</span> <span class='p'>(</span><span class='nf'>vmul</span> <span class='p'>(</span><span class='nb'>vector </span><span class='p'>(</span><span class='nf'>gh</span> <span class='mi'>1</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gh</span> <span class='mi'>2</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gh</span> <span class='mi'>3</span><span class='p'>))</span> <span class='mf'>0.1</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>draw-torus</span><span class='p'>)))</span> </code></pre> </div> <p>Pretty neat. Using OSC it is also really simple to control Renoise. First you will want to enable the OSC server in the Renoise preferences, and then you can use the following:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='nf'>osc-destination</span> <span class='s'>&quot;osc.udp://localhost:8000&quot;</span><span class='p'>)</span> <span class='c1'>; With the port you specify in the preferences</span> <span class='p'>(</span><span class='nf'>osc-send</span> <span class='s'>&quot;/renoise/song/bpm&quot;</span> <span class='s'>&quot;i&quot;</span> <span class='p'>(</span><span class='nb'>list </span><span class='mi'>120</span><span class='p'>))</span> <span class='c1'>; Set the BPM to 120</span> <span class='p'>(</span><span class='nf'>osc-send</span> <span class='s'>&quot;/renoise/transport/start&quot;</span> <span class='s'>&quot;&quot;</span> <span class='p'>(</span><span class='nf'>list</span><span class='p'>))</span> <span class='c1'>; Start playback</span> <span class='p'>(</span><span class='nf'>osc-send</span> <span class='s'>&quot;/renoise/transport/stop&quot;</span> <span class='s'>&quot;&quot;</span> <span class='p'>(</span><span class='nf'>list</span><span class='p'>))</span> <span class='c1'>; Stop playback</span> </code></pre> </div> <p>Next up is to get Fluxus working nicely with Emacs.. and I promise some more updates will come shortly (including the code I&#8217;ve promised) :)</p> C++ Eval? Hell yes. http://demonastery.org/63/c-eval-hell-yes/ Sat, 16 Apr 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/63/c-eval-hell-yes <p>Recently I&#8217;ve been getting back into <a href='http://en.wikipedia.org/wiki/Live_coding'>live coding</a>, and as part of that I have been experimenting with a simple livecoding framework in C++.</p> <p>One of my experiments involves using C++ as a <em>scripting language</em>, by compiling code on the fly (using g++, but any compiler should work) into a shared object, and then <a href='http://en.wikipedia.org/wiki/Dynamic_loading'>dlopen</a>-ing the resultant file and hooking up the necessary functions.</p> <p>By doing this I can have full access to the engine/framework and speed is never a concern. It also means I can modify it later to load any arbitrary shared object (ie. generated via C or any other language, perhaps Chicken?).</p> <p>The workflow I desired to achieve was to have an OpenGL context open, blank at first. From there I could open the editor of my choice, hack on some high level C++/OpenGL, and when I saved the file, the engine would recompile the file and load it, causing its rendering function to be overridden with the new one.</p> <p>I&#8217;m happy to say I&#8217;ve achieved what I was after!</p> <p><em>I will be posting the relevant source to do this in the next post</em>, but for now I will say that it involves a very simple class called <strong>FileTools</strong> that wraps <a href='http://en.wikipedia.org/wiki/Inotify'>inotify</a> on the Linux operating system (so it will need to be ported for other OS&#8217;s, or a generic polling solution could be used very easily, by simply resorting to <a href='http://en.wikipedia.org/wiki/Stat_(Unix'>stat</a>)), which allows one to watch a file with some simple code that looks like this:</p> <div class='highlight'><pre><code class='cpp'><span class='kt'>int</span> <span class='n'>fd</span> <span class='o'>=</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>addWatch</span><span class='p'>(</span><span class='s'>&quot;test.cpp&quot;</span><span class='p'>);</span> <span class='k'>while</span> <span class='p'>(</span><span class='n'>mainloop</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>hasChanged</span><span class='p'>(</span><span class='n'>fd</span><span class='p'>))</span> <span class='p'>{</span> <span class='c1'>// Uses select internally</span> <span class='c1'>// Cool!</span> <span class='p'>}</span> <span class='p'>}</span> <span class='n'>FileTools</span><span class='o'>::</span><span class='n'>removeWatch</span><span class='p'>(</span><span class='n'>fd</span><span class='p'>);</span> </code></pre> </div> <p>For my engine to extend this to include recompilation, I have another class called <strong>CodeTools</strong>, which wraps <code>system</code> and <code>dlopen</code>. This is also very easy to use, it looks like this:</p> <div class='highlight'><pre><code class='cpp'><span class='k'>if</span> <span class='p'>(</span><span class='n'>FileTools</span><span class='o'>::</span><span class='n'>hasChanged</span><span class='p'>(</span><span class='n'>fd</span><span class='p'>))</span> <span class='p'>{</span> <span class='n'>CodeTools</span><span class='o'>::</span><span class='n'>compileFile</span><span class='p'>(</span><span class='s'>&quot;test.cpp&quot;</span><span class='p'>,</span> <span class='p'>[](</span><span class='kt'>void</span><span class='o'>*</span> <span class='n'>handle</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>Renderer</span><span class='o'>::</span><span class='n'>renderp</span> <span class='n'>render</span> <span class='o'>=</span> <span class='p'>(</span><span class='n'>Renderer</span><span class='o'>::</span><span class='n'>renderp</span><span class='p'>)</span><span class='n'>dlsym</span><span class='p'>(</span><span class='n'>handle</span><span class='p'>,</span> <span class='s'>&quot;render&quot;</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>render</span><span class='p'>)</span> <span class='c1'>// Hook &#39;er up</span> <span class='o'>::</span><span class='n'>engine</span><span class='p'>.</span><span class='n'>renderer</span><span class='o'>-&gt;</span><span class='n'>userRender</span> <span class='o'>=</span> <span class='n'>render</span><span class='p'>;</span> <span class='p'>});</span> <span class='p'>}</span> </code></pre> </div> <p>Here we are passing a path to a file to compile, and a function (I&#8217;m using <a href='http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions'>C++0x lambdas</a> here) that takes a valid handle from <code>dlopen</code>.</p> <p>Using this class it is also possible to using <code>compileString</code> to compile a string via temp files.</p> <p>Oh and <strong><a href='http://i.imgur.com/64M4d.png'>a screenshot</a></strong> for those wanting to see it in action!</p> <p><a href='http://i.imgur.com/64M4d.png'><img alt='Desktop' src='http://i.imgur.com/64M4dm.png' /></a></p> Change GTK display on the fly http://demonastery.org/62/change-gtk-display-on-the-fly/ Sat, 09 Apr 2011 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/62/change-gtk-display-on-the-fly <p>While working on my <a href='http://demonastery.org/59/acer-aspire-one-d255e/'>netbook</a> away from my desktop machine, I pondered how I could view my email clients display (<a href='http://claws-mail.org'>claws-mail</a>, a GTK app), without having to resort to something such as <a href='http://en.wikipedia.org/wiki/Virtual_Network_Computing'>VNC</a>.</p> <p>I know this can be done using utilities such as <a href='http://en.wikipedia.org/wiki/Xmove'>xmove</a>, which essentially act as a proxy X server that can detach a client from one display and move it to another. But this requires you to start xmove before the application, and to tell the application to launch with its display on xmove.</p> <p>Nah. <em>We need something cooler than this.</em></p> <p>After using some Google fu it became apparent that the GTK library has a function named <code>gtk_window_set_screen</code> which is demonstrated in the <em>gtk-demo</em> application that comes with the GTK sources. This function allows the application to switch X11 display on the fly.. provided the application has a way to do so (which barely any do, apart from the GIMP, because most don&#8217;t need to).</p> <p>So I decided to look into ways of doing <em>code injection</em> in Linux, as a way of being able to call that function inside our target application. Turns out this is easy as pie using <a href='http://en.wikipedia.org/wiki/GNU_Debugger'>GDB</a>.</p> <p>First of all, we need to create a small library that contains our code. This will be loaded into memory and executed by us later. The code I hacked together looks like this (no guarantees whatsoever that this will work on your machine):</p> <div class='highlight'><pre><code class='c'><span class='c1'>// Include the headers we will need</span> <span class='cp'>#include &lt;stdio.h&gt;</span> <span class='cp'>#include &lt;gtk/gtk.h&gt;</span> <span class='c1'>// Now write the function we will be executing.</span> <span class='c1'>// This one takes a string containing the display to connect to</span> <span class='kt'>void</span> <span class='nf'>change_display</span><span class='p'>(</span><span class='kt'>char</span> <span class='o'>*</span><span class='n'>display_str</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>GdkDisplay</span> <span class='o'>*</span><span class='n'>display</span> <span class='o'>=</span> <span class='n'>gdk_display_get_default</span><span class='p'>();</span> <span class='n'>GtkWidget</span> <span class='o'>*</span><span class='n'>toplevel</span> <span class='o'>=</span> <span class='nb'>NULL</span><span class='p'>;</span> <span class='n'>GdkWindow</span> <span class='o'>*</span><span class='n'>window</span> <span class='o'>=</span> <span class='nb'>NULL</span><span class='p'>;</span> <span class='n'>GtkWidget</span> <span class='o'>*</span><span class='n'>widget</span> <span class='o'>=</span> <span class='nb'>NULL</span><span class='p'>;</span> <span class='c1'>// Not 100% necessary but gives you time before the line below this one runs</span> <span class='n'>sleep</span><span class='p'>(</span><span class='mi'>5</span><span class='p'>);</span> <span class='c1'>// This line gets the GDK window below the cursor</span> <span class='n'>window</span> <span class='o'>=</span> <span class='n'>gdk_display_get_window_at_pointer</span><span class='p'>(</span><span class='n'>display</span><span class='p'>,</span> <span class='nb'>NULL</span><span class='p'>,</span> <span class='nb'>NULL</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>window</span><span class='p'>)</span> <span class='p'>{</span> <span class='n'>gdk_window_get_user_data</span><span class='p'>(</span><span class='n'>window</span><span class='p'>,</span> <span class='p'>(</span><span class='n'>gpointer</span><span class='p'>)</span><span class='o'>&amp;</span><span class='n'>widget</span><span class='p'>);</span> <span class='n'>toplevel</span> <span class='o'>=</span> <span class='n'>gtk_widget_get_toplevel</span><span class='p'>(</span><span class='n'>widget</span><span class='p'>);</span> <span class='n'>GdkDisplay</span> <span class='o'>*</span><span class='n'>new_display</span> <span class='o'>=</span> <span class='n'>gdk_display_open</span><span class='p'>(</span><span class='n'>display_str</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='n'>new_display</span><span class='p'>)</span> <span class='n'>gtk_window_set_screen</span><span class='p'>(</span><span class='n'>GTK_WINDOW</span><span class='p'>(</span><span class='n'>toplevel</span><span class='p'>),</span> <span class='n'>gdk_display_get_screen</span><span class='p'>(</span><span class='n'>new_display</span><span class='p'>,</span> <span class='mi'>0</span><span class='p'>));</span> <span class='k'>else</span> <span class='n'>fprintf</span><span class='p'>(</span><span class='n'>stderr</span><span class='p'>,</span> <span class='s'>&quot;Could not connect to display </span><span class='se'>\&quot;</span><span class='s'>%s</span><span class='se'>\&quot;\n</span><span class='s'>&quot;</span><span class='p'>,</span> <span class='n'>display_str</span><span class='p'>);</span> <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span> <span class='n'>fprintf</span><span class='p'>(</span><span class='n'>stderr</span><span class='p'>,</span> <span class='s'>&quot;No window found</span><span class='se'>\n</span><span class='s'>&quot;</span><span class='p'>);</span> <span class='p'>}</span> <span class='c1'>// By this point the window should have moved itself to the display you passed in</span> <span class='p'>}</span> </code></pre> </div> <p>Cool. So now we just need to compile it and we&#8217;re a step closer to <em>winning</em>:</p> <div class='highlight'><pre><code class='bash'>gcc -shared -fPIC -o lib lib.c <span class='sb'>`</span>pkg-config --libs --cflags gtk+-2.0<span class='sb'>`</span> </code></pre> </div> <p>Now we should be left with our library sitting in our current directory. Now we can actually inject the code. For this part, we will fire up <strong>GDB</strong>, attaching to the program we wish to move:</p> <div class='highlight'><pre><code class='bash'>gdb attach <span class='sb'>`</span>pidof claws-mail<span class='sb'>`</span> </code></pre> </div> <p>A bunch of lines will scroll by, which you can largely ignore for this exercise, but you should be left with a nice <code>(gdb)</code> prompt. Now it&#8217;s time to inject our code!</p> <div class='highlight'><pre><code class='bash'><span class='o'>(</span>gdb<span class='o'>)</span> print <span class='o'>(</span>void*<span class='o'>)</span>dlopen<span class='o'>(</span><span class='s2'>&quot;/path/to/your/current/directory/lib&quot;</span>, 2<span class='o'>)</span> </code></pre> </div> <p>Yep, GDB has now loaded our library into the memory space of the application. Now we can run our function :)</p> <div class='highlight'><pre><code class='bash'><span class='o'>(</span>gdb<span class='o'>)</span> print change_display<span class='o'>(</span><span class='s2'>&quot;192.168.1.2:0&quot;</span><span class='o'>)</span> </code></pre> </div> <p>If we now quickly move our cursor over to the window of the application. After a few seconds the window should successfully move to the proper display.</p> <p>Pretty easy huh? :D There are plenty more things you can achieve with simple code injection like this, and for the purpose of this exercise, we could have written a GTK module instead. But this is just <em>cool</em>.</p> Mimicking Threading in PHP http://demonastery.org/61/mimicking-threading-in-php/ Sun, 03 Apr 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/61/mimicking-threading-in-php <p>People often criticize <a href='http://php.net'>PHP</a> for not having the ability to use <a href='http://en.wikipedia.org/wiki/Thread_(computer_science'>threading</a>), which is a fair point and quite often a drawback. Here I am presenting a method for mimicking threads through <a href='http://en.wikipedia.org/wiki/Fork_(operating_system'>forking</a>) of the PHP interpreter. This may not work as well on a Windows system since AFAIK forks are more expensive there than on unix (<em>I would love to be proven wrong however!</em>). You will also need to make sure that you have the <code>extension=sockets.so</code> somewhere in your <strong>php.ini</strong>.</p> <p>The code is very simple and short, it works using socket IPC and PHP serialization:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='k'>function</span> <span class='nf'>async</span><span class='p'>(</span><span class='nv'>$thunk</span><span class='p'>)</span> <span class='p'>{</span> <span class='c1'>// By creating a socket pair, we have a channel of communication</span> <span class='c1'>// between PHP processes</span> <span class='nb'>socket_create_pair</span><span class='p'>(</span><span class='nx'>AF_UNIX</span><span class='p'>,</span> <span class='nx'>SOCK_STREAM</span><span class='p'>,</span> <span class='mi'>0</span><span class='p'>,</span> <span class='nv'>$sockets</span><span class='p'>);</span> <span class='k'>list</span><span class='p'>(</span><span class='nv'>$parent</span><span class='p'>,</span> <span class='nv'>$child</span><span class='p'>)</span> <span class='o'>=</span> <span class='nv'>$sockets</span><span class='p'>;</span> <span class='k'>if</span> <span class='p'>((</span><span class='nv'>$pid</span> <span class='o'>=</span> <span class='nb'>pcntl_fork</span><span class='p'>())</span> <span class='o'>==</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>{</span> <span class='c1'>// We&#39;re in the child process now</span> <span class='nb'>socket_close</span><span class='p'>(</span><span class='nv'>$child</span><span class='p'>);</span> <span class='c1'>// Call the thunk, serialize the returned value, and send it</span> <span class='c1'>// through the channel we created (ie. to the parent process)</span> <span class='nb'>socket_write</span><span class='p'>(</span><span class='nv'>$parent</span><span class='p'>,</span> <span class='nb'>serialize</span><span class='p'>(</span><span class='nb'>call_user_func</span><span class='p'>(</span><span class='nv'>$thunk</span><span class='p'>)));</span> <span class='nb'>socket_close</span><span class='p'>(</span><span class='nv'>$parent</span><span class='p'>);</span> <span class='k'>exit</span><span class='p'>;</span> <span class='c1'>// We&#39;re done so we can exit here</span> <span class='p'>}</span> <span class='nb'>socket_close</span><span class='p'>(</span><span class='nv'>$parent</span><span class='p'>);</span> <span class='k'>return</span> <span class='k'>array</span><span class='p'>(</span><span class='nv'>$pid</span><span class='p'>,</span> <span class='nv'>$child</span><span class='p'>);</span> <span class='c1'>// This can treated as a &quot;thread handle&quot;</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>wait</span><span class='p'>(</span><span class='nv'>$proc</span><span class='p'>)</span> <span class='p'>{</span> <span class='nb'>pcntl_waitpid</span><span class='p'>(</span><span class='nv'>$proc</span><span class='p'>[</span><span class='mi'>0</span><span class='p'>],</span> <span class='nv'>$status</span><span class='p'>);</span> <span class='c1'>// Wait for the process to finish</span> <span class='c1'>// Read the data from the channel, and then unserialize it into</span> <span class='c1'>// a PHP object that can be returned</span> <span class='nv'>$output</span> <span class='o'>=</span> <span class='nb'>unserialize</span><span class='p'>(</span><span class='nb'>socket_read</span><span class='p'>(</span><span class='nv'>$proc</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>],</span> <span class='mi'>4096</span><span class='p'>));</span> <span class='nb'>socket_close</span><span class='p'>(</span><span class='nv'>$proc</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>return</span> <span class='nv'>$output</span><span class='p'>;</span> <span class='p'>}</span> </code></pre> </div> <p>And to use it is just as simple:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='nv'>$thread</span> <span class='o'>=</span> <span class='nx'>async</span><span class='p'>(</span><span class='k'>function</span> <span class='p'>()</span> <span class='p'>{</span> <span class='c1'>// Note that variables can be passed through with the &quot;use&quot; construct</span> <span class='c1'>// (ie. $thread = async(function() use($local_var) { ...</span> <span class='nb'>sleep</span><span class='p'>(</span><span class='mi'>2</span><span class='p'>);</span> <span class='c1'>// to show that we really are running asynchronously</span> <span class='k'>echo</span> <span class='s2'>&quot;Hello from Child Thread!</span><span class='se'>\n</span><span class='s2'>&quot;</span><span class='p'>;</span> <span class='k'>return</span> <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;hello&#39;</span><span class='p'>,</span> <span class='s1'>&#39;world!&#39;</span><span class='p'>);</span> <span class='p'>});</span> <span class='k'>echo</span> <span class='s2'>&quot;Hello from Main Thread</span><span class='se'>\n</span><span class='s2'>&quot;</span><span class='p'>;</span> <span class='nv'>$output</span> <span class='o'>=</span> <span class='nx'>wait</span><span class='p'>(</span><span class='nv'>$thread</span><span class='p'>);</span> <span class='nb'>print_r</span><span class='p'>(</span><span class='nv'>$output</span><span class='p'>);</span> <span class='c1'>// Prints:</span> <span class='c1'>//</span> <span class='c1'>// Hello from Main Thread</span> <span class='c1'>// (and then 2 seconds later)</span> <span class='c1'>// Hello from Child Thread</span> <span class='c1'>// Array</span> <span class='c1'>// (</span> <span class='c1'>// [0] =&gt; hello</span> <span class='c1'>// [1] =&gt; world!</span> <span class='c1'>// )</span> </code></pre> </div> <p>Feel free to rip this and use it in your own projects! The original code was pulled out from my <a href='https://github.com/ZaneA/ProtoIRC/blob/master/protoirc.php#L175'>ProtoIRC framework</a>, a small framework for prototyping IRC bots and utilities.</p> Chicken Scheme, and OpenGL http://demonastery.org/60/chicken-scheme-and-opengl/ Sat, 02 Apr 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/60/chicken-scheme-and-opengl <p>Today I&#8217;m posting an example of how you can quickly get started with <a href='http://en.wikipedia.org/wiki/OpenGL'>OpenGL</a> using <a href='http://call-cc.org'>Chicken Scheme</a>.</p> <p>I am posting the code in full, but I have commented it pretty well and so everything should be quite simple to understand.</p> <p>Unless you take out the texture rendering, you will probably want to get <a href='http://www.lonesock.net/soil.html'>SOIL</a> for your distribution (Archers can get it with <code>sudo pacman -S soil</code>).</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;;;</span> <span class='c1'>;;; Lets make a simple OpenGL application using Chicken Scheme!</span> <span class='c1'>;;; Thanks to all the egg authors and Chicken Scheme contributors for making this awesomeness possible!</span> <span class='c1'>;;;</span> <span class='c1'>;; Firstly, lets include the eggs that we will use.</span> <span class='c1'>;; These are the OpenGL and GLUT eggs (for display),</span> <span class='c1'>;; and the Inline egg (described below).</span> <span class='c1'>;; These can each be installed using the &quot;chicken-install&quot; command</span> <span class='p'>(</span><span class='nf'>use</span> <span class='nv'>gl</span> <span class='nv'>glut</span> <span class='nv'>inline</span><span class='p'>)</span> <span class='c1'>;; Now we will define some variables that we will reference later in our code</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>screen-w</span> <span class='mi'>800</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>screen-h</span> <span class='mi'>600</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>mouse-x</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>mouse-y</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>background-color</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='mi'>0</span> <span class='mi'>0</span> <span class='mi'>0</span> <span class='mi'>0</span><span class='p'>))</span> <span class='c1'>;; Using the wonderful inline egg, we can embed some C code directly into the</span> <span class='c1'>;; Scheme source and it will be compiled, cached and bound automatically, even</span> <span class='c1'>;; while using the interpreter! We&#39;re going to use this functionality to add</span> <span class='c1'>;; the ability to load textures into OpenGL using the wonderful SOIL library</span> <span class='c1'>;; Protip: If you select the lines inside inline in Emacs, you can use the</span> <span class='c1'>;; M-x narrow-to-region to show just the C code, and if you use M-x c-mode you</span> <span class='c1'>;; can even edit with your regular C keybindings. When you&#39;re done just use</span> <span class='c1'>;; M-x widen and then M-x scheme-mode to get back to normal. Emacs is awesome!</span> <span class='p'>(</span><span class='nf'>inline</span> <span class='o'>#</span><span class='nv'>&lt;&lt;EOF</span> <span class='nv'>//</span> <span class='nv'>The</span> <span class='k'>define </span><span class='nv'>guard</span> <span class='nv'>stops</span> <span class='nv'>Chicken</span> <span class='nv'>from</span> <span class='nv'>trying</span> <span class='nv'>to</span> <span class='nv'>read</span> <span class='k'>and </span><span class='nv'>parse</span> <span class='nv'>SOIL</span><span class='o'>.</span><span class='nv'>h</span> <span class='o'>#</span><span class='nv'>ifndef</span> <span class='nv'>CHICKEN</span> <span class='o'>#</span><span class='nv'>include</span> <span class='nv'>&lt;SOIL</span><span class='o'>.</span><span class='nv'>h&gt;</span> <span class='o'>#</span><span class='nv'>endif</span> <span class='nv'>//</span> <span class='nv'>A</span> <span class='nv'>simple</span> <span class='nv'>wrapper</span> <span class='nv'>to</span> <span class='nv'>load</span> <span class='nv'>an</span> <span class='nv'>OpenGL</span> <span class='nv'>texture</span> <span class='nv'>using</span> <span class='nv'>SOIL</span> <span class='nv'>with</span> <span class='nv'>sane</span> <span class='nv'>parameters</span> <span class='nv'>unsigned</span> <span class='nv'>int</span> <span class='nv'>LoadGLTexture</span><span class='p'>(</span><span class='nf'>char</span> <span class='nv'>*path</span><span class='p'>)</span> <span class='err'>{</span> <span class='nv'>return</span> <span class='nv'>SOIL_load_OGL_texture</span><span class='p'>(</span><span class='nf'>path,</span> <span class='nv'>SOIL_LOAD_AUTO,</span> <span class='nv'>SOIL_CREATE_NEW_ID,</span> <span class='nv'>SOIL_FLAG_POWER_OF_TWO</span> <span class='nv'>|</span> <span class='nv'>SOIL_FLAG_INVERT_Y</span> <span class='nv'>|</span> <span class='nv'>SOIL_FLAG_MULTIPLY_ALPHA</span> <span class='nv'>|</span> <span class='nv'>SOIL_FLAG_COMPRESS_TO_DXT</span> <span class='nv'>|</span> <span class='nv'>SOIL_FLAG_DDS_LOAD_DIRECT</span> <span class='nv'>|</span> <span class='nv'>SOIL_FLAG_TEXTURE_REPEATS</span><span class='p'>)</span><span class='c1'>;</span> <span class='err'>}</span> <span class='nv'>//</span> <span class='nv'>Bind</span> <span class='nv'>the</span> <span class='nv'>usleep</span> <span class='nv'>function</span> <span class='nv'>available</span> <span class='nv'>on</span> <span class='nv'>POSIX</span> <span class='nv'>systems</span><span class='o'>.</span> <span class='nv'>//</span> <span class='nv'>on</span> <span class='nv'>Win32</span> <span class='nv'>systems,</span> <span class='nv'>the</span> <span class='s'>&quot;Sleep&quot;</span> <span class='nv'>function</span> <span class='nv'>is</span> <span class='nv'>equivalent</span> <span class='nv'>int</span> <span class='nv'>usleep</span><span class='p'>(</span><span class='nf'>unsigned</span> <span class='nv'>int</span> <span class='nv'>ms</span><span class='p'>)</span><span class='c1'>;</span> <span class='nv'>EOF</span> <span class='s'>&quot;-lSOIL&quot;</span> <span class='c1'>; Arguments to be provided to compiler and linker</span> <span class='p'>)</span> <span class='c1'>;; This is one of those use cases I talked about in my call-cc article.</span> <span class='c1'>;; It provides the ability to break to a REPL by hitting the spacebar</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>return</span> <span class='no'>#f</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>break-to-repl</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>printf</span> <span class='s'>&quot;~nType (return) to resume rendering~n&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>call/cc</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>k</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>set! </span><span class='nv'>return</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>()</span> <span class='p'>(</span><span class='nf'>k</span> <span class='no'>#f</span><span class='p'>)))</span> <span class='p'>(</span><span class='nf'>repl</span><span class='p'>))))</span> <span class='c1'>;; Now we&#39;re going to define two simple functions that can be used when </span> <span class='c1'>;; coding our demos in OpenGL. This includes basic text display and the</span> <span class='c1'>;; drawing of a textured quad. Pretty simple but should serve as a good</span> <span class='c1'>;; starting point for creating your own stuff!</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>draw-text</span> <span class='nv'>text</span> <span class='nv'>x</span> <span class='nv'>y</span> <span class='o'>#</span><span class='nv'>!key</span> <span class='p'>(</span><span class='nf'>color</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='mi'>1</span> <span class='mi'>1</span> <span class='mi'>1</span> <span class='mi'>1</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>apply </span><span class='nv'>gl:Color4f</span> <span class='nv'>color</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:PushAttrib</span> <span class='nv'>gl:ENABLE_BIT</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Disable</span> <span class='nv'>gl:TEXTURE_2D</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:RasterPos2f</span> <span class='nv'>x</span> <span class='nv'>y</span><span class='p'>)</span> <span class='c1'>;; The cut macro is something I&#39;ve only just discovered. It essentially returns a function made</span> <span class='c1'>;; from the parameters provided, however &lt;&gt; is replaced with the argument that is passed to it</span> <span class='p'>(</span><span class='nf'>string-for-each</span> <span class='p'>(</span><span class='nf'>cut</span> <span class='nv'>glut:BitmapCharacter</span> <span class='nv'>glut:BITMAP_8_BY_13</span> <span class='nv'>&lt;&gt;</span><span class='p'>)</span> <span class='nv'>text</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:PopAttrib</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>draw-quad</span> <span class='nv'>t</span> <span class='nv'>x</span> <span class='nv'>y</span> <span class='nv'>w</span> <span class='nv'>h</span> <span class='o'>#</span><span class='nv'>!key</span> <span class='p'>(</span><span class='nf'>color</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='mi'>1</span> <span class='mi'>1</span> <span class='mi'>1</span> <span class='mi'>1</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>apply </span><span class='nv'>gl:Color4f</span> <span class='nv'>color</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:BindTexture</span> <span class='nv'>gl:TEXTURE_2D</span> <span class='nv'>t</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Begin</span> <span class='nv'>gl:QUADS</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:TexCoord2f</span> <span class='mi'>1</span> <span class='mi'>1</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Vertex2f</span> <span class='nv'>x</span> <span class='nv'>y</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:TexCoord2f</span> <span class='mi'>1</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Vertex2f</span> <span class='nv'>x</span> <span class='p'>(</span><span class='nb'>+ </span><span class='nv'>y</span> <span class='nv'>h</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>gl:TexCoord2f</span> <span class='mi'>0</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Vertex2f</span> <span class='p'>(</span><span class='nb'>+ </span><span class='nv'>x</span> <span class='nv'>w</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>+ </span><span class='nv'>y</span> <span class='nv'>h</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>gl:TexCoord2f</span> <span class='mi'>0</span> <span class='mi'>1</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Vertex2f</span> <span class='p'>(</span><span class='nb'>+ </span><span class='nv'>x</span> <span class='nv'>w</span><span class='p'>)</span> <span class='nv'>y</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:End</span><span class='p'>))</span> <span class='c1'>;; Now it&#39;s time to do the actual set up. We&#39;re going to define the</span> <span class='c1'>;; functions we need to open the display and handle any events through</span> <span class='c1'>;; callback functions we give to GLUT</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>setup-display</span><span class='p'>)</span> <span class='c1'>; These lines take care of setting up the GLUT window</span> <span class='p'>(</span><span class='nf'>glut:InitDisplayMode</span> <span class='p'>(</span><span class='nf'>bitwise-ior</span> <span class='nv'>glut:DOUBLE</span> <span class='nv'>glut:RGBA</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>glut:InitWindowSize</span> <span class='nv'>screen-w</span> <span class='nv'>screen-h</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>glut:CreateWindow</span> <span class='s'>&quot;Chicken Scheme OpenGL | Hit space for REPL&quot;</span><span class='p'>)</span> <span class='c1'>; Enable texturing and set background color</span> <span class='p'>(</span><span class='nf'>gl:Enable</span> <span class='nv'>gl:TEXTURE_2D</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:TexEnvf</span> <span class='nv'>gl:TEXTURE_ENV</span> <span class='nv'>gl:TEXTURE_ENV_MODE</span> <span class='nv'>gl:MODULATE</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>apply </span><span class='nv'>gl:ClearColor</span> <span class='nv'>background-color</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Enable</span> <span class='nv'>gl:BLEND</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:BlendFunc</span> <span class='nv'>gl:ONE</span> <span class='nv'>gl:ONE</span><span class='p'>)</span> <span class='c1'>; Set up a basic 2D orthogonal projection</span> <span class='p'>(</span><span class='nf'>gl:MatrixMode</span> <span class='nv'>gl:PROJECTION</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:LoadIdentity</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Ortho</span> <span class='mi'>0</span> <span class='nv'>screen-w</span> <span class='nv'>screen-h</span> <span class='mi'>0</span> <span class='mi'>-1</span> <span class='mi'>1</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:MatrixMode</span> <span class='nv'>gl:MODELVIEW</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>keyboard-handler</span> <span class='nv'>key</span> <span class='nv'>x</span> <span class='nv'>y</span><span class='p'>)</span> <span class='c1'>; If escape is pressed exit.</span> <span class='c1'>; If space is pressed then break to REPL</span> <span class='p'>(</span><span class='k'>cond </span><span class='p'>((</span><span class='nb'>eq? </span><span class='nv'>key</span> <span class='sc'>#\esc</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>exit</span><span class='p'>))</span> <span class='p'>((</span><span class='nb'>eq? </span><span class='nv'>key</span> <span class='sc'>#\space</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>break-to-repl</span><span class='p'>))))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>idle-handler</span><span class='p'>)</span> <span class='c1'>; Sleep for 100 microseconds to give up CPU time</span> <span class='p'>(</span><span class='nf'>usleep</span> <span class='mi'>100</span><span class='p'>)</span> <span class='c1'>; And then redisplay</span> <span class='p'>(</span><span class='nf'>glut:PostRedisplay</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>display-handler</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Clear</span> <span class='p'>(</span><span class='nf'>bitwise-ior</span> <span class='nv'>gl:DEPTH_BUFFER_BIT</span> <span class='nv'>gl:COLOR_BUFFER_BIT</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>gl:LoadIdentity</span><span class='p'>)</span> <span class='c1'>;; Here&#39;s where the drawing happens, so this is probably where</span> <span class='c1'>;; you&#39;ll spend most of your time hacking around. All that</span> <span class='c1'>;; this demo does however is draw a texture that follows the</span> <span class='c1'>;; cursor around the screen.</span> <span class='p'>(</span><span class='nf'>draw-text</span> <span class='s'>&quot;Hello, OpenGL World!&quot;</span> <span class='mi'>10</span> <span class='mi'>20</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>gl:Translatef</span> <span class='mi'>-50</span> <span class='mi'>-50</span> <span class='mi'>0</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>draw-quad</span> <span class='nv'>texture</span> <span class='nv'>mouse-x</span> <span class='nv'>mouse-y</span> <span class='mi'>100</span> <span class='mi'>100</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>glut:SwapBuffers</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>passive-motion-handler</span> <span class='nv'>x</span> <span class='nv'>y</span><span class='p'>)</span> <span class='c1'>; Update the mouse x and y positions</span> <span class='p'>(</span><span class='k'>set! </span><span class='nv'>mouse-x</span> <span class='nv'>x</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>set! </span><span class='nv'>mouse-y</span> <span class='nv'>y</span><span class='p'>))</span> <span class='c1'>;; Cool, now we&#39;re ready to run!</span> <span class='p'>(</span><span class='nf'>setup-display</span><span class='p'>)</span> <span class='c1'>; Load a texture</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>texture</span> <span class='p'>(</span><span class='nf'>LoadGLTexture</span> <span class='s'>&quot;circle_gradient.tga&quot;</span><span class='p'>))</span> <span class='c1'>; Hook up GLUT events</span> <span class='p'>(</span><span class='nf'>glut:KeyboardFunc</span> <span class='nv'>keyboard-handler</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>glut:PassiveMotionFunc</span> <span class='nv'>passive-motion-handler</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>glut:IdleFunc</span> <span class='nv'>idle-handler</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>glut:DisplayFunc</span> <span class='nv'>display-handler</span><span class='p'>)</span> <span class='c1'>; Start the GLUT mainloop, which runs until exit</span> <span class='p'>(</span><span class='nf'>glut:MainLoop</span><span class='p'>)</span> </code></pre> </div> <p>Make sure you have a texture of some sort sitting in the same directory as the code. I was using <strong>circular_gradient.tga</strong>.</p> <p>If you now run this using <code>csi example.csm</code>, you should see a window popup with some text and a simple quad that follows the mouse cursor. If you hit the <strong>spacebar</strong> the rendering will pause and you will see a REPL in the terminal you launched it from. Inside the REPL you can potentially transform the render loop and do other such fun things. As a simple idea of what you can achieve, make sure you have another texture sitting in the example directory, and then type the following in the REPL:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='k'>set! </span><span class='nv'>texture</span> <span class='p'>(</span><span class='nf'>LoadGLTexture</span> <span class='s'>&quot;newtexture.tga&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>return</span><span class='p'>)</span> </code></pre> </div> <p>If all goes well, your render loop should continue, with the old texture replaced by the new one you just loaded. Pretty nifty!</p> <p><em>In a future follow-up to this post I will have a go at adding FreeType font rendering, and using OpenAL for sound, so stay tuned!</em></p> Acer Aspire ONE D255E http://demonastery.org/59/acer-aspire-one-d255e/ Sun, 27 Mar 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/59/acer-aspire-one-d255e <p>A week ago I went searching for a small netbook. My requirements were pretty simple; it needed to be cheap, and be able to dual boot Linux and Windows 7. Because I&#8217;m in New Zealand, the first place I checked out was <a href='http://dse.co.nz'>Dick Smith Electronics</a>, which currently had a great special running on the Acer Aspire ONE D255E (<strong>$399 NZD</strong>, roughly <strong>$300 USD</strong>). Now the specs listed on the site were actually false, but the actual specs of the laptop are higher.</p> <p>The machine uses the Intel Atom N455 processor, which is a dual core CPU running at 1.66GHz. It has 1GB of DDR3 memory, a 250GB Hard Drive (non-SSD of course), 10.1&#8221; LED LCD at 1024x600 (which is tiny, but well suited to a window manager such as <a href='http://www.nongnu.org/ratpoison/'>ratpoison</a>. The VGA port also handles my 1920x1080 display with no trouble), and comes with Windows 7 Starter edition. These specs seem reasonable to me, and I&#8217;m used to getting the most out of my hardware. For interest sake, the machine also has a built-in webcam, 2-in-1 card reader, 802 11b/g/n Wifi (Atheros), a Synaptics touchpad that has basic multi-touch support, and a 3-cell Li-ion battery that gives roughly 4 hours of battery life (can also upgrade to a 6-cell). This particular machine has no bluetooth, although it seems to be an optional extra (along with internal 3G), and of course no optical drive.</p> <p>The first thing I did when I unboxed this machine (after installing the battery) was format the hard drive (<em>Windows 7 starter is plenty capable, but it&#8217;s not for me</em>). After getting a hold of an external optical drive I proceeded to install Windows 7 Ultimate on it, giving Win7 about 60GB of space, using a single partition only (there&#8217;s a trick to getting rid of the <em>System Reserved partition</em>, but it&#8217;s a pretty simple one). Once installed, I booted the machine up, and surprise surprise, there&#8217;s pretty much nil driver support for this thing using the built-in Win7 drivers. Even VGA was limited to 800x600. Luckily I have an extra machine on standby that I was able to use to download some drivers. Unfortunately this system is new enough that the drivers are only just hitting the net, and I wasn&#8217;t able to find the correct ones on the Acer site itself (If you want the names and download locations, ask in the comments). But after spending a couple of hours finding the correct ones, it was up and running smoothly.</p> <p>Next on the list was getting Debian installed. For this I used the non-free net-install Debian Testing ISO, which is great because it includes non-free Wifi firmware. The downside is that the Debian installer doesn&#8217;t support WPA encryption, even though it is available after. So I was forced to use the ethernet port for installing. I had some issues with Grub but I think that was down to user error, not a fault of Debian itself. Debian was also given 60GB to play with, split 50/50 between / and /home.</p> <p>Unlike Windows, Debian either detected or had the appropriate drivers handy after a first boot which was great. After installing X with the Intel driver, KMS appears to be working, and everything else works great including wifi (using the ath9k driver), battery, and temperature status. Suspend/resume seems to be set up correctly, although I haven&#8217;t actually tried it out yet. The Synaptics touchpad needs some tuning in Xorg.conf to work, but once that&#8217;s done it works better than it does in Windows, and you can even set up circular scrolling and coasting, yee-haw!.</p> <p>Overall the system isn&#8217;t as fast as what I&#8217;m used to, but it <em>is</em> very capable and is perfect for what I will use it for (web development, and Scheme hacking). Plus it&#8217;s the perfect size for a CarPC (I&#8217;m in the process of writing a nice <a href='http://mpd.wikia.com'>MusicPD</a> client now) ;)</p> <p>I would definitely recommend the Aspire ONE D255E to anyone else on the hunt for a cheap netbook.</p> <p><em>While I&#8217;m at it, if anyone has some suggestions for Scheme (or PHP) tutorials they would like to see then let me know in the comments (you can see them by clicking on the post title). I love putting them together but I find it hard to decide what to write about.</em></p> A Newbie Guide to Call/cc http://demonastery.org/58/a-newbie-guide-to-call-cc/ Mon, 14 Mar 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/58/a-newbie-guide-to-call-cc <p>I haven&#8217;t had much to write about in the last couple of weeks, but I&#8217;ve really wanted to do a small piece on the magic of <a href='http://en.wikipedia.org/wiki/Call-with-current-continuation'>call-with-current-continuation</a> in Scheme, aka. <strong>call/cc</strong>.</p> <p>For some reason I had a difficult time wrapping my head around this little statement, even though it isn&#8217;t terribly complicated at all (from an end coder perspective that is; I don&#8217;t want to imagine the headaches it causes for the compiler hackers ;)). For all intents and purposes, you can think of <strong>call/cc</strong> as a glorified <em>return</em> or a smart <em>goto</em> statement (and that is how it will sound when I try to explain it).</p> <p><em>But first of all, what is this continuation thing?</em></p> <p>You can think of a continuation as <em>an object that represents the position of execution in a running program</em>. If we call a continuation object as though it were a function, we will jump to that position in the program, and continue the flow from there.</p> <p>If we want to store a continuation we call the function <code>call-with-current-continuation</code> (shortened to <code>call/cc</code> in many Scheme implementations). This function takes a single argument, of a lambda to call.. with the current continuation.. An example is below:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='nf'>print</span> <span class='p'>(</span><span class='nb'>call/cc </span><span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>k</span><span class='p'>)</span> <span class='c1'>; k is used as a convention for a continuation variable as far as I understand</span> <span class='c1'>; We can do whatever we want here, it&#39;s just a regular function</span> <span class='c1'>; Lets return some text</span> <span class='s'>&quot;Hello, World&quot;</span><span class='p'>)))</span> </code></pre> </div> <p>This example will simply print &#8220;Hello, World&#8221; to the console. Now to show the mighty magic of continuations:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='nf'>print</span> <span class='p'>(</span><span class='nb'>call/cc </span><span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>k</span><span class='p'>)</span> <span class='c1'>; Pretend we are doing some processing here,</span> <span class='c1'>; perhaps looping over a list looking for something.</span> <span class='c1'>; Now pretend that we&#39;ve found what we&#39;re looking for.</span> <span class='c1'>; We are going to call the continuation with a value.</span> <span class='p'>(</span><span class='nf'>k</span> <span class='s'>&quot;We found the value man!&quot;</span><span class='p'>)</span> <span class='c1'>; And now this is placed after the loop</span> <span class='s'>&quot;Didn&#39;t find what we were looking for.&quot;</span> <span class='p'>)))</span> </code></pre> </div> <p>When <code>(k &quot;We found the value man!&quot;)</code> is called, we jump back to our continuation (ie. the place of <code>(call/cc)</code> and return the value passed to <code>k</code> back to <code>print</code>. So of course our example will print &#8220;We found the value man!&#8221; to the console.</p> <p>This is pretty much all that there is to know about continuations. As you can see it is really a way to allow functional programs to terminate from a function early.</p> <p>There are a wide variety of uses though, depending on how you dress up call/cc. A cool example comes from the in development <a href='http://github.com/sgrove/tehila'>Tehila</a> Scheme game engine, which simplified looks a little like this:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; Called when the Spacebar is hit</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>break-to-repl</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>printf</span> <span class='s'>&quot;Type (return) to resume gameplay~n&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>call/cc </span><span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>k</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>set! </span><span class='nv'>return</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>()</span> <span class='p'>(</span><span class='nf'>k</span> <span class='no'>#f</span><span class='p'>)))</span> <span class='c1'>; So the user can call (return) instead of (k #f)</span> <span class='p'>(</span><span class='nf'>repl</span><span class='p'>))))</span> <span class='c1'>; Call the built in REPL</span> </code></pre> </div> <p>This allows the user to hit Spacebar mid-game to get a REPL, which will pause the game. When they wish to continue, they simply enter <code>(return)</code> into the console, and the game continues from where it left off.</p> <p>Another good use of continuations is for implementing <a href='http://en.wikipedia.org/wiki/Exception_handling'>exceptions</a>. For example if you take the <a href='http://wiki.call-cc.org/eggref/4/srfi-34'>SRFI-34</a> (Exception Handling) egg available for Chicken Scheme, you can think of the <code>guard</code> construct as being <em>call/cc</em>, and the <code>raise</code> statement as being <code>(k &#39;myexception)</code>.</p> <p>So that&#8217;s it for my newbie guide to <code>call-with-current-continuation</code>. I hope this cleared it up for someone, and I hope that you now understand call/cc enough to make some cool things happen with it!</p> <p><em>Edit: DerGuteMoritz points out in the comments that you can also call continuations more than once, and gives an example:</em></p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='k'>define </span><span class='nv'>foo</span> <span class='no'>#f</span><span class='p'>)</span> <span class='p'>(</span><span class='nb'>display </span><span class='p'>(</span><span class='nb'>string-append </span><span class='p'>(</span><span class='nb'>call/cc </span><span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>k</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>set! </span><span class='nv'>foo</span> <span class='nv'>k</span><span class='p'>)</span> <span class='s'>&quot;foo&quot;</span><span class='p'>))</span> <span class='s'>&quot;\n&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>foo</span> <span class='s'>&quot;baz&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>foo</span> <span class='s'>&quot;qux&quot;</span><span class='p'>)</span> </code></pre> </div> <p>Which will print:</p> <div class='highlight'><pre><code class='text'>foo baz qux </code></pre> </div> A Scheme Infix Transformer http://demonastery.org/57/a-scheme-infix-transformer/ Tue, 08 Mar 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/57/a-scheme-infix-transformer <p>As promised in the last post, I am going to share an <a href='http://en.wikipedia.org/wiki/Infix_notation'>infix</a> function, that takes a list that looks like <code>(1 + (2 * 3))</code> and turns it into <code>(+ 1 (* 2 3))</code> (<a href='http://en.wikipedia.org/wiki/Prefix_notation'>Prefix</a>).</p> <p>Creating this function was a perfect place to start playing with <a href='http://en.wikipedia.org/wiki/Unit_testing'>Unit Testing</a> as well. Something that I have not used much of until now.</p> <p>Unit testing is really useful in this situation. We can write a tiny test that checks if our <code>infix/lr</code> (lr because it parses left to right, not that it matters) function gives the appropriate result. That test will look like this:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; Load the lightweight unit testing unit</span> <span class='p'>(</span><span class='nf'>use</span> <span class='nv'>srfi-78</span><span class='p'>)</span> <span class='c1'>; And write the test</span> <span class='p'>(</span><span class='nf'>check</span> <span class='p'>(</span><span class='nf'>infix/lr</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='mi'>1</span> <span class='nv'>+</span> <span class='p'>(</span><span class='mi'>2</span> <span class='nv'>*</span> <span class='mi'>3</span><span class='p'>)</span> <span class='nv'>+</span> <span class='mi'>4</span><span class='p'>))</span> <span class='c1'>; Check that this</span> <span class='k'>=&gt; </span> <span class='c1'>; matches</span> <span class='o'>&#39;</span><span class='p'>(</span><span class='nv'>+</span> <span class='p'>(</span><span class='nb'>+ </span><span class='mi'>1</span> <span class='p'>(</span><span class='nb'>* </span><span class='mi'>2</span> <span class='mi'>3</span><span class='p'>))</span> <span class='mi'>4</span><span class='p'>))</span> <span class='c1'>; this</span> </code></pre> </div> <p>If all goes well, once the function is written the test should pass.</p> <p>Here&#8217;s the complete function itself:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; Parses an infix list into a prefix list</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>infix/lr</span> <span class='nv'>lst</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>when</span> <span class='p'>(</span><span class='nb'>even? </span><span class='p'>(</span><span class='nb'>length </span><span class='nv'>lst</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>error</span> <span class='s'>&quot;Wrong number of arguments to infix operator&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='k'>let </span><span class='nv'>loop</span> <span class='p'>((</span><span class='nf'>n</span> <span class='p'>(</span><span class='nf'>first</span> <span class='nv'>lst</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>lst</span> <span class='p'>(</span><span class='nb'>cdr </span><span class='nv'>lst</span><span class='p'>)))</span> <span class='p'>(</span><span class='k'>if </span><span class='p'>(</span><span class='nb'>not </span><span class='p'>(</span><span class='nb'>null? </span><span class='nv'>lst</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>loop</span> <span class='p'>(</span><span class='nb'>list </span><span class='p'>(</span><span class='nf'>first</span> <span class='nv'>lst</span><span class='p'>)</span> <span class='nv'>n</span> <span class='p'>(</span><span class='k'>if </span><span class='p'>(</span><span class='nb'>list? </span><span class='p'>(</span><span class='nf'>second</span> <span class='nv'>lst</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>infix/lr</span> <span class='p'>(</span><span class='nf'>second</span> <span class='nv'>lst</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>second</span> <span class='nv'>lst</span><span class='p'>)))</span> <span class='p'>(</span><span class='nf'>drop</span> <span class='nv'>lst</span> <span class='mi'>2</span><span class='p'>))</span> <span class='nv'>n</span><span class='p'>)))</span> </code></pre> </div> <p>I firmly believe this can be written to look (and probably function) better than it currently is (<em>Edit: Using regular let instead of letrec now</em>), but I&#8217;m still learning. Notice I also check the number of arguments; if it is an even number this means we will be missing a value at the end, since obviously we need 3 items to perform the swap (two values and an operator).</p> <p>So that is the function part taken care of, and this should be perfectly usable as is, but we can take this a step further by binding it to a read macro. This part is really up to you, here&#8217;s how I do it:</p> <p>And now we have an infix macro that can be used for easy calculations!</p> <p>One word of warning though, this function does not take into account operator precedence (to keep it simple) and so you are required to use parentheses to enforce precedence.</p> <p>And of course because we&#8217;re simply swapping lists around, it is perfectly possible to infix <em>any</em> scheme function that takes two arguments.</p> <p>Enjoy! :)</p> An Intro to Scheme Macros http://demonastery.org/56/an-intro-to-scheme-macros/ Mon, 07 Mar 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/56/an-intro-to-scheme-macros <p>In this post I want to go a little deeper into the <a href='http://en.wikipedia.org/wiki/Macro_%28computer_science%29'>macro</a> system of Scheme (particularly Chicken), and share a couple of macros I&#8217;ve created.</p> <p>First of all, macros are what make Scheme and Lisp so exciting. Macros offer the ability to evaluate code at <em>compile</em> time, and modify the structure of a program <em>before it even runs</em>. You can think of it as a really really powerful <code>#define</code>, but where #define lets you modify text, a Lisp macro lets you modify the code structure itself.</p> <p>There are a couple of different kinds of macro available in Scheme, and as I&#8217;m somewhat of a young schemer I&#8217;m not completely sure which are available across all implementations and which are only available in Chicken. But I will assume that the macros here can be ported with relative ease.</p> <p>The first kind, looks a lot like a regular ol&#8217; function. It is even called like a function, only when this macro is read it leaves behind whatever it returns. Here&#8217;s an annotated example:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; Here we are going to create a new macro called &quot;return-me&quot;</span> <span class='c1'>; that will simply return in a list whatever is passed to it</span> <span class='p'>(</span><span class='k'>define-syntax </span><span class='nv'>return-me</span> <span class='p'>(</span><span class='k'>syntax-rules </span><span class='p'>()</span> <span class='c1'>; Any symbols placed in this list will be ignored</span> <span class='err'>[</span><span class='p'>(</span><span class='nf'>return-me</span> <span class='nv'>body</span> <span class='o'>...</span><span class='p'>)</span> <span class='c1'>; This is what the arguments should look like</span> <span class='p'>(</span><span class='nb'>list </span><span class='nv'>body</span> <span class='o'>...</span><span class='p'>)</span><span class='err'>]</span><span class='p'>))</span> <span class='c1'>; And this is how they should be transformed</span> <span class='c1'>; Example</span> <span class='p'>(</span><span class='nf'>return-me</span> <span class='s'>&quot;Hello&quot;</span> <span class='s'>&quot;World&quot;</span><span class='p'>)</span> <span class='k'>=&gt; </span><span class='p'>(</span><span class='s'>&quot;Hello&quot;</span> <span class='s'>&quot;World&quot;</span><span class='p'>)</span> </code></pre> </div> <p>As you can see, it&#8217;s nothing terribly complicated, but it opens up a world of possibilities. Extending on this previous example, I will show you a &#8220;run&#8221; macro, which gives a nice interface to launching applications through SSH and receiving the output:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; Firstly, we need a couple of extra units loaded</span> <span class='p'>(</span><span class='nf'>use</span> <span class='nv'>posix</span> <span class='nv'>regex</span> <span class='nv'>regex-literals</span><span class='p'>)</span> <span class='c1'>; This is a shell function which calls the supplied argument and</span> <span class='c1'>; returns the result in a list of lines</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>shell</span> <span class='nv'>args</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>call-with-input-pipe</span> <span class='nv'>args</span> <span class='nv'>read-lines</span><span class='p'>))</span> <span class='c1'>; The run macro itself</span> <span class='p'>(</span><span class='k'>define-syntax </span><span class='nv'>run</span> <span class='p'>(</span><span class='k'>syntax-rules </span><span class='p'>(</span><span class='nf'>as</span> <span class='nv'>on</span><span class='p'>)</span> <span class='c1'>; We want to ignore the words &quot;as&quot; and &quot;on&quot;</span> <span class='err'>[</span><span class='p'>(</span><span class='nf'>run</span> <span class='nv'>command</span> <span class='nv'>as</span> <span class='nv'>username</span> <span class='nv'>on</span> <span class='nv'>machine</span><span class='p'>)</span> <span class='c1'>; Here is the full macro</span> <span class='c1'>; This line extracts the host and port from the &quot;machine&quot; part</span> <span class='p'>(</span><span class='k'>let </span><span class='p'>(</span><span class='err'>[</span><span class='nv'>matches</span> <span class='p'>(</span><span class='nf'>string-match</span> <span class='o'>#</span><span class='nv'>/</span><span class='p'>(</span><span class='o'>.</span><span class='nv'>*?</span><span class='p'>)</span><span class='nv'>:</span><span class='p'>(</span><span class='o'>.</span><span class='nv'>+</span><span class='p'>)</span><span class='nv'>/</span> <span class='nv'>machine</span><span class='p'>)</span><span class='err'>]</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>when</span> <span class='p'>(</span><span class='nb'>list? </span><span class='nv'>matches</span><span class='p'>)</span> <span class='c1'>; Got some matches</span> <span class='p'>(</span><span class='nf'>shell</span> <span class='p'>(</span><span class='nf'>format</span> <span class='s'>&quot;ssh -C -p ~a ~a@~a ~a&quot;</span> <span class='p'>(</span><span class='nf'>third</span> <span class='nv'>matches</span><span class='p'>)</span> <span class='c1'>; Port</span> <span class='nv'>username</span> <span class='p'>(</span><span class='nf'>second</span> <span class='nv'>matches</span><span class='p'>)</span> <span class='c1'>; Machine</span> <span class='nv'>command</span><span class='p'>))))</span><span class='err'>]</span> <span class='c1'>; Cool, return the output</span> <span class='c1'>; Here we have a smaller version of the macro with some defaults</span> <span class='err'>[</span><span class='p'>(</span><span class='nf'>run</span> <span class='nv'>command</span> <span class='nv'>on</span> <span class='nv'>machine</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>run</span> <span class='nv'>command</span> <span class='nv'>as</span> <span class='p'>(</span><span class='nf'>getenv</span> <span class='s'>&quot;USERNAME&quot;</span><span class='p'>)</span> <span class='nv'>on</span> <span class='nv'>machine</span><span class='p'>)</span><span class='err'>]</span> <span class='c1'>; And same again here, but avoid the SSH step in this case</span> <span class='err'>[</span><span class='p'>(</span><span class='nf'>run</span> <span class='nv'>command</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>shell</span> <span class='nv'>command</span><span class='p'>)</span><span class='err'>]</span><span class='p'>))</span> <span class='c1'>; Example</span> <span class='p'>(</span><span class='nf'>run</span> <span class='s'>&quot;uname -a&quot;</span> <span class='nv'>as</span> <span class='s'>&quot;zanea&quot;</span> <span class='nv'>on</span> <span class='s'>&quot;pr0d:2222&quot;</span><span class='p'>)</span> <span class='k'>=&gt; </span><span class='p'>(</span><span class='s'>&quot;Linux pr0d 2.6 etc..&quot;</span><span class='p'>)</span> </code></pre> </div> <p>So as you can see we have already created our very own (albeit small) <a href='http://en.wikipedia.org/wiki/Domain-specific_language'>Domain Specific Language</a> used to describe how to run a command on another machine.</p> <p>The second kind of macro I&#8217;m going to introduce is the <em>read macro</em>. A read macro gives you the ability to control how the Scheme reader understands syntax. A very small example follows:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>; This example simply makes !sym become (not sym)</span> <span class='c1'>; The lambda expression is triggered whenever a &quot;!&quot; is encountered</span> <span class='p'>(</span><span class='nf'>set-read-syntax</span> <span class='sc'>#\!</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>port</span><span class='p'>)</span> <span class='o'>`</span><span class='p'>(</span><span class='nb'>not </span><span class='o'>,</span><span class='p'>(</span><span class='nb'>read </span><span class='nv'>port</span><span class='p'>))))</span> </code></pre> </div> <p>A very small example indeed, but it shows something useful.</p> <p>So I hope you&#8217;ve enjoyed this small intro to Scheme Macros.. In the next episode I&#8217;ll be showing another rather simple macro that allows you to use <em>infix</em> expressions (ie. 1 + 2 + 3) inside your programs&#8230; stay tuned..</p> A Brief Foray into Haskell http://demonastery.org/55/a-brief-foray-into-haskell/ Sun, 06 Mar 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/55/a-brief-foray-into-haskell <p>I&#8217;ve tried to learn <a href='http://haskell.org'>Haskell</a> in the past and found it completely horrible to look at. That was, until I got around to learning Scheme and decided to look deeper into it.</p> <p>A couple of nights ago a friend showed me a small piece of Haskell code which reads a series of lines formatted like this:</p> <div class='highlight'><pre><code class='text'>a 1 b 2 c 3 </code></pre> </div> <p>And sums up the second column. The code looks like this:</p> <div class='highlight'><pre><code class='haskell'><span class='nf'>foldl1</span> <span class='p'>(</span><span class='o'>+</span><span class='p'>)</span> <span class='p'>(</span><span class='n'>map</span> <span class='p'>(</span><span class='nf'>\</span><span class='n'>c</span> <span class='ow'>-&gt;</span> <span class='n'>read</span> <span class='p'>(</span><span class='n'>c</span> <span class='o'>!!</span> <span class='mi'>1</span><span class='p'>))</span> <span class='p'>(</span><span class='n'>map</span> <span class='n'>words</span> <span class='p'>(</span><span class='n'>lines</span> <span class='s'>&quot;a 1</span><span class='se'>\n</span><span class='s'>b 2</span><span class='se'>\n</span><span class='s'>c 3&quot;</span><span class='p'>)))</span> </code></pre> </div> <p>At first glance, I was at a total loss as to what was going on. So I fumbled around in ghci for a while figuring out what each part was doing.</p> <p>It took me a while to realise that both <code>words</code> and <code>lines</code> are builtins, and this alone cleared the picture up quite significantly.</p> <p>The other part I had major trouble with was the <code>!!</code>, and google was somewhat unhelpful at first, but it is basically the Haskell equivalent of <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='nb'>list-ref </span><span class='nv'>c</span> <span class='mi'>1</span><span class='p'>)</span> </code></pre> </div></p> <p>aka the array subscript operator.</p> <p>Now it&#8217;s starting to come together in my head. The line basically reads as (from right to left):</p> <p>Split the string &#8220;a 1\nb 2\nc 3&#8221; into a list of lines, and then for each of the lines, split the line into separate words. Now, for each of these lines, create a lambda that reads the list of words in the line, and &#8220;read&#8221; the second item (this causes the string &#8220;1&#8221; to become the integer 1) and return it. Finally, now that we have a list of integers, Fold them to the left using the &#8221;+&#8221; function. The result is 6.</p> <p>The translation into Scheme is quite easy too, if we define a couple of small helper functions:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='k'>define </span><span class='nv'>read/s</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>c</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>with-input-from-string</span> <span class='nv'>c</span> <span class='nv'>read</span><span class='p'>)))</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>words</span> <span class='nv'>string-split</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>lines</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>str</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>string-split</span> <span class='nv'>str</span> <span class='s'>&quot;\n&quot;</span><span class='p'>)))</span> <span class='c1'>; Now the actual translation (which has the same number of characters as the Haskell version!)</span> <span class='p'>(</span><span class='nf'>fold</span> <span class='nv'>+</span> <span class='mi'>0</span> <span class='p'>(</span><span class='nb'>map </span><span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>c</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>read/s</span> <span class='p'>(</span><span class='nf'>second</span> <span class='nv'>c</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>map </span><span class='nv'>words</span> <span class='p'>(</span><span class='nf'>lines</span> <span class='s'>&quot;a 1\nb 3\nc 3&quot;</span><span class='p'>))))</span> </code></pre> </div> <p>Just understanding this small piece of Haskell has made me curious about using it further. The idea that originally drove me away from it (the conciseness, which makes it hard to read at first), turns out to be its simplicity. Much the same as with Scheme.</p> Quake 2 Hacking http://demonastery.org/54/quake-2-hacking/ Sun, 20 Feb 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/54/quake-2-hacking <p><a href='http://i.imgur.com/60zIh.jpg'><img alt='http://i.imgur.com/60zIhm.jpg' src='http://i.imgur.com/60zIhm.jpg' /></a></p> <p>Quake 2 (aka <a href='http://en.wikipedia.org/wiki/Quake_II_engine'>id Tech 2</a>) is a great game and engine to hack. The source is pretty well laid out and the code is small enough that it doesn&#8217;t take forever to become familiar with it. It also has a great entity system that makes it a really suitable for prototyping.</p> <p>I spent the last couple of nights stripping as much of the game code as I could out, right down to the essentials, and then stripping the game data down to the bare minimum as well. I built a plain cube map with a single info_null entity, that gets loaded on startup, acting as a gateway map. The info_null entity contains a &#8220;model&#8221; key, which loads an arbitrary md2 from disk (in this case, some couch model I found online).</p> <p>Next I set about embedding Chicken Scheme into the game code as an interpreter, and a few thousand segfaults later, it works! I have output redirection and an &#8220;eval&#8221; command for the console, allowing you to type some code and get a response.</p> <p>I also started on a high level API for controlling in game objects that I will just implement as I go, that looks a little like this:</p> <div class='highlight'><pre><code class='scheme'><span class='p'>(</span><span class='nf'>q2:fire-blaster</span> <span class='p'>(</span><span class='nf'>q2:get-player-by-name</span> <span class='s'>&quot;Player&quot;</span><span class='p'>))</span> </code></pre> </div> <p>So for just a couple hours of work I have a decent engine and scripting language that can be built up in whatever direction I decide to go with it :D</p> Sawfish Theme, GperfectionHash http://demonastery.org/53/sawfish-theme-gperfectionhash/ Thu, 17 Feb 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/53/sawfish-theme-gperfectionhash <p><img alt='http://fc00.deviantart.net/fs70/i/2011/047/a/3/gperfection_hash_for_sawfish_by_hashbox-d39pm73.png' src='http://fc00.deviantart.net/fs70/i/2011/047/a/3/gperfection_hash_for_sawfish_by_hashbox-d39pm73.png' />Just a simple modern SawfishWM theme I made, modified from gperfection.</p> <p>There is a dark version (named perfection-hash), and a light version (named gperfection-hash-light), to suit dark and light GTK themes (not included).</p> <p>Font in title is <strong>&#8220;Helvetica Neue Bold 7&#8221;</strong>.</p> <p>To download, head over to <a href='http://hashbox.deviantart.com/art/Gperfection-Hash-for-Sawfish-197710239'>http://hashbox.deviantart.com/art/Gperfection-Hash-for-Sawfish-197710239</a>.</p> <p>To install, unzip inside <code>~/.sawfish/themes/</code> and select gperfection-hash(light) in Sawfish configuration.</p> <p>Have fun!</p> Chicken Scheme, and FFI http://demonastery.org/52/chicken-scheme-and-ffi/ Mon, 31 Jan 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/52/chicken-scheme-and-ffi <p>As a follow up on yesterdays post I&#8217;m going to show how easy it is to integrate some third party functionality in to a web application to provide &#8220;automatic tagging&#8221; using <a href='http://libots.sourceforge.net'>libots</a>.</p> <p>To do this, we&#8217;re going to use the Chicken FFI. Now this example is really so short that there&#8217;s no point in splitting it into multiple blocks, so here we go:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; FFI example</span> <span class='p'>(</span><span class='nf'>import</span> <span class='nv'>foreign</span><span class='p'>)</span> <span class='c1'>; Add the libots header</span> <span class='p'>(</span><span class='nf'>foreign-declare</span> <span class='s'>&quot;#include &lt;libots-1/ots/libots.h&gt;&quot;</span><span class='p'>)</span> <span class='c1'>; Declare the function we&#39;re going to use</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>ots-text-topics</span> <span class='p'>(</span><span class='nf'>foreign-lambda</span> <span class='nv'>c-string</span> <span class='s'>&quot;ots_text_topics&quot;</span> <span class='nv'>c-string</span> <span class='nv'>c-string</span> <span class='nv'>int</span><span class='p'>))</span> <span class='c1'>; And here&#39;s another useful one</span> <span class='p'>(</span><span class='k'>define </span><span class='nv'>ots-summarize</span> <span class='p'>(</span><span class='nf'>foreign-lambda*</span> <span class='nv'>c-string*</span> <span class='p'>((</span><span class='nf'>c-string</span> <span class='nv'>str</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>int</span> <span class='nv'>percent</span><span class='p'>))</span> <span class='s'>&quot;OtsArticle* article = ots_new_article();</span> <span class='s'> ots_load_xml_dictionary(article, \&quot;en\&quot;);</span> <span class='s'> ots_parse_stream(str, strlen(str), article);</span> <span class='s'> ots_grade_doc(article);</span> <span class='s'> ots_highlight_doc(article, percent);</span> <span class='s'> size_t outlen = 0;</span> <span class='s'> char *text = ots_get_doc_text(article, &amp;outlen);</span> <span class='s'> ots_free_article(article);</span> <span class='s'> C_return(text);&quot;</span><span class='p'>))</span> </code></pre> </div> <p>And now to use it (the automatic tagging part):</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; OTS tagging</span> <span class='p'>(</span><span class='k'>let* </span><span class='p'>((</span><span class='nf'>num-tags</span> <span class='mi'>3</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>body</span> <span class='s'>&quot;This is the post you want to tag&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>tags</span> <span class='p'>(</span><span class='nf'>ots-text-topics</span> <span class='nv'>body</span> <span class='s'>&quot;en&quot;</span> <span class='nv'>num-tags</span><span class='p'>)))</span> <span class='p'>(</span><span class='nb'>display </span><span class='p'>(</span><span class='nb'>string-append </span><span class='s'>&quot;The tags found are: &quot;</span> <span class='nv'>tags</span><span class='p'>)))</span> </code></pre> </div> <p>Now all that&#8217;s left is to compile it:</p> <div class='highlight'><pre><code class='bash'>csc code.scm <span class='sb'>`</span>pkg-config --cflags --libs glib-2.0 libots-1 libxml-2.0<span class='sb'>`</span> </code></pre> </div> <p>That&#8217;s really all there is to it!</p> Chicken Scheme, and Web RAD http://demonastery.org/51/chicken-scheme-and-web-rad/ Sun, 30 Jan 2011 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/51/chicken-scheme-and-web-rad <p>Recently I&#8217;ve taken more of a liking to <a href='http://call-cc.org'>Chicken Scheme</a>, and started trying to use it for more of my day to day development. <a href='https://github.com/ZaneA/PongClock'>Recently I wrote a port</a> of a <a href='http://www.reddit.com/r/web_design/comments/f6xff/html5js_pong_clock/'>JS + HTML5 Pong Clock</a> into Chicken Scheme using the OpenGL + GLUT libraries. I couldn&#8217;t believe how smoothly it went, since it was a line by line port, the only thing I needed to write myself were the graphics drawing routines, easy enough since we&#8217;re only dealing with white rectangles after all, but now it functions as a cross platform screensaver (verified on Linux, OSX, and XP!).</p> <p>But the area I spend most of my time in is web development, so I was pleased to find the <a href='http://wiki.call-cc.org/eggref/4/awful?action=show'>Awful framework</a> for Chicken. Despite the name it is anything but. A simple usage example looks like this:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; Hello World!</span> <span class='p'>(</span><span class='nf'>use</span> <span class='nv'>awful</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>define-page</span> <span class='s'>&quot;/&quot;</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>()</span> <span class='s'>&quot;Hello, World!&quot;</span><span class='p'>))</span> </code></pre> </div> <p>Yes, it really is that easy. Of course you&#8217;ll most likely want to define your own template, and that is really easy to do too, my templates look something like this:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; Defining a template</span> <span class='p'>(</span><span class='k'>define-syntax </span><span class='nv'>define-templated-page</span> <span class='p'>(</span><span class='k'>syntax-rules </span><span class='p'>()</span> <span class='p'>((</span><span class='nf'>_</span> <span class='nv'>path</span> <span class='nv'>body</span> <span class='o'>...</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>define-page</span> <span class='nv'>path</span> <span class='p'>(</span><span class='k'>lambda </span><span class='p'>()</span> <span class='p'>(</span><span class='nf'>&lt;html&gt;</span> <span class='p'>(</span><span class='nf'>&lt;head&gt;</span> <span class='p'>(</span><span class='nf'>&lt;title&gt;</span> <span class='s'>&quot;Page Title&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>&lt;link&gt;</span> <span class='nv'>rel:</span> <span class='s'>&quot;stylesheet&quot;</span> <span class='nv'>href:</span> <span class='s'>&quot;/style.css&quot;</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>&lt;body&gt;</span> <span class='nv'>body</span> <span class='o'>...</span> <span class='p'>(</span><span class='nf'>include-javascript</span> <span class='s'>&quot;/jquery.min.js&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>&lt;script&gt;</span> <span class='nv'>type:</span> <span class='s'>&quot;text/javascript&quot;</span> <span class='s'>&quot;$(function () {</span> <span class='s'>// jQuery goes here</span> <span class='s'>});&quot;</span><span class='p'>))))</span> <span class='nv'>no-template:</span> <span class='no'>#t</span><span class='p'>))))</span> </code></pre> </div> <p>Which is then used like this:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; Templated Hello World!</span> <span class='p'>(</span><span class='nf'>define-templated-page</span> <span class='s'>&quot;/&quot;</span> <span class='p'>(</span><span class='nf'>&lt;h1&gt;</span> <span class='s'>&quot;Hello&quot;</span><span class='p'>)</span> <span class='p'>(</span><span class='nf'>&lt;h2&gt;</span> <span class='s'>&quot;World!&quot;</span><span class='p'>))</span> </code></pre> </div> <p>This is a good example of how scheme macros can simplify anything and everything. It has made defining a new page as easy as adding <strong>a single line</strong> of code.</p> <p>Combined with DB connectors and a multitude of other awesome libraries, Chicken Scheme and the power of macros really make for a wonderful rapid prototyping environment. With the ability to compile down to a static executable, this is my new favourite method of creating desktop applications that use a browser for presentation.</p> BLACK - Blog Engine http://demonastery.org/49/black-blog-engine/ Thu, 30 Dec 2010 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/49/black-blog-engine <p>As part of the migration of my blog to the Linode, I&#8217;ve cleaned up and restructured the code that powers this blog somewhat and made it available on <a href='http://github.com/ZaneA/Black'>Github</a> for others to use. Right now it is there more as a reason for me to keep improving it than anything else, since it needs some work.. but hopefully it will become useful enough for someone else to use it in the future.</p> <p>The &#8220;engine&#8221; revolves around the single function &#8220;post&#8221;. An example of its usage is below:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='nx'>black\post</span><span class='p'>(</span><span class='nv'>$query</span><span class='p'>,</span> <span class='k'>function</span> <span class='p'>(</span><span class='nv'>$post</span><span class='p'>,</span> <span class='nv'>$issingle</span><span class='p'>)</span> <span class='p'>{</span> <span class='cp'>?&gt;</span><span class='x' /> <span class='x'> &lt;a href=&quot;/</span><span class='cp'>&lt;?</span><span class='o'>=</span> <span class='nv'>$post</span><span class='p'>[</span><span class='s1'>&#39;id&#39;</span><span class='p'>]</span> <span class='cp'>?&gt;</span><span class='x'>/&quot;&gt;</span><span class='cp'>&lt;?</span><span class='o'>=</span> <span class='nv'>$post</span><span class='p'>[</span><span class='s1'>&#39;title&#39;</span><span class='p'>]</span> <span class='cp'>?&gt;</span><span class='x'>&lt;/a&gt;</span> <span class='x'> &lt;br /&gt;</span> <span class='x'> Posted on </span><span class='cp'>&lt;?</span><span class='o'>=</span> <span class='nb'>date</span><span class='p'>(</span><span class='s1'>&#39;l, F jS Y&#39;</span><span class='p'>,</span> <span class='nv'>$post</span><span class='p'>[</span><span class='s1'>&#39;timestamp&#39;</span><span class='p'>])</span> <span class='cp'>?&gt;</span><span class='x' /> <span class='x'> &lt;br /&gt;</span> <span class='x'> Tags for this post are </span><span class='cp'>&lt;?</span><span class='o'>=</span> <span class='nv'>$post</span><span class='p'>[</span><span class='s1'>&#39;tags&#39;</span><span class='p'>]</span> <span class='cp'>?&gt;</span><span class='x' /> <span class='x'> &lt;br /&gt;</span> <span class='x'> Aaaannnd the post itself:</span> <span class='x'> &lt;br /&gt;</span> <span class='x'> </span><span class='cp'>&lt;?</span><span class='o'>=</span> <span class='nv'>$post</span><span class='p'>[</span><span class='s1'>&#39;body&#39;</span><span class='p'>]</span> <span class='cp'>?&gt;</span><span class='x' /> <span class='x'> &lt;br /&gt;</span> <span class='x'> </span><span class='cp'>&lt;?php</span> <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$issingle</span><span class='p'>)</span><span class='o'>:</span> <span class='cp'>?&gt;</span><span class='x' /> <span class='x'> Viewing by post id, so insert Disqus commenting stuff here perhaps?</span> <span class='x'> </span><span class='cp'>&lt;?php</span> <span class='k'>endif</span> <span class='cp'>?&gt;</span><span class='x' /> <span class='cp'>&lt;?php</span> <span class='p'>})</span> <span class='cp'>?&gt;</span><span class='x' /> </code></pre> </div> <p>Added into an existing website template, the provided function will be called for each post you have, printing them all out to the page.</p> New Server http://demonastery.org/48/new-server/ Mon, 27 Dec 2010 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/48/new-server <p>My blog has been migrated successfully to my Linode, which meant moving from one httpd (<b>Apache</b>) to another (<b>Nginx</b>), transferring MySQL data, and rewriting the rewrites ;)</p> <p>So far so good. I wasn&#8217;t expecting it to go smoothly at all. In celebration I&#8217;ve gone through my old posts and deleted or edited stuff that wasn&#8217;t really relevant or interesting. So hopefully the average post quality has increased a bit :)</p> <p>Cheers for now! And a belated <b>Merry Christmas and Happy New Year</b> to everyone!</p> My Linode Experience http://demonastery.org/47/my-linode-experience/ Sun, 05 Dec 2010 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/47/my-linode-experience <p>As mentioned in a previous post, I have been using a <a href='http://www.linode.com/?r=57643aa6ca57ddd9b742224a9c028bc1fcd5ac2c'>Linode</a> for the past few months and I just want to say that the experience I&#8217;ve had has been perfect. I purchased a <strong>Linode 512</strong> and I&#8217;m using it to host a few small websites on a pretty generic <a href='http://blog.rubynginx.com/index.php/2010_01_20/configure-your-linode/'>Nginx + PHP5.3 FastCGI stack</a>, along with <a href='http://library.linode.com/lemp-guides/ubuntu-10.04-lucid/'>MySQL</a> and <a href='http://library.linode.com/email/exim/send-only-mta-ubuntu-10.04-lucid'>Exim (as a send only MTA</a>), and the whole setup sits comfortably in 50mb of memory and seems to perform well too (time will tell, I haven&#8217;t done any benchmarks). No special configuration has been needed other than setting up a basic directory layout for my <a href='http://github.com/ZaneA/BDSM'>BDSM</a> project, which takes care of pushing my websites from my development box.</p> <p><img alt='/images/Linode_logo.jpeg' src='/images/Linode_logo.jpeg' /></p> <p>I would highly recommended <a href='http://www.linode.com/?r=57643aa6ca57ddd9b742224a9c028bc1fcd5ac2c'>Linode</a> to anyone looking for a VPS, the support is amazingly quick, and the uptime is great; and if you use my referral link to sign up I can get some extra credits, so that would of course be much appreciated :)</p> HashTWM Musings http://demonastery.org/46/hashtwm-musings/ Sun, 07 Nov 2010 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/46/hashtwm-musings <p>I know there has been a lot of requests for features to be implemented or fixed in <a href='http://github.com/ZaneA/HashTWM'>HashTWM</a>. But the reality is, I&#8217;m barely using Windows anymore and so I don&#8217;t have an urgent need for HashTWM.</p> <p>Despite all the progress around other tiling window managers for Windows I still believe there is room for improvement though, so I am putting some effort into getting a rewrite off the ground. My idea is to get a solid foundation built up that (if anything) through the power of open source, someone will be able to take and hopefully build their dream TWM out of.</p> <p>So far the rewrite has the following implemented:</p> <ul> <li>List structure (groups, with each group holding a list of windows, and a tiling method) and core list manipulation functions.</li> <li>A keyhook that is used for all interaction, which supports key-chaining! (this was top priority for the rewrite. No more non-working keys!)</li> <li>A small status window that can be used to display messages, or show the state of the keyhook input, with a look and feel similar to Ratpoison.</li> <li>Window open/close/focus hooks all set up and mostly connected to the list functions.</li> <li>A debug console that can be opened/closed on demand, for watching the window list and other internals.</li> </ul> <p>Stuff that still needs to be done:</p> <ul> <li>Integration of a scripting language. I will probably go with Lua since I am familiar with embedding it and I haven&#8217;t yet found a lisp that is tiny enough or easy to embed.</li> <li>The ability to <b>actually tile windows</b>. I&#8217;ve decided that 100% of the window tiling code will be written in Lua, so being able to write your own tiling functions will be a top priority.</li> <li>Other miscellaneous scripting hooks, because I want this to actually be useful.</li> </ul> <p>So there you have it. I will be working on this a bit more on Monday, and I should have my current progress into a <a href='http://github.com/ZaneA/HackWM'>GitHub repository</a> by Tuesday.</p> <p>Cheers, Zane</p> Sawfish and Emacs/org-mode http://demonastery.org/45/sawfish-and-emacs-org-mode/ Wed, 27 Oct 2010 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/45/sawfish-and-emacs-org-mode <p>Hi there, today I&#8217;m going to write a small example on connecting the <a href='http://sawfish.wikia.com'>Sawfish window manager</a> to the <a href='http://gnu.org/software/emacs'>Emacs text editor</a>.</p> <p>Why might you want to do this? Well mostly I just wanted to further my usage of Emacs, and thought the idea of being able to clock in and out of tasks in <a href='http://orgmode.org'>org-mode</a> whenever I change workspace or window would be pretty cool. Of course both Sawfish and Emacs make extensive use of the <a href='http://en.wikipedia.org/wiki/Lisp_(programming_language'>Lisp programming language</a>) so it is a natural fit :)</p> <p>To start off, you&#8217;ll want to be using the Sawfish window manager, and you&#8217;ll want to have <code>emacs.jl</code> somewhere in your lisp path. From there you can put something like the following in your <code>~/.sawfish/rc</code>:</p> <div class='highlight'><pre><code class='cl'><span class='c1'>;; Require emacs.jl for emacs functions</span> <span class='p'>(</span><span class='nb'>require</span> <span class='ss'>&#39;emacs</span><span class='p'>)</span> <span class='c1'>;; Define a hook to be run on workspace change, utilizes the emacs-eval function defined in emacs.jl</span> <span class='p'>(</span><span class='nv'>define</span> <span class='p'>(</span><span class='nv'>my-enter-workspace-hook</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>emacs-eval</span> <span class='p'>(</span><span class='nb'>format</span> <span class='no'>nil</span> <span class='s'>&quot;(org-clock-in-on-workspace-change %S)&quot;</span> <span class='p'>(</span><span class='nb'>nth</span> <span class='nv'>current-workspace</span> <span class='nv'>workspace-names</span><span class='p'>))))</span> <span class='c1'>;; Add our hook!</span> <span class='p'>(</span><span class='nv'>add-hook</span> <span class='ss'>&#39;enter-workspace-hook</span> <span class='nv'>my-enter-workspace-hook</span><span class='p'>)</span> </code></pre> </div> <p>You will need to reload Sawfish for these changes to take effect (or you can eval them from Emacs).</p> <p>Our hook makes Sawfish tell Emacs to run the <code>org-clock-in-on-workspace-change</code> function, passing the workspace name to it. We will define this now, open up your <code>~/.emacs</code> and place this somewhere:</p> <div class='highlight'><pre><code class='cl'><span class='c1'>;; The function that Sawfish calls</span> <span class='p'>(</span><span class='nb'>defun</span> <span class='nv'>org-clock-in-on-workspace-change</span> <span class='p'>(</span><span class='nv'>workspace</span><span class='p'>)</span> <span class='p'>(</span><span class='nv'>org-clock-out</span> <span class='no'>t</span><span class='p'>)</span> <span class='c1'>; The t will silence the error that appears if no task is clocked</span> <span class='p'>(</span><span class='nv'>org-map-entries</span> <span class='c1'>; Loop over org headings</span> <span class='ss'>&#39;org-clock-in</span> <span class='c1'>; Clock in to this task ..</span> <span class='nv'>workspace</span> <span class='ss'>&#39;agenda</span><span class='p'>))</span> <span class='c1'>; .. if the tag has same name as current workspace</span> <span class='c1'>; Now press C-x C-e here to load this function into emacs</span> </code></pre> </div> <p>Now that this is done, we have what is needed for this to function, and in fact, if all has gone well, Sawfish should now be communicating and running this Emacs function each time you switch workspace!</p> <p>Now, to make this useful, open up one of your agenda files, and add a tag to it, such as <code>:Web:</code> or <code>:Emacs:</code> etc. When that workspace is switched to in Sawfish, the task will be clocked in and out of automatically!</p> <p>Hope you find this useful, I&#8217;m sure I will! :D</p> <p><strong>Edit:</strong> Changed to use workspace names instead of number. This can be coupled with the function below to quickly rename workspaces:</p> <div class='highlight'><pre><code class='scheme'><span class='c1'>;; Bind this to a key like (rename-workspace current-workspace (prompt #:title &quot;Workspace Name:&quot;))</span> <span class='p'>(</span><span class='k'>define </span><span class='p'>(</span><span class='nf'>rename-workspace</span> <span class='nv'>n</span> <span class='nv'>name</span><span class='p'>)</span> <span class='s'>&quot;Rename the Nth workspace to NAME&quot;</span> <span class='p'>(</span><span class='nf'>setq</span> <span class='nv'>workspace-names</span> <span class='p'>(</span><span class='k'>let </span><span class='p'>((</span><span class='nf'>i</span> <span class='mi'>-1</span><span class='p'>))</span> <span class='p'>(</span><span class='nf'>mapcar</span> <span class='o'>#&#39;</span><span class='p'>(</span><span class='k'>lambda </span><span class='p'>(</span><span class='nf'>item</span><span class='p'>)</span> <span class='p'>(</span><span class='k'>if </span><span class='p'>(</span><span class='nb'>= </span><span class='nv'>n</span> <span class='p'>(</span><span class='nf'>setq</span> <span class='nv'>i</span> <span class='p'>(</span><span class='mi'>1</span><span class='nv'>+</span> <span class='nv'>i</span><span class='p'>)))</span> <span class='nv'>name</span> <span class='nv'>item</span><span class='p'>))</span> <span class='nv'>workspace-names</span><span class='p'>))))</span> </code></pre> </div> Scheme-to-PHP http://demonastery.org/44/scheme-to-php/ Tue, 28 Sep 2010 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/44/scheme-to-php <p><img alt='/images/chicken.png' src='/images/chicken.png' /></p> <p>I&#8217;m writing this post to inform of my latest GitHub repo, <a href='http://github.com/ZaneA/scheme-to-php'>Scheme-to-PHP</a>, which contains the beginnings of a very very naive Scheme to PHP5 translator. It will do so by implementing r4rs (or maybe r5rs) forms and macros in Scheme, that return the equivalent strings of PHP code, hopefully forming a working PHP script. There will be a way of calling native PHP functions and classes, and Scheme functions such as <code>map</code> will be mapped (no pun intended) to the equivalent PHP function (eg. <code>array_map</code>).</p> <p>This is being written using <a href='http://call-cc.org'>Chicken Scheme</a>, which I&#8217;m currently spending most of my time hacking about with and is totally awesome :)</p> XMMSinatra http://demonastery.org/43/xmmsinatra/ Fri, 10 Sep 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/43/xmmsinatra <p>Last night I released the first version of <a href='http://github.com/ZaneA/XMMSinatra'>XMMSinatra</a>, a tiny and minimal XMMS2 web client written in Sinatra (Ruby). You can find the code and a screenshot at the <a href='http://github.com/ZaneA/XMMSinatra'>Github repository</a>.</p> <p><a href='/images/xmmsinatra.png'><img alt='/images/xmmsinatra_thumb.png' src='/images/xmmsinatra_thumb.png' /></a></p> Hackfest Weekend http://demonastery.org/42/hackfest-weekend/ Wed, 01 Sep 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/42/hackfest-weekend <p>Back from a really fun hacking weekend in Wellington, where I met some new people (and fellow hackers) and got to work on a project integrating <a href='http://threadingbuildingblocks.org'>TBB</a> further into the <a href='http://github.com/facebook/hiphop-php'>HipHop-PHP</a> compiler (and exposing it to PHP), which can be found at <a href='http://github.com/OpenParallel'>Github</a>. We made some pretty good progress and came up with a few pretty graphs.</p> <p>As mentioned in the last post, I have decided to purchase a <a href='http://linode.com'>Linode VPS</a> for a couple of months to try it out, and so far I am super impressed with the overall service. I will be using it mainly as a LNMP (Linux, Nginx, MySQL, PHP) host and so far it is doing the job well. I will also be spending the coming months looking further into <a href='http://rubyonrails.org'>RoR</a>, Perl, a couple of NoSQL servers (<a href='http://couchdb.apache.org'>CouchDB</a>, <a href='http://code.google.com/p/redis/'>Redis</a>), and maybe a message passing framework or two. This will also give me a chance to play around with some monitoring systems, and some deployment systems, such as <a href='http://capify.org'>Capistrano</a>.</p> <p>As a side-note, anyone have any ideas of what to do with a bunch of Clickatell SMS credits? I have an account with plenty of credits but it&#8217;s sitting pretty stagnant at the moment.</p> <p>Also really looking forward to visiting Christchurch in the coming weeks. Haven&#8217;t been there in forever.</p> ProtoIRC http://demonastery.org/39/protoirc/ Fri, 09 Jul 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/39/protoirc <p>So I made a tiny and very hackable IRC bot/client base in PHP for rapid prototyping. Of course I threw it on <a href='http://github.com/ZaneA/ProtoIRC'>GitHub</a>. It makes heavy use of PHP &gt;= 5.3 closure support as well as regular expressions for defining just about everything. Basic knowledge of the IRC protocol is recommended. You can find more information in the README file in the previous link.</p> <p>Here is an example of what a minimal bot looks like:</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='k'>require</span><span class='p'>(</span><span class='s1'>&#39;protoirc.php&#39;</span><span class='p'>);</span> <span class='nv'>$irc</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>ProtoIRC</span><span class='p'>(</span><span class='s1'>&#39;nick@hostname:6667&#39;</span><span class='p'>,</span> <span class='k'>function</span> <span class='p'>(</span><span class='nv'>$irc</span><span class='p'>)</span> <span class='p'>{</span> <span class='c1'>// This code will run on connect</span> <span class='nv'>$irc</span><span class='o'>-&gt;</span><span class='na'>send</span><span class='p'>(</span><span class='s1'>&#39;JOIN #channel&#39;</span><span class='p'>);</span> <span class='p'>});</span> <span class='nv'>$irc</span><span class='o'>-&gt;</span><span class='na'>in</span><span class='p'>(</span><span class='s1'>&#39;/^:(.*)!~.* PRIVMSG (.*) :!echo (.*)/&#39;</span><span class='p'>,</span> <span class='k'>function</span> <span class='p'>(</span><span class='nv'>$irc</span><span class='p'>,</span> <span class='nv'>$nick</span><span class='p'>,</span> <span class='nv'>$channel</span><span class='p'>,</span> <span class='nv'>$args</span><span class='p'>)</span> <span class='p'>{</span> <span class='c1'>// Arguments are self documenting</span> <span class='nv'>$irc</span><span class='o'>-&gt;</span><span class='na'>send</span><span class='p'>(</span><span class='nv'>$channel</span><span class='p'>,</span> <span class='s2'>&quot;Echoing &#39;</span><span class='si'>{</span><span class='nv'>$args</span><span class='si'>}</span><span class='s2'>&#39; for you </span><span class='si'>{</span><span class='nv'>$nick</span><span class='si'>}</span><span class='s2'>&quot;</span><span class='p'>,</span> <span class='s1'>&#39;green&#39;</span><span class='p'>);</span> <span class='p'>});</span> <span class='c1'>// Also available is the ability to catch stdin, irc in, and irc out. Set up timers, and call functions asynchronously (fork/join).</span> <span class='nv'>$irc</span><span class='o'>-&gt;</span><span class='na'>go</span><span class='p'>();</span> </code></pre> </div> HashTWM Patch http://demonastery.org/38/hashtwm-patch/ Wed, 23 Jun 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/38/hashtwm-patch <p>This morning I woke up to find a patch waiting for me on GitHub that extends <a href='http://github.com/ZaneA/HashTWM'>HashTWM</a>&#8217;s primitive tag support with what appears to be a more full featured, dwm-like tag support. Thanks to <a href='http://github.com/gtellalov'>http://github.com/gtellalov</a> for this patch :)</p> <p>This is the beauty of open source :D</p> LibOrgParser Update http://demonastery.org/36/liborgparser-update/ Thu, 03 Jun 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/36/liborgparser-update <p>Today I brought my <a href='http://github.com/ZaneA/LibOrgParser'>LibOrgParser</a> repository up to date with my local copy, for the first time in a while since I&#8217;ve been rather slack with my local repository.. but hopefully I got everything. The new version brings reading and writing functionality, as well as a new API, and the OrgQL utility, which lets you run simple SQL like queries on an org-mode file, thanks to the SQLite library. Queries that look like this,</p> <div class='highlight'><pre><code class='sql'><span class='k'>SELECT</span> <span class='k'>ALL</span> <span class='k'>FROM</span> <span class='o'>/</span><span class='n'>home</span><span class='o'>/</span><span class='n'>hashbox</span><span class='o'>/</span><span class='n'>todo</span><span class='p'>.</span><span class='n'>org</span> <span class='k'>WHERE</span> <span class='n'>heading</span> <span class='k'>CONTAINS</span> <span class='n'>todo</span> </code></pre> </div> <p>Oh and I found this image I made a while ago, kinda neat I think :)</p> <p><img alt='/images/org-mode.jpg' src='/images/org-mode.jpg' /></p> <p>Add OrgQL to that, and that&#8217;s pretty much my todo list flow :)</p> <p><strong>Edit:</strong> Oh and while we&#8217;re at it, here&#8217;s a one liner bash function for opening links in a file:</p> <div class='highlight'><pre><code class='bash'><span class='k'>function </span>nav<span class='o'>()</span> <span class='o'>{</span> grep -ohE <span class='s2'>&quot;[[:alpha:]]*://[[:alnum:][:punct:]]*&quot;</span> <span class='nv'>$@</span> | <span class='k'>while </span><span class='nb'>read</span>; <span class='k'>do </span>xdg-open <span class='s2'>&quot;$REPLY&quot;</span>; <span class='k'>done</span>; <span class='o'>}</span> <span class='c'># use like this</span> nav todo.org someotherfile.txt </code></pre> </div> Misc Win32 Utilities http://demonastery.org/34/misc-win32-utilities/ Tue, 01 Jun 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/34/misc-win32-utilities <p>Just created a new git repository on GitHub for my <a href='http://github.com/ZaneA/Win32-Hacks'>Miscellaneous Win32 utilities</a>. Right now it just has my ExplorerGestures code, but I will be adding some more utilities as I find them on my hard drive.</p> <p><strong>Edit:</strong> Added some more utilities. Probably still more to come..</p> PrepFS http://demonastery.org/8/prepfs/ Mon, 31 May 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/8/prepfs <p>Been a while since I posted anything here, and it&#8217;s always good to have some fresh content, so I thought I&#8217;d post my latest creation PrepFS (Pre-process FS), a small utility FUSE filesystem, that enables preprocessing of files.</p> <p>My main motivation behind creating this, is enabling modified <code>.Xdefaults</code> dependent on running window manager, or machine it is being viewed from. An Example of usage would be something like this:</p> <p><code>~/.xinitrc</code></p> <div class='highlight'><pre><code class='bash'><span class='nv'>wm</span><span class='o'>=</span><span class='sb'>`</span><span class='nb'>echo</span> -e <span class='s2'>&quot;openbox\nxmonad&quot;</span> | dmenu<span class='sb'>`</span> prepfs ~/.dotfiles/prepfs -b ~/.dotfiles/real -pp <span class='s2'>&quot;gpp -D$wm -x \&quot;%s\&quot;&quot;</span> <span class='nb'>exec</span> <span class='nv'>$wm</span> </code></pre> </div> <p><code>~/.dotfiles/real/.Xdefaults</code></p> <div class='highlight'><pre><code class='bash'><span class='c'>#ifdef openbox</span> blah*blah: blah <span class='c'>#else</span> this*stuff: here <span class='c'>#endif</span> </code></pre> </div> <p>Then make sure <code>~/.Xdefaults</code> is symlinked to <code>~/.dotfiles/prepfs/.Xdefaults</code></p> <p>More information (including source) can be found here <a href='http://bbs.archlinux.org/viewtopic.php?pid=576680'>http://bbs.archlinux.org/viewtopic.php?pid=576680</a></p> MPD Class for PHP http://demonastery.org/33/mpd-class-for-php/ Mon, 31 May 2010 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/33/mpd-class-for-php <p>I&#8217;ve just been going through a couple of folders and I found a very basic PHP class I wrote to control the <a href='http://mpd.wikia.com/wiki/Music_Player_Daemon_Wiki'>Music Player Daemon</a>. Assuming the text protocol hasn&#8217;t changed much it should still work fine :)</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='cm'>/*</span> <span class='cm'> * Base MPDControl Class</span> <span class='cm'> * Provide functions for connecting and retrieving raw data from MPD</span> <span class='cm'> */</span> <span class='k'>class</span> <span class='nc'>MPDControl</span> <span class='p'>{</span> <span class='k'>var</span> <span class='nv'>$hostname</span><span class='p'>,</span> <span class='nv'>$port</span><span class='p'>,</span> <span class='nv'>$timeout</span><span class='p'>,</span> <span class='nv'>$socket</span><span class='p'>,</span> <span class='nv'>$errno</span><span class='p'>,</span> <span class='nv'>$errstr</span><span class='p'>;</span> <span class='k'>function</span> <span class='nf'>MPDControl</span><span class='p'>(</span><span class='nv'>$hostname</span> <span class='o'>=</span> <span class='s1'>&#39;localhost&#39;</span><span class='p'>,</span> <span class='nv'>$port</span> <span class='o'>=</span> <span class='s1'>&#39;6600&#39;</span><span class='p'>,</span> <span class='nv'>$timeout</span> <span class='o'>=</span> <span class='mi'>3</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>hostname</span> <span class='o'>=</span> <span class='nv'>$hostname</span><span class='p'>;</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>port</span> <span class='o'>=</span> <span class='nv'>$port</span><span class='p'>;</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>timeout</span> <span class='o'>=</span> <span class='nv'>$timeout</span><span class='p'>;</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>connect</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>socket</span> <span class='o'>=</span> <span class='o'>@</span><span class='nb'>fsockopen</span><span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>hostname</span><span class='p'>,</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>port</span><span class='p'>,</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>errno</span><span class='p'>,</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>errstr</span><span class='p'>,</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>timeout</span><span class='p'>);</span> <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>socket</span><span class='p'>)</span> <span class='p'>{</span> <span class='k'>return</span> <span class='k'>false</span><span class='p'>;</span> <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='k'>return</span> <span class='k'>true</span><span class='p'>;</span> <span class='p'>}</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>disconnect</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;close&#39;</span><span class='p'>);</span> <span class='nb'>fclose</span><span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>socket</span><span class='p'>);</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>getData</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$lines</span> <span class='o'>=</span> <span class='k'>Array</span><span class='p'>();</span> <span class='nv'>$line</span> <span class='o'>=</span> <span class='s1'>&#39;&#39;</span><span class='p'>;</span> <span class='k'>while</span> <span class='p'>((</span><span class='nx'>substr</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>,</span> <span class='mi'>0</span><span class='p'>,</span> <span class='mi'>2</span><span class='p'>)</span> <span class='o'>!=</span> <span class='s1'>&#39;OK&#39;</span><span class='p'>)</span> <span class='o'>&amp;&amp;</span> <span class='p'>(</span><span class='nx'>substr</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>,</span> <span class='mi'>0</span><span class='p'>,</span> <span class='mi'>3</span><span class='p'>)</span> <span class='o'>!=</span> <span class='s1'>&#39;ACK&#39;</span><span class='p'>))</span> <span class='p'>{</span> <span class='nv'>$line</span> <span class='o'>=</span> <span class='nb'>fgets</span><span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>socket</span><span class='p'>,</span> <span class='mi'>256</span><span class='p'>);</span> <span class='nv'>$lines</span><span class='p'>[]</span> <span class='o'>=</span> <span class='nv'>$line</span><span class='p'>;</span> <span class='p'>}</span> <span class='nb'>unset</span><span class='p'>(</span><span class='nv'>$lines</span><span class='p'>[</span><span class='nb'>count</span><span class='p'>(</span><span class='nv'>$lines</span><span class='p'>)</span><span class='o'>-</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>return</span> <span class='nv'>$lines</span><span class='p'>;</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>sendRaw</span><span class='p'>(</span><span class='nv'>$string</span><span class='p'>)</span> <span class='p'>{</span> <span class='nb'>fwrite</span><span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>socket</span><span class='p'>,</span> <span class='nv'>$string</span><span class='o'>.</span><span class='s2'>&quot;</span><span class='se'>\n</span><span class='s2'>&quot;</span><span class='p'>);</span> <span class='p'>}</span> <span class='p'>}</span> </code></pre> </div> <p>This is then complimented with a class that extends MPDControl.</p> <div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span> <span class='cm'>/*</span> <span class='cm'> * Extended version of MPDControl</span> <span class='cm'> * Provides function for getting commonly used info</span> <span class='cm'> */</span> <span class='k'>class</span> <span class='nc'>ExtendedMPDControl</span> <span class='k'>extends</span> <span class='nx'>MPDControl</span> <span class='p'>{</span> <span class='k'>function</span> <span class='nf'>getNowPlaying</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;currentsong&#39;</span><span class='p'>);</span> <span class='nv'>$song</span> <span class='o'>=</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$song</span> <span class='k'>as</span> <span class='nv'>$line</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$line</span> <span class='o'>=</span> <span class='nb'>explode</span><span class='p'>(</span><span class='s1'>&#39;:&#39;</span><span class='p'>,</span> <span class='nv'>$line</span><span class='p'>);</span> <span class='k'>switch</span> <span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>0</span><span class='p'>])</span> <span class='p'>{</span> <span class='k'>case</span> <span class='s1'>&#39;Artist&#39;</span><span class='o'>:</span> <span class='nv'>$artist</span> <span class='o'>=</span> <span class='nx'>trim</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>break</span><span class='p'>;</span> <span class='k'>case</span> <span class='s1'>&#39;Title&#39;</span><span class='o'>:</span> <span class='nv'>$title</span> <span class='o'>=</span> <span class='nx'>trim</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>break</span><span class='p'>;</span> <span class='p'>}</span> <span class='p'>}</span> <span class='k'>return</span> <span class='k'>Array</span><span class='p'>((</span><span class='k'>empty</span><span class='p'>(</span><span class='nv'>$artist</span><span class='p'>)</span> <span class='o'>?</span> <span class='s1'>&#39;None&#39;</span> <span class='o'>:</span> <span class='nv'>$artist</span><span class='p'>),</span> <span class='p'>(</span><span class='k'>empty</span><span class='p'>(</span><span class='nv'>$title</span><span class='p'>)</span> <span class='o'>?</span> <span class='s1'>&#39;None&#39;</span> <span class='o'>:</span> <span class='nv'>$title</span><span class='p'>));</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>randomOn</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;random 1&#39;</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>randomOff</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;random 0&#39;</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>play</span><span class='p'>(</span><span class='nv'>$id</span> <span class='o'>=</span> <span class='s1'>&#39;&#39;</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;play &#39;</span><span class='o'>.</span><span class='nv'>$id</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>stop</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;stop&#39;</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>clear</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;clear&#39;</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>remove</span><span class='p'>(</span><span class='nv'>$id</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;delete &#39;</span><span class='o'>.</span><span class='nv'>$id</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>add</span><span class='p'>(</span><span class='nv'>$path</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;add &quot;&#39;</span><span class='o'>.</span><span class='nv'>$path</span><span class='o'>.</span><span class='s1'>&#39;&quot;&#39;</span><span class='p'>);</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='p'>}</span> <span class='k'>function</span> <span class='nf'>getPlaylist</span><span class='p'>()</span> <span class='p'>{</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>sendRaw</span><span class='p'>(</span><span class='s1'>&#39;playlistinfo&#39;</span><span class='p'>);</span> <span class='nv'>$buffer</span> <span class='o'>=</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getData</span><span class='p'>();</span> <span class='nv'>$playpos</span> <span class='o'>=</span> <span class='o'>-</span><span class='mi'>1</span><span class='p'>;</span> <span class='nv'>$artist</span> <span class='o'>=</span> <span class='nv'>$album</span> <span class='o'>=</span> <span class='nv'>$title</span> <span class='o'>=</span> <span class='s1'>&#39;&#39;</span><span class='p'>;</span> <span class='nv'>$playlist</span> <span class='o'>=</span> <span class='k'>Array</span><span class='p'>();</span> <span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$buffer</span> <span class='k'>as</span> <span class='nv'>$line</span><span class='p'>)</span> <span class='p'>{</span> <span class='nv'>$line</span> <span class='o'>=</span> <span class='nb'>explode</span><span class='p'>(</span><span class='s1'>&#39;:&#39;</span><span class='p'>,</span> <span class='nv'>$line</span><span class='p'>);</span> <span class='k'>switch</span> <span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>0</span><span class='p'>])</span> <span class='p'>{</span> <span class='k'>case</span> <span class='s1'>&#39;Artist&#39;</span><span class='o'>:</span> <span class='nv'>$artist</span> <span class='o'>=</span> <span class='nx'>trim</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>break</span><span class='p'>;</span> <span class='k'>case</span> <span class='s1'>&#39;Album&#39;</span><span class='o'>:</span> <span class='nv'>$album</span> <span class='o'>=</span> <span class='nx'>trim</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>break</span><span class='p'>;</span> <span class='k'>case</span> <span class='s1'>&#39;Title&#39;</span><span class='o'>:</span> <span class='nv'>$title</span> <span class='o'>=</span> <span class='nx'>trim</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='k'>break</span><span class='p'>;</span> <span class='k'>case</span> <span class='s1'>&#39;Pos&#39;</span><span class='o'>:</span> <span class='c1'>// End of song output</span> <span class='nv'>$playlist</span><span class='p'>[</span><span class='nv'>$playpos</span><span class='o'>+</span><span class='mi'>1</span><span class='p'>]</span> <span class='o'>=</span> <span class='k'>Array</span><span class='p'>(</span><span class='nv'>$artist</span><span class='p'>,</span> <span class='nv'>$album</span><span class='p'>,</span> <span class='nv'>$title</span><span class='p'>);</span> <span class='nv'>$playpos</span> <span class='o'>=</span> <span class='nx'>trim</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>[</span><span class='mi'>1</span><span class='p'>]);</span> <span class='nv'>$artist</span> <span class='o'>=</span> <span class='nv'>$album</span> <span class='o'>=</span> <span class='nv'>$title</span> <span class='o'>=</span> <span class='s1'>&#39;&#39;</span><span class='p'>;</span> <span class='k'>break</span><span class='p'>;</span> <span class='p'>}</span> <span class='p'>}</span> <span class='k'>return</span> <span class='nv'>$playlist</span><span class='p'>;</span> <span class='p'>}</span> <span class='p'>}</span> <span class='cp'>?&gt;</span><span class='x' /> </code></pre> </div> <p>Consider this code to be in the public domain, so have fun with it!</p> ExplorerGestures http://demonastery.org/5/explorergestures/ Sat, 03 Oct 2009 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/5/explorergestures <p>So it&#8217;s <strong>2:56</strong> in the AM and I&#8217;ve just hacked up a little app to enable moving up a directory in Windows Explorer by using the Thunar <strong>middle click + drag up</strong> gesture. You can find it on my <a href='http://github.com/ZaneA'>Github</a>.</p> <p>Enjoy.</p> <p><strong>Edit:</strong> This morning I&#8217;ve extended it to have left and right gestures to go backward and forward respectively just like Thunar and Nautilus. Down is used for exit rather than refresh as Windows seems to take care of this.</p> Automatic agenda notification http://demonastery.org/25/automatic-agenda-notification/ Sat, 02 May 2009 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/25/automatic-agenda-notification <p>This article will show you how to utilize Emacs org-mode, python, a Nokia mobile (others may work too), and an SMS gateway like Clickatell, in order to receive a daily agenda that fits nicely into the phones calendar by using the vCalendar format. Yes that&#8217;s a fairly specialized combination, but hopefully will be useful to someone. I&#8217;m sure it&#8217;s possible to do the same using bluetooth instead of and SMS gateway, and I may update this to reflect that at some stage..</p> <p>Firstly, you will need org-mode set up and being utilized. Hopefully within it you will have something like:</p> <div class='highlight'><pre><code class='html'>* Write some code <span class='nt'>&lt;2009</span><span class='na'>-05-02</span> <span class='na'>Saturday</span> <span class='na'>3:00PM</span><span class='nt'>&gt;</span> * Write some more code <span class='nt'>&lt;2009</span><span class='na'>-05-02</span> <span class='na'>Saturday</span> <span class='na'>8:00PM</span><span class='nt'>&gt;</span> </code></pre> </div> <p>The idea is simple, we want some way of taking these headings, and turning them into vCalendar strings that can be sent to your phone.</p> <p>This first script is what I use to do just that:</p> <p><code>agenda.py</code></p> <div class='highlight'><pre><code class='python'><span class='c'>#!/usr/bin/env python</span> <span class='kn'>from</span> <span class='nn'>subprocess</span> <span class='kn'>import</span> <span class='n'>Popen</span><span class='p'>,</span><span class='n'>PIPE</span><span class='p'>;</span> <span class='kn'>from</span> <span class='nn'>time</span> <span class='kn'>import</span> <span class='n'>strftime</span><span class='p'>,</span> <span class='n'>strptime</span><span class='p'>;</span> <span class='kn'>from</span> <span class='nn'>sendsms</span> <span class='kn'>import</span> <span class='n'>sendsms</span><span class='p'>;</span> <span class='n'>dateformat</span> <span class='o'>=</span> <span class='s'>&quot;%Y%m</span><span class='si'>%d</span><span class='s'>T%H%M%S&quot;</span><span class='p'>;</span> <span class='n'>vcals</span> <span class='o'>=</span> <span class='p'>[];</span> <span class='n'>output</span> <span class='o'>=</span> <span class='n'>Popen</span><span class='p'>(</span><span class='s'>&quot;/usr/bin/emacs -batch -eval &#39;(org-batch-agenda-csv </span><span class='se'>\&quot;</span><span class='s'>a</span><span class='se'>\&quot;</span><span class='s'> org-agenda-ndays 1 org-agenda-show-all-dates t org-agenda-files `(,(expand-file-name </span><span class='se'>\&quot;</span><span class='s'>/full/path/to/your/org/file</span><span class='se'>\&quot;</span><span class='s'>)))&#39; 2&gt;/dev/null&quot;</span><span class='p'>,</span> <span class='n'>shell</span><span class='o'>=</span><span class='bp'>True</span><span class='p'>,</span> <span class='n'>stdout</span><span class='o'>=</span><span class='n'>PIPE</span><span class='p'>)</span><span class='o'>.</span><span class='n'>communicate</span><span class='p'>()[</span><span class='mi'>0</span><span class='p'>]</span><span class='o'>.</span><span class='n'>strip</span><span class='p'>();</span> <span class='k'>for</span> <span class='n'>line</span> <span class='ow'>in</span> <span class='n'>output</span><span class='o'>.</span><span class='n'>splitlines</span><span class='p'>():</span> <span class='p'>[</span><span class='n'>category</span><span class='p'>,</span> <span class='n'>head</span><span class='p'>,</span> <span class='nb'>type</span><span class='p'>,</span> <span class='n'>todo</span><span class='p'>,</span> <span class='n'>tags</span><span class='p'>,</span> <span class='n'>date</span><span class='p'>,</span> <span class='n'>time</span><span class='p'>,</span> <span class='n'>extra</span><span class='p'>,</span> <span class='n'>priorityl</span><span class='p'>,</span> <span class='n'>priorityn</span><span class='p'>,</span> <span class='n'>date2</span><span class='p'>]</span> <span class='o'>=</span> <span class='n'>line</span><span class='o'>.</span><span class='n'>split</span><span class='p'>(</span><span class='s'>&quot;,&quot;</span><span class='p'>);</span> <span class='k'>if</span> <span class='nb'>type</span> <span class='ow'>and</span> <span class='n'>time</span><span class='p'>:</span> <span class='k'>if</span> <span class='nb'>type</span> <span class='o'>==</span> <span class='s'>&quot;scheduled&quot;</span><span class='p'>:</span> <span class='n'>head</span> <span class='o'>=</span> <span class='s'>&quot;SCHEDULED, &quot;</span> <span class='o'>+</span> <span class='n'>head</span><span class='p'>;</span> <span class='k'>if</span> <span class='nb'>type</span> <span class='o'>==</span> <span class='s'>&quot;deadline&quot;</span><span class='p'>:</span> <span class='n'>head</span> <span class='o'>=</span> <span class='s'>&quot;DEADLINE, &quot;</span> <span class='o'>+</span> <span class='n'>head</span><span class='p'>;</span> <span class='n'>timestamp</span> <span class='o'>=</span> <span class='n'>strptime</span><span class='p'>(</span><span class='n'>date</span> <span class='o'>+</span> <span class='s'>&quot; &quot;</span> <span class='o'>+</span> <span class='n'>time</span><span class='p'>,</span> <span class='s'>&quot;%Y-%m-</span><span class='si'>%d</span><span class='s'> %H%M&quot;</span><span class='p'>);</span> <span class='n'>vcals</span><span class='o'>.</span><span class='n'>append</span><span class='p'>(</span><span class='s'>&quot;BEGIN:VCALENDAR</span><span class='se'>\n</span><span class='s'>VERSION:1.0</span><span class='se'>\n</span><span class='s'>BEGIN:VEVENT</span><span class='se'>\n</span><span class='s'>CATEGORIES:APPOINTMENT</span><span class='se'>\n</span><span class='s'>DTSTART:&quot;</span> <span class='o'>+</span> <span class='n'>strftime</span><span class='p'>(</span><span class='n'>dateformat</span><span class='p'>,</span> <span class='n'>timestamp</span><span class='p'>)</span> <span class='o'>+</span> <span class='s'>&quot;</span><span class='se'>\n</span><span class='s'>DTEND:&quot;</span> <span class='o'>+</span> <span class='n'>strftime</span><span class='p'>(</span><span class='n'>dateformat</span><span class='p'>,</span> <span class='n'>timestamp</span><span class='p'>)</span> <span class='o'>+</span> <span class='s'>&quot;</span><span class='se'>\n</span><span class='s'>SUMMARY:&quot;</span> <span class='o'>+</span> <span class='n'>head</span> <span class='o'>+</span> <span class='s'>&quot;</span><span class='se'>\n</span><span class='s'>DESCRIPTION:&quot;</span> <span class='o'>+</span> <span class='n'>head</span> <span class='o'>+</span> <span class='s'>&quot;</span><span class='se'>\n</span><span class='s'>END:VEVENT</span><span class='se'>\n</span><span class='s'>END:VCALENDAR&quot;</span><span class='p'>);</span> <span class='k'>for</span> <span class='n'>vcal</span> <span class='ow'>in</span> <span class='n'>vcals</span><span class='p'>:</span> <span class='n'>sendsms</span><span class='p'>(</span><span class='n'>vcal</span><span class='p'>,</span> <span class='s'>&quot;yourphonenumberhere&quot;</span><span class='p'>,</span> <span class='s'>&quot;SMS_NOKIA_VCAL&quot;</span><span class='p'>);</span> </code></pre> </div> <p>And here is the helper script to send sms through the Clickatell gateway:</p> <p><code>sendsms.py</code></p> <div class='highlight'><pre><code class='python'><span class='c'>#!/usr/bin/env python</span> <span class='c'># Script to send SMS via clickatell</span> <span class='kn'>import</span> <span class='nn'>urllib</span><span class='o'>,</span> <span class='nn'>urllib2</span><span class='p'>;</span> <span class='n'>username</span> <span class='o'>=</span> <span class='s'>&quot;put your Clickatell username here&quot;</span><span class='p'>;</span> <span class='n'>password</span> <span class='o'>=</span> <span class='s'>&quot;put your Clickatell password here&quot;</span><span class='p'>;</span> <span class='n'>api_id</span> <span class='o'>=</span> <span class='s'>&quot;put your Clickatell api id here&quot;</span><span class='p'>;</span> <span class='k'>def</span> <span class='nf'>sendsms</span><span class='p'>(</span><span class='n'>data</span><span class='p'>,</span> <span class='n'>number</span> <span class='o'>=</span> <span class='s'>&quot;yournumberhere&quot;</span><span class='p'>,</span> <span class='nb'>type</span> <span class='o'>=</span> <span class='s'>&quot;SMS_TEXT&quot;</span><span class='p'>):</span> <span class='n'>request</span> <span class='o'>=</span> <span class='s'>&quot;https://api.clickatell.com/http/sendmsg?user=&quot;</span> <span class='o'>+</span> <span class='n'>username</span> <span class='o'>+</span> <span class='s'>&quot;&amp;password=&quot;</span> <span class='o'>+</span> <span class='n'>password</span> <span class='o'>+</span> <span class='s'>&quot;&amp;api_id=&quot;</span> <span class='o'>+</span> <span class='n'>api_id</span> <span class='o'>+</span> <span class='s'>&quot;&amp;to=&quot;</span> <span class='o'>+</span> <span class='n'>number</span> <span class='o'>+</span> <span class='s'>&quot;&amp;msg_type=&quot;</span> <span class='o'>+</span> <span class='nb'>type</span> <span class='o'>+</span> <span class='s'>&quot;&amp;text=&quot;</span> <span class='o'>+</span> <span class='n'>urllib</span><span class='o'>.</span><span class='n'>quote_plus</span><span class='p'>(</span><span class='n'>data</span><span class='p'>);</span> <span class='n'>f</span> <span class='o'>=</span> <span class='n'>urllib2</span><span class='o'>.</span><span class='n'>urlopen</span><span class='p'>(</span><span class='n'>request</span><span class='p'>);</span> <span class='k'>print</span> <span class='n'>f</span><span class='o'>.</span><span class='n'>read</span><span class='p'>();</span> </code></pre> </div> <p>As long as this is in the same directory as <code>agenda.py</code> then it should import fine, otherwise you will want to move it into your Python PATH.</p> <p>Now all you need to do is add something like this to your crontab (use <code>crontab -e</code>):</p> <div class='highlight'><pre><code class='html'>15 7 * * * /path/to/agenda.py </code></pre> </div> <p>Make sure to replace everything in the scripts where necessary.</p> <p>Congratulations! Your PC should be ready to send your daily appointments to your phone at 7:15 every morning :)</p> I can haz assembly! http://demonastery.org/11/i-can-haz-assembly/ Mon, 20 Apr 2009 00:00:00 +1200 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/11/i-can-haz-assembly <p>Simple CPUID, I also experimented with a version using an extra buffer variable and <code>printf</code>. It may not be much to others but I&#8217;m learning!</p> <div class='highlight'><pre><code class='nasm'><span class='c1'>; CPUID</span> <span class='k'>section</span> <span class='nv'>.data</span> <span class='nl'>buffer:</span> <span class='kd'>db</span> <span class='s'>&quot;CPU Vendor ID: XXXXXXXXXXXX&quot;</span><span class='p'>,</span> <span class='mi'>10</span><span class='p'>,</span> <span class='mi'>0</span> <span class='nl'>bufferlen:</span> <span class='nf'>equ</span> <span class='kc'>$</span> <span class='o'>-</span> <span class='nv'>buffer</span> <span class='k'>section</span> <span class='nv'>.text</span> <span class='k'>global</span> <span class='nv'>_start</span> <span class='nl'>_start:</span> <span class='nf'>mov</span> <span class='nb'>eax</span><span class='p'>,</span> <span class='mi'>0</span> <span class='c1'>; &quot;Get maximum supported standard level and vendor ID string&quot;</span> <span class='k'>CPU</span><span class='nv'>ID</span> <span class='c1'>; Call CPUID</span> <span class='nf'>mov</span> <span class='p'>[</span><span class='nv'>buffer</span><span class='o'>+</span><span class='mi'>15</span><span class='p'>],</span> <span class='nb'>ebx</span> <span class='c1'>; Move 4 bytes from ebx to buffer+15</span> <span class='nf'>mov</span> <span class='p'>[</span><span class='nv'>buffer</span><span class='o'>+</span><span class='mi'>19</span><span class='p'>],</span> <span class='nb'>edx</span> <span class='c1'>; Move 4 bytes from edx to buffer+19</span> <span class='nf'>mov</span> <span class='p'>[</span><span class='nv'>buffer</span><span class='o'>+</span><span class='mi'>23</span><span class='p'>],</span> <span class='nb'>ecx</span> <span class='c1'>; Move 4 bytes from ecx to buffer+23</span> <span class='nf'>mov</span> <span class='nb'>eax</span><span class='p'>,</span> <span class='mi'>4</span> <span class='c1'>; write syscall</span> <span class='nf'>mov</span> <span class='nb'>ebx</span><span class='p'>,</span> <span class='mi'>1</span> <span class='c1'>; stdout</span> <span class='nf'>mov</span> <span class='nb'>ecx</span><span class='p'>,</span> <span class='nv'>buffer</span> <span class='c1'>; buffer</span> <span class='nf'>mov</span> <span class='nb'>edx</span><span class='p'>,</span> <span class='nv'>bufferlen</span> <span class='c1'>; size of buffer</span> <span class='nf'>int</span> <span class='mh'>80h</span> <span class='c1'>; call kernel</span> <span class='nl'>_exit:</span> <span class='nf'>mov</span> <span class='nb'>eax</span><span class='p'>,</span> <span class='mi'>1</span> <span class='c1'>; exit syscall</span> <span class='nf'>mov</span> <span class='nb'>ebx</span><span class='p'>,</span> <span class='mi'>0</span> <span class='c1'>; Return 0</span> <span class='nf'>int</span> <span class='mh'>80h</span> <span class='c1'>; call kernel</span> </code></pre> </div> A simple wallpaper wrapper http://demonastery.org/27/a-simple-wallpaper-wrapper/ Fri, 13 Mar 2009 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/27/a-simple-wallpaper-wrapper <p>Edit as necessary, requires hsetroot, mplayer, and a working xvidix on your graphics card (for video).</p> <div class='highlight'><pre><code class='bash'><span class='c'>#!/bin/sh</span> <span class='c'># Set Wallpaper</span> <span class='c'># If $1 is not empty</span> <span class='k'>if</span> <span class='o'>[</span> -n <span class='s2'>&quot;$1&quot;</span> <span class='o'>]</span> ; <span class='k'>then</span> <span class='k'> case</span> <span class='s2'>&quot;$1&quot;</span> in last<span class='o'>)</span> <span class='c'># Grab last set wallpaper from file and store in $WALL</span> <span class='nv'>WALL</span><span class='o'>=</span><span class='sb'>`</span>cat ~/desktop/lastwall<span class='sb'>`</span> ;; *<span class='o'>)</span> <span class='c'># Set $WALL from command line and write to file for future use</span> <span class='nv'>WALL</span><span class='o'>=</span><span class='nv'>$1</span> <span class='nb'>echo</span> <span class='nv'>$1</span> &gt; ~/desktop/lastwall ;; <span class='k'>esac</span> <span class='k'> case</span> <span class='s2'>&quot;$WALL&quot;</span> in *.jpg|*.jpeg|*.png|*.gif|*.bmp<span class='o'>)</span> <span class='c'># $WALL is an image file, so use hsetroot to set it as the background</span> <span class='nb'>echo </span>Setting with hsetroot... hsetroot -full <span class='s2'>&quot;$WALL&quot;</span> ;; *<span class='o'>)</span> <span class='c'># $WALL is likely not an image, so attempt to play with mplayer</span> <span class='nb'>echo </span>Setting with mplayer... <span class='c'># Blank out background first</span> hsetroot -solid <span class='s2'>&quot;#000000&quot;</span> <span class='c'># &quot;Play&quot; background using colorkey</span> sudo mplayer -fs -vo xvidix -rootwin -colorkey 000000 -quiet <span class='s2'>&quot;$WALL&quot;</span> &amp; ;; <span class='k'>esac</span> <span class='c'># Return good</span> <span class='nb'>exit </span>0 <span class='k'>else</span> <span class='k'> </span><span class='nb'>echo </span>Please specify an image or a video file to <span class='nb'>set</span>, or use <span class='s2'>&quot;last&quot;</span> <span class='c'># Return bad</span> <span class='nb'>exit </span>1 <span class='k'>fi</span> </code></pre> </div> <p>To use, run <code>setwallpaper.sh /path/to/image/or/video/file</code> or <code>setwallpaper.sh last</code></p> Change fonts dynamically http://demonastery.org/28/change-fonts-dynamically/ Wed, 18 Feb 2009 00:00:00 +1300 zane.a@demonastery.org (Zane Ashby) http://demonastery.org/28/change-fonts-dynamically <p>After some Q and A on the ArchLinux forums, I am left with this in my .zshrc, the ability to change fonts on the fly:</p> <div class='highlight'><pre><code class='bash'>vim_font<span class='o'>()</span> <span class='o'>{</span> <span class='nb'>echo</span> -e <span class='s1'>&#39;\e]710;xft:Terminus:style=Regular\007&#39;</span> vim <span class='nv'>$*</span> <span class='nb'>echo</span> -e <span class='s1'>&#39;\e]710;xft:lime:style=Regular\007&#39;</span> <span class='o'>}</span> <span class='nb'>alias </span><span class='nv'>vim</span><span class='o'>=</span><span class='s1'>&#39;vim_font&#39;</span> </code></pre> </div>