Done and Gets things smart

June 17th, 2008

Jeez, is there any profession in the world that is more self-loathing than ours? Am I smart enough, maybe I’m dumb, maybe that guy is smarter than me, I’m sure I’m smarter than that guy, but am I, maybe I’m wrong. Anyone recognise this lot?

Ho ho ho, the fun we had. And the freaking whining comments at the bottom of the post

I wanna be a done and gets things smart guy. Waaaahhh.

Great! Go ahead. See towards the end of the post as to how.

I’ve got a theory

"catchy phrases fool otherwise intelligent people"

For example, I’ve heard previously heard…

"you don’t understand something unless you can explain it to your grandma1"

…which is obviously not true. I don’t know about you, but my grandma isn’t interested in math and I can’t explain basic algebra to her. Howver, I can certainly understand it. And I bet Einstein would have had a job to explain relativity to his grandma.

Stevey takes a very scientific sounding phenomenon called the Dunning Kruger effect which basically says (amongst many similar things), that illiterate people can’t distinguish between good grammar and bad grammar2. He then extrapolates to the patently absurd

You have to be a gosh darned genius to recognise that someone is pretty smart.

Or is that even you have to be smarter than someone to figure out if they are smarter than you (!)

In their paper, Dunning and Kruger consider the bottom 5% of a particular population, and say that they are so incompetent (in this one particular area), that they can’t recognise how bad they are. Now, 1 in 20 programmers may need to worry about the Dunning Kruger effect and the fact they are really naff even though they think they are geniuses but everyone else can relax. And no, it doesn’t affect you3.

You know what, I know I’m a competent programmer and I can recognise programmers who are worse than me and programmers who are better than me. Isn’t that amazing? You don’t have to be smarter than Einstein4 to recognise that he was quite brilliant. Can’t you recognise people who are better than you? How did we get conned into thinking like this?

Another example to drive this home. I play tennis at club level. You could say I’m a mediocre tennis player. When I watch Federer play, I doubtless see more of the game than my friends who don’t play tennis. I also recognise that he is a much better player than me.

He then preys on our insecurities about these godlike programmers who have always finished their current task and are therefore always improving their system.

Stevey had two programmers in his first company who were godlike - the type of programmers you insignificant mortals will never meet5

Apparently you’re not gonna meet them ‘cuz when a company finds them, they never let them go.

So Stevey is in the top 5% and lets say these guys were in the top 5% of those who were left. Well, I can’t be bothered to calculate the probability of that from the gaussian curve6, but anyway, who cares. I bet they weren’t really that smart7.

We have guys like that in my *cough* fortune-500 company8 *cough*. The reason they are always finished, is because they haven’t got anything to do, and the reason they are always improving their system is because they are fairly competent and if they didn’t do that, they would get bored.

Of course, I could be bitter and twisted that I may be one of the 5% of guys that the Dunning-Kruger effect actually apply to. Maybe, you know, er, hopefully not9.

JG

Update:

Whenever I consider sitting down to write a post like this, I always think of the xkcd strip Duty calls (someone on the internet is wrong).


1. Can you see the strawman coming?

2. Well duh! That is what illiterate means.

3. It might affect you over there at the back though. Yes you.

4. My go to example guy.

5. I may be paraphrasing here.

6. I guess it isn’t that unlikely

7. Damn10! They could fix my code as well as their own11. That is absolutely amazing12.

8. The type of company where everyone is mediocre don’t you know.

9. But seriously guys, please have a bit of confidence in your abilities. This self-doubt is seriously uncool.


10. I’m convincing myself that I am smart here dammit!

11. With a magic wand no less.

12. If google is really populated by these super smart guys, why haven’t they come up with something amazing other than search that works, like, you know, something that fixes the gap between the haves and the have nots.

Uniquify and ido

June 16th, 2008

A very quick post today to mention a couple of core modules I’ve included in my config that make using emacs even nicer.

I’ve been using uniquify for a while as the default emacs behaviour when loading two identically named files is a bit naff1. I found this tip here.

(requireuniquify)

(setq uniquify-buffer-name-style ‘reverse)
(setq uniquify-separator “|”)
(setq uniquify-after-kill-buffer-p t)
(setq uniquify-ignore-buffers-re “^\\*”)

I’ve just added ido to my config today based on a post I found at the emacs blog. It might take a bit of getting used to but we’ll see how that goes.

