Merge pull request #18 from avronr/devel

Pre-1.0 Release
This commit is contained in:
Abraham Raji 2020-02-15 21:50:13 +05:30 committed by GitHub
commit 6b58db0866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1618 additions and 802 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
auto-saved-list

View File

@ -35,6 +35,12 @@ CLone this repo into your home folder if the folder is not named =.emacs.d=, ren
git clone https://github.com/avronr/armacs ~/.emacs.d
#+END_SRC
3. Switch to stable branch:
#+BEGIN_SRC sh
git checkout master
#+END_SRC
** Configuration
When Emacs is started, it normally tries to load a Lisp program from an “initialization file”, or “init file” for short. This file, if it exists, specifies how to initialize Emacs for you. Emacs looks for your init file using the filenames ~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el. Here all the init.el file does is point to the config.org file. All of the actual configuration is done in the ~/.emacs.d/config.org file.
** Contributing

1066
config.org

File diff suppressed because it is too large Load Diff

45
customsrc/ccpp.org Normal file
View File

@ -0,0 +1,45 @@
* C/C++
#+BEGIN_SRC emacs-lisp
(use-package ggtags
:ensure t
:config
(add-hook 'c-mode-common-hook
(lambda ()
(when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
(ggtags-mode 1)))))
#+END_SRC
** yasnippet
#+BEGIN_SRC emacs-lisp
(add-hook 'c++-mode-hook 'yas-minor-mode)
(add-hook 'c-mode-hook 'yas-minor-mode)
#+END_SRC
** flycheck
#+BEGIN_SRC emacs-lisp
(use-package flycheck-clang-analyzer
:ensure t
:config
(with-eval-after-load 'flycheck
(require 'flycheck-clang-analyzer)
(flycheck-clang-analyzer-setup)))
#+END_SRC
* Company
#+BEGIN_SRC emacs-lisp
(use-package company-ctags
:ensure t)
#+END_SRC
* Convenient packages
Insert and delete C++ header files automatically
#+BEGIN_SRC emacs-lisp
(use-package cpp-auto-include
:ensure t)
#+END_SRC
Completion-at-point backend for c/c++ using clang.
#+BEGIN_SRC emacs-lisp
(use-package cpp-capf
:ensure t)
#+END_SRC
Easy realtime C++ syntax check and IntelliSense with CMake.
#+BEGIN_SRC emacs-lisp
(use-package cpputils-cmake
:ensure t)
#+END_SRC

76
customsrc/dev.org Normal file
View File

@ -0,0 +1,76 @@
* Brackets using electric
If you write any code, you may enjoy this. Typing the first character in a set
of 2, completes the second one after your cursor. Opening a bracket? Its
closed for you already. Quoting something? Its closed for you already. You
can easily add and remove pairs yourself, have a look.
#+BEGIN_SRC emacs-lisp
(setq electric-pair-pairs '(
(?\{ . ?\})
(?\( . ?\))
(?\[ . ?\])
(?\" . ?\")
))
(electric-pair-mode t)
#+END_SRC
* Semantic Selection
So what this package does is it select text in way that's sensibe towards the
syntax. So for example if I'm in a html tag that is the child of another tag,
invoking the keybinding for this package will first select the child then the
parent and hierarchichally move upwards. No need to drag the mouse around,
this is selection done sensibly.
#+BEGIN_SRC emacs-lisp
(use-package expand-region
:bind ("C-=" . er/expand-region))
#+END_SRC
* Multiple Cursors
Multiple cursors for Emacs. Multiple cursors is a very nice package that lets
you create several cursors that all do the same thing as you type (see the
example below). You can add it to emacs using the steps described here Once
you have installed it, it is useful to set up a keybinding (a keyboard short-
cut) for it. You can do this by adding the following to your emacs config file
to set C-c m c as the binding for multiple cursors.
#+BEGIN_SRC emacs-lisp
(use-package multiple-cursors
:ensure t)
(require 'multiple-cursors)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
#+END_SRC
* Project Management
*Projectile* is a project interaction library for Emacs. Its goal is to
provide a nice set of features operating on a project level without
introducing external dependencies (when feasible). For instance - finding
project files has a portable implementation written in pure Emacs Lisp without
the use of GNU find (but for performance sake an indexing mechanism backed by
external commands exists as well).
Projectile tries to be practical - portability is great, but if some external
tools could speed up some task substantially and the tools are available,
Projectile will leverage them
#+BEGIN_SRC emacs-lisp
(use-package projectile
:ensure t
:init
(projectile-mode 1))
#+END_SRC
* Parentheses
- When programming I like my editor to try to help me with keeping parentheses balanced.
#+BEGIN_SRC emacs-lisp
(use-package smartparens
:diminish smartparens-mode
:config
(add-hook 'prog-mode-hook 'smartparens-mode))
#+END_SRC
- Highlight parens etc. for improved readability.
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:config
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
#+END_SRC
* Version Control
#+BEGIN_SRC emacs-lisp
(org-babel-load-file (expand-file-name "~/.emacs.d/customsrc/versionctrl.org"))
#+END_SRC

54
customsrc/dired.org Normal file
View File

@ -0,0 +1,54 @@
* dired
Hide dotfiles by default, but toggle their visibility with ..
#+BEGIN_SRC emacs-lisp
(use-package dired-hide-dotfiles
:config
(dired-hide-dotfiles-mode)
(define-key dired-mode-map "." 'dired-hide-dotfiles-mode))
#+END_SRC
Open media with the appropriate programs.
#+BEGIN_SRC emacs-lisp
(use-package dired-open
:config
(setq dired-open-extensions
'(("pdf" . "zathura")
("mkv" . "mpv")
("mp3" . "mpv")
("mp4" . "mpv")
("webm" . "mpv")
("avi" . "mpv"))))
#+END_SRC
These are the switches that get passed to ls when dired gets a list of files. Were using:
l: Use the long listing format.
h: Use human-readable sizes.
v: Sort numbers naturally.
A: Almost all. Doesnt include ”.” or ”..”.
#+BEGIN_SRC emacs-lisp
(setq-default dired-listing-switches "-lhvA")
#+END_SRC
Kill buffers of files/directories that are deleted in dired.
#+BEGIN_SRC emacs-lisp
(setq dired-clean-up-buffers-too t)
#+END_SRC
Always copy directories recursively instead of asking every time.
#+BEGIN_SRC emacs-lisp
(setq dired-recursive-copies 'always)
#+END_SRC
Ask before recursively deleting a directory, though.
#+BEGIN_SRC emacs-lisp
(setq dired-recursive-deletes 'top)
#+END_SRC
Open a file with an external program (that is, through xdg-open) by hitting C-c C-o.
#+BEGIN_SRC emacs-lisp
(defun dired-xdg-open ()
"In dired, open the file named on this line."
(interactive)
(let* ((file (dired-get-filename nil t)))
(call-process "xdg-open" nil 0 nil file)))
(define-key dired-mode-map (kbd "C-c C-o") 'dired-xdg-open)
#+END_SRC

451
customsrc/eshell.org Normal file
View File

@ -0,0 +1,451 @@
#+TITLE: Eshell
#+AUTHOR: Abraham Raji
#+EMAIL: abrahamraji99@gmail.com
#+STARTUP: overview
#+CREATOR: avronr
#+LANGUAGE: en
#+OPTIONS: num:nil
* Eshell
** Basics
*** Set up the Correct Path
Need the correct PATH even if we start Emacs from the GUI:
#+BEGIN_SRC emacs-lisp
(setenv "PATH"
(concat
"/usr/local/bin:/usr/local/sbin:"
(getenv "PATH")))
#+END_SRC
*** Pager Setup
If any program wants to pause the output through the =$PAGER= variable, well
, we don't really need that:
#+BEGIN_SRC emacs-lisp
(setenv "PAGER" "cat")
#+END_SRC
*** Navigation and Keys
Eshell comes with some interesting features:
- ~M-RET~ can be used to accumulate further commands while a command is currently
running. Since all input is passed to the subprocess being executed, there is no
automatic input queueing as there is with other shells.
- ~C-c C-t~ can be used to truncate the buffer if it grows too large.
- ~C-c C-r~ will move point to the beginning of the output of the last command.
With a prefix argument, it will narrow to view only that output.
- ~C-c C-o~ will delete the output from the last command.
- ~C-c C-f~ will move forward a complete shell argument.
- ~C-c C-b~ will move backward a complete shell argument.
** Configuration
Scrolling through the output and searching for results that can be copied to the
kill ring is a great feature of Eshell. However, instead of running =end-of-buffer
= key-binding, the following setting means any other key will jump back to the prompt:
#+BEGIN_SRC emacs-lisp
(use-package eshell
:init
(setq ;; eshell-buffer-shorthand t ... Can't see Bug#19391
eshell-scroll-to-bottom-on-input 'all
eshell-error-if-no-glob t
eshell-hist-ignoredups t
eshell-save-history-on-exit t
eshell-prefer-lisp-functions nil
eshell-destroy-buffer-when-process-dies t))
#+END_SRC
I can never seem to remember that =find= and =chmod= behave differently from
Emacs than their Unix counterparts, so the last setting will prefer the native
implementations.
** Visual Executables
Eshell would get somewhat confused if I ran the following commands directly through
the normal Emacs-Lisp library, as these need the better handling of ansiterm:
#+BEGIN_SRC emacs-lisp
(use-package eshell
:init
(add-hook 'eshell-mode-hook
(lambda ()
(add-to-list 'eshell-visual-commands "ssh")
(add-to-list 'eshell-visual-commands "tail")
(add-to-list 'eshell-visual-commands "top"))))
#+END_SRC
** Aliases
Gotta have some [[http://www.emacswiki.org/emacs/EshellAlias][shell aliases]], right?
#+BEGIN_SRC emacs-lisp
(add-hook 'eshell-mode-hook (lambda ()
(eshell/alias "e" "find-file $1")
(eshell/alias "ff" "find-file $1")
(eshell/alias "emacs" "find-file $1")
(eshell/alias "ee" "find-file-other-window $1")
(eshell/alias "gd" "magit-diff-unstaged")
(eshell/alias "gds" "magit-diff-staged")
(eshell/alias "d" "dired $1")
;; The 'ls' executable requires the Gnu version on the Mac
(let ((ls (if (file-exists-p "/usr/local/bin/gls")
"/usr/local/bin/gls"
"/bin/ls")))
(eshell/alias "ll" (concat ls " -AlohG --color=always")))))
#+END_SRC
** Git
My =gst= command is just an alias to =magit-status=, but using the =alias= doesn't
pull in the current working directory, so I make it a function, instead:
#+BEGIN_SRC emacs-lisp
(defun eshell/gst (&rest args)
(magit-status (pop args) nil)
(eshell/echo)) ;; The echo command suppresses output
#+END_SRC
** Find File
We should have an "f" alias for searching the current directory for a file, and
a "ef" for editing that file.
#+BEGIN_SRC emacs-lisp
(defun eshell/f (filename &optional dir try-count)
"Searches for files matching FILENAME in either DIR or the
current directory. Just a typical wrapper around the standard
`find' executable.
Since any wildcards in FILENAME need to be escaped, this wraps the shell command.
If not results were found, it calls the `find' executable up to
two more times, wrapping the FILENAME pattern in wildcat
matches. This seems to be more helpful to me."
(let* ((cmd (concat
(executable-find "find")
" " (or dir ".")
" -not -path '*/.git*'"
" -and -not -path '*node_modules*'"
" -and -not -path '*classes*'"
" -and "
" -type f -and "
"-iname '" filename "'"))
(results (shell-command-to-string cmd)))
(if (not (s-blank-str? results))
results
(cond
((or (null try-count) (= 0 try-count))
(eshell/f (concat filename "*") dir 1))
((or (null try-count) (= 1 try-count))
(eshell/f (concat "*" filename) dir 2))
(t "")))))
(defun eshell/ef (filename &optional dir)
"Searches for the first matching filename and loads it into a
file to edit."
(let* ((files (eshell/f filename dir))
(file (car (s-split "\n" files))))
(find-file file)))
#+END_SRC
Typing =find= in Eshell runs the =find= function, which doesnt do what I expect
, and creating an alias is ineffective in overriding it, so a function will do:
#+BEGIN_SRC emacs-lisp
(defun eshell/find (&rest args)
"Wrapper around the find executable."
(let ((cmd (concat "find " (string-join args))))
(shell-command-to-string cmd)))
#+END_SRC
** Clear
While deleting and recreating =eshell= may be just as fast, I always
forget and type =clear=, so let's implement it:
#+BEGIN_SRC emacs-lisp
(defun eshell/clear ()
"Clear the eshell buffer."
(let ((inhibit-read-only t))
(erase-buffer)
(eshell-send-input)))
#+END_SRC
** Predicate Filters and Modifiers
The =T= predicate filter allows me to limit file results that have have internal
=org-mode= tags. For instance, files that have a =#+TAGS:= header with a =mac=
label will be given to the =grep= function:
#+BEGIN_SRC sh
$ grep brew *.org(T'mac')
#+END_SRC
To extend Eshell, we need a two-part function.
1. Parse the Eshell buffer to look for the parameter (and move the point past the parameter).
2. A predicate function that takes a file as a parameter.
For the first step, we have our function /called/ as it helps parse the text at
this time. Based on what it sees, it returns the predicate function used to filter
the files:
#+BEGIN_SRC emacs-lisp
(defun eshell-org-file-tags ()
"Helps the eshell parse the text the point is currently on,
looking for parameters surrounded in single quotes. Returns a
function that takes a FILE and returns nil if the file given to
it doesn't contain the org-mode #+TAGS: entry specified."
(if (looking-at "'\\([^)']+\\)'")
(let* ((tag (match-string 1))
(reg (concat "^#\\+TAGS:.* " tag "\\b")))
(goto-char (match-end 0))
`(lambda (file)
(with-temp-buffer
(insert-file-contents file)
(re-search-forward ,reg nil t 1))))
(error "The `T' predicate takes an org-mode tag value in single quotes.")))
#+END_SRC
Add it to the =eshell-predicate-alist= as the =T= tag:
#+BEGIN_SRC emacs-lisp
(add-hook 'eshell-pred-load-hook (lambda ()
(add-to-list 'eshell-predicate-alist '(?T . (eshell-org-file-tags)))))
#+END_SRC
*Note:* We cant add it to the list until after we start our first
eshell session, so we just add it to the =eshell-pred-load-hook=
which is sufficient.
** Special Prompt
Following [[http://blog.liangzan.net/blog/2012/12/12/customizing-your-emacs-eshell-prompt/][these instructions]], we build a better prompt with the Git
branch in it (Of course, it matches my Bash prompt). First, we need
a function that returns a string with the Git branch in it,
e.g. ":master"
#+BEGIN_SRC emacs-lisp
(defun curr-dir-git-branch-string (pwd)
"Returns current git branch as a string, or the empty string if
PWD is not in a git repo (or the git command is not found)."
(interactive)
(when (and (not (file-remote-p pwd))
(eshell-search-path "git")
(locate-dominating-file pwd ".git"))
(let* ((git-url (shell-command-to-string "git config --get remote.origin.url"))
(git-repo (file-name-base (s-trim git-url)))
(git-output (shell-command-to-string (concat "git rev-parse --abbrev-ref HEAD")))
(git-branch (s-trim git-output))
(git-icon "\xe0a0")
(git-icon2 (propertize "\xf020" 'face `(:family "octicons"))))
(concat git-repo " " git-icon2 " " git-branch))))
#+END_SRC
The function takes the current directory passed in via =pwd= and
replaces the =$HOME= part with a tilde. I'm sure this function
already exists in the eshell source, but I didn't find it...
#+BEGIN_SRC emacs-lisp
(defun pwd-replace-home (pwd)
"Replace home in PWD with tilde (~) character."
(interactive)
(let* ((home (expand-file-name (getenv "HOME")))
(home-len (length home)))
(if (and
(>= (length pwd) home-len)
(equal home (substring pwd 0 home-len)))
(concat "~" (substring pwd home-len))
pwd)))
#+END_SRC
Make the directory name be shorter...by replacing all directory
names with just its first names. However, we leave the last two to
be the full names. Why yes, I did steal this.
#+BEGIN_SRC emacs-lisp
(defun pwd-shorten-dirs (pwd)
"Shorten all directory names in PWD except the last two."
(let ((p-lst (split-string pwd "/")))
(if (> (length p-lst) 2)
(concat
(mapconcat (lambda (elm) (if (zerop (length elm)) ""
(substring elm 0 1)))
(butlast p-lst 2)
"/")
"/"
(mapconcat (lambda (elm) elm)
(last p-lst 2)
"/"))
pwd))) ;; Otherwise, we just return the PWD
#+END_SRC
Break up the directory into a "parent" and a "base":
#+BEGIN_SRC emacs-lisp
(defun split-directory-prompt (directory)
(if (string-match-p ".*/.*" directory)
(list (file-name-directory directory) (file-name-base directory))
(list "" directory)))
#+END_SRC
Using virtual environments for certain languages is helpful to know,
especially since I change them based on the directory.
#+BEGIN_SRC emacs-lisp
(defun ruby-prompt ()
"Returns a string (may be empty) based on the current Ruby Virtual Environment."
(let* ((executable "~/.rvm/bin/rvm-prompt")
(command (concat executable "v g")))
(when (file-exists-p executable)
(let* ((results (shell-command-to-string executable))
(cleaned (string-trim results))
(gem (propertize "\xe92b" 'face `(:family "alltheicons"))))
(when (and cleaned (not (equal cleaned "")))
(s-replace "ruby-" gem cleaned))))))
(defun python-prompt ()
"Returns a string (may be empty) based on the current Python
Virtual Environment. Assuming the M-x command: `pyenv-mode-set'
has been called."
(when (fboundp #'pyenv-mode-version)
(let ((venv (pyenv-mode-version)))
(when venv
(concat
(propertize "\xe928" 'face `(:family "alltheicons"))
(pyenv-mode-version))))))
#+END_SRC
Now tie it all together with a prompt function can color each of the
prompts components.
#+BEGIN_SRC emacs-lisp
(defun eshell/eshell-local-prompt-function ()
"A prompt for eshell that works locally (in that is assumes
that it could run certain commands) in order to make a prettier,
more-helpful local prompt."
(interactive)
(let* ((pwd (eshell/pwd))
(directory (split-directory-prompt
(pwd-shorten-dirs
(pwd-replace-home pwd))))
(parent (car directory))
(name (cadr directory))
(branch (curr-dir-git-branch-string pwd))
(ruby (when (not (file-remote-p pwd)) (ruby-prompt)))
(python (when (not (file-remote-p pwd)) (python-prompt)))
(dark-env (eq 'dark (frame-parameter nil 'background-mode)))
(for-bars `(:weight bold))
(for-parent (if dark-env `(:foreground "dark orange") `(:foreground "blue")))
(for-dir (if dark-env `(:foreground "orange" :weight bold)
`(:foreground "blue" :weight bold)))
(for-git `(:foreground "green"))
(for-ruby `(:foreground "red"))
(for-python `(:foreground "#5555FF")))
(concat
(propertize "⟣─ " 'face for-bars)
(propertize parent 'face for-parent)
(propertize name 'face for-dir)
(when branch
(concat (propertize " ── " 'face for-bars)
(propertize branch 'face for-git)))
(when ruby
(concat (propertize " ── " 'face for-bars)
(propertize ruby 'face for-ruby)))
(when python
(concat (propertize " ── " 'face for-bars)
(propertize python 'face for-python)))
(propertize "\n" 'face for-bars)
(propertize (if (= (user-uid) 0) " #" " $") 'face `(:weight ultra-bold))
;; (propertize " └→" 'face (if (= (user-uid) 0) `(:weight ultra-bold :foreground "red") `(:weight ultra-bold)))
(propertize " " 'face `(:weight bold)))))
(setq-default eshell-prompt-function #'eshell/eshell-local-prompt-function)
#+END_SRC
Turn off the default prompt, otherwise, it won't use ours:
#+BEGIN_SRC emacs-lisp
(setq eshell-highlight-prompt nil)
#+END_SRC
Here is the result:
[[http://imgur.com/nkpwII0.png]]
** Tramp
The ability to edit files on remote systems is a wonderful win,
since it means I don't need to have my Emacs environment running on
remote machines (still a possibility, just not a requirement).
According to [[http://www.gnu.org/software/emacs/manual/html_node/tramp/Filename-Syntax.html][the manual]], I can access a file over SSH, via:
#+BEGIN_EXAMPLE
/ssh:10.52.224.67:blah
#+END_EXAMPLE
However, if I set the default method to SSH, I can do this:
#+BEGIN_EXAMPLE
/10.52.224.67:blah
#+END_EXAMPLE
So, let's do it...
#+BEGIN_SRC emacs-lisp
(setq tramp-default-method "ssh")
#+END_SRC
** Better Command Line History
On [[http://www.reddit.com/r/emacs/comments/1zkj2d/advanced_usage_of_eshell/][this discussion]] a little gem for using IDO to search back through
the history, instead of =M-R= to display the history in a selectable
buffer.
Also, while =M-p= cycles through the history, =M-P= actually moves
up the history in the buffer (easier than =C-c p= and =C-c n=?):
Since eshell's history often gets confused with blank lines in the
output, we can fix that with a better replacement functions pegged
to the =eshell-prompt-regexp= string:
#+BEGIN_SRC emacs-lisp
(defun eshell-next-prompt (n)
"Move to end of Nth next prompt in the buffer. See `eshell-prompt-regexp'."
(interactive "p")
(re-search-forward eshell-prompt-regexp nil t n)
(when eshell-highlight-prompt
(while (not (get-text-property (line-beginning-position) 'read-only) )
(re-search-forward eshell-prompt-regexp nil t n)))
(eshell-skip-prompt))
(defun eshell-previous-prompt (n)
"Move to end of Nth previous prompt in the buffer. See `eshell-prompt-regexp'."
(interactive "p")
(backward-char)
(eshell-next-prompt (- n)))
(defun eshell-insert-history ()
"Displays the eshell history to select and insert back into your eshell."
(interactive)
(insert (ido-completing-read "Eshell history: "
(delete-dups
(ring-elements eshell-history-ring)))))
(add-hook 'eshell-mode-hook (lambda ()
(define-key eshell-mode-map (kbd "M-S-P") 'eshell-previous-prompt)
(define-key eshell-mode-map (kbd "M-S-N") 'eshell-next-prompt)
(define-key eshell-mode-map (kbd "M-r") 'eshell-insert-history)))
#+END_SRC
** Helpers
Sometimes you just need to change something about the current file
you are editing...like the permissions or even execute it. Hitting
=Command-1= will prompt for a shell command string and then append
the current file to it and execute it.
#+BEGIN_SRC emacs-lisp
(defun execute-command-on-file-buffer (cmd)
(interactive "sCommand to execute: ")
(let* ((file-name (buffer-file-name))
(full-cmd (concat cmd " " file-name)))
(shell-command full-cmd)))
(bind-key "A-1" #'execute-command-on-file-buffer)
(defun execute-command-on-file-directory (cmd)
(interactive "sCommand to execute: ")
(let* ((dir-name (file-name-directory (buffer-file-name)))
(full-cmd (concat "cd " dir-name "; " cmd)))
(shell-command full-cmd)))
(bind-key "A-!" #'execute-command-on-file-directory)
(bind-key "s-!" #'execute-command-on-file-directory)
#+END_SRC
Some prompts, shells and terminal programs that display the exit
code as an icon in the fringe. So can the [[http://projects.ryuslash.org/eshell-fringe-status/][eshell-fringe-status]]
project. Seems to me, that if would be useful to rejuggle those
fringe markers so that the marker matched the command entered
(instead of seeing a red mark, and needing to scroll back in order
to wonder what command it was that made it). Still...
#+BEGIN_SRC emacs-lisp
(use-package eshell-fringe-status
:config
(add-hook 'eshell-mode-hook 'eshell-fringe-status-mode))
#+END_SRC

86
customsrc/hydra.org Normal file
View File

@ -0,0 +1,86 @@
* Hydra
This is a package for GNU Emacs that can be used to tie related commands into a family of short bindings with a common prefix - a Hydra.
Imagine that you have bound C-c j and C-c k in your config. You want to call C-c j and C-c k in some (arbitrary) sequence. Hydra allows you to:
- Bind your functions in a way that pressing C-c jjkk3j5k is equivalent to pressing C-c j C-c j C-c k C-c k M-3 C-c j M-5 C-c k. Any key other than j or k exits this state.
- Assign a custom hint to this group of functions, so that you know immediately after pressing C-c that you can follow up with j or k.
If you want to quickly understand the concept, see [the video demo](https://www.youtube.com/watch?v=_qZliI1BKzI).
#+BEGIN_SRC emacs-lisp
(use-package hydra
:ensure hydra
:init
(global-set-key
(kbd "C-x t")
(defhydra toggle (:color blue)
"toggle"
("a" abbrev-mode "abbrev")
("s" flyspell-mode "flyspell")
("d" toggle-debug-on-error "debug")
("c" fci-mode "fCi")
("f" auto-fill-mode "fill")
("t" toggle-truncate-lines "truncate")
("w" whitespace-mode "whitespace")
("q" nil "cancel")))
(global-set-key
(kbd "C-x j")
(defhydra gotoline
( :pre (linum-mode 1)
:post (linum-mode -1))
"goto"
("t" (lambda () (interactive)(move-to-window-line-top-bottom 0)) "top")
("b" (lambda () (interactive)(move-to-window-line-top-bottom -1)) "bottom")
("m" (lambda () (interactive)(move-to-window-line-top-bottom)) "middle")
("e" (lambda () (interactive)(end-of-buffer)) "end")
("c" recenter-top-bottom "recenter")
("n" next-line "down")
("p" (lambda () (interactive) (forward-line -1)) "up")
("g" goto-line "goto-line")
))
(global-set-key
(kbd "C-c t")
(defhydra hydra-global-org (:color blue)
"Org"
("t" org-timer-start "Start Timer")
("s" org-timer-stop "Stop Timer")
("r" org-timer-set-timer "Set Timer") ; This one requires you be in an orgmode doc, as it sets the timer for the header
("p" org-timer "Print Timer") ; output timer value to buffer
("w" (org-clock-in '(4)) "Clock-In") ; used with (org-clock-persistence-insinuate) (setq org-clock-persist t)
("o" org-clock-out "Clock-Out") ; you might also want (setq org-log-note-clock-out t)
("j" org-clock-goto "Clock Goto") ; global visit the clocked task
("c" org-capture "Capture") ; Don't forget to define the captures you want http://orgmode.org/manual/Capture.html
("l" (or )rg-capture-goto-last-stored "Last Capture"))
))
(defhydra hydra-multiple-cursors (:hint nil)
"
Up^^ Down^^ Miscellaneous % 2(mc/num-cursors) cursor%s(if (> (mc/num-cursors) 1) \"s\" \"\")
------------------------------------------------------------------
[_p_] Next [_n_] Next [_l_] Edit lines [_0_] Insert numbers
[_P_] Skip [_N_] Skip [_a_] Mark all [_A_] Insert letters
[_M-p_] Unmark [_M-n_] Unmark [_s_] Search
[Click] Cursor at point [_q_] Quit"
("l" mc/edit-lines :exit t)
("a" mc/mark-all-like-this :exit t)
("n" mc/mark-next-like-this)
("N" mc/skip-to-next-like-this)
("M-n" mc/unmark-next-like-this)
("p" mc/mark-previous-like-this)
("P" mc/skip-to-previous-like-this)
("M-p" mc/unmark-previous-like-this)
("s" mc/mark-all-in-region-regexp :exit t)
("0" mc/insert-numbers :exit t)
("A" mc/insert-letters :exit t)
("<mouse-1>" mc/add-cursor-on-click)
;; Help with click recognition in this hydra
("<down-mouse-1>" ignore)
("<drag-mouse-1>" ignore)
("q" nil)
("<mouse-1>" mc/add-cursor-on-click)
("<down-mouse-1>" ignore)
("<drag-mouse-1>" ignore))
#+END_SRC

110
customsrc/orgmode.org Normal file
View File

@ -0,0 +1,110 @@
* Org-mode
** org-bullets
Asterisk can be boring to look at.
#+BEGIN_SRC emacs-lisp
(use-package org-bullets
:init
(add-hook 'org-mode-hook #'org-bullets-mode))
#+END_SRC
** Enable spell-checking in Org-mode.
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook 'flyspell-mode)
#+END_SRC
** Replacing (...)
#+BEGIN_SRC emacs-lisp
(setq org-ellipsis " ▶")
#+END_SRC
** Exporting
Allow export to markdown and beamer (for presentations).
#+BEGIN_SRC emacs-lisp
(require 'ox-md)
(require 'ox-beamer)
#+END_SRC
Allow =babel= to evaluate Emacs lisp, Ruby, dot, or Gnuplot code.
#+BEGIN_SRC emacs-lisp
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)
(C . t)))
#+END_SRC
*** Exporting to HTML
Don't include a footer with my contact and publishing information at the bottom
of every exported HTML document.
#+BEGIN_SRC emacs-lisp
(setq org-html-postamble nil)
#+END_SRC
Exporting to HTML and opening the results triggers =/usr/bin/sensible-browser=,
which checks the =$BROWSER= environment variable to choose the right browser.
I'd like to always use Firefox, so:
#+BEGIN_SRC emacs-lisp
(setq browse-url-browser-function 'browse-url-generic
browse-url-generic-program "firefox")
(setenv "BROWSER" "firefox")
#+END_SRC
*** Exporting to PDF
- Open compiled PDFs in =zathura= instead of in the editor.
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook
'(lambda ()
(delete '("\\.pdf\\'" . default) org-file-apps)
(add-to-list 'org-file-apps '("\\.pdf\\'" . "zathura %s"))))
#+END_SRC
*** Add bootstrap styled export.
#+BEGIN_SRC emacs-lisp
(use-package ox-twbs)
#+END_SRC
*** ox-reveal
**** htmlize
This package converts the buffer text and the associated decorations to HTML. To use it, just switch to the buffer you want HTML-ized and type M-x htmlize-buffer. You will be switched to a new buffer that contains the resulting HTML code. You can edit and inspect this buffer, or you can just save it with C-x C-w. M-x htmlize-file will find a file, fontify it, and save the HTML version in FILE.html, without any additional intervention. M-x htmlize-many-files allows you to htmlize any number of files in the same manner. M-x htmlize-many-files-dired does the same for files marked in a dired buffer.
#+BEGIN_SRC emacs-lisp
(use-package htmlize
:ensure t)
(setq org-html-postamble nil)
#+END_SRC
Makes org documents into presentations using js.
#+BEGIN_SRC emacs-lisp
(use-package ox-reveal
:ensure ox-reveal)
(setq org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")
(setq org-reveal-mathjax t)
#+END_SRC
*** Tree Slide
A quick way to display an org-mode file is using [[https://github.com/takaxp/org-tree-slide][org-tree-slide]].
* org-tree-slide-move-next-tree (C->)
* org-tree-slide-move-previous-tree (C-<)
* org-tree-slide-content (C-x s c)
#+BEGIN_SRC elisp
(use-package org-tree-slide
:ensure t
:init
(setq org-tree-slide-skip-outline-level 4)
(org-tree-slide-simple-profile))
(define-key org-mode-map (kbd "<f8>") 'org-tree-slide-mode)
(define-key org-mode-map (kbd "c-<f8>") 'org-tree-slide-skip-done-toggle)
#+END_SRC
** Easy-to-add emacs-lisp template
Hitting tab after an "<el" in an org-mode file will create a template for emacs-lisp insertion.
#+BEGIN_SRC emacs-lisp
(add-to-list 'org-structure-template-alist
'("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
'("cp" "#+BEGIN_SRC c\n?\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
'("py" "#+BEGIN_SRC python\n?\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
'("base" "#+TITLE:\n#+AUTHOR: Abraham Raji\n#+EMAIL: abrahamraji99@gmail.com\n#+STARTUP: overview\n#+CREATOR: avronr\n#+LANGUAGE: en\n#+OPTIONS: num:nil\n"))
#+END_SRC

37
customsrc/python.org Normal file
View File

@ -0,0 +1,37 @@
#+TITLE: Python
#+AUTHOR: Abraham Raji
#+EMAIL: abrahamraji99@gmail.com
#+STARTUP: overview
#+CREATOR: avronr
#+LANGUAGE: en
#+OPTIONS: num:nil
* Python
**** Elpy
#+BEGIN_SRC emacs-lisp
(use-package elpy
:ensure t
:config
(elpy-enable))
#+END_SRC
**** Black
Black is an opinionated pyton formatter. Install with =pip install black= so the
command line tool is available.
#+BEGIN_SRC emacs-lisp
(use-package blacken)
#+END_SRC
**** Kivy
Sometimes I use kivy.
#+BEGIN_SRC emacs-lisp
(use-package kivy-mode
:mode ("\\.kv\\'" . kivy-mode))
#+END_SRC
**** yasnippet
#+BEGIN_SRC emacs-lisp
(add-hook 'python-mode-hook 'yas-minor-mode)
#+END_SRC
**** flycheck
#+BEGIN_SRC emacs-lisp
(add-hook 'python-mode-hook 'flycheck-mode)
#+END_SRC

98
customsrc/versionctrl.org Normal file
View File

@ -0,0 +1,98 @@
* Version Control
*** Magit
Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.
I love it. You could get the same functionality with other text editors too but none so light wieght or polished in my opinion.
#+BEGIN_SRC emacs-lisp
(use-package magit
:ensure t
:init
(progn
(bind-key "C-x g" 'magit-status)))
#+END_SRC
*** Git-gutter
Display line changes in gutter based on git history. Enable it everywhere.
Originally a Sublime Text plug-in to show information about files in a git repository:
- Gutter Icons indicating inserted, modified or deleted lines
- Diff Popup with details about modified lines
- Status Bar Text with information about file and repository
and provides some commands like:
- Goto Change to navigate between modified lines
- Copy from Commit to copy the original content from the commit
- Revert to Commit to revert a modified hunk to the original state in a commit
#+BEGIN_SRC emacs-lisp
(org-babel-load-file (expand-file-name "~/.emacs.d/customsrc/hydra.org"))
(use-package git-gutter
:config
(global-git-gutter-mode 't)
:diminish git-gutter-mode)
;; If you would like to use git-gutter.el and linum-mode
;(git-gutter:linum-setup)
;; If you enable git-gutter-mode for some modes
(add-hook 'ruby-mode-hook 'git-gutter-mode)
(global-set-key (kbd "C-x C-g") 'git-gutter)
(global-set-key (kbd "C-x v =") 'git-gutter:popup-hunk)
;; Jump to next/previous hunk
(global-set-key (kbd "C-x p") 'git-gutter:previous-hunk)
(global-set-key (kbd "C-x n") 'git-gutter:next-hunk)
;; Stage current hunk
(global-set-key (kbd "C-x v s") 'git-gutter:stage-hunk)
;; Revert current hunk
(global-set-key (kbd "C-x v r") 'git-gutter:revert-hunk)
;; Mark current hunk
(global-set-key (kbd "C-x v SPC") #'git-gutter:mark-hunk)
(global-set-key (kbd "M-g M-g") 'hydra-git-gutter/body)
(defhydra hydra-git-gutter (:body-pre (git-gutter-mode 1)
:hint nil)
"
Git gutter:
_j_: next hunk _s_tage hunk _q_uit
_k_: previous hunk _r_evert hunk _Q_uit and deactivate git-gutter
^ ^ _p_opup hunk
_h_: first hunk
_l_: last hunk set start _R_evision
"
("j" git-gutter:next-hunk)
("k" git-gutter:previous-hunk)
("h" (progn (goto-char (point-min))
(git-gutter:next-hunk 1)))
("l" (progn (goto-char (point-min))
(git-gutter:previous-hunk 1)))
("s" git-gutter:stage-hunk)
("r" git-gutter:revert-hunk)
("p" git-gutter:popup-hunk)
("R" git-gutter:set-start-revision)
("q" nil :color blue)
("Q" (progn (git-gutter-mode -1)
;; git-gutter-fringe doesn't seem to
;; clear the markup right away
(sit-for 0.1)
(git-gutter:clear))
:color blue))
#+END_SRC
*** Time machine
TimeMachine lets us step through the history of a file as recorded in git. Visit a git-controlled file and issue M-x git-timemachine (or bind it to a keybinding of your choice). If you just need to toggle the time machine you can use M-x git-timemachine-toggle. Use the following keys to navigate historic version of the file:
- =p= Visit previous historic version
- =n= Visit next historic version
- =w= Copy the abbreviated hash of the current historic version
- =W= Copy the full hash of the current historic version
- =g= Goto nth revision
- =t= Goto revision by selected commit message
- =q= Exit the time machine.
- =b= Run magit-blame on the currently visited revision (if magit available).
- =c= Show current commit using magit (if magit available).
#+BEGIN_SRC emacs-lisp
(use-package git-timemachine
:ensure t)
#+END_SRC

150
customsrc/webdev.org Normal file
View File

@ -0,0 +1,150 @@
* Web Development
I do quite a bit of web-development and have snippets, automatic indentation and autocompletion is a big help . =web-mode.el= is an autonomous emacs major-mode for editing web templates. It also takes care of basic stuff like syntax highlighting, auto pairing tags, removing white spaces etc. Web-mode is feature rich and as extensible as Emacs itself. For more details visit this [[http://web-mode.org/][link]]
#+BEGIN_SRC emacs-lisp
(use-package web-mode
:ensure t)
;;Automatically load web-mode when opening web-related files
(add-to-list 'auto-mode-alist '("\\.ts\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.css?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
(setq web-mode-engines-alist
'(("php" . "\\.phtml\\'")
("blade" . "\\.blade\\.")))
;;Set indentations
(defun my-web-mode-hook ()
"Hooks for Web mode."
(setq web-mode-markup-indent-offset 2)
(setq web-mode-code-indent-offset 2)
(setq web-mode-css-indent-offset 2))
(add-hook 'web-mode-hook 'my-web-mode-hook)
(setq tab-width 2)
;;Highlight of columns
(setq web-mode-enable-current-column-highlight t)
(setq web-mode-enable-current-element-highlight t)
;;Autoremove final white spaces on save
(add-hook 'local-write-file-hooks
(lambda ()
(delete-trailing-whitespace)
nil))
(defun my-web-mode-hook ()
(set (make-local-variable 'company-backends) '(company-css company-web-html company-yasnippet company-files))
)
#+END_SRC
*** Emmet Mode
Emmet (formerly *Zen Coding*) is a web-developers toolkit that can greatly improve your HTML & CSS workflow. With Emmet, you can type CSS-like expressions that can be dynamically parsed, and produce output depending on what you type in the abbreviation. Emmet is developed and optimised for web-developers whose workflow depends on HTML/XML and CSS, but can be used with programming languages too. For example, this abbreviation:
#+BEGIN_SRC html
ul#nav>li.item$*4>a{Item $}
#+END_SRC
...can be expanded into:
#+BEGIN_SRC html
<ul id="nav">
<li class="item1"><a href="">Item 1</a></li>
<li class="item2"><a href="">Item 2</a></li>
<li class="item3"><a href="">Item 3</a></li>
<li class="item4"><a href="">Item 4</a></li>
</ul>
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package emmet-mode
:ensure t)
;;Turn on Emmet in web-mode.
(add-hook 'web-mode-hook 'emmet-mode)
;;Web-mode is able to switch modes into css (style tags) or js (script tags) in an html file. For Emmet to switch between html and css properly in the same document, this hook is added.
(add-hook 'web-mode-before-auto-complete-hooks
'(lambda ()
(let ((web-mode-cur-language
(web-mode-language-at-pos)))
(if (string= web-mode-cur-language "php")
(yas-activate-extra-mode 'php-mode)
(yas-deactivate-extra-mode 'php-mode))
(if (string= web-mode-cur-language "css")
(setq emmet-use-css-transform t)
(setq emmet-use-css-transform nil)))))
#+END_SRC
** Modes
I need these packages installed:
#+BEGIN_SRC emacs-lisp
(use-package mustache-mode
:ensure t)
#+END_SRC
Need the smart parens:
#+BEGIN_SRC emacs-lisp
(use-package smartparens
:init (add-hook 'css-mode-hook 'smartparens-mode))
#+END_SRC
** Skewer
Live coding for HTML/CSS/JavaScript with a [[https://github.com/skeeto/skewer-mode][Skewer server]] running in Emacs.
#+BEGIN_SRC emacs-lisp
(use-package skewer-mode
:ensure t
:commands skewer-mode run-skewer
:config (skewer-setup))
#+END_SRC
Useful key-bindings with the =skewer-setup=:
- =C-x C-e= :: Evaluate the form before the point and display the result in the
- =minibuffer. If given a prefix argument, insert the result into the current
- =buffer.
- =C-M-x= :: Evaluate the top-level form around the point.
- =C-c C-k= :: Load the current buffer.
- =C-c C-z= :: Select the REPL buffer.
** Impatient Mode
When you are editting html files, it is kind of a pain to switch between
windows and refresh them everytime you want to see if your code works or not.
It is for this reason we have Impatient mode. This mode let's us see the
effect of our code as we type.
Using ~impatient-mode~
Enable the web server provided by ~simple-httpd~:
=M-x httpd-start=
Publish buffers by enabling the minor mode `impatient-mode`.
=M-x impatient-mode=
And then point your browser to http://localhost:8080/imp/, select a
buffer, and watch your changes appear as you type!
If you are editing HTML that references resources in other files (like
CSS) you can enable impatient-mode on those buffers as well. This will
cause your browser to live refresh the page when you edit a referenced
resource.
#+BEGIN_SRC emacs-lisp
(use-package impatient-mode
:ensure t)
#+END_SRC
*Security implications*
Please be aware that enabling `impatient-mode` exposes the whole directory in
which the file resides, not only the file itself. If our file is accessible
under `http://localhost:8080/imp/live/example.txt/`, it is possible to access `
http://localhost:8080/imp/live/example.txt/a-file-in-the-same-directory/or-even/a-subdirectory-of-it.txt`.
It's especially dangerous when enabling `impatient-mode` for files like
`~/.bashrc` because it allows to access any file in the user's home directory
files such as `~/.ssh/id_rsa`.
This behavior is not a bug, it is needed for the HTML files to work properly
along with their resources (such as CSS and JS). Please be aware of what is
exposed and/or configure your filewall accordingly.

240
customsrc/words.org Normal file
View File

@ -0,0 +1,240 @@
* Word Smithing
** Auto Complete
Using [[http://company-mode.github.io/][company-mode]] for all my auto completion needs.
Like [[https://github.com/vspinu/company-math][this idea]] of being able to easily insert math
symbols based on LaTeX keywords. Start typing a backslash.
#+BEGIN_SRC emacs-lisp
(use-package company
:ensure t
:init
(setq company-dabbrev-ignore-case t
company-show-numbers t)
(add-hook 'after-init-hook 'global-company-mode)
:config
(add-to-list 'company-backends 'company-math-symbols-unicode)
:bind ("C-:" . company-complete) ; In case I don't want to wait
:diminish company-mode)
(defun check-expansion ()
(save-excursion
(if (looking-at "\\_>") t
(backward-char 1)
(if (looking-at "\\.") t
(backward-char 1)
(if (looking-at "->") t nil)))))
(defun do-yas-expand ()
(let ((yas/fallback-behavior 'return-nil))
(yas/expand)))
(defun tab-indent-or-complete ()
(interactive)
(if (minibufferp)
(minibuffer-complete)
(if (or (not yas/minor-mode)
(null (do-yas-expand)))
(if (check-expansion)
(company-complete-common)
(indent-for-tab-command)))))
(global-set-key [tab] 'tab-indent-or-complete)
(use-package company-web
:ensure t)
(define-key web-mode-map (kbd "C-'") 'company-web-html)
;; emmet integration
(custom-set-faces
'(company-preview
((t (:foreground "darkgray" :underline t))))
'(company-preview-common
((t (:inherit company-preview))))
'(company-tooltip
((t (:background "lightgray" :foreground "black"))))
'(company-tooltip-selection
((t (:background "steelblue" :foreground "white"))))
'(company-tooltip-common
((((type x)) (:inherit company-tooltip :weight bold))
(t (:inherit company-tooltip))))
'(company-tooltip-common-selection
((((type x)) (:inherit company-tooltip-selection :weight bold))
(t (:inherit company-tooltip-selection)))))
(defun my-web-mode-hook ()
"Hook for `web-mode'."
(set (make-local-variable 'company-backends)
'(company-web-html company-yasnippet company-files)))
(add-hook 'web-mode-hook 'my-web-mode-hook)
;; Enable JavaScript completion between <script>...</script> etc.
(advice-add 'company-tern :before
#'(lambda (&rest _)
(if (equal major-mode 'web-mode)
(let ((web-mode-cur-language
(web-mode-language-at-pos)))
(if (or (string= web-mode-cur-language "javascript")
(string= web-mode-cur-language "jsx"))
(unless tern-mode (tern-mode))
(if tern-mode (tern-mode -1)))))))
;; manual autocomplete
(define-key web-mode-map (kbd "M-SPC") 'company-complete)
#+END_SRC
Take advantage of idle time by displaying some documentation
using [[https://www.github.com/expez/company-quickhelp][company-quickhelp]] project.
#+BEGIN_SRC emacs-lisp
(use-package company-quickhelp
:ensure t
:config
(company-quickhelp-mode 1))
#+END_SRC
This also requires [[https://github.com/pitkali/pos-tip/blob/master/pos-tip.el][pos-tip]].
** Yasnippets
The [[https://github.com/capitaomorte/yasnippet][yasnippet project]] allows me to create snippets of code that
can be brought into a file, based on the language.
#+BEGIN_SRC emacs-lisp
(use-package yasnippet
:ensure t
:init
(yas-global-mode 1)
:config)
(add-hook 'after-init-hook 'global-company-mode)
(global-set-key (kbd "M-/") 'company-complete-common)
(use-package company-jedi)
(add-to-list 'company-backends 'company-jedi)
(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)
#+END_SRC
*Note:*: the =snippets= directory contains directories for each
mode, e.g. =clojure-mode= and =org-mode=.
** Spell Checking
Spell checking with [[http://www.emacswiki.org/emacs/FlySpell][FlySpell]], which uses the built-in settings of
[[https://www.gnu.org/software/ispell/][ispell]]. The [[http://aspell.net][ASpell]] project is better supported than ISpell, and
it seems to be better than Hunspell for programming modes.
#+BEGIN_SRC shell
brew install aspell
#+END_SRC
Start for all text modes (but not for log files):
#+BEGIN_SRC emacs-lisp
(use-package flyspell
:ensure t
:diminish flyspell-mode
:init
(add-hook 'prog-mode-hook 'flyspell-prog-mode)
(dolist (hook '(text-mode-hook org-mode-hook))
(add-hook hook (lambda () (flyspell-mode 1))))
(dolist (hook '(change-log-mode-hook log-edit-mode-hook org-agenda-mode-hook))
(add-hook hook (lambda () (flyspell-mode -1))))
:config
(setq ispell-program-name "/usr/local/bin/aspell"
ispell-local-dictionary "en_US"
ispell-dictionary "american" ; better for aspell
ispell-extra-args '("--sug-mode=ultra" "--lang=en_US")
ispell-list-command "--list"
ispell-local-dictionary-alist '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']"
t ; Many other characters
("-d" "en_US") nil utf-8))))
#+END_SRC
ASpell automatically configures a personal dictionary
at =~/.aspell.en.pws=, so no need to configure that.
A possibly nifty feature of aspell is the ability to spellcheck
individual words in CamelCase that is used extensively in some
code (for details, see [[http://blog.binchen.org/posts/what-s-the-best-spell-check-set-up-in-emacs.html][this article]]).
#+BEGIN_SRC emacs-lisp
(use-package flyspell
:config
(defun flyspell-detect-ispell-args (&optional run-together)
"if RUN-TOGETHER is true, spell check the CamelCase words."
(let (args)
(setq args (list "--sug-mode=ultra" "--lang=en_US"))
(if run-together
(setq args (append args '("--run-together" "--run-together-limit=5" "--run-together-min=2"))))
args))
;; ispell-cmd-args is useless, it's the list of *extra* arguments we will append to the ispell process when "ispell-word" is called.
;; ispell-extra-args is the command arguments which will *always* be used when start ispell process
(setq-default ispell-extra-args (flyspell-detect-ispell-args t))
(defadvice ispell-word (around my-ispell-word activate)
(let ((old-ispell-extra-args ispell-extra-args))
(ispell-kill-ispell t)
(setq ispell-extra-args (flyspell-detect-ispell-args))
ad-do-it
(setq ispell-extra-args old-ispell-extra-args)
(ispell-kill-ispell t)))
(defadvice flyspell-auto-correct-word (around my-flyspell-auto-correct-word activate)
(let ((old-ispell-extra-args ispell-extra-args))
(ispell-kill-ispell t)
;; use emacs original arguments
(setq ispell-extra-args (flyspell-detect-ispell-args))
ad-do-it
;; restore our own ispell arguments
(setq ispell-extra-args old-ispell-extra-args)
(ispell-kill-ispell t)))
(defun text-mode-hook-setup ()
;; Turn off RUN-TOGETHER option when spell check text-mode
(setq-local ispell-extra-args (flyspell-detect-ispell-args)))
(add-hook 'text-mode-hook 'text-mode-hook-setup))
#+END_SRC
According to [[http://pragmaticemacs.com/emacs/jump-back-to-previous-typo/][this essay]], we can make a =flyspell-goto-previous-error=
(which really should be added to the official =flyspell= project):
#+BEGIN_SRC emacs-lisp :tangle no
(defun flyspell-goto-previous-error (arg)
"Go to ARG previous spelling error."
(interactive "p")
(while (not (= 0 arg))
(let ((pos (point))
(min (point-min)))
(when (and (eq (current-buffer) flyspell-old-buffer-error)
(eq pos flyspell-old-pos-error))
(if (= flyspell-old-pos-error min)
;; goto beginning of buffer
(progn
(message "Restarting from end of buffer")
(goto-char (point-max)))
(backward-word 1))
(setq pos (point)))
;; seek the next error
(while (and (> pos min)
(let ((ovs (overlays-at pos))
(r '()))
(while (and (not r) (consp ovs))
(if (flyspell-overlay-p (car ovs))
(setq r t)
(setq ovs (cdr ovs))))
(not r)))
(backward-word 1)
(setq pos (point)))
;; save the current location for next invocation
(setq arg (1- arg))
(setq flyspell-old-pos-error pos)
(setq flyspell-old-buffer-error (current-buffer))
(goto-char pos)
(if (= pos min)
(progn
(message "No more miss-spelled words!")
(setq arg 0))))))
#+END_SRC