onilog

posts tagged "elisp"

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))

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.

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.

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.

Testing org-blog fix

10 May 2012 1:39 AM (emacs | elisp | org-blog | test)

I've just adjusted just a little bit of code in org-blog, and now I want to see if it works correctly.

I was getting the following error message when I would try and export an org-blog project:

Selecting deleted buffer

It turns out that this is because of this little piece of code:

;; if buffer is already open, kill it
(if index-buffer
    (kill-buffer index-buffer))

I'm guessing it wasn't originally meant as a function for org-publish, well it was meant as an index function, but that feature seems to have changed over time. Let's see what can be made of it.

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.