elarson’s posterous

 
Filed under

emacs

 

Noticing Small Features

We recently returned from a tour. While on the road, I'm still working. I have a slick bean bag chair, curtains and MiFi router, which makes it possible to get my work done while cruising down the freeway. This is something I've discussed before.

My two recent annoyances with my setup are not having an automatic way of completing an email address and slow updates to the server. So far, the slow updates will probably involve setting up a local IMAP server to sync to and from. It is something that I've started looking into, but haven't spent that much time on it. It ends up being easy enough to just ignore email and save the time. What is rather annoying is having to enter email addresses.

It is not that bad, but it is relatively time consuming. My typing could be much better and it can be easy to make mistakes. Also, there are many times I'm copying the email address from some other resource such as a web page or IRC, in which case, there is a lot of buffer management to deal with. Again, not a huge deal but enough to warrant looking into solutions.

Fortunately, like most things in the Emacs landscape, there was already a good solution in place. The BBDB or the Insidious Big Brother Database. I initially tried using the tips mentioned on emacs-fu but found it didn't work. Fortunately, I found the solution was incredibly convenient and directly in the Wanderlust docs. The result, is now I'm collecting email addresses for completion much like I would get in gmail in addition to having an actual addressbook I might consider using. Pretty nice ROI for googling a bit.

This is realization you need a feature is a pretty common occurance in Linux. The conceptual basis is usually there to create a solution, but often times it takes a bit of work to really get things configured. Emacs is very similar, with the exception being it is almost expected that the configuration might very well be writing a new mode or piece of functionality yourself. It serves as a good reminder that I shouldn't go recommending Emacs to my parents anytime soon. Although it would be pretty cool if I did get a call from my dad asking about setting up a keybinding for some lisp function he wrote.

Loading mentions Retweet
Filed under  //   emacs   programming  

Just Checking In

Today I had the desire to write something down, but really didn't have a concise idea of what to write about. So this post is just going to be a small summary of some thoughts and experiences.

Free Software and Open Source

I recently read the RMS opinion on Codeplex and Miguel's response. After a quick glance over at planet gnome I noticed a few people taking sides and it occurred to me that the whole argument is rather silly. When I was in college the concept of free software made a ton of sense. Looking back it was because I didn't have any money, so generally anything free made a ton of sense. Now that I'm a full fledged tax paying adult, the glamour of free software has lost its glitz. It is not that free software has become unimportant or useless. What has happened, in my mind at least, is the arguments associated with free software have become rather stale. By stale, I simply mean it isn't anything exciting for me personally. I think free software is critical, but I have better things to do than care about it in its own right. I'm probably just getting old, but it was an interesting realization for me nonetheless.

Test Driven Development

At work I've been trying to improve my tests. By "improve" I really mean write them in earnest. It is a really difficult thing to write code using TDD. It is a similar approach to modeling in that it forces you to consider an abstract idea of what some code should do and look like. TDD is sort of like UML in the age of Ruby on Rails, which is kind of funny as the recent web frameworks and NoSQL all suggest rapid prototyping over planning before coding. While both UML and TDD are doing pretty much the same in terms of hashing out code, the obvious benefit of TDD is that you get something that can be used in the future. At the same time, a well tested code base is not that important if the tests are bad and are hard to run. Testing in web browsers is the most obvious case in point. The larger point then is obviously that planning, whether through tests, visio or some hodge podge of tools, is helpful for writing better code. It might also be argued that it is faster since the design is fleshed out to some extent, but I would ask if the time spent planning is included in that calculation and if it is a real calculation at all. Programmers have a nasty habit of estimating because of the constant requirement to create hypotheses in debugging. My bet is that many of the virtues of TDD (like UML as well) are overblown and the only real benefit is forcing a developer to focus on what the problem is. One of my issues is that it creates a whole new class of code that deals with testing. This is totally fine, but where are tests for the tests! It seems like a story that we'll probably never see the end of.

Text Browsing

I'm going to suggest that if you're a programmer, it would treat you well to try out a good text web browser. My recommendation is w3m due to its Emacs integration, but anything that can keep you in your work environment works. My guess is vimmers would get similar usage from links/lynx assuming the terminal is their environment. The reason being is that if you are constantly editing text and reading it in your dev environment, browsing the web textually can be a helpful tool to keep focus. For me, I get the same keybindings, easy copy and pasting, and simpler window/frame/buffer management. Beyond this though, it feels faster when it comes to reading documentation and finding helpful code. Your milage may vary, but it sure couldn't hurt to try.

