emacs.d: initial config version
- starting init.el just basics (package, use-package, path-handlin) - include my-site-start.el that includes site-start.d directory and imports all *.el files in lexical order - functionality is imported via use-package inside the *.el file (first run: internet connection is needed to MELPA)
This commit is contained in:
59
init.el
Normal file
59
init.el
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
;;; init.el --- user init file -*- no-byte-compile: t -*-
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; this emacs initilization file is inspired by
|
||||||
|
;; https://github.com/mwfogleman/.emacs.d/blob/master/michael.org
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
;; When using auto-compile
|
||||||
|
;; take care, that the init packages are not influenced
|
||||||
|
(setq load-prefer-newer t)
|
||||||
|
|
||||||
|
;; Added by Package.el. This must come before configurations of
|
||||||
|
;; installed packages. Don't delete this line. If you don't want it,
|
||||||
|
;; just comment it out by adding a semicolon to the start of the line.
|
||||||
|
;; You may delete these explanatory comments.
|
||||||
|
(require 'package)
|
||||||
|
(package-initialize)
|
||||||
|
|
||||||
|
(setq package-archives
|
||||||
|
'(("gnu" . "https://elpa.gnu.org/packages/")
|
||||||
|
("melpa" . "https://melpa.org/packages/")))
|
||||||
|
|
||||||
|
;; from now on, we make use of use-package
|
||||||
|
;; this will make sure a package is downloaded, efficiently configured
|
||||||
|
;; (e.g. after load, or as needed), keys will be bind in a concise way, and more
|
||||||
|
(unless (package-installed-p 'use-package)
|
||||||
|
(package-refresh-contents)
|
||||||
|
(package-install 'use-package))
|
||||||
|
(require 'use-package)
|
||||||
|
(setq use-package-always-ensure t)
|
||||||
|
|
||||||
|
;; use my-site-start package
|
||||||
|
(autoload 'my-site-start "~/.emacs.d/my-site-start" nil t)
|
||||||
|
(my-site-start "~/.emacs.d/site-start.d/")
|
||||||
|
|
||||||
|
(custom-set-variables
|
||||||
|
;; custom-set-variables was added by Custom.
|
||||||
|
;; 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.
|
||||||
|
'(font-use-system-font t)
|
||||||
|
'(magit-commit-arguments
|
||||||
|
(quote
|
||||||
|
("--signoff" "--gpg-sign=1EC4BE4FF2A6C9F4DDDF30F33C5F485DBD250D66")))
|
||||||
|
'(magit-log-arguments (quote ("--graph" "--decorate" "--show-signature" "-n256")))
|
||||||
|
'(package-selected-packages
|
||||||
|
(quote
|
||||||
|
(flycheck lsp-ui rustic forge pcmpl-git git-link git-timemachine magit use-package)))
|
||||||
|
'(paradox-github-token t)
|
||||||
|
'(php-mode-coding-style (quote wordpress))
|
||||||
|
'(show-paren-mode t)
|
||||||
|
'(visible-bell t))
|
||||||
|
(custom-set-faces
|
||||||
|
;; custom-set-faces was added by Custom.
|
||||||
|
;; 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.
|
||||||
|
)
|
||||||
|
|
||||||
255
my-site-start.el
Normal file
255
my-site-start.el
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
;;; my-site-start.el --- set up personal .emacs.d/site-start.d/
|
||||||
|
;;
|
||||||
|
;; Copyright (C) era eriksson <http://www.iki.fi/~era/> 2008-2015
|
||||||
|
;; License: GPL v2
|
||||||
|
;; Version: see `my-site-start-version' below
|
||||||
|
;;
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; The purpose of my-site-start is to simplify maintenance of user libraries.
|
||||||
|
;; Instead of indefinitely tweaking your .emacs, just create a site-start.d
|
||||||
|
;; directory and add symlinks to the libraries you want to load into Emacs.
|
||||||
|
;;
|
||||||
|
;; See README.md for a more detailed introduction, and the customization
|
||||||
|
;; variables below for the rest.
|
||||||
|
;;
|
||||||
|
;;
|
||||||
|
;; Github repository / download: <http://github.com/tripleee/my-site-start/>
|
||||||
|
;;
|
||||||
|
;;; History:
|
||||||
|
;;
|
||||||
|
;; 2015-02-25 Version 0.003 -- moved to Github; update documentation and links
|
||||||
|
;; 2009-02-09 Version 0.002 -- various tweaks and updated documentation
|
||||||
|
;; 2009-02-05 Version 0.001 -- first public beta.
|
||||||
|
;;
|
||||||
|
;; See changelog and version control history for details.
|
||||||
|
;;
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(defconst my-site-start-version "0.003"
|
||||||
|
"Version numer for `my-site-start' library.")
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;; FIXME: defcustom
|
||||||
|
|
||||||
|
|
||||||
|
(defvar my-site-start-inhibit-p nil "\
|
||||||
|
*Set to non-nil to inhibit the running of `my-site-start' when loading.")
|
||||||
|
|
||||||
|
(defvar my-site-start-file-name-regex
|
||||||
|
"\\(\\`\\|/\\)[0-9][0-9][-A-Za-z0-9_+.#$%@]+\.elc?$"
|
||||||
|
"*Regular expression to select which files to `load' from `my-site-start'.
|
||||||
|
|
||||||
|
If you change this setting, you might also need to change other settings.
|
||||||
|
The assumption that all selected files will have one or more numbers at the
|
||||||
|
beginning of the file name is present in several other parts of `my-site-start'
|
||||||
|
and so you will need to change at least `my-site-start-load-order-function'
|
||||||
|
if this is not true.")
|
||||||
|
|
||||||
|
(defvar my-site-start-avoid-dir-regex
|
||||||
|
(mapconcat
|
||||||
|
#'regexp-quote
|
||||||
|
'(
|
||||||
|
"RCS"
|
||||||
|
"CVS"
|
||||||
|
".git"
|
||||||
|
".svn"
|
||||||
|
;;;;;;;; TODO: hg, monotone, svk, arch, bzr, others ...?
|
||||||
|
)
|
||||||
|
"\\|")
|
||||||
|
"*Regular expression of directory names to avoid in `my-site-start'
|
||||||
|
when recursing into a directory tree.
|
||||||
|
|
||||||
|
The regular expression is applied in a context where the match is
|
||||||
|
anchored to the beginning and end of the bare directory name, without
|
||||||
|
a full path.")
|
||||||
|
|
||||||
|
(defvar my-site-start-load-order-function #'my-site-start-sort-load-order
|
||||||
|
"*Function accepting a list of strings specifying file names to be loaded,
|
||||||
|
and returning the list in sorted order. Used in `my-site-start' to decide
|
||||||
|
the order in which to load files.")
|
||||||
|
|
||||||
|
(defvar my-site-start-defer-file-p-function #'my-site-start-defer-file-p
|
||||||
|
"*Function to determine whether loading of a file name should be deferred.
|
||||||
|
|
||||||
|
See `my-site-start-do-deferred-loads'.")
|
||||||
|
|
||||||
|
(defvar my-site-start--deferred-load-files nil
|
||||||
|
"List of files to load from `my-site-start-do-deferred-loads'.
|
||||||
|
\(Internal use only.\)")
|
||||||
|
|
||||||
|
|
||||||
|
(defun my-site-start (dir &optional no-recursion) "\
|
||||||
|
Add DIR to `load-path' and load files matching `my-site-start-file-name-regex'.
|
||||||
|
|
||||||
|
The optional second argument NO-RECURSION says to not traverse any directories.
|
||||||
|
Those other directories will also be prepended to `load-path'.
|
||||||
|
|
||||||
|
Files will be sorted according to the function pointed to by the variable
|
||||||
|
`my-site-start-load-order-function'.
|
||||||
|
|
||||||
|
See also `my-site-start-defer-file-p-function' for controlling deferred
|
||||||
|
loading of files. The documentation for `my-site-start-do-deferred-loads'
|
||||||
|
contains further information about this feature. If a file is determined to
|
||||||
|
belong in the deferred set, it will be loaded only later, from within the
|
||||||
|
`my-site-start-interactive-setup-hook' hook.
|
||||||
|
|
||||||
|
If the value of the variable `my-site-start-inhibit-p' is non-nil,
|
||||||
|
`my-site-start' will only report which files would have been loaded.
|
||||||
|
Changes to the `load-path' will also not be made, only reported."
|
||||||
|
(mapc #'my-site-start-load
|
||||||
|
(my-site-start-split-deferred
|
||||||
|
(funcall my-site-start-load-order-function
|
||||||
|
(my-site-start-files (expand-file-name dir) no-recursion) )
|
||||||
|
'my-site-start--deferred-load-files) ) )
|
||||||
|
|
||||||
|
(defun my-site-start-split-deferred (list variable)
|
||||||
|
"Move deferred file names from LIST to VARIABLE, and return the rest.
|
||||||
|
|
||||||
|
Whether a file is to be deferred or not is determined by the function
|
||||||
|
pointed to by the variable `my-site-start-defer-file-p-function'."
|
||||||
|
(let (l f d v)
|
||||||
|
(while list
|
||||||
|
(setq f (car list)
|
||||||
|
list (cdr list) )
|
||||||
|
(setq v (if (funcall my-site-start-defer-file-p-function f) 'd 'l))
|
||||||
|
(set v (cons f (symbol-value v))) )
|
||||||
|
(set variable (append (symbol-value variable) (reverse d)))
|
||||||
|
(reverse l) ))
|
||||||
|
|
||||||
|
(defun my-site-start-load (file)
|
||||||
|
"Load FILE, unless `my-site-start' loading is inhibited.
|
||||||
|
|
||||||
|
If `my-site-start-inhibit-p' is non-nil, just print diagnostics indicating
|
||||||
|
what would have been done."
|
||||||
|
(message (if my-site-start-inhibit-p "Would load %s" "Loading %s") file)
|
||||||
|
(or my-site-start-inhibit-p (load-file file)) )
|
||||||
|
|
||||||
|
(defun my-site-start-files (dir no-recursion)
|
||||||
|
"Return files in DIR which are eligible for loading, obeying NO-RECURSION
|
||||||
|
i.e. only scanning the current directory if non-nil, otherwise descending
|
||||||
|
into subdirectories.
|
||||||
|
|
||||||
|
DIR is also added to the front of `load-path' unless it is already on the
|
||||||
|
path \(or `my-site-start-inhibit-p' is non-nil, in which case only log
|
||||||
|
whether the path would have been added\). If recursing, all traversed
|
||||||
|
directories will also be added to the path, under the same conditions.
|
||||||
|
|
||||||
|
DIR should be an absolute path name.
|
||||||
|
|
||||||
|
See `my-site-start-file-name-regex' for determining which files should be
|
||||||
|
loaded.
|
||||||
|
|
||||||
|
If both an `.el' and and `.elc' version of a file exists, only the newer
|
||||||
|
of the two is returned."
|
||||||
|
|
||||||
|
(message (if my-site-start-inhibit-p
|
||||||
|
(if (member dir load-path) "%s is already on load-path"
|
||||||
|
"Would add %s to load-path")
|
||||||
|
"Adding %s to load-path") dir)
|
||||||
|
(add-to-list 'load-path dir)
|
||||||
|
|
||||||
|
(let ((files (directory-files dir 'full-path nil ; no regex to filter on
|
||||||
|
'dont-sort))
|
||||||
|
(avoid-re
|
||||||
|
(concat "\\(\\`\\|/\\)"
|
||||||
|
"\\("
|
||||||
|
"\\.\\.?"
|
||||||
|
"\\|"
|
||||||
|
my-site-start-avoid-dir-regex
|
||||||
|
"\\)\\'") )
|
||||||
|
list file elc)
|
||||||
|
(save-match-data
|
||||||
|
(while files
|
||||||
|
(setq file (car files)
|
||||||
|
files (cdr files))
|
||||||
|
(cond
|
||||||
|
((file-directory-p file)
|
||||||
|
(or no-recursion
|
||||||
|
(string-match avoid-re file)
|
||||||
|
(setq list (append list (my-site-start-files file nil))) ) )
|
||||||
|
((string-match my-site-start-file-name-regex file)
|
||||||
|
(if (string-match "\\`\\(.*\\.el\\)c?\\'" file)
|
||||||
|
(setq file (match-string 1 file)
|
||||||
|
elc (concat file "c") )
|
||||||
|
(error "%s is neither .el nor .elc" file) )
|
||||||
|
(and (file-exists-p file)
|
||||||
|
(file-exists-p elc)
|
||||||
|
(file-newer-than-file-p elc file)
|
||||||
|
(setq file elc) )
|
||||||
|
(add-to-list 'list file) ) ) ) )
|
||||||
|
list) )
|
||||||
|
|
||||||
|
(defsubst my-site-start-split-filename (filename)
|
||||||
|
(if (string-match "\\(\\`\\|/\\)\\(\\([0-9][0-9]\\).*\\)\\.elc?\\'" filename)
|
||||||
|
(cons (string-to-number (match-string 3 filename))
|
||||||
|
(match-string 2 filename) )
|
||||||
|
(error "\"%s\" does not look like a valid .el/.elc file name" filename) ) )
|
||||||
|
(defun my-site-start-sort-load-order (list)
|
||||||
|
"Return the file names in LIST sorted numerically by basename.
|
||||||
|
|
||||||
|
This function assumes file names adhere to the convention of having a leading
|
||||||
|
numeric prefix to decide the load order, and will fail if this is not the
|
||||||
|
case."
|
||||||
|
(sort list
|
||||||
|
(function
|
||||||
|
(lambda (aa bb)
|
||||||
|
(save-match-data
|
||||||
|
(let ((a (my-site-start-split-filename aa))
|
||||||
|
(b (my-site-start-split-filename bb)))
|
||||||
|
(if (= (car a) (car b))
|
||||||
|
(string-lessp (cdr a) (cdr b))
|
||||||
|
(< (car a) (car b)) ) ) ))) ) )
|
||||||
|
|
||||||
|
|
||||||
|
(defun my-site-start-do-deferred-loads ()
|
||||||
|
"Load all files whose loading was deferred from `my-site-start'.
|
||||||
|
|
||||||
|
Load all files from the list `my-site-start--deferred-load-files'.
|
||||||
|
The value of `my-site-stat--deferred-load-files' is then set to nil.
|
||||||
|
|
||||||
|
The default `my-site-start-interactive-setup-hook' calls this function.
|
||||||
|
|
||||||
|
By convention, features which are only useful for interactive use should
|
||||||
|
be deferred, which in practice means they will only be loaded when Emacs
|
||||||
|
is started for interactive use \(and not, for example, from within a script,
|
||||||
|
say, to batch compile some Lisp files\).
|
||||||
|
|
||||||
|
Furthermore, the default `my-site-start-defer-file-p' function encodes the
|
||||||
|
convention that file names with a numeric prefix larger than 99 will be
|
||||||
|
deferred. See furthermore `my-site-start-defer-file-p-function' if you
|
||||||
|
wish to override this behavior."
|
||||||
|
(mapc #'my-site-start-load my-site-start--deferred-load-files)
|
||||||
|
(setq my-site-start--deferred-load-files nil) )
|
||||||
|
|
||||||
|
(defun my-site-start-defer-file-p (file)
|
||||||
|
"Return non-nil if FILE has a numeric prefix strictly bigger than 99.
|
||||||
|
|
||||||
|
This function is used as `my-site-start-defer-file-p-function' by default,
|
||||||
|
and implements the simple policy that a file name with a numeric prefix
|
||||||
|
larger than 99 names a file whose loading should be deferred."
|
||||||
|
(save-match-data
|
||||||
|
(string-match "\\`\\(.*/\\)?0*[1-9][0-9][0-9][^/]*\\'" file) ) )
|
||||||
|
|
||||||
|
|
||||||
|
(defvar my-site-start-interactive-setup-hook
|
||||||
|
(list (function my-site-start-do-deferred-loads))
|
||||||
|
"Hook run at the end of loading user's startup files, if running on a terminal.
|
||||||
|
|
||||||
|
This provides a facility for deferring loading of features which are only
|
||||||
|
useful in interactive use, but not e.g. when batch-compiling Elisp files.
|
||||||
|
|
||||||
|
By default, the hook runs `my-site-start-do-deferred-loads'.
|
||||||
|
|
||||||
|
Technically, this hook is run from `term-setup-hook' in turn.")
|
||||||
|
|
||||||
|
(add-hook 'term-setup-hook
|
||||||
|
'(lambda nil (run-hooks 'my-site-start-interactive-setup-hook)) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; This isn't really meant to be `require'd, but what the hey
|
||||||
|
|
||||||
|
(provide 'my-site-start)
|
||||||
|
|
||||||
|
;;; my-site-start.el ends here
|
||||||
1447
site-lisp/avy.el
Normal file
1447
site-lisp/avy.el
Normal file
File diff suppressed because it is too large
Load Diff
416
site-lisp/bind-key.el
Normal file
416
site-lisp/bind-key.el
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
;;; bind-key.el --- A simple way to manage personal keybindings
|
||||||
|
|
||||||
|
;; Copyright (c) 2012-2015 john wiegley
|
||||||
|
|
||||||
|
;; Author: John Wiegley <jwiegley@gmail.com>
|
||||||
|
;; Maintainer: John Wiegley <jwiegley@gmail.com>
|
||||||
|
;; Created: 16 Jun 2012
|
||||||
|
;; Version: 1.0
|
||||||
|
;; Keywords: keys keybinding config dotemacs
|
||||||
|
;; URL: https://github.com/jwiegley/use-package
|
||||||
|
|
||||||
|
;; 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 2, 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 gnu emacs; see the file copying. if not, write to the
|
||||||
|
;; free software foundation, inc., 59 temple place - suite 330,
|
||||||
|
;; boston, ma 02111-1307, usa.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; If you have lots of keybindings set in your .emacs file, it can be hard to
|
||||||
|
;; know which ones you haven't set yet, and which may now be overriding some
|
||||||
|
;; new default in a new emacs version. This module aims to solve that
|
||||||
|
;; problem.
|
||||||
|
;;
|
||||||
|
;; Bind keys as follows in your .emacs:
|
||||||
|
;;
|
||||||
|
;; (require 'bind-key)
|
||||||
|
;;
|
||||||
|
;; (bind-key "C-c x" 'my-ctrl-c-x-command)
|
||||||
|
;;
|
||||||
|
;; If you want the keybinding to override all minor modes that may also bind
|
||||||
|
;; the same key, use the `bind-key*' form:
|
||||||
|
;;
|
||||||
|
;; (bind-key* "<C-return>" 'other-window)
|
||||||
|
;;
|
||||||
|
;; If you want to rebind a key only in a particular keymap, use:
|
||||||
|
;;
|
||||||
|
;; (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
|
||||||
|
;;
|
||||||
|
;; To unbind a key within a keymap (for example, to stop your favorite major
|
||||||
|
;; mode from changing a binding that you don't want to override everywhere),
|
||||||
|
;; use `unbind-key':
|
||||||
|
;;
|
||||||
|
;; (unbind-key "C-c x" some-other-mode-map)
|
||||||
|
;;
|
||||||
|
;; To bind multiple keys at once, or set up a prefix map, a `bind-keys' macro
|
||||||
|
;; is provided. It accepts keyword arguments, please see its documentation
|
||||||
|
;; for a detailed description.
|
||||||
|
;;
|
||||||
|
;; To add keys into a specific map, use :map argument
|
||||||
|
;;
|
||||||
|
;; (bind-keys :map dired-mode-map
|
||||||
|
;; ("o" . dired-omit-mode)
|
||||||
|
;; ("a" . some-custom-dired-function))
|
||||||
|
;;
|
||||||
|
;; To set up a prefix map, use `:prefix-map' and `:prefix' arguments (both are
|
||||||
|
;; required)
|
||||||
|
;;
|
||||||
|
;; (bind-keys :prefix-map my-customize-prefix-map
|
||||||
|
;; :prefix "C-c c"
|
||||||
|
;; ("f" . customize-face)
|
||||||
|
;; ("v" . customize-variable))
|
||||||
|
;;
|
||||||
|
;; You can combine all the keywords together. Additionally,
|
||||||
|
;; `:prefix-docstring' can be specified to set documentation of created
|
||||||
|
;; `:prefix-map' variable.
|
||||||
|
;;
|
||||||
|
;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
|
||||||
|
;; will not be overridden by other modes), you may use `bind-keys*' macro:
|
||||||
|
;;
|
||||||
|
;; (bind-keys*
|
||||||
|
;; ("C-o" . other-window)
|
||||||
|
;; ("C-M-n" . forward-page)
|
||||||
|
;; ("C-M-p" . backward-page))
|
||||||
|
;;
|
||||||
|
;; After Emacs loads, you can see a summary of all your personal keybindings
|
||||||
|
;; currently in effect with this command:
|
||||||
|
;;
|
||||||
|
;; M-x describe-personal-keybindings
|
||||||
|
;;
|
||||||
|
;; This display will tell you if you've overriden a default keybinding, and
|
||||||
|
;; what the default was. Also, it will tell you if the key was rebound after
|
||||||
|
;; your binding it with `bind-key', and what it was rebound it to.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
(require 'easy-mmode)
|
||||||
|
|
||||||
|
(defgroup bind-key nil
|
||||||
|
"A simple way to manage personal keybindings"
|
||||||
|
:group 'emacs)
|
||||||
|
|
||||||
|
(defcustom bind-key-column-widths '(18 . 40)
|
||||||
|
"Width of columns in `describe-personal-keybindings'."
|
||||||
|
:type '(cons integer integer)
|
||||||
|
:group 'bind-key)
|
||||||
|
|
||||||
|
(defcustom bind-key-segregation-regexp
|
||||||
|
"\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
|
||||||
|
"Regular expression used to divide key sets in the output from
|
||||||
|
\\[describe-personal-keybindings]."
|
||||||
|
:type 'regexp
|
||||||
|
:group 'bind-key)
|
||||||
|
|
||||||
|
(defcustom bind-key-describe-special-forms nil
|
||||||
|
"If non-nil, extract docstrings from lambdas, closures and keymaps if possible."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'bind-key)
|
||||||
|
|
||||||
|
;; Create override-global-mode to force key remappings
|
||||||
|
|
||||||
|
(defvar override-global-map (make-keymap)
|
||||||
|
"override-global-mode keymap")
|
||||||
|
|
||||||
|
(define-minor-mode override-global-mode
|
||||||
|
"A minor mode so that keymap settings override other modes."
|
||||||
|
t "")
|
||||||
|
|
||||||
|
;; the keymaps in `emulation-mode-map-alists' take precedence over
|
||||||
|
;; `minor-mode-map-alist'
|
||||||
|
(add-to-list 'emulation-mode-map-alists
|
||||||
|
`((override-global-mode . ,override-global-map)))
|
||||||
|
|
||||||
|
(defvar personal-keybindings nil
|
||||||
|
"List of bindings performed by `bind-key'.
|
||||||
|
|
||||||
|
Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defmacro bind-key (key-name command &optional keymap predicate)
|
||||||
|
"Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
|
||||||
|
|
||||||
|
KEY-NAME may be a vector, in which case it is passed straight to
|
||||||
|
`define-key'. Or it may be a string to be interpreted as
|
||||||
|
spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of
|
||||||
|
`edmacro-mode' for details.
|
||||||
|
|
||||||
|
If PREDICATE is non-nil, it is a form evaluated to determine when
|
||||||
|
a key should be bound. It must return non-nil in such cases.
|
||||||
|
Emacs can evaluate this form at any time that it does redisplay
|
||||||
|
or operates on menu data structures, so you should write it so it
|
||||||
|
can safely be called at any time."
|
||||||
|
(let ((namevar (make-symbol "name"))
|
||||||
|
(keyvar (make-symbol "key"))
|
||||||
|
(kdescvar (make-symbol "kdesc"))
|
||||||
|
(bindingvar (make-symbol "binding")))
|
||||||
|
`(let* ((,namevar ,key-name)
|
||||||
|
(,keyvar (if (vectorp ,namevar) ,namevar
|
||||||
|
(read-kbd-macro ,namevar)))
|
||||||
|
(,kdescvar (cons (if (stringp ,namevar) ,namevar
|
||||||
|
(key-description ,namevar))
|
||||||
|
(quote ,keymap)))
|
||||||
|
(,bindingvar (lookup-key (or ,keymap global-map) ,keyvar)))
|
||||||
|
(add-to-list 'personal-keybindings
|
||||||
|
(list ,kdescvar ,command
|
||||||
|
(unless (numberp ,bindingvar) ,bindingvar)))
|
||||||
|
,(if predicate
|
||||||
|
`(define-key (or ,keymap global-map) ,keyvar
|
||||||
|
'(menu-item "" nil :filter (lambda (&optional _)
|
||||||
|
(when ,predicate
|
||||||
|
,command))))
|
||||||
|
`(define-key (or ,keymap global-map) ,keyvar ,command)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defmacro unbind-key (key-name &optional keymap)
|
||||||
|
"Unbind the given KEY-NAME, within the KEYMAP (if specified).
|
||||||
|
See `bind-key' for more details."
|
||||||
|
`(progn
|
||||||
|
(bind-key ,key-name nil ,keymap)
|
||||||
|
(setq personal-keybindings
|
||||||
|
(cl-delete-if #'(lambda (k)
|
||||||
|
,(if keymap
|
||||||
|
`(and (consp (car k))
|
||||||
|
(string= (caar k) ,key-name)
|
||||||
|
(eq (cdar k) ',keymap))
|
||||||
|
`(and (stringp (car k))
|
||||||
|
(string= (car k) ,key-name))))
|
||||||
|
personal-keybindings))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defmacro bind-key* (key-name command &optional predicate)
|
||||||
|
"Similar to `bind-key', but overrides any mode-specific bindings."
|
||||||
|
`(bind-key ,key-name ,command override-global-map ,predicate))
|
||||||
|
|
||||||
|
(defun bind-keys-form (args)
|
||||||
|
"Bind multiple keys at once.
|
||||||
|
|
||||||
|
Accepts keyword arguments:
|
||||||
|
:map MAP - a keymap into which the keybindings should be
|
||||||
|
added
|
||||||
|
:prefix KEY - prefix key for these bindings
|
||||||
|
:prefix-map MAP - name of the prefix map that should be created
|
||||||
|
for these bindings
|
||||||
|
:prefix-docstring STR - docstring for the prefix-map variable
|
||||||
|
:menu-name NAME - optional menu string for prefix map
|
||||||
|
:filter FORM - optional form to determine when bindings apply
|
||||||
|
|
||||||
|
The rest of the arguments are conses of keybinding string and a
|
||||||
|
function symbol (unquoted)."
|
||||||
|
;; jww (2016-02-26): This is a hack; this whole function needs to be
|
||||||
|
;; rewritten to normalize arguments the way that use-package.el does.
|
||||||
|
(if (and (eq (car args) :package)
|
||||||
|
(not (eq (car (cdr (cdr args))) :map)))
|
||||||
|
(setq args (cons :map (cons 'global-map args))))
|
||||||
|
(let* ((map (plist-get args :map))
|
||||||
|
(doc (plist-get args :prefix-docstring))
|
||||||
|
(prefix-map (plist-get args :prefix-map))
|
||||||
|
(prefix (plist-get args :prefix))
|
||||||
|
(filter (plist-get args :filter))
|
||||||
|
(menu-name (plist-get args :menu-name))
|
||||||
|
(pkg (plist-get args :package))
|
||||||
|
(key-bindings (progn
|
||||||
|
(while (keywordp (car args))
|
||||||
|
(pop args)
|
||||||
|
(pop args))
|
||||||
|
args)))
|
||||||
|
(when (or (and prefix-map (not prefix))
|
||||||
|
(and prefix (not prefix-map)))
|
||||||
|
(error "Both :prefix-map and :prefix must be supplied"))
|
||||||
|
(when (and menu-name (not prefix))
|
||||||
|
(error "If :menu-name is supplied, :prefix must be too"))
|
||||||
|
(let ((args key-bindings)
|
||||||
|
saw-map first next)
|
||||||
|
(while args
|
||||||
|
(if (keywordp (car args))
|
||||||
|
(progn
|
||||||
|
(setq next args)
|
||||||
|
(setq args nil))
|
||||||
|
(if first
|
||||||
|
(nconc first (list (car args)))
|
||||||
|
(setq first (list (car args))))
|
||||||
|
(setq args (cdr args))))
|
||||||
|
(cl-flet
|
||||||
|
((wrap (map bindings)
|
||||||
|
(if (and map pkg (not (eq map 'global-map)))
|
||||||
|
`((if (boundp ',map)
|
||||||
|
(progn ,@bindings)
|
||||||
|
(eval-after-load
|
||||||
|
,(if (symbolp pkg) `',pkg pkg)
|
||||||
|
'(progn ,@bindings))))
|
||||||
|
bindings)))
|
||||||
|
(append
|
||||||
|
(when prefix-map
|
||||||
|
`((defvar ,prefix-map)
|
||||||
|
,@(when doc `((put ',prefix-map 'variable-documentation ,doc)))
|
||||||
|
,@(if menu-name
|
||||||
|
`((define-prefix-command ',prefix-map nil ,menu-name))
|
||||||
|
`((define-prefix-command ',prefix-map)))
|
||||||
|
,@(if (and map (not (eq map 'global-map)))
|
||||||
|
(wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
|
||||||
|
`((bind-key ,prefix ',prefix-map nil ,filter)))))
|
||||||
|
(wrap map
|
||||||
|
(cl-mapcan
|
||||||
|
(lambda (form)
|
||||||
|
(if prefix-map
|
||||||
|
`((bind-key ,(car form) ',(cdr form) ,prefix-map ,filter))
|
||||||
|
(if (and map (not (eq map 'global-map)))
|
||||||
|
`((bind-key ,(car form) ',(cdr form) ,map ,filter))
|
||||||
|
`((bind-key ,(car form) ',(cdr form) nil ,filter)))))
|
||||||
|
first))
|
||||||
|
(when next
|
||||||
|
(bind-keys-form
|
||||||
|
(if pkg
|
||||||
|
(cons :package (cons pkg next))
|
||||||
|
next))))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defmacro bind-keys (&rest args)
|
||||||
|
"Bind multiple keys at once.
|
||||||
|
|
||||||
|
Accepts keyword arguments:
|
||||||
|
:map MAP - a keymap into which the keybindings should be
|
||||||
|
added
|
||||||
|
:prefix KEY - prefix key for these bindings
|
||||||
|
:prefix-map MAP - name of the prefix map that should be created
|
||||||
|
for these bindings
|
||||||
|
:prefix-docstring STR - docstring for the prefix-map variable
|
||||||
|
:menu-name NAME - optional menu string for prefix map
|
||||||
|
:filter FORM - optional form to determine when bindings apply
|
||||||
|
|
||||||
|
The rest of the arguments are conses of keybinding string and a
|
||||||
|
function symbol (unquoted)."
|
||||||
|
(macroexp-progn (bind-keys-form args)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defmacro bind-keys* (&rest args)
|
||||||
|
(macroexp-progn
|
||||||
|
(bind-keys-form `(:map override-global-map ,@args))))
|
||||||
|
|
||||||
|
(defun get-binding-description (elem)
|
||||||
|
(cond
|
||||||
|
((listp elem)
|
||||||
|
(cond
|
||||||
|
((eq 'lambda (car elem))
|
||||||
|
(if (and bind-key-describe-special-forms
|
||||||
|
(stringp (nth 2 elem)))
|
||||||
|
(nth 2 elem)
|
||||||
|
"#<lambda>"))
|
||||||
|
((eq 'closure (car elem))
|
||||||
|
(if (and bind-key-describe-special-forms
|
||||||
|
(stringp (nth 3 elem)))
|
||||||
|
(nth 3 elem)
|
||||||
|
"#<closure>"))
|
||||||
|
((eq 'keymap (car elem))
|
||||||
|
"#<keymap>")
|
||||||
|
(t
|
||||||
|
elem)))
|
||||||
|
;; must be a symbol, non-symbol keymap case covered above
|
||||||
|
((and bind-key-describe-special-forms (keymapp elem))
|
||||||
|
(let ((doc (get elem 'variable-documentation)))
|
||||||
|
(if (stringp doc) doc elem)))
|
||||||
|
((symbolp elem)
|
||||||
|
elem)
|
||||||
|
(t
|
||||||
|
"#<byte-compiled lambda>")))
|
||||||
|
|
||||||
|
(defun compare-keybindings (l r)
|
||||||
|
(let* ((regex bind-key-segregation-regexp)
|
||||||
|
(lgroup (and (string-match regex (caar l))
|
||||||
|
(match-string 0 (caar l))))
|
||||||
|
(rgroup (and (string-match regex (caar r))
|
||||||
|
(match-string 0 (caar r))))
|
||||||
|
(lkeymap (cdar l))
|
||||||
|
(rkeymap (cdar r)))
|
||||||
|
(cond
|
||||||
|
((and (null lkeymap) rkeymap)
|
||||||
|
(cons t t))
|
||||||
|
((and lkeymap (null rkeymap))
|
||||||
|
(cons nil t))
|
||||||
|
((and lkeymap rkeymap
|
||||||
|
(not (string= (symbol-name lkeymap) (symbol-name rkeymap))))
|
||||||
|
(cons (string< (symbol-name lkeymap) (symbol-name rkeymap)) t))
|
||||||
|
((and (null lgroup) rgroup)
|
||||||
|
(cons t t))
|
||||||
|
((and lgroup (null rgroup))
|
||||||
|
(cons nil t))
|
||||||
|
((and lgroup rgroup)
|
||||||
|
(if (string= lgroup rgroup)
|
||||||
|
(cons (string< (caar l) (caar r)) nil)
|
||||||
|
(cons (string< lgroup rgroup) t)))
|
||||||
|
(t
|
||||||
|
(cons (string< (caar l) (caar r)) nil)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun describe-personal-keybindings ()
|
||||||
|
"Display all the personal keybindings defined by `bind-key'."
|
||||||
|
(interactive)
|
||||||
|
(with-output-to-temp-buffer "*Personal Keybindings*"
|
||||||
|
(princ (format (concat "Key name%s Command%s Comments\n%s %s "
|
||||||
|
"---------------------\n")
|
||||||
|
(make-string (- (car bind-key-column-widths) 9) ? )
|
||||||
|
(make-string (- (cdr bind-key-column-widths) 8) ? )
|
||||||
|
(make-string (1- (car bind-key-column-widths)) ?-)
|
||||||
|
(make-string (1- (cdr bind-key-column-widths)) ?-)))
|
||||||
|
(let (last-binding)
|
||||||
|
(dolist (binding
|
||||||
|
(setq personal-keybindings
|
||||||
|
(sort personal-keybindings
|
||||||
|
(lambda (l r)
|
||||||
|
(car (compare-keybindings l r))))))
|
||||||
|
|
||||||
|
(if (not (eq (cdar last-binding) (cdar binding)))
|
||||||
|
(princ (format "\n\n%s\n%s\n\n"
|
||||||
|
(cdar binding)
|
||||||
|
(make-string (+ 21 (car bind-key-column-widths)
|
||||||
|
(cdr bind-key-column-widths)) ?-)))
|
||||||
|
(if (and last-binding
|
||||||
|
(cdr (compare-keybindings last-binding binding)))
|
||||||
|
(princ "\n")))
|
||||||
|
|
||||||
|
(let* ((key-name (caar binding))
|
||||||
|
(at-present (lookup-key (or (symbol-value (cdar binding))
|
||||||
|
(current-global-map))
|
||||||
|
(read-kbd-macro key-name)))
|
||||||
|
(command (nth 1 binding))
|
||||||
|
(was-command (nth 2 binding))
|
||||||
|
(command-desc (get-binding-description command))
|
||||||
|
(was-command-desc (and was-command
|
||||||
|
(get-binding-description was-command)))
|
||||||
|
(at-present-desc (get-binding-description at-present))
|
||||||
|
)
|
||||||
|
(let ((line
|
||||||
|
(format
|
||||||
|
(format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths)
|
||||||
|
(cdr bind-key-column-widths))
|
||||||
|
key-name (format "`%s\'" command-desc)
|
||||||
|
(if (string= command-desc at-present-desc)
|
||||||
|
(if (or (null was-command)
|
||||||
|
(string= command-desc was-command-desc))
|
||||||
|
""
|
||||||
|
(format "was `%s\'" was-command-desc))
|
||||||
|
(format "[now: `%s\']" at-present)))))
|
||||||
|
(princ (if (string-match "[ \t]+\n" line)
|
||||||
|
(replace-match "\n" t t line)
|
||||||
|
line))))
|
||||||
|
|
||||||
|
(setq last-binding binding)))))
|
||||||
|
|
||||||
|
(provide 'bind-key)
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
|
||||||
|
;; indent-tabs-mode: nil
|
||||||
|
;; End:
|
||||||
|
|
||||||
|
;;; bind-key.el ends here
|
||||||
585
site-lisp/boxquote.el
Normal file
585
site-lisp/boxquote.el
Normal file
@@ -0,0 +1,585 @@
|
|||||||
|
;;; boxquote.el --- Quote text with a semi-box.
|
||||||
|
;; Copyright 1999-2009 by Dave Pearson <davep@davep.org>
|
||||||
|
;; $Revision: 1.23 $
|
||||||
|
|
||||||
|
;; boxquote.el is free software distributed under the terms of the GNU
|
||||||
|
;; General Public Licence, version 2 or (at your option) any later version.
|
||||||
|
;; For details see the file COPYING.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; boxquote provides a set of functions for using a text quoting style that
|
||||||
|
;; partially boxes in the left hand side of an area of text, such a marking
|
||||||
|
;; style might be used to show externally included text or example code.
|
||||||
|
;;
|
||||||
|
;; ,----
|
||||||
|
;; | The default style looks like this.
|
||||||
|
;; `----
|
||||||
|
;;
|
||||||
|
;; A number of functions are provided for quoting a region, a buffer, a
|
||||||
|
;; paragraph and a defun. There are also functions for quoting text while
|
||||||
|
;; pulling it in, either by inserting the contents of another file or by
|
||||||
|
;; yanking text into the current buffer.
|
||||||
|
;;
|
||||||
|
;; The latest version of boxquote.el can be found at:
|
||||||
|
;;
|
||||||
|
;; <URL:http://www.davep.org/emacs/#boxquote.el>
|
||||||
|
|
||||||
|
;;; Thanks:
|
||||||
|
|
||||||
|
;; Kai Grossjohann for inspiring the idea of boxquote. I wrote this code to
|
||||||
|
;; mimic the "inclusion quoting" style in his Usenet posts. I could have
|
||||||
|
;; hassled him for his code but it was far more fun to write it myself.
|
||||||
|
;;
|
||||||
|
;; Mark Milhollan for providing a patch that helped me get the help quoting
|
||||||
|
;; functions working with XEmacs.
|
||||||
|
;;
|
||||||
|
;; Oliver Much for suggesting the idea of having a `boxquote-kill-ring-save'
|
||||||
|
;; function.
|
||||||
|
;;
|
||||||
|
;; Reiner Steib for suggesting `boxquote-where-is' and the idea of letting
|
||||||
|
;; `boxquote-describe-key' describe key bindings from other buffers. Also
|
||||||
|
;; thanks go to Reiner for suggesting `boxquote-insert-buffer'.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; Things we need:
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(require 'cl))
|
||||||
|
(require 'rect)
|
||||||
|
|
||||||
|
;; Attempt to handle older/other emacs.
|
||||||
|
(eval-and-compile
|
||||||
|
|
||||||
|
;; If customize isn't available just use defvar instead.
|
||||||
|
(unless (fboundp 'defgroup)
|
||||||
|
(defmacro defgroup (&rest rest) nil)
|
||||||
|
(defmacro defcustom (symbol init docstring &rest rest)
|
||||||
|
`(defvar ,symbol ,init ,docstring)))
|
||||||
|
|
||||||
|
;; If `line-beginning-position' isn't available provide one.
|
||||||
|
(unless (fboundp 'line-beginning-position)
|
||||||
|
(defun line-beginning-position (&optional n)
|
||||||
|
"Return the `point' of the beginning of the current line."
|
||||||
|
(save-excursion
|
||||||
|
(beginning-of-line n)
|
||||||
|
(point))))
|
||||||
|
|
||||||
|
;; If `line-end-position' isn't available provide one.
|
||||||
|
(unless (fboundp 'line-end-position)
|
||||||
|
(defun line-end-position (&optional n)
|
||||||
|
"Return the `point' of the end of the current line."
|
||||||
|
(save-excursion
|
||||||
|
(end-of-line n)
|
||||||
|
(point)))))
|
||||||
|
|
||||||
|
;; Customize options.
|
||||||
|
|
||||||
|
(defgroup boxquote nil
|
||||||
|
"Mark regions of text with a half-box."
|
||||||
|
:group 'editing
|
||||||
|
:prefix "boxquote-")
|
||||||
|
|
||||||
|
(defcustom boxquote-top-and-tail "----"
|
||||||
|
"*Text that will be used at the top and tail of the box."
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-top-corner ","
|
||||||
|
"*Text used for the top corner of the box."
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-bottom-corner "`"
|
||||||
|
"*Text used for the bottom corner of the box."
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-side "| "
|
||||||
|
"*Text used for the side of the box."
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-title-format "[ %s ]"
|
||||||
|
"*Format string to use when creating a box title."
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-title-files t
|
||||||
|
"*Should a `boxquote-insert-file' title the box with the file name?"
|
||||||
|
:type '(choice
|
||||||
|
(const :tag "Title the box with the file name" t)
|
||||||
|
(const :tag "Don't title the box with the file name" nil))
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-file-title-function #'file-name-nondirectory
|
||||||
|
"*Function to apply to a file's name when using it to title a box."
|
||||||
|
:type 'function
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-title-buffers t
|
||||||
|
"*Should a `boxquote-insert-buffer' title the box with the buffer name?"
|
||||||
|
:type '(choice
|
||||||
|
(const :tag "Title the box with the buffer name" t)
|
||||||
|
(const :tag "Don't title the box with the buffer name" nil))
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-buffer-title-function #'identity
|
||||||
|
"*Function to apply to a buffer's name when using it to title a box."
|
||||||
|
:type 'function
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-region-hook nil
|
||||||
|
"*Hooks to perform when on a region prior to boxquoting.
|
||||||
|
|
||||||
|
Note that all forms of boxquoting use `boxquote-region' to create the
|
||||||
|
boxquote. Because of this any hook you place here will be invoked by any of
|
||||||
|
the boxquoting functions."
|
||||||
|
:type 'hook
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-yank-hook nil
|
||||||
|
"*Hooks to perform on the yanked text prior to boxquoting."
|
||||||
|
:type 'hook
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-insert-file-hook nil
|
||||||
|
"*Hooks to perform on the text from an inserted file prior to boxquoting."
|
||||||
|
:type 'hook
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-kill-ring-save-title #'buffer-name
|
||||||
|
"*Function for working out the title for a `boxquote-kill-ring-save'.
|
||||||
|
|
||||||
|
The string returned from this function will be used as the title for a
|
||||||
|
boxquote when the saved text is yanked into a buffer with \\[boxquote-yank].
|
||||||
|
|
||||||
|
An example of a non-trivial value for this variable might be:
|
||||||
|
|
||||||
|
(lambda ()
|
||||||
|
(if (string= mode-name \"Article\")
|
||||||
|
(aref gnus-current-headers 4)
|
||||||
|
(buffer-name)))
|
||||||
|
|
||||||
|
In this case, if you are a `gnus' user, \\[boxquote-kill-ring-save] could be
|
||||||
|
used to copy text from an article buffer and, when it is yanked into another
|
||||||
|
buffer using \\[boxquote-yank], the title of the boxquote would be the ID of
|
||||||
|
the article you'd copied the text from."
|
||||||
|
:type 'function
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-describe-function-title-format "C-h f %s RET"
|
||||||
|
"*Format string to use when formatting a function description box title"
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-describe-variable-title-format "C-h v %s RET"
|
||||||
|
"*Format string to use when formatting a variable description box title"
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-describe-key-title-format "C-h k %s"
|
||||||
|
"*Format string to use when formatting a key description box title"
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-where-is-title-format "C-h w %s RET"
|
||||||
|
"*Format string to use when formatting a `where-is' description box title"
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
(defcustom boxquote-where-is-body-format "%s is on %s"
|
||||||
|
"*Format string to use when formatting a `where-is' description."
|
||||||
|
:type 'string
|
||||||
|
:group 'boxquote)
|
||||||
|
|
||||||
|
;; Main code:
|
||||||
|
|
||||||
|
(defun boxquote-xemacs-p ()
|
||||||
|
"Are we running in XEmacs?"
|
||||||
|
(and (boundp 'running-xemacs) (symbol-value 'running-xemacs)))
|
||||||
|
|
||||||
|
(defun boxquote-points ()
|
||||||
|
"Find the start and end points of a boxquote.
|
||||||
|
|
||||||
|
If `point' is inside a boxquote then a cons is returned, the `car' is the
|
||||||
|
start `point' and the `cdr' is the end `point'. NIL is returned if no
|
||||||
|
boxquote is found."
|
||||||
|
(save-excursion
|
||||||
|
(beginning-of-line)
|
||||||
|
(let* ((re-top (concat "^" (regexp-quote boxquote-top-corner)
|
||||||
|
(regexp-quote boxquote-top-and-tail)))
|
||||||
|
(re-left (concat "^" (regexp-quote boxquote-side)))
|
||||||
|
(re-bottom (concat "^" (regexp-quote boxquote-bottom-corner)
|
||||||
|
(regexp-quote boxquote-top-and-tail)))
|
||||||
|
(points
|
||||||
|
(cl-flet ((find-box-end (re &optional back)
|
||||||
|
(save-excursion
|
||||||
|
(when (if back
|
||||||
|
(search-backward-regexp re nil t)
|
||||||
|
(search-forward-regexp re nil t))
|
||||||
|
(point)))))
|
||||||
|
(cond ((looking-at re-top)
|
||||||
|
(cons (point) (find-box-end re-bottom)))
|
||||||
|
((looking-at re-left)
|
||||||
|
(cons (find-box-end re-top t) (find-box-end re-bottom)))
|
||||||
|
((looking-at re-bottom)
|
||||||
|
(cons (find-box-end re-top t) (line-end-position)))))))
|
||||||
|
(when (and (car points) (cdr points))
|
||||||
|
points))))
|
||||||
|
|
||||||
|
(defun boxquote-quoted-p ()
|
||||||
|
"Is `point' inside a boxquote?"
|
||||||
|
(not (null (boxquote-points))))
|
||||||
|
|
||||||
|
(defun boxquote-points-with-check ()
|
||||||
|
"Get the `boxquote-points' and flag an error of no box was found."
|
||||||
|
(or (boxquote-points) (error "I can't see a box here")))
|
||||||
|
|
||||||
|
(defun boxquote-title-format-as-regexp ()
|
||||||
|
"Return a regular expression to match the title."
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert (regexp-quote boxquote-title-format))
|
||||||
|
(setf (point) (point-min))
|
||||||
|
(when (search-forward "%s" nil t)
|
||||||
|
(replace-match ".*" nil t))
|
||||||
|
(buffer-string)))
|
||||||
|
|
||||||
|
(defun boxquote-get-title ()
|
||||||
|
"Get the title for the current boxquote."
|
||||||
|
(multiple-value-bind (prefix-len suffix-len)
|
||||||
|
(with-temp-buffer
|
||||||
|
(let ((look-for "%s"))
|
||||||
|
(insert boxquote-title-format)
|
||||||
|
(setf (point) (point-min))
|
||||||
|
(search-forward look-for)
|
||||||
|
(list (- (point) (length look-for) 1) (- (point-max) (point)))))
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(boxquote-narrow-to-boxquote)
|
||||||
|
(setf (point) (+ (point-min)
|
||||||
|
(length (concat boxquote-top-corner
|
||||||
|
boxquote-top-and-tail))))
|
||||||
|
(if (looking-at (boxquote-title-format-as-regexp))
|
||||||
|
(buffer-substring-no-properties (+ (point) prefix-len)
|
||||||
|
(- (line-end-position) suffix-len))
|
||||||
|
"")))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-title (title)
|
||||||
|
"Set the title of the current boxquote to TITLE.
|
||||||
|
|
||||||
|
If TITLE is an empty string the title is removed. Note that the title will
|
||||||
|
be formatted using `boxquote-title-format'."
|
||||||
|
(interactive (list (read-from-minibuffer "Title: " (boxquote-get-title))))
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(boxquote-narrow-to-boxquote)
|
||||||
|
(setf (point) (+ (point-min)
|
||||||
|
(length (concat boxquote-top-corner
|
||||||
|
boxquote-top-and-tail))))
|
||||||
|
(unless (eolp)
|
||||||
|
(kill-line))
|
||||||
|
(unless (zerop (length title))
|
||||||
|
(insert (format boxquote-title-format title))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-region (start end)
|
||||||
|
"Draw a box around the left hand side of a region bounding START and END."
|
||||||
|
(interactive "r")
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(cl-flet ((bol-at-p (n)
|
||||||
|
(setf (point) n)
|
||||||
|
(bolp))
|
||||||
|
(insert-corner (corner pre-break)
|
||||||
|
(insert (concat (if pre-break "\n" "")
|
||||||
|
corner boxquote-top-and-tail "\n"))))
|
||||||
|
(let ((break-start (not (bol-at-p start)))
|
||||||
|
(break-end (not (bol-at-p end))))
|
||||||
|
(narrow-to-region start end)
|
||||||
|
(run-hooks 'boxquote-region-hook)
|
||||||
|
(setf (point) (point-min))
|
||||||
|
(insert-corner boxquote-top-corner break-start)
|
||||||
|
(let ((start-point (line-beginning-position)))
|
||||||
|
(setf (point) (point-max))
|
||||||
|
(insert-corner boxquote-bottom-corner break-end)
|
||||||
|
(string-rectangle start-point
|
||||||
|
(progn
|
||||||
|
(setf (point) (point-max))
|
||||||
|
(forward-line -2)
|
||||||
|
(line-beginning-position))
|
||||||
|
boxquote-side)))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-buffer ()
|
||||||
|
"Apply `boxquote-region' to a whole buffer."
|
||||||
|
(interactive)
|
||||||
|
(boxquote-region (point-min) (point-max)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-insert-file (filename)
|
||||||
|
"Insert the contents of a file, boxed with `boxquote-region'.
|
||||||
|
|
||||||
|
If `boxquote-title-files' is non-nil the boxquote will be given a title that
|
||||||
|
is the result of applying `boxquote-file-title-function' to FILENAME."
|
||||||
|
(interactive "fInsert file: ")
|
||||||
|
(insert (with-temp-buffer
|
||||||
|
(insert-file-contents filename nil)
|
||||||
|
(run-hooks 'boxquote-insert-file-hook)
|
||||||
|
(boxquote-buffer)
|
||||||
|
(when boxquote-title-files
|
||||||
|
(boxquote-title (funcall boxquote-file-title-function filename)))
|
||||||
|
(buffer-string))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-insert-buffer (buffer)
|
||||||
|
"Insert the contents of a buffer, boxes with `boxquote-region'.
|
||||||
|
|
||||||
|
If `boxquote-title-buffers' is non-nil the boxquote will be given a title that
|
||||||
|
is the result of applying `boxquote-buffer-title-function' to BUFFER."
|
||||||
|
(interactive "bInsert Buffer: ")
|
||||||
|
(boxquote-text
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(buffer-substring-no-properties (point-min) (point-max))))
|
||||||
|
(when boxquote-title-buffers
|
||||||
|
(boxquote-title (funcall boxquote-buffer-title-function buffer))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-kill-ring-save ()
|
||||||
|
"Like `kill-ring-save' but remembers a title if possible.
|
||||||
|
|
||||||
|
The title is acquired by calling `boxquote-kill-ring-save-title'. The title
|
||||||
|
will be used by `boxquote-yank'."
|
||||||
|
(interactive)
|
||||||
|
(call-interactively #'kill-ring-save)
|
||||||
|
(setf (car kill-ring-yank-pointer)
|
||||||
|
(format "%S" (list
|
||||||
|
'boxquote-yank-marker
|
||||||
|
(funcall boxquote-kill-ring-save-title)
|
||||||
|
(car kill-ring-yank-pointer)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-yank ()
|
||||||
|
"Do a `yank' and box it in with `boxquote-region'.
|
||||||
|
|
||||||
|
If the yanked entry was placed on the kill ring with
|
||||||
|
`boxquote-kill-ring-save' the resulting boxquote will be titled with
|
||||||
|
whatever `boxquote-kill-ring-save-title' returned at the time."
|
||||||
|
(interactive)
|
||||||
|
(save-excursion
|
||||||
|
(insert (with-temp-buffer
|
||||||
|
(yank)
|
||||||
|
(setf (point) (point-min))
|
||||||
|
(let ((title
|
||||||
|
(let ((yanked (condition-case nil
|
||||||
|
(read (current-buffer))
|
||||||
|
(error nil))))
|
||||||
|
(when (listp yanked)
|
||||||
|
(when (eq (car yanked) 'boxquote-yank-marker)
|
||||||
|
(setf (buffer-string) (nth 2 yanked))
|
||||||
|
(nth 1 yanked))))))
|
||||||
|
(run-hooks 'boxquote-yank-hook)
|
||||||
|
(boxquote-buffer)
|
||||||
|
(when title
|
||||||
|
(boxquote-title title))
|
||||||
|
(buffer-string))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-defun ()
|
||||||
|
"Apply `boxquote-region' the current defun."
|
||||||
|
(interactive)
|
||||||
|
(mark-defun)
|
||||||
|
(boxquote-region (region-beginning) (region-end)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-paragraph ()
|
||||||
|
"Apply `boxquote-region' to the current paragraph."
|
||||||
|
(interactive)
|
||||||
|
(mark-paragraph)
|
||||||
|
(boxquote-region (region-beginning) (region-end)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-boxquote ()
|
||||||
|
"Apply `boxquote-region' to the current boxquote."
|
||||||
|
(interactive)
|
||||||
|
(let ((box (boxquote-points-with-check)))
|
||||||
|
(boxquote-region (car box) (1+ (cdr box)))))
|
||||||
|
|
||||||
|
(defun boxquote-help-buffer-name (item)
|
||||||
|
"Return the name of the help buffer associated with ITEM."
|
||||||
|
(if (boxquote-xemacs-p)
|
||||||
|
(loop for buffer in (symbol-value 'help-buffer-list)
|
||||||
|
when (string-match (concat "^*Help:.*`" item "'") buffer)
|
||||||
|
return buffer)
|
||||||
|
"*Help*"))
|
||||||
|
|
||||||
|
(defun boxquote-quote-help-buffer (help-call title-format item)
|
||||||
|
"Perform a help command and boxquote the output.
|
||||||
|
|
||||||
|
HELP-CALL is a function that calls the help command.
|
||||||
|
|
||||||
|
TITLE-FORMAT is the `format' string to use to product the boxquote title.
|
||||||
|
|
||||||
|
ITEM is a function for retrieving the item to get help on."
|
||||||
|
(let ((one-window-p (one-window-p)))
|
||||||
|
(boxquote-text
|
||||||
|
(save-window-excursion
|
||||||
|
(funcall help-call)
|
||||||
|
(with-current-buffer (boxquote-help-buffer-name (funcall item))
|
||||||
|
(buffer-substring-no-properties (point-min) (point-max)))))
|
||||||
|
(boxquote-title (format title-format (funcall item)))
|
||||||
|
(when one-window-p
|
||||||
|
(delete-other-windows))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-describe-function ()
|
||||||
|
"Call `describe-function' and boxquote the output into the current buffer."
|
||||||
|
(interactive)
|
||||||
|
(boxquote-quote-help-buffer
|
||||||
|
#'(lambda ()
|
||||||
|
(call-interactively #'describe-function))
|
||||||
|
boxquote-describe-function-title-format
|
||||||
|
#'(lambda ()
|
||||||
|
(car (if (boxquote-xemacs-p)
|
||||||
|
(symbol-value 'function-history)
|
||||||
|
minibuffer-history)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-describe-variable ()
|
||||||
|
"Call `describe-variable' and boxquote the output into the current buffer."
|
||||||
|
(interactive)
|
||||||
|
(boxquote-quote-help-buffer
|
||||||
|
#'(lambda ()
|
||||||
|
(call-interactively #'describe-variable))
|
||||||
|
boxquote-describe-variable-title-format
|
||||||
|
#'(lambda ()
|
||||||
|
(car (if (boxquote-xemacs-p)
|
||||||
|
(symbol-value 'variable-history)
|
||||||
|
minibuffer-history)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-describe-key (key)
|
||||||
|
"Call `describe-key' and boxquote the output into the current buffer.
|
||||||
|
|
||||||
|
If the call to this command is prefixed with \\[universal-argument] you will also be
|
||||||
|
prompted for a buffer. The key defintion used will be taken from that buffer."
|
||||||
|
(interactive "kDescribe key: ")
|
||||||
|
(let ((from-buffer (if current-prefix-arg
|
||||||
|
(read-buffer "Buffer: " (current-buffer) t)
|
||||||
|
(current-buffer))))
|
||||||
|
(let ((binding
|
||||||
|
(with-current-buffer from-buffer
|
||||||
|
(key-binding key))))
|
||||||
|
(if (or (null binding) (integerp binding))
|
||||||
|
(message "%s is undefined" (with-current-buffer from-buffer
|
||||||
|
(key-description key)))
|
||||||
|
(boxquote-quote-help-buffer
|
||||||
|
#'(lambda ()
|
||||||
|
(with-current-buffer from-buffer
|
||||||
|
(describe-key key)))
|
||||||
|
boxquote-describe-key-title-format
|
||||||
|
#'(lambda ()
|
||||||
|
(with-current-buffer from-buffer
|
||||||
|
(key-description key))))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-shell-command (command)
|
||||||
|
"Call `shell-command' with COMMAND and boxquote the output."
|
||||||
|
(interactive (list (read-from-minibuffer "Shell command: " nil nil nil 'shell-command-history)))
|
||||||
|
(boxquote-text (with-temp-buffer
|
||||||
|
(shell-command command t)
|
||||||
|
(buffer-string)))
|
||||||
|
(boxquote-title command))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-where-is (definition)
|
||||||
|
"Call `where-is' with DEFINITION and boxquote the result."
|
||||||
|
(interactive "CCommand: ")
|
||||||
|
(boxquote-text (with-temp-buffer
|
||||||
|
(where-is definition t)
|
||||||
|
(format boxquote-where-is-body-format definition (buffer-string))))
|
||||||
|
(boxquote-title (format boxquote-where-is-title-format definition)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-text (text)
|
||||||
|
"Insert TEXT, boxquoted."
|
||||||
|
(interactive "sText: ")
|
||||||
|
(save-excursion
|
||||||
|
(unless (bolp)
|
||||||
|
(insert "\n"))
|
||||||
|
(insert
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert text)
|
||||||
|
(boxquote-buffer)
|
||||||
|
(buffer-string)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-narrow-to-boxquote ()
|
||||||
|
"Narrow the buffer to the current boxquote."
|
||||||
|
(interactive)
|
||||||
|
(let ((box (boxquote-points-with-check)))
|
||||||
|
(narrow-to-region (car box) (cdr box))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-narrow-to-boxquote-content ()
|
||||||
|
"Narrow the buffer to the content of the current boxquote."
|
||||||
|
(interactive)
|
||||||
|
(let ((box (boxquote-points-with-check)))
|
||||||
|
(narrow-to-region (save-excursion
|
||||||
|
(setf (point) (car box))
|
||||||
|
(forward-line 1)
|
||||||
|
(point))
|
||||||
|
(save-excursion
|
||||||
|
(setf (point) (cdr box))
|
||||||
|
(line-beginning-position)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-kill ()
|
||||||
|
"Kill the boxquote and its contents."
|
||||||
|
(interactive)
|
||||||
|
(let ((box (boxquote-points-with-check)))
|
||||||
|
(kill-region (car box) (1+ (cdr box)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-fill-paragraph (arg)
|
||||||
|
"Perform a `fill-paragraph' inside a boxquote."
|
||||||
|
(interactive "P")
|
||||||
|
(if (boxquote-quoted-p)
|
||||||
|
(save-restriction
|
||||||
|
(boxquote-narrow-to-boxquote-content)
|
||||||
|
(let ((fill-prefix boxquote-side))
|
||||||
|
(fill-paragraph arg)))
|
||||||
|
(fill-paragraph arg)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-unbox-region (start end)
|
||||||
|
"Remove a box created with `boxquote-region'."
|
||||||
|
(interactive "r")
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(narrow-to-region start end)
|
||||||
|
(setf (point) (point-min))
|
||||||
|
(if (looking-at (concat "^" (regexp-quote boxquote-top-corner)
|
||||||
|
(regexp-quote boxquote-top-and-tail)))
|
||||||
|
(let ((ends (concat "^[" (regexp-quote boxquote-top-corner)
|
||||||
|
(regexp-quote boxquote-bottom-corner)
|
||||||
|
"]" boxquote-top-and-tail))
|
||||||
|
(lines (concat "^" (regexp-quote boxquote-side))))
|
||||||
|
(loop while (< (point) (point-max))
|
||||||
|
if (looking-at ends) do (kill-line t)
|
||||||
|
if (looking-at lines) do (delete-char 2)
|
||||||
|
do (forward-line)))
|
||||||
|
(error "I can't see a box here")))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun boxquote-unbox ()
|
||||||
|
"Remove the boxquote that contains `point'."
|
||||||
|
(interactive)
|
||||||
|
(let ((box (boxquote-points-with-check)))
|
||||||
|
(boxquote-unbox-region (car box) (1+ (cdr box)))))
|
||||||
|
|
||||||
|
(provide 'boxquote)
|
||||||
|
|
||||||
|
;;; boxquote.el ends here.
|
||||||
333
site-lisp/company-clang.el
Normal file
333
site-lisp/company-clang.el
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
;;; company-clang.el --- company-mode completion backend for Clang -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2011, 2013-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'company)
|
||||||
|
(require 'company-template)
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defgroup company-clang nil
|
||||||
|
"Completion backend for Clang."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defcustom company-clang-executable
|
||||||
|
(executable-find "clang")
|
||||||
|
"Location of clang executable."
|
||||||
|
:type 'file)
|
||||||
|
|
||||||
|
(defcustom company-clang-begin-after-member-access t
|
||||||
|
"When non-nil, automatic completion will start whenever the current
|
||||||
|
symbol is preceded by \".\", \"->\" or \"::\", ignoring
|
||||||
|
`company-minimum-prefix-length'.
|
||||||
|
|
||||||
|
If `company-begin-commands' is a list, it should include `c-electric-lt-gt'
|
||||||
|
and `c-electric-colon', for automatic completion right after \">\" and
|
||||||
|
\":\".")
|
||||||
|
|
||||||
|
(defcustom company-clang-arguments nil
|
||||||
|
"Additional arguments to pass to clang when completing.
|
||||||
|
Prefix files (-include ...) can be selected with `company-clang-set-prefix'
|
||||||
|
or automatically through a custom `company-clang-prefix-guesser'."
|
||||||
|
:type '(repeat (string :tag "Argument")))
|
||||||
|
|
||||||
|
(defcustom company-clang-prefix-guesser 'company-clang-guess-prefix
|
||||||
|
"A function to determine the prefix file for the current buffer."
|
||||||
|
:type '(function :tag "Guesser function" nil))
|
||||||
|
|
||||||
|
(defvar company-clang-modes '(c-mode c++-mode objc-mode)
|
||||||
|
"Major modes which clang may complete.")
|
||||||
|
|
||||||
|
(defcustom company-clang-insert-arguments t
|
||||||
|
"When non-nil, insert function arguments as a template after completion."
|
||||||
|
:type 'boolean
|
||||||
|
:package-version '(company . "0.8.0"))
|
||||||
|
|
||||||
|
;; prefix ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defvar company-clang--prefix nil)
|
||||||
|
|
||||||
|
(defsubst company-clang--guess-pch-file (file)
|
||||||
|
(let ((dir (directory-file-name (file-name-directory file))))
|
||||||
|
(when (equal (file-name-nondirectory dir) "Classes")
|
||||||
|
(setq dir (file-name-directory dir)))
|
||||||
|
(car (directory-files dir t "\\([^.]h\\|[^h]\\).pch\\'" t))))
|
||||||
|
|
||||||
|
(defsubst company-clang--file-substring (file beg end)
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert-file-contents-literally file nil beg end)
|
||||||
|
(buffer-string)))
|
||||||
|
|
||||||
|
(defun company-clang-guess-prefix ()
|
||||||
|
"Try to guess the prefix file for the current buffer."
|
||||||
|
;; Prefixes seem to be called .pch. Pre-compiled headers do, too.
|
||||||
|
;; So we look at the magic number to rule them out.
|
||||||
|
(let* ((file (company-clang--guess-pch-file buffer-file-name))
|
||||||
|
(magic-number (and file (company-clang--file-substring file 0 4))))
|
||||||
|
(unless (member magic-number '("CPCH" "gpch"))
|
||||||
|
file)))
|
||||||
|
|
||||||
|
(defun company-clang-set-prefix (&optional prefix)
|
||||||
|
"Use PREFIX as a prefix (-include ...) file for clang completion."
|
||||||
|
(interactive (let ((def (funcall company-clang-prefix-guesser)))
|
||||||
|
(unless (stringp def)
|
||||||
|
(setq def default-directory))
|
||||||
|
(list (read-file-name "Prefix file: "
|
||||||
|
(when def (file-name-directory def))
|
||||||
|
def t (when def (file-name-nondirectory def))))))
|
||||||
|
;; TODO: pre-compile?
|
||||||
|
(setq company-clang--prefix (and (stringp prefix)
|
||||||
|
(file-regular-p prefix)
|
||||||
|
prefix)))
|
||||||
|
|
||||||
|
;; Clean-up on exit.
|
||||||
|
(add-hook 'kill-emacs-hook 'company-clang-set-prefix)
|
||||||
|
|
||||||
|
;; parsing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; TODO: Handle Pattern (syntactic hints would be neat).
|
||||||
|
;; Do we ever see OVERLOAD (or OVERRIDE)?
|
||||||
|
(defconst company-clang--completion-pattern
|
||||||
|
"^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:]*\\)\\(?: : \\(.*\\)$\\)?$")
|
||||||
|
|
||||||
|
(defconst company-clang--error-buffer-name "*clang-error*")
|
||||||
|
|
||||||
|
(defun company-clang--lang-option ()
|
||||||
|
(if (eq major-mode 'objc-mode)
|
||||||
|
(if (string= "m" (file-name-extension buffer-file-name))
|
||||||
|
"objective-c" "objective-c++")
|
||||||
|
(substring (symbol-name major-mode) 0 -5)))
|
||||||
|
|
||||||
|
(defun company-clang--parse-output (prefix _objc)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let ((pattern (format company-clang--completion-pattern
|
||||||
|
(regexp-quote prefix)))
|
||||||
|
(case-fold-search nil)
|
||||||
|
lines match)
|
||||||
|
(while (re-search-forward pattern nil t)
|
||||||
|
(setq match (match-string-no-properties 1))
|
||||||
|
(unless (equal match "Pattern")
|
||||||
|
(save-match-data
|
||||||
|
(when (string-match ":" match)
|
||||||
|
(setq match (substring match 0 (match-beginning 0)))))
|
||||||
|
(let ((meta (match-string-no-properties 2)))
|
||||||
|
(when (and meta (not (string= match meta)))
|
||||||
|
(put-text-property 0 1 'meta
|
||||||
|
(company-clang--strip-formatting meta)
|
||||||
|
match)))
|
||||||
|
(push match lines)))
|
||||||
|
lines))
|
||||||
|
|
||||||
|
(defun company-clang--meta (candidate)
|
||||||
|
(get-text-property 0 'meta candidate))
|
||||||
|
|
||||||
|
(defun company-clang--annotation (candidate)
|
||||||
|
(let ((ann (company-clang--annotation-1 candidate)))
|
||||||
|
(if (not (and ann (string-prefix-p "(*)" ann)))
|
||||||
|
ann
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert ann)
|
||||||
|
(search-backward ")")
|
||||||
|
(let ((pt (1+ (point))))
|
||||||
|
(re-search-forward ".\\_>" nil t)
|
||||||
|
(delete-region pt (point)))
|
||||||
|
(buffer-string)))))
|
||||||
|
|
||||||
|
(defun company-clang--annotation-1 (candidate)
|
||||||
|
(let ((meta (company-clang--meta candidate)))
|
||||||
|
(cond
|
||||||
|
((null meta) nil)
|
||||||
|
((string-match "[^:]:[^:]" meta)
|
||||||
|
(substring meta (1+ (match-beginning 0))))
|
||||||
|
((string-match "(anonymous)" meta) nil)
|
||||||
|
((string-match "\\((.*)[ a-z]*\\'\\)" meta)
|
||||||
|
(let ((paren (match-beginning 1)))
|
||||||
|
(if (not (eq (aref meta (1- paren)) ?>))
|
||||||
|
(match-string 1 meta)
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert meta)
|
||||||
|
(goto-char paren)
|
||||||
|
(substring meta (1- (search-backward "<"))))))))))
|
||||||
|
|
||||||
|
(defun company-clang--strip-formatting (text)
|
||||||
|
(replace-regexp-in-string
|
||||||
|
"#]" " "
|
||||||
|
(replace-regexp-in-string "[<{[]#\\|#[>}]" "" text t)
|
||||||
|
t))
|
||||||
|
|
||||||
|
(defun company-clang--handle-error (res args)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let* ((buf (get-buffer-create company-clang--error-buffer-name))
|
||||||
|
(cmd (concat company-clang-executable " " (mapconcat 'identity args " ")))
|
||||||
|
(pattern (format company-clang--completion-pattern ""))
|
||||||
|
(err (if (re-search-forward pattern nil t)
|
||||||
|
(buffer-substring-no-properties (point-min)
|
||||||
|
(1- (match-beginning 0)))
|
||||||
|
;; Warn the user more aggressively if no match was found.
|
||||||
|
(message "clang failed with error %d:\n%s" res cmd)
|
||||||
|
(buffer-string))))
|
||||||
|
|
||||||
|
(with-current-buffer buf
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(erase-buffer)
|
||||||
|
(insert (current-time-string)
|
||||||
|
(format "\nclang failed with error %d:\n" res)
|
||||||
|
cmd "\n\n")
|
||||||
|
(insert err)
|
||||||
|
(setq buffer-read-only t)
|
||||||
|
(goto-char (point-min))))))
|
||||||
|
|
||||||
|
(defun company-clang--start-process (prefix callback &rest args)
|
||||||
|
(let ((objc (derived-mode-p 'objc-mode))
|
||||||
|
(buf (get-buffer-create "*clang-output*"))
|
||||||
|
;; Looks unnecessary in Emacs 25.1 and later.
|
||||||
|
(process-adaptive-read-buffering nil))
|
||||||
|
(if (get-buffer-process buf)
|
||||||
|
(funcall callback nil)
|
||||||
|
(with-current-buffer buf
|
||||||
|
(erase-buffer)
|
||||||
|
(setq buffer-undo-list t))
|
||||||
|
(let* ((process-connection-type nil)
|
||||||
|
(process (apply #'start-file-process "company-clang" buf
|
||||||
|
company-clang-executable args)))
|
||||||
|
(set-process-sentinel
|
||||||
|
process
|
||||||
|
(lambda (proc status)
|
||||||
|
(unless (string-match-p "hangup" status)
|
||||||
|
(funcall
|
||||||
|
callback
|
||||||
|
(let ((res (process-exit-status proc)))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(unless (eq 0 res)
|
||||||
|
(company-clang--handle-error res args))
|
||||||
|
;; Still try to get any useful input.
|
||||||
|
(company-clang--parse-output prefix objc)))))))
|
||||||
|
(unless (company-clang--auto-save-p)
|
||||||
|
(send-region process (point-min) (point-max))
|
||||||
|
(send-string process "\n")
|
||||||
|
(process-send-eof process))))))
|
||||||
|
|
||||||
|
(defsubst company-clang--build-location (pos)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char pos)
|
||||||
|
(format "%s:%d:%d"
|
||||||
|
(if (company-clang--auto-save-p) buffer-file-name "-")
|
||||||
|
(line-number-at-pos)
|
||||||
|
(1+ (length
|
||||||
|
(encode-coding-region
|
||||||
|
(line-beginning-position)
|
||||||
|
(point)
|
||||||
|
'utf-8
|
||||||
|
t))))))
|
||||||
|
|
||||||
|
(defsubst company-clang--build-complete-args (pos)
|
||||||
|
(append '("-fsyntax-only" "-Xclang" "-code-completion-macros")
|
||||||
|
(unless (company-clang--auto-save-p)
|
||||||
|
(list "-x" (company-clang--lang-option)))
|
||||||
|
company-clang-arguments
|
||||||
|
(when (stringp company-clang--prefix)
|
||||||
|
(list "-include" (expand-file-name company-clang--prefix)))
|
||||||
|
(list "-Xclang" (format "-code-completion-at=%s"
|
||||||
|
(company-clang--build-location pos)))
|
||||||
|
(list (if (company-clang--auto-save-p) buffer-file-name "-"))))
|
||||||
|
|
||||||
|
(defun company-clang--candidates (prefix callback)
|
||||||
|
(and (company-clang--auto-save-p)
|
||||||
|
(buffer-modified-p)
|
||||||
|
(basic-save-buffer))
|
||||||
|
(when (null company-clang--prefix)
|
||||||
|
(company-clang-set-prefix (or (funcall company-clang-prefix-guesser)
|
||||||
|
'none)))
|
||||||
|
(apply 'company-clang--start-process
|
||||||
|
prefix
|
||||||
|
callback
|
||||||
|
(company-clang--build-complete-args (- (point) (length prefix)))))
|
||||||
|
|
||||||
|
(defun company-clang--prefix ()
|
||||||
|
(if company-clang-begin-after-member-access
|
||||||
|
(company-grab-symbol-cons "\\.\\|->\\|::" 2)
|
||||||
|
(company-grab-symbol)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defconst company-clang-required-version 1.1)
|
||||||
|
|
||||||
|
(defvar company-clang--version nil)
|
||||||
|
|
||||||
|
(defun company-clang--auto-save-p ()
|
||||||
|
(< company-clang--version 2.9))
|
||||||
|
|
||||||
|
(defsubst company-clang-version ()
|
||||||
|
"Return the version of `company-clang-executable'."
|
||||||
|
(with-temp-buffer
|
||||||
|
(call-process company-clang-executable nil t nil "--version")
|
||||||
|
(goto-char (point-min))
|
||||||
|
(if (re-search-forward "clang\\(?: version \\|-\\)\\([0-9.]+\\)" nil t)
|
||||||
|
(let ((ver (string-to-number (match-string-no-properties 1))))
|
||||||
|
(if (> ver 100)
|
||||||
|
(/ ver 100)
|
||||||
|
ver))
|
||||||
|
0)))
|
||||||
|
|
||||||
|
(defun company-clang (command &optional arg &rest ignored)
|
||||||
|
"`company-mode' completion backend for Clang.
|
||||||
|
Clang is a parser for C and ObjC. Clang version 1.1 or newer is required.
|
||||||
|
|
||||||
|
Additional command line arguments can be specified in
|
||||||
|
`company-clang-arguments'. Prefix files (-include ...) can be selected
|
||||||
|
with `company-clang-set-prefix' or automatically through a custom
|
||||||
|
`company-clang-prefix-guesser'.
|
||||||
|
|
||||||
|
With Clang versions before 2.9, we have to save the buffer before
|
||||||
|
performing completion. With Clang 2.9 and later, buffer contents are
|
||||||
|
passed via standard input."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(cl-case command
|
||||||
|
(interactive (company-begin-backend 'company-clang))
|
||||||
|
(init (when (memq major-mode company-clang-modes)
|
||||||
|
(unless company-clang-executable
|
||||||
|
(error "Company found no clang executable"))
|
||||||
|
(setq company-clang--version (company-clang-version))
|
||||||
|
(when (< company-clang--version company-clang-required-version)
|
||||||
|
(error "Company requires clang version 1.1"))))
|
||||||
|
(prefix (and (memq major-mode company-clang-modes)
|
||||||
|
buffer-file-name
|
||||||
|
company-clang-executable
|
||||||
|
(not (company-in-string-or-comment))
|
||||||
|
(or (company-clang--prefix) 'stop)))
|
||||||
|
(candidates (cons :async
|
||||||
|
(lambda (cb) (company-clang--candidates arg cb))))
|
||||||
|
(meta (company-clang--meta arg))
|
||||||
|
(annotation (company-clang--annotation arg))
|
||||||
|
(post-completion (let ((anno (company-clang--annotation arg)))
|
||||||
|
(when (and company-clang-insert-arguments anno)
|
||||||
|
(insert anno)
|
||||||
|
(if (string-match "\\`:[^:]" anno)
|
||||||
|
(company-template-objc-templatify anno)
|
||||||
|
(company-template-c-like-templatify
|
||||||
|
(concat arg anno))))))))
|
||||||
|
|
||||||
|
(provide 'company-clang)
|
||||||
|
;;; company-clang.el ends here
|
||||||
214
site-lisp/company-template.el
Normal file
214
site-lisp/company-template.el
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
;;; company-template.el --- utility library for template expansion
|
||||||
|
|
||||||
|
;; Copyright (C) 2009, 2010, 2014-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
;; Author: Nikolaj Schumacher
|
||||||
|
|
||||||
|
;; This file is part of GNU Emacs.
|
||||||
|
|
||||||
|
;; GNU Emacs 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.
|
||||||
|
|
||||||
|
;; GNU Emacs 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defface company-template-field
|
||||||
|
'((((background dark)) (:background "yellow" :foreground "black"))
|
||||||
|
(((background light)) (:background "orange" :foreground "black")))
|
||||||
|
"Face used for editable text in template fields."
|
||||||
|
:group 'company)
|
||||||
|
|
||||||
|
(defvar company-template-nav-map
|
||||||
|
(let ((keymap (make-sparse-keymap)))
|
||||||
|
(define-key keymap [tab] 'company-template-forward-field)
|
||||||
|
(define-key keymap (kbd "TAB") 'company-template-forward-field)
|
||||||
|
keymap))
|
||||||
|
|
||||||
|
(defvar-local company-template--buffer-templates nil)
|
||||||
|
|
||||||
|
;; interactive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-templates-at (pos)
|
||||||
|
(let (os)
|
||||||
|
(dolist (o (overlays-at pos))
|
||||||
|
;; FIXME: Always return the whole list of templates?
|
||||||
|
;; We remove templates not at point after every command.
|
||||||
|
(when (memq o company-template--buffer-templates)
|
||||||
|
(push o os)))
|
||||||
|
os))
|
||||||
|
|
||||||
|
(defun company-template-move-to-first (templ)
|
||||||
|
(interactive)
|
||||||
|
(goto-char (overlay-start templ))
|
||||||
|
(company-template-forward-field))
|
||||||
|
|
||||||
|
(defun company-template-forward-field ()
|
||||||
|
(interactive)
|
||||||
|
(let* ((start (point))
|
||||||
|
(templates (company-template-templates-at (point)))
|
||||||
|
(minimum (apply 'max (mapcar 'overlay-end templates)))
|
||||||
|
(fields (cl-loop for templ in templates
|
||||||
|
append (overlay-get templ 'company-template-fields))))
|
||||||
|
(dolist (pos (mapcar 'overlay-start fields))
|
||||||
|
(and pos
|
||||||
|
(> pos (point))
|
||||||
|
(< pos minimum)
|
||||||
|
(setq minimum pos)))
|
||||||
|
(push-mark)
|
||||||
|
(goto-char minimum)
|
||||||
|
(company-template-remove-field (company-template-field-at start))))
|
||||||
|
|
||||||
|
(defun company-template-field-at (&optional point)
|
||||||
|
(cl-loop for ovl in (overlays-at (or point (point)))
|
||||||
|
when (overlay-get ovl 'company-template-parent)
|
||||||
|
return ovl))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-declare-template (beg end)
|
||||||
|
(let ((ov (make-overlay beg end)))
|
||||||
|
;; (overlay-put ov 'face 'highlight)
|
||||||
|
(overlay-put ov 'keymap company-template-nav-map)
|
||||||
|
(overlay-put ov 'priority 101)
|
||||||
|
(overlay-put ov 'evaporate t)
|
||||||
|
(push ov company-template--buffer-templates)
|
||||||
|
(add-hook 'post-command-hook 'company-template-post-command nil t)
|
||||||
|
ov))
|
||||||
|
|
||||||
|
(defun company-template-remove-template (templ)
|
||||||
|
(mapc 'company-template-remove-field
|
||||||
|
(overlay-get templ 'company-template-fields))
|
||||||
|
(setq company-template--buffer-templates
|
||||||
|
(delq templ company-template--buffer-templates))
|
||||||
|
(delete-overlay templ))
|
||||||
|
|
||||||
|
(defun company-template-add-field (templ beg end &optional display)
|
||||||
|
"Add new field to template TEMPL spanning from BEG to END.
|
||||||
|
When DISPLAY is non-nil, set the respective property on the overlay.
|
||||||
|
Leave point at the end of the field."
|
||||||
|
(cl-assert templ)
|
||||||
|
(when (> end (overlay-end templ))
|
||||||
|
(move-overlay templ (overlay-start templ) end))
|
||||||
|
(let ((ov (make-overlay beg end))
|
||||||
|
(siblings (overlay-get templ 'company-template-fields)))
|
||||||
|
;; (overlay-put ov 'evaporate t)
|
||||||
|
(overlay-put ov 'intangible t)
|
||||||
|
(overlay-put ov 'face 'company-template-field)
|
||||||
|
(when display
|
||||||
|
(overlay-put ov 'display display))
|
||||||
|
(overlay-put ov 'company-template-parent templ)
|
||||||
|
(overlay-put ov 'insert-in-front-hooks '(company-template-insert-hook))
|
||||||
|
(push ov siblings)
|
||||||
|
(overlay-put templ 'company-template-fields siblings)))
|
||||||
|
|
||||||
|
(defun company-template-remove-field (ovl &optional clear)
|
||||||
|
(when (overlayp ovl)
|
||||||
|
(when (overlay-buffer ovl)
|
||||||
|
(when clear
|
||||||
|
(delete-region (overlay-start ovl) (overlay-end ovl)))
|
||||||
|
(delete-overlay ovl))
|
||||||
|
(let* ((templ (overlay-get ovl 'company-template-parent))
|
||||||
|
(siblings (overlay-get templ 'company-template-fields)))
|
||||||
|
(setq siblings (delq ovl siblings))
|
||||||
|
(overlay-put templ 'company-template-fields siblings))))
|
||||||
|
|
||||||
|
(defun company-template-clean-up (&optional pos)
|
||||||
|
"Clean up all templates that don't contain POS."
|
||||||
|
(let ((local-ovs (overlays-at (or pos (point)))))
|
||||||
|
(dolist (templ company-template--buffer-templates)
|
||||||
|
(unless (memq templ local-ovs)
|
||||||
|
(company-template-remove-template templ)))))
|
||||||
|
|
||||||
|
;; hooks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-insert-hook (ovl after-p &rest _ignore)
|
||||||
|
"Called when a snippet input prompt is modified."
|
||||||
|
(unless after-p
|
||||||
|
(company-template-remove-field ovl t)))
|
||||||
|
|
||||||
|
(defun company-template-post-command ()
|
||||||
|
(company-template-clean-up)
|
||||||
|
(unless company-template--buffer-templates
|
||||||
|
(remove-hook 'post-command-hook 'company-template-post-command t)))
|
||||||
|
|
||||||
|
;; common ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-c-like-templatify (call)
|
||||||
|
(let* ((end (point-marker))
|
||||||
|
(beg (- (point) (length call)))
|
||||||
|
(templ (company-template-declare-template beg end))
|
||||||
|
paren-open paren-close)
|
||||||
|
(with-syntax-table (make-syntax-table (syntax-table))
|
||||||
|
(modify-syntax-entry ?< "(")
|
||||||
|
(modify-syntax-entry ?> ")")
|
||||||
|
(when (search-backward ")" beg t)
|
||||||
|
(setq paren-close (point-marker))
|
||||||
|
(forward-char 1)
|
||||||
|
(delete-region (point) end)
|
||||||
|
(backward-sexp)
|
||||||
|
(forward-char 1)
|
||||||
|
(setq paren-open (point-marker)))
|
||||||
|
(when (search-backward ">" beg t)
|
||||||
|
(let ((angle-close (point-marker)))
|
||||||
|
(forward-char 1)
|
||||||
|
(backward-sexp)
|
||||||
|
(forward-char)
|
||||||
|
(company-template--c-like-args templ angle-close)))
|
||||||
|
(when (looking-back "\\((\\*)\\)(" (line-beginning-position))
|
||||||
|
(delete-region (match-beginning 1) (match-end 1)))
|
||||||
|
(when paren-open
|
||||||
|
(goto-char paren-open)
|
||||||
|
(company-template--c-like-args templ paren-close)))
|
||||||
|
(if (overlay-get templ 'company-template-fields)
|
||||||
|
(company-template-move-to-first templ)
|
||||||
|
(company-template-remove-template templ)
|
||||||
|
(goto-char end))))
|
||||||
|
|
||||||
|
(defun company-template--c-like-args (templ end)
|
||||||
|
(let ((last-pos (point)))
|
||||||
|
(while (re-search-forward "\\([^,]+\\),?" end 'move)
|
||||||
|
(when (zerop (car (parse-partial-sexp last-pos (point))))
|
||||||
|
(company-template-add-field templ last-pos (match-end 1))
|
||||||
|
(skip-chars-forward " ")
|
||||||
|
(setq last-pos (point))))))
|
||||||
|
|
||||||
|
;; objc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun company-template-objc-templatify (selector)
|
||||||
|
(let* ((end (point-marker))
|
||||||
|
(beg (- (point) (length selector) 1))
|
||||||
|
(templ (company-template-declare-template beg end))
|
||||||
|
(cnt 0))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char beg)
|
||||||
|
(catch 'stop
|
||||||
|
(while (search-forward ":" end t)
|
||||||
|
(if (looking-at "\\(([^)]*)\\) ?")
|
||||||
|
(company-template-add-field templ (point) (match-end 1))
|
||||||
|
;; Not sure which conditions this case manifests under, but
|
||||||
|
;; apparently it did before, when I wrote the first test for this
|
||||||
|
;; function. FIXME: Revisit it.
|
||||||
|
(company-template-add-field templ (point)
|
||||||
|
(progn
|
||||||
|
(insert (format "arg%d" cnt))
|
||||||
|
(point)))
|
||||||
|
(when (< (point) end)
|
||||||
|
(insert " "))
|
||||||
|
(cl-incf cnt))
|
||||||
|
(when (>= (point) end)
|
||||||
|
(throw 'stop t)))))
|
||||||
|
(company-template-move-to-first templ)))
|
||||||
|
|
||||||
|
(provide 'company-template)
|
||||||
|
;;; company-template.el ends here
|
||||||
372
site-lisp/key-chord.el
Normal file
372
site-lisp/key-chord.el
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
;;; key-chord.el --- map pairs of simultaneously pressed keys to commands
|
||||||
|
;;-------------------------------------------------------------------
|
||||||
|
;;
|
||||||
|
;; Copyright (C) 2003,2005,2008,2012 David Andersson
|
||||||
|
;;
|
||||||
|
;; This file is NOT part of 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 2 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, write to the Free
|
||||||
|
;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
;; MA 02111-1307 USA
|
||||||
|
;;
|
||||||
|
;;-------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; Author: David Andersson <l.david.andersson(at)sverige.nu>
|
||||||
|
;; Created: 27 April 2003
|
||||||
|
;; Version: 0.6 (2012-10-23)
|
||||||
|
;; Keywords: keyboard chord input
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; ######## Compatibility ########################################
|
||||||
|
;;
|
||||||
|
;; Works with Emacs-20.3, 20.6, 20.7, 21.2, 21.4, 22.1 and 23.1
|
||||||
|
;; Does not work with Emacs-19.31 nor XEmacs-20.4 and 21.4.
|
||||||
|
|
||||||
|
;; ######## Quick start ########################################
|
||||||
|
;;
|
||||||
|
;; Add to your ~/.emacs
|
||||||
|
;;
|
||||||
|
;; (require 'key-chord)
|
||||||
|
;; (key-chord-mode 1)
|
||||||
|
;;
|
||||||
|
;; and some chords, for example
|
||||||
|
;;
|
||||||
|
;; (key-chord-define-global "hj" 'undo)
|
||||||
|
;; (key-chord-define-global ",." "<>\C-b")
|
||||||
|
|
||||||
|
;; ######## Terminology ########################################
|
||||||
|
;;
|
||||||
|
;; In this package, a "key chord" is two keys pressed simultaneously,
|
||||||
|
;; or a single key quickly pressed twice.
|
||||||
|
;;
|
||||||
|
;; (Sometimes pressing SHIFT and/or META plus another key is call a chord,
|
||||||
|
;; but not here. However SHIFT plus two normal keys can be a "key chord".)
|
||||||
|
|
||||||
|
;; ######## Description ########################################
|
||||||
|
;;
|
||||||
|
;; Key chord mode acts like a global minor mode controlled by the function
|
||||||
|
;; `key-chord-mode'.
|
||||||
|
;;
|
||||||
|
;; Key chord definitions are stored in ordinary key-maps.
|
||||||
|
;; The function `key-chord-define-global' defines a chord in the global
|
||||||
|
;; key-map and `key-chord-define' defines a chord in a specified key-map,
|
||||||
|
;; for example for a specific mode.
|
||||||
|
;;
|
||||||
|
;; A TWO-key chord is two distinct keys pressed simultaneously (within
|
||||||
|
;; one tenth of a second, or so).
|
||||||
|
;;
|
||||||
|
;; Examples:
|
||||||
|
;;
|
||||||
|
;; (key-chord-define-global ",." "<>\C-b")
|
||||||
|
;; (key-chord-define-global "hj" 'undo)
|
||||||
|
;; (key-chord-define-global [?h ?j] 'undo) ; the same
|
||||||
|
;; (key-chord-define-global "jk" 'dabbrev-expand)
|
||||||
|
;; (key-chord-define-global "cv" 'reindent-then-newline-and-indent)
|
||||||
|
;; (key-chord-define-global "4r" "$")
|
||||||
|
;;
|
||||||
|
;; Comma and dot pressed together insert a pair of angle brackets.
|
||||||
|
;; `h' and `j' pressed together invoke the undo command.
|
||||||
|
;; `j' and `k' pressed together invoke the dabbrev-expand command.
|
||||||
|
;; 'c' and 'v' pressed together insert a newline.
|
||||||
|
;; `4' and `r' pressed together insert a dollar sign.
|
||||||
|
;;
|
||||||
|
;; A ONE-key chord is a single key quickly pressed twice (within one third
|
||||||
|
;; of a second or so).
|
||||||
|
;;
|
||||||
|
;; Examples:
|
||||||
|
;;
|
||||||
|
;; (key-chord-define-global "''" "`'\C-b")
|
||||||
|
;; (key-chord-define-global ",," 'indent-for-comment)
|
||||||
|
;; (key-chord-define-global "qq" "the ")
|
||||||
|
;; (key-chord-define-global "QQ" "The ")
|
||||||
|
;;
|
||||||
|
;; Tick (') pressed twice inserts a back-tick and a tick (`').
|
||||||
|
;; Comma (,) pressed twice indents for and/or inserts a comment.
|
||||||
|
;; `q' pressed twice inserts the word "the ".
|
||||||
|
;;
|
||||||
|
;; Examples: Mode specific chords
|
||||||
|
;;
|
||||||
|
;; (key-chord-define c++-mode-map ";;" "\C-e;")
|
||||||
|
;; (key-chord-define c++-mode-map "{}" "{\n\n}\C-p\t")
|
||||||
|
;;
|
||||||
|
;; The command `key-chord-describe' lists currently defined key chords.
|
||||||
|
;; The standard command `describe-bindings' (C-h b) will also show key chords.
|
||||||
|
;;
|
||||||
|
;; The standard command `describe-key' (C-h k) will accept a key chord and
|
||||||
|
;; show its definition. (Isn't that amazing. There is no explicit code to
|
||||||
|
;; carry out this functionality.)
|
||||||
|
|
||||||
|
;; ######## Tips ########################################
|
||||||
|
;;
|
||||||
|
;; Don't chord key combinations that exists in the languages you typically
|
||||||
|
;; write. Otherwise, if you are typing fast, two key intended to be separate
|
||||||
|
;; letters might instead trig a chord.
|
||||||
|
;; E.g. "uu" would be a good chord in spanish but not in finnish, and
|
||||||
|
;; "hj" would be a good chord in english but not in swedish.
|
||||||
|
;;
|
||||||
|
;; Don't rely solely on /usr/dict/words to find unusual combination.
|
||||||
|
;; For example "cv" or "fg" can be quite common in certain kinds of
|
||||||
|
;; programming. Grep your own texts to verify that a combination is unusual.
|
||||||
|
;; And don't forget to check both permutations: "fg" and "gf".
|
||||||
|
;;
|
||||||
|
;; Choose two keys that are close to each other on the keyboard, so they
|
||||||
|
;; can be quickly typed without effort. Chords involving two hands (as
|
||||||
|
;; opposed to two fingers on one hand) are harder to type (quickly).
|
||||||
|
;; The idea is that key chords are to replace function keys for functions
|
||||||
|
;; that are frequently performed while the hands are in writing position.
|
||||||
|
;;
|
||||||
|
;; Key chords might not work well over a slow network.
|
||||||
|
|
||||||
|
;; ######## Limitations ########################################
|
||||||
|
;;
|
||||||
|
;; When recording keyboard macros, the time between keyboard inputs are not
|
||||||
|
;; recorded. Thus, the key-chord-input-method cannot know for sure if two keys
|
||||||
|
;; in a macro was a chord or not. The current solution remembers the first key
|
||||||
|
;; of the chords typed during macro recording, and keys that match those (and
|
||||||
|
;; are defined as chords) are considered key-chords during macro execution.
|
||||||
|
;; This knowledge is not saved with `name-last-kbd-macro', so they may
|
||||||
|
;; execute wrong if they contain pair of keys that match defined chords.
|
||||||
|
;;
|
||||||
|
;; Emacs will not call input-method-function for keys that have non numeric
|
||||||
|
;; codes or whos code is outside the range 32..126. Thus you cannot define
|
||||||
|
;; key chords involving function keys, control keys, or even your non-english
|
||||||
|
;; letters (on national keyboards) that otherwise are well positioned for
|
||||||
|
;; chording on your keyboard.
|
||||||
|
;; (I think chording left and right arrow keys would be useful, but cannot do.
|
||||||
|
;; I consider this a bug in Emacs. Input methods could happily return
|
||||||
|
;; unmodified *any* key they don't know about.)
|
||||||
|
;;
|
||||||
|
;; Key chords longer that 2 keys are not supported. It could be done, but I
|
||||||
|
;; don't think it is worth the trubbel since most keyboards will not reliably
|
||||||
|
;; send all key codes when 3 or more keys are pressed simultaneously.
|
||||||
|
;; It might also be a bit trickier to maintain performance.
|
||||||
|
;;
|
||||||
|
;; Key chord mode uses input-method-function. And so do internationalisation
|
||||||
|
;; packages (mule, quail, etc). Do not expect them to work well together.
|
||||||
|
;; The last one that gets the input-method-function rules.
|
||||||
|
|
||||||
|
;; ######## Implementation ########################################
|
||||||
|
;;
|
||||||
|
;; Key chords piggy back in ordinary key maps, so they can be defined
|
||||||
|
;; per mode without having to add hooks to all modes.
|
||||||
|
;;
|
||||||
|
;; Key chord key codes are vectors beginning with the atom `key-chord'.
|
||||||
|
;; A two key chord, e.g. "hj", will add two entries in the key-map.
|
||||||
|
;; E.g. [key-chord ?h ?j] and [key-chord ?j ?h].
|
||||||
|
;;
|
||||||
|
;; When key-chord-mode is enabled input-method-function is set to
|
||||||
|
;; key-chord-input-method.
|
||||||
|
|
||||||
|
;; ######## To do ########################################
|
||||||
|
;;
|
||||||
|
;; * Find a way to save key-chord info in keyboard macros.
|
||||||
|
;;
|
||||||
|
;; * Save previous value of input-method-function? And call it?
|
||||||
|
;;
|
||||||
|
;; * input-method-function is reset in *info* buffers! What to do?
|
||||||
|
;;
|
||||||
|
;; * How to enter interactively command OR string in key-chord-define-global?
|
||||||
|
;;
|
||||||
|
;; * Customize public vars (defcustom).
|
||||||
|
|
||||||
|
;; ######## History ########################################
|
||||||
|
;;
|
||||||
|
;; 0.6 (2012-10-23) l.david.andersson(at)sverige.nu
|
||||||
|
;; Add key-chord-define-local, key-chord-unset-local, key-chord-unset-global
|
||||||
|
;; 0.5 (2008-09-15) david(at)symsoft.se
|
||||||
|
;; Bugfix sit-for; Improved examples; New E-mail in comment
|
||||||
|
;; 0.4 (2005-05-07) david(at)symsoft.se
|
||||||
|
;; Slightly better macro heuristics; Added option key-chord-in-macros
|
||||||
|
;; 0.3 (2005-04-14) david(at)symsoft.se
|
||||||
|
;; Require advice; More examples
|
||||||
|
;; 0.2 (2003-09-13) david(at)symsoft.se
|
||||||
|
;; Quick and dirty fix for keyboard macros
|
||||||
|
;; 0.1 (2003-04-27) david(at)symsoft.se
|
||||||
|
;; First release
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(defvar key-chord-two-keys-delay 0.1 ; 0.05 or 0.1
|
||||||
|
"Max time delay between two key press to be considered a key chord.")
|
||||||
|
|
||||||
|
(defvar key-chord-one-key-delay 0.2 ; 0.2 or 0.3 to avoid first autorepeat
|
||||||
|
"Max time delay between two press of the same key to be considered a key chord.
|
||||||
|
This should normally be a little longer than `key-chord-two-keys-delay'.")
|
||||||
|
|
||||||
|
(defvar key-chord-in-macros t
|
||||||
|
"If nil, don't expand key chords when executing keyboard macros.
|
||||||
|
If non-nil, expand chord sequenses in macros, but only if a similar chord was
|
||||||
|
entered during the last interactive macro recording. (This carries a bit of
|
||||||
|
guesswork. We can't know for sure when executing whether two keys were
|
||||||
|
typed quickly or slowly when recorded.)")
|
||||||
|
|
||||||
|
;; Internal vars
|
||||||
|
(defvar key-chord-mode nil)
|
||||||
|
|
||||||
|
;; Shortcut for key-chord-input-method: no need to test a key again if it
|
||||||
|
;; didn't matched a chord the last time. Improves feedback during autorepeat.
|
||||||
|
(defvar key-chord-last-unmatched nil)
|
||||||
|
|
||||||
|
;; Macro heuristics: Keep track of which chords was used when the last macro
|
||||||
|
;; was defined. Or rather, only the first-char of the chords. Only expand
|
||||||
|
;; matching chords during macro execution.
|
||||||
|
(defvar key-chord-in-last-kbd-macro nil)
|
||||||
|
(defvar key-chord-defining-kbd-macro nil)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun key-chord-mode (arg)
|
||||||
|
"Toggle key chord mode.
|
||||||
|
With positive ARG enable the mode. With zero or negative arg disable the mode.
|
||||||
|
A key chord is two keys that are pressed simultaneously, or one key quickly
|
||||||
|
pressed twice.
|
||||||
|
\nSee functions `key-chord-define-global', `key-chord-define-local', and
|
||||||
|
`key-chord-define' and variables `key-chord-two-keys-delay' and
|
||||||
|
`key-chord-one-key-delay'."
|
||||||
|
|
||||||
|
(interactive "P")
|
||||||
|
(setq key-chord-mode (if arg
|
||||||
|
(> (prefix-numeric-value arg) 0)
|
||||||
|
(not key-chord-mode)))
|
||||||
|
(cond (key-chord-mode
|
||||||
|
(setq input-method-function 'key-chord-input-method)
|
||||||
|
(message "Key Chord mode on"))
|
||||||
|
(t
|
||||||
|
(setq input-method-function nil)
|
||||||
|
(message "Key Chord mode off"))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun key-chord-define-global (keys command)
|
||||||
|
"Define a key-chord of the two keys in KEYS starting a COMMAND.
|
||||||
|
\nKEYS can be a string or a vector of two elements. Currently only elements
|
||||||
|
that corresponds to ascii codes in the range 32 to 126 can be used.
|
||||||
|
\nCOMMAND can be an interactive function, a string, or nil.
|
||||||
|
If COMMAND is nil, the key-chord is removed.
|
||||||
|
\nNote that KEYS defined locally in the current buffer will have precedence."
|
||||||
|
(interactive "sSet key chord globally (2 keys): \nCSet chord \"%s\" to command: ")
|
||||||
|
(key-chord-define (current-global-map) keys command))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun key-chord-define-local (keys command)
|
||||||
|
"Locally define a key-chord of the two keys in KEYS starting a COMMAND.
|
||||||
|
\nKEYS can be a string or a vector of two elements. Currently only elements
|
||||||
|
that corresponds to ascii codes in the range 32 to 126 can be used.
|
||||||
|
\nCOMMAND can be an interactive function, a string, or nil.
|
||||||
|
If COMMAND is nil, the key-chord is removed.
|
||||||
|
\nThe binding goes in the current buffer's local map,
|
||||||
|
which in most cases is shared with all other buffers in the same major mode."
|
||||||
|
(interactive "sSet key chord locally (2 keys): \nCSet chord \"%s\" to command: ")
|
||||||
|
(key-chord-define (current-local-map) keys command))
|
||||||
|
|
||||||
|
(defun key-chord-unset-global (keys)
|
||||||
|
"Remove global key-chord of the two keys in KEYS."
|
||||||
|
(interactive "sUnset key chord globally (2 keys): ")
|
||||||
|
(key-chord-define (current-global-map) keys nil))
|
||||||
|
|
||||||
|
(defun key-chord-unset-local (keys)
|
||||||
|
"Remove local key-chord of the two keys in KEYS."
|
||||||
|
(interactive "sUnset key chord locally (2 keys): ")
|
||||||
|
(key-chord-define (current-local-map) keys nil))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun key-chord-define (keymap keys command)
|
||||||
|
"Define in KEYMAP, a key-chord of the two keys in KEYS starting a COMMAND.
|
||||||
|
\nKEYS can be a string or a vector of two elements. Currently only elements
|
||||||
|
that corresponds to ascii codes in the range 32 to 126 can be used.
|
||||||
|
\nCOMMAND can be an interactive function, a string, or nil.
|
||||||
|
If COMMAND is nil, the key-chord is removed."
|
||||||
|
(if (/= 2 (length keys))
|
||||||
|
(error "Key-chord keys must have two elements"))
|
||||||
|
;; Exotic chars in a string are >255 but define-key wants 128..255 for those
|
||||||
|
(let ((key1 (logand 255 (aref keys 0)))
|
||||||
|
(key2 (logand 255 (aref keys 1))))
|
||||||
|
(if (eq key1 key2)
|
||||||
|
(define-key keymap (vector 'key-chord key1 key2) command)
|
||||||
|
;; else
|
||||||
|
(define-key keymap (vector 'key-chord key1 key2) command)
|
||||||
|
(define-key keymap (vector 'key-chord key2 key1) command))))
|
||||||
|
|
||||||
|
(defun key-chord-lookup-key1 (keymap key)
|
||||||
|
"Like lookup-key but no third arg and no numeric return value."
|
||||||
|
(let ((res (lookup-key keymap key)))
|
||||||
|
(if (numberp res)
|
||||||
|
nil
|
||||||
|
;; else
|
||||||
|
res)))
|
||||||
|
|
||||||
|
(defun key-chord-lookup-key (key)
|
||||||
|
"Lookup KEY in all current key maps."
|
||||||
|
(let ((maps (current-minor-mode-maps))
|
||||||
|
res)
|
||||||
|
(while (and maps (not res))
|
||||||
|
(setq res (key-chord-lookup-key1 (car maps) key)
|
||||||
|
maps (cdr maps)))
|
||||||
|
(or res
|
||||||
|
(if (current-local-map)
|
||||||
|
(key-chord-lookup-key1 (current-local-map) key))
|
||||||
|
(key-chord-lookup-key1 (current-global-map) key))))
|
||||||
|
|
||||||
|
(defun key-chord-describe ()
|
||||||
|
"List key chord bindings in a help buffer.
|
||||||
|
\nTwo key chords will be listed twice and there will be Prefix Commands.
|
||||||
|
Please ignore that."
|
||||||
|
(interactive)
|
||||||
|
(describe-bindings [key-chord]))
|
||||||
|
|
||||||
|
(defun key-chord-input-method (first-char)
|
||||||
|
"Input method controlled by key bindings with the prefix `key-chord'."
|
||||||
|
(if (and (not (eq first-char key-chord-last-unmatched))
|
||||||
|
(key-chord-lookup-key (vector 'key-chord first-char)))
|
||||||
|
(let ((delay (if (key-chord-lookup-key (vector 'key-chord first-char first-char))
|
||||||
|
key-chord-one-key-delay
|
||||||
|
;; else
|
||||||
|
key-chord-two-keys-delay)))
|
||||||
|
(if (if executing-kbd-macro
|
||||||
|
(not (memq first-char key-chord-in-last-kbd-macro))
|
||||||
|
(when (bound-and-true-p eldoc-mode)
|
||||||
|
(eldoc-pre-command-refresh-echo-area))
|
||||||
|
|
||||||
|
(sit-for delay 0 'no-redisplay))
|
||||||
|
(progn
|
||||||
|
(setq key-chord-last-unmatched nil)
|
||||||
|
(list first-char))
|
||||||
|
;; else input-pending-p
|
||||||
|
(let* ((input-method-function nil)
|
||||||
|
(next-char (read-event))
|
||||||
|
(res (vector 'key-chord first-char next-char)))
|
||||||
|
(if (key-chord-lookup-key res)
|
||||||
|
(progn
|
||||||
|
(setq key-chord-defining-kbd-macro
|
||||||
|
(cons first-char key-chord-defining-kbd-macro))
|
||||||
|
(list 'key-chord first-char next-char))
|
||||||
|
;; else put back next-char and return first-char
|
||||||
|
(setq unread-command-events (cons next-char unread-command-events))
|
||||||
|
(if (eq first-char next-char)
|
||||||
|
(setq key-chord-last-unmatched first-char))
|
||||||
|
(list first-char)))))
|
||||||
|
;; else no key-chord keymap
|
||||||
|
(setq key-chord-last-unmatched first-char)
|
||||||
|
(list first-char)))
|
||||||
|
|
||||||
|
(require 'advice)
|
||||||
|
|
||||||
|
(defadvice start-kbd-macro (after key-chord activate)
|
||||||
|
(setq key-chord-defining-kbd-macro nil))
|
||||||
|
|
||||||
|
(defadvice end-kbd-macro (after key-chord activate)
|
||||||
|
(setq key-chord-in-last-kbd-macro key-chord-defining-kbd-macro))
|
||||||
|
|
||||||
|
(provide 'key-chord)
|
||||||
|
|
||||||
|
;;; key-chord.el ends here
|
||||||
764
site-lisp/meson-mode.el
Normal file
764
site-lisp/meson-mode.el
Normal file
@@ -0,0 +1,764 @@
|
|||||||
|
;;; meson-mode.el --- Major mode for the Meson build system files -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; Copyright (C) 2017 Michal Sojka
|
||||||
|
|
||||||
|
;; Author: Michal Sojka <sojkam1@fel.cvut.cz>
|
||||||
|
;; Version: 0.1
|
||||||
|
;; Keywords: languages, tools
|
||||||
|
;; URL: https://github.com/wentasah/meson-mode
|
||||||
|
;; Package-Requires: ((emacs "24.3"))
|
||||||
|
|
||||||
|
;; 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; This is a major mode for Meson build system files. Syntax
|
||||||
|
;; highlighting works reliably. Indentation works too, but there are
|
||||||
|
;; probably cases, where it breaks. Simple completion is supported via
|
||||||
|
;; `completion-at-point'. To start completion, use either <C-M-i> or
|
||||||
|
;; install completion frameworks such as `company'. To enable
|
||||||
|
;; `company' add the following to your .emacs:
|
||||||
|
;;
|
||||||
|
;; (add-hook 'meson-mode-hook 'company-mode)
|
||||||
|
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(defvar meson-mode-syntax-table
|
||||||
|
(let ((table (make-syntax-table))
|
||||||
|
(list (list ?\# "<"
|
||||||
|
?\n ">#"
|
||||||
|
?\' "\"'" ; See also meson-syntax-propertize-function
|
||||||
|
?\" "."
|
||||||
|
?\$ "."
|
||||||
|
?\& "."
|
||||||
|
?\* "."
|
||||||
|
?\+ "."
|
||||||
|
?\- "."
|
||||||
|
?\< "."
|
||||||
|
?\> "."
|
||||||
|
?\= "."
|
||||||
|
?\/ "."
|
||||||
|
?\| "."
|
||||||
|
)))
|
||||||
|
(while list
|
||||||
|
(modify-syntax-entry (pop list) (pop list) table))
|
||||||
|
table)
|
||||||
|
"Syntax table used while in `meson-mode'.")
|
||||||
|
|
||||||
|
(defun meson--max-length (&rest args)
|
||||||
|
(let ((lengths
|
||||||
|
(mapcar (lambda (x) (if (stringp x) (length x) x)) args)))
|
||||||
|
(apply 'max lengths)))
|
||||||
|
|
||||||
|
(eval-and-compile
|
||||||
|
(defconst meson-keywords
|
||||||
|
'("true" "false" "if" "else" "elif" "endif" "and" "or" "not" "foreach" "endforeach")))
|
||||||
|
|
||||||
|
(defconst meson-keywords-regexp
|
||||||
|
(rx symbol-start (eval `(or ,@meson-keywords)) symbol-end))
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defconst meson-keywords-max-length
|
||||||
|
(cl-reduce 'meson--max-length meson-keywords))
|
||||||
|
|
||||||
|
(eval-and-compile
|
||||||
|
(defconst meson-builtin-functions
|
||||||
|
'("add_global_arguments"
|
||||||
|
"add_global_link_arguments" "add_languages"
|
||||||
|
"add_project_arguments" "add_project_link_arguments"
|
||||||
|
"add_test_setup" "benchmark" "build_target"
|
||||||
|
"configuration_data" "configure_file" "custom_target"
|
||||||
|
"declare_dependency" "dependency" "error" "environment"
|
||||||
|
"executable" "find_program" "find_library" "files"
|
||||||
|
"generator" "get_option" "get_variable" "import"
|
||||||
|
"include_directories" "install_data" "install_headers"
|
||||||
|
"install_man" "install_subdir" "is_variable" "jar"
|
||||||
|
"join_paths" "library" "message" "project" "run_command"
|
||||||
|
"run_target" "set_variable" "shared_library"
|
||||||
|
"shared_module" "static_library" "subdir" "subproject"
|
||||||
|
"test" "vcs_tag")))
|
||||||
|
|
||||||
|
(defconst meson-builtin-functions-regexp
|
||||||
|
(rx (or line-start (not (any ".")))
|
||||||
|
symbol-start
|
||||||
|
(group (eval `(or ,@meson-builtin-functions)))
|
||||||
|
symbol-end
|
||||||
|
(zero-or-more whitespace)
|
||||||
|
(or "(" line-end)))
|
||||||
|
|
||||||
|
(eval-when-compile
|
||||||
|
(defconst meson-builtin-vars
|
||||||
|
'("meson" "build_machine" "host_machine" "target_machine")))
|
||||||
|
|
||||||
|
(defconst meson-builtin-vars-regexp
|
||||||
|
(rx symbol-start
|
||||||
|
(or (eval `(or ,@meson-builtin-vars)))
|
||||||
|
symbol-end))
|
||||||
|
|
||||||
|
(eval-and-compile
|
||||||
|
(defconst meson-literate-tokens
|
||||||
|
'( ;;"(" ")" "[" "]" ; Let syntactic parser handle these efficiently
|
||||||
|
"\"" "," "+=" "." "+" "-" "*"
|
||||||
|
"%" "/" ":" "==" "!=" "=" "<=" "<" ">=" ">" "?")))
|
||||||
|
|
||||||
|
(defconst meson-literate-tokens-max-length
|
||||||
|
(cl-reduce 'meson--max-length meson-literate-tokens))
|
||||||
|
|
||||||
|
(defconst meson-literate-tokens-regexp
|
||||||
|
(rx (eval `(or ,@meson-literate-tokens))))
|
||||||
|
|
||||||
|
(defconst meson-methods
|
||||||
|
`(("meson\\."
|
||||||
|
. ("get_compiler"
|
||||||
|
"is_cross_build"
|
||||||
|
"has_exe_wrapper"
|
||||||
|
"is_unity"
|
||||||
|
"is_subproject"
|
||||||
|
"current_source_dir"
|
||||||
|
"current_build_dir"
|
||||||
|
"source_root"
|
||||||
|
"build_root"
|
||||||
|
"add_install_script"
|
||||||
|
"add_postconf_script"
|
||||||
|
"install_dependency_manifest"
|
||||||
|
"project_version"
|
||||||
|
"version"
|
||||||
|
"project_name"
|
||||||
|
"get_cross_property"
|
||||||
|
"backend"))
|
||||||
|
(,(regexp-opt '("build_machine."
|
||||||
|
"host_machine."
|
||||||
|
"target_machine."))
|
||||||
|
. ("system"
|
||||||
|
"cpu_family"
|
||||||
|
"cpu"
|
||||||
|
"endian"))
|
||||||
|
(""
|
||||||
|
. ( ;; class TryRunResultHolder
|
||||||
|
"returncode"
|
||||||
|
"compiled"
|
||||||
|
"stdout"
|
||||||
|
"stderr"
|
||||||
|
|
||||||
|
;; class RunProcess
|
||||||
|
"returncode"
|
||||||
|
"stdout"
|
||||||
|
"stderr"
|
||||||
|
|
||||||
|
;; class EnvironmentVariablesHolder
|
||||||
|
"set"
|
||||||
|
"append"
|
||||||
|
"prepend"
|
||||||
|
|
||||||
|
;; class ConfigurationDataHolder
|
||||||
|
"set"
|
||||||
|
"set10"
|
||||||
|
"set_quoted"
|
||||||
|
"has"
|
||||||
|
"get"
|
||||||
|
|
||||||
|
;; class DependencyHolder
|
||||||
|
"found"
|
||||||
|
"type_name"
|
||||||
|
"version"
|
||||||
|
"get_pkgconfig_variable"
|
||||||
|
|
||||||
|
;; class InternalDependencyHolder
|
||||||
|
"found"
|
||||||
|
"version"
|
||||||
|
|
||||||
|
;; class ExternalProgramHolder
|
||||||
|
"found"
|
||||||
|
|
||||||
|
;; class ExternalLibraryHolder
|
||||||
|
"found"
|
||||||
|
|
||||||
|
;; class GeneratorHolder
|
||||||
|
"process"
|
||||||
|
|
||||||
|
;; class BuildMachine
|
||||||
|
"system"
|
||||||
|
"cpu_family"
|
||||||
|
"cpu"
|
||||||
|
"endian"
|
||||||
|
|
||||||
|
;; class CrossMachineInfo
|
||||||
|
"system"
|
||||||
|
"cpu"
|
||||||
|
"cpu_family"
|
||||||
|
"endian"
|
||||||
|
|
||||||
|
;; class BuildTargetHolder
|
||||||
|
"extract_objects"
|
||||||
|
"extract_all_objects"
|
||||||
|
"get_id"
|
||||||
|
"outdir"
|
||||||
|
"full_path"
|
||||||
|
"private_dir_include"
|
||||||
|
|
||||||
|
;; class CustomTargetHolder
|
||||||
|
"full_path"
|
||||||
|
|
||||||
|
;; class SubprojectHolder
|
||||||
|
"get_variable"
|
||||||
|
|
||||||
|
;; class CompilerHolder
|
||||||
|
"compiles"
|
||||||
|
"links"
|
||||||
|
"get_id"
|
||||||
|
"compute_int"
|
||||||
|
"sizeof"
|
||||||
|
"has_header"
|
||||||
|
"has_header_symbol"
|
||||||
|
"run"
|
||||||
|
"has_function"
|
||||||
|
"has_member"
|
||||||
|
"has_members"
|
||||||
|
"has_type"
|
||||||
|
"alignment"
|
||||||
|
"version"
|
||||||
|
"cmd_array"
|
||||||
|
"find_library"
|
||||||
|
"has_argument"
|
||||||
|
"has_multi_arguments"
|
||||||
|
"first_supported_argument"
|
||||||
|
"unittest_args"
|
||||||
|
"symbols_have_underscore_prefix"
|
||||||
|
|
||||||
|
;; string
|
||||||
|
"strip"
|
||||||
|
"format"
|
||||||
|
"to_upper"
|
||||||
|
"to_lower"
|
||||||
|
"underscorify"
|
||||||
|
"split"
|
||||||
|
"startswith"
|
||||||
|
"endswith"
|
||||||
|
"contains"
|
||||||
|
"to_int"
|
||||||
|
"join"
|
||||||
|
"version_compare"
|
||||||
|
|
||||||
|
;; number
|
||||||
|
"is_even"
|
||||||
|
"is_odd"
|
||||||
|
|
||||||
|
;; boolean
|
||||||
|
"to_string"
|
||||||
|
"to_int"
|
||||||
|
|
||||||
|
;; array
|
||||||
|
"length"
|
||||||
|
"contains"
|
||||||
|
"get"
|
||||||
|
|
||||||
|
))))
|
||||||
|
|
||||||
|
(defconst meson-basic-kwargs
|
||||||
|
'("install"
|
||||||
|
"c_pch"
|
||||||
|
"cpp_pch"
|
||||||
|
"c_args"
|
||||||
|
"cpp_args"
|
||||||
|
"cs_args"
|
||||||
|
"vala_args"
|
||||||
|
"fortran_args"
|
||||||
|
"d_args"
|
||||||
|
"java_args"
|
||||||
|
"link_args"
|
||||||
|
"link_depends"
|
||||||
|
"link_with"
|
||||||
|
"include_directories"
|
||||||
|
"dependencies"
|
||||||
|
"install_dir"
|
||||||
|
"main_class"
|
||||||
|
"gui_app"
|
||||||
|
"extra_files"
|
||||||
|
"install_rpath"
|
||||||
|
"resources"
|
||||||
|
"sources"
|
||||||
|
"objects"
|
||||||
|
"native"
|
||||||
|
"build_by_default"
|
||||||
|
))
|
||||||
|
|
||||||
|
(defconst meson-kwargs
|
||||||
|
`(("executable"
|
||||||
|
. ,meson-basic-kwargs)
|
||||||
|
("library"
|
||||||
|
. ,(append meson-basic-kwargs
|
||||||
|
'("version" ; Only for shared libs
|
||||||
|
"soversion" ; Only for shared libs
|
||||||
|
"name_prefix"
|
||||||
|
"name_suffix"
|
||||||
|
"vs_module_defs" ; Only for shared libs
|
||||||
|
"vala_header"
|
||||||
|
"vala_vapi"
|
||||||
|
"vala_gir"
|
||||||
|
"pic" ; Only for static libs
|
||||||
|
)))
|
||||||
|
("project"
|
||||||
|
. ("version"
|
||||||
|
"meson_version"
|
||||||
|
"default_options"))
|
||||||
|
("run_target"
|
||||||
|
. ("command"
|
||||||
|
"depends"))
|
||||||
|
("test"
|
||||||
|
. ("args"
|
||||||
|
"env"
|
||||||
|
"is_parallel"
|
||||||
|
"should_fail"
|
||||||
|
"valgring_args"
|
||||||
|
"timeout"
|
||||||
|
"workdir"))
|
||||||
|
("vcs_tag"
|
||||||
|
. ("input"
|
||||||
|
"output"
|
||||||
|
"fallback"))
|
||||||
|
("install_[[:alpha:]]+"
|
||||||
|
. ("install_dir"))
|
||||||
|
("add_languages"
|
||||||
|
. ("required"))
|
||||||
|
("add_test_setup"
|
||||||
|
. ("exe_wrapper"
|
||||||
|
"gdb"
|
||||||
|
"timeout_multiplier"
|
||||||
|
"env"))
|
||||||
|
("benchmark"
|
||||||
|
. ("args"
|
||||||
|
"env"
|
||||||
|
"should_fail"
|
||||||
|
"valgring_args"
|
||||||
|
"timeout"
|
||||||
|
"workdir"))
|
||||||
|
("configure_file"
|
||||||
|
. ("input"
|
||||||
|
"output"
|
||||||
|
"configuration"
|
||||||
|
"command"
|
||||||
|
"install_dir"))
|
||||||
|
("custom_target"
|
||||||
|
. ("input"
|
||||||
|
"output"
|
||||||
|
"command"
|
||||||
|
"install"
|
||||||
|
"install_dir"
|
||||||
|
"build_always"
|
||||||
|
"capture"
|
||||||
|
"depends"
|
||||||
|
"depend_files"
|
||||||
|
"depfile"
|
||||||
|
"build_by_default"))
|
||||||
|
("declare_dependency"
|
||||||
|
. ("include_directories"
|
||||||
|
"link_with"
|
||||||
|
"sources"
|
||||||
|
"dependencies"
|
||||||
|
"compile_args"
|
||||||
|
"link_args"
|
||||||
|
"version"))
|
||||||
|
("dependency"
|
||||||
|
. ("modules"
|
||||||
|
"required"
|
||||||
|
"version"
|
||||||
|
"native"
|
||||||
|
"static"
|
||||||
|
"fallback"
|
||||||
|
"default_options"))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
(eval-and-compile
|
||||||
|
(defconst meson-multiline-string-regexp
|
||||||
|
(rx "'''" (minimal-match (zero-or-more anything)) "'''"))
|
||||||
|
(defconst meson-string-regexp
|
||||||
|
(rx "'"
|
||||||
|
(zero-or-more
|
||||||
|
(or (not (any "'" "\\"))
|
||||||
|
(seq "\\" nonl)))
|
||||||
|
"'")))
|
||||||
|
|
||||||
|
(defconst meson-string-regexp
|
||||||
|
(rx (or (eval `(regexp ,meson-multiline-string-regexp))
|
||||||
|
(eval `(regexp ,meson-string-regexp)))))
|
||||||
|
|
||||||
|
(defconst meson-token-spec
|
||||||
|
`(("ignore" . ,(rx (one-or-more (any " " "\t"))))
|
||||||
|
("id" . ,(rx (any "_" "a-z" "A-Z") (zero-or-more (any "_" "a-z" "A-Z" "0-9"))))
|
||||||
|
("number" . ,(rx (one-or-more (any digit))))
|
||||||
|
("eol_cont" . ,(rx "\\" "\n"))
|
||||||
|
("eol" . "\n")))
|
||||||
|
|
||||||
|
(defvar meson-mode-font-lock-keywords
|
||||||
|
`((,meson-keywords-regexp . font-lock-keyword-face)
|
||||||
|
(,meson-builtin-functions-regexp . (1 font-lock-builtin-face))
|
||||||
|
(,meson-builtin-vars-regexp . font-lock-variable-name-face)))
|
||||||
|
|
||||||
|
(defconst meson-syntax-propertize-function
|
||||||
|
(syntax-propertize-rules
|
||||||
|
((rx (or "'''" "'")) (0 (ignore (meson-syntax-stringify))))))
|
||||||
|
|
||||||
|
(defsubst meson-syntax-count-quotes (&optional point limit)
|
||||||
|
"Count number of quotes after point (max is 3).
|
||||||
|
POINT is the point where scan starts (defaults to current point),
|
||||||
|
and LIMIT is used to limit the scan."
|
||||||
|
(let ((i 0)
|
||||||
|
(p (or point (point))))
|
||||||
|
(while (and (< i 3)
|
||||||
|
(or (not limit) (< (+ p i) limit))
|
||||||
|
(eq (char-after (+ p i)) ?\'))
|
||||||
|
(setq i (1+ i)))
|
||||||
|
i))
|
||||||
|
|
||||||
|
(defun meson-syntax-stringify ()
|
||||||
|
"Put `syntax-table' property correctly on single/triple apostrophes."
|
||||||
|
;; Inspired by python-mode
|
||||||
|
(let* ((num-quotes (length (match-string-no-properties 0)))
|
||||||
|
(ppss (prog2
|
||||||
|
(backward-char num-quotes)
|
||||||
|
(syntax-ppss)
|
||||||
|
(forward-char num-quotes)))
|
||||||
|
(in-comment (nth 4 ppss))
|
||||||
|
(string-start (and (not in-comment) (nth 8 ppss)))
|
||||||
|
(quote-starting-pos (- (point) num-quotes))
|
||||||
|
(quote-ending-pos (point))
|
||||||
|
(num-closing-quotes
|
||||||
|
(and string-start
|
||||||
|
(meson-syntax-count-quotes
|
||||||
|
string-start quote-starting-pos))))
|
||||||
|
(cond ((and string-start (= num-closing-quotes 0))
|
||||||
|
;; This set of quotes doesn't match the string starting
|
||||||
|
;; kind. Do nothing.
|
||||||
|
nil)
|
||||||
|
((not string-start)
|
||||||
|
;; This set of quotes delimit the start of a string.
|
||||||
|
(put-text-property quote-starting-pos (1+ quote-starting-pos)
|
||||||
|
'syntax-table (string-to-syntax "|")))
|
||||||
|
((= num-quotes num-closing-quotes)
|
||||||
|
;; This set of quotes delimit the end of a string.
|
||||||
|
(put-text-property (1- quote-ending-pos) quote-ending-pos
|
||||||
|
'syntax-table (string-to-syntax "|")))
|
||||||
|
((> num-quotes num-closing-quotes)
|
||||||
|
;; This may only happen whenever a triple quote is closing
|
||||||
|
;; a single quoted string. Add string delimiter syntax to
|
||||||
|
;; all three quotes.
|
||||||
|
(put-text-property quote-starting-pos quote-ending-pos
|
||||||
|
'syntax-table (string-to-syntax "|"))))))
|
||||||
|
|
||||||
|
;;; Completion
|
||||||
|
|
||||||
|
(defun meson-completion-at-point-function ()
|
||||||
|
(save-excursion
|
||||||
|
(let* ((end (progn (skip-syntax-forward "w_")
|
||||||
|
(point)))
|
||||||
|
(start (progn (skip-syntax-backward "w_")
|
||||||
|
(point)))
|
||||||
|
(ppss (syntax-ppss)))
|
||||||
|
(cond
|
||||||
|
((or (nth 3 ppss) ; inside string
|
||||||
|
(nth 4 ppss)) ; inside comment
|
||||||
|
nil) ; nothing to complete
|
||||||
|
|
||||||
|
;; kwargs
|
||||||
|
((and (> (nth 0 ppss) 0) ; inside parentheses
|
||||||
|
(eq (char-after (nth 1 ppss)) ?\()) ; rounded parentheses
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (nth 1 ppss))
|
||||||
|
(let ((kwargs (cl-some (lambda (x)
|
||||||
|
(when (looking-back (concat (car x) (rx (zero-or-more (any " " "\t"))))
|
||||||
|
(line-beginning-position))
|
||||||
|
(cdr x)))
|
||||||
|
meson-kwargs)))
|
||||||
|
;; complete mathing kwargs as well as built-in
|
||||||
|
;; variables/functions
|
||||||
|
(list start end (append kwargs meson-builtin-vars
|
||||||
|
meson-builtin-functions)))))
|
||||||
|
|
||||||
|
;; methods
|
||||||
|
((eq (char-before) ?.)
|
||||||
|
(let ((methods (cl-some
|
||||||
|
(lambda (x)
|
||||||
|
(when (looking-back (car x) (line-beginning-position))
|
||||||
|
(cdr x)))
|
||||||
|
meson-methods)))
|
||||||
|
(list start end methods)))
|
||||||
|
;; global things
|
||||||
|
(t
|
||||||
|
(list start end (append meson-keywords meson-builtin-vars
|
||||||
|
meson-builtin-functions)))))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Indetation
|
||||||
|
|
||||||
|
(require 'smie)
|
||||||
|
|
||||||
|
(defun meson--comment-bolp (&optional ppss_)
|
||||||
|
"Return non-nil if point is at the beginning of line, ignoring
|
||||||
|
comments."
|
||||||
|
(save-excursion
|
||||||
|
(let ((ppss (or ppss_
|
||||||
|
(syntax-ppss))))
|
||||||
|
(when (nth 4 ppss) ; inside comment
|
||||||
|
(goto-char (nth 8 ppss))) ; go to its beginning
|
||||||
|
(smie-rule-bolp))))
|
||||||
|
|
||||||
|
(defun meson-smie-forward-token ()
|
||||||
|
(let ((token 'unknown))
|
||||||
|
(while (eq token 'unknown)
|
||||||
|
(let ((ppss (syntax-ppss)))
|
||||||
|
;; When inside or at start of a comment, goto end of line so
|
||||||
|
;; that we can still return "eol" token there.
|
||||||
|
(when (or (nth 4 ppss)
|
||||||
|
(and (not (nth 3 ppss)) ; not inside string
|
||||||
|
(looking-at "#")))
|
||||||
|
(end-of-line)
|
||||||
|
(setq ppss (syntax-ppss))) ; update ppss after move
|
||||||
|
;; Determine token but do not move behind it
|
||||||
|
(setq token
|
||||||
|
(cond
|
||||||
|
;; Let syntactic parser handle parentheses (even inside
|
||||||
|
;; strings - this ensures that parentheses are NOT
|
||||||
|
;; indented inside strings according to meson
|
||||||
|
;; indentation rules)
|
||||||
|
((looking-at (rx (or (syntax open-parenthesis)
|
||||||
|
(syntax close-parenthesis))))
|
||||||
|
"")
|
||||||
|
;; After handling parentheses (inside strings), we can
|
||||||
|
;; handle strings
|
||||||
|
((or (when (nth 3 ppss) ; If inside string
|
||||||
|
(goto-char (nth 8 ppss)) ; goto beginning
|
||||||
|
nil)
|
||||||
|
(looking-at meson-string-regexp)) ; Match the whole string
|
||||||
|
"string")
|
||||||
|
((looking-at meson-keywords-regexp) (match-string-no-properties 0))
|
||||||
|
((cl-some (lambda (spec) (when (looking-at (cdr spec)) (car spec)))
|
||||||
|
meson-token-spec))
|
||||||
|
((looking-at meson-literate-tokens-regexp)
|
||||||
|
(match-string-no-properties 0))))
|
||||||
|
;; Remember token end (except for parentheses)
|
||||||
|
(let ((after-token (when (< 0 (length token)) (match-end 0))))
|
||||||
|
;; Skip certain tokens
|
||||||
|
(when (or (equal token "ignore")
|
||||||
|
(equal token "eol_cont")
|
||||||
|
(and (equal token "eol") ; Skip EOL when:
|
||||||
|
(or (> (nth 0 ppss) 0) ; - inside parentheses
|
||||||
|
(and (looking-back ; - after operator but not inside comments
|
||||||
|
meson-literate-tokens-regexp
|
||||||
|
(- (point) meson-literate-tokens-max-length))
|
||||||
|
(not (nth 4 ppss)))
|
||||||
|
(meson--comment-bolp ppss)))) ; - at empty line
|
||||||
|
(setq token 'unknown))
|
||||||
|
(when after-token
|
||||||
|
(goto-char after-token)))))
|
||||||
|
token))
|
||||||
|
|
||||||
|
(defun meson-smie-backward-token ()
|
||||||
|
(let ((token 'unknown))
|
||||||
|
(while (eq token 'unknown)
|
||||||
|
(let ((eopl (max ;; end of previous line (to properly match "eol_cont" below it is actually a character before)
|
||||||
|
(1- (line-end-position 0))
|
||||||
|
(point-min)))
|
||||||
|
(ppss (syntax-ppss)))
|
||||||
|
;; Skip comments
|
||||||
|
(when (nth 4 ppss) ; We are in a comment
|
||||||
|
(goto-char (nth 8 ppss)) ; goto its beginning
|
||||||
|
(setq ppss (syntax-ppss))) ; update ppss after move
|
||||||
|
(setq token
|
||||||
|
;; Determine token and move before it
|
||||||
|
(cond
|
||||||
|
;; Let syntactic parser handle parentheses (even inside
|
||||||
|
;; strings - this ensures that parentheses are NOT
|
||||||
|
;; indented inside strings according to meson
|
||||||
|
;; indentation rules)
|
||||||
|
((looking-back (rx (or (syntax open-parenthesis)
|
||||||
|
(syntax close-parenthesis)))
|
||||||
|
(1- (point)))
|
||||||
|
"")
|
||||||
|
;; Check for strings. Relying on syntactic parser allows us to
|
||||||
|
;; find the beginning of multi-line strings efficiently.
|
||||||
|
((nth 3 ppss) ; We're inside string or
|
||||||
|
(let ((string-start (nth 8 ppss)))
|
||||||
|
(when (not (equal (point) string-start))
|
||||||
|
(goto-char string-start)
|
||||||
|
"string")))
|
||||||
|
((equal (char-before) ?\') ; We're just after a string
|
||||||
|
(let* ((ppss- (syntax-ppss (1- (point)))))
|
||||||
|
(goto-char (nth 8 ppss-))
|
||||||
|
"string"))
|
||||||
|
;; Regexp-based matching
|
||||||
|
(t (let ((tok
|
||||||
|
;; Determine token but do not move before it
|
||||||
|
(cond
|
||||||
|
((looking-back meson-keywords-regexp (- (point) meson-keywords-max-length) t)
|
||||||
|
(match-string-no-properties 0))
|
||||||
|
((looking-back meson-literate-tokens-regexp
|
||||||
|
(- (point) meson-literate-tokens-max-length) t)
|
||||||
|
(match-string-no-properties 0))
|
||||||
|
((cl-some (lambda (spec) (when (looking-back (cdr spec) eopl t) (car spec)))
|
||||||
|
meson-token-spec)))))
|
||||||
|
(when tok
|
||||||
|
(goto-char (match-beginning 0)) ; Go before token now
|
||||||
|
(setq ppss (syntax-ppss))) ; update ppss
|
||||||
|
tok))))
|
||||||
|
(when (or (equal token "ignore")
|
||||||
|
(equal token "eol_cont")
|
||||||
|
(and (equal token "eol") ; Skip EOL when:
|
||||||
|
(or (> (nth 0 ppss) 0) ; - inside parentheses
|
||||||
|
(and (looking-back ; - after operator but not inside comments
|
||||||
|
meson-literate-tokens-regexp
|
||||||
|
(- (point) meson-literate-tokens-max-length))
|
||||||
|
(not (nth 4 ppss)))
|
||||||
|
(meson--comment-bolp ppss)))) ;- at empty line
|
||||||
|
(setq token 'unknown))))
|
||||||
|
token))
|
||||||
|
|
||||||
|
(defconst meson-smie-grammar
|
||||||
|
(smie-prec2->grammar
|
||||||
|
(smie-bnf->prec2
|
||||||
|
'((id)
|
||||||
|
(codeblock (line)
|
||||||
|
(codeblock "eol" codeblock))
|
||||||
|
(line (exp)
|
||||||
|
("if" ifblock "endif")
|
||||||
|
("if" ifblock "else" codeblock "endif")
|
||||||
|
("foreach" foreachblock "endforeach"))
|
||||||
|
(foreachblock (id ":" exp "eol" codeblock))
|
||||||
|
(ifblock (exp "eol" codeblock)
|
||||||
|
(exp "eol" codeblock "elif" ifblock)
|
||||||
|
)
|
||||||
|
(exp (exp "," exp)
|
||||||
|
(id ":" exp)
|
||||||
|
(exp "+=" exp)
|
||||||
|
(exp "=" exp)
|
||||||
|
;; (exp "?" exp ":" exp)
|
||||||
|
(exp "or" exp)
|
||||||
|
(exp "and" exp)
|
||||||
|
(exp "==" exp)
|
||||||
|
(exp "!=" exp)
|
||||||
|
(exp "<" exp)
|
||||||
|
(exp "<=" exp)
|
||||||
|
(exp ">" exp)
|
||||||
|
(exp ">=" exp)
|
||||||
|
(exp "+" exp)
|
||||||
|
(exp "-" exp)
|
||||||
|
(exp "*" exp)
|
||||||
|
(exp "/" exp)
|
||||||
|
(exp "%" exp)
|
||||||
|
;; ("not" exp)
|
||||||
|
;; ("-" exp)
|
||||||
|
;; (exp "." methodcall)
|
||||||
|
;; (exp "." exp)
|
||||||
|
;; (exp "(" args ")")
|
||||||
|
;; (exp "(" args ")" indexcall)
|
||||||
|
;; ("[" array "]")
|
||||||
|
;; ("true")
|
||||||
|
;; ("false")
|
||||||
|
)
|
||||||
|
;; (args (exp)
|
||||||
|
|
||||||
|
;; (id ":" exp))
|
||||||
|
;; (array (array "," array))
|
||||||
|
;; (methodcall (exp "(" args ")" )
|
||||||
|
;; ;; (exp "(" args ")" "." methodcall)
|
||||||
|
;; )
|
||||||
|
;; (indexcall ( "[" exp "]"))
|
||||||
|
)
|
||||||
|
`((assoc "eol" "elif")) ; FIXME: Solving eol/elif conflict this
|
||||||
|
; way may cause problems in indetation.
|
||||||
|
; Revisit this if it is the case.
|
||||||
|
`((assoc "eol")
|
||||||
|
(assoc ",")
|
||||||
|
(assoc ":")
|
||||||
|
(assoc "+=" "=")
|
||||||
|
(assoc "or")
|
||||||
|
(assoc "and")
|
||||||
|
(assoc "==" "!=" "<" "<=" ">" ">=")
|
||||||
|
(assoc "+" "-")
|
||||||
|
(assoc "*" "/" "%")
|
||||||
|
(assoc ".")
|
||||||
|
)
|
||||||
|
)))
|
||||||
|
|
||||||
|
(defgroup meson nil
|
||||||
|
"Meson build system mode for Emacs."
|
||||||
|
:group 'tools
|
||||||
|
:prefix "meson-")
|
||||||
|
|
||||||
|
(defcustom meson-indent-basic 2
|
||||||
|
"Indentation offset for meson.build files."
|
||||||
|
:type 'integer)
|
||||||
|
|
||||||
|
(defun meson-smie-rules (kind token)
|
||||||
|
(pcase (cons kind token)
|
||||||
|
(`(:elem . basic) meson-indent-basic)
|
||||||
|
(`(:elem . args) (- (save-excursion (beginning-of-line-text) (point)) (point)))
|
||||||
|
(`(,_ . ",") (smie-rule-separator kind))
|
||||||
|
(`(,(or :before :after) . "eol") (if (smie-rule-parent-p "if" "foreach" "elif" "else")
|
||||||
|
(smie-rule-parent meson-indent-basic)
|
||||||
|
(save-excursion
|
||||||
|
(smie-indent-forward-token)
|
||||||
|
(smie-backward-sexp 'halfsexp)
|
||||||
|
(cons 'column (current-column)))))
|
||||||
|
(`(:list-intro . ,(or "eol" ":" "")) t) ; "" is actually "[" because that's what lexer returns
|
||||||
|
(`(:after . ":") meson-indent-basic)
|
||||||
|
(`(:after . ,(or "=" "+=")) meson-indent-basic)
|
||||||
|
(`(:before . "[") (if (smie-rule-hanging-p) (smie-rule-parent)))
|
||||||
|
(`(:before . "(") (if (smie-rule-hanging-p)
|
||||||
|
(save-excursion
|
||||||
|
(smie-backward-sexp 'halfsexp) ; goto parent
|
||||||
|
(beginning-of-line-text)
|
||||||
|
(cons 'column (current-column)))))
|
||||||
|
(`(:after . ,(or "[" "(")) meson-indent-basic)
|
||||||
|
(`(:before . "elif") (smie-rule-parent))
|
||||||
|
(_ nil)))
|
||||||
|
|
||||||
|
;;; Mode definition
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-derived-mode meson-mode prog-mode "Meson"
|
||||||
|
"Major mode for editing Meson build system files."
|
||||||
|
:abbrev-table nil
|
||||||
|
(setq font-lock-defaults
|
||||||
|
'(meson-mode-font-lock-keywords
|
||||||
|
nil nil nil nil
|
||||||
|
))
|
||||||
|
|
||||||
|
(set (make-local-variable 'syntax-propertize-function)
|
||||||
|
meson-syntax-propertize-function)
|
||||||
|
|
||||||
|
(set (make-local-variable 'comment-start) "# ")
|
||||||
|
(set (make-local-variable 'comment-end) "")
|
||||||
|
(add-hook 'completion-at-point-functions
|
||||||
|
#'meson-completion-at-point-function nil t)
|
||||||
|
(smie-setup meson-smie-grammar #'meson-smie-rules
|
||||||
|
:forward-token #'meson-smie-forward-token
|
||||||
|
:backward-token #'meson-smie-backward-token)
|
||||||
|
)
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(progn
|
||||||
|
(add-to-list 'auto-mode-alist '("/meson\\(\\.build\\|_options\\.txt\\)\\'" . meson-mode))
|
||||||
|
(eval-after-load 'compile
|
||||||
|
'(progn
|
||||||
|
(add-to-list 'compilation-error-regexp-alist 'meson)
|
||||||
|
(add-to-list 'compilation-error-regexp-alist-alist
|
||||||
|
'(meson "^Meson encountered an error in file \\(.*\\), line \\([0-9]+\\), column \\([0-9]+\\):" 1 2 3)))))
|
||||||
|
|
||||||
|
(provide 'meson-mode)
|
||||||
|
;;; meson-mode.el ends here
|
||||||
|
|
||||||
|
;;(progn (mapatoms (lambda (x) (when (string-prefix-p "meson" (symbol-name x)) (makunbound x)))) (eval-buffer))
|
||||||
873
site-lisp/org-tree-slide.el
Normal file
873
site-lisp/org-tree-slide.el
Normal file
@@ -0,0 +1,873 @@
|
|||||||
|
;;; org-tree-slide.el --- A presentation tool for org-mode
|
||||||
|
;;
|
||||||
|
;; Copyright (C) 2011-2016 Takaaki ISHIKAWA
|
||||||
|
;;
|
||||||
|
;; Author: Takaaki ISHIKAWA <takaxp at ieee dot org>
|
||||||
|
;; Version: 2.8.5
|
||||||
|
;; Maintainer: Takaaki ISHIKAWA <takaxp at ieee dot org>
|
||||||
|
;; Twitter: @takaxp
|
||||||
|
;; Repository: https://github.com/takaxp/org-tree-slide
|
||||||
|
;; Keywords: org-mode, presentation, narrowing
|
||||||
|
;;
|
||||||
|
;; Committers: Yuuki ARISAWA (@uk-ar)
|
||||||
|
;; Eric S Fraga
|
||||||
|
;; Eike Kettner
|
||||||
|
;; Stefano BENNATI
|
||||||
|
;; Matus Goljer
|
||||||
|
;;
|
||||||
|
;; 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 GNU Emacs; see the file COPYING. If not, write to the
|
||||||
|
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
;; Boston, MA 02110-1301, USA.
|
||||||
|
;;
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; Requirement:
|
||||||
|
;; org-mode 6.33x or higher version
|
||||||
|
;; The latest version of the org-mode is recommended.
|
||||||
|
;; (see http://orgmode.org/)
|
||||||
|
;;
|
||||||
|
;; Usage:
|
||||||
|
;; 1. Put this elisp into your load-path
|
||||||
|
;; 2. Add (require 'org-tree-slide) in your .emacs
|
||||||
|
;; 3. Open an org-mode file
|
||||||
|
;; 4. Toggle org-tree-slide-mode (M-x org-tree-slide-mode)
|
||||||
|
;; then Slideshow will start and you can find "TSlide" in mode line.
|
||||||
|
;; 5. <left>/<right> will move between slides
|
||||||
|
;; 6. `C-x s c' will show CONTENT of the org buffer
|
||||||
|
;; Select a heading and type <right>, then Slideshow will start again.
|
||||||
|
;; 7. Toggle org-tree-slide-mode again to exit this minor mode
|
||||||
|
;;
|
||||||
|
;; Recommended minimum settings:
|
||||||
|
;; (global-set-key (kbd "<f8>") 'org-tree-slide-mode)
|
||||||
|
;; (global-set-key (kbd "S-<f8>") 'org-tree-slide-skip-done-toggle)
|
||||||
|
;;
|
||||||
|
;; and three useful profiles are available.
|
||||||
|
;;
|
||||||
|
;; 1. Simple use
|
||||||
|
;; M-x org-tree-slide-simple-profile
|
||||||
|
;;
|
||||||
|
;; 2. Presentation use
|
||||||
|
;; M-x org-tree-slide-presentation-profile
|
||||||
|
;;
|
||||||
|
;; 3. TODO Pursuit with narrowing
|
||||||
|
;; M-x org-tree-slide-narrowing-control-profile
|
||||||
|
;;
|
||||||
|
;; Type `C-h f org-tree-slide-mode', you can find more detail.
|
||||||
|
;;
|
||||||
|
;; Note:
|
||||||
|
;; - Make sure key maps below when you introduce this elisp.
|
||||||
|
;; - Customize variables, M-x customize-group ENT org-tree-slide ENT
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'org)
|
||||||
|
(require 'org-timer)
|
||||||
|
;;(require 'org-clock) ; org-clock-in, -out, -clocking-p
|
||||||
|
|
||||||
|
(defconst org-tree-slide "2.8.5"
|
||||||
|
"The version number of the org-tree-slide.el")
|
||||||
|
|
||||||
|
(defgroup org-tree-slide nil
|
||||||
|
"User variables for org-tree-slide."
|
||||||
|
:group 'org-structure)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-skip-outline-level 0
|
||||||
|
"Skip slides if a heading level is higher than or equal to this variable.
|
||||||
|
`0': never skip at any heading
|
||||||
|
e.g. set `4',
|
||||||
|
*** heading A ; display as a slide
|
||||||
|
entry
|
||||||
|
**** heading B ; skip! do not display as the next slide
|
||||||
|
**** heading C ; skip!
|
||||||
|
*** heading D ; display as the next slide
|
||||||
|
"
|
||||||
|
:type 'integer
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-fold-subtrees-skipped t
|
||||||
|
"If this flag is true, the subtrees in a slide will be displayed in fold.
|
||||||
|
When nil, the body of the subtrees will be revealed.
|
||||||
|
"
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-header t
|
||||||
|
"The status of displaying the slide header"
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-slide-in-effect t
|
||||||
|
"Using a visual effect of slide-in for displaying trees."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-cursor-init t
|
||||||
|
"Specify a cursor position when exit slideshow.
|
||||||
|
`t': the cursor will move automatically to the head of buffer.
|
||||||
|
nil: keep the same position."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-slide-in-blank-lines 10
|
||||||
|
"Specify the number of blank lines, the slide will move from this line."
|
||||||
|
:type 'integer
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-slide-in-waiting 0.02
|
||||||
|
"Specify the duration waiting the next update of overlay."
|
||||||
|
:type 'float
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-heading-emphasis nil
|
||||||
|
"Specify to use a custom face heading, or not"
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-never-touch-face nil
|
||||||
|
"If t, do NOT touch any face setting."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-skip-done nil
|
||||||
|
"Specify to show TODO item only or not."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-skip-comments t
|
||||||
|
"Specify to skip COMMENT item or not."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-activate-message
|
||||||
|
"Hello! This is org-tree-slide :-)"
|
||||||
|
"Message in mini buffer when org-tree-slide is activated."
|
||||||
|
:type 'string
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-deactivate-message
|
||||||
|
"Quit, Bye!"
|
||||||
|
"Message in mini buffer when org-tree-slide is deactivated."
|
||||||
|
:type 'string
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-modeline-display 'outside
|
||||||
|
"Specify how to display the slide number in mode line.
|
||||||
|
'lighter: shown in lighter (update info actively, then it's slow)
|
||||||
|
'outside: update infomation when moving to the next/previous slide
|
||||||
|
nil: nothing to be shown"
|
||||||
|
:type 'symbol
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defvar org-tree-slide-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(define-key map (kbd "C-x s c") 'org-tree-slide-content)
|
||||||
|
;; (define-key map (kbd "C-x s r") 'org-tree-slide-resume) ;; TODO
|
||||||
|
(define-key map (kbd "C-<") 'org-tree-slide-move-previous-tree)
|
||||||
|
(define-key map (kbd "C->") 'org-tree-slide-move-next-tree)
|
||||||
|
map)
|
||||||
|
"The keymap for `org-tree-slide'.")
|
||||||
|
|
||||||
|
(defface org-tree-slide-heading-level-2-init
|
||||||
|
'((t (:inherit outline-2)))
|
||||||
|
"Level 2."
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defface org-tree-slide-heading-level-3-init
|
||||||
|
'((t (:inherit outline-3)))
|
||||||
|
"Level 3."
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defface org-tree-slide-heading-level-2
|
||||||
|
'((t (:inherit outline-2 :height 1.4 :bold t)))
|
||||||
|
"Level 2."
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defface org-tree-slide-heading-level-3
|
||||||
|
'((t (:inherit outline-3 :height 1.3 :bold t)))
|
||||||
|
"Level 3."
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defvar org-tree-slide-mode nil)
|
||||||
|
;; These hooks was obsoleted, and will be deleted by Oct. 2015.
|
||||||
|
(defvar org-tree-slide-mode-play-hook nil
|
||||||
|
"[obsolete] A hook run when org-tree-slide--play is evaluated to start the slide show")
|
||||||
|
(defvar org-tree-slide-mode-stop-hook nil
|
||||||
|
"[obsolete] A hook run when org-tree-slide--stop is evaluated to stop the slide show")
|
||||||
|
(defvar org-tree-slide-mode-before-narrow-hook nil
|
||||||
|
"[obsolete] A hook run before evaluating org-tree-slide--display-tree-with-narrow")
|
||||||
|
(defvar org-tree-slide-mode-after-narrow-hook nil
|
||||||
|
"[obsolete] A hook run after evaluating org-tree-slide--display-tree-with-narrow")
|
||||||
|
|
||||||
|
;; Updated hooks
|
||||||
|
(defvar org-tree-slide-play-hook nil
|
||||||
|
"A hook run when org-tree-slide--play is evaluated to start the slide show")
|
||||||
|
(defvar org-tree-slide-stop-hook nil
|
||||||
|
"A hook run when org-tree-slide--stop is evaluated to stop the slide show")
|
||||||
|
(defvar org-tree-slide-before-narrow-hook nil
|
||||||
|
"A hook run before evaluating org-tree-slide--display-tree-with-narrow")
|
||||||
|
(defvar org-tree-slide-after-narrow-hook nil
|
||||||
|
"A hook run after evaluating org-tree-slide--display-tree-with-narrow")
|
||||||
|
(defvar org-tree-slide-before-move-next-hook nil
|
||||||
|
"A hook run before moving to the next slide")
|
||||||
|
(defvar org-tree-slide-before-move-previous-hook nil
|
||||||
|
"A hook run before moving to the previous slide")
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(define-minor-mode org-tree-slide-mode
|
||||||
|
"A presentation tool for org-mode.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
- Set minimal recommendation settings in .emacs
|
||||||
|
(global-set-key (kbd \"<f8>\") 'org-tree-slide-mode)
|
||||||
|
(global-set-key (kbd \"S-<f8>\") 'org-tree-slide-skip-done-toggle)
|
||||||
|
- Open an org file
|
||||||
|
- Type <f8> to start org-tree-slide-mode
|
||||||
|
- Type <left>/<right> to move between trees
|
||||||
|
- To exit this minor mode, just type <f8> again.
|
||||||
|
|
||||||
|
Profiles:
|
||||||
|
|
||||||
|
- [ Simple ]
|
||||||
|
=> M-x `org-tree-slide-simple-profile'
|
||||||
|
|
||||||
|
1. No header display
|
||||||
|
2. No slide-in effect
|
||||||
|
3. The cursor will move to the head of buffer when exit
|
||||||
|
4. No slide number display in mode line
|
||||||
|
5. Display every type of tree
|
||||||
|
|
||||||
|
- [ Presentation ]
|
||||||
|
=> M-x `org-tree-slide-presentation-profile'
|
||||||
|
|
||||||
|
1. Display header
|
||||||
|
2. Enable slide-in effect
|
||||||
|
3. The cursor will move to the head of buffer when exit
|
||||||
|
4. Display slide number in mode line
|
||||||
|
5. Display every type of tree
|
||||||
|
|
||||||
|
- [ TODO Pursuit with narrowing ]
|
||||||
|
=> M-x `org-tree-slide-narrowing-control-profile'
|
||||||
|
|
||||||
|
1. No header display
|
||||||
|
2. No slide-in effect
|
||||||
|
3. The cursor will keep the same position when exit
|
||||||
|
4. Display slide number in mode line
|
||||||
|
5. Display TODO trees only
|
||||||
|
"
|
||||||
|
:init-value nil
|
||||||
|
:lighter (:eval (org-tree-slide--update-modeline))
|
||||||
|
:keymap org-tree-slide-mode-map
|
||||||
|
:group 'org-tree-slide
|
||||||
|
:require 'org
|
||||||
|
(if org-tree-slide-mode
|
||||||
|
(org-tree-slide--setup)
|
||||||
|
(org-tree-slide--abort)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-play-with-timer ()
|
||||||
|
"Start slideshow with setting a count down timer."
|
||||||
|
(interactive)
|
||||||
|
(org-timer-set-timer)
|
||||||
|
(unless (org-tree-slide--active-p)
|
||||||
|
(org-tree-slide-mode)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-without-init-play ()
|
||||||
|
"Start slideshow without the init play. Just enter org-tree-slide-mode."
|
||||||
|
(interactive)
|
||||||
|
(org-tree-slide-mode)
|
||||||
|
(widen)
|
||||||
|
(org-overview)
|
||||||
|
(goto-char 1))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-content ()
|
||||||
|
"Change the display for viewing content of the org file during
|
||||||
|
the slide view mode is active."
|
||||||
|
(interactive)
|
||||||
|
(when (org-tree-slide--active-p)
|
||||||
|
(org-tree-slide--hide-slide-header)
|
||||||
|
(org-tree-slide--move-to-the-first-heading)
|
||||||
|
(org-overview)
|
||||||
|
(org-content (if (> org-tree-slide-skip-outline-level 0)
|
||||||
|
(1- org-tree-slide-skip-outline-level)))
|
||||||
|
(message "<< CONTENT >>")))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-simple-profile ()
|
||||||
|
"Set variables for simple use.
|
||||||
|
`org-tree-slide-header' => nil
|
||||||
|
`org-tree-slide-slide-in-effect' => nil
|
||||||
|
`org-tree-slide-heading-emphasis' => nil
|
||||||
|
`org-tree-slide-cursor-init' => t
|
||||||
|
`org-tree-slide-modeline-display' => nil
|
||||||
|
`org-tree-slide-skip-done' => nil
|
||||||
|
`org-tree-slide-skip-comments' => t
|
||||||
|
"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-header nil)
|
||||||
|
(setq org-tree-slide-slide-in-effect nil)
|
||||||
|
(setq org-tree-slide-heading-emphasis nil)
|
||||||
|
(setq org-tree-slide-cursor-init t)
|
||||||
|
(setq org-tree-slide-modeline-display nil)
|
||||||
|
(setq org-tree-slide-skip-done nil)
|
||||||
|
(setq org-tree-slide-skip-comments t)
|
||||||
|
(message "simple profile: ON"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-presentation-profile ()
|
||||||
|
"Set variables for presentation use.
|
||||||
|
`org-tree-slide-header' => t
|
||||||
|
`org-tree-slide-slide-in-effect' => t
|
||||||
|
`org-tree-slide-heading-emphasis' => nil
|
||||||
|
`org-tree-slide-cursor-init' => t
|
||||||
|
`org-tree-slide-modeline-display' => 'outside
|
||||||
|
`org-tree-slide-skip-done' => nil
|
||||||
|
`org-tree-slide-skip-comments' => t
|
||||||
|
"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-header t)
|
||||||
|
(setq org-tree-slide-slide-in-effect t)
|
||||||
|
(setq org-tree-slide-heading-emphasis nil)
|
||||||
|
(setq org-tree-slide-cursor-init t)
|
||||||
|
(setq org-tree-slide-modeline-display 'outside)
|
||||||
|
(setq org-tree-slide-skip-done nil)
|
||||||
|
(setq org-tree-slide-skip-comments t)
|
||||||
|
(message "presentation profile: ON"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-narrowing-control-profile ()
|
||||||
|
"Set variables for TODO pursuit with narrowing.
|
||||||
|
`org-tree-slide-header' => nil
|
||||||
|
`org-tree-slide-slide-in-effect' => nil
|
||||||
|
`org-tree-slide-heading-emphasis' => nil
|
||||||
|
`org-tree-slide-cursor-init' => nil
|
||||||
|
`org-tree-slide-modeline-display' => 'lighter
|
||||||
|
`org-tree-slide-skip-done' => t
|
||||||
|
`org-tree-slide-skip-comments' => t
|
||||||
|
"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-header nil)
|
||||||
|
(setq org-tree-slide-slide-in-effect nil)
|
||||||
|
(setq org-tree-slide-heading-emphasis nil)
|
||||||
|
(setq org-tree-slide-cursor-init nil)
|
||||||
|
(setq org-tree-slide-modeline-display 'lighter)
|
||||||
|
(setq org-tree-slide-skip-done t)
|
||||||
|
(setq org-tree-slide-skip-comments t)
|
||||||
|
(message "narrowing control profile: ON"))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-display-header-toggle ()
|
||||||
|
"Toggle displaying the slide header"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-header (not org-tree-slide-header))
|
||||||
|
(unless org-tree-slide-header
|
||||||
|
(org-tree-slide--hide-slide-header))
|
||||||
|
(org-tree-slide--display-tree-with-narrow))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-slide-in-effect-toggle ()
|
||||||
|
"Toggle using slide-in effect"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-slide-in-effect (not org-tree-slide-slide-in-effect))
|
||||||
|
(org-tree-slide--display-tree-with-narrow))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-heading-emphasis-toggle ()
|
||||||
|
"Toggle applying emphasis to heading"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-heading-emphasis (not org-tree-slide-heading-emphasis))
|
||||||
|
(org-tree-slide--apply-custom-heading-face org-tree-slide-heading-emphasis))
|
||||||
|
|
||||||
|
(defvar org-tree-slide--previous-line 0)
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-skip-done-toggle ()
|
||||||
|
"Toggle show TODO item only or not"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-skip-done (not org-tree-slide-skip-done))
|
||||||
|
(setq org-tree-slide--previous-line -1) ; to update modeline intentionally
|
||||||
|
(when org-tree-slide-header
|
||||||
|
(org-tree-slide--show-slide-header))
|
||||||
|
(if org-tree-slide-skip-done
|
||||||
|
(message "TODO Pursuit: ON") (message "TODO Pursuit: OFF")))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-tree-slide-skip-comments-toggle ()
|
||||||
|
"Toggle show COMMENT item or not"
|
||||||
|
(interactive)
|
||||||
|
(setq org-tree-slide-skip-comments (not org-tree-slide-skip-comments))
|
||||||
|
(if org-tree-slide-skip-comments
|
||||||
|
(message "COMMENT: HIDE") (message "COMMENT: SHOW")))
|
||||||
|
|
||||||
|
(defun org-tree-slide-move-next-tree ()
|
||||||
|
"Display the next slide"
|
||||||
|
(interactive)
|
||||||
|
(when (org-tree-slide--active-p)
|
||||||
|
(unless (equal org-tree-slide-modeline-display 'outside)
|
||||||
|
(message " Next >>"))
|
||||||
|
(cond
|
||||||
|
((and (org-tree-slide--narrowing-p) ;displaying a slide, not the contents
|
||||||
|
(org-tree-slide--last-tree-p (progn (beginning-of-line) (point)))) ;the last subtree
|
||||||
|
(org-tree-slide-content))
|
||||||
|
((or
|
||||||
|
(or (and (org-tree-slide--before-first-heading-p)
|
||||||
|
(not (org-at-heading-p)))
|
||||||
|
(and (= (point-at-bol) 1) (not (org-tree-slide--narrowing-p))))
|
||||||
|
(or (org-tree-slide--first-heading-with-narrow-p)
|
||||||
|
(not (org-at-heading-p))))
|
||||||
|
(run-hooks 'org-tree-slide-before-move-next-hook)
|
||||||
|
(widen)
|
||||||
|
(org-tree-slide--outline-next-heading)
|
||||||
|
(org-tree-slide--display-tree-with-narrow))
|
||||||
|
;; stay the same slide (for CONTENT MODE, on the subtrees)
|
||||||
|
(t nil (org-tree-slide--display-tree-with-narrow)))
|
||||||
|
;; (when (and org-tree-slide-skip-done (looking-at (concat "^\\*+ " org-not-done-regexp))) (org-clock-in) )
|
||||||
|
))
|
||||||
|
|
||||||
|
(defun org-tree-slide-move-previous-tree ()
|
||||||
|
"Display the previous slide"
|
||||||
|
(interactive)
|
||||||
|
(when (org-tree-slide--active-p)
|
||||||
|
(unless (equal org-tree-slide-modeline-display 'outside)
|
||||||
|
(message "<< Previous"))
|
||||||
|
(org-tree-slide--hide-slide-header) ; for at the first heading
|
||||||
|
(run-hooks 'org-tree-slide-before-move-previous-hook)
|
||||||
|
(widen)
|
||||||
|
(cond
|
||||||
|
((org-tree-slide--before-first-heading-p)
|
||||||
|
(message "before first heading (org-tree-slide)" ))
|
||||||
|
((not (org-at-heading-p))
|
||||||
|
(org-tree-slide--outline-previous-heading)
|
||||||
|
(org-tree-slide--outline-previous-heading))
|
||||||
|
(t (org-tree-slide--outline-previous-heading)))
|
||||||
|
;; (when (and org-tree-slide-skip-done (looking-at (concat "^\\*+ " org-not-done-regexp))) (org-clock-in) )
|
||||||
|
(org-tree-slide--display-tree-with-narrow)
|
||||||
|
;; To avoid error of missing header in Emacs24
|
||||||
|
(if (= emacs-major-version 24)
|
||||||
|
(goto-char (point-min)))))
|
||||||
|
|
||||||
|
;;; Internal functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
(defvar org-tree-slide--slide-number nil)
|
||||||
|
(make-variable-buffer-local 'org-tree-slide--slide-number)
|
||||||
|
|
||||||
|
(defvar org-tree-slide--lighter " TSlide"
|
||||||
|
"Lighter for org-tree-slide.
|
||||||
|
This is displayed by default if `org-tree-slide-modeline-display' is `nil'.")
|
||||||
|
|
||||||
|
(defun org-tree-slide--line-number-at-pos ()
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(line-number-at-pos))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--update-modeline ()
|
||||||
|
(when (org-tree-slide--active-p)
|
||||||
|
(cond
|
||||||
|
((equal org-tree-slide-modeline-display 'lighter)
|
||||||
|
(setq org-tree-slide--slide-number
|
||||||
|
(format " %s" (org-tree-slide--count-slide (point))))
|
||||||
|
(setq org-tree-slide--previous-line (org-tree-slide--line-number-at-pos))
|
||||||
|
org-tree-slide--slide-number)
|
||||||
|
;; just return the current org-tree-slide--slide-number quickly.
|
||||||
|
((equal org-tree-slide-modeline-display 'outside)
|
||||||
|
org-tree-slide--slide-number)
|
||||||
|
(t org-tree-slide--lighter))))
|
||||||
|
|
||||||
|
(defvar org-tree-slide--header-overlay nil
|
||||||
|
"Flag to check the status of overlay for a slide header.")
|
||||||
|
|
||||||
|
(defun org-tree-slide--setup ()
|
||||||
|
(when (org-tree-slide--active-p)
|
||||||
|
(org-tree-slide--play)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--abort ()
|
||||||
|
(when (equal major-mode 'org-mode)
|
||||||
|
(org-tree-slide--stop)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--play ()
|
||||||
|
"Start slide view with the first tree of the org-mode buffer."
|
||||||
|
(run-hooks 'org-tree-slide-mode-play-hook)
|
||||||
|
(run-hooks 'org-tree-slide-play-hook)
|
||||||
|
(org-tree-slide--apply-local-header-to-slide-header)
|
||||||
|
(when org-tree-slide-heading-emphasis
|
||||||
|
(org-tree-slide--apply-custom-heading-face t))
|
||||||
|
(when (or org-tree-slide-cursor-init (org-tree-slide--before-first-heading-p))
|
||||||
|
(org-tree-slide--move-to-the-first-heading))
|
||||||
|
(org-tree-slide--beginning-of-tree)
|
||||||
|
(when (org-tree-slide--heading-skip-p)
|
||||||
|
(org-tree-slide--outline-next-heading))
|
||||||
|
(org-tree-slide--display-tree-with-narrow)
|
||||||
|
(when org-tree-slide-activate-message
|
||||||
|
(message "%s" org-tree-slide-activate-message)))
|
||||||
|
|
||||||
|
(defvar org-tree-slide-startup "overview"
|
||||||
|
"If you have `#+STARTUP:' line in your org buffer, the org buffer will
|
||||||
|
be shown with corresponding status (content, showall, overview:default).")
|
||||||
|
|
||||||
|
(defun org-tree-slide--stop ()
|
||||||
|
"Stop the slide view, and redraw the org-mode buffer with #+STARTUP:."
|
||||||
|
(widen)
|
||||||
|
(org-show-siblings)
|
||||||
|
(when (or org-tree-slide-cursor-init (org-tree-slide--before-first-heading-p))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(org-overview)
|
||||||
|
(cond ((equal "content" org-tree-slide-startup)
|
||||||
|
(message "CONTENT: %s" org-tree-slide-startup)
|
||||||
|
(org-content))
|
||||||
|
((equal "showall" org-tree-slide-startup)
|
||||||
|
(message "SHOW ALL: %s" org-tree-slide-startup)
|
||||||
|
(org-cycle '(64)))
|
||||||
|
(t nil)))
|
||||||
|
(org-tree-slide--hide-slide-header)
|
||||||
|
(when org-timer-start-time
|
||||||
|
(org-timer-stop))
|
||||||
|
(when org-tree-slide-heading-emphasis
|
||||||
|
(org-tree-slide--apply-custom-heading-face nil))
|
||||||
|
;; (when (and org-tree-slide-skip-done (looking-at (concat "^\\*+ " org-not-done-regexp))) (when (org-clocking-p) (org-clock-out) ) )
|
||||||
|
(run-hooks 'org-tree-slide-mode-stop-hook)
|
||||||
|
(run-hooks 'org-tree-slide-stop-hook)
|
||||||
|
(when org-tree-slide-deactivate-message
|
||||||
|
(message "%s" org-tree-slide-deactivate-message)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--display-tree-with-narrow ()
|
||||||
|
"Show a tree with narrowing and also set a header at the head of slide."
|
||||||
|
(run-hooks 'org-tree-slide-mode-before-narrow-hook)
|
||||||
|
(run-hooks 'org-tree-slide-before-narrow-hook)
|
||||||
|
(when (equal org-tree-slide-modeline-display 'outside)
|
||||||
|
(setq org-tree-slide--slide-number
|
||||||
|
(format " %s" (org-tree-slide--count-slide (point))))
|
||||||
|
(setq org-tree-slide--previous-line (org-tree-slide--line-number-at-pos)))
|
||||||
|
(goto-char (point-at-bol))
|
||||||
|
(unless (org-tree-slide--before-first-heading-p)
|
||||||
|
(hide-subtree) ; support CONTENT (subtrees are shown)
|
||||||
|
(org-show-entry)
|
||||||
|
;; If this is the last level to be displayed, show the full content
|
||||||
|
(if (and (not org-tree-slide-fold-subtrees-skipped)
|
||||||
|
(org-tree-slide--heading-level-skip-p (1+ (org-outline-level))))
|
||||||
|
(org-tree-slide--show-subtree)
|
||||||
|
(show-children))
|
||||||
|
;; (org-cycle-hide-drawers 'all) ; disabled due to performance reduction
|
||||||
|
(org-narrow-to-subtree))
|
||||||
|
(when org-tree-slide-slide-in-effect
|
||||||
|
(org-tree-slide--slide-in org-tree-slide-slide-in-blank-lines))
|
||||||
|
(when org-tree-slide-header
|
||||||
|
(org-tree-slide--show-slide-header))
|
||||||
|
(run-hooks 'org-tree-slide-after-narrow-hook)
|
||||||
|
(run-hooks 'org-tree-slide-mode-after-narrow-hook))
|
||||||
|
|
||||||
|
(defun org-tree-slide--show-subtree ()
|
||||||
|
"Show everything after this heading at deeper levels except COMMENT items."
|
||||||
|
(save-excursion
|
||||||
|
(outline-back-to-heading)
|
||||||
|
(outline-map-region
|
||||||
|
(lambda ()
|
||||||
|
(if (org-tree-slide--heading-skip-comment-p)
|
||||||
|
(hide-subtree)
|
||||||
|
(show-subtree)
|
||||||
|
(org-cycle-hide-drawers 'all)))
|
||||||
|
(point)
|
||||||
|
(progn (outline-end-of-subtree)
|
||||||
|
(if (eobp) (point-max) (1+ (point)))))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--outline-next-heading ()
|
||||||
|
(org-tree-slide--outline-select-method
|
||||||
|
(org-tree-slide--outline-skip-type
|
||||||
|
(if (outline-next-heading) t 'last)
|
||||||
|
(org-outline-level))
|
||||||
|
'next))
|
||||||
|
|
||||||
|
(defun org-tree-slide--outline-previous-heading ()
|
||||||
|
(org-tree-slide--outline-select-method
|
||||||
|
(org-tree-slide--outline-skip-type
|
||||||
|
(if (outline-previous-heading) t 'first)
|
||||||
|
(org-outline-level))
|
||||||
|
'previous))
|
||||||
|
|
||||||
|
(defvar org-tree-slide--all-skipped t
|
||||||
|
"A flag to know if all trees are skipped")
|
||||||
|
|
||||||
|
(defun org-tree-slide--outline-select-method (action direction)
|
||||||
|
(cond ((and (equal action 'last) (equal direction 'next))
|
||||||
|
(unless org-tree-slide--all-skipped
|
||||||
|
(org-tree-slide--outline-previous-heading))) ; Return back.
|
||||||
|
((and (equal action 'first) (equal direction 'previous))
|
||||||
|
(unless org-tree-slide--all-skipped
|
||||||
|
(org-tree-slide--move-to-the-first-heading))) ; Stay first heading
|
||||||
|
((and (equal action 'skip) (equal direction 'next))
|
||||||
|
(org-tree-slide--outline-next-heading)) ; recursive call
|
||||||
|
((and (equal action 'skip) (equal direction 'previous))
|
||||||
|
(org-tree-slide--outline-previous-heading)) ; recursive call
|
||||||
|
(t
|
||||||
|
(setq org-tree-slide--all-skipped nil)
|
||||||
|
nil)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--heading-skip-p ()
|
||||||
|
"This method assume the cursor exist at the heading.
|
||||||
|
** COMMENT ; t
|
||||||
|
hoge ; nil
|
||||||
|
hoge ; nil
|
||||||
|
*** hoge ; nil
|
||||||
|
"
|
||||||
|
(or (or (org-tree-slide--heading-done-skip-p)
|
||||||
|
(org-tree-slide--heading-level-skip-p))
|
||||||
|
(org-tree-slide--heading-skip-comment-p)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--heading-level-skip-p (&optional level)
|
||||||
|
(and (> org-tree-slide-skip-outline-level 0)
|
||||||
|
(<= org-tree-slide-skip-outline-level (or level (org-outline-level)))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--heading-done-skip-p ()
|
||||||
|
(and org-tree-slide-skip-done
|
||||||
|
(not
|
||||||
|
(looking-at
|
||||||
|
;; 6.33x does NOT support org-outline-regexp-bol
|
||||||
|
(concat "^\\*+ " org-not-done-regexp)))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--heading-skip-comment-p ()
|
||||||
|
(and org-tree-slide-skip-comments
|
||||||
|
(looking-at (concat "^\\*+ " org-comment-string))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--outline-skip-type (has-target-outline current-level)
|
||||||
|
(cond ((equal has-target-outline 'last) 'last)
|
||||||
|
((equal has-target-outline 'first) 'first)
|
||||||
|
((org-tree-slide--heading-skip-p) 'skip)
|
||||||
|
(t nil)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--slide-in (blank-lines)
|
||||||
|
(let ((min-line -1))
|
||||||
|
(when org-tree-slide-header
|
||||||
|
(setq min-line 2))
|
||||||
|
(while (< min-line blank-lines)
|
||||||
|
(org-tree-slide--set-slide-header blank-lines)
|
||||||
|
(sit-for org-tree-slide-slide-in-waiting)
|
||||||
|
(setq blank-lines (1- blank-lines)))))
|
||||||
|
|
||||||
|
(defvar org-tree-slide-title nil
|
||||||
|
"If you have `#+TITLE:' line in your org buffer, it wil be used as a title
|
||||||
|
of the slide. If the buffer has no `#+TITLE:' line, the name of
|
||||||
|
current buffer will be displayed.")
|
||||||
|
|
||||||
|
(defvar org-tree-slide-email nil
|
||||||
|
"If you have `#+EMAIL:' line in your org buffer, it will be used as
|
||||||
|
an address of the slide.")
|
||||||
|
|
||||||
|
(defvar org-tree-slide-author nil
|
||||||
|
"If you have `#+AUTHOR:' line in your org buffer, it will be used as
|
||||||
|
a name of the slide author.")
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-breadcrumbs " > "
|
||||||
|
"Display breadcrumbs in the slide header.
|
||||||
|
|
||||||
|
If non-nil, it should be a string used as a delimiter used to
|
||||||
|
concat the headers."
|
||||||
|
:type '(choice (const :tag "Don't display breadcrumbs" nil)
|
||||||
|
(string :tag "Delimiter"))
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defcustom org-tree-slide-breadcrumbs-hide-todo-state t
|
||||||
|
"If non-nil, hide TODO states in the breadcrumbs."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-tree-slide)
|
||||||
|
|
||||||
|
(defun org-tree-slide--apply-local-header-to-slide-header ()
|
||||||
|
(save-excursion
|
||||||
|
(org-tree-slide--move-to-the-first-heading)
|
||||||
|
(let ((limit (point)))
|
||||||
|
(org-tree-slide--set-header-var-by-regxep
|
||||||
|
'org-tree-slide-title "#\\+TITLE:[ \t]*\\(.*\\)$" limit)
|
||||||
|
(org-tree-slide--set-header-var-by-regxep
|
||||||
|
'org-tree-slide-author "#\\+AUTHOR:[ \t]*\\(.*\\)$" limit)
|
||||||
|
(org-tree-slide--set-header-var-by-regxep
|
||||||
|
'org-tree-slide-email "#\\+EMAIL:[ \t]*\\(.*\\)$" limit)
|
||||||
|
(org-tree-slide--set-header-var-by-regxep
|
||||||
|
'org-tree-slide-startup "#\\+STARTUP:[ \t]*\\(.*\\)$" limit))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--set-header-var-by-regxep (header-variable regexp limit)
|
||||||
|
(goto-char 1)
|
||||||
|
(set header-variable
|
||||||
|
(if (re-search-forward regexp limit t) (match-string 1) nil)))
|
||||||
|
|
||||||
|
(defface org-tree-slide-header-overlay-face
|
||||||
|
'((((class color) (background dark))
|
||||||
|
(:bold t :foreground "white" :background "black"))
|
||||||
|
(((class color) (background light))
|
||||||
|
(:bold t :foreground "black" :background "white"))
|
||||||
|
(t (:bold t :foreground "black" :background "white")))
|
||||||
|
"Face for org-tree-slide--header-overlay")
|
||||||
|
|
||||||
|
(defun org-tree-slide--get-parents (&optional delim)
|
||||||
|
"Get parent headlines and concat them with DELIM."
|
||||||
|
(setq delim (or delim " > "))
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(let ((parents nil))
|
||||||
|
(while (org-up-heading-safe)
|
||||||
|
(push (org-get-heading
|
||||||
|
'no-tags
|
||||||
|
org-tree-slide-breadcrumbs-hide-todo-state)
|
||||||
|
parents))
|
||||||
|
(mapconcat 'identity parents delim)))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--set-slide-header (blank-lines)
|
||||||
|
(org-tree-slide--hide-slide-header)
|
||||||
|
(setq org-tree-slide--header-overlay
|
||||||
|
(make-overlay (point-min) (+ 1 (point-min))))
|
||||||
|
(overlay-put org-tree-slide--header-overlay 'after-string " ")
|
||||||
|
(overlay-put org-tree-slide--header-overlay
|
||||||
|
'face
|
||||||
|
'org-tree-slide-header-overlay-face)
|
||||||
|
(if org-tree-slide-header
|
||||||
|
(overlay-put org-tree-slide--header-overlay 'display
|
||||||
|
(concat (if org-tree-slide-title org-tree-slide-title
|
||||||
|
(buffer-name))
|
||||||
|
"\n"
|
||||||
|
(format-time-string "%Y-%m-%d") " "
|
||||||
|
(when org-tree-slide-author
|
||||||
|
(concat org-tree-slide-author " "))
|
||||||
|
(when org-tree-slide-email
|
||||||
|
(concat "<" org-tree-slide-email ">"))
|
||||||
|
(when org-tree-slide-breadcrumbs
|
||||||
|
(concat "\n" (org-tree-slide--get-parents
|
||||||
|
org-tree-slide-breadcrumbs)))
|
||||||
|
(org-tree-slide--get-blank-lines blank-lines)))
|
||||||
|
(overlay-put org-tree-slide--header-overlay 'display
|
||||||
|
(org-tree-slide--get-blank-lines blank-lines))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--get-blank-lines (lines)
|
||||||
|
(let ((breaks ""))
|
||||||
|
(while (< 0 lines)
|
||||||
|
(setq lines (1- lines))
|
||||||
|
(setq breaks (concat breaks "\n")))
|
||||||
|
breaks))
|
||||||
|
|
||||||
|
(defun org-tree-slide--show-slide-header ()
|
||||||
|
(org-tree-slide--set-slide-header 2))
|
||||||
|
|
||||||
|
(defun org-tree-slide--hide-slide-header ()
|
||||||
|
(when org-tree-slide--header-overlay
|
||||||
|
(delete-overlay org-tree-slide--header-overlay)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--move-to-the-first-heading ()
|
||||||
|
(setq org-tree-slide--all-skipped t)
|
||||||
|
(widen)
|
||||||
|
(goto-char 1)
|
||||||
|
(unless (looking-at "^\\*+ ")
|
||||||
|
(outline-next-heading))
|
||||||
|
(when (org-tree-slide--heading-skip-p)
|
||||||
|
(setq org-tree-slide--all-skipped t)
|
||||||
|
(org-tree-slide--outline-next-heading)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--apply-custom-heading-face (status)
|
||||||
|
"Change status of heading face."
|
||||||
|
(unless org-tree-slide-never-touch-face
|
||||||
|
(cond (status
|
||||||
|
(custom-set-faces
|
||||||
|
'(org-level-2 ((t (:inherit org-tree-slide-heading-level-2))))
|
||||||
|
'(org-level-3 ((t (:inherit org-tree-slide-heading-level-3))))))
|
||||||
|
(t
|
||||||
|
(custom-set-faces
|
||||||
|
'(org-level-2 ((t (:inherit org-tree-slide-heading-level-2-init))))
|
||||||
|
'(org-level-3 ((t (:inherit org-tree-slide-heading-level-3-init)))))
|
||||||
|
))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--count-slide (&optional pos)
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let ((count 0)
|
||||||
|
(current-slide 0)
|
||||||
|
(current-point (or pos (point))))
|
||||||
|
(when (and (looking-at "^\\*+ ") (not (org-tree-slide--heading-skip-p)))
|
||||||
|
(setq count 1)
|
||||||
|
(setq current-slide 1))
|
||||||
|
(while (outline-next-heading)
|
||||||
|
(when (not (org-tree-slide--heading-skip-p))
|
||||||
|
(setq count (1+ count))
|
||||||
|
(when (>= current-point (point))
|
||||||
|
(setq current-slide (1+ current-slide)))))
|
||||||
|
(cond
|
||||||
|
((= count 0) "[-/-]") ; no headings
|
||||||
|
((= current-slide 0) (format "[-/%d]" count)) ; before first heading
|
||||||
|
(t
|
||||||
|
(format "[%d/%d]" current-slide count)))))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--active-p ()
|
||||||
|
(and org-tree-slide-mode (equal major-mode 'org-mode)))
|
||||||
|
|
||||||
|
(defun org-tree-slide--narrowing-p ()
|
||||||
|
"Check the current status if narrowing or not"
|
||||||
|
(not (and (= (point-min) 1) (= (point-max) (1+ (buffer-size))))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--before-first-heading-p ()
|
||||||
|
"Extension of org-before-first-heading-p to support org 6.33x.
|
||||||
|
#+TITLE: title ; t
|
||||||
|
#+STARTUP: content ; t
|
||||||
|
* first ; t
|
||||||
|
hoge ; nil
|
||||||
|
** second ; nil
|
||||||
|
** third ; nil
|
||||||
|
"
|
||||||
|
(and (org-before-first-heading-p) (not (org-tree-slide--narrowing-p))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--first-heading-with-narrow-p ()
|
||||||
|
"Check the current point is on the first heading with narrowing.
|
||||||
|
** first ; t
|
||||||
|
hoge ; nil
|
||||||
|
hoge ; nil
|
||||||
|
*** second ; nil
|
||||||
|
hoge ; nil
|
||||||
|
*** third ; nil
|
||||||
|
"
|
||||||
|
(and (org-tree-slide--narrowing-p) (= (point-at-bol) (point-min))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--last-tree-p (target)
|
||||||
|
"Check if the target point is in the last heading or it's body.
|
||||||
|
** n-1 ; nil
|
||||||
|
** n ; t
|
||||||
|
hoge ; t
|
||||||
|
"
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(goto-char target)
|
||||||
|
(if (org-tree-slide--beginning-of-tree)
|
||||||
|
(= (point) (org-tree-slide--last-heading-position))
|
||||||
|
nil))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--last-heading-position ()
|
||||||
|
"Return the position of the last heading.
|
||||||
|
If the position does not exist in the buffer, then return nil."
|
||||||
|
(save-excursion
|
||||||
|
(save-restriction
|
||||||
|
(goto-char (buffer-size))
|
||||||
|
(org-tree-slide--beginning-of-tree))))
|
||||||
|
|
||||||
|
(defun org-tree-slide--beginning-of-tree ()
|
||||||
|
"Return beginning point of the line, or t.
|
||||||
|
If the position does not exist in the buffer, then return nil."
|
||||||
|
(beginning-of-line)
|
||||||
|
(if (and (not (org-tree-slide--heading-skip-p)) ;if the header has to be skipped
|
||||||
|
(org-at-heading-p))
|
||||||
|
(point)
|
||||||
|
(progn
|
||||||
|
(outline-previous-heading) ;go to previous heading
|
||||||
|
(org-tree-slide--beginning-of-tree)) ;recursion until a visible heading is found
|
||||||
|
)) ; return position or nil.
|
||||||
|
|
||||||
|
(provide 'org-tree-slide)
|
||||||
|
|
||||||
|
;;; org-tree-slide.el ends here
|
||||||
48
site-lisp/smerge.el
Normal file
48
site-lisp/smerge.el
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
;;; smerge-mode.el --- Minor mode for the Meson build system files -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; This is a minor mode to resolve via diff3.
|
||||||
|
;; Important keybindings:
|
||||||
|
;; smerge-next bound to smerge-command-prefixn to move to next conflict.
|
||||||
|
;; smerge-previous bound to smerge-command-prefixp to move to previous conflict.
|
||||||
|
;; smerge-keep-current bound to smerge-command-prefixRET to keep the version the cursor is on.
|
||||||
|
;; smerge-keep-mine bound to smerge-command-prefixm to keep your changes.
|
||||||
|
;; smerge-keep-other bound to smerge-command-prefixo to keep other changes.
|
||||||
|
;; smerge-ediff bound to smerge-command-prefixE to start an ediff session to merge the conflicts. This is same as vc-resolve-conflicts (thanks @phils and @Malabarba for pointing this out).
|
||||||
|
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; Default prefix
|
||||||
|
;; I find the default prefix for smerge-mode C-c^ cumbersome
|
||||||
|
;; next lines change it to to 'C-c v'
|
||||||
|
(setq smerge-command-prefix "\C-cv")
|
||||||
|
|
||||||
|
;; Enabling smerge-mode automatically
|
||||||
|
(defun my-enable-smerge-maybe ()
|
||||||
|
(when (and buffer-file-name (vc-backend buffer-file-name))
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (point-min))
|
||||||
|
(when (re-search-forward "^<<<<<<< " nil t)
|
||||||
|
(smerge-mode +1)))))
|
||||||
|
|
||||||
|
(add-hook 'buffer-list-update-hook #'my-enable-smerge-maybe)
|
||||||
|
|
||||||
|
|
||||||
|
;;; smerge-mode.el ends here
|
||||||
|
|
||||||
|
;;(progn (mapatoms (lambda (x) (when (string-prefix-p "smerge" (symbol-name x)) (makunbound x)))) (eval-buffer))
|
||||||
1205
site-lisp/use-package.el
Normal file
1205
site-lisp/use-package.el
Normal file
File diff suppressed because it is too large
Load Diff
76
site-start.d/00-my-setup.el
Normal file
76
site-start.d/00-my-setup.el
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
;;; 00-my-setup.el --- basic personal definitions
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; to debug the startup, run Emacs with folloging flag
|
||||||
|
;; emacs --debug-init
|
||||||
|
;;;
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; regular used custom function
|
||||||
|
(defun reload-init-file ()
|
||||||
|
"Reload my init file."
|
||||||
|
(interactive)
|
||||||
|
(load-file user-init-file))
|
||||||
|
|
||||||
|
(bind-key "C-c M-l" 'reload-init-file)
|
||||||
|
|
||||||
|
;; surpress bloat messages
|
||||||
|
(setq inhibit-startup-message t
|
||||||
|
initial-scratch-message ""
|
||||||
|
inhibit-startup-echo-area-message t
|
||||||
|
inhibit-splash-screen t)
|
||||||
|
|
||||||
|
;; line wrapping
|
||||||
|
(setq new-line-add-newlines nil)
|
||||||
|
(setq-default truncate-lines t)
|
||||||
|
(setq truncate-partial-width-windows nil)
|
||||||
|
|
||||||
|
;; symbol and cursor handling
|
||||||
|
(global-prettify-symbols-mode +1)
|
||||||
|
(setq x-stretch-cursor t)
|
||||||
|
|
||||||
|
;; to window panes organized horizontally
|
||||||
|
;; (split-window-horizontally)
|
||||||
|
|
||||||
|
;; python mode adaptions
|
||||||
|
(add-hook 'python-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(setq indent-tabs-mode t)
|
||||||
|
(setq python-indent 8)
|
||||||
|
(setq tab-width 4)))
|
||||||
|
|
||||||
|
;; enable 'linux' as default c-mode minor mode
|
||||||
|
(add-hook 'c-mode-common-hook
|
||||||
|
'linux)
|
||||||
|
|
||||||
|
;; auto enable modes
|
||||||
|
(semantic-mode 1)
|
||||||
|
|
||||||
|
;; auto enable recent files
|
||||||
|
(recentf-mode 1)
|
||||||
|
|
||||||
|
;; where are my encrypted auth keys
|
||||||
|
(setq auth-sources
|
||||||
|
'((:source "~/.emacs.d/secrets/.authinfo.gpg")))
|
||||||
|
|
||||||
|
;; automactic handling of whitespace cleanup
|
||||||
|
(add-hook 'before-save-hook 'whitespace-cleanup)
|
||||||
|
|
||||||
|
;; font settings
|
||||||
|
(set-default-font "Source Code Pro" nil t)
|
||||||
|
(set-face-attribute 'default nil :height 110)
|
||||||
|
|
||||||
|
;; prettify symbols
|
||||||
|
(global-prettify-symbols-mode +1)
|
||||||
|
|
||||||
|
;; save Emacs backup files in one central directory, not cluttering the filesystem
|
||||||
|
(setq backup-directory-alist
|
||||||
|
`(("." . ,(expand-file-name
|
||||||
|
(concat user-emacs-directory "backups")))))
|
||||||
|
|
||||||
|
;; shorten yes or no dialog
|
||||||
|
(fset 'yes-or-no-p 'y-or-n-p)
|
||||||
|
|
||||||
|
(provide '00-my-setup)
|
||||||
|
;;; 00-my-setup.el ends here
|
||||||
11
site-start.d/02-load-path.el
Normal file
11
site-start.d/02-load-path.el
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
;;; 02-load-path.el --- customize loadpath
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; load-path will enable to autoload your custom lisp code
|
||||||
|
;; that is not handled via packages (like use-package)
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(add-to-list 'load-path "~/.emacs.d/site-lisp")
|
||||||
|
|
||||||
|
(provide '02-load-path)
|
||||||
|
;;; 401-rust.el ends here
|
||||||
19
site-start.d/101-async.el
Normal file
19
site-start.d/101-async.el
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
;;; 101-async.el --- asynchronous code execution
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Async enables asynchronous processing in Emacs, as well as some basic implementations of asynchronous capabilities
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(use-package async
|
||||||
|
:init
|
||||||
|
(autoload 'dired-async-mode "dired-async.el" nil t)
|
||||||
|
(dired-async-mode 1)
|
||||||
|
(async-bytecomp-package-mode 1)
|
||||||
|
(autoload 'dired-async-mode "dired-async.el" nil t)
|
||||||
|
(async-bytecomp-package-mode 1)
|
||||||
|
(dired-async-mode 1)
|
||||||
|
(require 'smtpmail-async)
|
||||||
|
(setq send-mail-function 'async-smtpmail-send-it))
|
||||||
|
|
||||||
|
(provide '101-async)
|
||||||
|
;;; 101-async.el ends here
|
||||||
29
site-start.d/102-hydra.el
Normal file
29
site-start.d/102-hydra.el
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
;;; 102-hydra.el --- tie related commands into a family of short bindings
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Hydra enables you to tie related commands into a family of short bindings
|
||||||
|
;; with a common prefix - a Hydra.
|
||||||
|
;; reference: https://github.com/abo-abo/hydra
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(use-package hydra
|
||||||
|
:config
|
||||||
|
(setq hydra-lv nil))
|
||||||
|
|
||||||
|
;; Zooming
|
||||||
|
(defhydra hydra-zoom ()
|
||||||
|
"zoom"
|
||||||
|
("+" text-scale-increase "in")
|
||||||
|
("=" text-scale-increase "in")
|
||||||
|
("-" text-scale-decrease "out")
|
||||||
|
("_" text-scale-decrease "out")
|
||||||
|
("0" (text-scale-adjust 0) "reset")
|
||||||
|
("q" nil "quit" :color blue))
|
||||||
|
|
||||||
|
(bind-keys ("C-x C-0" . hydra-zoom/body)
|
||||||
|
("C-x C-=" . hydra-zoom/body)
|
||||||
|
("C-x C--" . hydra-zoom/body)
|
||||||
|
("C-x C-+" . hydra-zoom/body))
|
||||||
|
|
||||||
|
(provide '102-hydra)
|
||||||
|
;;; 102-hydra.el ends here
|
||||||
71
site-start.d/103-ivy-councel.el
Normal file
71
site-start.d/103-ivy-councel.el
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
;;; 102-ivy-councel.el --- Completion framework for Emacs
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Ivy - a generic completion frontend for Emacs,
|
||||||
|
;; Swiper - isearch with an overview
|
||||||
|
;; Councel - it consumes Ivy and provides useful commands
|
||||||
|
|
||||||
|
;; Reference: https://github.com/abo-abo/swiper
|
||||||
|
;; Presentation: https://writequit.org/denver-emacs/presentations/2017-04-11-ivy.html
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(use-package counsel
|
||||||
|
:bind (("C-x C-f" . counsel-find-file)
|
||||||
|
("C-x C-m" . counsel-M-x)
|
||||||
|
("C-x C-f" . counsel-find-file)
|
||||||
|
("C-h f" . counsel-describe-function)
|
||||||
|
("C-h v" . counsel-describe-variable)
|
||||||
|
("M-i" . counsel-imenu)
|
||||||
|
("M-I" . counsel-imenu)
|
||||||
|
("C-c i" . counsel-unicode-char)
|
||||||
|
:map read-expression-map
|
||||||
|
("C-r" . counsel-expression-history)))
|
||||||
|
|
||||||
|
(use-package swiper
|
||||||
|
:bind (("C-s" . swiper)
|
||||||
|
("C-r" . swiper)
|
||||||
|
("C-c C-r" . ivy-resume)
|
||||||
|
:map ivy-minibuffer-map
|
||||||
|
("C-SPC" . ivy-restrict-to-matches))
|
||||||
|
:init
|
||||||
|
(ivy-mode 1)
|
||||||
|
:config
|
||||||
|
(setq ivy-count-format "(%d/%d) "
|
||||||
|
ivy-display-style 'fancy
|
||||||
|
ivy-height 4
|
||||||
|
ivy-use-virtual-buffers t
|
||||||
|
ivy-initial-inputs-alist () ;; http://irreal.org/blog/?p=6512
|
||||||
|
enable-recursive-minibuffers t))
|
||||||
|
|
||||||
|
(use-package all-the-icons)
|
||||||
|
|
||||||
|
(use-package ivy-rich
|
||||||
|
:after ivy
|
||||||
|
:config
|
||||||
|
;; All the icon support to ivy-rich
|
||||||
|
(defun ivy-rich-switch-buffer-icon (candidate)
|
||||||
|
(with-current-buffer
|
||||||
|
(get-buffer candidate)
|
||||||
|
(all-the-icons-icon-for-mode major-mode)))
|
||||||
|
|
||||||
|
(setq ivy-rich--display-transformers-list
|
||||||
|
'(ivy-switch-buffer
|
||||||
|
(:columns
|
||||||
|
((ivy-rich-switch-buffer-icon (:width 2))
|
||||||
|
(ivy-rich-candidate (:width 30))
|
||||||
|
(ivy-rich-switch-buffer-size (:width 7))
|
||||||
|
(ivy-rich-switch-buffer-indicators (:width 4 :face error :align right))
|
||||||
|
(ivy-rich-switch-buffer-major-mode (:width 12 :face warning))
|
||||||
|
(ivy-rich-switch-buffer-project (:width 15 :face success))
|
||||||
|
(ivy-rich-switch-buffer-path (:width (lambda (x) (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.3))))))
|
||||||
|
:predicate
|
||||||
|
(lambda (cand) (get-buffer cand)))))
|
||||||
|
|
||||||
|
;; Add custom icons for various modes that can break ivy-rich
|
||||||
|
(add-to-list 'all-the-icons-mode-icon-alist '(dashboard-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-dsilver))
|
||||||
|
(add-to-list 'all-the-icons-mode-icon-alist '(ess-mode all-the-icons-fileicon "R" :face all-the-icons-lblue))
|
||||||
|
|
||||||
|
(ivy-rich-mode 1))
|
||||||
|
|
||||||
|
(provide '102-ivy-councel)
|
||||||
|
;;; 102-ivy-councel.el ends here
|
||||||
35
site-start.d/104-avy.el
Normal file
35
site-start.d/104-avy.el
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
;;; 104-avy-ace.el --- Quick jumping inside Emacs
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Avy - Jump to Characters and Words
|
||||||
|
;; Ace - Jump to Windows
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(use-package avy
|
||||||
|
:bind ("M-SPC" . avy-goto-char)
|
||||||
|
:config
|
||||||
|
(setq avy-background t
|
||||||
|
avy-keys '(?a ?o ?e ?u ?i ?d ?h ?t ?n ?s)))
|
||||||
|
|
||||||
|
(use-package ace-window
|
||||||
|
:bind (("C-x o" . ace-window)
|
||||||
|
("M-2" . ace-window))
|
||||||
|
:init
|
||||||
|
(setq aw-background nil
|
||||||
|
aw-keys '(?a ?o ?e ?u ?i ?d ?h ?t ?n ?s)))
|
||||||
|
|
||||||
|
(use-package ace-link
|
||||||
|
:init
|
||||||
|
(ace-link-setup-default))
|
||||||
|
|
||||||
|
(bind-keys :prefix-map avy-map
|
||||||
|
:prefix "C-c j"
|
||||||
|
("c" . avy-goto-char)
|
||||||
|
("l" . avy-goto-line)
|
||||||
|
("w" . avy-goto-word-or-subword-1)
|
||||||
|
("W" . ace-window)
|
||||||
|
("z" . avy-zap-to-char)
|
||||||
|
("Z" . avy-zap-up-to-char))
|
||||||
|
|
||||||
|
(provide '104-avy-ace)
|
||||||
|
;;; 104-avy-ace.el ends here
|
||||||
22
site-start.d/105-flycheck.el
Normal file
22
site-start.d/105-flycheck.el
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
;;; 105-flycheck.el --- on-the-fly syntax checking
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(use-package flycheck
|
||||||
|
:ensure t
|
||||||
|
:init
|
||||||
|
;; enables syntax checking for every supported language
|
||||||
|
(global-flycheck-mode))
|
||||||
|
|
||||||
|
;; Force flycheck to always use c++11 support. We use
|
||||||
|
;; the clang language backend so this is set to clang
|
||||||
|
;;(add-hook 'c++-mode-hook
|
||||||
|
;; (lambda () (setq flycheck-clang-language-standard "c++11")))
|
||||||
|
|
||||||
|
;; Use flycheck-pyflakes for python. Seems to work a little better.
|
||||||
|
;;(require 'flycheck-pyflakes)
|
||||||
|
|
||||||
|
(provide '105-flycheck)
|
||||||
|
;;; 105-flycheck.el ends here
|
||||||
71
site-start.d/106-parentheses.el
Normal file
71
site-start.d/106-parentheses.el
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
;;; 106-parentheses.el --- use smartparens
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Ease completion aof the right parenthese
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(use-package smartparens
|
||||||
|
:bind
|
||||||
|
(("C-M-f" . sp-forward-sexp)
|
||||||
|
("C-M-b" . sp-backward-sexp)
|
||||||
|
("C-M-d" . sp-down-sexp)
|
||||||
|
("C-M-a" . sp-backward-down-sexp)
|
||||||
|
("C-S-a" . sp-beginning-of-sexp)
|
||||||
|
("C-S-d" . sp-end-of-sexp)
|
||||||
|
("C-M-e" . sp-up-sexp)
|
||||||
|
("C-M-u" . sp-backward-up-sexp)
|
||||||
|
("C-M-t" . sp-transpose-sexp)
|
||||||
|
("C-M-n" . sp-next-sexp)
|
||||||
|
("C-M-p" . sp-previous-sexp)
|
||||||
|
("C-M-k" . sp-kill-sexp)
|
||||||
|
("C-M-w" . sp-copy-sexp)
|
||||||
|
("M-<delete>" . sp-unwrap-sexp)
|
||||||
|
("M-S-<backspace>" . sp-backward-unwrap-sexp)
|
||||||
|
("C-<right>" . sp-forward-slurp-sexp)
|
||||||
|
("C-<left>" . sp-forward-barf-sexp)
|
||||||
|
("C-M-<left>" . sp-backward-slurp-sexp)
|
||||||
|
("C-M-<right>" . sp-backward-barf-sexp)
|
||||||
|
("M-D" . sp-splice-sexp)
|
||||||
|
("C-M-<delete>" . sp-splice-sexp-killing-forward)
|
||||||
|
("C-M-<backspace>" . sp-splice-sexp-killing-backward)
|
||||||
|
("C-M-S-<backspace>" . sp-splice-sexp-killing-around)
|
||||||
|
("C-]" . sp-select-next-thing-exchange)
|
||||||
|
("C-<left_bracket>" . sp-select-previous-thing)
|
||||||
|
("C-M-]" . sp-select-next-thing)
|
||||||
|
("M-F" . sp-forward-symbol)
|
||||||
|
("M-B" . sp-backward-symbol)
|
||||||
|
("H-t" . sp-prefix-tag-object)
|
||||||
|
("H-p" . sp-prefix-pair-object)
|
||||||
|
("H-s c" . sp-convolute-sexp)
|
||||||
|
("H-s a" . sp-absorb-sexp)
|
||||||
|
("H-s e" . sp-emit-sexp)
|
||||||
|
("H-s p" . sp-add-to-previous-sexp)
|
||||||
|
("H-s n" . sp-add-to-next-sexp)
|
||||||
|
("H-s j" . sp-join-sexp)
|
||||||
|
("H-s s" . sp-split-sexp)
|
||||||
|
("M-9" . sp-backward-sexp)
|
||||||
|
("M-0" . sp-forward-sexp))
|
||||||
|
:init
|
||||||
|
(smartparens-global-mode t)
|
||||||
|
(show-smartparens-global-mode t)
|
||||||
|
(use-package smartparens-config
|
||||||
|
:ensure f)
|
||||||
|
(bind-key "s" 'smartparens-mode toggle-map)
|
||||||
|
(when (is-mac-p)
|
||||||
|
(bind-keys ("<s-right>" . sp-forward-slurp-sexp)
|
||||||
|
("<s-left>" . sp-forward-barf-sexp)))
|
||||||
|
(sp-with-modes '(markdown-mode gfm-mode)
|
||||||
|
(sp-local-pair "*" "*"))
|
||||||
|
(sp-with-modes '(org-mode)
|
||||||
|
(sp-local-pair "=" "=")
|
||||||
|
(sp-local-pair "*" "*")
|
||||||
|
(sp-local-pair "/" "/")
|
||||||
|
(sp-local-pair "_" "_")
|
||||||
|
(sp-local-pair "+" "+")
|
||||||
|
(sp-local-pair "<" ">")
|
||||||
|
(sp-local-pair "[" "]"))
|
||||||
|
(use-package rainbow-delimiters
|
||||||
|
:hook (prog-mode . rainbow-delimiters-mode)))
|
||||||
|
|
||||||
|
(provide '106-parantheses)
|
||||||
|
;;; 106-parentheses.el ends here
|
||||||
19
site-start.d/201-counsel-gtags.el
Normal file
19
site-start.d/201-counsel-gtags.el
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
;;; 20-counsel-gtags.el --- counsel-gtags adaptions
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Online Documentation can be found at
|
||||||
|
;; https://github.com/syohex/emacs-counsel-gtags
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(add-hook 'c-mode-hook 'counsel-gtags-mode)
|
||||||
|
(add-hook 'c++-mode-hook 'counsel-gtags-mode)
|
||||||
|
|
||||||
|
(with-eval-after-load 'counsel-gtags
|
||||||
|
(define-key counsel-gtags-mode-map (kbd "M-t") 'counsel-gtags-find-definition)
|
||||||
|
(define-key counsel-gtags-mode-map (kbd "M-r") 'counsel-gtags-find-reference)
|
||||||
|
(define-key counsel-gtags-mode-map (kbd "M-s") 'counsel-gtags-find-symbol)
|
||||||
|
(define-key counsel-gtags-mode-map (kbd "M-,") 'counsel-gtags-go-backward)
|
||||||
|
)
|
||||||
|
|
||||||
|
;;; 20-counsel-gtags.el ends here
|
||||||
32
site-start.d/201-hs-minor-mode.el
Normal file
32
site-start.d/201-hs-minor-mode.el
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
;;; 20-hs-minor-mode.el --- hide-show code folding
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; Online Documentation can be found at
|
||||||
|
;; https://www.emacswiki.org/emacs/HideShow
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(load-library "hideshow")
|
||||||
|
(global-set-key (kbd "C-+") 'toggle-hiding)
|
||||||
|
(global-set-key (kbd "C-\\") 'toggle-selective-display)
|
||||||
|
|
||||||
|
;; activate on following major modes
|
||||||
|
(add-hook 'c-mode-common-hook 'hs-minor-mode)
|
||||||
|
(add-hook 'emacs-lisp-mode-hook 'hs-minor-mode)
|
||||||
|
(add-hook 'java-mode-hook 'hs-minor-mode)
|
||||||
|
(add-hook 'lisp-mode-hook 'hs-minor-mode)
|
||||||
|
(add-hook 'perl-mode-hook 'hs-minor-mode)
|
||||||
|
(add-hook 'sh-mode-hook 'hs-minor-mode)
|
||||||
|
(add-hook 'rust-mode-hook 'hs-minor-mode)
|
||||||
|
|
||||||
|
;; Hide the comments too when you do a 'hs-hide-all'
|
||||||
|
(setq hs-hide-comments nil)
|
||||||
|
|
||||||
|
;; Set whether isearch opens folded comments, code, or both
|
||||||
|
;; where x is code, comments, t (both), or nil (neither)
|
||||||
|
(setq hs-isearch-open 'code)
|
||||||
|
|
||||||
|
;; enable hs-minor-mode globaly
|
||||||
|
;; (hs-minor-mode 1)
|
||||||
|
|
||||||
|
;;; 20-hs-minor-mode.el ends here
|
||||||
74
site-start.d/401-rust.el
Normal file
74
site-start.d/401-rust.el
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
;;; 401-rust.el --- handle rust code
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; using rust-mode with rust-analyzer via lsp
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
;; load rustic -> IDE like for rust
|
||||||
|
(use-package rustic
|
||||||
|
:ensure t
|
||||||
|
:init
|
||||||
|
(setq rustic-lsp-server 'rust-analyzer)
|
||||||
|
(setq rustic-format-on-save t))
|
||||||
|
|
||||||
|
;; use the lsp UI package
|
||||||
|
(use-package lsp-ui)
|
||||||
|
|
||||||
|
;; use rust-analyzer via lsp
|
||||||
|
;; (setq lsp-rust-analyzer-server-command '("~/.cargo/bin/rust-analyzer"))
|
||||||
|
;; (add-hook 'before-save-hook (lambda () (when (eq 'rust-mode major-mode)
|
||||||
|
;; (lsp-format-buffer))))
|
||||||
|
|
||||||
|
;; load the language-server-protocol (lsp)
|
||||||
|
;; (use-package lsp-mode
|
||||||
|
;; :init
|
||||||
|
;; (add-hook 'prog-mode-hook 'lsp-mode)
|
||||||
|
;; :after rustic)
|
||||||
|
|
||||||
|
;; ;; :config
|
||||||
|
;; ;; (use-package lsp-flycheck
|
||||||
|
;; ;; :ensure f ; comes with lsp-mode
|
||||||
|
;; ;; :after rustic))
|
||||||
|
|
||||||
|
;; (push 'rustic-clippy flycheck-checkers)
|
||||||
|
|
||||||
|
;; Turn off flycheck.
|
||||||
|
;; (remove-hook 'rustic-mode-hook 'flycheck-mode)
|
||||||
|
|
||||||
|
|
||||||
|
;; ;; load rust-mode
|
||||||
|
;; (use-package rust-mode
|
||||||
|
;; :mode "\\.rs\\'"
|
||||||
|
;; :init
|
||||||
|
;; (setq rust-format-on-save t))
|
||||||
|
|
||||||
|
|
||||||
|
;; ;; bind the lsp-rust mode
|
||||||
|
;; (use-package lsp-rust
|
||||||
|
;; :after lsp-mode)
|
||||||
|
|
||||||
|
;; option: bind commands to keys:
|
||||||
|
;; - lsp-rust-analyzer-join-lines
|
||||||
|
;; - lsp-extend-selection
|
||||||
|
;; - lsp-rust-analyzer-expand-macro
|
||||||
|
|
||||||
|
|
||||||
|
;; (autoload 'rust-mode "rust-mode"
|
||||||
|
;; "Major mode for the rust programming language" t)
|
||||||
|
|
||||||
|
;; (add-hook 'rust-mode-hook #'racer-mode)
|
||||||
|
;; (add-hook 'racer-mode-hook #'eldoc-mode)
|
||||||
|
;; (add-hook 'racer-mode-hook #'company-mode)
|
||||||
|
;; (add-hook 'rust-mode-hook 'cargo-minor-mode)
|
||||||
|
;; (add-hook 'flycheck-mode #'flycheck-rust)
|
||||||
|
;; (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)
|
||||||
|
|
||||||
|
;; ;; reccommended: use spaces instead of tabs
|
||||||
|
;; (add-hook 'rust-mode-hook
|
||||||
|
;; (lambda () (setq indent-tabs-mode nil)))
|
||||||
|
|
||||||
|
;; ;; on save, run rustfmt if installed (C-c C-f)
|
||||||
|
;; (setq rust-format-on-save t)
|
||||||
|
|
||||||
|
(provide '401-rust)
|
||||||
|
;;; 401-rust.el ends here
|
||||||
10
site-start.d/50-ansi-color.el
Normal file
10
site-start.d/50-ansi-color.el
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
;;
|
||||||
|
;; support ansi colour shemes
|
||||||
|
;;
|
||||||
|
|
||||||
|
(require 'ansi-color)
|
||||||
|
(defun colorize-compilation-buffer ()
|
||||||
|
(toggle-read-only)
|
||||||
|
(ansi-color-apply-on-region compilation-filter-start (point))
|
||||||
|
(toggle-read-only))
|
||||||
|
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
|
||||||
26
site-start.d/50-boxquote.el
Normal file
26
site-start.d/50-boxquote.el
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
;;; 400-boxquote.el --- showing an inline arguments hints
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; provides a set of functions for using a text quoting style that partially boxes
|
||||||
|
;; in the left hand side of an area of text.
|
||||||
|
;; such a marking style might be used to show externally included text or example code
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
(require 'boxquote)
|
||||||
|
|
||||||
|
(global-set-key (kbd "C-c b y") 'boxquote-yank)
|
||||||
|
(global-set-key (kbd "C-c b r") 'boxquote-region)
|
||||||
|
(global-set-key (kbd "C-c b u") 'boxquote-unbox-region)
|
||||||
|
(global-set-key (kbd "C-c b t") 'boxquote-title)
|
||||||
|
(global-set-key (kbd "C-c b i") 'boxquote-insert-file)
|
||||||
|
(global-set-key (kbd "C-c b k") 'boxquote-kill)
|
||||||
|
(global-set-key (kbd "C-c b s") 'boxquote-shell-command)
|
||||||
|
|
||||||
|
(global-set-key (kbd "C-c b b") 'boxquote-buffer)
|
||||||
|
(global-set-key (kbd "C-c b p") 'boxquote-paragraph)
|
||||||
|
(global-set-key (kbd "C-c b n") 'boxquote-narrow-to-boxquote)
|
||||||
|
|
||||||
|
(global-set-key (kbd "C-c b w") 'boxquote-where-is)
|
||||||
|
(global-set-key (kbd "C-c b d f") 'boxquote-describe-function)
|
||||||
|
(global-set-key (kbd "C-c b d k") 'boxquote-describe-key)
|
||||||
|
(global-set-key (kbd "C-c b d v") 'boxquote-describe-variable)
|
||||||
68
site-start.d/501-git.el
Normal file
68
site-start.d/501-git.el
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
;;; 501-git.el --- git user adaptions
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; loading standard git.el
|
||||||
|
;;(require 'git)
|
||||||
|
|
||||||
|
;; load magit for git handling
|
||||||
|
(use-package magit
|
||||||
|
:ensure t
|
||||||
|
:bind (("C-x g" . magit-status)
|
||||||
|
("C-c g" . magit-status)
|
||||||
|
:map magit-status-mode-map
|
||||||
|
("TAB" . magit-section-toggle)
|
||||||
|
("<C-tab>" . magit-section-cycle)
|
||||||
|
:map magit-branch-section-map
|
||||||
|
("RET" . magit-checkout))
|
||||||
|
:config
|
||||||
|
(add-hook 'after-save-hook 'magit-after-save-refresh-status)
|
||||||
|
(setq magit-use-overlays nil
|
||||||
|
magit-section-visibility-indicator nil
|
||||||
|
magit-completing-read-function 'ivy-completing-read
|
||||||
|
magit-push-always-verify nil
|
||||||
|
magit-repository-directories '("~/src/"))
|
||||||
|
(use-package git-timemachine
|
||||||
|
:bind (("C-x v t" . git-timemachine)))
|
||||||
|
(use-package git-link
|
||||||
|
:bind (("C-x v L" . git-link))
|
||||||
|
:init
|
||||||
|
(setq git-link-open-in-browser t))
|
||||||
|
(use-package pcmpl-git)
|
||||||
|
(defun visit-pull-request-url ()
|
||||||
|
"Visit the current branch's PR on Github."
|
||||||
|
(interactive)
|
||||||
|
(browse-url
|
||||||
|
(format "https://github.com/%s/pull/new/%s"
|
||||||
|
(replace-regexp-in-string
|
||||||
|
"\\`.+github\\.com:\\(.+\\)\\.git\\'" "\\1"
|
||||||
|
(magit-get "remote"
|
||||||
|
(magit-get-remote)
|
||||||
|
"url"))
|
||||||
|
(cdr (magit-get-remote-branch)))))
|
||||||
|
|
||||||
|
(bind-key "v" 'visit-pull-request-url magit-mode-map)
|
||||||
|
|
||||||
|
;; Do Not Show Recent Commits in status window
|
||||||
|
;; https://github.com/magit/magit/issues/3230#issuecomment-339900039
|
||||||
|
(magit-add-section-hook 'magit-status-sections-hook
|
||||||
|
'magit-insert-unpushed-to-upstream
|
||||||
|
'magit-insert-unpushed-to-upstream-or-recent
|
||||||
|
'replace))
|
||||||
|
|
||||||
|
;; load forge to handle github, gitlab, etc
|
||||||
|
;;(require 'forge)
|
||||||
|
(use-package forge
|
||||||
|
:after magit)
|
||||||
|
|
||||||
|
(defvar my/magit-default-options
|
||||||
|
`(
|
||||||
|
(pulling "--rebase")
|
||||||
|
))
|
||||||
|
|
||||||
|
;;(advice-add 'magit-key-mode :filter-args #'magit-key-mode--add-default-options)
|
||||||
|
|
||||||
|
(provide '501-git)
|
||||||
|
;;; 501-git.el ends here
|
||||||
13
site-start.d/502-meson-mode.el
Normal file
13
site-start.d/502-meson-mode.el
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
;;; 500-meson-mode.el --- meson build system
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
; GNU Emacs major mode to support meson build system
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(autoload 'meson-mode "meson-mode"
|
||||||
|
"Major mode for the Meson build system files" t)
|
||||||
|
|
||||||
|
(add-hook 'meson-mode-hook 'company-mode)
|
||||||
|
|
||||||
|
;;; 500-meson-mode.el ends here
|
||||||
Reference in New Issue
Block a user