Klimi's new dotfiles with stow.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

617 行
22 KiB

  1. ;;; powerline.el --- Rewrite of Powerline
  2. ;; Copyright (C) 2012-2013 Donald Ephraim Curtis
  3. ;; Copyright (C) 2013 Jason Milkins
  4. ;; Copyright (C) 2012 Nicolas Rougier
  5. ;; Author: Donald Ephraim Curtis <dcurtis@milkbox.net>
  6. ;; URL: http://github.com/milkypostman/powerline/
  7. ;; Version: 2.4
  8. ;; Keywords: mode-line
  9. ;; Package-Requires: ((cl-lib "0.2"))
  10. ;; This file is free software; you can redistribute it and/or modify
  11. ;; it under the terms of the GNU General Public License as published by
  12. ;; the Free Software Foundation; either version 3, or (at your option)
  13. ;; any later version.
  14. ;; This file is distributed in the hope that it will be useful,
  15. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;; GNU General Public License for more details.
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. ;;; Commentary:
  21. ;;
  22. ;; Powerline is a library for customizing the mode-line that is based on the Vim
  23. ;; Powerline. A collection of predefined themes comes with the package.
  24. ;;
  25. ;;; Code:
  26. (eval-and-compile (require 'powerline-themes))
  27. (eval-and-compile (require 'powerline-separators))
  28. (require 'cl-lib)
  29. (defgroup powerline nil
  30. "Powerline, a prettier mode line."
  31. :group 'mode-line)
  32. (defface powerline-active0 '((t (:inherit mode-line)))
  33. "Powerline face 0."
  34. :group 'powerline)
  35. (defface powerline-active1 '((t (:background "grey17" :foreground "white" :inherit mode-line)))
  36. "Powerline face 1."
  37. :group 'powerline)
  38. (defface powerline-active2 '((t (:background "grey40" :foreground "white" :inherit mode-line)))
  39. "Powerline face 2."
  40. :group 'powerline)
  41. (defface powerline-inactive0
  42. '((t (:inherit mode-line-inactive)))
  43. "Powerline face 0."
  44. :group 'powerline)
  45. (defface powerline-inactive1
  46. '((t (:background "grey11" :inherit mode-line-inactive)))
  47. "Powerline face 1."
  48. :group 'powerline)
  49. (defface powerline-inactive2
  50. '((t (:background "grey20" :inherit mode-line-inactive)))
  51. "Powerline face 2."
  52. :group 'powerline)
  53. (defface mode-line-buffer-id-inactive
  54. '((t (:inherit mode-line-buffer-id)))
  55. "Powerline mode-line face"
  56. :group 'powerline)
  57. (defcustom powerline-default-separator 'arrow
  58. "The separator to use for the default theme.
  59. Valid Values: alternate, arrow, arrow-fade, bar, box, brace,
  60. butt, chamfer, contour, curve, rounded, roundstub, wave, zigzag,
  61. utf-8."
  62. :group 'powerline
  63. :type '(choice (const alternate)
  64. (const arrow)
  65. (const arrow-fade)
  66. (const bar)
  67. (const box)
  68. (const brace)
  69. (const butt)
  70. (const chamfer)
  71. (const contour)
  72. (const curve)
  73. (const rounded)
  74. (const roundstub)
  75. (const slant)
  76. (const wave)
  77. (const zigzag)
  78. (const utf-8)
  79. (const nil)))
  80. (defcustom powerline-utf-8-separator-left #xe0b0
  81. "The unicode character number for the left facing separator"
  82. :group 'powerline
  83. :type '(choice integer (const nil)))
  84. (defcustom powerline-utf-8-separator-right #xe0b2
  85. "The unicode character number for the right facing separator"
  86. :group 'powerline
  87. :type '(choice integer (const nil)))
  88. (defcustom powerline-default-separator-dir '(left . right)
  89. "The separator direction to use for the default theme.
  90. CONS of the form (DIR . DIR) denoting the lean of the
  91. separators for the left and right side of the powerline.
  92. DIR must be one of: left, right"
  93. :group 'powerline
  94. :type '(cons (choice :tag "Left Hand Side" (const left) (const right))
  95. (choice :tag "Right Hand Side" (const left) (const right))))
  96. (defcustom powerline-height nil
  97. "Override the mode-line height."
  98. :group 'powerline
  99. :type '(choice integer (const nil)))
  100. (defcustom powerline-text-scale-factor nil
  101. "Scale of mode-line font size to default text size.
  102. Smaller mode-line fonts will be a float value less that 1.
  103. Larger mode-line fonts require a float value greater than 1.
  104. This is needed to make sure that text is properly aligned."
  105. :group 'powerline
  106. :type '(choice float integer (const nil)))
  107. (defcustom powerline-buffer-size-suffix t
  108. "Display the buffer size suffix."
  109. :group 'powerline
  110. :type 'boolean)
  111. (defcustom powerline-gui-use-vcs-glyph nil
  112. "Display a unicode character to represent a version control system. Not always supported in GUI."
  113. :group 'powerline
  114. :type 'boolean)
  115. (defcustom powerline-narrowed-indicator "Narrow"
  116. "A string to display in the mode-line when the buffer is narrowed."
  117. :group 'powerline
  118. :type 'string)
  119. (defun pl/create-or-get-cache ()
  120. "Return a frame-local hash table that acts as a memoization cache for powerline. Create one if the frame doesn't have one yet."
  121. (let ((table (frame-parameter nil 'powerline-cache)))
  122. (if (hash-table-p table) table (pl/reset-cache))))
  123. (defun pl/reset-cache ()
  124. "Reset and return the frame-local hash table used for a memoization cache."
  125. (let ((table (make-hash-table :test 'equal)))
  126. ;; Store it as a frame-local variable
  127. (modify-frame-parameters nil `((powerline-cache . ,table)))
  128. table))
  129. (defun powerline-current-separator ()
  130. "Get the current default separator. Always returns utf-8 in non-gui mode."
  131. (if window-system
  132. powerline-default-separator
  133. 'utf-8))
  134. ;;
  135. ;; the frame-local powerline cache causes problems if included in a saved desktop,
  136. ;; so delete it before the desktop is saved.
  137. ;;
  138. ;; see https://github.com/milkypostman/powerline/issues/58
  139. ;;
  140. ;; It is better to put the following code into your init file for Emacs 24.4 or later.
  141. ;; (require 'frameset)
  142. ;; (push '(powerline-cache . :never) frameset-filter-alist)
  143. ;;
  144. (defun powerline-delete-cache (&optional frame)
  145. "Set the FRAME cache to nil."
  146. (set-frame-parameter frame 'powerline-cache nil))
  147. (defun powerline-desktop-save-delete-cache ()
  148. "Set all caches to nil unless `frameset-filter-alist' has :never for powerline-cache."
  149. (unless (and (boundp 'frameset-filter-alist)
  150. (eq (cdr (assq 'powerline-cache frameset-filter-alist))
  151. :never))
  152. (dolist (fr (frame-list)) (powerline-delete-cache fr))))
  153. (add-hook 'desktop-save-hook 'powerline-desktop-save-delete-cache)
  154. ;; from memoize.el @ http://nullprogram.com/blog/2010/07/26/
  155. (defun pl/memoize (func)
  156. "Memoize FUNC.
  157. If argument is a symbol then install the memoized function over
  158. the original function. Use frame-local memoization."
  159. (cl-typecase func
  160. (symbol (fset func (pl/memoize-wrap-frame-local (symbol-function func))) func)
  161. (function (pl/memoize-wrap-frame-local func))))
  162. (defun pl/memoize-wrap-frame-local (func)
  163. "Return the memoized version of FUNC.
  164. The memoization cache is frame-local."
  165. (let ((funcid (cl-gensym)))
  166. `(lambda (&rest args)
  167. ,(concat (documentation func) (format "\n(memoized function %s)" funcid))
  168. (let* ((cache (pl/create-or-get-cache))
  169. (key (cons ',funcid args))
  170. (val (gethash key cache)))
  171. (if val
  172. val
  173. (puthash key (apply ,func args) cache))))))
  174. (defun pl/separator-height ()
  175. "Get default height for rendering separators."
  176. (or powerline-height (frame-char-height)))
  177. (defun powerline-reset ()
  178. "Reset memoized functions."
  179. (interactive)
  180. (pl/memoize (pl/alternate left))
  181. (pl/memoize (pl/alternate right))
  182. (pl/memoize (pl/arrow left))
  183. (pl/memoize (pl/arrow right))
  184. (pl/memoize (pl/arrow-fade left))
  185. (pl/memoize (pl/arrow-fade right))
  186. (pl/memoize (pl/bar left))
  187. (pl/memoize (pl/bar right))
  188. (pl/memoize (pl/box left))
  189. (pl/memoize (pl/box right))
  190. (pl/memoize (pl/brace left))
  191. (pl/memoize (pl/brace right))
  192. (pl/memoize (pl/butt left))
  193. (pl/memoize (pl/butt right))
  194. (pl/memoize (pl/chamfer left))
  195. (pl/memoize (pl/chamfer right))
  196. (pl/memoize (pl/contour left))
  197. (pl/memoize (pl/contour right))
  198. (pl/memoize (pl/curve left))
  199. (pl/memoize (pl/curve right))
  200. (pl/memoize (pl/rounded left))
  201. (pl/memoize (pl/rounded right))
  202. (pl/memoize (pl/roundstub left))
  203. (pl/memoize (pl/roundstub right))
  204. (pl/memoize (pl/slant left))
  205. (pl/memoize (pl/slant right))
  206. (pl/memoize (pl/wave left))
  207. (pl/memoize (pl/wave right))
  208. (pl/memoize (pl/zigzag left))
  209. (pl/memoize (pl/zigzag right))
  210. (pl/memoize (pl/nil left))
  211. (pl/memoize (pl/nil right))
  212. (pl/utf-8 left)
  213. (pl/utf-8 right)
  214. (pl/reset-cache))
  215. (powerline-reset)
  216. (defun pl/make-xpm (name color1 color2 data)
  217. "Return an XPM image with NAME using COLOR1 for enabled and COLOR2 for disabled bits specified in DATA."
  218. (when window-system
  219. (create-image
  220. (concat
  221. (format "/* XPM */
  222. static char * %s[] = {
  223. \"%i %i 2 1\",
  224. \". c %s\",
  225. \" c %s\",
  226. "
  227. (downcase (replace-regexp-in-string " " "_" name))
  228. (length (car data))
  229. (length data)
  230. (or (pl/hex-color color1) "None")
  231. (or (pl/hex-color color2) "None"))
  232. (let ((len (length data))
  233. (idx 0))
  234. (apply 'concat
  235. (mapcar #'(lambda (dl)
  236. (setq idx (+ idx 1))
  237. (concat
  238. "\""
  239. (concat
  240. (mapcar #'(lambda (d)
  241. (if (eq d 0)
  242. (string-to-char " ")
  243. (string-to-char ".")))
  244. dl))
  245. (if (eq idx len)
  246. "\"};"
  247. "\",\n")))
  248. data))))
  249. 'xpm t :ascent 'center)))
  250. (defun pl/percent-xpm
  251. (height pmax pmin winend winstart width color1 color2)
  252. "Generate percentage xpm of HEIGHT for PMAX to PMIN given WINEND and WINSTART with WIDTH and COLOR1 and COLOR2."
  253. (let* ((height- (1- height))
  254. (fillstart (round (* height- (/ (float winstart) (float pmax)))))
  255. (fillend (round (* height- (/ (float winend) (float pmax)))))
  256. (data nil)
  257. (i 0))
  258. (while (< i height)
  259. (setq data (cons
  260. (if (and (<= fillstart i)
  261. (<= i fillend))
  262. (append (make-list width 1))
  263. (append (make-list width 0)))
  264. data))
  265. (setq i (+ i 1)))
  266. (pl/make-xpm "percent" color1 color2 (reverse data))))
  267. (pl/memoize 'pl/percent-xpm)
  268. ;;;###autoload
  269. (defun powerline-hud (face1 face2 &optional width)
  270. "Return an XPM of relative buffer location using FACE1 and FACE2 of optional WIDTH."
  271. (unless width (setq width 2))
  272. (let ((color1 (if face1 (face-background face1) "None"))
  273. (color2 (if face2 (face-background face2) "None"))
  274. (height (or powerline-height (frame-char-height)))
  275. pmax
  276. pmin
  277. (ws (window-start))
  278. (we (window-end)))
  279. (save-restriction
  280. (widen)
  281. (setq pmax (point-max))
  282. (setq pmin (point-min)))
  283. (pl/percent-xpm height pmax pmin we ws
  284. (* (frame-char-width) width) color1 color2)))
  285. ;;;###autoload
  286. (defun powerline-mouse (click-group click-type string)
  287. "Return mouse handler for CLICK-GROUP given CLICK-TYPE and STRING."
  288. (cond ((eq click-group 'minor)
  289. (cond ((eq click-type 'menu)
  290. `(lambda (event)
  291. (interactive "@e")
  292. (minor-mode-menu-from-indicator ,string)))
  293. ((eq click-type 'help)
  294. `(lambda (event)
  295. (interactive "@e")
  296. (describe-minor-mode-from-indicator ,string)))
  297. (t
  298. `(lambda (event)
  299. (interactive "@e")
  300. nil))))
  301. (t
  302. `(lambda (event)
  303. (interactive "@e")
  304. nil))))
  305. ;;;###autoload
  306. (defun powerline-concat (&rest strings)
  307. "Concatonate STRINGS and pad sides by spaces."
  308. (concat
  309. " "
  310. (mapconcat 'identity (delq nil strings) " ")
  311. " "))
  312. ;;;###autoload
  313. (defmacro defpowerline (name body)
  314. "Create function NAME by wrapping BODY with powerline padding an propetization."
  315. `(defun ,name
  316. (&optional face pad)
  317. (powerline-raw ,body face pad)))
  318. (defun pl/property-substrings (str prop)
  319. "Return a list of substrings of STR when PROP change."
  320. (let ((beg 0) (end 0)
  321. (len (length str))
  322. (out))
  323. (while (< end (length str))
  324. (setq end (or (next-single-property-change beg prop str) len))
  325. (setq out (append out (list (substring str beg (setq beg end))))))
  326. out))
  327. (defun pl/assure-list (item)
  328. "Assure that ITEM is a list."
  329. (if (listp item)
  330. item
  331. (list item)))
  332. (defun pl/add-text-property (str prop val)
  333. (mapconcat
  334. (lambda (mm)
  335. (let ((cur (pl/assure-list (get-text-property 0 'face mm))))
  336. (propertize mm 'face (append cur (list val)))))
  337. (pl/property-substrings str prop)
  338. ""))
  339. ;;;###autoload
  340. (defun powerline-raw (str &optional face pad)
  341. "Render STR as mode-line data using FACE and optionally PAD import on left (l) or right (r)."
  342. (when str
  343. (let* ((rendered-str (format-mode-line str))
  344. (padded-str (concat
  345. (when (and (> (length rendered-str) 0) (eq pad 'l)) " ")
  346. (if (listp str) rendered-str str)
  347. (when (and (> (length rendered-str) 0) (eq pad 'r)) " "))))
  348. (if face
  349. (pl/add-text-property padded-str 'face face)
  350. padded-str))))
  351. ;;;###autoload
  352. (defun powerline-fill (face reserve)
  353. "Return empty space using FACE and leaving RESERVE space on the right."
  354. (unless reserve
  355. (setq reserve 20))
  356. (when powerline-text-scale-factor
  357. (setq reserve (* powerline-text-scale-factor reserve)))
  358. (when (and window-system (eq 'right (get-scroll-bar-mode)))
  359. (setq reserve (- reserve 3)))
  360. (propertize " "
  361. 'display `((space :align-to (- (+ right right-fringe right-margin) ,reserve)))
  362. 'face face))
  363. (defun powerline-fill-center (face reserve)
  364. "Return empty space using FACE to the center of remaining space leaving RESERVE space on the right."
  365. (unless reserve
  366. (setq reserve 20))
  367. (when powerline-text-scale-factor
  368. (setq reserve (* powerline-text-scale-factor reserve)))
  369. (propertize " "
  370. 'display `((space :align-to (- (+ center (.5 . right-margin)) ,reserve
  371. (.5 . left-margin))))
  372. 'face face))
  373. ;;;###autoload (autoload 'powerline-major-mode "powerline")
  374. (defpowerline powerline-major-mode
  375. (propertize (format-mode-line mode-name)
  376. 'mouse-face 'mode-line-highlight
  377. 'help-echo "Major mode\n\ mouse-1: Display major mode menu\n\ mouse-2: Show help for major mode\n\ mouse-3: Toggle minor modes"
  378. 'local-map (let ((map (make-sparse-keymap)))
  379. (define-key map [mode-line down-mouse-1]
  380. `(menu-item ,(purecopy "Menu Bar") ignore
  381. :filter (lambda (_) (mouse-menu-major-mode-map))))
  382. (define-key map [mode-line mouse-2] 'describe-mode)
  383. (define-key map [mode-line down-mouse-3] mode-line-mode-menu)
  384. map)))
  385. ;;;###autoload (autoload 'powerline-minor-modes "powerline")
  386. (defpowerline powerline-minor-modes
  387. (mapconcat (lambda (mm)
  388. (propertize mm
  389. 'mouse-face 'mode-line-highlight
  390. 'help-echo "Minor mode\n mouse-1: Display minor mode menu\n mouse-2: Show help for minor mode\n mouse-3: Toggle minor modes"
  391. 'local-map (let ((map (make-sparse-keymap)))
  392. (define-key map
  393. [mode-line down-mouse-1]
  394. (powerline-mouse 'minor 'menu mm))
  395. (define-key map
  396. [mode-line mouse-2]
  397. (powerline-mouse 'minor 'help mm))
  398. (define-key map
  399. [mode-line down-mouse-3]
  400. (powerline-mouse 'minor 'menu mm))
  401. (define-key map
  402. [header-line down-mouse-3]
  403. (powerline-mouse 'minor 'menu mm))
  404. map)))
  405. (split-string (format-mode-line minor-mode-alist))
  406. (propertize " " 'face face)))
  407. ;;;###autoload (autoload 'powerline-narrow "powerline")
  408. (defpowerline powerline-narrow
  409. (when ;; (buffer-narrowed-p) introduced in Emacs 24.3.
  410. (/= (- (point-max) (point-min)) (buffer-size))
  411. (propertize powerline-narrowed-indicator
  412. 'mouse-face 'mode-line-highlight
  413. 'help-echo "mouse-1: Remove narrowing from the current buffer"
  414. 'local-map (make-mode-line-mouse-map
  415. 'mouse-1 'mode-line-widen))))
  416. ;;;###autoload (autoload 'powerline-vc "powerline")
  417. (defpowerline powerline-vc
  418. (when (and (buffer-file-name (current-buffer)) vc-mode)
  419. (if (and window-system (not powerline-gui-use-vcs-glyph))
  420. (format-mode-line '(vc-mode vc-mode))
  421. (format " %s%s"
  422. (char-to-string #xe0a0)
  423. (format-mode-line '(vc-mode vc-mode))))))
  424. ;;;###autoload (autoload 'powerline-encoding "powerline")
  425. (defpowerline powerline-encoding
  426. (let ((buf-coding (format "%s" buffer-file-coding-system)))
  427. (if (string-match "\\(dos\\|unix\\|mac\\)" buf-coding)
  428. (match-string 1 buf-coding)
  429. buf-coding)))
  430. ;;;###autoload (autoload 'powerline-buffer-size "powerline")
  431. (defpowerline powerline-buffer-size
  432. (propertize
  433. (if powerline-buffer-size-suffix
  434. "%I"
  435. "%i")
  436. 'mouse-face 'mode-line-highlight
  437. 'local-map (make-mode-line-mouse-map
  438. 'mouse-1 (lambda () (interactive)
  439. (setq powerline-buffer-size-suffix
  440. (not powerline-buffer-size-suffix))
  441. (force-mode-line-update)))))
  442. ;;;###autoload (autoload 'powerline-buffer-id "powerline")
  443. (defun powerline-buffer-id (&optional face pad)
  444. (powerline-raw
  445. (format-mode-line
  446. (concat " " (propertize
  447. (format-mode-line mode-line-buffer-identification)
  448. 'face face
  449. 'mouse-face 'mode-line-highlight
  450. 'help-echo "Buffer name\n\ mouse-1: Previous buffer\n\ mouse-3: Next buffer"
  451. 'local-map (let ((map (make-sparse-keymap)))
  452. (define-key map [mode-line mouse-1] 'mode-line-previous-buffer)
  453. (define-key map [mode-line mouse-3] 'mode-line-next-buffer)
  454. map))))
  455. face pad))
  456. ;;;###autoload (autoload 'powerline-process "powerline")
  457. (defpowerline powerline-process
  458. (cond
  459. ((symbolp mode-line-process) (symbol-value mode-line-process))
  460. ((listp mode-line-process) (format-mode-line mode-line-process))
  461. (t mode-line-process)))
  462. (defvar pl/default-mode-line mode-line-format)
  463. (defvar pl/minibuffer-selected-window-list '())
  464. (defun pl/minibuffer-selected-window ()
  465. "Return the selected window when entereing the minibuffer."
  466. (when pl/minibuffer-selected-window-list
  467. (car pl/minibuffer-selected-window-list)))
  468. (defun pl/minibuffer-setup ()
  469. "Save the `minibuffer-selected-window' to `pl/minibuffer-selected-window'."
  470. (push (minibuffer-selected-window) pl/minibuffer-selected-window-list))
  471. (add-hook 'minibuffer-setup-hook 'pl/minibuffer-setup)
  472. (defun pl/minibuffer-exit ()
  473. "Set `pl/minibuffer-selected-window' to nil."
  474. (pop pl/minibuffer-selected-window-list))
  475. (add-hook 'minibuffer-exit-hook 'pl/minibuffer-exit)
  476. (defvar powerline-selected-window (frame-selected-window)
  477. "Selected window.")
  478. (defun powerline-set-selected-window ()
  479. "Set the variable `powerline-selected-window' appropriately."
  480. (when (not (minibuffer-window-active-p (frame-selected-window)))
  481. (setq powerline-selected-window (frame-selected-window))
  482. (force-mode-line-update)))
  483. (defun powerline-unset-selected-window ()
  484. "Unset the variable `powerline-selected-window' and update the mode line."
  485. (setq powerline-selected-window nil)
  486. (force-mode-line-update))
  487. (add-hook 'window-configuration-change-hook 'powerline-set-selected-window)
  488. ;; focus-in-hook was introduced in emacs v24.4.
  489. ;; Gets evaluated in the last frame's environment.
  490. (add-hook 'focus-in-hook 'powerline-set-selected-window)
  491. ;; focus-out-hook was introduced in emacs v24.4.
  492. (add-hook 'focus-out-hook 'powerline-unset-selected-window)
  493. ;; Executes after the window manager requests that the user's events
  494. ;; be directed to a different frame.
  495. (defadvice handle-switch-frame (after powerline-handle-switch-frame activate)
  496. "Call `powerline-set-selected-window'."
  497. (powerline-set-selected-window))
  498. (add-hook 'buffer-list-update-hook #'powerline-set-selected-window)
  499. ;;;###autoload (autoload 'powerline-selected-window-active "powerline")
  500. (defun powerline-selected-window-active ()
  501. "Return whether the current window is active."
  502. (eq powerline-selected-window (selected-window)))
  503. (defun powerline-revert ()
  504. "Revert to the default Emacs mode-line."
  505. (interactive)
  506. (setq-default mode-line-format pl/default-mode-line))
  507. (defun pl/render (item)
  508. "Render a powerline ITEM."
  509. (cond
  510. ((and (listp item) (eq 'image (car item)))
  511. (propertize " " 'display item
  512. 'face (plist-get (cdr item) :face)))
  513. (item item)))
  514. (defun powerline-render (values)
  515. "Render a list of powerline VALUES."
  516. (mapconcat 'pl/render values ""))
  517. (defun powerline-width (values)
  518. "Get the length of VALUES."
  519. (if values
  520. (let ((val (car values)))
  521. (+ (cond
  522. ((stringp val) (string-width (format-mode-line val)))
  523. ((and (listp val) (eq 'image (car val)))
  524. (car (image-size val)))
  525. (t 0))
  526. (powerline-width (cdr values))))
  527. 0))
  528. (provide 'powerline)
  529. ;;; powerline.el ends here