(ido-mode t)
(setq ido-enable-flex-matching t)

I’ve added those sections to a file I have called my-defaults.el that contains my really short pieces of configuration.

my-defaults.el

;; ———————————————————————- ;;

(requireido)
(requireuniquify)

;; ———————————————————————- ;;

(global-font-lock-mode 1)
(setq inhibit-splash-screen t)
(setq font-lock-maximum-decoration 3)
(fset ‘yes-or-no-p ‘y-or-n-p)
(tool-bar-mode -1)
(show-paren-mode 1)
(transient-mark-mode t)
(customize-set-variable ’scroll-bar-mode ‘right)
(setq case-fold-search t)

(line-number-mode 1)
(column-number-mode 1)

;; ———————————————————————- ;;

(setq backup-directory-alist
      (cons ‘(“.” . “~/.emacs-backups”) backup-directory-alist))

;; ———————————————————————- ;;

(ido-mode t)
(setq ido-enable-flex-matching t)

;; ———————————————————————- ;;

(setq uniquify-buffer-name-style ‘reverse)
(setq uniquify-separator “|”)
(setq uniquify-after-kill-buffer-p t)
(setq uniquify-ignore-buffers-re “^\\*”)

;; ———————————————————————- ;;

(providemy-defaults)

;; ———————————————————————- ;;

1. It appends an integer in angle brackets to the second file with a non-unique name, e.g. file.cpp<2>.

Emacs templates

June 15th, 2008

Currently I use muse with htmlize to write my blog posts but I’m always on the lookout for something better e.g. nxml-mode supported by templates. I tried it out recently to see if it was a worthy replacement. The conclusion in my case, for those with short attention spans, is not so far.

Muse provides a mechanism for including files, including the result of running emacs-lisp, perl or python code, entering verbatim html and a whole bunch of other stuff, but the two most important features for me are that with a bare minimum of markup I can layout my post as I want1 and include syntax highlighted code. A possible alternative to minimal markup would be to have a bunch of templates that I can enter with a few keysrokes.

The emacs wiki has a nice set of links to templating engines. After a few minutes experimentation, I decided that skeleton mode2 was the one for me. One of the most verbose html constructs is the table. A basic two by two table will include the following html tags.

<table>
  <tr>
    <td></td>
    <td></td>
  </tr>

  <tr>
    <td></td>
    <td></td>
  </tr>
</table>

Here is the code to define a skeleton that inserts a 1 by 1 table.

(define-skeleton sk-html-table-1-1
  “Insert a 1 by 1 html table”
  “”
  “<table>”            > “\n”
  ”  <tr>”             > “\n”
  ”    <td>” _ “</td>” > “\n”
  ”  </tr>”            > “\n”
  “</table>” >)

That is pretty inflexible. What if we want to have a different number of rows and columns? Unfortunately, define-skeleton doesn’t work quite like you might want. Rather than inserting the tags five times, the following code doesn’t insert anything.

(define-skeleton sk-test
  “xyz”
  “”
  (dotimes (rep 5)
     “<a>”     > “\n”
     “<b></b>” > “\n”
     “</a>”    > “\n”))

To surround each string with (insert ...) would be far too verbose. What we want is a function that handles strings and > in the same way as define-skeleton. Unfortunately that is not possible. If you call a function like this (func >) then > will be evaluated before the function is called. In this case it will try to find a variable called > which probably won’t exist and then emacs will complain

let: Symbol's value as variable is void: >

To avoid the evaluation, what we need is a macro.

(defmacro skeleton-list (&rest params)
  (dolist (elem params)
    (if (eq elem ‘>)
        (indent-according-to-mode)
      (insert elem))))

sk-test then becomes trivial.

(define-skeleton sk-test
  “xyz”
  “”
  (dotimes (rep 5)
    (skeleton-list “<a>”     > “\n”
                   “<b></b>” > “\n”
                   “</a>”    > “\n”)))

We can call skeleton-read to ask for the number of rows and columns we would like our table to have. Then, using skeleton-list, the code for a basic table is the following3.

