Nic0's Sphere 2012-01-22T10:48:38+01:00 http://www.nicosphere.net Nicolas Paris Clint, Command Line Library for Python 2012-01-05T00:00:00+01:00 http://www.nicosphere.net/clint-command-line-library-for-python <p>This library is the kind I like, the kind which make your life easier, perfect for someone like me, who uses Python all the time. So, what can <a href="https://github.com/kennethreitz/clint">Clint</a> do for you? Well, there are a bunch of tools that might come handy when you do some command line based programming, especially quick scripts. If you use Python as your primary langage, CLI stuff is always useful.</p> <h3>Colors</h3> <p>Having some colored output can be nice, but I don&rsquo;t want to use some ncurses interface to have a nice display. A common request is for text color to be green for an expected result, and red otherwise. The highest ranked answer from <a href="http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python">this stackoverflow&rsquo;s question</a> gives some<code>'\033[93m'</code>, which it does the works, but isn&rsquo;t lovely, or even <em>pythonic</em>.</p> <p>Let&rsquo;s see the simplest example possible:</p> <div class="highlight"><pre><code class="python"><span class="kn">from</span> <span class="nn">clint.textui</span> <span class="kn">import</span> <span class="n">colored</span> <span class="k">print</span> <span class="n">colored</span><span class="o">.</span><span class="n">red</span><span class="p">(</span><span class="s">&#39;some warning message&#39;</span><span class="p">)</span> <span class="k">print</span> <span class="n">colored</span><span class="o">.</span><span class="n">green</span><span class="p">(</span><span class="s">&#39;nicely done!&#39;</span><span class="p">)</span> </code></pre> </div> <p>How intuitive was that! At least, I don&rsquo;t need to check on the documentation every time I want a red message!</p> <p>If you only need one word in different color, it&rsquo;s as simple as a concatenation, here&rsquo;s a quick example:</p> <div class="highlight"><pre><code class="python"><span class="kn">from</span> <span class="nn">clint.textui</span> <span class="kn">import</span> <span class="n">colored</span> <span class="k">print</span> <span class="s">&#39;I love &#39;</span> <span class="o">+</span> <span class="n">colored</span><span class="o">.</span><span class="n">yellow</span><span class="p">(</span><span class="s">&#39;pyt&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="n">colored</span><span class="o">.</span><span class="n">blue</span><span class="p">(</span><span class="s">&#39;hon&#39;</span><span class="p">)</span> </code></pre> </div> <h3>Indentation</h3> <p>One of the main feature of Clint, is to handle nicely indentations. It even managed nested indentation, a <em>quote</em> system, allow you to set some prefix chars, like quotes in emails for example. Here a quick example:</p> <div class="highlight"><pre><code class="python"><span class="kn">from</span> <span class="nn">clint.textui</span> <span class="kn">import</span> <span class="n">colored</span><span class="p">,</span> <span class="n">indent</span><span class="p">,</span> <span class="n">puts</span> <span class="k">with</span> <span class="n">indent</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">quote</span><span class="o">=</span><span class="n">colored</span><span class="o">.</span><span class="n">red</span><span class="p">(</span><span class="s">&#39; &gt;&#39;</span><span class="p">)):</span> <span class="n">puts</span> <span class="p">(</span><span class="s">&#39;some random text&#39;</span><span class="p">)</span> <span class="n">puts</span> <span class="p">(</span><span class="s">&#39;another text&#39;</span><span class="p">)</span> <span class="k">with</span> <span class="n">indent</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">quote</span><span class="o">=</span><span class="n">colored</span><span class="o">.</span><span class="n">green</span><span class="p">(</span><span class="s">&#39; |&#39;</span><span class="p">)):</span> <span class="n">puts</span><span class="p">(</span><span class="s">&#39;some more nested identation&#39;</span><span class="p">)</span> <span class="n">puts</span><span class="p">(</span><span class="s">&#39;cool isn</span><span class="se">\&#39;</span><span class="s">t?&#39;</span><span class="p">)</span> </code></pre> </div> <p>Once executed, the output gives:</p> <pre><code>&gt; some random text &gt; another text &gt; | some more nested identation &gt; | cool isn't? </code></pre> <p>Looks good without breaking a sweat!</p> <h3>Arguments</h3> <p>There are ways to handle arguments, like the module <code>argparse</code>, or even <code>sys.args</code>. However, Clint wants to be as simple and useful as possible. It allows you to make distinction between the arguments passed:</p> <ul> <li><code>args.all</code> a simple list of every arguments passed.</li> <li><code>args.flags</code> list only flags, meaning with <code>--foo</code> or <code>-f</code> passed, excluding everything else that doesn&rsquo;t contain a dash.</li> <li><code>args.files</code> this one could be very useful, it detects files in the arguments line, even with <code>*</code> wildcard. So for example you have in the directory <code>foo.py</code> and <code>bar.py</code>, entering something like <code>*.py</code> will return in the <code>args.files</code> a list with those two files.</li> <li><code>args.not_files</code> is every thing that wasn&rsquo;t detected by the above argument.</li> <li><code>args.grouped</code> help you to managed grouped arguments.</li> </ul> <p>For a redistributed program that I take time over, I would probably use <code>argparse</code>, as it&rsquo;s more common, and gives you a nice help output. But for a quick homemade script, that only need to take few arguments, I really think this could be an alternative. Either way, it worth having a look at.</p> <h3>Progress bar, files and pipes</h3> <p>Clint comes with more tools, which are easy to use. Let&rsquo;s look at a progress bar with Clint:</p> <div class="highlight"><pre><code class="python"><span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span> <span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">random</span> <span class="kn">from</span> <span class="nn">clint.textui</span> <span class="kn">import</span> <span class="n">progress</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">progress</span><span class="o">.</span><span class="n">bar</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">)):</span> <span class="n">sleep</span><span class="p">(</span><span class="n">random</span><span class="p">()</span> <span class="o">*</span> <span class="mf">0.2</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">progress</span><span class="o">.</span><span class="n">dots</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">)):</span> <span class="n">sleep</span><span class="p">(</span><span class="n">random</span><span class="p">()</span> <span class="o">*</span> <span class="mf">0.2</span><span class="p">)</span> </code></pre> </div> <pre><code>[######################## ] 75/100 </code></pre> <p>Clint handles pipes, eg. <code>cat foo.txt | bar.py</code>, or resources like handling files IO.</p> <h3>Documentation and Conclusion</h3> <p>This post is not a review of every possible utility that Clint has to offer, but more of a quick overview, and memo for myself. I really think Clint could come in handy from time to time. Unfortunately, there is a lack of documentation, not much more than the <a href="https://github.com/kennethreitz/clint/tree/develop/examples">README</a> from the github repository, as the <code>/doc/</code> directory doesn&rsquo;t contain much. The best place to start is to directly check <a href="https://github.com/kennethreitz/clint/tree/develop/examples">example</a> codes provides with the library.</p> <p>Another thing that could bother you is, so far, Clint only works with python 2.x. Python 3 compatibility is include in the todo list, as is documentations.<br/> <strong>Edit about Python3</strong>: Not true anymore, thanks to Kenneth Reitz, whose done a release today with Python3 support!</p> <p>I hope you enjoyed this quick review of <a href="https://github.com/kennethreitz/clint">Clint</a>. Anyway, it&rsquo;s in my toolbox now.</p> Changes on This Blog 2012-01-02T00:00:00+01:00 http://www.nicosphere.net/changes-on-this-blog <p>Since I started blogging, this is the biggest change I&rsquo;ve done. So I felt like I own you an explanation. The main reason was to separate the English content from the French one. Well, at least, it&rsquo;s what I&rsquo;m telling myself, as I know I changed the blog engine for <a href="https://github.com/mojombo/jekyll">Jekyll</a>, just because I like the way it works. I&rsquo;m aware that it might sounds unreasonable to change of CMS like that, but I&rsquo;m blogging for my pleasure, spending lots of time with, so it worth to change for a better system, that suite better my way about computers.</p> <h2>About French Content</h2> <p>First time I said in this blog that I wanted to write in english was in <a href="http://www.nicosphere.net/choix-de-la-langue-pour-un-billet-technique-2357/">this post</a>, it was more than 9 months ago. It took me some time to find the courage to do so, as I started only a couple of months ago.</p> <p>Anyway, I moved the content to <a href="http://fr.nicosphere.net">this link</a>, I had to manage some redirections, as it isn&rsquo;t a good idea to leaves 404 pages. I probably won&rsquo;t use it that much now. I certainly only publish the Hacker Weekly News series, I did think about to stop it, but I like this series, helps me to classify information, and keep track of it. So I&rsquo;ll should carry on the series on the French part of this site. So, if you still want follow the Hacker Weekly News series, you should add <a href="http://fr.nicosphere.net/feed/">this feed</a> on your reader.</p> <p>The main site, of this post, keep the same feed as before, so no need to change anything.</p> <h2>About Jekyll</h2> <p>If you never heard about <a href="https://github.com/mojombo/jekyll">Jekyll</a>, is a static website generator, the main idea is to generate the entire site in plain HTML, with obviously some JavaScript, but no server side language such as PHP. I never really liked hack into Wordpress, at the opposite to Jekyll, witch is much easier to get into. You just need some Ruby background. I hesitated with blogofile as it&rsquo;s written in Python.</p> <p>I won&rsquo;t explain why Jekyll, or any static website generator, are nice to use, there is already lots of blog post around the web.</p> <h2>About Github Pages</h2> <p>I did want try this solution, Jekyll was build to works with Github pages, the idea is simply to push on the repository, and Github does the generation of the site. The problem is Github doesn&rsquo;t allow any plugins. Fair enough, I can understand that they don&rsquo;t want any arbitrary code to be run on them server, but it loose one of the main interest of it. No plugins, no hack, no interest, simple as that. So I&rsquo;ll host myself, with some kind of rsync over ftp, seems like lftp does something like that with the mirror mode.</p> <p>I would think about Github pages if I haven&rsquo;t used a plugin to generate all my redirection.</p> <p>I still have some stuffs and improvements to take care of.</p> <p>That&rsquo;s all for now, see you soon with some real blog posts!</p> PhotoShow, Web gallery without SQL 2011-12-04T00:00:00+01:00 http://www.nicosphere.net/photoshow-web-gallery-without-sql-2558 <p>When it comes to web gallery, I usually choose <a href="http://piwigo.org/">Piwigo</a>, a safe choice for a stable PHP gallery.</p> <p>Last week, I heard about a new project, called <a href="http://www.photoshow-gallery.com/">PhotoShow</a>, a nice looking web gallery. A <a href="http://www.photoshow-gallery.com/demo/">demo website</a> is available. Here a quick functionalities review.</p> <ul> <li>Easy installation, get latest tarball on github, or simply a git clone, set two lines from the configuration file, and you are ready to go.</li> <li>Structure based on file system and directory, easy to manages and organizes photos and structures.</li> <li>Generate thumbnails and 800*600 images automatically with phpthumb.</li> <li>Two based directories, one with real photos, one with generated ones.</li> <li>Drag n' Drop to upload and manages the website.</li> <li>No SQL bases needed, it only based on the file system.</li> <li>Nice looking jQuery effects.</li> <li>Work fine without JavaScript.</li> <li>Manage public and private albums.</li> <li>Comments system.</li> </ul> <p><a href="/img/photoshow.png"><img src="/img/photoshow.png" alt="" title="photoshow" width="653" height="155" class="aligncenter size-full wp-image-2559" /></a></p> <p>First, I have to warn you that PhotoShow still on a early stage of his developpment. It seems stable enough, the project should improve quickly in a near future, with probably some new features. So perhaps it isn&rsquo;t ready for <em>production</em>, but should be fine for a personal use.</p> <p>Installation and configuration are straight forward, the easiest is use <code>git clone</code>, it would be simple to keep the gallery update with upstream by doing a <code>git pull</code>. You need to edit the <code>conf.ini</code> file, to set both photos and generated photos pathname. Once it done, you only need to answer the form to set your name/password account, and you&rsquo;re done.o</p> <div class="highlight"><pre><code class="bash">git clone https://github.com/thibaud-rohmer/PhotoShow.git </code></pre> </div> <p>Some would appreciate the drag n' drop system, I personally liked the disposition of thumbnails, compact as google galleries, managed well different size to find the optimal display, allow you to quickly see every photos of an album.</p> <p>I will keep an eye on this project for sure.</p> <p>At last, the code can be found on <a href="https://github.com/thibaud-rohmer/PhotoShow">github</a>, under the GNU GPLv3.</p> Manage automatically two dictionaries with Firefox 2011-12-03T00:00:00+01:00 http://www.nicosphere.net/manage-automatically-two-dictionaries-with-firefox-2557 <p>When your native language isn&rsquo;t English, and when, like me, you spend time writing around the Internet, between comments from some news sites, blog posts and programming question-answer site, you have to deal with at least two languages, English, and whatever language you use at home. Unfortunately, I have trouble with grammar and spelling<a href="But">^1</a>. I probably have done what everyone else with bad spelling would do in this case, add to Firefox a spell checker. It does what I want, but as I write across websites, I need to switch the spell checker from French to English, certainly more often that I even notice.</p> <p>Switching of dictionaries is annoying, but not enough to really do something about it. When you&rsquo;re switching it, you think that perhaps you should try to google about it if there is any kind of shortcut or whatever would do the trick and save you some time, but you forget as soon as you switched the dictionary, and your mind focus on the answer/comment you&rsquo;re writing. Same thing for asking to some geek friends, quickly forgotten to ask, every time.</p> <p>So I&rsquo;d carry this <em>problem</em> who isn&rsquo;t really one, and by chance, I found the perfect solution for what I&rsquo;m asking for. It could be obvious to some persons, but after all, I&rsquo;m not switching of dictionary for that long time ago. The answer I found is no more that <a href="https://addons.mozilla.org/fr/firefox/addon/dictionary-switcher/">a Firefox plugin, called dictionary switcher</a>. This plugin recognize automatically the language you are taping of, and adapt the dictionary in function of it, few more options on it to do more precisely what you want. With a name link that, I could find it earlier, but the thing is I didn&rsquo;t toke time to look for.</p> <p>Short blog post, for a quick trick, maybe it could be useful to someone else.</p> The missing newsletter of Arch Linux 2011-12-02T00:00:00+01:00 http://www.nicosphere.net/the-missing-newsletter-of-arch-linux-2555 <p>Most of Linux distributions comes with newsletters, a short summary of what happen around distributions and the community himself. Interestingly enough, Arch Linux doesn&rsquo;t have anymore one, as far as I know. It wasn&rsquo;t always like this, here a quick review of what was done so far.</p> <p>y apologies if any informations was inaccurate.</p> <h2>The newsletter</h2> <p>Feb 2004 &ndash; Jul 2009</p> <p>As the Arch community is growing, some of you may never heard about this old newsletter, start with weekly issue, quickly became a twice a month release, finished as a monthly issue. The information provide was good, but as I became an Arch user around this time, I haven&rsquo;t the opportunity to read lots of them. For information, you still can read old archives on this link.</p> <p><a href="http://www.archlinux.org/static/magazine/">Arch Linux Newsletters Archives</a></p> <p>I&rsquo;m certainly not the only one, but I miss this newsletter.</p> <h2>Arch User Magazine</h2> <p>Apr 2009 &ndash; Jun 2009</p> <p>Unofficial project initiate by Ghost1227, in a paper magazine style, old issues can be grab in the same link as the Newsletters Archives. We can still read <a href="https://bbs.archlinux.org/viewtopic.php?id=68922">the bbs thread</a> for the first released issue. Three issues was made, and it will be merge with the official newsletter, as the author doesn&rsquo;t have the time to carry on the project as he wanted.</p> <h2>Arch Linux Magazine</h2> <p>Aug 2009 &ndash; Mar 2010</p> <p>The official newsletter, by Kensai, and the Arch User Magazine, by Ghost1227, will join their force together to provide a magazine available in both format html (newsletter format) and pdf (scribus/magazine format). Here is the <a href="https://bbs.archlinux.org/viewtopic.php?id=77538">bbs thread</a> for nostalgic, about the first released announce by Kensai. I proudly translate issues with others French contributors in my language back this time. Unfortunately, a lack of contribution, and certainly of time as well, ended the magazine after 4 releases. But meanwhile, Kensai left for personal reasons.</p> <h2>Rolling Release</h2> <p>Sep 2010 &ndash; May 2011 (Until now?)</p> <p><a href="http://rollingrelease.com/">Rolling Release</a> is an official website that aimed to succeed the Arch Linux agazine, as it&rsquo;s an e-zine, no need to have a regular issue, or even spend time with scribus to make a nice looking pdf. Here the <a href="https://bbs.archlinux.org/viewtopic.php?id=105236">forum announce</a> of the official launch of the site. Technically, the website look nice, allows comments. Even someone, jdarnold, started for few weeks a weekly issue on this site. The website has nice posts for a while, but hasn&rsquo;t published anything since May 2011, without any official reason that I&rsquo;m aware of, other than the lack of time I guess.</p> <h2>The missing newsletter</h2> <p>All this news was great informations, I&rsquo;m very thankful for all the time that contributors spends on this, on their own time. But what&rsquo;s now? I know what you think, <em>&ldquo;you want one? Do It Yourself!&rdquo;</em>, it&rsquo;s absolutely true if I was following Arch Linux actuality enough, and a more fluent English.</p> <p>What I do know is that this kind of initiatives often come from one man, no more, after all, Arch Linux came from a one man project as well. So, maybe if you are close to the community, following forum or mailing list, you might consider start some kind of newsletter. It doesn&rsquo;t need to be great, long, with lots informations. Few links in a paper, with a short description, a couple of tricks or applications taken from the forum, it&rsquo;s all it need to start something, I&rsquo;m sure the community would be thankful for this, well I&rsquo;ll be thankful for sure.</p> Tyrs 0.6.0, ncurses Twitter client, first release with Urwid 2011-12-01T00:00:00+01:00 http://www.nicosphere.net/tyrs-0-6-0-ncurses-twitter-client-first-release-with-urwid-2553 <p>Tyrs is a Twitter and Identi.ca client based on ncurses. This major release is the first one using the <a href="http://excess.org/urwid/">urwid</a> library. It will improve greatly the user interface.</p> <ul> <li>Edit a tweet: Previous release had a poorly way to edit tweet, I knew it, and wasn&rsquo;t especially proud of it and always wanted to do it again from scratch. With urwid, it was easier to manage it. So now, it&rsquo;s more like an IRC input bar to write tweet. We can do what we usually want, such as go back with arrow keys.</li> <li>I had feedback as the unicode wasn&rsquo;t perfect, editing a tweet with 2-bits long Chinese characters could sometime break the application. Fortunately, urwid has an excellent utf-8 support, so the overall management of unicode should be improve, and shouldn&rsquo;t be an issue anymore.</li> <li>More generally, a better display with less bugs.</li> </ul> <p>In many way the interaction with user is improve, and in many details. This release still in early stage of development of the urwid interface, this mean it&rsquo;s usable, but some functionalities aren&rsquo;t yet implements, and will be done soon. I always follow the <em>release early, release often</em> plan, and even everything isn&rsquo;t ready yet, I believe the improvement worth a release.</p> <p>Some stuff that need to be done in further releases:</p> <ul> <li>Configuration, lot of configuration was about the display, it will be the point of the next release.</li> <li>Better default shortcut, I&rsquo;m not so happy about the default shortcut, I&rsquo;ve started with some, and added while I was doing the implementation, but, I guess it could be remap in much better way, even if it customizable in the configuration file.</li> <li>Display without boxes, as I&rsquo;m not a huge fan of line, I&rsquo;ll probably do three default layout, <em>coming soon</em>.</li> <li>Few more functionalities such as lists, information about user&hellip;</li> </ul> <p>If you are using Arch Linux, the installation through the <a href="https://aur.archlinux.org/packages.php?ID=48849">AUR package</a> is easy:</p> <pre><code>yaourt -S tyrs # Or the latest git revision yaourt -S tyrs-git </code></pre> <p>You may find the latest code in the <a href="https://github.com/Nic0/tyrs">github repository</a>, and find tarballs in the <a href="http://pypi.python.org/pypi/tyrs">pypi page</a> of the project.</p> <p>I hope you&rsquo;ll enjoy it. As usually, any feedback is much appreciated.</p> HTML output screenshot with Urwid ncurses library 2011-11-30T00:00:00+01:00 http://www.nicosphere.net/html-output-screenshot-with-urwid-ncurses-library-2552 <p>Urwid is a ncurses library for Python, you may check older posts if you&rsquo;re not familiar about it. So far, we&rsquo;ve seen some useful functionalities and tricks, to run urwid, therefor, it&rsquo;s time to see something (almost) useless but geek, and in the spirit of ncurses programs, as urwid allow to take &ldquo;screenshots&rdquo; of the application, with a HTML output.</p> <p>The problem with the reference guide of urwid, it&rsquo;s that is not so easy to figure out how to get things done as we want. This corresponds to the <em>screen capture</em> part of the reference guide. But the easiest way to get started it&rsquo;s to check source code, and not the <em>real</em> code of urwid, but the code who actually generate the tutorial of urwid, they do use this functionality for this part. Check in the tarball, <code>docgen_tutorial.py</code> to get examples.</p> <p>Let&rsquo;s take our own example, based on the code we&rsquo;ve done in earlier post, for reminder, we obtain a list of item (couple title/description), in a <code>urwid.Frame</code> that allow to divide the space in three parts, header (the selected item), the body (list of the items), the footer (edit the description of current item). It was where we was last time. So let&rsquo;s add a screenshot of it.</p> <h2>The idea</h2> <p>The screenshot will be triggered by the <em>s</em> keystroke, the idea is to start over the main loop, and pass in arguments the sequence of keystroke wanted.</p> <h2>Trick about screen size</h2> <p>We need to pass in the screenshot the size of the screen. It will be a tuple <em>(y, x)</em>, it could be some random numbers, but it could be useful for the screenshot, and many other functionalities, to get the real size of the screen, and their is a variable for that.</p> <div class="highlight"><pre><code class="python"><span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="p">,</span> <span class="n">palette</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">keystroke</span><span class="p">)</span> <span class="c">#[...]</span> <span class="c">#This variable contain the size in a tuple (x, y)</span> <span class="n">size</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">screen_size</span> </code></pre> </div> <h2>About the output</h2> <p>The output will come in a variable, but after every stroke we ask, their will be a screenshot, retrieve in a list, we need to choose the good one, probably the last one.</p> <h2>The screenshot code</h2> <div class="highlight"><pre><code class="python"><span class="kn">import</span> <span class="nn">urwid.html_fragment</span> <span class="c"># [...]</span> <span class="k">def</span> <span class="nf">keystroke</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">)</span> <span class="c"># [...]</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;s&#39;</span><span class="p">:</span> <span class="n">init</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">html_fragment</span><span class="o">.</span><span class="n">screenshot_init</span> <span class="n">collect</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">html_fragment</span><span class="o">.</span><span class="n">screenshot_collect</span> <span class="n">init</span><span class="p">([</span><span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">screen_size</span><span class="p">],</span> <span class="p">[[</span><span class="s">&#39;down&#39;</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;enter&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s">&#39;q&#39;</span><span class="p">]])</span> <span class="n">MyApp</span><span class="p">()</span> <span class="k">with</span> <span class="nb">open</span> <span class="p">(</span><span class="s">&#39;output.html&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">collect</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> </code></pre> </div> <p>In this code, we prepare two functions.</p> <ul> <li><code>init</code> will be pass the sequence of keystroke, quite forward to understand.</li> <li><code>collect</code> retrieve the result, as it was said earlier, it gives a list, we want only the latest element.</li> </ul> <p>The result it place in the file <code>output.html</code> that we can see with firefox.</p> <h2>The result</h2> <pre><span style="color:#ff0000;background:#000000">selected: item 3: Cras a magna sit amet fel... </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 0 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 1 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 2 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#cd0000;background:#e5e5e5">item 3 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 4 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 5 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 6 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 7 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 8 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 9 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 10 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 11 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 12 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 13 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 14 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 15 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 16 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 17 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 18 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 19 </span><span style="color:#0000ee;background:#e5e5e5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 20 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 21 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 22 </span><span style="color:#0000ee;background:#e5e5e5">Sed sollicitudin, nulla id viverra pulvinar. </span> <span style="color:#0000ee;background:#e5e5e5"> </span><span style="color:#0000ee;background:#e5e5e5">item 23 </span><span style="color:#0000ee;background:#e5e5e5">Cras a magna sit amet felis fringilla lobortis. </span> </pre> <h2>The full code</h2> <div class="highlight"><pre><code class="python"><span class="kn">import</span> <span class="nn">urwid</span> <span class="kn">import</span> <span class="nn">random</span> <span class="kn">import</span> <span class="nn">urwid.html_fragment</span> <span class="k">class</span> <span class="nc">ItemWidget</span> <span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">WidgetWrap</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">description</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">id</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;item </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="n">description</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">item</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;fixed&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Padding</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="n">left</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">description</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s">&#39;item </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">...&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">),</span> <span class="n">description</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span> <span class="n">w</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Columns</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">item</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">__super</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">w</span><span class="p">)</span> <span class="k">def</span> <span class="nf">selectable</span> <span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="n">key</span> <span class="k">class</span> <span class="nc">CustomEdit</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Edit</span><span class="p">):</span> <span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">signals</span><span class="o">.</span><span class="n">MetaSignals</span> <span class="n">signals</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;done&#39;</span><span class="p">]</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_edit_text</span><span class="p">())</span> <span class="k">return</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;esc&#39;</span><span class="p">:</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">return</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Edit</span><span class="o">.</span><span class="n">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span> <span class="k">class</span> <span class="nc">MyApp</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">palette</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">,</span><span class="s">&#39;dark blue&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;focus&#39;</span><span class="p">,</span><span class="s">&#39;dark red&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;head&#39;</span><span class="p">,</span><span class="s">&#39;light red&#39;</span><span class="p">,</span> <span class="s">&#39;black&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="n">lorem</span> <span class="o">=</span> <span class="p">[</span> <span class="s">&#39;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&#39;</span><span class="p">,</span> <span class="s">&#39;Sed sollicitudin, nulla id viverra pulvinar.&#39;</span><span class="p">,</span> <span class="s">&#39;Cras a magna sit amet felis fringilla lobortis.&#39;</span><span class="p">,</span> <span class="p">]</span> <span class="n">items</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="n">item</span> <span class="o">=</span> <span class="n">ItemWidget</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">lorem</span><span class="p">))</span> <span class="n">items</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="n">header</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrMap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected:&#39;</span><span class="p">),</span> <span class="s">&#39;head&#39;</span><span class="p">)</span> <span class="n">walker</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">SimpleListWalker</span><span class="p">(</span><span class="n">items</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ListBox</span><span class="p">(</span><span class="n">walker</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">),</span> <span class="n">header</span><span class="o">=</span><span class="n">header</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="p">,</span> <span class="n">palette</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">keystroke</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="n">walker</span><span class="p">,</span> <span class="s">&#39;modified&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">update</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> <span class="k">def</span> <span class="nf">keystroke</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;Q&#39;</span><span class="p">):</span> <span class="k">raise</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ExitMainLoop</span><span class="p">()</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> <span class="k">if</span> <span class="nb">input</span> <span class="o">==</span> <span class="s">&#39;e&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit</span><span class="p">()</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;s&#39;</span><span class="p">:</span> <span class="n">init</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">html_fragment</span><span class="o">.</span><span class="n">screenshot_init</span> <span class="n">collect</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">html_fragment</span><span class="o">.</span><span class="n">screenshot_collect</span> <span class="n">init</span><span class="p">([</span><span class="bp">self</span><span class="o">.</span><span class="n">loop</span><span class="o">.</span><span class="n">screen_size</span><span class="p">],</span> <span class="p">[[</span><span class="s">&#39;down&#39;</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;enter&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s">&#39;q&#39;</span><span class="p">]])</span> <span class="n">MyApp</span><span class="p">()</span> <span class="k">with</span> <span class="nb">open</span> <span class="p">(</span><span class="s">&#39;output.html&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">collect</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="n">CustomEdit</span><span class="p">(</span><span class="s">&#39; &gt;&gt; &#39;</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_footer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_focus</span><span class="p">(</span><span class="s">&#39;footer&#39;</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit_done</span><span class="p">)</span> <span class="k">def</span> <span class="nf">edit_done</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_focus</span><span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">disconnect_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit_done</span><span class="p">)</span> <span class="k">if</span> <span class="n">content</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="n">focus</span><span class="o">.</span><span class="n">description</span><span class="o">.</span><span class="n">set_text</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_footer</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">MyApp</span><span class="p">()</span> </code></pre> </div> Several colored string with Urwid 2011-11-23T00:00:00+01:00 http://www.nicosphere.net/several-colored-string-with-urwid-2546 <p>OK, this one is an easy and quick stuff, that I&rsquo;m almost ashame to share. But the thing is, I search for it, and I wasn&rsquo;t even sure where to look at it. The reason I put it here is because I trying to put together some trick about urwid, stuff I spend some time to looking for, even if it isn&rsquo;t so much time. If someone need it, he should find it easily here.</p> <p>The idea is to highlight some worlds in a string. The answer was right in the front of me from the start! As it was shown in the <code>tour.py</code>, the very first script in the official tutorial.</p> <div class="highlight"><pre><code class="python"><span class="n">palette</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;main&#39;</span><span class="p">,</span> <span class="s">&#39;dark blue&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;hl&#39;</span><span class="p">,</span> <span class="s">&#39;dark red&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span> <span class="p">]</span> <span class="n">txt</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">([</span> <span class="s">&quot;Some random text, with an &quot;</span><span class="p">,</span> <span class="p">(</span><span class="s">&#39;hl&#39;</span><span class="p">,</span> <span class="s">&quot;IMPORTANT &quot;</span><span class="p">),</span> <span class="s">&quot;word. Other boring stuff.&quot;</span> <span class="p">]),</span> <span class="s">&#39;main&#39;</span><span class="p">)</span> </code></pre> </div> <p>This short example, witch is only a part of a code of course, shows a string with the <code>main</code> color, with the <em>IMPORTANT</em> word colored with the <code>hl</code> attribute. It only a list, with a tuple for different colors, color attribute first.</p> <p>As I said, it isn&rsquo;t a very exalting post, just a quick trick.</p> Footer Edit with Urwid, IRC-Client-like input 2011-11-23T00:00:00+01:00 http://www.nicosphere.net/footer-edit-with-urwid-irc-client-like-input-2547 <p>We start with the code from <a href="http://www.nicosphere.net/selectable-list-with-urwid-for-python-2542/">Selectable List with Urwid for Python</a>, check before the <a href="http://www.nicosphere.net/signals-with-urwid-for-python-2545/">Signals with Urwid for Python</a> for a small involvement of the code, for handling signals.</p> <p>So far, we have a selectable list containing two items each (title and description). We can go through it with up and down key arrows, and select one of them with the <em>enter</em> key. We use <em>urwid.Frame</em> witch give us an useful layout divided in three parts, <em>header</em>, <em>body</em> and <em>footer</em>. In the last post, we used the header to display the selected item, the body to display the list, and the footer wasn&rsquo;t used at all.</p> <p>Now, what we want is to use the footer for an <em>Edit</em> widget, exactly like ncurses IRC-client such as IRSSI or weechat. When we will press the <code>e</code> key (for edit) an input widget will appear, taking place at the footer, once validate, with <em>enter</em>, or abort with <em>escape</em> the output will replace the description of the current selected item.</p> <p>In the following screenshot, the list was generated with random description. the 4th item was replaced with this editing process, and we&rsquo;re about to replace the 5th item as well. It may seem not a big deal, but it still a good exercise to gain practice with urwid.</p> <p><a href="/img/urwid-edit.png"><img src="/img/urwid-edit-300x120.png" alt="Urwid Edit" title="urwid-edit" width="300" height="120" class="size-medium wp-image-2548" /></a></p> <p>Let&rsquo;s talk about the code. <strong>The full code is at the end of the post</strong>.</p> <ul> <li><em>ItemWidget</em>: is almost the same as before, it used to create an item for the list, it was only change in order to set the description part, here the changing part.</li> </ul> <div class="highlight"><pre><code class="python"><span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="n">description</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">item</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;fixed&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Padding</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="n">left</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">description</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="p">]</span> </code></pre> </div> <ul> <li><em>CustomEdit</em>: inheritance of the <em>Edit</em> widget, it will emit a signal <em>done</em> once finish editing, and will give an argument to the callback, the content of the editing, or <em>None</em> if it was abort with the <em>escape</em> key. If neither keys is pressed, the key is return and managed by the normal <em>Edit</em> widget.</li> </ul> <div class="highlight"><pre><code class="python"><span class="k">class</span> <span class="nc">CustomEdit</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Edit</span><span class="p">):</span> <span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">signals</span><span class="o">.</span><span class="n">MetaSignals</span> <span class="n">signals</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;done&#39;</span><span class="p">]</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_edit_text</span><span class="p">())</span> <span class="k">return</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;esc&#39;</span><span class="p">:</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">return</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Edit</span><span class="o">.</span><span class="n">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span> </code></pre> </div> <ul> <li><em>MyApp</em>: I moved the code in a class, most of the code is the same except for the last two method.</li> </ul> <p>The <em>edit</em> method is directly call when the <code>e</code> key is pressed. It only create a <em>CustomEdit</em> object, that would be set to the footer, but we need to specified to the frame (<em>view</em>) that the footer have the focus now, otherwise it would not be editable. At last, we connect the signal, to treat the content once the edit is done.</p> <div class="highlight"><pre><code class="python"> <span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="n">CustomEdit</span><span class="p">(</span><span class="s">&#39; &gt;&gt; &#39;</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_footer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_focus</span><span class="p">(</span><span class="s">&#39;footer&#39;</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit_done</span><span class="p">)</span> </code></pre> </div> <p>Once the edit is done, the <em>edit_done</em> function is called as a callback, with the content. Then we modify the content of the description in the list. And set back to <em>None</em> the footer, as we don&rsquo;t want anything display anymore.</p> <div class="highlight"><pre><code class="python"> <span class="k">def</span> <span class="nf">edit_done</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_focus</span><span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">disconnect_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit_done</span><span class="p">)</span> <span class="k">if</span> <span class="n">content</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="n">focus</span><span class="o">.</span><span class="n">description</span><span class="o">.</span><span class="n">set_text</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_footer</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span> </code></pre> </div> <p>That&rsquo;s it, in this example this code is used to manage a list, but it could be used for a large set of applications.</p> <p>Here the full code:</p> <div class="highlight"><pre><code class="python"><span class="kn">import</span> <span class="nn">urwid</span> <span class="kn">import</span> <span class="nn">random</span> <span class="kn">import</span> <span class="nn">urwid.html_fragment</span> <span class="k">class</span> <span class="nc">ItemWidget</span> <span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">WidgetWrap</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">description</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">id</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;item </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="n">description</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">item</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;fixed&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Padding</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="n">left</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">description</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s">&#39;item </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">...&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">),</span> <span class="n">description</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span> <span class="n">w</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Columns</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">item</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">__super</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">w</span><span class="p">)</span> <span class="k">def</span> <span class="nf">selectable</span> <span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="n">key</span> <span class="k">class</span> <span class="nc">CustomEdit</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Edit</span><span class="p">):</span> <span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">signals</span><span class="o">.</span><span class="n">MetaSignals</span> <span class="n">signals</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;done&#39;</span><span class="p">]</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_edit_text</span><span class="p">())</span> <span class="k">return</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;esc&#39;</span><span class="p">:</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">return</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Edit</span><span class="o">.</span><span class="n">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span> <span class="k">class</span> <span class="nc">MyApp</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">palette</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">,</span><span class="s">&#39;dark blue&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;focus&#39;</span><span class="p">,</span><span class="s">&#39;dark red&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;head&#39;</span><span class="p">,</span><span class="s">&#39;light red&#39;</span><span class="p">,</span> <span class="s">&#39;black&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="n">lorem</span> <span class="o">=</span> <span class="p">[</span> <span class="s">&#39;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&#39;</span><span class="p">,</span> <span class="s">&#39;Sed sollicitudin, nulla id viverra pulvinar.&#39;</span><span class="p">,</span> <span class="s">&#39;Cras a magna sit amet felis fringilla lobortis.&#39;</span><span class="p">,</span> <span class="p">]</span> <span class="n">items</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="n">item</span> <span class="o">=</span> <span class="n">ItemWidget</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">lorem</span><span class="p">))</span> <span class="n">items</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="n">header</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrMap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected:&#39;</span><span class="p">),</span> <span class="s">&#39;head&#39;</span><span class="p">)</span> <span class="n">walker</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">SimpleListWalker</span><span class="p">(</span><span class="n">items</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ListBox</span><span class="p">(</span><span class="n">walker</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">),</span> <span class="n">header</span><span class="o">=</span><span class="n">header</span><span class="p">)</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="p">,</span> <span class="n">palette</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">keystroke</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="n">walker</span><span class="p">,</span> <span class="s">&#39;modified&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">update</span><span class="p">)</span> <span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> <span class="k">def</span> <span class="nf">keystroke</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;Q&#39;</span><span class="p">):</span> <span class="k">raise</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ExitMainLoop</span><span class="p">()</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> <span class="k">if</span> <span class="nb">input</span> <span class="o">==</span> <span class="s">&#39;e&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit</span><span class="p">()</span> <span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">foot</span> <span class="o">=</span> <span class="n">CustomEdit</span><span class="p">(</span><span class="s">&#39; &gt;&gt; &#39;</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_footer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_focus</span><span class="p">(</span><span class="s">&#39;footer&#39;</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit_done</span><span class="p">)</span> <span class="k">def</span> <span class="nf">edit_done</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_focus</span><span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">disconnect_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">foot</span><span class="p">,</span> <span class="s">&#39;done&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">edit_done</span><span class="p">)</span> <span class="k">if</span> <span class="n">content</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="n">focus</span><span class="o">.</span><span class="n">description</span><span class="o">.</span><span class="n">set_text</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">set_footer</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">MyApp</span><span class="p">()</span> </code></pre> </div> <p>Hope it can help someone.</p> Signals with Urwid for Python 2011-11-22T00:00:00+01:00 http://www.nicosphere.net/signals-with-urwid-for-python-2545 <p>Urwid, a Ncurses library for Python, handle a signal system, witch is nice for a ncurses library. You may want to check others posts on urwid if needed. We&rsquo;ll see two examples here.</p> <h2>A first example</h2> <p>Let&rsquo;s start with the code from <a href="http://www.nicosphere.net/selectable-list-with-urwid-for-python-2542/">the last post</a>, for reminder, it does a selectable list, with <em>SimpleListWalker</em>, and display the selected item every time <em>Enter</em> is pressed. It&rsquo;s a simple code, that we&rsquo;ll extend a little.</p> <p><strong>What we want</strong> is to every time we move from the list, the selection is update to the header, showing the correct item, and we want have it working with a signal. Through, it would has other way to get it work, but it&rsquo;s a way to start.</p> <p><a href="http://excess.org/urwid/reference.html#connect_signal">The reference about signals</a> isn&rsquo;t so easy to get into, maybe the best example from the tutorial is <a href="http://excess.org/urwid/tutorial.html#frlb">Events and listbox widget</a>, but in this example, the signal is connected to an <em>Edit Widget</em>, here, we doesn&rsquo;t have such thing, and we want use the list instead. If we try with the <code>change</code> argument, it would says to us that list doesn&rsquo;t have such signal. So let&rsquo;s find out witch signal a list has by reading the code source.</p> <div class="highlight"><pre><code class="python"><span class="k">class</span> <span class="nc">ListWalker</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">signals</span><span class="o">.</span><span class="n">MetaSignals</span> <span class="n">signals</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;modified&quot;</span><span class="p">]</span> <span class="k">def</span> <span class="nf">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">id</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_modified</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">signals</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&quot;modified&quot;</span><span class="p">)</span> </code></pre> </div> <p>Fine, as the <em>SimpleListWalker</em> extends to <em>ListWalker</em>, it seems that this widget use the <code>modified</code> signal, so let&rsquo;s use this one for our example. Here the interesting part, but if you want the entire code, who is basically the same as the last post, you can find it <a href="https://gist.github.com/1385390">in a gist</a>.</p> <div class="highlight"><pre><code class="python"> <span class="n">items</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="n">item</span> <span class="o">=</span> <span class="n">ItemWidget</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">lorem</span><span class="p">))</span> <span class="n">items</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="n">header</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrMap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected:&#39;</span><span class="p">),</span> <span class="s">&#39;head&#39;</span><span class="p">)</span> <span class="n">walker</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">SimpleListWalker</span><span class="p">(</span><span class="n">items</span><span class="p">)</span> <span class="n">listbox</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ListBox</span><span class="p">(</span><span class="n">walker</span><span class="p">)</span> <span class="n">view</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">listbox</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">),</span> <span class="n">header</span><span class="o">=</span><span class="n">header</span><span class="p">)</span> <span class="k">def</span> <span class="nf">update</span><span class="p">():</span> <span class="n">focus</span> <span class="o">=</span> <span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">palette</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="n">keystrock</span><span class="p">)</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="n">walker</span><span class="p">,</span> <span class="s">&#39;modified&#39;</span><span class="p">,</span> <span class="n">update</span><span class="p">)</span> <span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> </code></pre> </div> <p>Importants remarques:</p> <ul> <li>The signal is connected to the <em>SimpleListWalker</em>, so the walker variable, and not to the listbox, as <em>ListBox</em> extends <em>BoxWidget</em> doesn&rsquo;t respond to the <code>modified</code> signal.</li> <li>The update function correspond at the same function when we pressed <em>Enter</em> in the last post.</li> </ul> <p>That&rsquo;s it, nothing complicated, we run it, and it works as expected, every time we move, the header is updated with the signal system.</p> <h2>What about others signals?</h2> <p>Their is no signal list in the documentation, so let&rsquo;s find out some more signal with the documentation. We&rsquo;ll looking for <code>signals = ['foo']</code> in the code, it might give us a clue.</p> <div class="highlight"><pre><code class="bash"><span class="nv">$ </span>ack <span class="s1">&#39;signals = \[&#39;</span> display_common.py 703: <span class="nv">signals</span> <span class="o">=</span> <span class="o">[</span>UPDATE_PALETTE_ENTRY, INPUT_DESCRIPTORS_CHANGED<span class="o">]</span> vterm.py 1317: <span class="nv">signals</span> <span class="o">=</span> <span class="o">[</span><span class="s1">&#39;closed&#39;</span>, <span class="s1">&#39;beep&#39;</span>, <span class="s1">&#39;leds&#39;</span>, <span class="s1">&#39;title&#39;</span><span class="o">]</span> widget.py 719: <span class="nv">signals</span> <span class="o">=</span> <span class="o">[</span><span class="s2">&quot;change&quot;</span><span class="o">]</span> wimp.py 104: <span class="nv">signals</span> <span class="o">=</span> <span class="o">[</span><span class="s2">&quot;change&quot;</span><span class="o">]</span> 422: <span class="nv">signals</span> <span class="o">=</span> <span class="o">[</span><span class="s2">&quot;click&quot;</span><span class="o">]</span> listbox.py 37: <span class="nv">signals</span> <span class="o">=</span> <span class="o">[</span><span class="s2">&quot;modified&quot;</span><span class="o">]</span> </code></pre> </div> <p>We find the the <code>modified</code> signal as shown in the first code in this post. And without surprise, widget.py contain a <code>change</code> signal, exactly as it was shown with the <em>Edit Widget</em> in the tutorial. The 719 line corresponding to the Edit class. So:</p> <ul> <li>Edit (widget.py): change</li> <li>ListWalker (listbox.py): modified</li> <li>CheckBox (wimp.py): change</li> <li>Button (wimp.py): click</li> </ul> <p>vterm.py is more specific and exist only on the latest 1.0.0 version.</p> <h2>Custom signal from scratch</h2> <p>Let&rsquo;s go deeper, and create a signal from scratch. The example will as simple as possible. We create an object, containing a function that raise a signal, on the other hand, an hello world that would change his message when it will receive the signal. I found <a href="http://article.gmane.org/gmane.comp.lib.urwid/742/">another example from the mailing list</a> but a bit more confusing maybe.</p> <p>Here the simplest example that I could came with.</p> <div class="highlight"><pre><code class="python"><span class="kn">import</span> <span class="nn">urwid</span> <span class="kn">import</span> <span class="nn">urwid.signals</span> <span class="k">class</span> <span class="nc">Sig</span> <span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">signals</span><span class="o">.</span><span class="n">MetaSignals</span> <span class="n">signals</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;custom&#39;</span><span class="p">]</span> <span class="k">def</span> <span class="nf">send_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">urwid</span><span class="o">.</span><span class="n">emit_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;custom&#39;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span> <span class="n">txt</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&quot;Hello World&quot;</span><span class="p">)</span> <span class="n">fill</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Filler</span><span class="p">(</span><span class="n">txt</span><span class="p">,</span> <span class="s">&#39;top&#39;</span><span class="p">)</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">Sig</span><span class="p">()</span> <span class="k">def</span> <span class="nf">update</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;Callback once the signal is received&quot;&quot;&quot;</span> <span class="n">fill</span><span class="o">.</span><span class="n">body</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&quot;Text Updated&quot;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">show_or_exit</span><span class="p">(</span><span class="nb">input</span><span class="p">):</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;Q&#39;</span><span class="p">):</span> <span class="k">raise</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ExitMainLoop</span><span class="p">()</span> <span class="c">#We press the &#39;u&#39; letter (as in update)</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;u&#39;</span><span class="p">:</span> <span class="n">sig</span><span class="o">.</span><span class="n">send_signal</span><span class="p">()</span> <span class="c">#connection between the object, the signal name and the callback</span> <span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="n">sig</span><span class="p">,</span> <span class="s">&#39;custom&#39;</span><span class="p">,</span> <span class="n">update</span><span class="p">)</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="n">fill</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="n">show_or_exit</span><span class="p">)</span> <span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">main</span><span class="p">()</span> </code></pre> </div> <p>First thing, don&rsquo;t forget the import. Now, we create the <code>Sig</code> object, it only purposes it to send a signal once we ask for by calling the <code>send_signal</code> function. Every line is important, but easily understandable.</p> <p>The main function isn&rsquo;t more difficult. I added some comments in case. The most important, it&rsquo;s the callback to the update function and how it&rsquo;s connected with:</p> <div class="highlight"><pre><code class="python"><span class="n">urwid</span><span class="o">.</span><span class="n">connect_signal</span><span class="p">(</span><span class="n">sig</span><span class="p">,</span> <span class="s">&#39;custom&#39;</span><span class="p">,</span> <span class="n">update</span><span class="p">)</span> </code></pre> </div> <p>That&rsquo;s all for now, I hope it&rsquo;ll give you some more very basics example to get started with signals and urwid, as the documentation isn&rsquo;t always easy. To be continued&hellip;</p> Selectable List with Urwid for Python 2011-11-20T00:00:00+01:00 http://www.nicosphere.net/selectable-list-with-urwid-for-python-2542 <p>Urwid is a ncurses library for Python, after <a href="http://www.nicosphere.net/urwid-for-python-a-ncurses-library-2541/">a short introduction</a> of urwid, I said I will keep update some training code. As urwid isn&rsquo;t so easy library to start with and examples aren&rsquo;t find all around the Internet, I through it could be interesting (for myself at least) to have some more code.</p> <p><strong>The complete code can be view at the end of this post</strong></p> <p>We want something very common, a simple list of items (title + description), and select one item as we go through the list. To understand easier what we want, here a screenshot of the result.</p> <p><a href="/img/urwid-item.png"><img src="/img/urwid-item-300x181.png" alt="" title="urwid-item" width="300" height="181" class="aligncenter size-medium wp-image-2544" /></a></p> <p>The main idea, is to create a selectable widget, with everything we want in it, and create a <em>SimpleListWalker</em> from a list of this widget.</p> <p>First, let&rsquo;s see this custom widget.</p> <div class="highlight"><pre><code class="python"><span class="k">class</span> <span class="nc">ItemWidget</span> <span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">WidgetWrap</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">description</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">id</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s">&#39;item </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">...&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">),</span> <span class="n">description</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">item</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;fixed&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Padding</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;item </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">)),</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="n">left</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">description</span><span class="p">),</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="n">w</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Columns</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">item</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">__super</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">w</span><span class="p">)</span> <span class="k">def</span> <span class="nf">selectable</span> <span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="n">key</span> </code></pre> </div> <ul> <li>Selectable method</li> </ul> <p>To make a list, it have to be selectable, otherwise when you scroll, it will behave like a web browser, it will scroll the screen as soon as you press the down key, instead of go through every item of the screen before. For example, by default, <em>urwid.Text</em> isn&rsquo;t a selectable item, and can be overwrite.</p> <ul> <li>Keypress method</li> </ul> <p>This is required, but in this example, we won&rsquo;t handle keypress itself, so we simply return the key, and will be handle in the main loop.</p> <ul> <li>Init method</li> </ul> <p>What we do here is to prepare a widget that is a combination of other widgets, so we prepare it, and call it parent constructor in the last line.</p> <p>Some more explanation:</p> <div class="highlight"><pre><code class="python"> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">id</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s">&#39;item </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">...&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">),</span> <span class="n">description</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span> </code></pre> </div> <p>This is some basic stuff, the content attribute is more to retrieve information after it would be selected.</p> <div class="highlight"><pre><code class="python"> <span class="n">w</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Columns</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">item</span><span class="p">)</span> </code></pre> </div> <p>First, I skip the explanation for <em>self.item</em> as it better to keep in mind what we want, so for every item, we display it as a two columns layout. so it will be align nicely.</p> <div class="highlight"><pre><code class="python"> <span class="p">(</span><span class="s">&#39;fixed&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Padding</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;item </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">)),</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="n">left</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> </code></pre> </div> <p>There is a lot in this one.</p> <ul> <li><em>fixed</em> and <em>15</em>, this will tell to the <em>Columns</em> widget that we want this column to be fixed to 15, as we want a smaller column for the title than the description. We affect at the column 15 cols width.</li> <li><em>urwid.Padding</em> and <em>left=2</em>, this tell we don&rsquo;t want the list start right on the left, so we give it two cols space.</li> <li><em>urwid.AttrWrap</em> and <em>body</em> and <em>focus</em>, usual color wrap, with a second one that specify witch palette color do we use when the item have the focus, note that it could be an other name.</li> <li><em>urwid.Text</em> doesn&rsquo;t need much more explanation.</li> </ul> <div class="highlight"><pre><code class="python"><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">description</span><span class="p">),</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> </code></pre> </div> <p>This is almost the same as the other one. This one is easier and doesn&rsquo;t need more explanation.</p> <p>That&rsquo;s it for the <em>ItemWidget</em>, It&rsquo;s ready and we only need to construct a list from this.</p> <div class="highlight"><pre><code class="python"><span class="k">def</span> <span class="nf">main</span> <span class="p">():</span> <span class="n">palette</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">,</span><span class="s">&#39;dark cyan&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;focus&#39;</span><span class="p">,</span><span class="s">&#39;dark red&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;head&#39;</span><span class="p">,</span><span class="s">&#39;light red&#39;</span><span class="p">,</span> <span class="s">&#39;black&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="n">lorem</span> <span class="o">=</span> <span class="p">[</span> <span class="s">&#39;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&#39;</span><span class="p">,</span> <span class="s">&#39;Sed sollicitudin, nulla id viverra pulvinar.&#39;</span><span class="p">,</span> <span class="s">&#39;Cras a magna sit amet felis fringilla lobortis.&#39;</span><span class="p">,</span> <span class="p">]</span> </code></pre> </div> <p>Here&rsquo;s go some basic stuff, the very classic palette, and a <em>lorem generator</em> that will give some random description.</p> <div class="highlight"><pre><code class="python"> <span class="k">def</span> <span class="nf">keystroke</span> <span class="p">(</span><span class="nb">input</span><span class="p">):</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;Q&#39;</span><span class="p">):</span> <span class="k">raise</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ExitMainLoop</span><span class="p">()</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span> <span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> </code></pre> </div> <p>We handle keystrokes in the main method, the important thing is we get back the content of the focus element of the list of widget, and set the content of the header with it.</p> <div class="highlight"><pre><code class="python"> <span class="n">items</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="n">items</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">ItemWidget</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">lorem</span><span class="p">)))</span> </code></pre> </div> <p>this is where we construct the list, some basic stuff.</p> <div class="highlight"><pre><code class="python"> <span class="n">header</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrMap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected:&#39;</span><span class="p">),</span> <span class="s">&#39;head&#39;</span><span class="p">)</span> <span class="n">listbox</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ListBox</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">SimpleListWalker</span><span class="p">(</span><span class="n">items</span><span class="p">))</span> <span class="n">view</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">listbox</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">),</span> <span class="n">header</span><span class="o">=</span><span class="n">header</span><span class="p">)</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">palette</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="n">keystroke</span><span class="p">)</span> <span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> </code></pre> </div> <p>And finally, we put everything together, by creating the <em>SimpleListWalker</em>.</p> <p>Here the code, without my disturbing comments:</p> <div class="highlight"><pre><code class="python"><span class="kn">import</span> <span class="nn">urwid</span> <span class="kn">import</span> <span class="nn">random</span> <span class="k">class</span> <span class="nc">ItemWidget</span> <span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">WidgetWrap</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">description</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">id</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s">&#39;item </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">...&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">),</span> <span class="n">description</span><span class="p">[:</span><span class="mi">25</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">item</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;fixed&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Padding</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;item </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="nb">id</span><span class="p">)),</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="n">left</span><span class="o">=</span><span class="mi">2</span><span class="p">)),</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">description</span><span class="p">),</span> <span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;focus&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="n">w</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Columns</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">item</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">__super</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">w</span><span class="p">)</span> <span class="k">def</span> <span class="nf">selectable</span> <span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">keypress</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="n">key</span> <span class="k">def</span> <span class="nf">main</span> <span class="p">():</span> <span class="n">palette</span> <span class="o">=</span> <span class="p">[</span> <span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">,</span><span class="s">&#39;dark cyan&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;focus&#39;</span><span class="p">,</span><span class="s">&#39;dark red&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;standout&#39;</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;head&#39;</span><span class="p">,</span><span class="s">&#39;light red&#39;</span><span class="p">,</span> <span class="s">&#39;black&#39;</span><span class="p">),</span> <span class="p">]</span> <span class="n">lorem</span> <span class="o">=</span> <span class="p">[</span> <span class="s">&#39;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&#39;</span><span class="p">,</span> <span class="s">&#39;Sed sollicitudin, nulla id viverra pulvinar.&#39;</span><span class="p">,</span> <span class="s">&#39;Cras a magna sit amet felis fringilla lobortis.&#39;</span><span class="p">,</span> <span class="p">]</span> <span class="k">def</span> <span class="nf">keystroke</span> <span class="p">(</span><span class="nb">input</span><span class="p">):</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;Q&#39;</span><span class="p">):</span> <span class="k">raise</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ExitMainLoop</span><span class="p">()</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="s">&#39;enter&#39;</span><span class="p">:</span> <span class="n">focus</span> <span class="o">=</span> <span class="n">listbox</span><span class="o">.</span><span class="n">get_focus</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">content</span> <span class="n">view</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span> <span class="s">&#39;selected: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">focus</span><span class="p">)),</span> <span class="s">&#39;head&#39;</span><span class="p">))</span> <span class="n">items</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span> <span class="n">items</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">ItemWidget</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">lorem</span><span class="p">)))</span> <span class="n">header</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">AttrMap</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&#39;selected:&#39;</span><span class="p">),</span> <span class="s">&#39;head&#39;</span><span class="p">)</span> <span class="n">listbox</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ListBox</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">SimpleListWalker</span><span class="p">(</span><span class="n">items</span><span class="p">))</span> <span class="n">view</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Frame</span><span class="p">(</span><span class="n">urwid</span><span class="o">.</span><span class="n">AttrWrap</span><span class="p">(</span><span class="n">listbox</span><span class="p">,</span> <span class="s">&#39;body&#39;</span><span class="p">),</span> <span class="n">header</span><span class="o">=</span><span class="n">header</span><span class="p">)</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">palette</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="n">keystroke</span><span class="p">)</span> <span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span> <span class="n">main</span><span class="p">()</span> </code></pre> </div> <p>Their are certainly others ways to do this, but as I&rsquo;m learning Urwid, I didn&rsquo;t find this information so easily, so I though I could be useful to someone else who will want have a try with Urwid.</p> <p>This list, even if it&rsquo;s a very basic one, is a common thing, as lots application need some kind of selectable list. I probably publish some more exercises of this kind as I&rsquo;ll go through my learning of Urwid.</p> Urwid for Python, a ncurses library 2011-11-19T00:00:00+01:00 http://www.nicosphere.net/urwid-for-python-a-ncurses-library-2541 <p>This, is the first part of a six posts series on Urwid.</p> <ul> <li><a href="http://www.nicosphere.net/urwid-for-python-a-ncurses-library-2541">Urwid for Python, a ncurses library</a></li> <li><a href="http://www.nicosphere.net/selectable-list-with-urwid-for-python-2542">Selectable List with Urwid for Python</a></li> <li><a href="http://www.nicosphere.net/signals-with-urwid-for-python-2545">Signals with Urwid for Python</a></li> <li><a href="http://www.nicosphere.net/footer-edit-with-urwid-irc-client-like-input-2547">Footer Edit with Urwid, IRC-Client-like input</a></li> <li><a href="http://www.nicosphere.net/several-colored-string-with-urwid-2546">Several colored string with Urwid</a></li> <li><a href="http://www.nicosphere.net/html-output-screenshot-with-urwid-ncurses-library-2552">HTML output screenshot with Urwid ncurses library</a></li> </ul> <p>I really like ncurses programs, it&rsquo;s certainly what I use the most for an every day usage. The <a href="http://docs.python.org/library/curses.html">curses module</a> from Python provides some elements to build an application, it&rsquo;s what I used for my last program <a href="http://tyrs.nicosphere.net">Tyrs</a>. Unfortunately, the module doesn&rsquo;t provide any widgets or advances elements, usually instead of reinvents the wheel, we use a library. As far as I know, Python have only two libraries for ncurses.</p> <ul> <li><a href="http://pypi.python.org/pypi/pyCDK/0.1">PyCDK</a> is some alpha stage library, who doesn&rsquo;t seem to be maintain anymore. It&rsquo;s originally a binding of the CDK library for C. I tried it, but I didn&rsquo;t manage to get it work, maybe I was unlucky. Anyway, I would not advise this library.</li> <li><a href="http://excess.org/urwid/">Urwid</a> is a serious library, who&rsquo;s come with lots of features and widgets, and will be the subject of this post.</li> </ul> <p>Unfortunately, their isn&rsquo;t any others libraries that those two.</p> <p>It&rsquo;s always interesting when starting consider a library to know if their are others programs using it too, a list is provide <a href="http://excess.org/urwid/wiki/ApplicationList">by the website</a>, with some interesting programs, such as wicd-curses, hachoir and the Debian &ldquo;reportbug&rdquo; tool.</p> <p>The most interesting pieces of example to get start with come from <a href="http://excess.org/urwid/examples.html">this page</a>, a set of small programs with screenshot.</p> <p>Urwid come with lots of features and widget, allow you to display a nice layout easily, editing text, 256 colors, utf-8, check box, advance list management, mouse event and much more. The documentation and tutorial is well documented.</p> <p>Urwid is maybe not so easy to get start with if you&rsquo;re not used to play with library, and maybe it&rsquo;s why it isn&rsquo;t more popular but have lots of potential. Urwid has became mature, and after seven years of development as reach the 1.0.0 release few months ago.</p> <p>Here is a traditional Hello World, with a quit keystroke handling.</p> <div class="highlight"><pre><code class="python"><span class="kn">import</span> <span class="nn">urwid</span> <span class="n">txt</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Text</span><span class="p">(</span><span class="s">&quot;Hello World&quot;</span><span class="p">)</span> <span class="n">fill</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">Filler</span><span class="p">(</span><span class="n">txt</span><span class="p">,</span> <span class="s">&#39;top&#39;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">exit</span><span class="p">(</span><span class="nb">input</span><span class="p">):</span> <span class="k">if</span> <span class="nb">input</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;q&#39;</span><span class="p">,</span> <span class="s">&#39;Q&#39;</span><span class="p">):</span> <span class="k">raise</span> <span class="n">urwid</span><span class="o">.</span><span class="n">ExitMainLoop</span><span class="p">()</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">urwid</span><span class="o">.</span><span class="n">MainLoop</span><span class="p">(</span><span class="n">fill</span><span class="p">,</span> <span class="n">unhandled_input</span><span class="o">=</span><span class="nb">exit</span><span class="p">)</span> <span class="n">loop</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> </code></pre> </div> <p>I will soon write some more posts about Urwid, with codes and more technical. This is only a short introduction of Urwid. I hope this post will give you enough reason to give Urwid a try.</p> Tyrs a Microblogging Client based on Ncurses 2011-11-06T00:00:00+01:00 http://www.nicosphere.net/tyrs-a-microblogging-client-based-on-ncurses-2534 <p><a href="http://tyrs.nicosphere.net">Tyrs</a> is a microblogging client, supporting Twitter and Status.net (identi.ca), it&rsquo;s based on console using the <a href="http://en.wikipedia.org/wiki/Ncurses">NCurses</a> module from Python. The release of the 0.5.0 version is a good excuse to introduce Tyrs.</p> <p>Tyrs aims to get a good interaction with a fairly intuitive interface that can provide support ncurses. Tyrs tries also not to impose choices to the user by providing a configuration file for features, display and defaults keys. You don&rsquo;t like borders, space between tweets, or colors? It&rsquo;s all configurable in an INI-like file.</p> <p>It&rsquo;s really for the fun I started Tyrs, as I&rsquo;m not a developer. I chose to start this project because I use it, as well as educational purpose. Moreover, contrary to what you should believe, I am not a big Twitter user, just a little regular user, wanting to have pleasure to write a program. The first lines are from May</p> <p>The license used is GPLv3, its development is carried out on <a href="https://github.com/Nic0/tyrs">a repository on Github</a>, the code source is also available in the <a href="http://pypi.python.org/pypi/tyrs">pypi page</a>. Tyrs is Free Software.</p> <p>I first used other clients, GUI or CLI, but the CLI alternatives doesn&rsquo;t correspond specifically to my expectations. There are mainly:</p> <ul> <li><a href="http://www.bitlbee.org/main.php/news.r.html">BitleBee</a>, is an application to be added to IRC client such as irssi or weechat. I never was a big fan of bitlebee.</li> <li><a href="http://www.floodgap.com/software/ttytter/">TTYtter</a>, is the application I was using before writing Tyrs. Very complete and mature. His approach does not include however ncurses, and therefore, although it is easily controllable from the keyboard, it doesn&rsquo;t have the interactive that have ncurses software.</li> </ul> <p>Since then, I had the opportunity to discover other microblogging clients, but generally without ncurses support. According to my tastes, I through that there was a lack to find my favorite ncurses Twitter client, and so, fit my console application collection that I use every days.</p> <p>Here a screenshot (<a href="http://pix.toile-libre.org/upload/original/1320604662.png">full screen view</a>) to visualize what we are talking about, it isn&rsquo;t my timeline, but someone&rsquo;s public timeline.</p> <p>![Screenshot of Tyrs] (http://pix.toile-libre.org/upload/img/1320604662.png)</p> <p>Let&rsquo;s go a little deeper into of Tyrs with an overview of the main features.</p> <ul> <li>Timelines <ul> <li>Home: Used to view your tweets timeline, similar to what you have on your home page of the site.</li> <li>Mention: Includes tweets containing your nickname.</li> <li>Direct: Includes messages sent privately.</li> <li>Favorites: Displays tweets who has been bookmarked.</li> <li>Other &hellip;</li> </ul> </li> </ul> <p>The Timelines are navigable with the arrow keys or with &lsquo;j&rsquo; and &lsquo;k&rsquo;. We could be compared to buffers of a ncurses IRC client.</p> <p>This way of separate timelines is quite close to what can be seen in the microblogging classic clients with a graphical interface. It&rsquo;s probably a reason why the interface is intuitive even if it&rsquo;s a console application.</p> <ul> <li>Indicator of activities</li> </ul> <p>As we can display only one timeline, the indicator of activity indicates whether new notices have appeared in other timelines, this detail avoids having to navigate between timelines only to check for new incomings. A counter can also quantify the activity. This place can also view the timeline currently selected. Location is at the top right.</p> <ul> <li><p>Standard features:</p> <ul> <li>OAuth authentication;</li> <li>Follow / Unfollow, ie subscribe to a feed of persons;</li> <li>Search for a particular keyword;</li> <li>Favorites;</li> <li>Direct messages;</li> <li>Opening direct URLs;</li> </ul> </li> <li><p>Various</p> <ul> <li>Retweets Counter: This is a detail, but after using it a while, I must say that I am used to. The purpose is to indicate the number of times a tweet has been relayed (retweeted). It is therefore a possibility to visualize in real time, popularity of a status.</li> <li>Support URL shortener, so far, the main services are supported ur1.ca, bit.ly and goo.gl.</li> <li>Proxy support through the configuration file. This is one of the latest feature added.</li> <li>Filter system for tweets that do not contain URLs, the system that can filter by name. It&rsquo;s a way to reduce <em>noise</em>.</li> <li><em>Waterline</em> to identify the last tweet read in the last use, it is re-adjusted if necessary by just a key strock.</li> <li>View a thread to get the conversation history. The answers to a tweet are viewable by an envelope icon (✉).</li> <li>Ability to start several instances of Tyrs, passing as argument &lsquo;-a account&rsquo;.</li> </ul> </li> </ul> <p>The number of keys shortcut can be confusing at first, the most common is displayed at the bottom of the screen, that can be switched off, and a help screen is available by pressing &lsquo;h&rsquo;.</p> <p>As mentioned in the introduction, the main idea is to leave the choice up to the user, and most behavior is customizable through a configuration file, that is also generated at startup to ease your first customization.</p> <p>Tyrs has been translated into French and Spanish, so this may seem anecdotal, but it isn&rsquo;t for me because is a real example of what I like in free software, opportunities for contributions and exchange of humans from all horizons, not speaking a word of Spanish, but it&rsquo;s indeed a contribution straight from Venezuela, which is given to Tyrs. Other aids to correct my poor English thanks to <a href="http://jasonwryan.com/">jasonwryan</a> from Arch Linux, or proposals for patches and bug reports and the packaging for distribution, including Frugalware. Contributions and help which are always appreciated, especially because it&rsquo;s a small project.</p> <p>If I am passionate about programming, I also have another focus is to keep a blog. I mention here is not to make an advertisement, but because I think <a href="http://www.nicosphere.net/tag/tyrs/">the topics about Tyrs</a>(unfortunately in French) are indicative of the state of mind in which I came to write Tyrs, Speaking of this little program is the first time early in its design, while the feature was only able to read his instructions without being able to to send. There are some form of narrative developments and problems sometimes encountered in darkness, discovering ncurses for Python.</p> <p>For installation, more details are on <a href="http://tyrs.nicosphere.net/reference.html">the documentation page</a>, a package is available for Arch Linux and Frugalware, in the case of Arch Linux, you simply do:</p> <pre><code>yaourt -S tyrs </code></pre> <p>Tyrs are mainly tested with Python 2.7, I&rsquo;m not sure of the result obtained with earlier versions of Python. However if you have this version of Python and python-pip installed you can do:</p> <pre><code>pip install tyrs </code></pre> <p>Tyrs is not perfect, far from it, as seen above, support for Python prior to 2.7 is not really tested. Another black, is editing a record, I&rsquo;m really not satisfied with the system before, I think I would see to rewrite that part in-depth, something I wanted to do for a long time, but always rejected. Certainly other bugs, depending of the moon and distribution of butterflies.</p> <p>I opened a thread on the <a href="https://bbs.archlinux.org/viewtopic.php?id=119588">Arch Linux Forum</a>.</p> <p>Free Software often come with <a href="http://www.gnu.org/s/gsl/manual/html_node/No-Warranty.html">no warranty</a> but I did my best not to introduce bugs. I&rsquo;m interested in all returns, regardless of the form, comments, bug reports, patches. Most important thing is I really enjoyed write Tyrs.</p> <p>Some usefull links to learn more about Tyrs:</p> <ul> <li><a href="http://tyrs.nicosphere.net">Project Home Page</a></li> <li><a href="http://tyrs.nicosphere.net/reference.html">Project Documentation</a></li> <li><a href="https://github.com/Nic0/tyrs">Project on Github</a></li> <li><a href="http://pypi.python.org/pypi/tyrs">Project on Pypi</a></li> </ul> Why AUR is part of the Arch Linux success 2011-11-01T00:00:00+01:00 http://www.nicosphere.net/why-aur-is-part-of-the-arch-linux-success-2529 <p>If you usually follow some blogs about Linux, especially those on Arch Linux, there is a common word that you are come across often, <em>AUR</em>, acronym of <em>Arch User Repository</em>. You might wonder what does it mean, what does it imply for the distribution, and why it&rsquo;s so popular for the Arch Linux community. If you asking yourself those questions, this post is for you.</p> <p>First, you should keep these two characteristics in mind.</p> <ul> <li>Everybody may contribute to AUR.</li> <li>It&rsquo;s really easy to contribute to AUR.</li> </ul> <p>AUR is a kind of repository totally public, open to whoever want to contribute to let some resources available to anyone. No ceremonials, agreement or long ritual initiation to submits a package to AUR.</p> <p>It&rsquo;s as easy to contribute to AUR as to use it, with some <em>AUR helpers</em> such as <code>yaourt</code> or others alternatives. Install a package from AUR isn&rsquo;t more difficult than install one with the official package manager <code>pacman</code>, manager such as <code>apt-get</code> for Debian or Ubuntu. Dependencies and research are easily managed that way. Even a vote system allow credibility about security and code source of a package.</p> <p>The main idea about packaging for <em>AUR</em> is to write some installation directives in a file called <em>PKGBUILD</em>, by simply follow some easy packaging&rsquo;s rules. That&rsquo;s what <em>AUR</em> contain, only directives that gives instruction to the helper on how to build the package. There aren&rsquo;t binary packages in <em>AUR</em>.</p> <p>The fact that a <em>PKGBUILD</em> is easy to write increase the idea that everyone can contribute to <em>AUR</em> given that the repository is open to everyone. If you managed to install Arch Linux by yourself, you should be able to find out how to write <em>PKGBUILD</em>. Of these two ideas, easy to contribute, and for everyone, resulting implications very beneficial for Arch Linux.</p> <p>For example, a person who have some practice with it, can make a script or a program available within few minutes (which was the case for example to offer <a href="http://www.nicosphere.net/suivre-hacker-news-depuis-la-console-2372/">hacker-top</a> and <a href="http://www.nicosphere.net/suivre-reddit-depuis-la-console-2392/">reddit-top</a> a bit on a whim). If more time was needed, would I have done it? probably not. This is also beneficial for the user, so you may easily enjoy interesting programs that would not be known however.</p> <p>This simplification of the provision also encourages some exotic applications, with for example some very recent drivers that would not be incorporated otherwise. But also with the latest programming frameworks in vogues. Knowing that a framework can gain very big reputation in a short time. So latest framework can be available easily and quickly to users. Most importantly, it allows them to be updated, This is important if the evolution is rapid. For example, if I try Node.js, I do not want the version of last year, but the latest. Same for Ruby on Rails, I do not want to watch a version of Ruby, which may not be compatible with the latest Rails. This last example taken from a real example, when we saw on the forums concerns about running Rails with version 3, especially for Debian. All installed cleanly with a packet manager, not by hand as we see often advisable in such cases.</p> <p>All this convenience, and the non-formality could even be quantified. The website, <a href="http://aur.archlinux.org/">front-end of AUR</a>, announces 32,000 packages available for archers, it&rsquo;s more than 29,000 packages <a href="http://www.debian.org/">debian announced on their home page</a>. So I know that is not the same and that is not far from being a troll, but it is a fact that Arch Linux has a community and a number of developers much less important than Debian, and is undeniable, for this system, Arch Linux is able to offer to his users almost as many packages.</p> <p>From the maintainer&rsquo;s point of view, those concerned with the <code>[community]</code> repository, they can easily demote a package in AUR so it was officially supported, without worrying to much about consequences, associated with the fact that Arch Linux only supports two architectures, not dragging dozen architecture to their credit. these two points I believe are the key to their reactivity, and can keep a small core team (no more than two dozen core-dev, without TU&rsquo;s). A responsiveness of a small team to a rolling release enough stable to interest a median users of Linux.</p> <p>AUR also allows a developer to easily share its application, whatever the language chosen, each language generally offers opportunities, such as <code>pip</code> (python) <code>gem</code> (ruby), it is still nice to have an opportunity to ensure the smooth running of installation on its own distribution. Simplify installation and distribution of software that is not known and still under development, is a good way to promote an application. Furthermore, PKGBUILD allows be easily coupled to a manager for review as git or svn, allowing for easier returns on development issues by an user.</p> <p>Among all these points, everyone&rsquo;s winner, from the median user to developers. I hope that with these explanations, far from being exhaustive, the success of the AUR for Arch Linux is more clear implications that can be blurred at first.</p> <p>Without AUR, Arch Linux would no longer be the same.</p> <p><em><strong>Edit</strong>: More comments on <a href="http://news.ycombinator.com/item?id=3181579">Hacker News</a>, or on <a href="http://www.reddit.com/r/archlinux/comments/lwbvv/why_aur_is_part_of_the_arch_linux_success/">Reddit</a>.</em></p> Comparison of major Linux distributions forums 2011-08-30T00:00:00+02:00 http://www.nicosphere.net/comparison-of-major-linux-distributions-forums-2473 <p>It could be useful to visualize the registrations of the major Linux distribution forums, and gives an idea of the health of each one. This is what it will be done here. <a href="http://www.nicosphere.net/petit-bilan-de-sante-darch-linux-2438/">A previous article</a>(French) describe step by step the procedure used to retrieve registrations date from forums, based on scrapy to crawl the forum and pylab to draw graphs.</p> <p>There is two kind of graphics, sums of registrations per months, and per day. The first one is better to visualize average, second one give more accurate graphs. As the last month (august) isn&rsquo;t complete, there is a fall in last spot for months graphs. To collects data, I took my time, make sure it was accurate, check between number of the file entry, and what it&rsquo;s actually said in the forum. In doubt I run tests twice.</p> <p>Bellow is a list of forums that I goes through here. They are major forum for each distribution, witch I added some French one to compared the accuracy.</p> <ul> <li><a href="#archlinux">Arch Linux</a> <ul> <li>archlinux.org</li> <li>archlinux.fr</li> </ul> </li> <li><a href="#ubuntu">Ubuntu</a> <ul> <li>ubuntu.org</li> <li>ubuntu-fr.org</li> </ul> </li> <li><a href="#debian">Debian</a> <ul> <li>debian.org</li> <li>debian.fr</li> </ul> </li> <li><a href="#fedora">Fedora</a></li> <li><a href="#mint">Linux Mint</a></li> <li><a href="#pclinuxos">PCLinuxOs</a></li> <li><a href="#puppy">Puppy</a></li> <li><a href="#gentoo">Gentoo</a></li> <li><a href="#sabayon">Sabayon</a></li> <li><a href="#chakra">Chakra</a></li> <li><a href="#mandriva">Mandriva</a></li> <li><a href="#opensuse">OpenSuse</a></li> <li><a href="#conclusion">Conclusion</a></li> </ul> <hr /> <h2><a name="archlinux">Arch Linux</a></h2> <h3>Archlinux (en)</h3> <ul> <li>Website: http://bbs.archlinux.org</li> <li>Members: 37,331</li> <li>1st registration: 2002-08-12</li> </ul> <p><a href="/img/archlinuxorg1.png"><img class="size-medium wp-image-2446 " title="archlinuxorg" src="/img/archlinuxorg1-300x165.png" alt="" width="300" height="165" /></a></p> <p><a href="/img/archlinuxorgday.png"><img src="/img/archlinuxorgday-300x163.png" alt="" title="archlinuxorgday" width="300" height="163" class="size-medium wp-image-2468" /></a></p> <h3>Archlinux (fr)</h3> <ul> <li>Website: http://forums.archlinux.fr</li> <li>Members: 3,040</li> <li>1st registration: 2006-08-11</li> </ul> <p><a href="/img/archlinuxfr.png"><img class="size-medium wp-image-2445 " title="archlinuxfr" src="/img/archlinuxfr-300x168.png" alt="" width="300" height="168" /></a></p> <hr /> <h2><a name="ubuntu">Ubuntu</a></h2> <h3>Ubuntu (en)</h3> <ul> <li>Website: http://ubuntuforums.org</li> <li>Members: 1,416,637</li> <li>1st registration: 2004-10-07</li> </ul> <p>This site doesn&rsquo;t have any memberlist, this option was deactivate, so I needed to go through every members profile. This wouldn&rsquo;t be a problem if the forum hasn&rsquo;t 1.4 million members. So I took only one of every ten members, based on the id number. This give 140,000 members crawled. So, the graphic is not the exact reality, but close enough I&rsquo;m sure.</p> <p>The last raise is surprising, and doesn&rsquo;t appear on the French one, It might be some spam, such as with the Debian one (we see this one right after). It not easy to be sure, as they don&rsquo;t provide a user list.</p> <p><a href="/img/ubuntuorg.png"><img class="aligncenter size-medium wp-image-2455" title="ubuntuorg" src="/img/ubuntuorg-300x161.png" alt="Registration per months (x10) for Ubuntu forum" width="300" height="161" /></a></p> <p><a href="/img/ubuntuorgday.png"><img class="size-medium wp-image-2456" title="ubuntuorgday" src="/img/ubuntuorgday-300x174.png" alt="" width="300" height="174" /></a></p> <h3>Ubuntu (fr)</h3> <ul> <li>Website: http://forum.ubuntu-fr.org/</li> <li>Members: 171,126</li> <li>1st registration: 2004-12-17</li> </ul> <p><a href="/img/ubuntufr.png"><img class="size-medium wp-image-2457" title="ubuntufr" src="/img/ubuntufr-300x164.png" alt="" width="300" height="164" /></a></p> <p><a href="/img/ubuntufrday.png"><img class="size-medium wp-image-2458" title="ubuntufrday" src="/img/ubuntufrday-300x161.png" alt="" width="300" height="161" /></a></p> <hr /> <h2><a name="debian">Debian</a></h2> <h3>Debian (en)</h3> <ul> <li>Website: http://forums.debian.net/</li> <li>Members: 37,567</li> <li>1st Registration: 2004-02-15</li> </ul> <p>This forum has recently lots of spam user, they aim to have a backlink in the member list. The list contain lots of not Linux related links.</p> <p><a href="/img/debiannet.png"><img class="size-medium wp-image-2448" title="debiannet" src="/img/debiannet-300x168.png" alt="" width="300" height="168" /></a></p> <h3>Debian (fr)</h3> <ul> <li>Website: https://www.debian-fr.org/</li> <li>Members: 9,859</li> <li>1st registration: 2003-02-28</li> </ul> <p><a href="/img/debianfr.png"><img class="size-medium wp-image-2447" title="debianfr" src="/img/debianfr-300x170.png" alt="" width="300" height="170" /></a></p> <hr /> <h2><a name="fedora">Fedora</a></h2> <h3>Fedora (en)</h3> <ul> <li>Website: http://forums.fedoraforum.org/</li> <li>Members: 172,622</li> <li>1st registration: 2004-01-26</li> </ul> <p><a href="/img/fedora.png"><img src="/img/fedora-300x168.png" alt="" title="fedora" width="300" height="168" class="size-medium wp-image-2449" /></a></p> <p><a href="/img/fedoraday.png"><img class="size-medium wp-image-2450" title="fedoraday" src="/img/fedoraday-300x163.png" alt="" width="300" height="163" /></a></p> <h3>Fedora (fr)</h3> <ul> <li>Site: http://forums.fedora-fr.org</li> <li>Membres: 20,837</li> <li>1ère inscription: 2002-01-19</li> </ul> <p><a href="/img/fedorafr.png"><img src="/img/fedorafr-300x159.png" alt="Inscription par mois sur le forum Fedora (fr)" title="fedorafr" width="300" height="159" class="aligncenter size-medium wp-image-2477" /></a></p> <p><a href="/img/fedorafrday.png"><img src="/img/fedorafrday-300x165.png" alt="Inscription par jour sur le forum Fedora (fr)" title="fedorafrday" width="300" height="165" class="aligncenter size-medium wp-image-2478" /></a></p> <hr /> <h2><a name="mint">Linux Mint</a></h2> <ul> <li>Website: http://forums.linuxmint.com/</li> <li>Members: 53,972</li> <li>1st registration: 2006-11-15</li> </ul> <p><a href="/img/linuxmint.png"><img class="size-medium wp-image-2452" title="linuxmint" src="/img/linuxmint-300x166.png" alt="" width="300" height="166" /></a></p> <p><a href="/img/mintday.png"><img src="/img/mintday-300x165.png" alt="" title="mintday" width="300" height="165" class="size-medium wp-image-2472" /></a></p> <hr /> <h2><a name="pclinuxog">PCLinuxOs</a></h2> <ul> <li>Website: http://www.pclinuxos.com/forum/</li> <li>Members: 6,194</li> <li>1st registration: 2006-01-18</li> </ul> <p><a href="/img/pclinuxos.png"><img src="/img/pclinuxos-300x168.png" alt="" title="pclinuxos" width="300" height="168" class="size-medium wp-image-2466" /></a></p> <hr /> <h2><a name="puppy">Puppy</a></h2> <ul> <li>Website: http://murga-linux.com/puppy/</li> <li>Members: 18032</li> <li>1st registration: 2005-05-04</li> </ul> <p><a href="/img/puppy.png"><img src="/img/puppy-300x169.png" alt="" title="puppy" width="300" height="169" class="size-medium wp-image-2471" /></a></p> <hr /> <h2><a name="gentoo">Gentoo</a></h2> <ul> <li>Website: http://forums.gentoo.org/</li> <li>Members: 133,317</li> <li>1st registration: 2002-04-08</li> </ul> <p><a href="/img/gentoo.png"><img class="size-medium wp-image-2451" title="gentoo" src="/img/gentoo-300x162.png" alt="" width="300" height="162" /></a></p> <p><a href="/img/gentooday.png"><img class="size-medium wp-image-2459" title="gentooday" src="/img/gentooday-300x165.png" alt="" width="300" height="165" /></a></p> <hr /> <h2><a name="Sabayon">Sabayon</a></h2> <ul> <li>Website: http://forum.sabayon.org/</li> <li>Members: 27,869</li> <li>1st registration: 2005-10-14</li> </ul> <p><a href="/img/sabayon.png"><img src="/img/sabayon-300x161.png" alt="Registration per month for Sabayon forum" title="sabayon" width="300" height="161" class="aligncenter size-medium wp-image-2469" /></a></p> <p><a href="/img/sabayonday.png"><img src="/img/sabayonday-300x162.png" alt="" title="sabayonday" width="300" height="162" class="size-medium wp-image-2470" /></a></p> <hr /> <h2><a name="opensuse">OpenSuse</a></h2> <ul> <li>Website: http://forums.opensuse.org/</li> <li>Members: 61,223</li> <li>1st registration: 2007-06-25</li> </ul> <p><a href="/img/opensuse.png"><img src="/img/opensuse-300x164.png" alt="Registration per month for OpenSuse forum" title="opensuse" width="300" height="164" class="aligncenter size-medium wp-image-2463" /></a></p> <p><a href="/img/opensuseday.png"><img src="/img/opensuseday-300x166.png" alt="" title="opensuseday" width="300" height="166" class="size-medium wp-image-2464" /></a></p> <hr /> <h2><a name="mandriva">Mandriva</a></h2> <ul> <li>Website: http://forum.mandriva.com/en/</li> <li>Members: 67,460</li> <li>1st registration: 2001-12-16</li> </ul> <p><a href="/img/mandriva.png"><img src="/img/mandriva-300x163.png" alt="" title="mandriva" width="300" height="163" class="size-medium wp-image-2460" /></a></p> <p><a href="/img/mandrivaday1.png"><img src="/img/mandrivaday1-300x170.png" alt="" title="mandrivaday" width="300" height="170" class="size-medium wp-image-2465" /></a></p> <p><a href="/img/mandrivaday2.png"><img src="/img/mandrivaday2-300x168.png" alt="" title="mandrivaday2" width="300" height="168" class="size-medium wp-image-2462" /></a></p> <hr /> <h2><a name="chakra">Chakra</a></h2> <ul> <li>Website: http://chakra-project.org/bbs/</li> <li>Members: 4,614</li> <li>1st registration: 2008-12-15</li> </ul> <p><a href="/img/chackra.png"><img src="/img/chackra-300x163.png" alt="" title="chackra" width="300" height="163" class="size-medium wp-image-2467" /></a></p> <hr /> <h2><a name="conclusion">Conclusion</a></h2> <p>I started this mainly to test scrapy with a real example, but curiosity push me to conduct those tests for major Linux distribution. I really thinks this reflect the reality, of each distributions popularity. It&rsquo;s interesting to compare results with DistroWatch, specially as the provide result from past years.</p> <p>Few distributions missing, as CentOS, Knoppix, Frugalware, but I had some difficulties to retrieve results from them forum. And Frugalware as not enought members to make result, less than one hundred, due to a very young forum.</p> <p>As I said <a href="http://www.nicosphere.net/petit-bilan-de-sante-darch-linux-2438/">last time</a>, yes, Arch Linux doing well. I was surprise with the rise of Linux Mint, confirm with the result from DistroWatch, between first and second place with Ubuntu. I&rsquo;m surprise too than Fedora didn&rsquo;t get a rise when Ubuntu turn to Unity, as Arch Linux had. And I&rsquo;m glade that Gentoo come back.</p> <p>At last, a small ranking of the health of the Linux distributions:</p> <ul> <li>Good health: Arch Linux, Linux Mint, PCLinuxOs,</li> <li>Stagnant: Ubuntu, Debian</li> <li>Not so good: Fedora, Puppy, Sabayon, Gentoo</li> <li>Bad shape: Mandriva, OpenSuse, Chakra</li> </ul>