Administering Systems

At work we recently rolled out a new system. It isn't actually new, but is in fact the latest step in an improvement to a current system. What always strikes me about the smart folks I work with is how gracefully they walk the line between system administrator and programmer. The two fields are completely intertwined, but the best programmers are those that have the better understanding of both sides. This is probably partly why I'm not that great of a programmer! For whatever reason, my mind doesn't ever seem to really indulge in the system administration side of things. It is always a challenge for me to make pre-existing software work the way I think it should. That doesn't mean I'm not trying of course! But it does mean that I have a ton to learn and will for the foreseeable future.

ACL Wrap Up

This past weekend was ACL in Austin and it was a blast. We saw Them Crooked Vultures, The Walkmen, School of Seven Bells, Broken Social Scene and some guys from Phoenix DJ. We also played a show with The Riverboat Gamblers and The Soldier Thread. It was a ton of fun. On the road we don't really get to hang out that much. There is usually somewhere to drive, something to load or unload or something to sell that usually keeps us busy. It was great to come home, rest and then have a great weekend of music and friends. We didn't go to ACL proper and I'm glad. There were plenty of bands I would have liked to catch but the weather was horrid and my guess is I would have been pretty miserable in the mud. Hopefully next year there will be some nicer weather. Who knows, maybe we'll even get to play!

Loading mentions Retweet
Filed under  //   emacs   music   programming  

Finally Using Emacs for Web Browsing and Email

It has taken a long time, but I've finally managed to get email working relatively well in Emacs! In the end Wanderlust was the client of choice for me. It has a pretty simple file format for organizing mail and the keybindings have already begun to be rather natural. The reasoning behind my quest for merging my email and emacs had more todo with my recent tour than an actual desire or need for checking mail in my text editor. I was perfectly happy with Gmail and in fact I'm technically still using it through IMAP. The real reason was that I wanted to try and reduce my bandwidth usage. On tour I had a 5 Gig cap on my network usage. Having never really monitored this sort of thing before, I had no idea how much bandwidth things like IRC might use when you're talking about every day, all day usage. To make things worse, I forgot to grab the USB cable that would let me check my current usage for the month, so I was essentially flying blind!

My fear of an enormous bill made me consider what I could do reduce my bandwidth. The obvious avoidance of listening to music and watching videos was easy. Also, reading local versions of docs was another helpful tactic. This lead me to see a few things about w3m, which I had tried to use before in Emacs. It dawned on me that things like code examples viewed in a text based web browser makes nothing but sense in my text editor. It makes things like copying and pasting code samples a breeze. After getting used to w3m in Emacs it became clear that I should really try to finally tackle email. As I said, Gmail has been just fine, so the motivation wasn't very strong to move. The killer feature in my mind was tying things into my todo list and avoiding Gmail's constant stream of Ajax requests. I'm sure the bandwidth savings are practically nothing, but nonetheless, it seemed like if I got things working it might really be helpful in ways similar to w3m.

Once things were configured and I managed to get everything working, I did notice some helpful bits. Silly annoyances that really should never have been a problem smoothed out. I'm talking about basic copy and paste issues I noticed here and there when working with Emacs and the rest of my desktop. Little things like working with Trac was also a good deal faster, although it was something of a let down that I couldn't submit updates to tickets. Finally, it seems more reasonable to keep up with mailing lists as most of the necessary content (code) is close at hand. This last aspect seems to be the biggest draw of using Emacs. I primarily write code and keeping more tools inside Emacs makes it faster to transition between those tools and the code I'm working on. Of course it does seem kind of cool in a geeky way to work almost solely in text, but the main nicety is actually being more productive. I'm hoping in the next couple weeks things can continue to become a little more streamlined. The killer app that I would like to find a good Emacs replacement for is my feed reader. Google Reader is great but something more bare might help to move through things faster and generally filter out the cruft. That said, blogs were one of the first things I cut out in my quest to lower bandwidth. My desire to check what is new in the blogosphere has greatly diminished since taking a break. I'd like to potentially keep it that way for a while.