(define-skeleton sk-html-table
  “Insert an html table”
  “”
  ‘(setq v1 (skeleton-read “table rows: “))
  ‘(setq v2 (skeleton-read “table columns: “))
  “<table>”            > “\n”

  ”  <tr>”             > “\n”
  ”    <td>” _ “</td>” > “\n”
  (dotimes (col (1- (string-to-int v2)))
    (skeleton-list “<td></td>” > “\n”))
  ”  </tr>”             > “\n”

  (dotimes (row (1- (string-to-int v1)))
    (skeleton-list “\n” “<tr>” > “\n”)
    (dotimes (col (string-to-int v2))
      (skeleton-list “<td></td>” > “\n”))
    (skeleton-list “</tr>” > “\n”))

  “</table>” >)

This does make creating tables quite a bit easier, but for me, even if I had a full set of templates, muse is still a superior option for at least the following reasons:

  1. The file with minimal mark-up is easier to work on.
  2. Source code colouring is nicely integrated into muse with htmlize
  3. Anything that html can do, so can muse with the use of the <verbatim> tag.

JG


1. For example, I simply enter a paragraph normally, separated by carriage returns and it is automatically surrounded by <p> tags when I generate the html.

2. It isn’t actually a mode in the emacs sense.

3. There is probably a better solution lurking within skeleton mode that doesn’t require any extensions. If anyone knows of one, I’d appreciate hearing about it.

Emacs keymaps - prefix keys

June 4th, 2008

If you look at all the key-bindings with (describe-bindings) you will see that there are not very many single control key combinations remaining. For this reason, emacs allows prefix keys and the guidelines recommend that user-defined bindings are prefixed with C-c1.

After extensive customisation, you may find that you start to run out of two-key-combos prefixed with C-c. Is it possible to have a three-key-combo? Of course it is - take C-x-4-[something] or C-x-5-[something] for example.

I have a number of bindings beginning with C-ci2 for inserting things. For example, I use C-cid for inserting today’s date in YYYYMMDD format3. However, if you try (global-set-key "\C-cid" 'my-insert-date) emacs complains that C-c i is not a prefix key.

Debugger entered--Lisp error: (error "Key sequence C-c i d starts with non-prefix key C-c i")
  define-key([snip] …) “\Cid” my-insert-date)
  global-set-key(”\Cid” my-insert-date)
  eval((global-set-key “\Cid” (quote my-insert-date)))
  eval-last-sexp-1(nil)
  eval-last-sexp(nil)
  call-interactively(eval-last-sexp)

You first have to define C-ci as a prefix key by setting it to a keymap.

(defvar my-insert-map nil)
(setq my-insert-map (make-sparse-keymap))

(global-set-key “\C-ci” my-insert-map)
(global-set-key “\C-cid” ‘my-insert-date)

