commit
6b58db0866
|
@ -0,0 +1 @@
|
|||
auto-saved-list
|
|
@ -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
1066
config.org
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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? It’s
|
||||
closed for you already. Quoting something? It’s 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
|
|
@ -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. We’re using:
|
||||
|
||||
l: Use the long listing format.
|
||||
h: Use human-readable sizes.
|
||||
v: Sort numbers naturally.
|
||||
A: Almost all. Doesn’t 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
|
|
@ -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 doesn’t 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 can’t 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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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-developer’s 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.
|
|
@ -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
|
Loading…
Reference in New Issue