Loading mentions Retweet
Filed under  //   emacs   programming  

My Org-Mode Server

I went ahead and started working out how to get my todo list online. I started off pretty simple and ended up with a relatively nice system. The basic idea is that I can push my org files to my webserver and edit them. Likewise, I can pull from the server. It started with some simple paver scripts that uploaded the files and quickly became an actual application.

Here is the paver file for some of the operations:


import os
from mercurial import commands, ui, hg
from paver.easy import *
import subprocess

IONROCK_HG = 'ssh://eric@ionrock.org/path/to/todos/'
REMOTE_TODO = IONROCK_HG # '/local/dev/path/to/todos'

@task
def server():
    import cherrypy
    cherrypy.tree.graft(TodoServer(base_url='/'), '/')
    cherrypy.quickstart()

@task
def create_repo():
    cmd = subprocess.call("fab create_repo:hosts='ionrock.org'", shell=True)

@task
def commit():
    conf = ui.ui()    
    user = conf.username()
    repo = hg.repository(conf, '.')
    files = [f for f in os.listdir('.') if f.endswith('.org')]
    commands.add(conf, repo, *files)
    commands.commit(conf, repo, addremove=True, message='Syncing org files')
    commands.push(conf, repo, REMOTE_TODO)

@task
@needs('commit')
def pull():
    conf = ui.ui()    
    user = conf.username()
    repo = hg.repository(conf, '.')
    commands.pull(conf, repo, REMOTE_TODO)
    commands.update(conf, repo)

@task
@needs('commit')
def update():
    cmd = subprocess.call("fab update_todos:hosts='ionrock.org'", shell=True)
    

The server task was for starting the eventual web application for development. The commit task just automatically commits the current org files and pushes them to the remote server. The pull command does the commit first, then pulls from the remote server. These two commands uses the mercurial libraries to work with the mercurial repos.

The create_repo was just a simple task to create an mercurial repo. More interesting is the update task which updates the remote todo mercurial repo. I'm using fabric for this aspect. It was all really easy. Here is the fabfile:


from fabric import run

def update_todos():
    run('cd /home/eric/htdocs/todo && hg up')

def create_repo():
    run('cd /home/eric/htdocs/todo && hg init')

Hopefully it is really clear what is happening here. Fabric lets you run commands via ssh on a remote server.

The actual todo server is a bit longer but also pretty simple.


import os
import re
import posixpath as path
import difflib
from selector import Selector
from webob import Response, Request
from webob.exc import *
from mercurial import commands, ui, hg
import datetime


class TodoFile(object):
    def __init__(self, fn):
        self.fn = fn
        self.html_diff = difflib.HtmlDiff()
        self.diff = difflib.Differ()
        self.matcher = difflib.SequenceMatcher()
        lines = [l for l in open(fn, 'r')]
        self.matcher.set_seq2(lines)

    def _hg(self):
        conf = ui.ui()
        user = conf.username()
        repo = hg.repository(os.path.dirname(self.fn))
        return conf, repo, user

    def __str__(self):
        return ''.join(self.read())
    
    def read(self):
        return [l for l in open(self.fn, 'r')]

    def write(self, new):
        f = open(self.fn, 'w')
        clean = re.sub('\r', '', new)
        f.write(new)
        f.close()
        conf, repo, user = self._hg()
        date = datetime.datetime.now().strftime('%m-%d-%y %H:%M')
        commands.commit(conf, repo, message='Web write on %s' % date)
        
    def is_different(self, new):
        self.matcher.set_seqs(new.split('\n'), self.read())

    def diff_txt(self, new):
        return list(difflib.context_diff(new.split('\n'), self.read()))

    def diff_html(self, new):
        return self.html_diff.make_file(self.read(), new.split('\n'))        
    

class TodoStore(object):
    def __init__(self, directory):
        self.dir = os.path.abspath(directory)

    def get_todo(self, name):
        for fn in os.listdir(self.dir):
            if fn.endswith('.org') and (fn[:-4] == name):
                return TodoFile(os.path.join(self.dir, fn))
        return false

    def all(self):
        return [fn[:-4] for fn in os.listdir(self.dir) if fn.endswith('.org')]


