onilog

Stop shr from using background color

3 April 2014 10:13 PM (emacs | elisp | config)

Here's just one more example why Emacs is so awesome

Reading mail in Gnus is very nice, but shr has become a little too good at its job. Add to this the many occasions when a background is specified without specifying a foreground, plus a color theme that is the inverse of what is usually expected, and you can get hard-to-read HTML messages, gray foreground and gray background.

I've looked at the other possible renderers, but they don't look very nice compared to shr. So just remove its ability to add background colors.

(defun oni:shr-colorize-remove-last-arg (args)
  "If ARGS has more than 3 items, remove the last one."
  (if (> (length args) 3)
      (butlast args)
    args))

(with-eval-after-load 'shr
  (advice-add #'shr-colorize-region :filter-args
              #'oni:shr-colorize-remove-last-arg))

Hello, Cask

31 January 2014 11:17 PM (emacs | config | cask)

I've been very resistant to looking at Cask. I felt that, much like for example el-get, it was trying to re-solve a problem that has been solved by ELPA since Emacs v24 in a way incompatible with ELPA.

I have finally looked at it, and to my pleasant surprise it works with ELPA instead of beside it, as a wrapper adding some extra functionality. Using and supporting Cask doesn't mean you don't support ELPA. And theoretically using Cask does open up possibilities for development by creating separate development environments (package wise), though I haven't tried this out yet.

I've switched over my configuration to using Cask, which will also help me keep the configuration on my laptop synchronized more easily.

Aside from a fairly long Cask file, making it work is pretty simple, as the website suggests.

(eval-and-compile
  (require 'cask "~/projects/ext/cask/cask.el")
  (cask-initialize))

I add an eval-and-compile so the external process compiling my init.el doesn't complain about not being able to load ELPA-installed packages.

Now instead of starting up Emacs, running M-x list-packages, pressing U and then X (and y at least once) it's a matter of

cd ~/.emacs.d
cask update

Much easier.

Mounting music dir before MPD

24 November 2013 2:03 PM (systemd | mpd | config)

Systemd allows you to specify a program to run before running the main daemon (or program) with ExecStartPre. This can, for instance, be used to run a mount command before starting mpd. By adding under the [Service] heading:

ExecStartPre=/usr/bin/mount /mnt/music

Now I have already setup my fstab to know what to mount on /mnt/music, but of course that shouldn't be necessary. According to the systemd.service(5) man page it uses the same syntax as ExecStart, which tells us that one must use absolute file names since no shell is used to start them.

This also has the effect of stopping the ExecStart part from the .service from being executed if the ExecStartPre doesn't finish successfully. Which works out great in my case as I don't want to start mpd if my music directory didn't mount. If you want to ignore the exit status of (one of) the ExecStartPre commands you can prefix it with a -, for example:

ExecStartPre=-/usr/bin/mount /mnt/music

Which would continue running the ExecStart even if mounting failed.

Also know that there can be multiple ExecStartPre options and they will be executed serially, so for example:

ExecStartPre=/usr/bin/mount /mnt/music
ExecStartPre=-/usr/bin/mount /mnt/music2

This would fail if /mnt/music doesn't mount, but would continue just fine if /mnt/music did and /mnt/music2 didn't.

rlwrapping sbcl

6 October 2013 1:02 PM (lisp | cli | sbcl)

SBCL is an excellent lisp implementation. The only thing that's not so nice about it is overly simple command-line interface. The absence of <UP>, C-a, M-b, etc. can be annoying, even though I only occasionally use SBCL directly.

I have 3 solutions to this problem now:

  • Use SLIME, which is what I do most of the time, but sometimes this
    isn't practical.

  • Use Linedit. I tried this, and it was cool. But somehow I broke it
    and now I can't get it to work.

  • Use rlwrap. This requires you to either always invoke SBCL asrlwrap sbcl or create an alias for it. This works very well too,
    is very simple and doesn't noticeably increase start-up time.

C-d to close eshell

17 August 2013 2:25 AM (emacs | eshell | elisp | config)

One of the "tricks" that I have learned to use when working with terminals is using C-d to close them, or when working on a TTY logout. It somehow grew to the extent that if I can't use it, I get annoyed, like with eshell.

I have customized ansi-term to immediately close its buffer after the shell quits. This makes it very easy to start an ansi-term, which I've bound to C-c t, run a quick command (perhaps make, or similar), C-d, and I'm out. I want that for my eshell too.

There are a few conditions that I want met before the buffer is killed, though.

  1. Since eshell is an Emacs mode like any other, C-d is usually used
    to forward-kill characters, I don't want to lose this.

  2. I only want it to quit when the line of input is empty.

The following piece of code make sure these conditions are met.

  1. It interactively calls delete-char, which keeps keybindings like
    C-4 C-d to delete 4 characters working.

  2. It catches the error condition which is signaled wheneverdelete-char can't do it's job (like when there's nothing left to
    delete in the buffer).

  3. It checks to make sure that the signaled error is the end-of-buffer
    error. I don't want to kill the buffer if I try to delete more
    characters than are in the buffer because I feel that could cause
    irritating surprises.

  4. It checks of the cursor is at the eshell prompt. This, combined
    with only responding to the end-of-buffer error, makes sure we're
    on an empty line and not just at the end of the input. Sometimes
    keys are pressed at the wrong time and I don't want to have to
    re-type a command just because I was being an idiot.

  5. If the right conditions aren't met, signal the error again so I can
    see what's going on.

(defun eshell-C-d ()
  "Either call `delete-char' interactively or quit."
  (interactive)
  (condition-case err
      (call-interactively #'delete-char)
    (error (if (and (eq (car err) 'end-of-buffer)
                    (looking-back eshell-prompt-regexp))
               (kill-buffer)
             (signal (car err) (cdr err))))))

I then bind this to C-d in eshell.

(add-hook 'eshell-mode-hook
          (lambda () (local-set-key (kbd "C-d") #'eshell-C-d)))

Some quick git diff tips

11 August 2013 0:54 AM (git | org-mode | diff | tips | magit | emacs | lisp | hy | elisp)

A couple of quick tips. As you possibly know you can specify some options to be used for diffs (and other things) per file type. The one I'm interested in is the function name.

For org-mode

The primary way of identifying which part of an org-mode document a change occurs in seems to me to be the heading. So, in your $HOME/.gitconfig put:

[diff "org"]
      xfuncname = "^\\*+.*"

Which should show any lines starting with one or more * characters. And then in $XDG_CONFIG_HOME/git/attributes or $HOME/.config/git/attributes put:

*.org   diff=org

For lisp and lisp-like langauges

For anything that resembles lisp (so Common Lisp, Emacs Lisp, Hy, scheme, etc.) I would think that the easiest thing to do is just see the closes top-level form. So, in your $HOME/.gitconfig put:

[diff "lisp"]
      xfuncname = "^\\([^ ]+ [^ ]+"

Which should show the opening parenthesis and the first two words. For example:

(defun some-function-name
(defclass my-awesome-class
(define-route this-strange-route

And then put in your $XDG_CONFIG_HOME/git/attributes or $HOME/.config/git/attributes:

*.lisp  diff=lisp
*.el    diff=lisp
*.hy    diff=lisp
*.scm   diff=lisp

And possibly any other lisp-like language files you can think of.

Notstumpwm

24 May 2013 0:10 AM (stumpwm | notion | config | lua | lisp | wm | archlinux | exherbo)

I have just returned from an excursion into the land of exherbo, which is an awesome source-based distro, and I found that while I was gone, something changed that made stumpwm cause a segmentation fault in X11 a few seconds after starting up.

I have tried everything I can think of to get it running again, but alas, to no avail. So I started looking at alternatives again. Feeling a little crazy I decided to give notion another try. And it fits strangely well.

It's configured/extended in lua, which I'm not particularly fond of, and it has a (in my opinion) crazy default configuration. But it also allows Emacs-like key combinations out-of-the-box, which is a very big plus in my book. So the quest to bring it closer to my stumpwm setup has begun.

Window layout

One of the nicest additions to my stumpwm configuration I made in the last few weeks was a loaded window configuration which put my Emacs frames in a big chunk of my left monitor, my terminals on my left monitor with just enough space for 80 columns and my web browser filling my right screen. I had also set-up some rules to always place them in the correct spots.

I have not yet tried to automatically place the windows in the right spots, but I do have the proportions right. I just had to delete the right frames and resize the one for terminals and, by default, notion remembers this set-up and automatically restores it when I log in.

I will look at creating a special layout for this so I don't have to worry about (accidentally) changing things.

run-or-raise

I found this interesting page about run-or-raise-like functionality for Ion3, which notion is a fork of. This is a little outdated, though, since notion has changed (apparently) the workings of some functions and lua 5.2 introduced the goto keyword, so I had to change it to this:

function oni_match_class(class)
   local result = {}
   ioncore.clientwin_i(
      function (win)
         if class == win:get_ident().class then
            table.insert(result, win)
            return false
         end
         return true
      end
   )
   return result
end

function xsteve_run_byclass(prog, class)
   local win = oni_match_class(class)[1]
   if win then
      win:goto_()
   else
      ioncore.exec(prog)
   end
end

There is no function to get a list of all the client windows, only a function to iterate over them. For the moment I am only interested in finding the first window with class CLASS, so I return false when a match is found, this stops the iteration process. I also had to use the WRegion.goto_ function, instead of WRegion.goto because of the mentioned change in lua 5.2, but they are the same.

I then only have to bind it:

defbindings("WScreen", {
    -- ...
    submap("Control+Z", {
        -- ...
        kpress("E", "xsteve_run_byclass('emacsclient -ca emacs', 'Emacs')"),
        kpress("W", "xsteve_run_byclass('conkeror', 'Conkeror')"),
        kpress("C", "xsteve_run_byclass('urxvt', 'URxvt')"),
    }),
})

Quoting C-z

One of the coolest things about using a prefix in stumpwm that I have been able to find in precious few other solutions is the ability to send the prefix key to the applications you use, so you don't entirely miss its functionality. In stumpwm this is easy, but in notion its a little more work:

defbindings("WClientWin", {
    -- ...
    submap("Control+Z", {
        -- ...
        kpress("Q", "WClientWin.quote_next(_)"),
    }),
})

This means that I have to type C-z q C-z to send the C-z key to, for instance, Emacs. That a few more keys than I was used to in stumpwm, but at least it's possible.

CLark 0.1.0

3 April 2013 11:04 PM (clark | markam | project | common lisp)

A few days ago I tagged CLark 0.1.0.

CLark is a Common Lisp rewrite of my Markam project, which in turn was a Chicken Scheme rewrite of linkwave. With each rewrite I come a step closer to having the program that I need. Linkwave could only store bookmarks, Markam could also search through them and had a conkeror interface which allowed adding and searching through bookmarks. Now CLark expands upon this by allowing users to edit their bookmark's information, changing the tags, removing bookmarks, writing their own commands, an improved command-line interface and bookmark status checking (bookmarked or not). It also adds commands to conkeror for the data manipulation commands that are new (edit, set-tags, remove) and a mode-line indicator of bookmarked status.

For now it only targets SBCL, but I'm not averse to including others.

The next big step should be adding a mcclim-based GUI for those crazy people who don't like to use the command line.

New tag pages

3 April 2013 3:33 AM (tekuti | meta | dispass.el)

I've changed my tekuti instance to have tag pages that look more like the index page. I did this so that I can use tag pages as news pages for my various projects. You may have a look at the dispass.el project site to see the new "Read News" link, which will take you to the dispass.el tag page.

Markam v0.2.0

16 February 2013 11:37 AM (markam | project)

I've just pushed version 0.2.0 of my project Markam. It took longer than I thought it would. Since storing was still all I wanted to do I had no rush to add anything else. Until now.

Changes include:

  • Add install, uninstall and install-strip targets to the Makefile,
    this should make installing easier.

  • Add simple tag/title searching. Looks through bookmarks for any that
    have been tagged with the given string, or that have it somewhere in
    their title.

  • Add a --script switch, which changes output for both the default and
    search behavior. When this switch is passed to markam it outputs the
    name, description and url of each bookmark, where each bookmark is
    separated by C-^ (Record separator) and each field by C-_ (Unit separator). This should help in building tools around it by making
    parsing somewhat easier. The bundled Conkeror interface uses it.

  • Update the Conkeror interface:

    • Add the commands markam-find-url and markam-find-url-new-buffer.
      These call markam with a possible search string and add them as
      completion candidates, for easy searching and opening of your
      bookmarks. markam-find-url uses the current buffer and
      markam-find-url-new-buffer opens the url in a new buffer.