Hidden Gem Packages
Table of Contents
Author | Lee Hinman (lee@elastic.co) |
Date | 2017-11-02 16:04:23 |
Introduction
Let's talk about some "mini" packages that don't warrant a whole talk, but are really useful in a pinch nonetheless!
Hideshow
Hideshow is a buffer-local minor mode that allows you to selectively display portions of a program, called "blocks".
It's turned on and off with hs-minor-mode
and most of the bindings hide (hah get it!) behind C-c
@
:
Key | Action |
---|---|
C-c @ C-h |
Hide the current block (hs-hide-block ) |
C-c @ C-s |
Show the current block (hs-show-block ) |
C-c @ C-c |
Toggle visibility of the current block (hs-toggle-hiding ) |
S-mouse-2 |
Toggle hiding/showing for the block (hs-mouse-toggle-hiding ) |
C-c @ C-M-h |
Hide all the top level blocks (hs-hide-all ) |
C-c @ C-M-s |
Show all top level blocks (hs-show-all ) |
C-c @ C-l |
Hide blocks n levels below this block (hs-hide-level ) |
And there is a customization I'd recommend also:
;; Automatically open a block if you search for something where it matches (setq hs-isearch-open t)
Here's what I'd consider a minimal configuration for it:
(use-package hideshow :bind (("C-c TAB" . hs-toggle-hiding) ("C-\\" . hs-toggle-hiding) ("M-+" . hs-show-all)) :init (add-hook #'prog-mode-hook #'hs-minor-mode) :diminish hs-minor-mode :config ;; Add `json-mode' and `javascript-mode' to the list (setq hs-special-modes-alist (mapcar 'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (java-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (json-mode "{" "}" "/[*/]" nil) (javascript-mode "{" "}" "/[*/]" nil)))))
The main way I use this is to put the point (represented as |
in the code below) inside of an
expression and then hit C-c TAB
or C-\
, which changes
{ "foo": {| "bar": "baz" }, "eggplant": 11 }
Into
{ "foo": { ... }, "eggplant": 11 }
I have another helper that I really like (especially for Java files) that looks like:
(defvar eos/hs-level 2 "Default level to hide at when calling `eos/fold-show-only-methods'. This is buffers may set this to be buffer-local.") (setq eos/hs-fold-show-only-methods-active-p nil) (defun eos/hs-fold-show-only-methods () "Toggle between hiding all methods using `eos/hs-level' or showing them." (interactive) (save-excursion (if eos/hs-fold-show-only-methods-active-p (progn (hs-show-all) (setq-local eos/hs-fold-show-only-methods-active-p nil)) (progn (goto-char (point-min)) (hs-hide-level eos/hs-level) (setq-local eos/hs-fold-show-only-methods-active-p t))))) (global-set-key (kbd "M-\\") 'eos/hs-fold-show-only-methods)
I can then use M-\
to only show method names and signatures, hiding the bodies.
Expand-region
Expand-region let's you take the current point and expand the selection, this is great with things
like transient-mark-mode
and delete-selection-mode
!
(use-package expand-region :ensure t :defer t :bind (("C-c e" . er/expand-region) ;; I almost never use this, so it has an awkward binding ("C-M-@" . er/contract-region)))
Since this is hard to explain, I'll show what it does!
Git tools
Besides Magit, there are a bunch of other helpful tools for git, and vcs in general
git-gutter
Git-gutter is a way to show what parts of a file were changed. It pops up configurable symbols (+, -, =) in the margin. It's also a great way to navigate through a file by jumping through the parts that have been changed.
Here's how I like to configure it. Note that the git-gutter-fringe part is entirely optional and I only use for making the fringe look "nice" (I'll demo this). If you don't want it you can remove the custom bitmap definitions.
(use-package git-gutter :ensure t :when window-system :defer t :bind (("C-x P" . git-gutter:popup-hunk) ("C-x p" . git-gutter:previous-hunk) ("C-x n" . git-gutter:next-hunk) ("C-c G" . git-gutter:popup-hunk)) :diminish "" :init (add-hook 'prog-mode-hook #'git-gutter-mode) (add-hook 'text-mode-hook #'git-gutter-mode) :config (use-package git-gutter-fringe :ensure t :init (require 'git-gutter-fringe) (when (fboundp 'define-fringe-bitmap) (define-fringe-bitmap 'git-gutter-fr:added [224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224] nil nil 'center) (define-fringe-bitmap 'git-gutter-fr:modified [224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224] nil nil 'center) (define-fringe-bitmap 'git-gutter-fr:deleted [0 0 0 0 0 0 0 0 0 0 0 0 0 128 192 224 240 248] nil nil 'center))))
The other helpful thing is git-gutter:revert-hunk
which can be used to revert only a single chunk
of change without having to jump back into Magit.
git-timemachine
Git-timemachine allows you to go back through the history of a file, seeing how it's been changed. There really isn't much configuration:
(use-package git-timemachine :ensure t)
And then do M-x git-timemachine
, you can use p
and n
to jump between the previous and next
revision of the file, w
or W
to copy the short/full hash of the commit you're looking at, and
q
to quit.
There are a few more keybinds, so check out the project to see what else you can do!
git-messenger
Along the same lines, sometimes all you want to see is the message for the particular line you're
at. Git-messenger lets you pop this up and copy the relevant information. I like to bind mine to
C-c M
:
(use-package git-messenger :ensure t :commands git-messenger:popup-message :bind (("C-c M" . git-messenger:popup-message)) :config (setq git-messenger:show-detail t))
browse-at-remote
Finally, sometimes you need to send someone a link, and you want to open whatever you're currently looking at in the Github, Gitlab, Bitbucket, etc UI. Browse-at-remote lets you do this, and even highlights what ever you have selected in the UI.
(use-package browse-at-remote :ensure t :commands browse-at-remote :bind ("C-c g g" . browse-at-remote))
Let's see what it looks like!
Alert
Alert is for notifications, and very easy to use
(use-package alert :ensure t :config (when (eq system-type 'darwin) (setq alert-default-style 'notifier)) (when (eq system-type 'gnu/linux) (setq alert-default-style 'notifications)))
And then you can do:
(alert "Test alert") (alert "Give the presentation!" :title "Denver Emacs") (alert "Don't mess up!" :title "Emacs" :severity 'high)
Use it when your write your own helpers! Like this one that alerts when compilation (M-x compile
)
finishes:
(defun eos/compile-finished (buffer msg) (alert msg :title buffer :category 'compilation)) (add-to-list 'compilation-finish-functions 'eos/compile-finished)
Which-key
Which-key shows you possible completions when you half-type a shortcut. It's hard to explain so trying it is best, install it with the following:
(use-package which-key :ensure t :init (which-key-mode 1))
And then press C-h
, wait a few seconds, and then a popup comes up with all the options you can
choose. Very helpful! It works with any kind of prefix (try Helm's prefix key, C-x
, or C-c
for
instance)
Prodigy
Sometimes it can be helpful to start up a service, for instance, if you are a Ruby dev you might want to start a Rails server, or if you want to run some service you need for development.
Prodigy lets you have a great UI for this, as well as seeing the state, and viewing the logs
(use-package prodigy :ensure t :defer t :config (setq prodigy-services '()) (prodigy-define-service :name "Elasticsearch 5.6.3" :cwd "~/ies/elasticsearch-5.6.3" :command "~/ies/elasticsearch-5.6.3/bin/elasticsearch" :tags '(work test es) :port 9200) (prodigy-define-service :name "Simple HTTP server" :cwd "~/" :command "python" :args '("-m" "SimpleHTTPServer" "8000") :port 8000 :tags '(http)))
You can then do M-x prodigy
to bring up the UI and see what you can run. s
starts a command, S
stops it, and $
jumps to a buffer showing the logs from the process (g
refreshes the view).