class Auth(object):
    def __init__(self, creds, login_url, success_url=None):
        self.login_url = login_url
        self.success_url = success_url
        self.creds = creds

    def __call__(self, f):
        def func(env, sr):
            sess = env['beaker.session']
            if sess.get('auth.user'):
                return f(env, sr)
            req = Request(env)
            sess['auth.after_login_url'] = req.url
            sess.save()
            return HTTPSeeOther(location=self.login_url)(env, sr)
        return func

    def login(self, env, sr):
        res = Response()
        sess = env['beaker.session']
        flash = sess.get('flash', '')
        if flash:
            sess['flash'] = ''
            sess.save()
        res.write('''<div>%s</div>
        <form action="%s" method="post">
          <label for="username">Username</label>
          <input type="text" name="username" value=""><br />
          <label for="password">Password</label>
          <input type="password" name="password" value=""><br />
          <input type="submit" value="login" />
        </form>''' % (flash, self.login_url))
        return res(env, sr)

    def handle_login(self, env, sr):
        req = Request(env)
        post = req.POST
        sess = env['beaker.session']        
        if post.get('username') and post.get('password'):
            if self.creds.get(post['username']):
                if self.creds[post['username']] == post['password']:
                    sess['auth.user'] = post['username']
                    url = sess.get('auth.after_login_url', self.success_url)
                    sess.save()
                    return HTTPSeeOther(location=url)(env, sr)
        sess['flash'] = 'Error logging in.'
        sess.save()
        return HTTPSeeOther(location=self.login_url)(env, sr)
            

class TodoServer(object):

    def __init__(self, **config):
        self.conf = {
            'todo_dir': os.path.dirname(os.path.abspath(__file__)),
        }
        self.conf.update(config or {})

        self.auth = Auth(self.conf.get('creds', {}),
                         self.url('login'),
                         self.url())
        

        self.store = TodoStore(self.conf['todo_dir'])

        self.router = Selector([
            ('[/]', {'GET': self.listing}),
            ('/login[/]', {
                'GET': self.auth.login,
                'POST': self.auth.handle_login
            }),
            ('/{name}/edit[/]', {
                'GET': self.edit,
                'POST':  self.auth(self.update)
            }),
            ('/{name}[/]', {'GET': self.read}),
        ])

    def url(self, extras=None):
        extras = extras or ''
        if isinstance(extras, list):
            extras = '/'.join(extras)
        return path.join(self.conf['base_url'], extras)

    def _header(self):
        return '''<html><head>
        <title>org todo server</title>
        <style type="text/css">
        body {
            font-size: 2em; font-family: sans-serif;
        }
        </style>
        '''

    def _footer(self):
        return '''</body></html>'''

    def edit(self, env, sr):
        res = Response()
        req = Request(env)
        name = req.urlvars['name']
        td = self.store.get_todo(name)

        res.write(self._header())
        res.write('''
        <form action="%s" method="post">
        <input type="submit" name="submit" value="save" /><br />        
        <textarea rows="50" cols="80" name="new_body">%s</textarea>
        </form>
        ''' % (self.url('%s/edit' % name), str(td)))
        res.write(self._footer())
        
        return res(env, sr)

    def update(self, env, sr):
        req = Request(env)
        name = req.urlvars['name']
        new_body = req.POST['new_body']
        todo = self.store.get_todo(name)
        todo.write(new_body.strip())
        location = self.url('%s' % name)
        return HTTPSeeOther(location=location)(env, sr)

    def read(self, env, sr):
        res = Response()
        req = Request(env)
        name = req.urlvars['name']

        res.write(self._header())
        res.write('''
        Home | Edit
        <hr />
        <pre>''' % (self.url(), self.url('%s/edit' % name)))
        td = self.store.get_todo(name)
        res.write(str(td))
        res.write('</pre>')
        res.write(self._footer())
        
        return res(env, sr)

    def listing(self, env, sr):
        res = Response()

        res.write(self._header())
        res.write('<ul>\n')
        for f in self.store.all():
            res.write('<li>%s</li>\n' % (self.url(f), f))
        res.write('</ul>\n')
        res.write(self._footer())
        
        return res(env, sr)

    def __call__(self, env, sr):
        return self.router(env, sr)


