From 23737a96faf98d0848c8228cca48104c2d113252 Mon Sep 17 00:00:00 2001 From: Carolyn Knight Date: Fri, 20 Dec 2019 13:03:43 -0800 Subject: [PATCH] We goin! --- init.el | 285 ++++++++++-------- lisp/ol-notmuch.el | 155 ++++++++++ lisp/sr-speedbar.el.1 | 651 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 972 insertions(+), 119 deletions(-) create mode 100755 lisp/ol-notmuch.el create mode 100755 lisp/sr-speedbar.el.1 diff --git a/init.el b/init.el index 2607e62..fa07d3f 100644 --- a/init.el +++ b/init.el @@ -5,11 +5,12 @@ ;; \/_/ \/_/ \/_/ \/_/ \/_/ \/_____/ \/_____/ -;;; Bad stuff +;;; BAD stuff (setq package-check-signature nil) ;;; Making the interface not terrible ;;; -(set-face-attribute 'default t :font "scientifica") +(add-to-list 'default-frame-alist '(font . "scientifica-11")) +(set-face-attribute 'default t :font "scientifica-11") (menu-bar-mode -1) @@ -79,18 +80,32 @@ (package-install 'use-package)) ; and install the most recent version of use-package (require 'use-package) ; guess what this one does too ? -(setq use-package-always-ensure t) ; autodownload plugins (use-package auto-package-update :config (setq auto-package-update-delete-old-versions t) (setq auto-package-update-hide-results t) (auto-package-update-maybe)) +;; straight.el +(defvar bootstrap-version) +(let ((bootstrap-file + (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) + (bootstrap-version 5)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously + "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" + 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) + +(setq straight-use-package-by-default t) +(setq straight-vc-git-default-protocol 'ssh) +(setq straight-check-for-modifications 'live) + ;;; Evil!! - ; evil-collection -(use-package evil-collection - :config (evil-collection-init)) ; General (use-package general @@ -125,6 +140,9 @@ (custom-set-faces '(line-number-current-line ((t :weight bold :foreground "white"))))) + ; evil-collection +(use-package evil-collection + :config (evil-collection-init)) ; evil-escape (use-package evil-escape :config @@ -149,8 +167,7 @@ (use-package powerthesaurus) -(use-package lsp-mode - :commands lsp) +(use-package lsp-mode) (use-package lsp-ui :commands lsp-ui-mode) (use-package company-lsp :commands company-lsp) (use-package helm-lsp :commands helm-lsp-workspace-symbol) @@ -294,8 +311,16 @@ ;;; Interface ;;theme -(add-to-list 'custom-theme-load-path "~/.emacs.d/themes") -(load-theme 'xresources t) +(use-package ewal-doom-themes + :straight (ewal-doom-themes + :host gitlab + :repo "jjzmajic/ewal" + :branch "develop" + :files ("doom-themes/*.el") + :depth full)) +(load-theme 'ewal-doom-one t) +(enable-theme 'ewal-doom-one) + (use-package multi-term :config @@ -345,9 +370,18 @@ ;; doom-modeline (use-package doom-modeline + :config + (setq doom-modeline-icon nil) + (if window-system (setq doom-modeline-unicode-fallback t)) + (setq doom-modeline-buffer-file-name-style 'truncate-upto-project) + (setq doom-modeline-major-mode-color-icon t) + (setq doom-modeline-continuous-word-count-modes '(markdown-mode gfm-mode org-mode)) + (setq doom-modeline-modal-icon t) + (setq doom-modeline-env-version t) + (setq inhibit-compacting-font-caches t) :hook (after-init . doom-modeline-mode)) (set-face-attribute 'mode-line nil - :box '(:line-width 3)) + :box '(:line-width 0)) ;; helm @@ -491,7 +525,7 @@ ;; enable in markdown, too (add-hook 'markdown-mode-hook 'toc-org-mode) - (define-key markdown-mode-map (kbd "\C-c\C-o") 'toc-org-markdown-follow-thing-at-point) +u (define-key markdown-mode-map (kbd "\C-c\C-o") 'toc-org-markdown-follow-thing-at-point) (warn "toc-org not found")) ;;; Emacs-lisp @@ -499,50 +533,50 @@ ;;; LaTeX -(use-package tex - :ensure auctex - :mode ("\\.tex\\'" . LaTeX-mode) - :interpreter ("tex" . LaTeX-mode) - :config - (setq TeX-save-query nil) - (add-hook 'LaTeX-mode-hook 'turn-on-auto-fill) - (setq TeX-source-correlate-mode t) - (setq LaTeX-item-indent 1) - (setq TeX-auto-save t) - (setq TeX-parse-self t) - (setq-default TeX-master nil) - (add-hook 'LaTeX-mode-hook 'visual-line-mode) - (add-hook 'LaTeX-mode-hook 'flyspell-mode) - (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode) - (add-hook 'LaTeX-mode-hook 'turn-on-reftex) - (add-hook 'LaTeX-mode-hook 'TeX-interactive-mode) - (add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode) - (setq TeX-view-program-selection '((output-pdf "Zathura"))) - (eval-after-load "tex" - '(progn - (add-to-list - 'TeX-engine-alist - '(default-shell-escape "Default with shell escape" - "pdftex -shell-escape" - "pdflatex -shell-escape" - ConTeXt-engine)))) - ;; (setq-default TeX-engine 'default-shell-escape) +;; (use-package tex +;; :straight auctex +;; :mode ("\\.tex\\'" . LaTeX-mode) +;; :interpreter ("tex" . LaTeX-mode) +;; :config +;; (setq TeX-save-query nil) +;; (add-hook 'LaTeX-mode-hook 'turn-on-auto-fill) +;; (setq TeX-source-correlate-mode t) +;; (setq LaTeX-item-indent 1) +;; (setq TeX-auto-save t) +;; (setq TeX-parse-self t) +;; (setq-default TeX-master nil) +;; (add-hook 'LaTeX-mode-hook 'visual-line-mode) +;; (add-hook 'LaTeX-mode-hook 'flyspell-mode) +;; (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode) +;; (add-hook 'LaTeX-mode-hook 'turn-on-reftex) +;; (add-hook 'LaTeX-mode-hook 'TeX-interactive-mode) +;; (add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode) +;; (setq TeX-view-program-selection '((output-pdf "Zathura"))) +;; (eval-after-load "tex" +;; '(progn +;; (add-to-list +;; 'TeX-engine-alist +;; '(default-shell-escape "Default with shell escape" +;; "pdftex -shell-escape" +;; "pdflatex -shell-escape" +;; ConTeXt-engine)))) +;; ;; (setq-default TeX-engine 'default-shell-escape) - (setq reftex-plug-into-AUCTeX t)) +;; (setq reftex-plug-into-AUCTeX t)) -(use-package company-auctex - :after tex - :config - (company-auctex-init)) +;; (use-package company-auctex +;; :after tex +;; :config +;; (company-auctex-init)) -(use-package company-math - :after tex - :config - (defun my-latex-mode-setup () - (setq-local company-backends - (append '((company-math-symbols-latex company-math-symbols-unicode company-latex-commands company-auctex)) - company-backends))) - (add-hook 'TeX-mode-hook 'my-latex-mode-setup)) +;; (use-package company-math +;; :after tex +;; :config +;; (defun my-latex-mode-setup () +;; (setq-local company-backends +;; (append '((company-math-symbols-latex company-math-symbols-unicode company-latex-commands company-auctex)) +;; company-backends))) +;; (add-hook 'TeX-mode-hook 'my-latex-mode-setup)) ;;; projects @@ -570,25 +604,47 @@ :commands gopher) -(require 'tls) -(use-package erc) -(require 'erc-nicklist) -(setq erc-autojoin-channels-alist - '(("freenode.net" "#emacs" "#erc" "##crawl" "#iww" "#clojure" "#rust" "#haskell" "#NetBSD" "#pkgsrc" "#go-nuts"))) -;; (erc-ssl :server "irc.freenode.net" :port 6697 :nick "gigavinyl") -;; (erc-ssl :server "irc.oftc.net" :port 6697 :nick "gigavinyl") -(erc :server "irc.indymedia.org" :port 6667 :nick "gigavinyl") +;; (use-package erc) +;; (require 'erc-nicklist) +;; (setq erc-autojoin-channels-alist +;; '(("freenode.net" "#emacs" "#erc" "##crawl" "#iww" "#clojure" "#rust" "#haskell" "#NetBSD" "#pkgsrc" "#go-nuts"))) +;; ;; (erc-ssl :server "irc.freenode.net" :port 6697 :nick "gigavinyl") +;; ;; (erc-ssl :server "irc.oftc.net" :port 6697 :nick "gigavinyl") +;; ;;(erc :server "irc.indymedia.org" :port 6667 :nick "gigavinyl") -(use-package erc-colorize) -(use-package ercn) -(use-package erc-status-sidebar) -(use-package erc-youtube) -(use-package erc-yt) -(use-package erc-social-graph) -(require 'erc-sasl) -(add-to-list 'erc-sasl-server-regexp-list "irc.freenode.net") +;; (use-package erc-colorize) +;; (use-package erc-status-sidebar) +;; (use-package erc-youtube) +;; (use-package erc-yt) +;; (use-package erc-social-graph) +;; (require 'erc-sasl) +;; (add-to-list 'erc-sasl-server-regexp-list "irc.freenode.net") +;; circe +(use-package circe + :general + (general-nmap + "i" 'circe)) +(setq auth-sources '("~/.authinfo.gpg")) +(defun my-fetch-password (&rest params) + (require 'auth-source) + (let ((match (car (apply 'auth-source-search params)))) + (if match + (let ((secret (plist-get match :secret))) + (if (functionp secret) + (funcall secret) + secret)) + (error "Password not found for %S" params)))) + +(defun my-nickserv-password (server) + (my-fetch-password :login "gigavinyl" :machine "irc.freenode.net")) + +(setq circe-network-options + '(("Freenode" + :nick "gigavinyl" + :channels (:after-auth "#emacs" "#emacs-circe" "##rust" "#clojure" "#iww" "#foodnotbombs" "#anarchism" "#NetBSD" "#pkgsrc") + :nickserv-password my-nickserv-password))) (use-package deadgrep @@ -640,7 +696,7 @@ systematically send encrypted emails when possible." (mml-secure-message-sign-encrypt))) (add-hook 'message-send-hook #'message-sign-encrypt-if-all-keys-available) -(require 'org-notmuch) +;(require 'ol-notmuch) (use-package helm-notmuch :general (general-nmap @@ -665,7 +721,6 @@ systematically send encrypted emails when possible." (require 'notmuch-address) (setq notmuch-address-command "/usr/local/bin/nottoomuch-addresses.sh") -(notmuch-address-message-insinuate) (setq notmuch-address-selection-function (lambda (prompt collection initial-input) @@ -744,11 +799,6 @@ systematically send encrypted emails when possible." (require 'sr-speedbar) -(use-package weechat) -(require 'weechat-notifications) -(require 'weechat-latex) -(require 'weechat-speedbar) - (use-package exec-path-from-shell @@ -777,7 +827,9 @@ systematically send encrypted emails when possible." :interpreter ("rust" . rustic)) (use-package flycheck-rust - :after rust-mode) +; :config (with-eval-after-load 'rustic (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)) + :after rustic) + (use-package racer :after rust-mode @@ -799,8 +851,6 @@ systematically send encrypted emails when possible." :interpreter ("go" . go-mode) :config (add-hook 'go-mode-hook 'lsp-deferred)) -(use-package go-flycheck - :after go-mode) (use-package gorepl-mode :after go-mode :config @@ -820,39 +870,39 @@ systematically send encrypted emails when possible." ;;; Clojure -(use-package clojure-mode - :mode ("\\.clj*\\'" . clojure-mode) - :interpreter ("clojure" . clojure-mode)) +;; (use-package clojure-mode +;; :mode ("\\.clj*\\'" . clojure-mode) +;; :interpreter ("clojure" . clojure-mode)) -(use-package cider - :after clojure-mode - :config - (add-hook 'clojure-mode-hook #'cider-mode) - (setq nrepl-hide-special-buffers t)) +;; (use-package cider +;; :after clojure-mode +;; :config +;; (add-hook 'clojure-mode-hook #'cider-mode) +;; (setq nrepl-hide-special-buffers t)) -(use-package emidje - :after clojure-mode - :config - (eval-after-load 'cider - #'emidje-setup)) +;; (use-package emidje +;; :after clojure-mode +;; :config +;; (eval-after-load 'cider +;; #'emidje-setup)) -(use-package flycheck-clojure - :after flycheck - :config - (eval-after-load 'flycheck '(flycheck-clojure-setup)) - (add-hook 'after-init-hook #'global-flycheck-mode)) +;; (use-package flycheck-clojure +;; :after flycheck +;; :config +;; (eval-after-load 'flycheck '(flycheck-clojure-setup)) +;; (add-hook 'after-init-hook #'global-flycheck-mode)) -(use-package clj-refactor - :after clojure-mode - :config - (defun my-clojure-mode-hook () - (clj-refactor-mode 1 - (yas-minor-mode 1)) - (cljr-add-keybindings-with-prefix "C-c C-m")) - (add-hook 'clojure-mode-hook #'my-clojure-mode-hook)) ; for adding require/use/import statements +;; (use-package clj-refactor +;; :after clojure-mode +;; :config +;; (defun my-clojure-mode-hook () +;; (clj-refactor-mode 1 +;; (yas-minor-mode 1)) +;; (cljr-add-keybindings-with-prefix "C-c C-m")) +;; (add-hook 'clojure-mode-hook #'my-clojure-mode-hook)) ; for adding require/use/import statements -(use-package clojure-snippets - :after clojure-mode) +;; (use-package clojure-snippets +;; :after clojure-mode) ;;; Misc langs (use-package yaml-mode @@ -862,6 +912,7 @@ systematically send encrypted emails when possible." (general-define-key :states 'normal + "b" 'helm-buffers-list "rl" 'load-file "~/emacs.d/init.el") ;; byte-compile @@ -888,17 +939,14 @@ systematically send encrypted emails when possible." ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. - '(browse-url-browser-function (quote browse-url-firefox)) + '(browse-url-browser-function 'browse-url-firefox) '(custom-safe-themes - (quote - ("c74e83f8aa4c78a121b52146eadb792c9facc5b1f02c917e3dbb454fca931223" "e4c8810d9ab925567a69c11d5c95d198a4e7d05871453b2c92c020712559c4c1" default))) + '("c74e83f8aa4c78a121b52146eadb792c9facc5b1f02c917e3dbb454fca931223" "e4c8810d9ab925567a69c11d5c95d198a4e7d05871453b2c92c020712559c4c1" default)) '(elfeed-feeds - (quote - ("https://therealnews.com/feed" "https://blog.netbsd.org/tnf/feed/entries/atom" "http://libcom.org/library-latest/feed" "https://itsgoingdown.org/feed/podcast/" "https://crimethinc.com/feed" "https://www.indybay.org/syn/generate_rss.php?page_id=60&include_posts=1&include_blurbs=1" "https://www.indybay.org/syn/generate_rss.php?page_id=12&include_posts=1&include_blurbs=1" "https://unicornriot.ninja/feed/" "https://blackrosefed.org/feed/" "http://news.infoshop.org/feed/" "https://antifascistnews.net/feed/" "https://en.squat.net/feed/" "https://enoughisenough14.org/feed/" "https://thefreeonline.wordpress.com/feed/" "https://www.redpepper.org.uk/feed" "https://anarchistnews.org/rss.xml" "https://waronsociety.noblogs.org/?feed=rss2" "https://en-contrainfo.espiv.net/feed/" "https://earthfirstjournal.org/newswire/feed/" "https://anarchistwithoutcontent.wordpress.com/feed/" "https://countervortex.org/node/feed" "http://ideasandaction.info/feed/" "https://industrialworker.iww.org/?feed=rss2" "https://www.iww.org/node/feed" "https://transfelinism.wordpress.com/feed/" "https://yogthos.net/feed.xml"))) - '(helm-completion-style (quote emacs)) + '("https://therealnews.com/feed" "https://blog.netbsd.org/tnf/feed/entries/atom" "http://libcom.org/library-latest/feed" "https://itsgoingdown.org/feed/podcast/" "https://crimethinc.com/feed" "https://www.indybay.org/syn/generate_rss.php?page_id=60&include_posts=1&include_blurbs=1" "https://www.indybay.org/syn/generate_rss.php?page_id=12&include_posts=1&include_blurbs=1" "https://unicornriot.ninja/feed/" "https://blackrosefed.org/feed/" "http://news.infoshop.org/feed/" "https://antifascistnews.net/feed/" "https://en.squat.net/feed/" "https://enoughisenough14.org/feed/" "https://thefreeonline.wordpress.com/feed/" "https://www.redpepper.org.uk/feed" "https://anarchistnews.org/rss.xml" "https://waronsociety.noblogs.org/?feed=rss2" "https://en-contrainfo.espiv.net/feed/" "https://earthfirstjournal.org/newswire/feed/" "https://anarchistwithoutcontent.wordpress.com/feed/" "https://countervortex.org/node/feed" "http://ideasandaction.info/feed/" "https://industrialworker.iww.org/?feed=rss2" "https://www.iww.org/node/feed" "https://transfelinism.wordpress.com/feed/" "https://yogthos.net/feed.xml")) + '(helm-completion-style 'emacs) '(lui-buttons-list - (quote - (("\\(?:id\\|mid\\|thread\\):[0-9A-Za-z][0-9A-Za-z.@-]*" 0 notmuch-show 0) + '(("\\(?:id\\|mid\\|thread\\):[0-9A-Za-z][0-9A-Za-z.@-]*" 0 notmuch-show 0) ("`\\([A-Za-z0-9+=*/-]+\\)'" 1 lui-button-elisp-symbol 1) ("\\ +;; Keywords: outlines, hypermedia, calendar, wp +;; Homepage: https://orgmode.org + +;; This file is not part of GNU Emacs. + +;; This file 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 2, or (at your option) +;; any later version. + +;; This file 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 GNU Emacs. If not, see . + +;;; Commentary: + +;; This file implements links to notmuch messages and "searches". A +;; search is a query to be performed by notmuch; it is the equivalent +;; to folders in other mail clients. Similarly, mails are referred to +;; by a query, so both a link can refer to several mails. + +;; Links have one the following form +;; notmuch: +;; notmuch-search:. + +;; The first form open the queries in notmuch-show mode, whereas the +;; second link open it in notmuch-search mode. Note that queries are +;; performed at the time the link is opened, and the result may be +;; different from when the link was stored. + +;;; Code: + +(require 'ol) +(require 'org) + +;; customisable notmuch open functions +(defcustom org-notmuch-open-function + 'org-notmuch-follow-link + "Function used to follow notmuch links. + +Should accept a notmuch search string as the sole argument." + :group 'org-notmuch + :version "24.4" + :package-version '(Org . "8.0") + :type 'function) + +(defcustom org-notmuch-search-open-function + 'org-notmuch-search-follow-link + "Function used to follow notmuch-search links. +Should accept a notmuch search string as the sole argument." + :group 'org-notmuch + :version "24.4" + :package-version '(Org . "8.0") + :type 'function) + +(make-obsolete-variable 'org-notmuch-search-open-function nil "9.3") + + + +;; Install the link type +(org-link-set-parameters "notmuch" + :follow #'org-notmuch-open + :store #'org-notmuch-store-link) + +(defun org-notmuch-store-link () + "Store a link to a notmuch search or message." + (when (memq major-mode '(notmuch-show-mode notmuch-tree-mode)) + (let* ((message-id (notmuch-show-get-message-id t)) + (subject (notmuch-show-get-subject)) + (to (notmuch-show-get-to)) + (from (notmuch-show-get-from)) + (date (org-trim (notmuch-show-get-date))) + desc link) + (org-store-link-props :type "notmuch" :from from :to to :date date + :subject subject :message-id message-id) + (setq desc (org-email-link-description)) + (setq link (concat "notmuch:id:" message-id)) + (org-add-link-props :link link :description desc) + link))) + +(defun org-notmuch-open (path) + "Follow a notmuch message link specified by PATH." + (funcall org-notmuch-open-function path)) + +(defun org-notmuch-follow-link (search) + "Follow a notmuch link to SEARCH. + +Can link to more than one message, if so all matching messages are shown." + (require 'notmuch) + (notmuch-show search)) + + + +(org-link-set-parameters "notmuch-search" + :follow #'org-notmuch-search-open + :store #'org-notmuch-search-store-link) + +(defun org-notmuch-search-store-link () + "Store a link to a notmuch search or message." + (when (eq major-mode 'notmuch-search-mode) + (let ((link (concat "notmuch-search:" notmuch-search-query-string)) + (desc (concat "Notmuch search: " notmuch-search-query-string))) + (org-store-link-props :type "notmuch-search" + :link link + :description desc) + link))) + +(defun org-notmuch-search-open (path) + "Follow a notmuch message link specified by PATH." + (message "%s" path) + (org-notmuch-search-follow-link path)) + +(defun org-notmuch-search-follow-link (search) + "Follow a notmuch link by displaying SEARCH in notmuch-search mode." + (require 'notmuch) + (notmuch-search search)) + + + +(org-link-set-parameters "notmuch-tree" + :follow #'org-notmuch-tree-open + :store #'org-notmuch-tree-store-link) + +(defun org-notmuch-tree-store-link () + "Store a link to a notmuch search or message." + (when (eq major-mode 'notmuch-tree-mode) + (let ((link (concat "notmuch-tree:" (notmuch-tree-get-query))) + (desc (concat "Notmuch tree: " (notmuch-tree-get-query)))) + (org-store-link-props :type "notmuch-tree" + :link link + :description desc) + link))) + +(defun org-notmuch-tree-open (path) + "Follow a notmuch message link specified by PATH." + (message "%s" path) + (org-notmuch-tree-follow-link path)) + +(defun org-notmuch-tree-follow-link (search) + "Follow a notmuch link by displaying SEARCH in notmuch-tree mode." + (require 'notmuch) + (notmuch-tree search)) + +(provide 'ol-notmuch) + +;;; ol-notmuch.el ends here diff --git a/lisp/sr-speedbar.el.1 b/lisp/sr-speedbar.el.1 new file mode 100755 index 0000000..40bc7c6 --- /dev/null +++ b/lisp/sr-speedbar.el.1 @@ -0,0 +1,651 @@ +;;; sr-speedbar.el --- Same frame speedbar + +;; Author: Sebastian Rose +;; Maintainer: Sebastian Rose +;; Peter Lunicks +;; Copyright (C) 2008, 2009, Sebastian Rose, all rights reserved. +;; Copyright (C) 2008, 2009, Andy Stewart, all rights reserved. +;; Copyright (C) 2009, Peter Lunicks, all rights reversed. +;; Created: 2008 +;; Version: 20161025 +;; X-Original-Version: 0.1.10 +;; Last-Updated: 2016-10-25 +;; URL: http://www.emacswiki.org/emacs/download/sr-speedbar.el +;; Keywords: speedbar, sr-speedbar.el +;; Compatibility: GNU Emacs 22 ~ GNU Emacs 25 +;; +;; Features required by this library: +;; +;; `speedbar' `advice' `cl' +;; + +;;; This file is NOT part of GNU Emacs + +;;; License +;; +;; 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, 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; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth +;; Floor, Boston, MA 02110-1301, USA. + +;;; Commentary: +;; +;; The sr-speedbar.el was created just because I could not believe what I +;; read on http://www.emacswiki.org/cgi-bin/wiki/Speedbar. They wrote there +;; that it is not possible to show the speedbar in the same frame. But, as +;; we all know, ecb had this already. So I started as some kind of joke :) +;; But when I found it useful and use it all the time. +;; +;; Now you type windows key with 's' (`s-s' in Emacs) will show the speedbar +;; in an extra window, same frame. You can customize the initial width of the +;; speedbar window. +;; +;; Below are commands you can use: +;; +;; `sr-speedbar-open' Open `sr-speedbar' window. +;; `sr-speedbar-close' Close `sr-speedbar' window. +;; `sr-speedbar-toggle' Toggle `sr-speedbar' window. +;; `sr-speedbar-select-window' Select `sr-speedbar' window. +;; `sr-speedbar-refresh-turn-on' Turn on refresh speedbar content. +;; `sr-speedbar-refresh-turn-off' Turn off refresh speedbar content. +;; `sr-speedbar-refresh-toggle' Toggle refresh speedbar content. +;; +;; Enjoy! ;) +;; + +;;; Installation: +;; +;; Copy sr-speedbar.el to your load-path and add to your ~/.emacs +;; +;; (require 'sr-speedbar) +;; (global-set-key (kbd "s-s") 'sr-speedbar-toggle) +;; +;; ... or any key binding you like. +;; + +;;; Customize: +;; +;; M-x customize-group RET sr-speedbar RET + +;;; Change log: +;; * 25 Oct 2016: +;; * Hong Xu +;; * Fix compilation warning when `helm-alive-p' is not defined. +;; +;; * 04 Aug 2015: +;; * Tamas Levai : +;; * fix compilation warnings +;; +;; * 15 Sep 2014: +;; * Tu, Do Hoang +;; * define `sr-speedbar-handle-other-window-advice' and `ad-advised-definition-p' +;; before defining `sr-speedbar-skip-other-window-p'. Othewise, `sr-speedbar' +;; fails to load at this stage. +;; +;; * Do not used advised `pop-to-buffer' when helm window is +;; alive. Otherwise another horizontal buffer is created inside +;; Helm buffer. +;; +;; * Uwe Koloska +;; * define `ad-advised-definition-p' only if it's not defined +;; fixes an error on Emacs 24.3 where `macrop' ist still named +;; `ad-macro-p' +;; +;; * 03 Aug 2014: +;; * Reuben Thomas : +;; * Reduce to a single width preference, and make it work properly on +;; startup. +;; * Miscellaneous tidying of documentation and comments. +;; * Remove version constant; should be using the package header, and it +;; was already way out of date. +;; +;; * 08 Jun 2014: +;; * Gregor Zattler: +;; * test if symbol `ad-advised-definition-p' is defined, +;; since Christian Brassats version test failed on emacs +;; 23.3.91.1 +;; +;; * 05 May 2014: +;; * Christian Brassat: +;; * `ad-advised-definition-p' is not supported since Emacs 24.4. +;; +;; * 09 Mar 2013: +;; * Tharre: +;; * Remove Emacs 21 compatibility code as it fails to compile on Emacs 24. +;; +;; * 20 July 2009: +;; * Peter Lunicks: +;; * Add new option `sr-speedbar-right-side' to control which +;; side of the frame the speedbar appears on. +;; +;; * 18 Feb 2009: +;; * Andy Stewart: +;; * Fix bug between ECB and `sr-speedbar-close'. +;; +;; * 29 Jan 2009: +;; * Andy Stewart: +;; * Fix doc. +;; +;; * 13 Jan 2009: +;; * Andy Stewart: +;; * Use `emacs-major-version' instead comment for Emacs 21 compatibility. +;; * Rewrite advice for `pop-to-buffer' to avoid `pop-to-buffer' not effect +;; when have many dedicated window in current frame. +;; * Rewrite advice for `delete-other-windows' to avoid use common variable +;; `delete-protected-window-list' and use `window-dedicated-p' instead. +;; Remove variable `delete-protected-window-list' and function +;; `sr-speedbar-dedicated-match-protected-window-p'. +;; +;; * 04 Jan 2009: +;; * Andy Stewart: +;; * Add new option `sr-speedbar-auto-refresh' control refresh content. +;; * Add new functions: +;; `sr-speedbar-refresh-turn-on', +;; `sr-speedbar-refresh-turn-off', +;; `sr-speedbar-refresh-toggle'. +;; * Fix doc. +;; +;; * 30 Dec 2008: +;; * Andy Stewart: +;; * Rewrite advice for `delete-other-windows' for fix the bug +;; with window configuration save and revert. +;; * Rewrite advice for `delete-window', now just remember window +;; width before deleted, and can use `delete-window' do same effect +;; as command `sr-speedbar-close'. +;; * Add new option `sr-speedbar-max-width'. +;; Remember window width before hide, except larger than value of +;; `sr-speedbar-max-width'. +;; * Add new variable `delete-protected-window-list', for protected +;; special window don't deleted. +;; This variable is common for any extension that use dedicated +;; window. +;; * Fix doc. +;; +;; * 29 Dec 2008: +;; * Andy Stewart: +;; * Pick-up and refactory code that use `buffer-live-p' or `window-live-p', +;; and replace with `sr-speedbar-buffer-exist-p' and +;; `sr-speedbar-window-exist-p'. +;; * Rename some function with prefix `sr-speedbar-' to avoid +;; conflict with other functions. +;; * Pick-up the code that handle advice for `other-window', +;; and replace with function `sr-speedbar-handle-other-window-advice'. +;; * Clean up code, make more clear. +;; +;; * 21 Dec 2008: +;; * Andy Stewart: +;; * Fix the bug `sr-speedbar-open' and `sr-speedbar-close'. +;; * Fix doc. +;; +;; * 20 Dec 2008 +;; * Andy Stewart: +;; * Fix `ad-advised-definition-p' error. +;; * Fix doc. +;; +;; * 17 Dec 2008 +;; * Andy Stewart: +;; * Add new option `sr-speedbar-skip-other-window-p' and new advice +;; for `other-window', make user skip select `sr-speedbar' window +;; when use command `other-window'. +;; * Fix the name of advice, make more clear. +;; * Fix the bug `sr-speedbar-select-window' when no live window exist. +;; * Fix doc. +;; +;; * 16 Dec 2008: +;; * Andy Stewart: +;; * Fix the bug of `sr-speedbar-refresh', use `default-directory' +;; get refresh directory instead through function in `dired'. +;; * Fix `window-live-p' bug, check window valid value before use +;; `window-live-p' test `sr-speedbar-window'. +;; * Fix `buffer-live-p' bug, check buffer valid value before use +;; `buffer-live-p' test `speedbar-buffer'. +;; * Add advice `pop-to-buffer' to make function `display-buffer' +;; can pop-up window when just have two windows (one is `sr-speedbar' +;; window) in current frame. +;; * Add group `sr-speedbar'. +;; More better customize interface through `customize-group'. +;; +;; * 28 Sep 2008: +;; * Andy Stewart: +;; * Fix a bug, when `sr-speedbar-toggle' many times, window width +;; will increment automatically. +;; * Use around advices replace, make code simple. +;; * Use `sr-speedbar-open' replace `sr-speedbar-no-separate-frame'. +;; * Clean up code. +;; +;; * 28 Sep 2008: +;; * Sebastian: +;; * set `sr-speedbar-delete-windows' to nil to avoid +;; the removal of other windows. +;; +;; * 26 Jun 2008: +;; * Sebastian: +;; * Added Andy Stewart's patch to refresh the speedbar's contents. +;; Thanks for this one! +;; +;; * Init: +;; * Sebastian: +;; * Added some lines to get it working: +;; * splitting the window and remember it, +;; * changing the way speedbar finds a file. +;; * File view of speedbar is now working all right. +;; * C-x 1 in other window deletes speedbar-window, just calling +;; M-x sr-speedbar-no-separate-frame again is fine now. +;; * Toggle speedbar works, width is save when toggling. +;; * Recalculate speedbar width if window-width - speedbar-width <= 0 +;; * Speedbar window is now dedicated to speedbar-buffer. +;; + +;;; Acknowledgements: +;; +;; All emacsers ... :) +;; + +;;; Bug +;; +;; + +;;; TODO +;; +;; +;; + +;;; Require +(require 'speedbar) +(require 'advice) +(require 'cl-lib) +(eval-when-compile + (require 'cl)) + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; User Customization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defgroup sr-speedbar nil + "Same frame speedbar." + :group 'speedbar) + +(defcustom sr-speedbar-default-width 40 + "Initial width of `sr-speedbar-window' under window system." + :type 'integer + :group 'sr-speedbar) + +(defcustom sr-speedbar-max-width 50 + "The max width limit that window allowed. +Default, if hide `sr-speedbar' window will remember +window width, except the window width larger than +this value." + :type 'integer + :group 'sr-speedbar) + +(defcustom sr-speedbar-auto-refresh t + "Automatically refresh speedbar content when changed directory. +Default is t." + :type 'boolean + :set (lambda (symbol value) + (set symbol value)) + :group 'sr-speedbar) + +(defcustom sr-speedbar-right-side t + "Show the speedbar to the right side of the current window. +If nil, the speedbar will appear on the left. +Default is t." + :type 'boolean + :set (lambda (symbol value) + (set symbol value)) + :group 'sr-speedbar) + +(defcustom sr-speedbar-delete-windows nil + "Allow the speedbar to delete other windows before showing up. +If nil, speedbar will not touch your window configuration. +Otherwise `delete-other-windows' will be called before showing +the speedbar. + +Default is nil." + :type 'boolean + :group 'sr-speedbar) + +(if (not (fboundp 'ad-advised-definition-p)) + (defun ad-advised-definition-p (definition) + "Return non-nil if DEFINITION was generated from advice information." + (if (or (ad-lambda-p definition) + (macrop definition) + (ad-compiled-p definition)) + (let ((docstring (ad-docstring definition))) + (and (stringp docstring) + (get-text-property 0 'dynamic-docstring-function docstring)))))) + +(defun sr-speedbar-handle-other-window-advice (activate) + "Handle advice for function `other-window'. +If ACTIVATE is `non-nil' enable advice `sr-speedbar-other-window-advice'. +Otherwise disable it." + (if activate + (ad-enable-advice 'other-window 'after 'sr-speedbar-other-window-advice) + (ad-disable-advice 'other-window 'after 'sr-speedbar-other-window-advice)) + (ad-activate 'other-window)) + +(defcustom sr-speedbar-skip-other-window-p nil + "Whether skip `sr-speedbar' window with `other-window'. +Default, can use `other-window' select window in cyclic +ordering of windows. But sometimes we don't want select +`sr-speedbar' window use `other-window'. +Just want make `sr-speedbar' window as a view sidebar. + +So please turn on this option if you want skip +`sr-speedbar' window with `other-window'. + +Default is nil." + :type 'boolean + :set (lambda (symbol value) + (set symbol value) + (if (fboundp 'ad-advised-definition-p) + (when (ad-advised-definition-p 'other-window) + (sr-speedbar-handle-other-window-advice value)) + (when (ad-is-advised 'other-window) + (sr-speedbar-handle-other-window-advice value)))) + :group 'sr-speedbar) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Constant ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defconst sr-speedbar-buffer-name "*SPEEDBAR*" + "The buffer name of sr-speedbar.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar sr-speedbar-width sr-speedbar-default-width + "Initial width of speedbar-window.") + +(defvar sr-speedbar-window nil + "Speedbar window.") + +(defvar sr-speedbar-last-refresh-dictionary nil + "The last refresh dictionary record of 'sr-speedbar-refresh'.") + +(eval-when-compile + (defvar ecb-activated-window-configuration nil) + (defun ecb-activate ()) + (defun ecb-deactivate ())) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Interactive functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;###autoload +(defun sr-speedbar-toggle () + "Toggle sr-speedbar window. +Toggle visibility of sr-speedbar by resizing +the `sr-speedbar-window' to a minimal width +or the last width when visible. +Use this function to create or toggle visibility +of a speedbar-window. It will be created if necessary." + (interactive) + (if (sr-speedbar-exist-p) + (sr-speedbar-close) + (sr-speedbar-open))) + +;;;###autoload +(defun sr-speedbar-open () + "Create `sr-speedbar' window." + (interactive) + (if (not (sr-speedbar-exist-p)) + (let ((current-window (selected-window))) + ;; Ensure only one window is there + ;; when `sr-speedbar-delete-windows' is non-nil + (if sr-speedbar-delete-windows + (delete-other-windows)) + ;; Whether activate `other-window' advice + ;; to skip `sr-speedbar' window when use `other-window'. + (sr-speedbar-handle-other-window-advice sr-speedbar-skip-other-window-p) + ;; Switch buffer + (if (sr-speedbar-buffer-exist-p speedbar-buffer) + (unless (sr-speedbar-window-exist-p sr-speedbar-window) + (sr-speedbar-get-window)) + (if (<= (sr-speedbar-current-window-take-width) sr-speedbar-width) + (setq sr-speedbar-width sr-speedbar-default-width)) + (sr-speedbar-get-window) ;get `sr-speedbar' window that split current window + (setq speedbar-buffer (get-buffer-create sr-speedbar-buffer-name) + speedbar-frame (selected-frame) + dframe-attached-frame (selected-frame) + speedbar-select-frame-method 'attached + speedbar-verbosity-level 0 ;don't say anything, i don't like ... :) + speedbar-last-selected-file nil) + (set-buffer speedbar-buffer) + (buffer-disable-undo speedbar-buffer) ;make disable in speedbar buffer, otherwise will occur `undo-outer-limit' error + (speedbar-mode) + (speedbar-reconfigure-keymaps) + (speedbar-update-contents) + (speedbar-set-timer 1) + ;; Add speedbar hook. + (add-hook 'speedbar-before-visiting-file-hook 'sr-speedbar-before-visiting-file-hook t) + (add-hook 'speedbar-before-visiting-tag-hook 'sr-speedbar-before-visiting-tag-hook t) + (add-hook 'speedbar-visiting-file-hook 'sr-speedbar-visiting-file-hook t) + (add-hook 'speedbar-visiting-tag-hook 'sr-speedbar-visiting-tag-hook t) + ;; Add `kill-buffer-hook'. + (add-hook 'kill-buffer-hook 'sr-speedbar-kill-buffer-hook) ;add `kill-buffer-hook' + ;; Auto refresh speedbar content + ;; if option `sr-speedbar-auto-refresh' is non-nil + (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh)) + (set-window-buffer sr-speedbar-window (get-buffer sr-speedbar-buffer-name)) + (set-window-dedicated-p sr-speedbar-window t) ;make `sr-speedbar-window' dedicated to speedbar-buffer. + (select-window current-window)) + (message "`sr-speedbar' window has exist."))) + +(defun sr-speedbar-close () + "Close `sr-speedbar' window and save window width." + (interactive) + (if (sr-speedbar-exist-p) + (let ((current-window (selected-window))) + ;; Remember window width. + (sr-speedbar-select-window) + (sr-speedbar-remember-window-width) + ;; Close window. + (if (and (require 'ecb nil t) + ecb-activated-window-configuration) + ;; Toggle ECB window when ECB window activated. + (progn + (ecb-deactivate) + (ecb-activate)) + ;; Otherwise delete dedicated window. + (delete-window sr-speedbar-window) + (if (sr-speedbar-window-exist-p current-window) + (select-window current-window)))) + (message "`sr-speedbar' window is not exist."))) + +(defun sr-speedbar-select-window () + "Force the windows that contain `sr-speedbar'." + (interactive) + (if (sr-speedbar-exist-p) + (select-window sr-speedbar-window) + (message "`sr-speedbar' window is not exist."))) + +(defun sr-speedbar-refresh-turn-on () + "Turn on refresh content automatically." + (interactive) + (setq sr-speedbar-auto-refresh t) + (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh t)) + +(defun sr-speedbar-refresh-turn-off () + "Turn off refresh content automatically." + (interactive) + (setq sr-speedbar-auto-refresh nil) + (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh t)) + +(defun sr-speedbar-refresh-toggle () + "Toggle refresh content status." + (interactive) + (setq sr-speedbar-auto-refresh (not sr-speedbar-auto-refresh)) + (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh t)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; utilise functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defun sr-speedbar-exist-p () + "Return `non-nil' if `sr-speedbar' is exist. +Otherwise return nil." + (and (sr-speedbar-buffer-exist-p speedbar-buffer) + (sr-speedbar-window-exist-p sr-speedbar-window))) + +(defun sr-speedbar-window-p () + "Return `non-nil' if current window is `sr-speedbar' window. +Otherwise return nil." + (equal sr-speedbar-buffer-name (buffer-name (window-buffer)))) + +(defun sr-speedbar-remember-window-width () + "Remember window width." + (let ((win-width (sr-speedbar-current-window-take-width))) + (if (and (sr-speedbar-window-p) + (> win-width 1) + (<= win-width sr-speedbar-max-width)) + (setq sr-speedbar-width win-width)))) + +(defun sr-speedbar-get-window () + "Get `sr-speedbar' window." + (let ((current-window (selected-window)) + ;; Get split new window. + (new-window (split-window + (selected-window) + (if sr-speedbar-right-side + (- (sr-speedbar-current-window-take-width) sr-speedbar-width) + sr-speedbar-width) + t))) + ;; Select split window. + (setq sr-speedbar-window + (if sr-speedbar-right-side + ;; Select right window when `sr-speedbar-right-side' is enable. + new-window + ;; Otherwise select left widnow. + current-window)))) + +(defun sr-speedbar-before-visiting-file-hook () + "Function that hook `speedbar-before-visiting-file-hook'." + (select-window (previous-window))) + +(defun sr-speedbar-before-visiting-tag-hook () + "Function that hook `speedbar-before-visiting-tag-hook'." + (select-window (previous-window))) + +(defun sr-speedbar-visiting-file-hook () + "Function that hook `speedbar-visiting-file-hook'." + (select-window (previous-window))) + +(defun sr-speedbar-visiting-tag-hook () + "Function that hook `speedbar-visiting-tag-hook'." + (select-window (previous-window))) + +(defun sr-speedbar-kill-buffer-hook () + "Function that hook `kill-buffer-hook'." + (when (eq (current-buffer) speedbar-buffer) + (setq speedbar-frame nil + dframe-attached-frame nil + speedbar-buffer nil) + (speedbar-set-timer nil) + (remove-hook 'speedbar-before-visiting-file-hook 'sr-speedbar-before-visiting-file-hook) + (remove-hook 'speedbar-before-visiting-tag-hook 'sr-speedbar-before-visiting-tag-hook) + (remove-hook 'speedbar-visiting-file-hook 'sr-speedbar-visiting-file-hook) + (remove-hook 'speedbar-visiting-tag-hook 'sr-speedbar-visiting-tag-hook))) + +(defun sr-speedbar-refresh () + "Refresh the context of speedbar." + (when (and (not (equal default-directory sr-speedbar-last-refresh-dictionary)) ;if directory is change + (not (sr-speedbar-window-p))) ;and is not in speedbar buffer + (setq sr-speedbar-last-refresh-dictionary default-directory) + (speedbar-refresh))) + +(defun sr-speedbar-handle-auto-refresh (activate &optional echo-show) + "Automatically refresh speedbar content when changed directory. +Do nothing if option ACTIVATE is nil. +Will display message if ECHO-SHOW is non-nil." + (if activate + (progn + (add-hook 'speedbar-timer-hook 'sr-speedbar-refresh) + (if echo-show (message "Turn on speedbar content refresh automatically."))) + (remove-hook 'speedbar-timer-hook 'sr-speedbar-refresh) + (if echo-show (message "Turn off speedbar content refresh automatically.")))) + +(defun sr-speedbar-current-window-take-width (&optional window) + "Return the width that WINDOW take up. +If WINDOW is nil, get current window." + (let ((edges (window-edges window))) + (- (nth 2 edges) (nth 0 edges)))) + +(defun sr-speedbar-window-dedicated-only-one-p () + "Only have one non-dedicated window." + (interactive) + (let ((window-number 0) + (dedicated-window-number 0)) + (walk-windows + (lambda (w) + (with-selected-window w + (incf window-number) + (if (window-dedicated-p w) + (incf dedicated-window-number))))) + (if (and (> dedicated-window-number 0) + (= (- window-number dedicated-window-number) 1)) + t nil))) + +(defun sr-speedbar-window-exist-p (window) + "Return `non-nil' if WINDOW is exist. +Otherwise return nil." + (and window (window-live-p window))) + +(defun sr-speedbar-buffer-exist-p (buffer) + "Return `non-nil' if BUFFER is exist. +Otherwise return nil." + (and buffer (buffer-live-p buffer))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Advices ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defadvice delete-other-windows (around sr-speedbar-delete-other-window-advice activate) + "This advice to make `sr-speedbar' window can't deleted by command `delete-other-windows'." + (let ((sr-speedbar-active-p (sr-speedbar-window-exist-p sr-speedbar-window))) + (if sr-speedbar-active-p + (let ((current-window (selected-window))) + (dolist (win (window-list)) + (when (and (window-live-p win) + (not (eq current-window win)) + (not (window-dedicated-p win))) + (delete-window win)))) + ad-do-it))) + +(defadvice delete-window (before sr-speedbar-delete-window-advice activate) + "This advice to remember `sr-speedbar' window width before deleted. +Use `delete-window' delete `sr-speedbar' window have same effect as `sr-speedbar-close'." + ;; Remember window width before deleted. + (sr-speedbar-remember-window-width)) + +(defadvice pop-to-buffer (before sr-speedbar-pop-to-buffer-advice activate) + "This advice is to fix `pop-to-buffer' problem with dedicated window. +Default, function `display-buffer' can't display buffer in select window +if current window is `dedicated'. + +So function `display-buffer' conflict with `sr-speedbar' window, because +`sr-speedbar' window is `dedicated' window. + +That is to say, when current frame just have one `non-dedicated' window, +any functions that use `display-buffer' can't split windows +to display buffer, even option `pop-up-windows' is enable. + +And the example function that can occur above problem is `pop-to-buffer'." + (when (and pop-up-windows ;`pop-up-windows' is enable + (sr-speedbar-window-dedicated-only-one-p) ;just have one `non-dedicated' window + (sr-speedbar-window-exist-p sr-speedbar-window) + (not (sr-speedbar-window-p)) ;not in `sr-speedbar' window + (not (bound-and-true-p helm-alive-p))) + (split-window-vertically) + (windmove-down))) + +(defadvice other-window (after sr-speedbar-other-window-advice) + "Default, can use `other-window' select window in cyclic ordering of windows. +But sometimes we don't want select `sr-speedbar' window use `other-window'. +Just want make `sr-speedbar' window as a view sidebar. + +This advice can make `other-window' skip `sr-speedbar' window." + (let ((count (or (ad-get-arg 0) 1))) + (when (and (sr-speedbar-window-exist-p sr-speedbar-window) + (eq sr-speedbar-window (selected-window))) + (other-window count)))) + +(provide 'sr-speedbar) + +;;; sr-speedbar.el ends here