;;; minimap.el --- Sidebar showing a "mini-map" of a buffer
-;; Copyright (C) 2009-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
-;; Author: David Engster <dengste@eml.cc>
+;; Author: David Engster <deng@randomsample.de>
;; Keywords:
-;; Version: 1.0
+;; Version: 1.1
;; This file is part of GNU Emacs.
;; highlights the currently shown region and updates its position
;; automatically. You can navigate in the minibar by dragging the
;; active region with the mouse, which will scroll the corresponding
-;; edit buffer.
+;; edit buffer. Additionally, you can overlay information from the
+;; tags gathered by CEDET's semantic analyzer.
-;; To create the minimap sidebar, type M-x minimap-create.
-;; To dismiss it, type M-x minimap-kill.
-
-;; Usage:
-;; * Use 'M-x minimap-create' in a buffer you're currently editing.
-;; * Use 'M-x minimap-kill' to kill the minimap.
-;; * Use 'M-x customize-group RET minimap RET' to adapt minimap to your needs.
+;; Simply use M-x minimap-mode to toggle activation of the minimap.
+;; Use 'M-x customize-group RET minimap RET' to adapt minimap to your
+;; needs.
;;; KNOWN BUGS:
;; * Moving the active region with the keyboard / mouse-wheel ?
+;;; News:
+
+;;;; Changes since v1.0:
+;;
+;; - Largely rewritten as a minor mode; use M-x minimap-mode to
+;; enable/disable.
+;; - Minimap will now remain active for all buffers which derive from
+;; `prog-mode' (can be changed through `minimap-major-modes'). The
+;; minimap window will be automatically created or deleted (see new
+;; variables `minimap-recreate-window' and
+;; `minimap-automatically-delete-window').
+;; - Possibility to set a minimum width of the minimap window
+;; (`minimap-minimum-width').
+;; - Minimap window will be marked so that you should not be able to
+;; enter it.
+;; - Semantic overlays will be automatically updated during editing.
+;; - Lots of bug fixes.
+
;;; Customizable variables:
(defgroup minimap nil
'((((background dark))
(:box (:line-width 1 :color "white")
:inherit (font-lock-function-name-face minimap-font-face)
- :height 2.5 :background "gray10"))
+ :height 2.75 :background "gray10"))
(t (:box (:line-width 1 :color "black")
:inherit (font-lock-function-name-face minimap-font-face)
- :height 2.5 :background "gray90")))
+ :height 2.75 :background "gray90")))
"Face used for functions in the semantic overlay.")
(defface minimap-semantic-variable-face
'((((background dark))
(:box (:line-width 1 :color "white")
:inherit (font-lock-variable-name-face minimap-font-face)
- :height 2.5 :background "gray10"))
+ :height 2.75 :background "gray10"))
(t (:box (:line-width 1 :color "black")
:inherit (font-lock-function-name-face minimap-font-face)
- :height 2.5 :background "gray90")))
+ :height 2.75 :background "gray90")))
"Face used for variables in the semantic overlay.")
(defface minimap-semantic-type-face
'((((background dark))
(:box (:line-width 1 :color "white")
:inherit (font-lock-type-face minimap-font-face)
- :height 2.5 :background "gray10"))
+ :height 2.75 :background "gray10"))
(t (:box (:line-width 1 :color "black")
:inherit (font-lock-function-name-face minimap-font-face)
- :height 2.5 :background "gray90")))
+ :height 2.75 :background "gray90")))
"Face used for types in the semantic overlay.")
-(defcustom minimap-width-fraction 0.2
+(defcustom minimap-width-fraction 0.15
"Fraction of width which should be used for minimap sidebar."
:type 'number
:group 'minimap)
+(defcustom minimap-minimum-width 30
+ "Minimum width of minimap in characters (default size).
+Use nil to disable."
+ :type 'number
+ :group 'minimap)
+
(defcustom minimap-window-location 'left
"Location of the minimap window.
Can be either the symbol `left' or `right'."
(const :tag "Right" right))
:group 'minimap)
-(defcustom minimap-buffer-name-prefix "*MINIMAP* "
- "Prefix for buffer names of minimap sidebar."
+(defcustom minimap-buffer-name " *MINIMAP*"
+ "Buffer name of minimap sidebar."
:type 'string
:group 'minimap)
:type 'boolean
:group 'minimap)
-(defcustom minimap-hide-fringes t
+(defcustom minimap-hide-fringes nil
"Whether the minimap should hide the fringes."
:type 'boolean
:group 'minimap)
-(defcustom minimap-dedicated-window nil
+(defcustom minimap-dedicated-window t
"Whether the minimap should create a dedicated window."
:type 'boolean
:group 'minimap)
:type '(repeat symbol)
:group 'minimap)
+(defcustom minimap-major-modes '(prog-mode)
+ "Major modes for which a minimap should be created.
+This can also be a parent mode like 'prog-mode.
+If nil, a minimap must be explicitly created for each buffer."
+ :type '(repeat symbol)
+ :group 'minimap)
+
+(defcustom minimap-recreate-window t
+ "Whether the minimap window should be automatically re-created.
+If this is non-nil, the side window for the minimap will be
+automatically re-created as soon as you kill it."
+ :type 'boolean
+ :group 'minimap)
+
+(defcustom minimap-automatically-delete-window t
+ "Whether the minimap window should be automatically deleted.
+Setting this to non-nil will delete the minibuffer side window
+when you enter a buffer which is not derived from
+`minimap-major-modes' (excluding the minibuffer)."
+ :type 'boolean
+ :group 'minimap)
+
;;; Internal variables
+;; The buffer currently displayed in the minimap
+(defvar minimap-active-buffer nil)
+;; Window start/end from the base buffer
(defvar minimap-start nil)
(defvar minimap-end nil)
+;; General overlay for the minimap
+(defvar minimap-base-overlay nil)
+;; Overlay for the active region
(defvar minimap-active-overlay nil)
-(defvar minimap-bufname nil)
+;; Timer
(defvar minimap-timer-object nil)
-(defvar minimap-active-minimaps 0)
-(defvar minimap-base-overlay nil)
+;; Lines the minimap can display
(defvar minimap-numlines nil)
(defvar minimap-pointmin-overlay nil)
-(make-variable-buffer-local 'minimap-start)
-(make-variable-buffer-local 'minimap-end)
-(make-variable-buffer-local 'minimap-active-overlay)
-(make-variable-buffer-local 'minimap-bufname)
-(make-variable-buffer-local 'minimap-base-overlay)
-(make-variable-buffer-local 'minimap-numlines)
-(make-variable-buffer-local 'minimap-pointmin-overlay)
+;;; Helpers
+
+(defun minimap-active-current-buffer-p ()
+ "Whether the current buffer is displayed in the minimap."
+ (and (eq (current-buffer) minimap-active-buffer)
+ (get-buffer minimap-buffer-name)
+ (with-current-buffer minimap-buffer-name
+ (eq minimap-active-buffer (buffer-base-buffer)))))
+
+(defsubst minimap-get-window ()
+ "Get current minimap window."
+ (when (get-buffer minimap-buffer-name)
+ (get-buffer-window minimap-buffer-name)))
+
+(defsubst minimap-kill-buffer ()
+ "Kill the minimap buffer."
+ (when (get-buffer minimap-buffer-name)
+ (kill-buffer minimap-buffer-name)))
+
+(defun minimap-create-window ()
+ (let ((width (round (* (window-width)
+ minimap-width-fraction))))
+ (when (< width minimap-minimum-width)
+ (setq width minimap-minimum-width))
+ (if (eq minimap-window-location 'left)
+ (split-window-horizontally width)
+ (split-window-horizontally
+ (* -1 width))
+ (other-window 1))
+ ;; Set up the minimap window:
+ ;; You should not be able to enter the minimap window.
+ (set-window-parameter nil 'no-other-window t)
+ ;; Hide things.
+ (when minimap-hide-scroll-bar
+ (setq vertical-scroll-bar nil))
+ (when minimap-hide-fringes
+ (set-window-fringes nil 0 0))
+ ;; Switch to buffer.
+ (switch-to-buffer
+ (get-buffer-create minimap-buffer-name) t t)
+ ;; Do not fold lines in the minimap.
+ (setq truncate-lines t)
+ ;; Make it dedicated.
+ (when minimap-dedicated-window
+ (set-window-dedicated-p nil t))
+ (prog1
+ (selected-window)
+ (other-window 1))))
+
+(defun minimap-setup-hooks (&optional remove)
+ "Hook minimap into other modes.
+If REMOVE is non-nil, remove minimap from other modes."
+ (if remove
+ (progn
+ (remove-hook 'outline-view-change-hook 'minimap-sync-overlays)
+ (remove-hook 'hs-hide-hook 'minimap-sync-overlays)
+ (remove-hook 'hs-show-hook 'minimap-sync-overlays))
+ ;; outline-(minor-)mode
+ (add-hook 'outline-view-change-hook 'minimap-sync-overlays)
+ ;; hideshow
+ (add-hook 'hs-hide-hook 'minimap-sync-overlays)
+ (add-hook 'hs-show-hook 'minimap-sync-overlays)))
;;; Minimap creation / killing
+(define-minor-mode minimap-mode
+ "Toggle minimap mode."
+ :global t
+ :group 'minimap
+ :lighter " MMap"
+ (if minimap-mode
+ (progn
+ (when (and minimap-major-modes
+ (apply 'derived-mode-p minimap-major-modes))
+ (unless (minimap-get-window)
+ (minimap-create-window))
+ ;; Create minimap.
+ (minimap-new-minimap))
+ ;; Create timer.
+ (setq minimap-timer-object
+ (run-with-idle-timer minimap-update-delay t 'minimap-update))
+ ;; Hook into other modes.
+ (minimap-setup-hooks))
+ ;; Turn it off
+ (minimap-kill)
+ (minimap-setup-hooks t)))
+
;;;###autoload
(defun minimap-create ()
- "Create a minimap sidebar for the current window."
+ "Create a minimap sidebar."
(interactive)
- ;; If minimap is visible, do nothing.
- (unless (and minimap-bufname
- (get-buffer minimap-bufname)
- (get-buffer-window (get-buffer minimap-bufname)))
- (let ((bufname (concat minimap-buffer-name-prefix
- (buffer-name (current-buffer))))
- (new-win (if (eq minimap-window-location 'left)
- (split-window-horizontally
- (round (* (window-width)
- minimap-width-fraction)))
- (split-window-horizontally
- (round (* (window-width)
- (- 1 minimap-width-fraction))))
- (other-window 1))))
- ;; If minimap exists but isn't visible, reuse it.
- (if (and minimap-bufname
- (get-buffer minimap-bufname))
- (switch-to-buffer minimap-bufname t)
- ;; Otherwise create new minimap
- (minimap-new-minimap bufname)
- ;; If this is the first minimap, create the idle timer.
- (when (zerop minimap-active-minimaps)
- (setq minimap-timer-object
- (run-with-idle-timer minimap-update-delay t 'minimap-update)))
- (setq minimap-active-minimaps
- (1+ minimap-active-minimaps))))
- (other-window 1)
- (minimap-sync-overlays)))
+ (minimap-mode 1))
-(defun minimap-new-minimap (bufname)
- "Create new minimap BUFNAME for current buffer and window."
- (let ((indbuf (make-indirect-buffer (current-buffer) bufname t))
+(defun minimap-new-minimap ()
+ "Create new minimap BUFNAME for current buffer and window.
+Re-use already existing minimap window if possible."
+ (interactive)
+ (let ((currentbuffer (current-buffer))
+ (win (minimap-get-window))
+ (indbuf (make-indirect-buffer (current-buffer)
+ (concat minimap-buffer-name "_temp")))
(edges (window-pixel-edges)))
- (setq minimap-bufname bufname)
- (set-buffer indbuf)
- (when minimap-hide-scroll-bar
- (setq vertical-scroll-bar nil))
- (switch-to-buffer indbuf)
- (setq minimap-base-overlay (make-overlay (point-min) (point-max) nil t t))
- (overlay-put minimap-base-overlay 'face 'minimap-font-face)
- (overlay-put minimap-base-overlay 'priority 1)
- (setq minimap-pointmin-overlay (make-overlay (point-min) (1+ (point-min))))
- (setq minimap-start (window-start)
- minimap-end (window-end)
- minimap-active-overlay (make-overlay minimap-start minimap-end)
- line-spacing 0)
- (overlay-put minimap-active-overlay 'face
- 'minimap-active-region-background)
- (overlay-put minimap-active-overlay 'priority 5)
- (minimap-mode 1)
- (when (and (boundp 'linum-mode)
- linum-mode)
- (linum-mode 0))
- (when minimap-hide-fringes
- (set-window-fringes nil 0 0))
- (when minimap-dedicated-window
- (set-window-dedicated-p nil t))
- (setq buffer-read-only t)
- ;; Calculate the actual number of lines displayable with the minimap face.
- (setq minimap-numlines
- (floor
- (/
- (- (nth 3 edges) (nth 1 edges))
- (car (progn (redisplay) (window-line-height))))))))
+ ;; Remember the active buffer currently displayed in the minimap.
+ (setq minimap-active-buffer (current-buffer))
+ ;; Hook into CEDET if necessary.
+ (when (and minimap-display-semantic-overlays
+ (boundp 'semantic-after-toplevel-cache-change-hook))
+ (add-hook 'semantic-after-partial-cache-change-hook
+ 'minimap-apply-semantic-overlays nil t)
+ (add-hook 'semantic-after-toplevel-cache-change-hook
+ 'minimap-apply-semantic-overlays nil t))
+ (with-selected-window win
+ ;; Now set up the minimap:
+ (when (window-dedicated-p)
+ (set-window-dedicated-p nil nil))
+ (switch-to-buffer indbuf t t)
+ (minimap-kill-buffer)
+ (rename-buffer minimap-buffer-name)
+ ;; Do not fold lines in the minimap.
+ (setq truncate-lines t)
+ (when minimap-dedicated-window
+ (set-window-dedicated-p nil t))
+ (setq minimap-base-overlay (make-overlay (point-min) (point-max) nil t t))
+ (overlay-put minimap-base-overlay 'face 'minimap-font-face)
+ (overlay-put minimap-base-overlay 'priority 1)
+ (setq minimap-pointmin-overlay (make-overlay (point-min) (1+ (point-min))))
+ (setq minimap-start (window-start)
+ minimap-end (window-end)
+ minimap-active-overlay (make-overlay minimap-start minimap-end)
+ line-spacing 0)
+ (overlay-put minimap-active-overlay 'face
+ 'minimap-active-region-background)
+ (overlay-put minimap-active-overlay 'priority 5)
+ (minimap-sb-mode 1)
+ (when (and (boundp 'linum-mode)
+ linum-mode)
+ (linum-mode 0))
+ (setq buffer-read-only t)
+ ;; Calculate the actual number of lines displayable with the minimap face.
+ (setq minimap-numlines
+ (floor
+ (/
+ (- (nth 3 edges) (nth 1 edges))
+ (car (progn (redisplay t) (window-line-height)))))))
+ (minimap-sync-overlays)))
;;;###autoload
(defun minimap-kill ()
- "Kill minimap for current buffer.
-Cancel the idle timer if no more minimaps are active."
+ "Kill minimap."
(interactive)
- (if (null minimap-bufname)
- (message "No minimap associated with %s." (buffer-name (current-buffer)))
- (let ((curname (buffer-name (current-buffer)))
- (buf (get-buffer minimap-bufname))
- (win (get-buffer-window minimap-bufname)))
- (setq minimap-bufname nil)
- (if (null buf)
- (message "No minimap associated with %s." curname)
- (when win
- (delete-window win))
- (kill-buffer buf)
- (when (zerop
- (setq minimap-active-minimaps
- (1- minimap-active-minimaps)))
- (cancel-timer minimap-timer-object)
- (setq minimap-timer-object nil))
- (message "Minimap for %s killed." curname)))))
+ (when (minimap-get-window)
+ (delete-window (minimap-get-window)))
+ (cancel-timer minimap-timer-object))
;;; Minimap update
"Update minimap sidebar if necessary.
This is meant to be called from the idle-timer or the post command hook.
When FORCE, enforce update of the active region."
- (when minimap-bufname
- (let ((win (get-buffer-window minimap-bufname))
- start end pt ov)
- (when win
- (setq start (window-start)
- end (window-end)
- pt (point)
- ov)
- (with-selected-window win
- (unless (and (not force)
- (= minimap-start start)
- (= minimap-end end))
- (move-overlay minimap-active-overlay start end)
- (setq minimap-start start
- minimap-end end)
- (minimap-recenter (line-number-at-pos (/ (+ end start) 2))
- (/ (- (line-number-at-pos end)
- (line-number-at-pos start))
- 2)))
- (goto-char pt)
- (when minimap-always-recenter
- (recenter (round (/ (window-height) 2)))))))))
+ (interactive)
+ ;; If we are in the minibuffer, do nothing.
+ (unless (active-minibuffer-window)
+ (if (minimap-active-current-buffer-p)
+ ;; We are still in the same buffer, so just update the minimap.
+ (let ((win (minimap-get-window))
+ (start (window-start))
+ (end (window-end))
+ (pt (point)))
+ (when (and (null win)
+ minimap-recreate-window)
+ ;; The minimap window is no longer visible, so create it again...
+ (setq win (minimap-create-window))
+ ;; ...and switch to existing minimap buffer.
+ (with-selected-window win
+ (when (window-dedicated-p)
+ (set-window-dedicated-p nil nil))
+ (switch-to-buffer minimap-buffer-name t t)
+ (when minimap-dedicated-window
+ (set-window-dedicated-p nil t))))
+ (with-selected-window win
+ ;; Make sure the base overlay spans the whole buffer.
+ (unless (and (= (overlay-start minimap-base-overlay) (point-min))
+ (= (overlay-end minimap-base-overlay) (point-max)))
+ (move-overlay minimap-base-overlay (point-min) (point-max)))
+ (unless (and (not force)
+ (= minimap-start start)
+ (= minimap-end end))
+ ;; Update the overlay.
+ (move-overlay minimap-active-overlay start end)
+ (setq minimap-start start
+ minimap-end end)
+ (minimap-recenter (line-number-at-pos (/ (+ end start) 2))
+ (/ (- (line-number-at-pos end)
+ (line-number-at-pos start))
+ 2)))
+ (goto-char pt)
+ (when minimap-always-recenter
+ (recenter (round (/ (window-height) 2)))))
+ ;; Redisplay
+ (sit-for 0))
+ ;; The buffer was switched, check if the minimap should switch, too.
+ (if (and minimap-major-modes
+ (apply 'derived-mode-p minimap-major-modes))
+ (progn
+ ;; Create window if necessary...
+ (unless (minimap-get-window)
+ (minimap-create-window))
+ ;; ...and re-create minimap with new buffer...
+ (minimap-new-minimap)
+ ;; Redisplay
+ (sit-for 0)
+ ;; ...and call update again.
+ (minimap-update t))
+ ;; Otherwise, delete window if the user so wishes.
+ (when (and (minimap-get-window)
+ minimap-automatically-delete-window)
+ ;; We wait a tiny bit before deleting the window, since we
+ ;; might only be temporarily in another buffer.
+ (run-with-timer 0.3 nil
+ (lambda ()
+ (when (and (null (minimap-active-current-buffer-p))
+ (minimap-get-window))
+ (delete-window (minimap-get-window))))))))))
;;; Overlay movement
(start-point (posn-point end-posn))
(make-cursor-line-fully-visible nil)
(cursor-type nil)
+ (minimap-automatically-delete-window nil)
(pcselmode (when (boundp 'pc-selection-mode)
pc-selection-mode))
pt ev)
;;; Minimap minor mode
-(defvar minimap-mode-map (make-sparse-keymap)
- "Keymap used by `minimap-mode'.")
+ (defvar minimap-sb-mode-map (make-sparse-keymap)
+ "Keymap used by `minimap-sb-mode'.")
-(define-key minimap-mode-map [down-mouse-1] 'minimap-move-overlay-mouse)
-(define-key minimap-mode-map [down-mouse-2] 'minimap-move-overlay-mouse)
-(define-key minimap-mode-map [down-mouse-3] 'minimap-move-overlay-mouse)
+(define-key minimap-sb-mode-map [down-mouse-1] 'minimap-move-overlay-mouse)
+(define-key minimap-sb-mode-map [down-mouse-2] 'minimap-move-overlay-mouse)
+(define-key minimap-sb-mode-map [down-mouse-3] 'minimap-move-overlay-mouse)
-(define-minor-mode minimap-mode
+(define-minor-mode minimap-sb-mode
"Minor mode for minimap sidebar."
- nil "minimap" minimap-mode-map)
+ nil "minimap" minimap-sb-mode-map)
;;; Sync minimap with modes which create/delete overlays.
"Synchronize overlays between base and minimap buffer.
Apply semantic overlays or face enlargement if necessary."
(interactive)
- (when minimap-bufname
- (let ((baseov (overlays-in (point-min) (point-max)))
- (semantic (and (boundp 'semantic-version)
- (semantic-active-p)))
- ov props p)
- (with-current-buffer minimap-bufname
- (remove-overlays)
- (while baseov
- (when (setq props (minimap-get-sync-properties (car baseov)))
- (setq ov (make-overlay (overlay-start (car baseov))
- (overlay-end (car baseov))))
- (while (setq p (car props))
- (overlay-put ov (car p) (cadr p))
- (setq props (cdr props))))
- (setq baseov (cdr baseov)))
- (move-overlay minimap-pointmin-overlay (point-min) (1+ (point-min)))
- ;; Re-apply font overlay
- (move-overlay minimap-base-overlay (point-min) (point-max)))
- ;; Face enlargement
- (when (and font-lock-mode
- (or (eq minimap-enlarge-certain-faces 'always)
- (and (eq minimap-enlarge-certain-faces 'as-fallback)
- (or (not minimap-display-semantic-overlays)
- (not semantic)))))
- (when (eq font-lock-support-mode 'jit-lock-mode)
- (jit-lock-fontify-now))
- (with-current-buffer minimap-bufname
- (minimap-enlarge-faces)))
- ;; Semantic overlays
- (when (and semantic
- minimap-display-semantic-overlays)
- (minimap-apply-semantic-overlays)))
- (minimap-update t)))
+ ;; Get overlays and Semantic status from base buffer.
+ (when (and minimap-mode
+ (minimap-active-current-buffer-p))
+ (with-current-buffer minimap-active-buffer
+ (let ((baseov (overlays-in (point-min) (point-max)))
+ (semantic (and (boundp 'semantic-version)
+ (semantic-active-p)))
+ ov props p)
+ ;; Apply overlays to minimap.
+ (with-current-buffer minimap-buffer-name
+ ;; Delete overlays (but keep our own).
+ (let ((ovs (overlays-in (point-min) (point-max))))
+ (dolist (ov ovs)
+ (unless (member ov (list minimap-pointmin-overlay
+ minimap-base-overlay
+ minimap-active-overlay))
+ (delete-overlay ov))))
+ (while baseov
+ (when (and (eq (overlay-buffer (car baseov)) minimap-active-buffer)
+ (setq props (minimap-get-sync-properties (car baseov))))
+ (setq ov (make-overlay (overlay-start (car baseov))
+ (overlay-end (car baseov))))
+ (while (setq p (car props))
+ (overlay-put ov (car p) (cadr p))
+ (setq props (cdr props))))
+ (setq baseov (cdr baseov)))
+ (move-overlay minimap-pointmin-overlay (point-min) (1+ (point-min)))
+ ;; Re-apply font overlay
+ (move-overlay minimap-base-overlay (point-min) (point-max)))
+ ;; Face enlargement
+ (when (and font-lock-mode
+ (or (eq minimap-enlarge-certain-faces 'always)
+ (and (eq minimap-enlarge-certain-faces 'as-fallback)
+ (or (not minimap-display-semantic-overlays)
+ (not semantic)))))
+ (when (eq font-lock-support-mode 'jit-lock-mode)
+ (jit-lock-fontify-now))
+ (minimap-enlarge-faces))
+ ;; Semantic overlays
+ (when (and semantic
+ minimap-display-semantic-overlays)
+ (minimap-apply-semantic-overlays t))))))
(defun minimap-get-sync-properties (ov)
"Get properties from overlay OV which should be synced.
minimap-sync-overlay-properties)))
(defun minimap-enlarge-faces ()
- "Apply default font to all faces in `minimap-normal-height-faces'.
-This has to be called in the minimap buffer."
+ "Apply default font to all faces in `minimap-normal-height-faces'."
(let ((pos (next-single-property-change (point-min) 'face))
next ov face)
(while pos
(setq face (get-text-property pos 'face))
- (when (delq nil (mapcar (lambda (x) (equal x face))
- minimap-normal-height-faces))
- (setq ov
- (make-overlay pos
- (setq pos (next-single-property-change pos 'face))))
- (overlay-put ov 'face `(:family ,(face-font 'default)))
- (overlay-put ov 'priority 5))
+ (when (and face
+ (member face minimap-normal-height-faces))
+ (with-current-buffer minimap-buffer-name
+ (setq ov
+ (make-overlay pos
+ (setq pos (next-single-property-change pos 'face))))
+ (overlay-put ov 'face `(:family ,(face-font 'default)))
+ (overlay-put ov 'priority 5)))
(setq pos (next-single-property-change pos 'face)))))
-(defun minimap-apply-semantic-overlays ()
+(defun minimap-apply-semantic-overlays (tags)
"Apply semantic overlays to the minimap.
-This has to be called from the base buffer."
- (let ((tags (semantic-fetch-tags))
- tag class ov ovnew)
- (while tags
- (setq tag (car tags))
- (setq class (semantic-tag-class tag))
- (setq ov (semantic-tag-overlay tag))
- (when (and (overlayp ov)
- (or (eq class 'function)
- (eq class 'type)
- (eq class 'variable)))
- (with-current-buffer minimap-bufname
- (let ((start (overlay-start ov))
- (end (overlay-end ov))
- (name (semantic-tag-name tag)))
- (overlay-put
- (setq ovnew (make-overlay start end))
- 'face `(:background ,(face-background
- (intern (format "minimap-semantic-%s-face"
- (symbol-name class))))))
- (overlay-put ovnew 'priority 1)
- (setq start
- (minimap-line-to-pos (/ (+ (line-number-at-pos start)
- (line-number-at-pos end)) 2)))
- (setq end (progn (goto-char start) (point-at-eol)))
- (setq ovnew (make-overlay start end))
- (overlay-put ovnew 'face (format "minimap-semantic-%s-face"
- (symbol-name class)))
- (overlay-put ovnew 'display (concat " " name " "))
- (overlay-put ovnew 'priority 6))))
- (setq tags (cdr tags)))))
-
-;; outline-(minor-)mode
-(add-hook 'outline-view-change-hook 'minimap-sync-overlays)
-
-;; hideshow
-(add-hook 'hs-hide-hook 'minimap-sync-overlays)
-(add-hook 'hs-show-hook 'minimap-sync-overlays)
+TAGS is the list of tags. If it is t, fetch tags from buffer."
+ (when (and tags
+ minimap-mode)
+ (with-current-buffer minimap-active-buffer
+ (let (tag class ov ovnew)
+ (when (eq tags t)
+ (setq tags (semantic-fetch-tags)))
+ (while tags
+ (setq tag (car tags))
+ (setq class (semantic-tag-class tag))
+ (setq ov (semantic-tag-overlay tag))
+ (when (and (overlayp ov)
+ (or (eq class 'function)
+ (eq class 'type)
+ (eq class 'variable)))
+ (with-current-buffer minimap-buffer-name
+ (let ((start (overlay-start ov))
+ (end (overlay-end ov))
+ (name (semantic-tag-name tag)))
+ ;; First, remove old Semantic overlays.
+ (remove-overlays start end 'minimap-semantic t)
+ ;; Now put the new ones.
+ (overlay-put
+ (setq ovnew (make-overlay start end))
+ 'face `(:background ,(face-background
+ (intern (format "minimap-semantic-%s-face"
+ (symbol-name class))))))
+ (overlay-put ovnew 'priority 1)
+ (overlay-put ovnew 'minimap-semantic t)
+ (setq start
+ (minimap-line-to-pos (/ (+ (line-number-at-pos start)
+ (line-number-at-pos end)) 2)))
+ (goto-char start)
+ (while (looking-at "^$")
+ (forward-line -1))
+ (setq start (point))
+ (setq end (progn (goto-char start) (point-at-eol)))
+ (setq ovnew (make-overlay start end))
+ (overlay-put ovnew 'face (format "minimap-semantic-%s-face"
+ (symbol-name class)))
+ (overlay-put ovnew 'display (concat " " name " "))
+ (overlay-put ovnew 'priority 6)
+ (overlay-put ovnew 'minimap-semantic t))))
+ (setq tags (cdr tags)))))))
(provide 'minimap)