This is a WSGI app simply because I'm using WSGI for my main application. I save a bit of memory by running all my smaller apps via one WSGI server (CherryPy), which makes a difference as I use a VPS.

One observation I made is that things would have been simpler had I been able to use CherryPy. Things like sessions, form processing and even URL routing would have been built in and made the whole thing a lot simpler in terms of dependencies and actual code.

This also made me realize what the problem is building applications with WSGI. You really need a framework. I don't mean Pylons, web.py or some other WSGI framework. But you will undoubtedly write some glue code to help handle things like request and response objects that help to deal with form handling, sessions and cookies. It is nice to know that it is so easy to create these micro frameworks, but at the same time, it is clear that people would be making bad decisions. I only say that because I'm one of them.

When I think of the micro frameworks I've written throughout the past few years, it is clear that I've had to experiment quite a bit. WebOb was a helpful library for sure, but the API you build translating the request to a WebOb Request means breaking WSGI at some level. That means that you've lost the advantages of WSGI as an API for your application. In my mind, it makes me wonder why then the app was written with WSGI in the first place as there is a solid and proven API already built with something like CherryPy.

I doubt I'll rewrite my whole site anytime soon, but if I do, the application framework will most definitely revolve around the framework rather than WSGI. The advantages that I believed were present ended up being much less than I thought. Having a tool like CherryPy manages to take care of the generic aspects enough while letting me use more opinionated aspects such as templating or databases. You could most certainly substitute your framework of choice, but for me CherryPy is making more and more sense.

Loading mentions Retweet
Filed under  //   emacs   mercurial   python  

Some Org-Mode Workflow

I've got to say that org-mode has been treating me rather well. To contrast this, I also started playing with Evernote on my iphone. In theory, Evernote seems really helpful for working with todo lists. It has been reasonably nice for things like going to the store to buy a list of things. One feature that seemed really helpful was the ability to take a picture of something as a note. I took a picture of a pedal board I was making for Lauren that had some measuremeants on it. Unfortunately, for some odd reason, it wasn't saved. I think this happened when I tried to write a note that went along with the photo. It wasn't a huge deal and I'm sure user error was part of the equation, but I really hope that the photo feature is able to let jot down some notes in addition to simply having a picture.

Going back to org-mode, I found this tutorial. I had read it plenty of times before but it didn't really click what was happening. I was always frustrated that the agenda side of org-mode required configuration. That was probably more a function of my own lack of understanding tweaking my .emacs file than a real negative. Now that I'm more familiar with Emacs Lisp, doing small configuration details in my .emacs doesn't seem like nearly as big a deal. After all, that is what it is there for!

This morning I went ahead and create a few different org files to better manage my todo list items. The next step will be to migrate my current todo file to the different files and start throwing in a few deadlines (C-c C-d). Hopefully once that is working, the agenda side of org can be of more use to me. The end of that tutorial mentions a time log of sorts as well, which seems pretty helpful. The other idea is to use the org clock in/out feature which I've used in the past.

At one of my jobs I had to do a lot of service work that was billable which meant keeping track of time. Org-mode was very helpful there in the end. I did write a small command line utility as well, but maintaining it was just silly. We had an idea for a script we called brain that acted like a catchall for generic tools to help productivity. It was kind of modeled after Paste's paster command. We used IronPython for it and it ended up being somewhat helpful. If I were to do something like that I think I would use Paver. In fact, this gives me an idea!

It will be trivial to write a simple paver command that lets me sync a rendered version of my todo list to my server. I can also use emacs on the server to re-gen the HTML view after editing it. It should be really simple to have an edit window with the text and then regen on the server. The on my home machine, I'll effectively pull down any changes and be on my way. At the very least, pushing via paver will be trivial.

What is nice is that thanks to my recent todo list, I really have been more productive. There have been a million things to do before tour and it hasn't been that bad getting them all done along side taking care of my work. While it is pretty mundane, I'm still really excited.

Loading mentions Retweet
Filed under  //   emacs   programming  

More Time Management

The past day or so I've really been trying to be improving my use of a todo list. Org-mode has been very helpful and I'm trying to figure out how I can better use my iphone. I'd imagine a web app that writes to an org-mode file or something similar might do the trick, but that seems to be a long ways off.