Note that setting the prefix key passes the keymap rather than a symbol with the name of the keymap. I first tried (global-set-key "\C-ci" 'my-insert-map) and wondered why it wasn’t working.

And if you were at all curious about the definition of my-insert-date, here it is.

(defun my-insert-date ()
  (interactive)
  (insert (format-time-string “%Y%m%d”)))

JG


1. That is emacs parlance for CTRL-c.

2. I think I saw an article about using C-ci as in insert prefix before but I don’t remember where so apologies for the lack of attribution.

3. Yes, it doesn’t save many keystrokes but for a guy like me who can’t remember what day it is, let alone the date, it lightens the cognitive load considerably.

Vertical buffer mode

May 28th, 2008

Something I’ve heard and read more than a few times is "why should I use emacs when I have notepad / wordpad / textpad". At least notepad and wordpad are not serious contenders as a programmers editor, but textpad has a few nice features such as the ability to edit multiple files and source code coloring. Of course, emacs can do both of these so the most recent time a developer said it I challenged them as to why they prefer Textpad to emacs.

The first complaint, quite predictably, was that Ctrl-C / Ctrl-V doesn’t work as they are used to. Emacs 22 ships with a mode that fixes this - cua-mode. The developer was pleasantly surprised to discover that activating this mode makes mark/cut/copy/paste work as they would expect1.

(cua-mode t)

The next thing he mentioned that he liked was the list of all currently opened files. Hmmm… C-x C-b (list-buffers) gives the same thing right? Actually this wasn’t quite what he wants. Textpad keeps a permanent list of opened files in a noarrow frame at the left of the window. This strikes me as a waste of space, but I guess the customer is always right. Let me hack something up quickly.

(defun vertical-buffer-list ()
  (interactive)
  (list-buffers)
  (delete-other-windows)
  (split-window-horizontally 30)
  (switch-to-buffer “*Buffer List*”)
  (toggle-read-only 0)
  (sort-lines nil (point-min) (point-max))
  (toggle-read-only t)
  (other-window 1)
  (move-beginning-of-line 1))

(global-set-key [f3] ‘vertical-buffer-list)

He was relatively happy with how that looked, but clicking on the file opened the buffer in the buffer-list frame, not in the main frame. The function that runs when the mouse is clicked is Buffer-menu-mouse-select. The obvious solution is to flip the buffers after it finishes running which can be implemented simply using advice.

(defun buffer-flip-windows ()
  (let ((b (current-buffer)))
    (switch-to-buffer “*Buffer List*”)
    (other-window 1)
    (switch-to-buffer b)))

(defadvice Buffer-menu-mouse-select (after buffer-other-window)
  “Open the new buffer in the other window”
  (funcall ‘buffer-flip-windows))

(ad-activate ‘Buffer-menu-mouse-select)

Of course, this is a pretty ugly/fragile/unconfigurable hack, but it shows what can be mocked-up in a few lines of emacs-lisp. If you want to see what emacs is really capable of along these lines check out ECB.

After I finished, I used it myself briefly but found I was always closing the buffer-list window to maximise real-estate. I modified the advice to the following:

(defadvice Buffer-menu-mouse-select (after buffer-other-window)
  “Delete the other windows after opening the new buffer”
  (delete-other-windows))

Why should a developer use emacs rather than Textpad? In emacs, everything is infinitely changeable and extendable. I have written many tiny functions to save me time while working and also a couple of medium applications that sit nicely within the emacs framework. Fantastically useful tools such as org-mode, muse and fly-make have been implemented and are simple to install and use. With emacs, there are no real limits. That is why I use emacs. However, it might not be a good reason for you.

JG


1. I almost said correctly there, but of course the emacs way is the correct way.

Quiz mode

May 26th, 2008

Here is a tiny emacs app just for fun. Someone asked me for a program that would test their subject knowledge prior to an exam. I could have implemented this in a million different ways and I chose emacs to make a simple keyboard driven interface.

The questions are along the lines of given a case who is the claimant and who is the defendant. The obvious data structure is a list of triples containing the name of the case and the parties. As most of emacs editing functionality is not required it makes sense to make a major mode which I will call quiz.

Specifying all of the questions took most of the time…

(defconst *quiz-questions*
  ‘(
    ["Invitation to treat" "Fisher" "Bell"]
    ["Offer" "Carlill" "Carbolic Smoke"]
    ;; … More cases
    ))

(defconst *quiz-number-of-questions*
  (length *quiz-questions*))

(defvar quiz-current-question 0)

A bunch of accessors is just good style in case I decide on an alternative data structure.

(defsubst quiz-get-case (q) (aref q 0))
(defsubst quiz-get-claimant (q) (aref q 1))
(defsubst quiz-get-defendant (q) (aref q 2))
(defsubst quiz-get-number-of-parties (q) (- (length q) 1))

I store the number of the current question and the current question in quiz-current question.

(defun quiz-choose-question ()
  (let ((n (random *quiz-number-of-questions*)))
    (setq quiz-current-question (cons n (nth n *quiz-questions*)))))

This user would probably like to see all of the options available at all times. Therefore asking a question should look like this:

(n)ext | (a)nswer | (q)uit

Offer --> ?

…and selecting the answer should say:

(n)ext | (a)nswer | (q)uit

Offer --> Carlill vs Carbolic Smoke
(defun quiz-init-buffer ()
  (erase-buffer)
  (insert “(n)ext | (a)nswer | (q)uit\n\n”))

(defun quiz-display-question ()
  (let ((q (quiz-get-case (cdr quiz-current-question))))
    (insert (format “%s –> ?” q))
    (backward-char)))

(defun quiz-parties-to-string (c)
  (let ((p (quiz-get-number-of-parties c))
        (claimant (quiz-get-claimant c)))
    (if (= p 1) (format “%s” claimant)
      (format “%s vs %s” claimant (quiz-get-defendant c)))))

The actual interface is provided by quiz-next-question quiz-get-answer and quiz-quit. get-answer could do with a bit of a tidy-up but for a quick hack it will do.

(defun quiz-next-question ()
  (interactive)
  (quiz-init-buffer)
  (quiz-choose-question)
  (quiz-display-question))

(defun quiz-get-answer ()
  (interactive)
  (let* ((q (cdr quiz-current-question))
         (c (quiz-get-case q))
         (p (quiz-parties-to-string q)))
    (quiz-init-buffer)
    (insert (format “%s –> %s” c p))))

(defun quiz-quit ()
  (interactive)
  (when (y-or-n-p “Really quit? “)
    (save-buffers-kill-emacs)))

Now set up the major mode. It is a lot easier than you might think with define-derived-mode.

A quick note about the keymap: I want to disable other key-bindings. There are a couple of ways to do this: (suppress-keymap quiz-mode-map) or (define-key quiz-mode-map [t] ‘undefined). I used the second of these which disables every key you haven’t defined but I add back in M-x as I’m always scared of being trapped in a mode with no way out.

(defvar quiz-mode-map nil
  “Keymap for quiz major mode.”)

(define-derived-mode quiz-mode text-mode “Quiz”
  “Major mode for interacting with databases.
Special commands:
\\{quiz-mode-map}”)

(if quiz-mode-map
    nil
  (setq quiz-mode-map (make-sparse-keymap))
  (define-key quiz-mode-map “n” ‘quiz-next-question)
  (define-key quiz-mode-map “a” ‘quiz-get-answer)
  (define-key quiz-mode-map “q” ‘quiz-quit)
  (define-key quiz-mode-map [t] ‘undefined)
  (define-key quiz-mode-map “\M-x” ‘execute-extended-command))

(defun quiz-enter-quiz-mode ()
  (interactive)
  (switch-to-buffer “*quiz*” t)
  (random t)
  (quiz-mode)
  (quiz-next-question))

Finally, load up the defaults and enter the mode when we start.

(load “c:/packages/emacs-files/my-vars.el”)
(add-to-list ‘load-path *elisp-dir*)

(requiremy-defaults)

;; 
(quiz-enter-quiz-mode)

The complete file looks like this:

;; ———————————————————————- ;;

(load “c:/packages/emacs-files/my-vars.el”)
(add-to-list ‘load-path *elisp-dir*)

(requiremy-defaults)

;; ———————————————————————- ;;

(defconst *quiz-questions*
  ‘(
    ["Invitation to treat" "Fisher" "Bell"]
    ["Offer" "Carlill" "Carbolic Smoke"]
    ;; … More cases
    ))

(defconst *quiz-number-of-questions*
  (length *quiz-questions*))

(defvar quiz-current-question 0)

(defsubst quiz-get-case (q) (aref q 0))
(defsubst quiz-get-claimant (q) (aref q 1))
(defsubst quiz-get-defendant (q) (aref q 2))
(defsubst quiz-get-number-of-parties (q) (- (length q) 1))

;; ———————————————————————- ;;

(defun quiz-choose-question ()
  (let ((n (random *quiz-number-of-questions*)))
    (setq quiz-current-question (cons n (nth n *quiz-questions*)))))

(defun quiz-display-question ()
  (let ((q (quiz-get-case (cdr quiz-current-question))))
    (insert (format “%s –> ?” q))
    (backward-char)))

(defun quiz-init-buffer ()
  (erase-buffer)
  (insert “(n)ext | (a)nswer | (q)uit\n\n”))

(defun quiz-next-question ()
  (interactive)
  (quiz-init-buffer)
  (quiz-choose-question)
  (quiz-display-question))

(defun quiz-parties-to-string (c)
  (let ((p (quiz-get-number-of-parties c))
        (claimant (quiz-get-claimant c)))
    (if (= p 1) (format “%s” claimant)
      (format “%s vs %s” claimant (quiz-get-defendant c)))))

(defun quiz-get-answer ()
  (interactive)
  (let* ((q (cdr quiz-current-question))
         (c (quiz-get-case q))
         (p (quiz-parties-to-string q)))
    (quiz-init-buffer)
    (insert (format “%s –> %s” c p))))

(defun quiz-quit ()
  (interactive)
  (when (y-or-n-p “Really quit? “)
    (save-buffers-kill-emacs)))

;; ———————————————————————- ;;

(defvar quiz-mode-map nil
  “Keymap for quiz major mode.”)

(define-derived-mode quiz-mode text-mode “Quiz”
  “Major mode for interacting with databases.
Special commands:
\\{quiz-mode-map}”)

(if quiz-mode-map
    nil
  (setq quiz-mode-map (make-sparse-keymap))
  (define-key quiz-mode-map “n” ‘quiz-next-question)
  (define-key quiz-mode-map “a” ‘quiz-get-answer)
  (define-key quiz-mode-map “q” ‘quiz-quit)
  (define-key quiz-mode-map [t] ‘undefined)
  (define-key quiz-mode-map “\M-x” ‘execute-extended-command))

(defun quiz-enter-quiz-mode ()
  (interactive)
  (switch-to-buffer “*quiz*” t)
  (random t)
  (quiz-mode)
  (quiz-next-question))

;; ———————————————————————- ;;

(quiz-enter-quiz-mode)

;; ———————————————————————- ;;

This is the batchfile to start quiz mode.

set EMACS_FILES=c:/packages/emacs-files
set EMACS_DIR=c:/packages/emacs-22.1

%EMACS_DIR%/bin/runemacs.exe -q --load %EMACS_FILES%/quiz.el

Emacs file uploader

May 23rd, 2008

I recently received a couple of emails from people saying something along the lines of muse, htmlize and some cobbled-together file uploading functions may be sufficient for a guy with a text-only blog such as myself. However, for a blog with images, emacs isn’t really a practical solution. They clearly don’t know about the excellent dired mode.

dired displays a directory listing within a buffer and allows you to easily perform all sorts of operations on those files or a selection of files including deleting, renaming, chmoding, compressing, performing regex replacements… well, you get the picture. It is a pretty cool file manager. Not only that, but it allows you to hook your own code into it.

If you recall I already have a file upload function (ftp-upload-file) defined from here. That being the case we can easily add a binding to call that function when we press a key in a dired buffer.

;; ———————————————————————- ;;

(defun ftp-dired-upload-file ()
  (interactive)
  (ftp-upload-file (expand-file-name (dired-get-file-for-visit))))

(define-key dired-mode-map “\C-c\C-u” ‘ftp-dired-upload-file)

;; ———————————————————————- ;;

I also added a keybinding to open my images directory. Who knows, maybe one day I’ll even use it :)

