To use this change your init file for something like
(require 'org) (org-babel-load-file (expand-file-name "settings.org" user-emacs-directory))
Then you will only have your org file to handle all your emacs configuration. It may sound overkill in the beginning. It is not.
Bootstrapping use-package. This looks for use package in the system ans installs it if it is not there. This is the only package we need to install this way.
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile
(require 'use-package))
(require 'diminish) ;; if you use :diminish
(require 'bind-key) ;; if you use any :bind variant
I’ll add homebrewe’d emacs packages to load path. We only have to do this in a Mac.
(if (eq system-type 'darwin)
(let ((default-directory "/usr/local/share/emacs/site-lisp/"))
(normal-top-level-add-subdirs-to-load-path)))
Unfortunately I can’t store any secret in this file since it will go to Github. I’ll leave a secrets file apart to define variables.
(load-file "~/.emacs.d/secrets.el")
Copy the environment variables from shell’s environment
(use-package exec-path-from-shell
:ensure t
:no-require t
:config (progn
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
(exec-path-from-shell-copy-env "GEM_PATH")))
Let’s copy and paste in a regular Linux way
(cua-mode t)
I’ll add a function to edit settings.org file. I don’t need a shortcut since this is not such a common task now.
(defun settings ()
"Edits settings.org file"
(interactive)
(find-file "~/.emacs.d/settings.org"))
Make window undecorated
(set-frame-parameter nil 'undecorated t)
Remove scrollbars. One extra character per line and goodbye to that unthemed thing :P
(scroll-bar-mode -1)
Disable menu and icon bar
(menu-bar-mode -1)
(tool-bar-mode -1)
Show full path of file in status bar
(setq frame-title-format '(:eval (if (buffer-file-name) (abbreviate-file-name (buffer-file-name)) "%b")))
Paren highlight
(show-paren-mode 1)
(setq show-paren-delay 0)
Asking y/n instead of yes/no. Also preventing the dialog when on macos from being shown.
(defalias 'yes-or-no-p 'y-or-n-p)
(defadvice yes-or-no-p (around prevent-dialog activate)
"Prevent yes-or-no-p from activating a dialog"
(let ((use-dialog-box nil))
ad-do-it))
(defadvice y-or-n-p (around prevent-dialog-yorn activate)
"Prevent y-or-n-p from activating a dialog"
(let ((use-dialog-box nil))
ad-do-it))
We will use rainbow delimiters when possible
(use-package rainbow-delimiters
:ensure t
:init (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
Highlight current line
(global-hl-line-mode)
Do not show splash screen
(setq inhibit-splash-screen t)
Removing top bar in MacOS
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
(add-to-list 'default-frame-alist '(ns-appearance . dark))
Tab bar
(use-package centaur-tabs
:ensure t
:demand
:config (progn
(setq centaur-tabs-style "chamfer"
centaur-tabs-set-bar 'under
centaur-tabs-height 20
centaur-tabs-set-icons t
centaur-tabs-set-modified-marker t)
(centaur-tabs-mode t)
(defun centaur-tabs-hide-tab (x)
(let ((name (format "%s" x)))
(or
(string-prefix-p "*epc" name)
(string-prefix-p "*helm" name)
(string-prefix-p "*Compile-Log*" name)
(string-prefix-p "*lsp" name)
(and (string-prefix-p "magit" name)
(not (file-name-extension name)))
))))
:bind
("C-M-j" . centaur-tabs-backward)
("C-M-l" . centaur-tabs-forward))
Use spaces instead of tabs
(setq-default indent-tabs-mode nil)
Nothing bigger than 120 lines. This is nice also for code. ;). Anyway we can avoid the org node since this may make sense for longer texts.
(use-package whitespace
:ensure t
:diminish whitespace-mode
:config (progn (setq whitespace-line-column 120)
(setq whitespace-style '(face empty tabs lines-tail trailing))
(setq whitespace-global-modes '(not org-mode web-mode "Web" emacs-lisp-mode))
(global-whitespace-mode t)))
Enable word wrap globally.
(global-visual-line-mode t)
(diminish 'visual-line-mode)
(use-package doom-themes
:ensure t
:config (progn
(load-theme 'doom-one t)
(doom-themes-org-config)))
(use-package doom-modeline
:ensure t
:hook (after-init . doom-modeline-mode)
:config (setq doom-modeline-height 15))
Font. I like a ton of different fonts and I use them a lot. My choices are:
- Hermit / light: Playful. Coding must be fun.
- M+ 1mn / light: When you are feeling professional
- Iosevka / normal (180): A shorter alternative to M+
- Input Mono Compressed: Somewhat old school but really readable.
- Source code pro: Wide but nice
To show the list of available fonts you can eval (print (font-family-list))
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8)
(set-face-attribute 'default nil
:family "IBM Plex Mono"
:height 165
:weight 'regular
:width 'normal)
Manually setting font for managing Unicode symbols
(use-package unicode-fonts
:ensure t
:init (unicode-fonts-setup))
(set-fontset-font t 'unicode "Apple Color Emoji" nil 'prepend)
Smoother scrolling with mouse. This is the only thing I still miss from Sublime text
(setq mouse-wheel-follow-mouse 't)
(setq scroll-conservatively 101)
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
Scrolling with keyboard before touching bottom.
(setq redisplay-dont-pause t
scroll-margin 2
scroll-step 1
scroll-conservatively 10000
scroll-preserve-screen-position 1)
(use-package smooth-scrolling
:ensure t
:init (setq smooth-scroll-margin 10))
Let’s use ibuffer for buffer listing
(defalias 'list-buffers 'ibuffer)
This is useful in huge config files. In one project I’m dealing with huge yamls and this is great
(use-package highlight-indentation
:ensure t)
Let’s loop gifs by default
(setq image-animate-loop 1)
Use emacs native line numbers
(global-display-line-numbers-mode t)
Incremental search in minibuffer
(iswitchb-mode 1)
By default arrow keys do not work in iswitchb This can solve it
(defun iswitchb-local-keys ()
(mapc (lambda (K)
(let* ((key (car K)) (fun (cdr K)))
(define-key iswitchb-mode-map (edmacro-parse-keys key) fun)))
'(("<right>" . iswitchb-next-match)
("<left>" . iswitchb-prev-match)
("<up>" . ignore )
("<down>" . ignore ))))
(add-hook 'iswitchb-define-mode-map-hook 'iswitchb-local-keys)
(setq mac-option-key-is-meta t)
(setq mac-right-option-modifier nil)
(setq mac-command-modifier 'super)
This is not too useful but it is awesome. This makes Fn key in Mac to be Hyper. I must admit that this is only here so I can make an hyper-space combo.
(setq ns-function-modifier 'hyper) ; make Fn key do Hyper
There are some default mac bindings that are annoying to me. I will disable s-P for printing and all the function keys.
(global-unset-key (kbd "s-p"))
(global-unset-key (kbd "<f1>"))
(global-unset-key (kbd "s-w"))
(global-unset-key (kbd "<f2>"))
(global-unset-key (kbd "C-z"))
This takes back mouse and makes it work in a terminal. Commented until I make terminal mode to work as I want.
(require 'mouse)
(xterm-mouse-mode t)
(defun track-mouse (e))
(setq mouse-sel-mode t)
I like macos copy and paster better
(define-key global-map (kbd "s-x") 'kill-region)
(define-key global-map (kbd "s-c") 'kill-ring-save)
(define-key global-map (kbd "s-v") 'yank)
(define-key global-map (kbd "s-a") 'mark-whole-buffer)
This is a small script so ALT key drags lines up and down.
(use-package move-text
:ensure t
:bind (("M-<up>" . move-text-up)
("M-<down>" . move-text-down)))
Line duplication
(defun duplicate-line ()
"Duplicates current line"
(interactive)
(let
((text-to-insert (thing-at-point 'line)))
(forward-line 1)
(insert text-to-insert)
(forward-line -1)))
(global-set-key (kbd "C-*") 'duplicate-line)
(defun eval-and-replace ()
"Replace the preceding sexp with its value."
(interactive)
(backward-kill-sexp)
(condition-case nil
(prin1 (eval (read (current-kill 0)))
(current-buffer))
(error (message "Invalid expression")
(insert (current-kill 0)))))
(global-set-key (kbd "C-c C-e") 'eval-and-replace)
I don’t want ALT-backspace to change my kill ring since I don’t often want that there.
(defun delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
(interactive "p")
(delete-region (point) (progn (backward-word arg) (point))))
(global-set-key (kbd "<M-backspace>") 'delete-word)
This is a small snippet to move to next or previous windows with C-x p and C-x o
(global-set-key (kbd "C-x p") 'other-window)
(defun other-window-previous (&optional n)
"Moves to previous window"
(interactive "p")
(other-window (if n (- n) -1)))
(global-set-key (kbd "C-x o") 'other-window-previous)
(global-set-key (kbd "C-x l") 'next-buffer)
(global-set-key (kbd "C-x j") 'previous-buffer)
Enabling winner mode to restore the configuration of window layout.
(winner-mode t)
This is a cool package to help in making the current window more prominent
(use-package golden-ratio
:ensure t
:diminish golden-ratio-mode
:init
(golden-ratio-mode 1))
Eyebrowse is extremely useful for temporarily maximize a window and then go back to its previous split state.
(use-package eyebrowse
:ensure t
:init (eyebrowse-mode t))
Much better undo than the default one.
(use-package undo-tree
:ensure t
:diminish undo-tree-mode
:init
(progn
(global-undo-tree-mode 1)
(defalias 'redo 'undo-tree-redo)
(global-set-key (kbd "s-z") 'undo)
(global-set-key (kbd "s-Z") 'redo)))
This is binding the visualization to C-s-z but instead of that combo I need to use that strange status number.
(global-set-key (kbd "<C-s-268632090>") 'undo-tree-visualize)
Typing over a selection deletes text
(delete-selection-mode 1)
Expand region key binding.
(use-package expand-region
:ensure t
:bind (("C-s-e" . er/expand-region)
("C-s-E" . er/contract-region)))
These are multiple cursors bindings.
(use-package multiple-cursors
:ensure t
:bind (("C-d" . mc/mark-next-like-this)
("C-S-d" . mc/mark-previous-like-this)
("C-M-d" . mc/mark-all-like-this)
("H-SPC" . set-rectangular-region-anchor)))
Avy jump is great for moving around. I use the new timer version. This was introduced in avy 0.4.0 and it is a really beautiful way of moving around. A combination of classical avy jump + isearch
(use-package avy
:ensure t
:bind ("C-c j" . avy-goto-char-timer))
Multiple cursors has smoe weird requirements. We can use jump to char or phi search in order to make it easier to move backwars and forward
(use-package jump-char
:ensure t
:bind (("C-c u" . jump-char-backward)
("C-c i" . jump-char-forward)))
(use-package phi-search
:ensure t
:bind (("C-S-s" . phi-search)
("C-S-r" . phi-search-backward)))
(add-hook 'text-mode-hook 'goto-address-mode)
(add-hook 'prog-mode-hook 'goto-address-prog-mode)
For a personn that works in different languages this is awesome
(use-package dumb-jump
:bind (("C-." . dumb-jump-go)
("C-:" . dumb-jump-quick-look)
("M-g b" . dumb-jump-quick-look))
:config (setq dumb-jump-selector 'ivy)
:ensure)
(use-package yafolding
:ensure t
:init (add-hook 'ruby-mode-hook 'yafolding-mode)
:bind (("<C-return>" . yafolding-toggle-element)))
A small snippet to open current file in external editor.
TODO: give credit for this.
(defun open-with (arg)
"Open visited file in default external program.
With a prefix ARG always prompt for command to use."
(interactive "P")
(when buffer-file-name
(shell-command (concat
(cond
((and (not arg) (eq system-type 'darwin)) "open")
((and (not arg) (member system-type '(gnu gnu/linux gnu/kfreebsd))) "xdg-open")
(t (read-shell-command "Open current file with: ")))
" "
(shell-quote-argument buffer-file-name)))))
(global-set-key (kbd "C-c o") 'open-with)
Remove trailing whitespace of the file
(add-hook 'before-save-hook 'delete-trailing-whitespace)
I am not very happy with no emacs terminal so I will stay using tmux and have some shortcuts here
(use-package emamux
:ensure t
:bind (("C-ç" . emamux:send-command)))
(require 'midnight)
Kill buffers if they were last disabled more than this seconds ago
(setq clean-buffer-list-delay-special 900)
(defvar clean-buffer-list-timer nil
"Stores clean-buffer-list timer if there is one. You can disable clean-buffer-list by (cancel-timer clean-buffer-list-timer).")
;; run clean-buffer-list every 4 hours
(setq clean-buffer-list-timer (run-at-time t 14400 'clean-buffer-list))
;; kill everything, clean-buffer-list is very intelligent at not killing
;; unsaved buffer.
(setq clean-buffer-list-kill-regexps '("^.*$"))
This will create a folder called $HOME/.saves-emacs that will contain all backups.
This is done so we avoid cluttering the folder where the file is being edited
(setq
backup-by-copying t ; don't clobber symlinks
backup-directory-alist
'(("." . "~/.saves-emacs")) ; don't litter my fs tree
delete-old-versions t
kept-new-versions 6
kept-old-versions 2
version-control t) ; use versioned backups
Enabling projectile for project management
(use-package projectile
:ensure t
:diminish projectile-mode "Ⓟ"
:init (progn
(setq projectile-enable-caching nil)
(setq projectile-switch-project-action 'projectile-dired))
:config (progn
(projectile-mode +1)
(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)))
Let’s use Flycheck’s integration with ispell
(use-package flyspell
:ensure t
:bind (("C-S-s-<f8>" . cycle-ispell-languages)
("<f8>" . ispell-word))
:init (progn
(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'markdown-mode-hook 'flyspell-mode)
(let ((langs '("english" "spanish")))
(setq lang-ring (make-ring (length langs)))
(dolist (elem langs) (ring-insert lang-ring elem)))
(defun cycle-ispell-languages ()
(interactive)
(let ((lang (ring-ref lang-ring -1)))
(ring-insert lang-ring lang)
(ispell-change-dictionary lang)))
(ispell-change-dictionary "english")
(setq flyspell-default-dictionary "english"))
:config (unbind-key "C-," flyspell-mode-map))
And we can provide a thesaurus
(use-package synonyms
:ensure t
:bind ("S-<f8>" . synonyms)
:init (progn
(setq synonyms-file "~/.emacs.d/resources/synonyms/mthesaur.txt")
(setq synonyms-cache-file "~/.emacs.d/resources/synonyms/mthesaur.cache")))
;;(use-package minimal-theme
;; :ensure t)
(use-package writeroom-mode
:ensure t
:preface (defun my-writeroom-theme (arg)
(cond
((= arg 1)
(enable-theme 'minimal-light))
((= arg -1)
(disable-theme 'minimal-light)))))
Org mode is one of the most awesome things in emacs.
Binding F7 to open a personal_notes.org file in root of projectile and F3 to the agenda file.
(require 'projectile)
(defun my/projectile-open-personal-notes ()
"Opens a personal_notes.org file in project folder"
(interactive)
(let
((folder (projectile-project-root)))
(if folder
(progn
(split-window-right)
(other-window 1)
(find-file (concat folder "personal_notes.org")))
(message "No project folder found"))))
(defun my/open-org-agenda ()
"Opens agenda file"
(interactive)
(progn
(split-window-right)
(other-window 1)
(find-file "~/Nextcloud/org/index.org")))
(use-package org
:ensure t
:preface
(defun my/fix-inline-images ()
(when org-inline-image-overlays
(org-redisplay-inline-images)))
:bind (("<f3>" . my/open-org-agenda)
("<f7>" . my/projectile-open-personal-notes)
("C-c c" . org-capture)
("C-c a" . org-agenda))
:init (progn
(setq org-startup-with-inline-images t)
;; (setq org-hide-emphasis-markers t) <- This is causing problems with asterisks in headers
(setq org-default-notes-file "~/Nextcloud/org/capture.org")
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/Nextcloud/org/index.org" "Tasks") "* TODO %?\n %i\n %a")
("r" "Retro" entry (file+headline "~/Nextcloud/org/retro.org" "Retro") "* %?\nEntered on %U\n %i\n %a")))
(setq org-directory "~/Nextcloud/org")
(setq org-mobile-inbox-for-pull "~/Nextcloud/org/index.org")
(setq org-todo-keywords
'((sequence "TODO" "INPROGRESS" "DONE(!)" )))
)
:config (progn
(unbind-key "C-," org-mode-map)
(add-hook 'org-babel-after-execute-hook 'my/fix-inline-images)))
Org bullets will display bullet points as UTF characters
(use-package org-bullets
:ensure t
:config (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
The export to HTML of org mode requires htmlize
(use-package htmlize
:ensure t)
Let’s configure some languages to run in org-babel mode.
- Ditta: To draw diagrams
- Haskell
- Ruby
- A REST client
- Python
- Digraph
(org-babel-do-load-languages 'org-babel-load-languages '(
(ruby . t)
(ditaa . t)
(haskell . t)
(python . t)
(dot . t)))
(setq org-ditaa-jar-path "/usr/local/Cellar/ditaa/0.10/libexec/ditaa0_10.jar")
I can never accept code from external sources :P161
(defun my-org-confirm-babel-evaluate (lang body) nil)
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
Adding bibliography. I’m starting to write a lot these days so a bibliography plugin is nice.
(use-package org-ref
:ensure t)
Adding a function to save images in clipboard to a doc
(defun org-image-from-clipboard ()
"Takes a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
(interactive)
(org-display-inline-images)
(let ((filename (concat
(make-temp-name
(concat (file-name-nondirectory (buffer-file-name)) "_imgs/" (format-time-string "%Y%m%d_%H%M%S_")) ) ".png")))
(unless (file-exists-p (file-name-directory filename))
(make-directory (file-name-directory filename)))
(call-process "pngpaste" nil nil nil filename)
(if (file-exists-p filename)
(insert (concat "[[file:" filename "]]")))
(org-display-inline-images)))
Back to Ivy. It is faster than Helm and that is enough for me these days.
Swiper is beautiful. Better than standard search.
(use-package ivy
:ensure t
:diminish ivy-mode
:bind (("C-x b" . ivy-switch-buffer)
("C-c v" . ivy-push-view)
("C-c V" . ivy-pop-view))
:config (progn
(setq ivy-use-virtual-buffers t)
(define-key ivy-minibuffer-map (kbd "M-j") 'ivy-immediate-done))
:init (ivy-mode 1))
(use-package counsel
:ensure t
:bind (
("M-x" . counsel-M-x)
("C-S-f" . counsel-rg))
:init (setq counsel-rg-base-command "rg -i --no-heading --line-number --color never %s ."))
(use-package swiper
:ensure t
:bind ("C-s" . swiper))
Using projectile mode
(setq projectile-completion-system 'ivy)
(use-package counsel-projectile
:ensure t
:bind (("C-p" . counsel-projectile-find-file)
("C-f" . counsel-projectile-rg))
:init ()
:config ())
(use-package yasnippet
:ensure t
;; :diminish yas-minor-mode "Ⓨ "
:config (progn (setq yas-snippet-dirs '("~/.emacs.d/snippets"))
(add-hook 'term-mode-hook (lambda() (setq yas-dont-activate t)))
(yas-global-mode 1)))
Globally we will enable electric pair to match parentheses.
(electric-pair-mode 1)
We will globally enable syntax highlight
(use-package flycheck
:ensure t
:diminish flycheck-mode "✈"
:config (add-hook 'after-init-hook #'global-flycheck-mode))
Company mode is used for autocompletion
I set the delay to 0 to prevent any waiting for the autocompletion popup to show
Usually it is not needed at the start (remember I use emacs daemon).
(use-package company
:ensure t
:diminish company-mode "Ⓒ"
:init (global-company-mode)
:config (progn
(setq company-idle-delay .3)
(setq company-echo-delay 0)
(setq company-tooltip-limit 15)
(setq company-minimum-prefix-length 1)
(setq company-dabbrev-downcase nil)))
This comes with emacs by default so I won’t be use packaging
;(define-key c-mode-map "\C-d/" nil)
Awesome package to navigate json
(use-package json-navigator
:ensure t)
Just for coloring…
(use-package yaml-mode
:ensure t
:diminish)
;; (add-hook 'cider-mode-hook #'eldoc-mode)
;; In case of errors with nREPL you can enable this
;; (setq nrepl-log-messages t)
;; Hide cider special buffers
(setq nrepl-hide-special-buffers t)
;; Print a maximum of 100 items per collection
(setq cider-repl-print-length 100)
(setq cider-repl-result-prefix ";; => ")
(setq cider-interactive-eval-result-prefix ";; => ")
Let’s add some packages for Haskell coding
(use-package haskell-mode
:ensure t
:init (progn
(add-hook 'haskell-mode-hook 'flycheck-mode)))
(use-package web-mode
:ensure t
:mode (("\\.html?\\'" . web-mode)
("\\.html\\.erb\\'" . web-mode))
:config
(progn
(setq web-mode-markup-indent-offset 2)
(setq web-mode-css-indent-offset 2)
(setq web-mode-code-indent-offset 2)
(setq web-mode-enable-auto-pairing t))
(setq web-mode-enable-current-element-highlight t))
Also for SASS
(use-package scss-mode
:ensure t
:mode (("\\.scss\\'" . scss-mode))
:config (setq scss-compile-at-save nil))
Some projects I do use HAML
(use-package haml-mode
:ensure t)
And our good old Emmet. Previously called Zencoding
(use-package emmet-mode
:ensure t
:diminish
:config (progn
(add-hook 'css-mode-hook 'emmet-mode)
(setq emmet-expand-jsx-className? t)))
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (progn
(setq markdown-command "multimarkdown")
(setq markdown-max-image-size '(700 . 300)))
)
Saving images from clipboard in markdown
(defun md-image-from-clipboard ()
"Takes a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
(interactive)
(let ((filename (concat
(make-temp-name
(concat (file-name-nondirectory (buffer-file-name)) ".images/" (format-time-string "%Y%m%d_%H%M%S_")) ) ".png")))
(unless (file-exists-p (file-name-directory filename))
(make-directory (file-name-directory filename) t))
(call-process "pngpaste" nil nil nil filename)
(if (file-exists-p filename)
(insert (concat ""))))
)
Adding file types with no rb extension: rake files, irbrc…
(add-to-list 'auto-mode-alist
'("\\.\\(?:gemspec\\|irbrc\\|gemrc\\|rake\\|rb\\|ru\\|thor\\)\\'" . ruby-mode))
(add-to-list 'auto-mode-alist
'("\\(Capfile\\|Gemfile\\(?:\\.[a-zA-Z0-9._-]+\\)?\\|[rR]akefile\\)\\'" . ruby-mode))
;; Adding syntax checking
;(add-hook 'ruby-mode-hook 'flymake-ruby-load)
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(use-package projectile-rails
:ensure t
:diminish projectile-rails-mode "RoR "
:config (add-hook 'projectile-mode-hook 'projectile-rails-on))
Some customizations of highlight
- Highlight equal sign
- Mark a debug
(font-lock-add-keywords 'ruby-mode
'(("\\<\\(binding.pry\\|binding.irb\\)\\>" . font-lock-warning-face)
("\\<\\(=\\>\\)" . font-lock-keyword-face)))
For editing code in Ruby in electric mode
(use-package ruby-electric
:ensure t
:init (add-hook 'ruby-mode-hook #'ruby-electric-mode))
Use Rubocop for Ruby code linting
(use-package rubocop
:ensure t
:diminish rubocop-mode
:init (add-hook 'ruby-mode-hook #'rubocop-mode))
To not envy RubyMine users
(use-package ruby-refactor
:ensure t
:init (add-hook 'ruby-mode-hook 'ruby-refactor-mode-launch))
To avoid adding comments at the beginning of file
(setq ruby-insert-encoding-magic-comment nil)
(use-package crystal-mode
:ensure t)
(use-package alchemist
:ensure t
:config (setq alchemist-hooks-test-on-save t)
:bind (("C-c m" . alchemist-mix)))
Linting and syntax checking.
Before having it available you need to run
npm install -g eslint babel-eslint eslint-plugin-react
(use-package js2-mode
:ensure t
:init (setq js-indent-level 2)
:config (add-hook 'js-mode-hook 'js2-minor-mode))
React specific settings
(add-to-list 'auto-mode-alist '("\\.jsx$" . web-mode))
(setq web-mode-content-types-alist
'(("jsx" . "\\.js[x]?\\'")))
And for Vue.js
(use-package vue-mode
:ensure t
:defer)
(use-package coffee-mode
:ensure t
:config (custom-set-variables
'(coffee-tab-width 2)))
Both adding support for coding and babel to accept it
(use-package tide
:ensure t
:preface (defun my/tide-save-hook ()
(when (eq major-mode 'typescript-mode)
(tide-format-before-save)))
:mode ("\\.ts\\'" . typescript-mode)
:init
(add-hook 'typescript-mode-hook
(progn
;;(tide-setup)
(eldoc-mode +1)
(company-mode +1)
(flycheck-mode +1)
(tide-hl-identifier-mode +1)
(add-hook 'before-save-hook 'my/tide-save-hook)
(setq typescript-indent-level 4
typescript-expr-indent-offset 4
js-indent-level 4
company-tooltip-align-annotations t)
)))
(use-package ob-typescript
:ensure t
:init (org-babel-do-load-languages
'org-babel-load-languages
'((typescript . t))))
I will add angular support here since I play with angular only from typescript
(use-package ng2-mode
:ensure t)
Go mode. This will also autoformat after saving following go standards
We need to run the following commands in a new machine
“` go get golang.org/x/tools/cmd/goimports “`
(use-package go-mode
:ensure t
:defer
:bind ("C-c C-r" . go-remove-unused-imports)
:init (setq gofmt-command "goimports")
:config (add-hook 'before-save-hook 'gofmt-before-save))
(use-package go-guru
:ensure t
:defer)
(use-package go-complete
:ensure t
:config (add-hook 'completion-at-point-functions 'go-complete-at-point))
Autocomplete for Go. We will be using company mode too.
(use-package company-go
:defer
:ensure t
:config (add-hook 'go-mode-hook (lambda ()
(set (make-local-variable 'company-backends) '(company-go))
(company-mode))))
(use-package elm-mode
:ensure t
:defer
:init (progn
(add-hook 'elm-mode-hook #'elm-oracle-setup-completion)
(setq elm-format-on-save t)
(with-eval-after-load 'company
(add-to-list 'company-backends 'company-elm))))
(use-package rust-mode
:defer
:ensure t)
Racer gives us autocompletion. Before using we need:
$ rustup component add rust-src $ cargo install racer
(use-package racer
:defer
:ensure t
:init (progn
(add-hook 'rust-mode-hook #'racer-mode)
(add-hook 'racer-mode-hook #'eldoc-mode)))
Flycheck rust checker
(use-package flycheck-rust
:ensure t
:config (with-eval-after-load 'rust-mode
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup)))
Even though python-mode is good enough we need to do some linting
(use-package flymake-python-pyflakes
:ensure t
:init (setq flymake-python-pyflakes-executable "flake8"))
Using python3 exporting babel
(setq org-babel-python-command "python3")
All our projects.
(use-package pipenv
:ensure t
:init
(setq
pipenv-projectile-after-switch-function
#'pipenv-projectile-after-switch-extended)
:config
(add-hook 'python-mode-hook #'pipenv-mode))
Ethereum’s programming language
(use-package solidity-mode
:ensure t)
We have to install Dart in order to use this. Just remember to follow instructions at https://github.com/dart-lang/homebrew-dart
(use-package dart-mode
:config (setq dart-format-on-save t)
:ensure t)
(use-package lua-mode
:ensure t)
(use-package zig-mode
:ensure t)
(defun my/init-nim-mode ()
"Local init function for `nim-mode'."
(nimsuggest-mode)
;; Remember: Only enable either `flycheck-mode' or `flymake-mode' at the same time.
;; (flycheck-mode 1)
;; (flymake-mode 1)
;; The following modes are disabled for Nim files just for the case
;; that they are enabled globally.
;; Anything that is based on smie can cause problems.
(auto-fill-mode 0)
(electric-indent-local-mode 0)
)
(use-package nim-mode
:ensure t
:init (add-hook 'nim-mode-hook 'my/init-nim-mode))
(use-package protobuf-mode
:ensure t)
For init files we have conf mode
(use-package conf-mode
:ensure t)
We will use Magit for git. Also opening timemachine is a nice binding to have.
(define-prefix-command 'magit-map)
(global-set-key (kbd "C-,") 'magit-map)
(use-package magit
:ensure t
:bind (("<f6>" . magit-status)
("H-6" . magit-status)
("C-, ," . magit-status)
("C-, s" . magit-stage-file)
("C-, c" . magit-commit)
("C-, b" . magit-checkout)
("C-, l" . magit-log-buffer-file))
:config (progn
(setq magit-display-buffer-function 'magit-display-buffer-fullframe-status-v1)
(setq magit-revision-show-gravatars t)))
(use-package forge
:ensure t
:after magit)
Since I use github a lot let’s use this layer over magit
;; (use-package magithub
;; :ensure t
;; :after magit
;; :config
;; (magithub-feature-autoinject t)
;; (setq magithub-clone-default-directory "~/code"))
Time machine is a nice package to browse the story of a file
(use-package git-timemachine
:ensure t
:bind (("C-<f6>" . git-timemachine)))
Also for some projects it is nice to be able to browse the file on Github.
(use-package github-browse-file
:ensure t
:bind (("C-c g f" . github-browse-file)))
Emacs is great for managing docker images. Also I will use the syntax help for Dockerfiles
(use-package docker
:ensure t)
(use-package dockerfile-mode
:ensure t
:config (add-to-list 'auto-mode-alist '("Dockerfile\\'" . dockerfile-mode)))
When I start typing a combo a help with the possible continuations appear if I wait for a while.
(use-package which-key
:ensure t
:defer 0.2
:diminish
:config (which-key-mode))
Integration with Dash
(add-to-list 'load-path "~/.emacs.d/vendor/dash-at-point")
(autoload 'dash-at-point "dash-at-point"
"Search the word at point with Dash." t nil)
(global-set-key "\C-cd" 'dash-at-point)
(global-set-key "\C-ce" 'dash-at-point-with-docset)
(defun neotree-to-root ()
"Moves neotree to root of project"
(interactive)
(let ((git-folder (projectile-project-root)))
(neotree-dir git-folder)))
(use-package neotree
:ensure t
:bind ("<C-tab>" . neotree-toggle))
Start using dired+
Making dired to open the file in the current buffer instead of opening a new one
Dired likes gnu ls more than ls in osx so let’s make it use it
Wdired mode is awesome. Let’s bind a key to it. It allows us to write the buffer to rename files.
Also I prefer passing some switches to ls
(use-package dired
:config
(use-package dired+
:load-path "vendor/dired+/")
:init (progn
(put 'dired-find-alternate-file 'disabled nil)
(setq ls-lisp-use-insert-directory-program t)
(if (eq system-type 'darwin)
(setq insert-directory-program "gls"))
(setq dired-listing-switches "-lah")
))
(define-key dired-mode-map (kbd "C-w") 'wdired-change-to-wdired-mode)
Adding sort options to dired
(use-package dired-quick-sort
:ensure t
:config
(dired-quick-sort-setup))
This is just for measuring the frequency for the commands run
(use-package keyfreq
:ensure t
:init (progn
(keyfreq-mode 1)
(keyfreq-autosave-mode 1)
(setq keyfreq-excluded-commands
'(self-insert-command
abort-recursive-edit
previous-line
next-line))))
I use elfeed to read RSS. It can be configured via and org mode file. Extra awesomeness!
(defun elfeed-feeds ()
"Open the elfeed feeds file"
(interactive)
(find-file "~/.emacs.d/elfeed/elfeed.org"))
(defun my/elfeed-send-to-pocket ()
"Send current article to pocket"
(interactive)
(let
((url (elfeed-entry-link elfeed-show-entry)))
(shell-command (concat "echo '\\n\\n" url "' | msmtp readlater.iliwkd1e3iq@instapaper.com"))
(message "Saved to Instapaper!")))
(defun my/elfeed-send-to-tts ()
"Send current article to a text to speech system"
(interactive)
(let*
((html-to-read (elfeed-deref (elfeed-entry-content elfeed-show-entry)))
(text-to-read (replace-regexp-in-string "<.*?>" "" html-to-read))
(temp-input-file (make-temp-file "elfeed-input-tts"))
(temp-output-file (make-temp-file "elfeed-output-tts" nil ".mp3"))
(polly-command (concat "aws polly synthesize-speech --region eu-west-1 --output-format mp3 --voice-id Joanna --text \"$(< " temp-input-file ")\" " temp-output-file )))
(progn
(write-region text-to-read nil temp-input-file)
(shell-command polly-command)
(shell-command (concat "open -g " temp-output-file)))))
(use-package elfeed
:ensure t
:init (progn
(use-package elfeed-org
:ensure t
:init (progn
(elfeed-org)
(setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed/elfeed.org"))
(setq elfeed-use-curl t))
(setf url-queue-timeout 30)))
:config
(bind-keys :map elfeed-show-mode-map
("x" . my/elfeed-send-to-pocket)
("t" . my/elfeed-send-to-tts)))
Why leaving emacs? The most useful thing I can have here is just to stop current song if I have to pay attention to a different thing or stop the noise.
(use-package spotify
:ensure t
:bind (("C-c s" . spotify-playpause)))
To read PDFs let’s switch to pdf-tools. It is much much faster than docview. Also There is the interleave mode to ease the note taking.
(use-package pdf-tools
:ensure t
:init ()
:config (add-to-list 'auto-mode-alist '("\\.pdf\\'" . pdf-view-mode)))
(use-package interleave
:ensure t)
(use-package ivy-bibtex
:ensure t
:init (progn
(setq bibtex-completion-bibliography
'("~/Dropbox/org/library.bib"))
(setq bibtex-completion-fallback-options
'(("Lead 2 Amazon" . "http://lead.to/amazon/en/?key=%s&si=all&op=bt&bn=&so=sa&ht=us")
("Google Scholar" . "https://scholar.google.com/scholar?q=%s")))))
(setq debug-on-error t)
I migrated not so long ago my blog to hugo to be able to write posts in org mode.
(use-package easy-hugo
:ensure t
:init (progn
(setq easy-hugo-basedir "~/code/sites/joy.pm/")
(setq easy-hugo-url "https://joy.pm")
(setq easy-hugo-root "~/code/sites/joy.pm/")
(setq easy-hugo-previewtime "300")
))
I’m starting to use org-reveal for presentations
(use-package ox-reveal
:ensure t
:init ()
:config (setq org-reveal-root "vendor/reveal.js"))
I will create a pair of hydras.
- f1: Navigates between apps installed in emacs like twitter or email
- f2: Navigate between most used projects
(use-package hydra
:ensure t
:bind (("<f1>" . applications-menu/body))
:config (progn
(hydra-add-font-lock)
(defhydra applications-menu (:color blue :hint nil)
"
^Apps^
------
_f_: elfeed 📰 _b_: Blog 🖊
"
("f" elfeed :color blue)
("b" easy-hugo :color blue)
("q" nil))))
These are some general functions that are useful and have no better place to be in
Copies the file to the clipboard.
(defun current_buffer_file_name ()
(if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name)))
(defun copy-path-to-clipboard ()
"Copy the current buffer full file path to the clipboard."
(interactive)
(let ((filename (current_buffer_file_name)))
(when filename
(kill-new filename)
(message "Copied buffer file name '%s' to the clipboard." filename))))
(defun copy-filename-to-clipboard ()
"Copy the current buffer file name relative to projectile root to the clipboard."
(interactive)
(let* ((filename (replace-regexp-in-string (projectile-project-root) "" (current_buffer_file_name))))
(when filename
(kill-new filename)
(message "Copied buffer file name '%s' to the clipboard." filename))))
This function just reloads chrome. This is useful to avoid too much alt-tab
(defun chrome-reload ()
"Reloads current chrome window"
(interactive)
(shell-command "chrome-cli reload"))
(define-prefix-command 'manage-browser-map)
(global-set-key (kbd "C-b") 'manage-browser-map)
(defun chrome-reload ()
"Reloads current chrome window"
(interactive)
(shell-command "chrome-cli reload"))
(define-key manage-browser-map "r" 'chrome-reload)
These are scripts that are worthy of their own source file and I’m not including them here.
(use-package copy-rtf
:load-path "src/copy-rtf/"
:commands (copy-rtf))
(use-package p161-mode
:load-path "src/p161-mode/"
:commands p161-mode)
(defun turn-on-p161-mode-hook ()
(cond ((string-match "^//Users/rafael/code/platform161/" buffer-file-name)
(p161-mode 1))))
;; (add-hook 'text-mode-hook 'turn-on-p161-mode-hook)
(load-file "~/.emacs.d/src/emacs-presentation-mode/emacs-presentation-mode.el")
(load-file "~/.emacs.d/src/gif-me.el/gif-me.el")
(use-package org-jira
:ensure t
:config (setq jiralib-url "https://jira.platform161.com"))