One issue I'm trying to figure out is how to keep my todo list scheduled. It doesn't make sense to schedule everything or force some kind of due date, but having some way to set a deadline seems helpful. Also, when there are things that do have a deadline, it would be nice to schedule a time to take care of them. This past week I've had quite a few errands to take care of to get ready for tour and my todo list has been pretty helpful keeping track of things. My problem has been finding a simple way to make a note that I'm planning to take care of them on a specific day or time.

I'm hoping something like agenda in org-mode might be helpful organizing my todo items and setting a few deadlines. It is obvious having the list is helpful and now I'd really like to move towards improving my understanding of what constitutes a healthy workload. Part of this learning process will most likely end up including a timecard of sorts to help define how much time I'm really spending on things. That is another part of better time management that will probably have to wait a bit, but I'll definitely put it on my todo list.

Loading mentions Retweet
Filed under  //   emacs  

Emacs Regexp Search and Replace

This is mainly just a reminder on how to do a search and replace with emacs using regular expressions.

First step is to find what you want to find using the regexp builder (M-x regexp-builder). I'm going to consider this crucial since emacs regex seems to be a little different from other regex engines (ie Python).

Second, once you have your regex, you define a section to capture for later use. Emacs uses parens as literals in regex, so grouping is done via escaping them:



\(http[|s]\)://\(.*\)


This provides two groups, the "http" and the rest after the "://".

Lastly, you do the actual replace-regex and provide the necessary details. To use something you caputured (put in a group) in your replacement,  you either use "\&" when you have no groups, or "\1" where 1 is the group index (like in other regex engines). Here is some code I used it on:



class SomeTest(SeleniumTest):
    def __init__(self):
        self.t.open('/path/to/test', '')
        self.t.pause('500', '')
        # ... other commands
        self.t.pause('1100', '')
        #.... more commands
        self.t.pause('1500, '')


What I wanted to do was turn all those pause calls to "self.pause(${time})". Here is what I did in emacs:



M-x replace-regexp RET self.t.pause('\([[:digit:]]+\)', '') RET self.pause('\1') RET


Not very difficult, but when you don't practice that sort of thing it becomes easy to forget.

Loading mentions Retweet
Filed under  //   emacs   programming  

Getting Back to Basics

At work there were some changes to the VPN server that seemingly made my ability to connect something of a problem. It turned out to be an issue with my home router, but in the process I went ahead and tried working on Linux instead of OSX. At work other folks are pretty happy with tiling window managers such as Ion3 and AwesomeWM, so I gave some a try. It has been a while since using Linux on the desktop, but it was a surprisingly nice experience. Since then, I went ahead and have gotten my ubuntu partition up to snuff and have been using it full time.

The window manager I settled on is called StumpWM. It is written by the same guy who did Ratpoison with the major difference being that Lisp is used instead of C. You are able to manage windows in the same way you manage frames in Emacs, so it feels pretty comfortable to an Emacs user. While it was easy to get started using StumpWM, there were still things that needed to be setup. Specifically, getting my VPN to stable place was something of a blocker.

I found that in Gnome, things worked pretty well. NetworkManager made the VPN setup a cinch (although I did figure out how to get things working with pon/poff). I wanted to effectively have Gnome for setting up all the niceties such as a tray and NetworkManager. My first step was to try StumpWM with Gnome. This was pretty easy by setting an environment variable in a .gnomerc file.


export WINDOW_MANAGER=/usr/bin/stumpwm


The problem with this was that the panel and nautilus desktop were both frames in StumpWM. It just didn't feel right. What I did eventually was find trayer, a system tray replacement that only has a tray. It is really simple and it made running nm-applet really easy. There is a really cool screencast showing off StumpWM that showed starting the gnome panel and it working directly with StumpWM, but it didn't work for me. Likewise, there were a bunch of example configuration files that I tried to pull from that didn't work. Eventually it became clear I was using an old version of StumpWM. When I upgraded, things were much nicer. The documentation magically became correct and I could script things as needed in my StumpWM config. I setup my two monitors and things have been smooth sailing. Here is my StumpWM for reference if anyone is interested:

[code]

;; -*-lisp-*-

(in-package stumpwm)
(run-shell-command "python ~/xstart.py")
(define-key *root-map* (kbd "C-.") "gnext")
(define-key *root-map* (kbd "C-,") "gprev")

(defcommand firefox () ()
  "Start/Switchto Firefox."
  (run-or-raise "firefox" '(:class "Firefox")))

(define-key *root-map* (kbd "f") "firefox")

(run-shell-command "/usr/bin/trayer --edge bottom --SetDockType false --transparent true --expand false --align center &")
(run-shell-command "/usr/bin/gnome-settings-daemon &")
;;(run-shell-command "/usr/bin/gnome-panel &")
(run-shell-command "/usr/bin/nm-applet &")
(run-shell-command "/usr/bin/bluetooth-applet &")
(run-shell-command "/usr/bin/pactl load-module module-x11-xsmp &")

(set-prefix-key (kbd "C-i"))


;; create groups
(run-commands
 "gnewbg System"
 "gnewbg Web")

;; (run-commands "exec gnome-settings-daemon")

(setf *window-border-style* :thin)

;; Turn on the modeline
(if (not (head-mode-line (current-head)))
     (toggle-mode-line (current-screen) (current-head)))


;; Show the time in the modeline
(setf *screen-mode-line-format*
      (list '(:eval (run-shell-command "date '+%R, %F %a'|tr -d [:cntrl:]" t)) " | [^B%n^b] %W"))

(setf *mouse-focus-policy* :sloppy) ;; :click, :ignore, :sloppy

[code]

Most of the startup commands that are run I took from the gnome session editor where they are listed. The python "xstart.py" script just uses xrandr to setup my second monitor if it is connected. I could see that being an issue if I ever give a presentation, but honestly I'd probably just end up using something like Gnome or OSX if it were really that big a problem.

So far, I'm really happy with the setup. It is nice to be able to focus on primarily using the keyboard and the opportunity to continue to customize my environment seems like a healthy way of improving my knowledge of *nix and programming in general. What's more, it is nice to know I'm primarily using free software again. Beyond things not costing much, I have the opportunity to do whatever I like with the code. It may not seem like a big deal, but knowing that I have the ability to change the code as I need to is a pretty powerful concept.

Loading mentions Retweet
Filed under  //   emacs   linux  

Emacs: For Those Not Command Line Inclined

At work most folks use Vim. I use Emacs. We have fun debates all the time regarding why each other's editors are better. Nothing serious, just fun. One of the things I've realized is that I do most of my work within Emacs, which is a pretty common sentiment for Emacs users. I run servers, ipython, diffs, irc, tweet, etc. all in Emacs. I'm realizing part of the reason Emacs appeals to me in such a way is that it effectively has become my desktop environment through the shell. To put it another way, my command line skills suck, so Emacs is my GUI.

This became extremely clear to me when I was going to apply a diff. I had started working on a feature around the same time we were going to make a release. I was bouncing back and forth between branches, making fixes and moving forward a new feature. At one point, I realized I was working in the wrong branch. I needed to move my uncommitted work to the default branch and push my release branch changes. I didn't want to commit and then transplant the changes. That seemed like a bad idea because that would be a commit and then revert of the code in the log. It seemed like a good time to try and learn how to really work with diffs and patches so I did a quick "hg diff > release_to_default.diff" and was on my way.

After pushing my release changes, I needed to figure how to apply the patches in the diff. I started looking at the patch command. Back in the day, I used to try and do things like patch my kernel, but the whole patching experience was never very fluid to me. I didn't do nearly enough to become proficient. Realizing my desire not to actually use the patch command, I went ahead and opened the diff file in Emacs. Sure enough there was syntax highlighting for diff output along with a diff-mode menu. I took a quick look at the menu, saw C-a C-c applies a patch to a file. One keyboard command later, I had applied part of the diff file. A few more commands later and I was done! Very nice.

I'm obviously avoiding some potentially important information here by choosing the Emacs way over learning something about the patch command. I can't say I'd reccommend the same steps. At the same time, it was so easy! Some day I'm really hoping I'll get my head wrapped around using a shell like a real guru, but for the time being, I don't mind a little magic in my editor... Even if the Vim folks make fun of me for it!

Loading mentions Retweet
Filed under  //   emacs