;; ———————————————————————- ;;

(defconst *ftp-images-directory* (concat *ftp-WEB* “blog/images”))

(defun ftp-dired-get-images-dir ()
  (interactive)
  (dired *ftp-images-directory*))

(global-set-key “\C-Ci” ‘ftp-dired-get-images-dir)

;; ———————————————————————- ;;

PHP, emacs-lisp and wrapping

May 22nd, 2008

I’ve come to the conclusion (like many people before me no doubt) that there are two ways to make a blog popular. The first of these is to write smart things that your readers will learn from. The second of these is to write patently absurd claims1 and wait for the defenders of the truth to show up and assault your comments section. Obviously, the first of these options is far harder than the second.

One thing you can be sure of is Jeff "Coding Horror" Atwood will often provoke a good discussion. Fairly frequently this will be because of how wrong his posts are. For example, take his most recent post PHP sucks, but it doesn’t matter. Not since Giles Bowkett touted lack of debugger support as a feature can I remember such a ridiculous article. Yahoo and Facebook aren’t using PHP because it is available on all the cheap shared hosting platforms. They are using it because it solves some problems that other popular languages do not.

In many ways, PHP is in a similar boat to emacs-lisp. It isn’t the greatest language (although it isn’t that bad), but a whole bunch of things have been written for it/in it that no-one wants to write for themselves. In PHP’s case, that includes great database access and integration with apache. In emacs-lisp that includes emacs itself, org-mode, muse, tramp, ange-ftp, etc. etc.

