onilog

posts tagged "coding"

Guess what's back

3 October 2012 10:24 PM (org-mode | tekuti | meta | emacs | elisp | coding | blogging)

A while ago I wrote a couple of functions in GNU Emacs to help me with blogging using tekuti. I don't know how, but I somehow accidentally deleted the file these functions were in and didn't have the energy to retrieve it.

Today I wanted to blog a little again and so I rewrote the functions from last time, but this time hopefully a little better. I'm now fully dependent on org-mode and use its comment/property syntax to manage tekuti's metadata.

I've already put it in a temporary spot for safe keeping, I'll move it somewhere else when I have a little more of it.

The functions I'll still want to add include:

  • Editing the posts I've written in org, showing the options I used
    for them in the usual way.

  • Automatic committing, this shouldn't be too hard since I've also
    written an emacs minor mode that does this.

  • Easy saving, listing and continuing of drafts, right now I'm just
    placing org files in my $HOME directory.

And anything else that I can come up with later.

HI

3 October 2012 2:35 AM (scheme | xdg | coding)

Since I have nothing better to say and still want to say something, here is some nonsense:

I've been having an issue with loading configuration and data files. The problem is that I like the XDG Base Directory Specification and am trying to write my software in such a way that it supports both this and the usual(/old) folder in $HOME approach.

This doesn't sound all that difficult, nor is it, but still I was making a lot of mistakes with it, because I don't just want to support something, I don't want to force whomever (nobody but me, really) uses my software to be forced in to anything. So first I need to check if the XDG environment variables exist, if they do then I have to see if the file I want to load exists in that directory, if it doesn't and one does exist in $HOME I want that one, but if the one in home doesn't exist either, I want the one in the XDG folder again. It gets messy.

I feel that I may have it now, though8239

(define (stored-file xdg-env file)
  "Try to get FILE stored either in XDG-ENV or the home directory."
  (let ((xdg (getenv xdg-env))
        (stored-file (string-append
                      (getenv "HOME") "/.project/" file)))
    (unless (or (file-exists? stored-file) (not xdg))
      (set! stored-file (string-append xdg "/project/" file)))
    stored-file))

(define (config-file file)
  (stored-file "XDG_CONFIG_HOME"))

(define (data-file file)
  (stored-file "XDG_DATA_HOME"))

(define (rc-file)
  (config-file "rc.scm"))

(define (list-file)
  (data-file "list.scm"))

The stored-file function first assumes that we will want to grab it from the directory in $HOME, when it can't verify that that particular file exists and knows that the XDG variable isn't empty it will instead return a reference to the file in that directory.

All the other functions are just there to make it clear and convenient to load these files and not specifically necessary. The good part of this function, in my opinion, is that is separates configuration and data files from each other in code, but will just grab it all from the same directory when working with the $HOME directory. This, of course, can create naming conflicts, but if you have naming conflicts this way you might get confused by what you're doing here or there anyway.

Cool new scratch buffers

2 August 2012 0:27 AM (emacs | elisp | coding)

I had a thought today: It would be nice if I could have more than one scratch buffer, and even nicer if they could easily have different major modes.

So, I had this function in my emacs init file, raise-scratch:

(defun raise-scratch ()
  "Show the *scratch* buffer."
  (interactive)
  (switch-to-buffer "*scratch*"))

Its nice, it allowed me to do exactly what I wanted to do, easily open my scratch buffer. I bound this to XF86HomePage, which makes sense to me, since emacs always starts in the *scratch* buffer.

Today, though, it didn't seem to be quite enough. As I said, it would be nice to have the ability to have multiple scratch buffers with different major modes. This is handy for messing around with some sawfish-mode code, or python-mode, for example.

(defun raise-scratch (&optional mode)
  "Show the *scratch* buffer. If called with a universal
argument, ask the user which mode to use. If MODE is not nil,
open a new buffer with the name *MODE-scratch* and load MODE as
its major mode."
  (interactive (list (if current-prefix-arg
                         (read-string "Mode: ")
                       nil)))
  (let* ((bname (if mode
                    (concat "*" mode "-scratch*")
                  "*scratch*"))
         (buffer (get-buffer bname))
         (mode-sym (intern (concat mode "-mode"))))

    (unless buffer
      (setq buffer (generate-new-buffer bname))
      (with-current-buffer buffer
        (when (fboundp mode-sym)
          (funcall mode-sym))))

    (switch-to-buffer buffer)))

This is quite a bit bigger. It now takes an optional mode argument, when it is called interactively it will check if the universal prefix argument (C-u) was used and if so, asks for the value of mode.

If mode has been specified it will create a new buffer with the name *MODE-scratch*. It will then insert a file local property line specifying the major mode to use and then switches to it.

