0
0

clickable minor mode

Last updated at Posted at 2024-08-10

概要

Emacs のテキスト内の URL 文字列をマウスクリックするとブラウザで開くためのものです.多分 Windows Emacs 限定です.

探せばたくさんありそうですし, デフォルトでもある機能ですが (自分は ido-use-url-at-point を使っています) お手軽に連続チェックしたいとき用のものです.

インストールなど

このページの下にある clickable-mode.el をファイルにして load-path の通ったところにおいて init.el でレクワイアしておき

init.el
(require 'clickable-mode)

使いたいときに起動します(必要ならキーバインドします).

M-x clickable-mode

起動中は url 文字列がリンク・フェイスになりマウスオーバーでハイライトし,左クリックするとブラウザでそのアドレスを開きます.
C-return でも開き tab, backtab で url 文字列を横断できます.

応用

常用するときは, 例えば html-mode ならinit.el に以下のように書きます.

init.el
(add-hook 'html-mode-hook #'clickable-mode)

menu に設定しておけば名前やバインドを忘れても安心です.

init.el
(easy-menu-add-item
 global-map '(menu-bar)
 '("Private" ["Clickable mode" clickable-mode
              :style toggle :selected clickable-mode]))

clickable-mode.el

clickable-mode.el
;;; clickable-mode.el --- Clickable minor mode.
;; $Id: clickable-mode.qiita,v 1.1 2024-08-10 09:06:18+09 fubuki Exp fubuki $

;;; Commentary:

;; Make the URL string clickable.

;;; Install:

;; (require 'clickable-mode)
;;
;; (easy-menu-add-item
;;  global-map '(menu-bar)
;;  '("Private" ["Clickable" clickable-mode
;;               :style toggle :selected clickable-mode]))

;;; fix:

;; Ctrl + mouse (C-mouse-1) 等で動かなかったのを修正.

;; (add-hook 'clickable-mode-hook
;;           (lambda ()
;;             (define-key clickable-mode-mouse-map [C-mouse-1] #'clickable-open)
;;             (define-key clickable-mode-mouse-map [C-down-mouse-1] #'clickable-open)))

;;; Code:

(defvar clickable-mode-mouse-map
  (let ((map (make-sparse-keymap)))
    (define-key map [mouse-1]  #'clickable-open)
    (define-key map [C-return] #'clickable-open)
    map))

(defvar clickable-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [tab]   #'clickable-next)
    (define-key map [S-tab] #'clickable-previous)
    map))

(defvar-local clickable-ov nil)
(defvar clickable-url "https?://[^\"> \n]+")

(defun clickable-make ()
  (let (ov)
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward clickable-url nil t)
        (push (make-overlay (match-beginning 0) (match-end 0)) ov)))
    (dolist (o ov)
      (overlay-put o 'category 'clickable)
      (overlay-put o 'face 'link)
      (overlay-put o 'mouse-face 'highlight)
      (overlay-put o 'uri (buffer-substring (overlay-start o) (overlay-end o)))
      (overlay-put o 'keymap clickable-mode-mouse-map))
    (setq clickable-ov ov)))

(defun clickable-clear ()
  (setq clickable-ov nil)
  (remove-overlays (point-min) (point-max) 'category 'clickable))

(defun clickable-open ()
  (interactive)
  (let ((pos (posn-point (event-start last-command-event))))
    (and pos (goto-char pos))
    (dolist (o (overlays-at (point)))
      (if (eq (overlay-get o 'category) 'clickable)
          (w32-shell-execute "open" (overlay-get o 'uri))))))

(defun clickable-next (arg)
  (interactive "p")
  (dotimes (i arg) (clickable--next)))

(defun clickable-previous (arg)
  (interactive "p")
  (dotimes (i arg) (clickable--previous)))

(defun clickable--next ()
  (let ((pos (next-single-char-property-change (point) 'category)))
    (goto-char pos)
    (or (overlays-at pos) (clickable--next))))

(defun clickable--previous ()
  (let ((pos (previous-single-char-property-change (point) 'category)))
    (goto-char pos)
    (or (overlays-at pos) (clickable--previous))))

;;;###autoload
(define-minor-mode clickable-mode
  "Mouse click url open mode."
  :init-value nil
  :lighter " Clickable"
  (if clickable-mode
      (clickable-make)
    (clickable-clear)))

;;;###autoload
(define-derived-mode clickable-text-mode text-mode  "CText"
  "Mouse click url open text mode."
  (clickable-mode 1))

(provide 'clickable-mode)
;;; clickable-mode.el ends here

更新情報 (Sep 7 2024)

github にその後機能強化した版をアップしました.
表示中に C-c @ c (clickable-change) でマッチ対象や生成リンクの変更ができるようになっています.
ルールはカスタム変数 clickable-url で指定します.

clickable-mode

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0