Diary SiteMap RecentChanges About Contact Calendar

Search:

Matching Pages:

Emacs

Emacs Feed The pages where I write about Emacs. It doesn’t happen very often. I think you’re probably best off following Planet Emacsen.

2014-07-26 Oddmuse Curl

These days I’ve been working on Oddmuse Curl, an Emacs mode for editing Oddmuse wikis including this one, and Emacs Wiki. I’ve been trying to fit more and more functionality into the Emacs Version Control (VC) framework. It has been an interesting challenge. There still many things I’m missing, but a surprising amount of stuff already works.

  • better highlighting of wiki markup
  • inserting known pages
  • following links
  • creating new pages
  • posting any buffer to a wiki
  • creating new “blog” pages (name starts with current date)
  • searching wiki for a text (this does not work for Emacs Wiki because of Duck Duck Go unless you add old=1 to oddmuse-search-command – and that’s very slow)
  • searching wiki for matching page names (since we already have a list of page names cached, I guess a fancier interface is possible)
  • preview of edits in an Emacs buffer
  • preview of edits in a local file with a browser
  • preview of current page in a browser (browse-url)
  • diff with current version on the wiki
  • revert to current version on the wiki
  • log of all the changes made to a page
  • recent changes

Tags: RSS RSS

Add Comment

2014-06-26 Encrypting Mail using Gnus on OSX

Today I learned…

  1. If you want to use GPG, and you’re on OSX, pinentry will not work. You need a graphical pinentry tool. Your best bet is GPG Tools which is linked from the GnuPG website. You get Mail and Keychain integration for free, which I don’t really care about at the moment, and you get all the command line tools. Thus when I ran gpg in eshell just now, I was asked for my passphrase.
  2. If you want Emacs to know about your gpg-agent, you need to tell it about the PID and the temporary file and all that. My solution is Emacs-only. There’s probably a better way to do this such that you can use GPG from elsewhere as well. See the code snippet below.
  3. If you use Gnus to send mail, you cannot read the encrypted mails unless you set a mysterious variable. See the code snippet below.

First, how to run gpg-agent from your init file:

(setenv "GPG_AGENT_INFO"
	(with-temp-buffer
	  (shell-command "/usr/local/bin/gpg-agent --daemon" (current-buffer))
	  (goto-char (point-min))
	  (when (re-search-forward "GPG_AGENT_INFO=\\([^;\n]+\\)" nil t)
	    (match-string 1))))
;; (getenv "GPG_AGENT_INFO")

How to make sure that mails are always encrypted to you, too:

(setq mml2015-encrypt-to-self t
      mml2015-signers '("353AEFEF"))

There you go.

The alternative to mml2015-signers would be to set mml2015-sign-with-sender to t, I guess.

Tags: RSS RSS

Comments on 2014-06-26 Encrypting Mail using Gnus on OSX

Thanks! I’ve been meaning to get round to this for ages.

– Alok Singh 2014-06-28 14:09 UTC



AlexSchroeder
Now that I have GPG Tools installed, I’m not sure the GPG_AGENT_INFO environment variable is still needed. The entire business of setting environment variables for OSX Maverick is a mess. 😡

AlexSchroeder 2014-06-28 14:47 UTC

Add Comment

2014-06-24 Emacs and Dice

Recently, somebody asked on Google+:

If I roll one of the five standard gaming dice (d4, d6, d8, d10, d12) and you also roll one of those, what are my chances of rolling higher, equal or lower than you, for each possible combination of dice.

I decided to write a little program to simply count it since I was unable to figure it out by thinking it through.

Update: Now that I’ve looked at the data, the formula is obvious. Assume x is the lower die:

x winning `(x(x-1))/2/(xy) = (x-1)/(2y)`
tie `x/(xy) = 1/y`
y winning `((x(x-1))/2 + x(y-x))/(xy) = 1 - ((x+1)/(2y))`
(dolist (die-1 '(4 6 8 10 12))
  (dolist (die-2 '(4 6 8 10 12))
    (unless (< die-2 die-1)
      (let ((a 0) (b 0) (n 0))
	(insert (format "d%d vs. d%d" die-1 die-2))
	(newline)
	(newline)
	(insert "     ")
	(dotimes (roll-1 die-1)
	  (insert (format " %4d" (1+ roll-1))))
	(newline)
	(dotimes (roll-2 die-2)
	  (insert (format " %4d" (1+ roll-2)))
	  (dotimes (roll-1 die-1)
	    (insert "    "
		    (cond ((> roll-1 roll-2)
			   (incf a)
			   "A")
			  ((= roll-1 roll-2)
			   (incf n)
			   "-")
			  (t
			   (incf b)
			   "B"))))
	  (newline))
	(newline)
	(let ((total (+ a b n)))
	  (insert (format "A: %d / %d = %4.3f\n" a total (/ a 1.0 total)))
	  (insert (format "B: %d / %d = %4.3f\n" b total (/ b 1.0 total)))
	  (insert (format "-: %d / %d = %4.3f\n" n total (/ n 1.0 total))))
	(newline)
	(newline)))))

d4 vs. d4

         1    2    3    4
    1    -    A    A    A
    2    B    -    A    A
    3    B    B    -    A
    4    B    B    B    -

A: 6 / 16 = 0.375
B: 6 / 16 = 0.375
-: 4 / 16 = 0.250


d4 vs. d6

         1    2    3    4
    1    -    A    A    A
    2    B    -    A    A
    3    B    B    -    A
    4    B    B    B    -
    5    B    B    B    B
    6    B    B    B    B

A: 6 / 24 = 0.250
B: 14 / 24 = 0.583
-: 4 / 24 = 0.167


d4 vs. d8

         1    2    3    4
    1    -    A    A    A
    2    B    -    A    A
    3    B    B    -    A
    4    B    B    B    -
    5    B    B    B    B
    6    B    B    B    B
    7    B    B    B    B
    8    B    B    B    B

A: 6 / 32 = 0.188
B: 22 / 32 = 0.688
-: 4 / 32 = 0.125


d4 vs. d10

         1    2    3    4
    1    -    A    A    A
    2    B    -    A    A
    3    B    B    -    A
    4    B    B    B    -
    5    B    B    B    B
    6    B    B    B    B
    7    B    B    B    B
    8    B    B    B    B
    9    B    B    B    B
   10    B    B    B    B

A: 6 / 40 = 0.150
B: 30 / 40 = 0.750
-: 4 / 40 = 0.100


d4 vs. d12

         1    2    3    4
    1    -    A    A    A
    2    B    -    A    A
    3    B    B    -    A
    4    B    B    B    -
    5    B    B    B    B
    6    B    B    B    B
    7    B    B    B    B
    8    B    B    B    B
    9    B    B    B    B
   10    B    B    B    B
   11    B    B    B    B
   12    B    B    B    B

A: 6 / 48 = 0.125
B: 38 / 48 = 0.792
-: 4 / 48 = 0.083


d6 vs. d6

         1    2    3    4    5    6
    1    -    A    A    A    A    A
    2    B    -    A    A    A    A
    3    B    B    -    A    A    A
    4    B    B    B    -    A    A
    5    B    B    B    B    -    A
    6    B    B    B    B    B    -

A: 15 / 36 = 0.417
B: 15 / 36 = 0.417
-: 6 / 36 = 0.167


d6 vs. d8

         1    2    3    4    5    6
    1    -    A    A    A    A    A
    2    B    -    A    A    A    A
    3    B    B    -    A    A    A
    4    B    B    B    -    A    A
    5    B    B    B    B    -    A
    6    B    B    B    B    B    -
    7    B    B    B    B    B    B
    8    B    B    B    B    B    B

A: 15 / 48 = 0.312
B: 27 / 48 = 0.562
-: 6 / 48 = 0.125


d6 vs. d10

         1    2    3    4    5    6
    1    -    A    A    A    A    A
    2    B    -    A    A    A    A
    3    B    B    -    A    A    A
    4    B    B    B    -    A    A
    5    B    B    B    B    -    A
    6    B    B    B    B    B    -
    7    B    B    B    B    B    B
    8    B    B    B    B    B    B
    9    B    B    B    B    B    B
   10    B    B    B    B    B    B

A: 15 / 60 = 0.250
B: 39 / 60 = 0.650
-: 6 / 60 = 0.100


d6 vs. d12

         1    2    3    4    5    6
    1    -    A    A    A    A    A
    2    B    -    A    A    A    A
    3    B    B    -    A    A    A
    4    B    B    B    -    A    A
    5    B    B    B    B    -    A
    6    B    B    B    B    B    -
    7    B    B    B    B    B    B
    8    B    B    B    B    B    B
    9    B    B    B    B    B    B
   10    B    B    B    B    B    B
   11    B    B    B    B    B    B
   12    B    B    B    B    B    B

A: 15 / 72 = 0.208
B: 51 / 72 = 0.708
-: 6 / 72 = 0.083


d8 vs. d8

         1    2    3    4    5    6    7    8
    1    -    A    A    A    A    A    A    A
    2    B    -    A    A    A    A    A    A
    3    B    B    -    A    A    A    A    A
    4    B    B    B    -    A    A    A    A
    5    B    B    B    B    -    A    A    A
    6    B    B    B    B    B    -    A    A
    7    B    B    B    B    B    B    -    A
    8    B    B    B    B    B    B    B    -

A: 28 / 64 = 0.438
B: 28 / 64 = 0.438
-: 8 / 64 = 0.125


d8 vs. d10

         1    2    3    4    5    6    7    8
    1    -    A    A    A    A    A    A    A
    2    B    -    A    A    A    A    A    A
    3    B    B    -    A    A    A    A    A
    4    B    B    B    -    A    A    A    A
    5    B    B    B    B    -    A    A    A
    6    B    B    B    B    B    -    A    A
    7    B    B    B    B    B    B    -    A
    8    B    B    B    B    B    B    B    -
    9    B    B    B    B    B    B    B    B
   10    B    B    B    B    B    B    B    B

A: 28 / 80 = 0.350
B: 44 / 80 = 0.550
-: 8 / 80 = 0.100


d8 vs. d12

         1    2    3    4    5    6    7    8
    1    -    A    A    A    A    A    A    A
    2    B    -    A    A    A    A    A    A
    3    B    B    -    A    A    A    A    A
    4    B    B    B    -    A    A    A    A
    5    B    B    B    B    -    A    A    A
    6    B    B    B    B    B    -    A    A
    7    B    B    B    B    B    B    -    A
    8    B    B    B    B    B    B    B    -
    9    B    B    B    B    B    B    B    B
   10    B    B    B    B    B    B    B    B
   11    B    B    B    B    B    B    B    B
   12    B    B    B    B    B    B    B    B

A: 28 / 96 = 0.292
B: 60 / 96 = 0.625
-: 8 / 96 = 0.083


d10 vs. d10

         1    2    3    4    5    6    7    8    9   10
    1    -    A    A    A    A    A    A    A    A    A
    2    B    -    A    A    A    A    A    A    A    A
    3    B    B    -    A    A    A    A    A    A    A
    4    B    B    B    -    A    A    A    A    A    A
    5    B    B    B    B    -    A    A    A    A    A
    6    B    B    B    B    B    -    A    A    A    A
    7    B    B    B    B    B    B    -    A    A    A
    8    B    B    B    B    B    B    B    -    A    A
    9    B    B    B    B    B    B    B    B    -    A
   10    B    B    B    B    B    B    B    B    B    -

A: 45 / 100 = 0.450
B: 45 / 100 = 0.450
-: 10 / 100 = 0.100


d10 vs. d12

         1    2    3    4    5    6    7    8    9   10
    1    -    A    A    A    A    A    A    A    A    A
    2    B    -    A    A    A    A    A    A    A    A
    3    B    B    -    A    A    A    A    A    A    A
    4    B    B    B    -    A    A    A    A    A    A
    5    B    B    B    B    -    A    A    A    A    A
    6    B    B    B    B    B    -    A    A    A    A
    7    B    B    B    B    B    B    -    A    A    A
    8    B    B    B    B    B    B    B    -    A    A
    9    B    B    B    B    B    B    B    B    -    A
   10    B    B    B    B    B    B    B    B    B    -
   11    B    B    B    B    B    B    B    B    B    B
   12    B    B    B    B    B    B    B    B    B    B

A: 45 / 120 = 0.375
B: 65 / 120 = 0.542
-: 10 / 120 = 0.083


d12 vs. d12

         1    2    3    4    5    6    7    8    9   10   11   12
    1    -    A    A    A    A    A    A    A    A    A    A    A
    2    B    -    A    A    A    A    A    A    A    A    A    A
    3    B    B    -    A    A    A    A    A    A    A    A    A
    4    B    B    B    -    A    A    A    A    A    A    A    A
    5    B    B    B    B    -    A    A    A    A    A    A    A
    6    B    B    B    B    B    -    A    A    A    A    A    A
    7    B    B    B    B    B    B    -    A    A    A    A    A
    8    B    B    B    B    B    B    B    -    A    A    A    A
    9    B    B    B    B    B    B    B    B    -    A    A    A
   10    B    B    B    B    B    B    B    B    B    -    A    A
   11    B    B    B    B    B    B    B    B    B    B    -    A
   12    B    B    B    B    B    B    B    B    B    B    B    -

A: 66 / 144 = 0.458
B: 66 / 144 = 0.458
-: 12 / 144 = 0.083

Tags: RSS RSS

Comments on 2014-06-24 Emacs and Dice

I thought you drew the visualizations by hand. I didn’t think your little piece of Lisp code drew them. Three cheers for simulations with Lisp!

Aaron S. Hawley 2014-06-24 23:05 UTC



AlexSchroeder
Thanks. :)

AlexSchroeder 2014-06-25 10:05 UTC

Add Comment

2014-04-07 Homebrew Problems

I’ve been using Homebrew on our Mac for a while now. I like it very much. I’ve recently run into an issue, though. Sending emails from Emacs stopped working. I was getting was this:

Opening STARTTLS connection to `fencepost.gnu.org:25'...failed
network-stream-get-response: Wrong type argument: processp, nil

The important setting to remember to learn more is this:

(setq smtpmail-debug-info t)

Resent the mail and switch to a buffer called *trace of SMTP session to fencepost.gnu.org*.

There:

220 fencepost.gnu.org ESMTP Exim 4.71 Mon, 07 Apr 2014 01:00:52 -0400
250-fencepost.gnu.org Hello 178-83-163-103.dynamic.hispeed.ch [178.83.163.103]
250-SIZE 52428800
250-PIPELINING
250-AUTH CRAM-MD5
250-STARTTLS
250 HELP

Process smtpmail deleted
dyld: Library not loaded: /usr/local/lib/libnettle.4.7.dylib
  Referenced from: /usr/local/bin/gnutls-cli
  Reason: image not found

Process smtpmail trace/BPT trap: 5

Oops, it seems that I uninstalled something that gnutls required!

Time to check things:

alex@Megabombus:/usr/local/bin (master)$ brew update
...
alex@Megabombus:/usr/local/bin (master)$ brew upgrade nettle
Error: nettle-2.7.1 already installed
alex@Megabombus:/usr/local/bin (master)$ brew upgrade gnutls
Error: gnutls-3.2.12.1 already installed
alex@Megabombus:/usr/local/bin (master)$ ls /usr/local/lib/libnettle.*
/usr/local/lib/libnettle.4.5.dylib /usr/local/lib/libnettle.a
/usr/local/lib/libnettle.4.dylib   /usr/local/lib/libnettle.dylib
alex@Megabombus:/usr/local/bin (master)$ brew reinstall gnutls
==> Reinstalling gnutls
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/gnutls-3.2.
Already downloaded: /Library/Caches/Homebrew/gnutls-3.2.12.1.mavericks.bottle.tar.gz
==> Pouring gnutls-3.2.12.1.mavericks.bottle.tar.gz
🍺  /usr/local/Cellar/gnutls/3.2.12.1: 931 files, 8,4M
alex@Megabombus:/usr/local/bin (master)$ brew reinstall nettle
==> Reinstalling nettle
Warning: nettle-2.7.1 already installed, it's just not linked
alex@Megabombus:/usr/local/bin (master)$ brew link  nettle
Linking /usr/local/Cellar/nettle/2.7.1... 16 symlinks created
alex@Megabombus:/usr/local/bin (master)$ gnutls-cli --version
gnutls-cli 3.2.12
Copyright (C) 2000-2014 Free Software Foundation, and others, all rights reserved.
This is free software. It is licensed for use, modification and
redistribution under the terms of the GNU General Public License,
version 3 or later <http://gnu.org/licenses/gpl.html>


Please send bug reports to:  <bugs@gnutls.org>

That seems to have fixed it!

I wonder how this happened in the first place.

Tags: RSS RSS

Add Comment

2014-02-14 Finding Duplicate Files

I have a ton of files I downloaded to my tablet and I have a ton of files on my external harddisk. How can I ever clean it all up? With Emacs, I have dired, but no easy way to figure out which files have changed – specially if the files are not all in the same directory structure. Based on EmacsWiki:JoeBloggsdired-dups.el I wrote a new version that did what I wanted it to do.

Find dired-duplicates.el on GitHub.

Now that I think about it, I guess my code does the exact opposite: it find differences, not duplicates. I should change those names…

(As it turns out, there are still bugs in the code. Ouch.)

Tags: RSS

Add Comment

2013-12-02 Emacs Defaults

I saw Andrew Hyatt post on Google+:

From the emacs-devel list comes a query for builtin packages that would be useful to enable by default.
They are interested in getting feedback from the community. If you have a builtin package you think should be enabled by default, add a comment, and we circulate this back to the emacs-devel list.

Check it out via Gmane, and now a survey on Emacs Wiki.

I skimmed my ~/.emacs and looked at all the little settings I think would make better defaults… For the complete file, see my current config file for Emacs on Windows.

(show-paren-mode 1)
(winner-mode 1)
(windmove-default-keybindings)
(column-number-mode 1)
(savehist-mode 1)
(iswitchb-mode 1)
(global-set-key (kbd "C-x C-b") 'bs-show)
(require 'dired-x)
(setq dired-recursive-deletes 'top
      dired-recursive-copies 'top
      dired-dwim-target t)
(setq sentence-end-double-space nil)
(dolist (hook '(emacs-lisp-mode-hook
        lisp-mode-hook
        rcirc-mode
        change-log-mode
        texinfo-mode-hook))
  (add-hook hook (lambda ()
           (eldoc-mode 1)
           (set (make-local-variable 'sentence-end-double-space) t))))
(setq eshell-save-history-on-exit t)
(setq cperl-hairy t
      cperl-electric-parens 'null)
(add-hook 'cperl-mode-hook
      (lambda ()
        (local-set-key (kbd "C-h f") 'cperl-perldoc)))
(add-hook 'rcirc-mode-hook
      (lambda ()
        (rcirc-track-minor-mode 1)))

(defun describe-hash (variable &optional buffer)
  "Display the full documentation of VARIABLE (a symbol).
    Returns the documentation as a string, also.
    If VARIABLE has a buffer-local value in BUFFER (default to the current buffer),
    it is displayed along with the global value."
  (interactive
   (let ((v (variable-at-point))
     (enable-recursive-minibuffers t)
     val)
     (setq val (completing-read
        (if (and (symbolp v)
             (hash-table-p (symbol-value v)))
            (format
             "Describe hash-map (default %s): " v)
          "Describe hash-map: ")
        obarray
        (lambda (atom) (and (boundp atom)
                    (hash-table-p (symbol-value atom))))
        t nil nil
        (if (hash-table-p v) (symbol-name v))))
     (list (if (equal val "")
           v (intern val)))))
  (with-output-to-temp-buffer (help-buffer)
    (maphash (lambda (key value)
           (pp key)
           (princ " => ")
           (pp value)
           (terpri))
         (symbol-value variable))))

(define-key isearch-mode-map (kbd "C-h") 'isearch-highlight-phrase)

(put 'narrow-to-region 'disabled nil)
(put 'not-modified 'disabled t)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)

Tags: RSS

Add Comment

2013-10-22 Random Names on IRC

Sometimes I wonder whether nicks on IRC give too much away. Sex, cultural background, … So here’s an experiment. Do you treat the people the same if you can’t see their nick names?

The following setup uses colored nicks and random names for <span class="site">Emacs</span><span class="separator">:</span><span class="page">rcirc</span>.

rcirc: Random Names

Tags: RSS

Add Comment

2013-07-26 Extracting Starred URLs from Google Reader Takeout Data

Google Reader was shut down. Luckily Google Takeout allowed you to download all of your data before the shut it down. I did that. I wanted to extract all the URLs to the articles I starred in order to post them on this blog… maybe.

Here’s how I did it. First, take a look at the file starred.json.

    (setq starred-items (with-current-buffer "starred.json (Google Reader-takeout.zip)"
			  (goto-char (point-min))
			  (json-read)))
    (mapcar (lambda (item) (car item)) starred-items)
    ⇒ (items direction updated author title id)

I’m interested in items, which happens to be an array. Let’s see what each item contains.

    (mapcar (lambda (item) (car item))
            (aref (cdr (assoc-string "items" starred-items)) 0))
    ⇒ (origin annotations comments author content replies alternate updated published title categories id timestampUsec crawlTimeMsec)

As it happens, the URL I’m interested in is part of alternate. Let’s make sure there’s always exactly one entry:

    (mapc (lambda (item)
	    (when (not (= 1 (length (cdr (assoc-string "alternate" item)))))
	      (error "%S" item)))
	  (cdr (assoc-string "items" starred-items)))

Phew! Let’s produce a first list of URLs and the respective titles:

    (mapc (lambda (item)
	    (let ((href (cdr (assoc-string "href"
					   (aref (cdr (assoc-string "alternate" item)) 0))))
		  (title (cdr (assoc-string "title" item))))
	      (insert (format "* [%s %s]\n" href title))))
	  (cdr (assoc-string "items" starred-items)))

I hate feedproxy URLs and so I absolutely wanted to get rid of all the URLs starting with http://feedproxy.google.com/. This required a bit more code since neither url-retrieve-synchronously nor url-retrieve do exactly what I want.

    (defun redirection-target (url)
      (save-match-data
	(let ((url-request-method "HEAD")
	      (retrieval-done nil)
	      (spinner "-\|/")
	      (n 0))
	  (url-retrieve url
			(lambda (status &rest ignore)
			  (setq retrieval-done t
				url (plist-get status :redirect)
				url (replace-regexp-in-string "blogspot\\.ch" "blogspot.com" url)
				url (replace-regexp-in-string "\\?utm.*" "" url))))
	  (while (not retrieval-done)
	    (sit-for 1)
	    (message "Waiting... %c" (aref spinner (setq n (mod (1+ n) (length spinner))))))
	  url)))

Now I can run the following search an replace operation in the buffer where I generated my list:

    (while (re-search-forward "http://feedproxy\\.google\\.com/\\S-+" nil t)
      (replace-match (redirection-target (match-string 0))))

Phew, thank you, Emacs!

Tags: RSS

Add Comment

2013-05-08 Distributing XP With Emacs

This topic ties together two topics that probably don’t see too much overlap.

  1. I play role-playing games of the D&D old school variety.
  2. I use Emacs to help me do simple stuff on a daily basis.

The problem: the party of characters my players run is huge. Even if there are usually only around ten characters that are part of a single session, there are more than thirty primary and secondary characters on the status page. Given the wiki table for the status page, how can I quickly add up the correct XP and gold values? Any XP gained is shared equally amongst the characters that took part in the session but any gold gained is distributed according to each characters share. Primary characters get a full share, secondary characters get a third of a share.

I used Emacs widget mode to create a page like this:

XP total:   805          
Gold total: 7191         
[X] Schalk
[ ] Uluf
[ ] Witschik
[X] Schachtmann
[ ] Sirius
[X] Logard
[X] Arnd
[X] Tinaya
[ ] Pyrula
[ ] Pijo
[ ] Garo
[X] Zeta
[ ] Pipo
[X] Fusstritt
[ ] Thor
[ ] Jack
[ ] Gloria
[ ] Hermann
[ ] Urs
[ ] Alpha
[ ] Beta
[ ] Gamma
[ ] Boden
[ ] Basel
[ ] Bern
[X] Nuschka
[ ] Moranor
[ ] Axirios Hectaxius

[Go!]

And here’s the code to do it:

(defconst fünf-winde-regexp "^\\(|\\[\\[\\(.*?\\)\\]\\][ \t]*|[ \t]*\\(1\\|1/3\\)[ \t]*\\)|\\([ \t]*[0-9]+[ \t]*\\)|\\([ \t]*[0-9]+[ \t]*\\)"
  "Regular expression to parse the Status page.
\(let ((str (match-string 1))
      (name (match-string 2))
      (share (match-string 3))
      (xp (match-string 4))
      (gold (match-string 5)))
    ...\)")

(defvar fünf-winde-buf nil
  "Source buffer.")

(defvar fünf-winde-xp nil
  "XP share.")

(defvar fünf-winde-gold nil
  "Gold share.")

(defvar fünf-winde-party nil
  "Charakters in the party.")

(defun fünf-winde-xp-and-gold ()
  "Hand out Gold and XP."
  (interactive)
  (let ((buf (current-buffer))
	(names))
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward fünf-winde-regexp nil t)
	(setq names (cons (match-string 2) names))))
    (switch-to-buffer "*Fünf Winde*")
    (kill-all-local-variables)
    (set (make-local-variable 'fünf-winde-buf) buf)
    (make-local-variable 'fünf-winde-xp)
    (make-local-variable 'fünf-winde-gold)
    (make-local-variable 'fünf-winde-party)
    (let ((inhibit-read-only t))
      (erase-buffer))
    (remove-overlays)
    (setq fünf-winde-xp
	  (widget-create 'integer
			 :size 13
			 :format "XP total:   %v\n"
			 0))
    (setq fünf-winde-gold
	  (widget-create 'integer
			 :size 13
			 :format "Gold total: %v\n"
			 0))
    (setq fünf-winde-party
	  (apply 'widget-create 'checklist
		 (mapcar (lambda (name)
			   `(item ,name))
			 (nreverse names))))
    (widget-insert "\n")
    (widget-create 'push-button
		   :notify (lambda (&rest ignore)
			     (fünf-winde-process
			      fünf-winde-buf
			      (widget-value fünf-winde-xp)
			      (widget-value fünf-winde-gold)
			      (widget-value fünf-winde-party)))
		   "Go!")
    (widget-insert "\n")
    (use-local-map widget-keymap)
    (local-set-key (kbd "q") 'bury-buffer)
    (local-set-key (kbd "SPC") 'widget-button-press)
    (local-set-key (kbd "<left>") 'widget-backward)
    (local-set-key (kbd "<up>") 'widget-backward)
    (local-set-key (kbd "<right>") 'widget-forward)
    (local-set-key (kbd "<down>") 'widget-forward)
    (widget-setup)
    (goto-char (point-min))
    (widget-forward 1)))

(defun fünf-winde-process (buf total-xp total-gold party)
  (message "(fünf-winde-process (get-buffer \"%s\") %d %d '%S)"
	   buf total-xp total-gold party)
  (switch-to-buffer buf)
  (save-excursion
    (let ((xp-shares 0)
	  (xp-share nil)
	  (gold-shares 0)
	  (gold-share nil))
      (goto-char (point-min))
      (while (re-search-forward fünf-winde-regexp nil t)
	(let ((name (match-string 2))
	      (share (match-string 3)))
	  (when (member name party)
	    (setq gold-shares (+ gold-shares
				 (cond ((string= share "1/2") 0.5)
				       ((string= share "1/3") (/ 1.0 3))
				       (t (string-to-number share))))
		  xp-shares (1+ xp-shares)))))
      (setq gold-share (/ total-gold gold-shares)
	    xp-share (/ total-xp xp-shares))
      (goto-char (point-min))
      (while (re-search-forward fünf-winde-regexp nil t)
	(let ((str (match-string 1))
	      (name (match-string 2))
	      (share (match-string 3))
	      (xp (match-string 4))
	      (gold (match-string 5)))
	  (when (member name party)
	    (setq gold (format (concat "%9d")
			       (+  (string-to-number gold)
				   (* gold-share (cond ((string= share "1/2") 0.5)
						       ((string= share "1/3") (/ 1.0 3))
						       (t (string-to-number share))))))
		  xp (format (concat "%9d")
			     (+  (string-to-number xp)
				 xp-share)))
	    (replace-match (concat str
				   "|" xp
				   "|" gold))))))))

I’m not sure I’m spending my time wisely, but there you go. I used to have a simpler piece of code that helped me distribute XP and gold separately. The drawback was that it would ask me for every person in the table “was this character in the party? (y/n)” and that’s a lot of yes and no replies if you go through the list twice.

It’s also a stark reminder that simpler old rules doesn’t automatically mean less work for the referee. With D&D 3.5, I had a spreadsheet to compute the XP gained based on challenge rating and character level. It wasn’t something to do quickly without a book in front of me. Now the complexity of the task has been reduced, but the number of characters has exploded to compensate!

Tags: RSS RSS RSS

Add Comment

2013-04-26 Emacs Wiki Redesign

I finally installed the new theme for Emacs Wiki. Feel free to leave comments on the Talk page. Bootstrap allows me to make all the changes at run-time, ie. add a few scripts including a script that changes the wiki’s HTML (emacs-bootstrap.js) and a new CSS file (bootstrap.css).

Since no changes to the script are necessary I can continue to provide the old theme for those that don’t feel like switching.

Tags: RSS

Comments on 2013-04-26 Emacs Wiki Redesign

Yay for bootstrap! It really makes the life easier if you want your web application to look consistently.

Radomir Dopieralski 2013-04-26 15:22 UTC

Add Comment

More...

Define external redirect: rcircRandomNames rcirc rcircColoredNicks