Another thing that people seem to forget, is that once you have a way of making basic data structures and subroutines you can go a long way towards fixing many problems that a language has. E.g. if you don’t like the inconsistent naming of the subroutines in PHP, wrap them with your own better names. Make sure you follow a good example such as this one.

JG


1. Hey - maybe I should try that. Er, Vista is a great operating system! Vi is better than emacs!

Emacs, muse and htmlize

May 20th, 2008

It looks like I missed an interesting discussion on humane markup langages last week. Obviously I use emacs to write my blog posts with muse and htmlize. A tiny bit of Juan wrap makes it a pleasure. I wouldn’t write at all if I had to use raw HTML (although maybe it wouldn’t be so bad if I used nxml-mode).

I like the comments about normalizing HTML. Show me the code. Until there is something available I’ll stick to my regex based humane markup translator thank you very much. Of course I know that comments require a different level of trust than your own publishing system (unless for some reason it is not the case that you trust yourself but you don’t trust ‘them‘). However, you should still minimise the effort required or far fewer people will leave comments.

JG

Note: in the code below we could redefine muse-html-header and muse-html-footer to get the exact output that we want but in fact it is handy to have the html available so you can load it into a browser.

Update: I found that this guy said something similar to what I wanted to say, but he said it much more elegantly.

;; ———————————————————————- ;;

