LinkdMode is a MinorMode for embedding little (optionally icon-decorated) hyperlinks in all kinds of text files, and doing various things with them (delimiting regions for processing, documenting and navigating source code, or creating a personal wiki notebook.) It is inspired by a lot of other modes: EevMode, HowmMode, EmacsWikiMode, and so on. But it works regardless of the MajorMode you are using, so it can be used to uniformly interlink files of many different kinds.
It’s in alpha release at this point, but progressing rapidly.
Is this the canonical version that we should use, or does ShaunJohnson have a version somewhere else?
This is the canonical version - I haven’t had any time to release a new version. – ShaunJohnson
If there are any users of LinkD out there I would like to hear from you, particularly regarding:
New release featuring a menu for LinkD mode and conditional enabling of LinkD mode in the targets of @file links. These two features can be customised using the variables linkd-use-menu and linkd-enable-linkd-mode-in-target.
Additionally all uses of defvar have been replaced by defcustom.
This version can be found here: Lisp:linkd.el.
I like it! Very simple to use. Here is some feedback – HTH:
‘mouse-2’key binding does not seem to work for me much of the time. I’m not sure why, or under what circumstances. When it doesn’t work, a
‘yank’occurs instead. I don’t know if there is a bug in Emacs 22 or in Linkd or in my own code.
‘down-mouse-2’in my own code, so I thought that binding it to nil on the link text might help. I tried making these changes, but they didn’t really help:
(defun linkd-follow-mouse (event) "Follow the clicked link." (interactive "e") (when event (select-window (posn-window (event-start event))) ; <== Added (goto-char (posn-point (event-start event))) (linkd-follow (linkd-link-at-point)))) (overlay-put overlay 'keymap (let ((keymap (make-sparse-keymap))) (define-key keymap [down-mouse-2] nil) ; <== Added (define-key keymap [(mouse-2)] 'linkd-follow-mouse) (define-key keymap (kbd "M-RET") 'linkd-follow-at-point) keymap))
(@...)”. One way to reproduce this is to leave
‘linkd-mode’and reenter. It also occurs when
‘mouse-2’(incorrectly) yanks text into a link and then I undo the yank – the undo changes the link appearance to “
(@...)” with a yellow foreground. (I’m not using icons, BTW.)
C-c , s’ – it seems to create an empty link, which I doubt is a good thing.
C-c .’, I got an error “
no follow function for link nil”, which might have been appropriate, but it was not appropriate that it sent me to the beginning of the buffer. It should leave point where it was.
;; See (@> "Foo Bar and how it will make ;; you healthy and wise)
Thanks for your comments and feedback. I’ve added several TODO items to my OrgMode page for the project.
I’m going to remove the default keybinding for mouse-2 and let people choose their own. I’m probably going to use M-mouse-1 or something. I really hate how mouse-2 is X yank command, but also the default for following links in Emacs. Especially in light of it being a little difficult (for me) to press scroll wheels without scrolling. – DavidOtoole
You’re welcome; hope it helps.
Do you mean that users will need to tweak the overlay code, to put key bindings on the text? Many users will never do that. I think your first approach was better: provide some mouse binding on the text itself. It doesn’t really matter if it is
‘mouse-2’ is the more conventional one, so far.
I retested, using
emacs -q in a December 2006 build of Emacs 22, and I ran into the same
‘mouse-2’ problems. So it has nothing to do with my own
I also retested using using
emacs -q in Emacs 21, and I had no such problem – it worked perfectly. So, I think there is an Emacs 22 bug involved here. Please test this yourself and report a bug (
‘report-emacs-bug’) if you can specify a recipe to reproduce it. Thanks again for Linkd. BTW, what does the
‘d’ stand for, “David”? – DrewAdams
Hi again DrewAdams,
Yes my name is DavidOtoole. I will try to figure out the bug. Thanks for your testing!
1. Any news? Did you find and report an Emacs 22 bug? I see that your latest version does not bind a mouse button at all. That’s too bad. Many potential users would gladly click a mouse button to move around buffers easily, but they might not want to use keyboard keys. Linkd is something that could be useful to novice users, as well as hardcore Emacs fans.
2. Please consider also adding some more description for the mode, so users will see, for instance info on the major features and bindings when they do
3. Thanks for adding
‘linkd-back’. – DrewAdams
This inspired me to finish and publish an idea I have been carrying around for long. I have written an elisp library to make links out of the text in any buffer. The definition of links depends on the current major mode and it is extensible through a table. Links are of course created automatically. There is currently support for html, web mail, emacs lisp etc. Maybe this idea can be married with LinkdMode in some way? (I have asked long ago, but the interest seems low.)
linkd-edit-link-at-point seems not worked. I think follwings is worked. – Sugawara
(defun linkd-edit-link-at-point () "Edit the Linkd link at point." (interactive) (let ((link (linkd-link-at-point))) (when link (goto-char (next-single-char-property-change (point) 'linkd)) (if (keywordp (car (cdr link))) (save-excursion ; it's a general link. drop the @ sign (linkd-insert-link (substring (format "%S" (car link)) 1) (cdr link))) ;; it's a single-arg link (let ((new-value (read-from-minibuffer "New value: " (car (cdr link))))) (save-excursion (insert (format "%S" (list (car link) new-value)))))) ;; now erase old link (re-search-backward linkd-generic-regexp) (delete-region (match-beginning 0) (match-end 0)))))
A bug in the function ‘linkd-match’ causes the error “wrong argument symbolp, (some list in your code)” when using lazy-lock font-lock mode. Replacing linkd-match with the version below fixes the error:
(defun linkd-match (limit) "Try to read link sexp between point and LIMIT. Return non-nil if a link is found. Set match-data appropriately." (let ((sexp nil)) (when (search-forward (concat "(" "@") limit t) (backward-char 2)) (let ((begin-point (point))) (condition-case nil (setq sexp (read (current-buffer))) ((error nil))) (when (and (symbolp (car-safe sexp)) ; <-- clause added to prevent feeding non-symbol to 'symbol-name' (string-match "@.*" (symbol-name (car-safe sexp)))) (let ((begin-marker (make-marker)) (end-marker (make-marker))) (set-marker begin-marker begin-point) (set-marker end-marker (point)) (set-match-data (list begin-marker end-marker))) t))))
(@...) always represents a linkd link. This can be a problem in lisp code if it calls a function or macro whose name starts with
@, as linkd unfortunately does not restrict itself to comments and strings.
‘linkd-render-link’ to the version below, at least stops linkd from falling in a heap and breaking font-lock when it finds that a
@... function does not exist. The ideal solution would be to force linkd to only search in non-’code’ parts of a buffer.
(defun linkd-render-link (beg end) "Invoke a link's rendering code." (unless (get-text-property beg 'linkd-fontified) (save-excursion (goto-char beg) (let ((sexp (read (current-buffer)))) ;; The sexp is always a function call, where the name of the ;; function begins with '@' (when (and sexp (fboundp (car sexp))) (add-text-properties beg (+ beg 1) (list 'linkd-fontified t)) (let* ((plist (eval sexp)) (renderer (plist-get plist :render))) (unless renderer (error "No renderer for link.")) (funcall renderer beg end)))))))
I’m not the maintainer of Linkd, but I applied your fix to the Wiki copy of linkd.el, and I informed the maintainer. Thanks.
Wrt your comment about not rendering in non-code sections: I’m not sure that’s always appropriate. We could check for comment syntax, but Linkd is also useful for buffers that have no notion of comments (e.g. text files). – DrewAdams