It's the first time I'm using a list with the interactive command, it always seemed very alien to me, but it seems quite clear how it works now.

It was a challenge to figure out how I wanted to do this. My first idea was to ask for a file extension and match that to auto-mode-alist, but that has regexps for keys, so not easily matched. Then there is the problem of figuring out how to load the right major mode in another way, since adding such a file local property line happens after the buffer has been loaded, and thus has no effect on which major mode is chosen.

Of course, this approach doesn't ensure the right major mode gets chosen, but that's really up to whomever uses it.

It makes me very happy to use such an extensible editor.

Update: fixed my flawed code.

eval-and-compile

27 July 2012 9:19 PM (emacs | elisp | config | coding)

I'm reading up a little on byte-compilation in GNU Emacs and I read about just exactly a feature that I needed.

A while ago, I was working on my init file, adding some auto-complete code since I wanted to try it again. I noticed that, because auto-complete is installed through package, it couldn't load the appropriate files at compile time.

I know that package-initialize should be called before calling or using any package-installed functions and I have it in my init file, but this doesn't help at compile time. So, ugly as I thought it was, I added

(eval-when-compile (package-initialize))

just above the call to the auto-complete functions. I hated having to do that, I know it's just one line, but its not at all DRY.

Just now, though, I read about eval-and-compile, and according to the documentation in the elisp reference manual, it should do exactly what I want, eval both when running and when compiling.

(eval-and-compile (package-initialize))

I'm currently trying it out, I just tested it once and it seems to work like a charm.

Of course, this might never have been an issue if I didn't use emacs -Q to compile my init file, just to speed up loading during compilation a little bit.

Another way to get a selection

3 May 2012 10:04 AM (emacs | elisp | org-mode | coding)

When I was first looking into improving my mailbox selection function I was looking at how to just ask the user for input with completions. Though now that I came across tmm-prompt I really prefer this way of working, at least in this case.

However, today another function was mentioned, in response to someone pointing out org-completing-read: completing-read. Wow that's a far leap.

Anyway:

(completing-read "Your favorite color: "
                 '("red" "green" "blue" "yellow"))

This will ask for user input and provide these options as completions, but it won't show a list of options, of provide shortcuts, like tmm-prompt does.

It's good to know these things, and I really should read both the emacs manual and the emacs lisp reference manual at some point.

Ask for selection in emacs, addendum

2 May 2012 9:52 PM (emacs | elisp | coding)

I erroneously assumed (and thought I tested) that using tmm-prompt could be done the way I described before. The oni:mailbox-map variable needs to be a little different from what I'd shown before, namely:

(defvar oni:mailbox-map
  '("top" ("menu" ("ryulash.org" . "ryu")
           ("ninthfloor" . "ninthfloor")
           ("gmail" . "gmail")
           ("aethon" . "aethon")))
  "A mailbox map for use with `tmm-prompt'.")

Without the top and menu items it will complain about wrong arguments.

Show identi.ca icon with new dents

2 May 2012 9:36 PM (emacs | elisp | identica | mode-line | icon | coding)

I've written this a while ago after I found out how images can be added to the emacs modeline. I like being notified of things that go on, and new dents is a good example of this, though notify-send and an urgency hint don't always work for that.

This works:

