;;; feebleline.el --- Replace modeline with a slimmer proxy ;; Copyright 2018 Benjamin Lindqvist ;; Author: Benjamin Lindqvist ;; Maintainer: Benjamin Lindqvist ;; URL: https://github.com/tautologyclub/feebleline ;; Package-Version: 1.1 ;; Version: 1.1 ;; This file is not part of GNU Emacs. ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; For hardline Luddite editing! ;; Feebleline removes the modeline and replaces it with a slimmer proxy ;; version, which displays some basic information in the echo area ;; instead. This information is only displayed if the echo area is not used ;; for anything else (but if you switch frame/window, it will replace whatever ;; message is currently displayed). ;; To customize feebleline's format, modify `feebleline-mode-line-text'. ;; NOTE: ;; feebleline.el will look considerably better with the following ;; settings: ;; (window-divider-mode t) ;; (setq window-divider-default-bottom-width 1) ;; (setq window-divider-default-places (quote bottom-only)) ;; But this mode does not work for all EMACS versions and may not work with ;; terminal EMACS (but I haven't checked). If you're on GUI EMACS and your ;; version supports it, just place the following in your init file: ;; (feebleline-default-settings) ;; Otherwise, do (feebleline-mode t) instead, but be warned that I'm not sure ;; if it will look good. ;;; Code: (require 'advice) (defvar feebleline-use-legacy-settings nil) (when (< emacs-major-version 25) (setq feebleline-use-legacy-settings t)) (defface feebleline-time-face '((t :inherit 'font-lock-comment-face)) "Feebleline timestamp face." :group 'feebleline) (defface feebleline-linum-face '((t :inherit 'default)) "Feebleline linum face." :group 'feebleline) (defface feebleline-bufname-face '((t :inherit 'font-lock-function-name-face)) "Feebleline buffer name face." :group 'feebleline) (defface feebleline-asterisk-face '((t :foreground "salmon")) "Feebleline file modified asterisk face." :group 'feebleline) (defface feebleline-previous-buffer-face '((t :foreground "#7e7e7e")) "Feebleline prev buffer face." :group 'feebleline) (defface feebleline-dir-face '((t :inherit 'font-lock-variable-name-face)) "Feebleline direcory face." :group 'feebleline) (defface feebleline-git-branch-face '((t :inherit 'font-lock-comment-face :bold nil :italic t)) "Feebleline git branch face." :group 'feebleline) ;; Customizations (defcustom feebleline-show-time nil "Set this if you want to show the time in the modeline. Note: Toggling feebleline-mode is necessary for changes to take effect." :group 'feebleline) (defcustom feebleline-show-git-branch nil "Set this if you want to show the git branch in the modeline. Note: Toggling feebleline-mode is necessary for changes to take effect." :group 'feebleline) (defcustom feebleline-show-previous-buffer nil "Set this if you want to show the previous 'buffer-name' in the modeline. Note: Toggling feebleline-mode is necessary for changes to take effect." :group 'feebleline) (defcustom feebleline-show-directory t "Set this if you want to show the direcory path in the modeline. Note: Toggling feebleline-mode is necessary for changes to take effect." :group 'feebleline) (defun feebleline-previous-buffer-name () "Get name of previous buffer." (buffer-name (other-buffer (current-buffer) 1))) (defvar feebleline-mode-line-text '(("%s" ((feebleline-time-fn)) (face feebleline-time-face)) ("%6s" ((feebleline-linum-fn)) (face feebleline-linum-face)) (" %s" ((feebleline-dir-fn)) (face feebleline-dir-face)) ("%s" ((feebleline-bufname-fn)) (face feebleline-bufname-face)) ("%s" ((feebleline-buf-modified-fn)) (face feebleline-asterisk-face)) ("%s" ((feebleline-git-branch-fn)) (face feebleline-git-branch-face)) ("%s" ((feebleline-previous-buf-fn)) (face feebleline-previous-buffer-face))) "Each element is a list with the following format: (FORMAT-STRING FORMAT-ARGS PROPS) FORMAT-STRING will be used as the first argument to `format', and FORMAT-ARGS (a list) will be expanded as the rest of `format' arguments. If PROPS is given, it should be a list which will be sent to `add-text-properties'.") (defun feebleline--git-branch-string () "Return current git branch as a string, or the empty string if pwd is not in a git repo (or the git command is not found)." (interactive) (require 'esh-ext) (when (and (eshell-search-path "git") (locate-dominating-file default-directory ".git")) (let ((git-output (shell-command-to-string (concat "cd " default-directory " && git branch | grep '\\*' | sed -e 's/^\\* //'")))) (if (> (length git-output) 0) (concat " : " (substring git-output 0 -1)) "(no branch)")))) (defvar feebleline--home-dir nil) (defun feebleline-buf-modified-fn () "Return asterisk if buffer is a file and it was modified." (if (and (buffer-file-name) (buffer-modified-p)) "*" "")) (defun feebleline-bufname-fn () "Return name of buffer." (buffer-name)) (defun feebleline-linum-fn () "Return linum:colnum." (format "%s:%s" (format-mode-line "%l") (current-column))) (defun feebleline-previous-buf-fn () "Return name of previous buffer." (concat " | " (feebleline-previous-buffer-name))) (defun feebleline-dir-fn () "Return linum:colnum." (if (buffer-file-name) (replace-regexp-in-string feebleline--home-dir "~" (file-name-directory (buffer-file-name))) "")) (defun feebleline-time-fn () "Return timestamp." (format-time-string "[%H:%M:%S] ")) (defun feebleline-git-branch-fn () "Show git branch." (feebleline--git-branch-string)) (defun feebleline-default-settings-on () "Some default settings that works well with feebleline." (setq window-divider-default-bottom-width 1 window-divider-default-places (quote bottom-only)) (window-divider-mode t) (setq-default mode-line-format nil)) (defun feebleline-legacy-settings-on () "Some default settings for EMACS < 25." (set-face-attribute 'mode-line nil :height 0.1)) (defvar feebleline--timer) (defvar feebleline--mode-line-format-previous) ;;;###autoload (define-minor-mode feebleline-mode "Replace modeline with a slimmer proxy." :require 'feebleline :global t (if feebleline-mode ;; Activation: (progn (setq feebleline--home-dir (expand-file-name "~")) (setq feebleline--mode-line-format-previous mode-line-format) (setq feebleline--timer (run-with-timer 0 0.5 'feebleline-mode-line-proxy-fn)) (if feebleline-use-legacy-settings (feebleline-legacy-settings-on) (feebleline-default-settings-on)) (unless feebleline-show-time (defun feebleline-time-fn () "")) (unless feebleline-show-directory (defun feebleline-dir-fn () "")) (unless feebleline-show-git-branch (defun feebleline-git-branch-fn () "")) (unless feebleline-show-previous-buffer (defun feebleline-previous-buf-fn () "")) (ad-activate 'handle-switch-frame) (add-hook 'focus-in-hook 'feebleline-mode-line-proxy-fn)) ;; Deactivation: (set-face-attribute 'mode-line nil :height 1) (setq-default mode-line-format feebleline--mode-line-format-previous) (cancel-timer feebleline--timer) (ad-deactivate 'handle-switch-frame) (remove-hook 'focus-in-hook 'feebleline-mode-line-proxy-fn) (with-current-buffer " *Minibuf-0*" (erase-buffer)))) (defun feebleline--mode-line-part (part) "Return a PART (an element) of `feebleline-mode-line-text` as a propertized string." (let ((text (apply #'format (append (list (car part)) (mapcar #'eval (cadr part))))) (props (elt part 2))) (when props (add-text-properties 0 (length text) props text)) text)) (defun feebleline--message-maybe () "Replace echo-area message with mode-line proxy." (progn (let ((feebleline-placeholder (mapconcat #'feebleline--mode-line-part feebleline-mode-line-text ""))) (with-current-buffer " *Minibuf-0*" (erase-buffer) (insert feebleline-placeholder))))) (defun feebleline-mode-line-proxy-fn () "Put a mode-line proxy in the echo area *if* echo area is empty." (unless (current-message) (feebleline--message-maybe))) (defadvice handle-switch-frame (after switch-frame-message-name) "Get the modeline proxy to work with i3 switch focus." (feebleline--message-maybe) ad-do-it (feebleline--message-maybe)) (provide 'feebleline) ;;; feebleline.el ends here