|B||X||Update xtla : E-Mail from Stefan Reichör (2005.06.02)|
|B||X||Change to BBDB aliases instead of (2005.05.06)|
|B||X||Write BBDB/Planner code for (2005.05.06)|
|B||X||Modify my note markup code for more blockish-ness (2005.04.21 planner emacs)|
|B||X||Modify my task markup code to make it tabular (2005.04.21 planner emacs)|
|B||C||Migrate the rest of my configuration to XEmacs (2005.04.21)|
20. (semi)form letters: hooray for open source!: 23:35
Fortunately, my mail client was up to the task. One of the benefits of having both your contact information and your mail client in an easily-programmable environment is that you can hack together a quick program to do exactly what you want.
I had typed everyone's two-year-plans into my contact information manager's Notes field following a special format. It was the work of a few minutes to record and run a macro that extracted the data and created a signature for each person who attended my send-off party.
I then wrote a couple of short functions that looped over the currently displayed contact records and drafted messages for each of them following a template.
This resulted in 31 drafts I could edit and send without hassles. Much fun!
For future reference (and for the handful of Emacs geeks or learners in the audience), here's the code I used to make it all happen:
(defun sacha/bbdb-send-form-mail (bbdb-record &optional subject template) "Compose a form message to the people indicated by the current BBDB record(s)." (interactive (list (if (bbdb-do-all-records-p) (mapcar 'car bbdb-records) (bbdb-current-record)) (read-string "Subject: ") (read-string "Template (<NICK>): "))) (if (consp bbdb-record) (let ((records bbdb-record)) (while records (sacha/bbdb-send-form-mail-1 (car records) subject template) (setq records (cdr records)))) (sacha/bbdb-send-form-mail-1 bbdb-record subject template))) (defun sacha/bbdb-send-form-mail-1 (bbdb-record &optional subject template) "Compose a form message for one person." (if bbdb-inside-electric-display (bbdb-electric-throw-to-execute (list 'sacha/bbdb-send-form-mail bbdb-record subject))) ;; else... (cond ((null bbdb-record) (error "record unexists")) ((null (bbdb-record-net bbdb-record)) (message "%s record unhas a network addresses." (or (bbdb-record-name bbdb-record) "Unknown"))) (t (bbdb-send-mail-internal (bbdb-dwim-net-address bbdb-record) subject (list bbdb-record)) (goto-char (point-min)) (when (re-search-forward "--text follows this line--" nil t) (forward-line 1) (insert template) (goto-char (point-min)) (while (search-forward "<NICK>" nil t) (replace-match (or (bbdb-record-getprop bbdb-record 'nick) (bbdb-record-name bbdb-record)) t t)) (when (bbdb-record-getprop bbdb-record 'signature) (goto-char (point-max)) (insert "\n") (let ((p (point))) (insert (bbdb-record-getprop bbdb-record 'signature)) (fill-region-as-paragraph p (point)))) (goto-char (point-min)) (if (re-search-forward "^Subject: $" nil t) (end-of-line))))))
I used M-x local-set-key to bind sacha/bbdb-send-form-mail to M. * M then applies the function to all displayed records. ../emacs/miniedit.el makes it easy to edit long strings in the minibuffer, and that made the template much easier to write.
Emacs totally rocks. Nothing else has ever given me this much power.
自動車製造は人間の労働者に代わって、コンピューターが組み込まれたロボットによって行われている。 Car manufacturing is carried out by computer-programmed robots in place of human workers.
19. Working with Emacs: 12:12
There is a difference between discussion and stroking each other's ego. :)
Working with Emacs is a humbling experience. It brings you face to face with accumulated centuries of developers' work. Emacs involves people in its development to an unusual extent. Working with vi and even Eclipse made me feel more like a user than a co-developer. Working with Emacs made me feel part of the community, even when I was still struggling to make sense of the parentheses.
If in that sense, Emacs worship is considered ego-stroking, then sure, I'm guilty. I can't help but express my appreciation for one of those things that has really changed my life and made free, open source software really meaningful to me. For the culture, really, that made it possible. It's a piece of software, but it's also a conversation with so many developers around the world.
To newbies: if you're curious about the thrills of open source development and you want a nice, easy way to get started, why not try modifying Emacs? It's easy to pick up. All the source code is there, and you can modify it on the fly. We've had complete non-programmers try it out and fall in love with programming. They get thrilled when they share their tweaks and other people respond with comments and suggestions. This is good stuff. Try it out. =)
I suppose Emacs is off-topic. After all, it's cross-platform, not Linux-specific. I could easily be extolling the wonders of Emacs on Mac OS X, Microsoft Windows, or BSD. Emacs doesn't require Linux. (Neither does Apache, but you don't see people waxing lyrical about web servers that often, do you?) The flood of Emacs-related posts that deluge the list whenever someone unwittingly brings up the topic is probably incomprehensible to people who've never tried Emacs or tried Emacs as just an editor and didn't like it.
Still, I want to share what makes open source real for me. Not kernel hacking, which is still too intimidating despite the existence of projects like kernel-janitor. Not network or system administration, which I don't have the patience to do. Just the free and flexible customization of something I use everyday and the thrill of sharing these customizations with other people in a community that spans the world.
I guess that's why I post on PLUG instead of plug-misc. I don't think PLUG should just be a venue for asking and answering technical questions, but also for sharing nifty hacks and examples of how far a Linux system can be pushed. Other people push their systems in terms of hardware and services. I push mine in terms of how well it can fit me, how well it can anticipate my needs.
I want to stroke other people's egos. I want people to discover how they can contribute to free and open source software, to experience the thrill of seeing their code out there and being used. Open source development isn't just for PHP wizards or C freaks who can contribute to existing projects or launch an entirely new project on their own. Maybe--just maybe!--people who thought themselves just users of a text editor will be inspired to think about how they can start customizing their own.
コンピュータを使えば時間に節約になる。 Computers will save you a lot of time.
I can't help but agree with you. Emacs is the way that I appreciated FOSS more compared to GNU/Linux per se. Why? It's because I easily felt part of the community of Emacs users and hackers on the Emacs Wiki. That kind of interaction makes it less scary for newbies, IMHO. I mean, not all people on the Emacs Wiki are very friendly, I suppose, but the ones I have interacted with as I was learning to use various tools and modes available showed me that I can do something for the FOSS community, which is to write about what I learn. I don't even know ELISP but at least I know that my blog entries are helpful to others too. =)
I guess we have been too giddy over Emacs on the PLUG mailing list that is why someone suggested that. Well, I know I have always been giddy about it but I can't help myself! ^_^ Emacs is wonderful...
Besides there are so many hacks in Emacs that make FOSS usage, learning and advocacy so much fun! Like the Planner mode that allows me to somewhat organize my life, my thoughts, my schedule. Eshell allows me to do some things without opening a separate terminal. In Planner, I also store my notes on advocacy and my blog entry drafts. I also listen to music on Emacs. And when something goes wrong on whatever mode I am using, I can email the maintainer immediately, to tell him/her what happened so that the bug can be fixed, etc. I try to be as detailed as possible when I do that. So I guess that is my contribution. =)
In any case, I also enjoy the company of people using Emacs, not just because we talk about Emacs but because I am learning so much about you guys =)
18. Planner support for action-lock.el: 08:42
(add-to-list 'action-lock-default-rules (list (with-planner emacs-wiki-url-or-name-regexp) 'planner-action-lock-follow-name-at-point)) (setq action-lock-rules action-lock-default-rules) (defvar planner-action-lock-default-directory planner-directory "Expand files relative to this directory.") (defun planner-action-lock-follow-name-at-point (&optional other-window) (let ((link-name (match-string 0)) (base-buffer (current-buffer)) ;; the name of the buffer that contains the link. check ;; whether buffer-name is a WikiName, else make it one (parent-name (or (emacs-wiki-page-name) (concat "[[" (buffer-name) "]]")))) (with-planner (let ((link (emacs-wiki-wiki-link-target link-name))) (if (emacs-wiki-wiki-url-p link) (emacs-wiki-browse-url link other-window) ;; The name list is current since the last time the buffer was ;; highlighted (let* ((base (emacs-wiki-wiki-base link-name)) (file (emacs-wiki-page-file base)) (tag (and (not (emacs-wiki-wiki-url-p link)) (emacs-wiki-wiki-tag link))) (find-file-function (if other-window 'find-file-other-window 'find-file)) (parent-allowed-backlink-p (not (string-match emacs-wiki-exclude-backlink-parent-regexp parent-name))) (parent-backlink (and parent-allowed-backlink-p (emacs-wiki-get-current-backlink))) (newbuf (funcall find-file-function (or file (expand-file-name base (or planner-action-lock-default-directory (and (buffer-file-name) (file-name-directory (buffer-file-name))) default-directory))))) (emacs-wiki-create-backlinks (and emacs-wiki-create-backlinks parent-allowed-backlink-p)) (make-link-p (and emacs-wiki-create-backlinks ;; insert backlink only in new files (null file) (not (string-match emacs-wiki-exclude-backlink-regexp (emacs-wiki-page-name (buffer-file-name newbuf))))))) (when tag (goto-char (point-min)) (re-search-forward (concat "^\\.?#" tag) nil t)) (when refresh-buffer (when make-link-p (emacs-wiki-insert-backlink parent-name parent-backlink)) ;; todo: is with-current-buffer necessary here? (with-current-buffer newbuf (add-hook 'after-save-hook 'emacs-wiki-refresh-buffers-once t t) ;; save the new file to avoid another backlink if the ;; buffer is visited again before being saved (when (or make-link-p (and (null file) (not parent-allowed-backlink-p))) ;; set modified status to t: pages with excluded ;; parents may not be modified, but we want to save ;; anyway (set-buffer-modified-p t) (save-buffer))))))))))
コンピュータの知識はすべての科学」にとって基本である。 Knowledge of computers is basic to all sciences.
17. Emacs snippet for pmwiki attachments: 13:44
(defun sacha/dired-marked-images-as-attach () "Return a list of images ready to be inserted into a pmwiki page." (interactive) (kill-new (mapconcat (lambda (item) (concat "Attach:" (file-name-nondirectory item))) (dired-get-marked-files) "\n")))
16. Automatically scheduling tasks onto TaskPool: 10:52
(defadvice planner-create-task-from-buffer (before paul activate) "Automatically schedule task onto TaskPool as well as other projects." (if plan-page (unless (string-match plan-page "TaskPool") (setq plan-page (concat plan-page planner-multi-separator "TaskPool"))) (setq plan-page "TaskPool")))
Here's another snippet that will unschedule tasks from TaskPool when you mark them completed with C-c C-x (planner-task-done). Nifty stuff, huh?
(defadvice planner-task-done (after paul activate) "Remove completed tasks from the TaskPool if that still leaves them linked." (let ((info (planner-current-task-info))) (when (planner-task-link-text info) ;; If it is linked to TaskPool _and_ at least one other thing (if (string-match planner-multi-separator (planner-task-link-text info)) (planner-multi-replan-task (planner-multi-make-link (planner-multi-filter-links "^TaskPool$" (planner-multi-task-link-as-list info) t))) ;; Else if it has a date and is linked to TaskPool (if (and (planner-task-date info) (string= (planner-task-link info) "TaskPool")) (planner-replan-task nil))))))
原始的な計算機が、コンピューターの開発されるずっと以前に存在していた。 Primitive calculating machines existed long before computers were developed.
15. Adding an arbitrary extension to your planner files: 16:55
Use the 'rename' tool to add .txt extensions to all of your files, or use the following code to rename all of your planner files from a running Planner setup:
(defun my-rename-planner-files () "Rename all my planner files to .txt if they don't have that extension yet." (interactive) (mapcar (lambda (file) (unless (string-match "\\.txt$" (cdr file)) (rename-file (cdr file) (concat (cdr file) ".txt")) (message "%s" (cdr file)))) (planner-file-alist)) (with-planner (emacs-wiki-refresh-file-alist)))
Then add this to your ~/.emacs before you load Planner:
(setq emacs-wiki-ignored-extensions-regexp "\\.txt") (defadvice emacs-wiki-find-file (around extension activate) "Open the Emacs Wiki page WIKI by name. If COMMAND is non-nil, it is the function used to visit the file. If DIRECTORY is non-nil, it is the directory in which the Wiki page will be created if it does not already exist." (unless (interactive-p) (setq wiki (cons wiki (cdr (assoc wiki (emacs-wiki-file-alist)))))) ;; At this point, `wiki' is (GIVEN-PAGE FOUND-FILE). (if (cdr wiki) (let ((buffer (funcall (or command 'find-file) (cdr wiki)))) (if (= (prefix-numeric-value current-prefix-arg) 16) (with-current-buffer buffer (set (make-variable-buffer-local 'emacs-wiki-directories) (cons (file-name-directory (cdr wiki)) emacs-wiki-directories)) (set (make-variable-buffer-local 'emacs-wiki-file-alist) nil))) buffer) (let* ((dirname (or directory (emacs-wiki-maybe t) (car emacs-wiki-directories))) (filename (expand-file-name (car wiki) dirname))) (unless (file-exists-p dirname) (make-directory dirname t)) (funcall (or command 'find-file) (concat filename ".txt")))))
新しいパソコンを買うつもりで金を溜めているんだ。 I am saving money in order to buy a new personal computer.
14. xtla and Gnus: 18:01
There is a feature in xtla.el to send/review patches via gnus.
To set it up, you need the following lines for your .emacs:(tla-insinuate-gnus) (setq tla-apply-patch-mapping '(((nil "planner" nil nil nil) "~/work/planner-dev/")))
Replace ~/work/planner-dev/ with your planner working directory
The patches are sent as .tar.gz files.
When you receive such a patch (I will send one soon), You can hit
K t v to view the patch
K t a to apply the patch
I can even provide a log message in the mail. You can insert the log message via C-c C-p in the tla-log-edit buffer.
E-Mail from Stefan Reichör
その限られた性能のために私はコンピユーターに幻滅を感じている。 Its limited capability has disenchanted me with computer.
13. Task management with Emacs: Text files: 09:58
The simplest way to get started with Emacs for task management is to keep your TODOs in a plain text file, like ~/TODO. You can keep this text file in any format you want. To make it easier for you to see what you need to do, you can keep active TODOs near the top and completed tasks near the bottom.
If you load your TODO file every time you start up Emacs, then you'll be sure to check it every day. Put the following line in your ~/.emacs to have it automatically loaded when you start:
You'll also want to make it easy to open during an Emacs session. If your TODO file is just a keyboard shortcut away, you'll find it easier to keep all of your reminders in the file. Here's a snippet that shows the TODO file in the current window.
(defun my/todo () "Bring up the TODO file." (interactive) (find-file "~/TODO") (goto-char (point-min))) ;; Now bind it to a convenient shortcut key (global-set-key (kbd "<f5> <f5>") 'my/todo)
Now you can hit F5 F5 to show your TODO. If you want your TODO file to show up in another window, remove that and use this snippet instead:
(defun my/todo () "Bring up the TODO file." (interactive) (find-file-other-window "~/TODO") (goto-char (point-min))) ;; Now bind it to a convenient shortcut key (global-set-key (kbd "<f5> <f5>") 'my/todo)
If you want to be able to add stuff to your TODO without getting distracted from your work, add this to your ~/.emacs:
(defun my/add-todo (task) "Add a line to the TODO file." (interactive "MTask: ") (with-current-buffer (find-file-noselect "~/TODO") (goto-char (point-min)) (insert task "\n") (save-buffer))) (global-set-key (kbd "<f5> t") 'my/add-todo)
See? Emacs is fun and easy to configure. You can store your tasks in a plain text file and then add keyboard shortcuts to make your tasks easier to manage.
There are many sophisticated task management packages for Emacs. I'll write about one of them tomorrow. In the meantime, if you want to find out what task manager I _really_ like using, you can check out PlannerMode! =)
何社製のコンピューターをお使いですか。 What make of computer do you use?
12. BBDB tags: 01:52
HEY. This might actually work. Here's a quick test of
(defun sacha/bbdb-get-tags (record) "Return the tags for RECORD as a list." (let ((tags (bbdb-record-getprop record 'tags))) (when tags (split-string tags)))) (defun sacha/bbdb-test-tags (query tags) "Return non-nil if QUERY is a subset of TAGS." (let ((result t)) (while (and result query) (unless (member (car query) tags) (setq result nil)) (setq query (cdr query))) result)) (defun sacha/bbdb-search-tags-internal (records tags) "Return a list of RECORDS matching TAGS." (when (stringp tags) (setq tags (split-string tags))) (let (result) (while records (when (sacha/bbdb-test-tags tags (sacha/bbdb-get-tags (car records))) (setq result (cons (car records) result))) (setq records (cdr records))) result)) (defun sacha/bbdb-search-tags (tags) "Display all the records that match TAGS." (interactive "MTags: ") (bbdb-display-records (sacha/bbdb-search-tags-internal (bbdb-records) tags))) (defun sacha/planner-bbdb-link (record) "Return a link to RECORD." (or (bbdb-record-getprop record 'plan) ;; From a BBDB entry with a plan page; use that. Yay! (concat "[[bbdb://" (emacs-wiki-replace-regexp-in-string " " "." (bbdb-record-name record)) "][" (bbdb-record-name record) "]]"))) (defun sacha/bbdb-get-tags-index () "Return a list of tags and records." (let ((tags-alist '()) (records (bbdb-records)) tags entry list link) (while records (setq tags (sacha/bbdb-get-tags (car records))) (while tags (setq entry (assoc (car tags) tags-alist)) (setq list (cdr entry)) (add-to-list 'list (car records)) (if entry (setcdr entry list) (add-to-list 'tags-alist (cons (car tags) list))) (setq tags (cdr tags))) (setq records (cdr records))) tags-alist)) (defun sacha/planner-bbdb-insert-tags-alist (&optional tag-alist) "Insert TAG-ALIST into the current buffer." (interactive) (unless tag-alist (setq tag-alist (sacha/bbdb-get-tags-index))) (insert (mapconcat (lambda (item) (concat (car item) " | " (mapconcat 'sacha/planner-bbdb-link (cdr item) ","))) tag-alist "\n")))
To think that only took me an hour of leisurely coding (including my contact information)...
昨年度のコンピューターからの利益は、今年度分よりも１０％近く多かった。 Profit on computers for the previous year was nearly ten percent higher than the current year.
11. sacha/emacs-wiki-markup-string: 16:21
(defun sacha/emacs-wiki-markup-string (string) "Mark up STRING according to `emacs-wiki-publishing-rules'. No header or footer is added." (let ((emacs-wiki-project emacs-wiki-current-project)) (with-temp-buffer (emacs-wiki-mode) (insert string) (let ((emacs-wiki-publishing-header "") (emacs-wiki-publishing-footer "")) (emacs-wiki-replace-markup)) (buffer-string))))
うちの猫は台所にいます。 Our cat is in the kitchen.
10. Lightning completion and highlight completion: 00:28
私はこの猫の世話をしなければならない。 I have to look after this cat.
9. Modification of johnsu01's scoring: 15:44
(setq planner-sort-tasks-key-function 'planner-sort-tasks-by-score) (defvar planner-score-rules '(("read" . 50)) "Alist of planner scoring rules of the form (regexp . score-value). Tasks with higher scores are listed first.") (defun planner-sort-tasks-by-score () "Sort tasks by the rule in the table." (let ((score 0) (case-fold-search t) (line (buffer-substring-no-properties (line-beginning-position) (line-end-position)))) (mapc (lambda (item) (when (string-match (car item) line) (setq score (- score (cdr item))))) planner-score-rules) score))
8. Managing my mail: 15:38
Yes, yes, the Gmail way is to keep everything in one folder and then use searches to filter your messages. Still, I like being able to glance at my screen and see 2 personal messages and 3 planner-related messages.
I use Gnus topics to divide my mail into folders and subfolders. Mail groups are hidden unless they have mail. Some groups like mail.misc and mail.planner are generally useful, so I keep them visible even if they don't have unread mail.
Gnus allows you to automatically score threads and messages up and down based on various criteria. You can set it to completely hide boring messages, show them in a different color, show interesting messages in a different color, etc.
On most mailing lists and newsgroups, I don't bother reading message bodies. I just scan through subjects, hitting k to kill entire threads I don't find interesting. Gnus remembers what threads I've killed, marks them as read, and scores them down automatically. It also scores up messages containing certain keywords, replies to my posts, and threads I found interesting.
I put interesting people in my BBDB contact database. Gnus indicates messages from them with a little + beside their name in the message summary. If someone I know is interested in a thread, I might find it interesting as well.
I've set Gnus up to hide quoted text. This makes browsing through threads much easier because I can concentrate only on the the new parts. I can hit a few keys to expose sections of the quoted text if the replies aren't immediately obvious from the context.
I can also set it up to remove ads at the bottom of messages, particularly long signatures, To: lines with more than N recipients, that sort of thing. I can tell it to strip out HTML, too.
Sometimes I'll jump into the middle of a thread. I can use ^ to get to the parent message.
I use swish++ to index and search through my personal and planner-related mail.
Most of my tasks come in through e-mail. Planner lets me keep track of my TODOs easily by automatically hyperlinking to the mail message I'm looking at when I create a task. Dealing with a few items on my TODO list is much easier than going through a large inbox! =)
7. flashcard-import-from-kill: 10:17
(defun flashcard-import-from-kill (deck) "Import cards for DECK from the clipboard, which should be colon-separated. Question : Answer" (interactive (list flashcard-deck)) (unless (eq major-mode 'flashcard-mode) (error "You're not in a deckfile.")) (with-temp-buffer (yank) (goto-char (point-min)) (while (re-search-forward "^ *\\(.*\\) +: +\\(.*\\)$" nil t) (flashcard-add-card deck (flashcard-make-card (match-string 1) (match-string 2))))) (when (and (interactive-p) (not flashcard-card)) (flashcard-ask)))
6. Nifty Japanese stuff: Kakasi: 10:36
5. highlight-tail-mode: 09:24
4. More Emacs evangelization: flashcard: 15:43
I told him to download Emacs and grab Jorgen Schaefer's flashcard.el from my ../emacs directory. I then grabbed the dictionary file that Kanji Gold couldn't recognized, replaced [ with : to get flashcard to recognize it without problems, then set up a deck for him. I tweaked the default faces a bit--they're horrible on light-colored displays. I copied the suggested feedback config and explained the pigeonhole method to him. I tweaked the checking function so that it checked for substrings and treated empty input as a definitely incorrect answer. He wanted the answers displayed all the time, so I coded that in as well.
The initial word list was too big, so I copied 9 words and put them into a file, then imported them into a deck. Later, when he finishes this deck, I'll show him how to create another colon file and import it. I'll also ask him if he wants to tweak the number of compartments.
He's asked me if I can get YM working in the text editor as well. I'm currently tunneled through Richi's host, but I think I can open a local tunnel for him as well, if he feels like using ERC. 'course, normal YM just might work, and chances are there's a YM-specific client somewhere in Emacs.
I've made no efforts to hide Emacs' complexity. I lean over and drop into Lisp code in front of him because I want him to have a working environment up and running as soon as possible. Who knows? Maybe he'll use Emacs even after the internship. =)
He looks like he's having fun, and certainly appreciates the fact that I can hack the editor to fit how he wants to do things. He wants to match the readings, too, which means I'll need to figure out how leim works under Windows. I'll do that on Monday.
3. Emacs for Authors: 12:54
A book writer has written a guide on how to use Emacs in lieu of mainstream word processors. Check it out!
Post from R. Wood on comp.emacs
2. two-mode-mode: Multiple modes in one Emacs buffer: 12:50
1. xtla goodness ([[EmacsTips#note19][EmacsTips:19]]"[[emacs]]) : 18:42
In related news, I'll really need to migrate the archive. At 98414