(add-to-list
 'global-mode-string
 '(:eval
   (unless (zerop identica-new-dents-count)
     (propertize " " 'display identica-active-indicator-image))))

This will show an icon in your modeline whenever there are new dents, at this time there dents will not have been loaded into the buffer, so you'll have to refresh it, after which the icon disappears.

Ask for selection in Emacs

2 May 2012 9:09 PM (emacs | elisp | coding)

I came across an email on one of the emacs mailing lists today, where someone asked how to ask a user for input whilst providing completions. The first answer he got was to try tmm-prompt, so I looked into it a little.

I use mu4e as my primary email program, but since it isn't designed (seemingly) for use with multiple accounts I've got some wrapper functions that set some variables according to my liking and then start mu4e. This works very well, but it's a pain to have to use M-x view-ryu-mail or M-x view-ninthfloor-mail and such, so I wrote a function to read a string from the minibuffer, which I then bound to the <XF86Mail> key, this turned it into, for example <XF86Mail> ryu and <XF86Mail> ninthfloor and so on, but this doesn't have any completion or notification of my options.

So after looking at tmm-prompt I came up with the following:

(defvar oni:mailbox-map
  '(("ryulash.org" . "ryu")
    ("ninthfloor" . "ninthfloor"))
  "A mailbox map for use with `tmm-prompt'.")

(defun view-ryu-mail ()...)
(defun view-ninthfloor-mail ()...)

(defun view-mu ()
  (interactive)
  (let* ((tmm-completion-prompt "Choose a mailbox\n")
         (inbox (tmm-prompt oni:mailbox-map)))
    (funcall (intern (concat "view-" inbox "-mail")))))

I've left out the definitions and some mail accounts for brevity.

tmm-prompt is usually used when using the text-mode menu with M-`, but it works very well here too. This changes mailbox selection to, for example <XF86Mail> r or <XF86Mail> n.

Silly django confusion

24 April 2012 3:51 PM (python | django | coding)

I'm setting up a testing environment for work, using fixtures to save and load test data and I got a little stumped by something I ran into.

I had exported one of the database tables we use to a json file that I was going to import into a fresh new database to test with. When I imported it everything seemed fine, except when looking at the actual page. So this is what I found:

SELECT * FROM app_table;
    => 3 rows of data
from app.models import Table

Table.objects.count()
    => 3

Table.objects.all()
    => []

This is weird. So I looked at the django.db.connection.queries property and I realized that it was doing a join since the model subclasses another:

from django.db import models

from app.models import SuperTable

class Table(SuperTable):...

Which, of course, means that in order to get the complete Table instance, the related SuperTable instance is also required, but in order to do a COUNT of app_table it isn't necessary. And that's where the inconsistency came from, now that I've also copied the contents of SuperTable everything is fine again.

And old is new again

9 February 2012 0:00 AM (emacs | elisp | config | coding)

Now that I've got my .xbindkeysrc pretty much the way I want it I have some time again for other things. So I thought that I should work on my .emacs.d/init.el again, since it has been a while since I cleaned it up/tweaked it.

I'm returning to a state where my emacs configuration is seperated into several (small) files that get byte compiled and loaded during startup. Of course they should only get compiled if they're not still up-to-date. The advantage this would have is that once I've byte compiled my init.el, the rest (no matter how many git pull's further) just gets automatically recompiled.

The old way I did this seems to be this:

(setq d-dir "~/.emacs.d/")
(setq d-el-files (directory-files d-dir nil "^[0-9]\\{2\\}-\.*el$"))

(byte-recompile-directory d-dir)
(while d-el-files
  (let ((my-file-name (concat d-dir (car d-el-files))))
    (if (not (file-exists-p (concat my-file-name "c")))
        (byte-compile-file my-file-name))
    (load (substring my-file-name 0 (- (length my-file-name) 3)))
    (setq d-el-files (cdr d-el-files))))

If I remember correctly: the byte-recompile-directory function only recompile files, it doesn't compile files that have already been compiled, so after recompiling everything I had to check whether or not there were any uncompiled files left. I also seem to go crazy a little bit with the substring there. And the regexp there doesn't seem quite right8239

Just now I wrote (taking the previous code as an example):

(require 'bytecomp)

(setq startup-directory "~/.emacs.d/startup/")
(setq startup-files (directory-files startup-directory nil "^[^.].*\\.el$"))

(while startup-files
  (let ((filename (concat startup-directory (car startup-files))))
    (if (not (eq (byte-recompile-file filename nil 0) nil))
        (load (substring filename 0 -3))))
  (setq startup-files (cdr startup-files)))

I noticed that when I didn't require bytecomp, it didn't recognize byte-recompile-file as a function, so I need that.

I still use a separate load call to load the file, because it seems that using the LOAD parameter of the byte-recompile-file function loads the source file, not the byte compiled one. This seems strange to me, though, I should ask about that.

I check the result of byte-recompile-file against nil, which is what it should return if there are errors, so I don't try loading it when there are errors.

I also discovered that using a negative argument doesn't just work for substring's START parameter, which makes it much cleaner than the old version.

I hope it works at least as well as the old version, but I think it at least looks nicer.

Then, 2 files that I changed, one for all my autoloads and one for my auto-mode-alist variable:

(defun set-autoload (params)
  (autoload (nth 0 params) (nth 1 params) (nth 2 params) (nth 3 params)))

(mapc
 'set-autoload
 '((column-marker-1         "column-marker"      "First column marker"  t)
   (column-marker-2         "column-marker"      "Second column marker" t)
   (rainbow-delimiters-mode "rainbow-delimiters" "Shiny delimiters"     t)
   (go-mode                 "go-mode"            "Major mode for Go"    t))

Which again, in my opinion, looks much nicer than autoload calls spread all over a 500+ lines init.el. Along with:

(setq auto-mode-alist
      (append '(("\\.tpl$" . html-mode)
                ("\\.go$"  . go-mode))
              auto-mode-alist))

Which also looks better than a lot of add-to-list calls spread around.

Of course, for brevity, I didn't include all my settings, that would take up way too much space.

It'll probably get much slower again, but maybe it's worth it if I can get everything cleaned up this much. I hope I can work on this some more over the next few days. Man, lisp programming sure is fun!