(requiremuse-mode)
(requiremuse-publish)
(requiremuse-html)

;; ———————————————————————- ;;

(defconst *muse-start* “Page published by Emacs Muse begins here”)
(defconst *muse-end* “Page published by Emacs Muse ends here”)

(defun my-muse-publish ()
  “Publish the current page as html and copy the html into the clipboard”
  (interactive)
  (let* ((cb (current-buffer))
         (filename (buffer-file-name))
         (extpos (string-match “.muse$” filename))
         (html-file (concat (substring filename 0 extpos) “.html”)))
    (muse-publish-file filename “html”)
    (let ((b (get-file-buffer html-file))
          (kill-buffer-query-functions nil))
      (when b (kill-buffer b)))
    (find-file html-file)

    (goto-char (point-min))
    (re-search-forward *muse-start*)
    (move-beginning-of-line 2)
    (let ((begin (point)))
      (re-search-forward *muse-end*)
      (move-beginning-of-line -1)
      (copy-region-as-kill begin (point)))

    (switch-to-buffer cb)
    (message “file published”)))

(define-key muse-mode-map [f7] ‘my-muse-publish)

;; ———————————————————————- ;;

(defun muse-minor-modes ()
  (longlines-mode 1)
  (font-lock-mode nil))

(add-hook ‘muse-mode-hook ‘muse-minor-modes)

;; ———————————————————————- ;;

(providemuse-config)

;; ———————————————————————- ;;

Considering paying for hosting

May 17th, 2008

I’m sure my regular readers have by now been wondering why the regular updates have petered out. Recently I’ve been faced with a dilemma. Since this blog became insanely popular I’ve been thinking of paying for hosting. Well, actually it isn’t popular at all - fewer than 300 people have visited in total. However, I know that I could attract many more a few more people by (e.g.) posting more frequently.

So why pay for hosting? That’s crazy talk right? After all, my current free host offers everything I need - php and mysql to run wordpress and, at the current level of visitors, more than enough disk and bandwidth. Well, a couple of things.

First of all, right when the blog was taking off, I had 80 visitors one day and 40 the next. Okay, that is nothing but it is almost half my total. The reason for the sudden influx is that two of my posts were submitted to http://programming.reddit.com by some kind soul and shortly afterwards my blog was offline for one and a half days1. Readership cratered. The fact that the posts were voted into oblivion is beside the point.

The second issue I’ve had is that I half-suspect that the webhost itself is blacklisted in a few places. I’m not just saying that because I’m so dismally unpopular. I once tried to to convert one of my posts to a tinyurl which resulted in a page stating that the host has been blocked from tinyurl for sending spam or something to that effect2. Recently though, I’ve been able to use tinyurl again so it looks like it was just a temporary issue.

I’ve been unable to submit my posts to reddit either - they get removed shortly after submission which I initially attributed to this blacklisting. However as someone else successfully submitted my posts, I guess there is another reason.

Back to the pressing question - why pay for hosting? Surely I could use http://wordpress.com with such a low readership. Unfortunately, that wouldn’t work for me. I like to have the flexibility to modify my CSS without, ahem, paying. Also, I store files other than pictures and blog posts, namely emacs-lisp files. I could circumvent the latter by using an online storage site but the former I couldn’t without paying. If I’m going to pay, I’d rather get a full webhost and I couldn’t even find a price within 5 minutes of searching. That is annoying.

Assuming I am going to move hosts, the fact that I don’t own a domain means that any effort I spend popularizing this blog will be wasted as I will soon need to start from scratch. Hence the lack of recent updates. Of course, if I did end up paying I would want to get something back eventually. Hopefully I will finally become popular and the next time I find myself looking for a job I’ll be able to mention this blog and get the following response:

"Oh yeah, you’re the modest genius with the terrible writing over at the hugely memorable URL http://juangarcia.890m.com. You’re hired"

Yeah right!

JG


1. This is the only outstanding issue that I know of with the current host.

2. The original version of this post didn’t state that the problem with tinyurl has been resolved. Thanks to Patrix for pointing that out.