literate_emacs icon indicating copy to clipboard operation
literate_emacs copied to clipboard

Literate Emacs configuration with EXWM

#+title: Emacs literate configuration #+author: Wanderson Ferreira #+EMAIL: [email protected] #+date: 2020:04:02

Literate Emacs configuration style. This is part of my journey for /Teach myself programming in 10 years/. I'm using this configuration on a system running [[https://wiki.archlinux.org/][Arch Linux]] and Emacs 26.3, that's why this configuration will be using the latest features and /not check/ for the system it's running on.

Every emacs user should write his own configuration file and steal as many code as he wants from here (or elsewhere).

#+BEGIN_SRC emacs-lisp (unless (equal user-login-name "wand") (warn "Please don't load Wand init file, it probably won't work for you.") (with-current-buffer " load" (goto-char (point-max)))) #+END_SRC

Very nice text about [[https://zachholman.com/2010/08/dotfiles-are-meant-to-be-forked/][Why should you share your dotfiles]]. I will try to record all relevant configuration of my current box in the literate style here.

Really trying to avoid another [[https://www.emacswiki.org/emacs/DotEmacsBankruptcy][Emacs Bankruptcy]]. o/

  • Summary :TOC:
  • [[#packages][Packages]]
    • [[#initialization][initialization]]
    • [[#use-package][use-package]]
    • [[#custom-packages][custom packages]]
  • [[#dependencies][Dependencies]]
    • [[#extra][extra]]
      • [[#scrot][scrot]]
      • [[#screensavers][screensavers]]
      • [[#dunst][dunst]]
      • [[#mpv][mpv]]
    • [[#browsers][browsers]]
      • [[#qutebrowser][qutebrowser]]
      • [[#google-chrome][google chrome]]
  • [[#operating-system][Operating System]]
    • [[#async][async]]
    • [[#path][path]]
    • [[#security][security]]
    • [[#compilation][compilation]]
    • [[#system-monitor][system monitor]]
    • [[#garbage-collection][garbage collection]]
      • [[#collector-magic-hack][collector magic hack]]
    • [[#manage-external-services][manage external services]]
  • [[#aesthetics][Aesthetics]]
    • [[#cleaning][cleaning]]
    • [[#theme-and-faces][theme and faces]]
      • [[#buffer-based-theming][buffer based theming]]
      • [[#download-themes][download themes]]
      • [[#default-theme][default theme]]
    • [[#time][time]]
    • [[#font][font]]
    • [[#mode-line][mode line]]
      • [[#menu][menu]]
    • [[#fringe][fringe]]
  • [[#defaults][Defaults]]
    • [[#ediff][ediff]]
    • [[#word-wrapping][word wrapping]]
    • [[#backup][backup]]
    • [[#recentf][recentf]]
    • [[#save-place][save place]]
    • [[#save-history][save history]]
    • [[#uniquify][uniquify]]
    • [[#extended-command][extended command]]
    • [[#case-switch][case switch]]
    • [[#registers][registers]]
    • [[#abbreviation][abbreviation]]
    • [[#imenu][imenu]]
    • [[#ibuffer][ibuffer]]
    • [[#minibuffer][minibuffer]]
      • [[#get-more-space-for-editing][get more space for editing]]
    • [[#calendar][calendar]]
    • [[#webjump][webjump]]
    • [[#authentication-source][authentication source]]
    • [[#enable-the-disabled-commands][enable the disabled commands]]
  • [[#hydras][Hydras]]
  • [[#help-and-info][Help and Info]]
    • [[#info][info]]
    • [[#customization-to-info-mode][customization to info-mode]]
      • [[#define-keys][define keys]]
      • [[#hydras-1][hydras]]
  • [[#editing-text][Editing Text]]
    • [[#defaults-1][defaults]]
      • [[#key-bindings][key bindings]]
      • [[#very-large-files][very large files]]
      • [[#eldoc][eldoc]]
      • [[#subword][subword]]
    • [[#extra-features][extra features]]
      • [[#change-inner][change inner]]
      • [[#expand-region][expand region]]
      • [[#jump-to-char][jump to char]]
      • [[#move-through-edit-points][move through edit points]]
    • [[#highlights][highlights]]
      • [[#symbols][symbols]]
      • [[#browse-kill-ring][browse kill ring]]
    • [[#utf-8][utf-8]]
    • [[#multiple-cursors][multiple cursors]]
    • [[#custom-functions][custom functions]]
      • [[#smart-move-to-beginning-of-visible-line-or-not][smart move to beginning of visible line (or not)]]
      • [[#unfill-paragraph][unfill paragraph]]
      • [[#unfill-region][unfill region]]
      • [[#duplicate-line-or-region][duplicate line or region]]
    • [[#web-paste][web paste]]
  • [[#completions][Completions]]
    • [[#minibuffer-1][minibuffer]]
      • [[#ivy][ivy]]
      • [[#icomplete][icomplete]]
    • [[#company-mode][company mode]]
      • [[#completion-help][completion help]]
      • [[#company-roam-backend][company roam backend]]
    • [[#hippie-expand][hippie expand]]
  • [[#window][Window]]
    • [[#scrolling][scrolling]]
    • [[#popwin][popwin]]
    • [[#ace-window][ace window]]
    • [[#custom-functions-1][custom functions]]
    • [[#clean-it-up-after-some-time][clean it up after some time.]]
    • [[#perspective][perspective]]
    • [[#same-window][same window]]
    • [[#winner][winner]]
    • [[#resize][resize]]
  • [[#alerts][Alerts]]
    • [[#alert][alert]]
    • [[#user-configuration][user configuration]]
      • [[#slack-notifications][slack notifications]]
      • [[#telegram-notifications][telegram notifications]]
    • [[#custom-functions-2][custom functions]]
  • [[#dired][Dired]]
    • [[#hide-details][hide details]]
    • [[#guidelines][guidelines]]
      • [[#mark-files-in-dired][mark files in dired]]
      • [[#replace-text-in-multiple-files][replace text in multiple files]]
    • [[#functions][functions]]
  • [[#bookmark][Bookmark]]
  • [[#tramp][TRAMP]]
  • [[#version-control][Version Control]]
    • [[#magit][magit]]
      • [[#magit-setup][magit setup]]
      • [[#magit-hydra][magit hydra]]
      • [[#forge][forge]]
    • [[#git-config][git config]]
    • [[#git-ignore][git ignore]]
    • [[#time-machine][time machine]]
    • [[#visual-identification][visual identification]]
    • [[#miscellaneous][miscellaneous]]
    • [[#custom-functions-3][custom functions]]
      • [[#visit-pull-request][visit pull request]]
  • [[#search][Search]]
    • [[#wgrep][wgrep]]
    • [[#visual-regexp][visual regexp]]
    • [[#grep-fullscreen][grep fullscreen]]
    • [[#ripgrep][ripgrep]]
    • [[#isearch][isearch]]
    • [[#occur][occur]]
    • [[#google-this][google this]]
  • [[#shell][Shell]]
    • [[#eshell-mode][eshell mode]]
      • [[#change-defaults][change defaults]]
      • [[#clear-buffer][clear buffer]]
      • [[#bookmark-1][bookmark]]
      • [[#aliases][aliases]]
    • [[#shell-mode][shell mode]]
  • [[#general-programming][General Programming]]
    • [[#toggle-between-src-and-tests][toggle between src and tests]]
    • [[#whitespaces][whitespaces]]
      • [[#hungry-delete][hungry delete]]
    • [[#parenthesis][parenthesis]]
      • [[#paredit][paredit]]
      • [[#disabled-smartparens][DISABLED smartparens]]
    • [[#folding][folding]]
      • [[#folding-based-on-indentation-and-syntax][folding based on indentation and syntax]]
      • [[#fold-regions-based-on-selection][fold regions based on selection]]
    • [[#go-to-definition][go to definition]]
      • [[#dumb-jump][dumb jump]]
    • [[#documentation][documentation]]
    • [[#programming-languages][programming languages]]
      • [[#clojure][clojure]]
      • [[#common-lisp][common lisp]]
      • [[#elisp][elisp]]
      • [[#python][python]]
      • [[#sql][sql]]
      • [[#latex][latex]]
      • [[#tla-plus][tla plus]]
    • [[#linters][linters]]
    • [[#unified-modeling-language][unified modeling language]]
    • [[#how-do-i-do-it][how do I do it?]]
    • [[#custom-functions-4][custom functions]]
      • [[#align-blocks][align blocks]]
  • [[#additional-major-modes][Additional Major Modes]]
    • [[#rest-client][rest client]]
      • [[#create-a-tmp-restclient-buffer][create a tmp restclient buffer]]
    • [[#edn][edn]]
    • [[#markdown][markdown]]
    • [[#json][json]]
    • [[#xml][xml]]
    • [[#yaml][yaml]]
    • [[#makefile][makefile]]
  • [[#pdf][PDF]]
  • [[#org-mode][Org mode]]
    • [[#literate-programming][literate programming]]
      • [[#what-is-noweb][what is noweb?]]
    • [[#table-of-contents][table of contents]]
    • [[#configuration][configuration]]
      • [[#defaults-2][defaults]]
      • [[#capture][capture]]
      • [[#babel][babel]]
      • [[#structure-templates][structure templates]]
      • [[#revealjs][reveal.js]]
    • [[#habits][habits]]
      • [[#documentation-repeated-tasks][[documentation] repeated tasks]]
    • [[#journal][journal]]
      • [[#what-is-a-personal-journal][what is a personal journal?]]
      • [[#writeroom][writeroom]]
    • [[#presentation][presentation]]
    • [[#agenda][agenda]]
      • [[#defaults-3][defaults]]
      • [[#disabled---gmail-agenda][DISABLED - gmail agenda]]
    • [[#beamer][beamer]]
    • [[#tips-and-tricks][tips and tricks]]
      • [[#compute-difference-between-two-dates][compute difference between two dates.]]
      • [[#insert-template-for-documenting-a-meeting][insert template for documenting a meeting]]
      • [[#export-to-asciidoc][export to asciidoc]]
  • [[#second-brain][Second brain]]
    • [[#org-roam][Org Roam]]
    • [[#protocol][Protocol]]
    • [[#enable-local-files][Enable local files]]
  • [[#tip-of-the-day][Tip of the day]]
  • [[#projects][Projects]]
  • [[#spelling][Spelling]]
    • [[#correct-your-spelling-errors-on-the-fly][correct your spelling errors on the fly]]
    • [[#using-a-grammar--style-checker][using a grammar & style checker]]
    • [[#synonyms][synonyms]]
    • [[#translate][translate]]
    • [[#typing][typing]]
  • [[#snippets][Snippets]]
  • [[#docker][Docker]]
  • [[#social-networks][Social Networks]]
    • [[#rss-feed][rss feed]]
      • [[#load-config][load config]]
      • [[#elfeed-newsletters][elfeed newsletters]]
      • [[#filter][filter]]
      • [[#automatic-update][automatic Update]]
      • [[#star-and-unstar][star and unstar]]
      • [[#youtube][youtube]]
      • [[#score][score]]
    • [[#slack][slack]]
      • [[#custom-functions-5][custom functions]]
    • [[#telegram][telegram]]
    • [[#spotify][spotify]]
    • [[#twitter][twitter]]
  • [[#weather][Weather]]
  • [[#pomodoro][Pomodoro]]
  • [[#financial][Financial]]
    • [[#ledger-explanation][ledger explanation]]
      • [[#plaintext-accounting-with-the-ledger-ecosystem][plaintext accounting with the ledger ecosystem]]
  • [[#guru][Guru]]
  • [[#advice][Advice]]
    • [[#pop-to-mark][pop to mark]]
    • [[#yank-indent][yank indent]]
  • [[#recording][Recording]]
    • [[#timing][timing]]
  • [[#logs][Logs]]
    • [[#commands-logs][commands logs]]
  • [[#custom-functions-6][Custom Functions]]
    • [[#shell-1][shell]]
      • [[#kubernetes][kubernetes]]
      • [[#keys-i-use-to-work-with][keys i use to work with]]
    • [[#http-based][http-based]]
      • [[#find-my-current-ip][find my current ip]]
    • [[#editing][editing]]
      • [[#what-sudo][what? sudo!]]
      • [[#eval-and-replace][eval and replace]]
      • [[#insert-todays-date][insert today's date]]
      • [[#kill-all-the-comments][kill all the comments]]
    • [[#buffer][buffer]]
      • [[#go-to-scratch-buffer][go to scratch buffer]]
      • [[#kill-buffer-and-the-file-associated][kill buffer and the file associated]]
      • [[#rename-current-buffer-and-file-associated][rename current buffer and file associated]]
    • [[#miscellaneous-1][miscellaneous]]
      • [[#generate-password][generate password]]
  • [[#keys][Keys]]
    • [[#free-keys][free keys?]]
    • [[#hint][hint]]
    • [[#global-definitions][global definitions]]
    • [[#cast][cast]]
    • [[#key-frequency][key frequency]]
  • [[#emms][Emms]]
    • [[#mode-line-cycle][mode line cycle]]
  • [[#exwm][Exwm]]
    • [[#lxde][lxde]]
    • [[#additional-functions][additional Functions]]
    • [[#exwm-basics][exwm basics]]
      • [[#window-manager][window manager]]
    • [[#edit-text-fields][edit text fields]]
    • [[#app-runner][app runner]]
    • [[#multiple-screens][multiple screens]]
    • [[#system-package][system package]]
    • [[#notification-daemon][notification daemon]]
    • [[#window-behaviour][window behaviour]]
    • [[#key-bindings-1][key bindings]]
      • [[#logging-out-with-lxde][Logging out with LXDE]]
    • [[#important-commands][important commands]]
  • [[#references][References]]
  • Packages

    Emacs facility to download and install "packages" that implement additional features. You can find information about a specific package by using =C-h P= that prompts for the name and shows more details.

    There is a very detail package in Emacs help system that you can find on [[info:emacs#Packages][info:emacs#Packages]].

    I always start a new configuration setup with a naive mindset that I will not install thousands of external packages, however they are so good and make our life so much easier that is hard to avoid them altogether.

** initialization

Let's initialize the package system. #+begin_src emacs-lisp (require 'package)

 (unless (bound-and-true-p package--initialized)
   (package-initialize))

#+end_src

Despite the fact that GNU Elpa, the standard repository, of Emacs packages maintained by the core team already have many different packages, I like to use another external repository called [[https://melpa.org/#/][Melpa]] which is currently maintained by the community and curated by Purcell's and his team.

#+begin_src emacs-lisp (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t) #+end_src

We need to refresh the archives to make this change to take place.

#+begin_src emacs-lisp (unless (file-exists-p "~/.emacs.d/elpa/archives/melpa") (package-refresh-contents)) #+end_src

Also, by default Emacs also automatically loads all installed packages in subsequent Emacs session. I want to disable it.

#+begin_src emacs-lisp (setq package-enable-at-startup nil) #+end_src

** use-package

When you have more than a dozen packages, it makes the process of managing them very difficult without any additional help. And by my experience the only real issue is due to performance because you will inevitably have many external packages loaded in situations where you don't need it. Fortunately, Jon Wiegley made our lives easier by creating =use-package=, please look for =C-h P use-package= to more details.

#+begin_src emacs-lisp (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package) (package-install 'delight))

 (require 'use-package)

#+end_src

We can add new keywords to =use-package=, stolen from [[https://github.com/xuchunyang/emacs.d/blob/master/init.el][here.]] #+BEGIN_SRC emacs-lisp (defmacro bk-use-package-keywords-add (keyword) "Add new keyword as placeholder" `(progn (add-to-list 'use-package-keywords ,keyword 'append) (defun ,(intern (format "use-package-normalize/%s" keyword)) (&rest _)) (defun ,(intern (format "use-package-handler/%s" keyword)) (&rest _))))

(bk-use-package-keywords-add :about)
(bk-use-package-keywords-add :homepage)

#+END_SRC

** custom packages

Some old packages simply are not in any repository, they are only elisp files distributed over the web. I will place these files inside a folder called =lisps=.

#+BEGIN_SRC emacs-lisp (setq site-lisps-dir (expand-file-name "lisps" user-emacs-directory))

(dolist (project (directory-files site-lisps-dir t "\\w+"))
  (when (file-directory-p project)
    (add-to-list 'load-path project)))

#+END_SRC

  • Dependencies

    List of external packages that I rely on in my daily basis

** extra *** scrot

[[https://en.wikipedia.org/wiki/Scrot][Scrot]] (SCReenshOT) is a screenshot capturing utility that uses the
imlib2 library to acquire and save images. By default, the
captured file is saved with a date-stamped filename in the current
directory, although you can also explicitly specify the name of
the captured images when the command is run.

Generic command to help us out here!
#+BEGIN_SRC emacs-lisp
  (defun bk/scrot-cmd (cmd name folder)
    "Scrot CMD to be executed and saving to the correct picture NAME in the FOLDER.
  Folder is a symbol recognizing the folder name."
    (interactive)
    (let* ((folder-path (cl-case folder
                         (:window "/home/wand/Pictures/window/")
                         (:region "/home/wand/Pictures/region/")
                         ))
           (filepath (concat folder-path name ".png"))
           (scrot-cmd (format "scrot %s %s -e 'xclip -selection c -t image/png < $f'" cmd filepath)))
      (start-process-shell-command "pt" nil scrot-cmd)))
#+END_SRC

Capture the print screen of the current window
#+BEGIN_SRC emacs-lisp
  (defun bk/print-window ()
    "Print current window."
    (interactive)
    (let ((print-name (read-from-minibuffer "Print name: ")))
      (bk/scrot-cmd "" print-name :window)))
#+END_SRC

Print screens are way to serious, right? Take that region
#+BEGIN_SRC emacs-lisp
  (defun bk/print-region ()
    "Print screen interactively."
    (interactive)
    (let ((print-name (read-from-minibuffer "Print name: ")))
      (bk/scrot-cmd "-s" print-name :region)))

  (eval-after-load 'exwm
    '(exwm-input-set-key (kbd "<print>") #'bk/print-region))
#+END_SRC

I also need to go fast to these folders, no more: 
=C-x C-j /home C-s Pictures RET {window,region}= o.O

#+BEGIN_SRC emacs-lisp
  (set-register ?w '(file . "~/Pictures/window"))
  (set-register ?r '(file . "~/Pictures/region"))
#+END_SRC

*** screensavers

I use the external package called =xscreensaver= which is amazing.
You can lock the screen by pressing =s-l= or calling =M-x
bk/lock-screen=.

Emacs zone is also an happy surprise for me. It seems like this is
a default mode to 'zones' Emacs out by choosing one of its random
modes to obfuscate the current buffer, which can then be used as a
screensaver.

I will add some configuration for this.
#+BEGIN_SRC emacs-lisp

  (use-package zone
    :ensure nil
    :config
    (defvar zone--window-config nil)
    (defadvice zone (before zone-ad-clean-ui)
      "Maximize window before `zone' starts."
      (setq zone--window-config (current-window-configuration))
      (delete-other-windows)
      (when (and (eq window-system 'x) (executable-find "xtrlock"))
        (start-process "xtrlock" nil "xtrlock")))
    (defadvice zone (after zone-ad-restore-ui)
      "Restore window configuration."
      (when zone--window-config
        (set-window-configuration zone--window-config)
        (setq zone--window-config nil)))
    (ad-activate 'zone))
#+END_SRC

I also installed =xtrlock= so when I activate =zone= I also lock
my screen. In order to unlock you just need to start typing the
correct password and press =RET=.

*** dunst

[[https://dunst-project.org/][Dunst]] is a lightweight replacement for the notification-daemons
provided by most desktop environments. Dunst allows for the use of
HTML markup in notifications, some examples are bold, italics,
strike-though, and underline.

The relevant bits of my =.dunstrc=.
#+BEGIN_SRC bash
  [global]
  font = Source Code Pro Medium

  [urgency_low]
  # IMPORTANT: colors have to be defined in quotation marks.
  # Otherwise the "#" and following would be interpreted as a comment.
  frame_color = "#3B7C87"
  foreground = "#3B7C87"
  background = "#191311"
  timeout = 8

  [urgency_normal]
  frame_color = "#5B8234"
  foreground = "#5B8234"
  background = "#191311"
  timeout = 10

  [urgency_critical]
  frame_color = "#B7472A"
  foreground = "#B7472A"
  background = "#191311"
  timeout = 12
#+END_SRC

*** mpv

[[https://mpv.io/][mpv]] is a free (as in freedom) media player for the command line.
It supports a wide variety of media file formats, audio, and video
codecs, and subtitle types.

On screen controller, while mpv strives for minimalism and
provides no real GUI, it has a small controller on top of the
video for basic control.

** browsers *** qutebrowser

A keyboard-driven, vim-like browser based on PyQt5 [[https://www.qutebrowser.org/][web browser]] with
a minimal GUI.

I met this project back at the university in 2012 and is hard to
remember but I think it was the first time that I talked to other
programmers online with attempts to report bugs and errors for the
maintainers of this browser. Very nice project.

The [[https://raw.githubusercontent.com/qutebrowser/qutebrowser/master/doc/img/cheatsheet-big.png][cheat sheet]] is very important.

The following file is not my complete =config.py= file for
qutebrowser, only the diff from defaults. If you want to create a
default config file, you should use =:config-write-py --default=.

#+BEGIN_SRC conf
  # Always restore open sites when qutebrowser is reopened.
  # Type: Bool
  c.auto_save.session = False

  # Show javascript alerts
  # Type: Bool
  c.content.javascript.alert = False

  # Allow websites to record audio/video
  c.content.media_capture = 'ask'

  # Allow websites to lock your mouse
  c.content.mouse_lock = True

  # Allow websites to show notifications
  c.content.notifications = False

  ## Open a new window for every tab.
  ## Type: Bool
  c.tabs.tabs_are_windows = True
#+END_SRC

*** google chrome

You know, that time when the internet tells you: "you can't see
this page without a google-based product today"
  • Operating System

    Functionalities that interface directly with the underlying operating system.

** async

Asynchronous bytecode compilation and various other actions makes Emacs look SIGNIFICANTLY less often which is a good thing. #+BEGIN_SRC emacs-lisp (use-package async :ensure t :defer t :init (dired-async-mode 1) (async-bytecomp-package-mode 1) :custom (async-bytecomp-allowed-packages '(all))) #+END_SRC

** path

Teach Emacs about the PATH of the underlying OS.

#+begin_src emacs-lisp (setenv "PATH" (concat (getenv "PATH") ":/home/wand/private/scripts")) (setq exec-path (append exec-path '("/home/wand/private/scripts")))

 (setenv "PATH" (concat (getenv "PATH") ":/usr/local/bin"))
 (setq exec-path (append exec-path '("/usr/local/bin")))

 (setenv "LD_LIBRARY_PATH" (concat (getenv "LD_LIBRARY_PATH") ":/usr/local/lib"))
 (setq exec-path (append exec-path '("/usr/local/lib")))

#+end_src

I've been using qutebrowser as my main browser for more than one year now. Idk, I like keyboard centric products. #+BEGIN_SRC emacs-lisp (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "qutebrowser") #+END_SRC

** security

Fix old security Emacs problems #+BEGIN_SRC emacs-lisp (eval-after-load "enriched" '(defun enriched-decode-display-prop (start end &optional param) (list start end))) #+END_SRC

** TODO compilation

#+begin_src emacs-lisp (use-package emacs :ensure nil :config (setq compilation-always-kill t compilation-ask-about-save nil compilation-context-lines 10 compilation-window-height 100 compilation-scroll-output 'first-error)) #+end_src

** system monitor

A tiny system monitor that can be enabled or disabled at runtime, useful for checking performance with power-hungry processes in ansi-term. #+BEGIN_SRC emacs-lisp (use-package symon :ensure t :defer t) #+END_SRC

Built in =htop=. #+BEGIN_SRC emacs-lisp (setq proced-auto-update-flag t proced-auto-update-interval 1 proced-descend t) #+END_SRC

** garbage collection

Garbage collection shouldn't happen during startup, as what will slow Emacs down. Do it later.

Change the default values. #+BEGIN_SRC emacs-lisp (defvar file-name-handler-alist-old file-name-handler-alist)

 (setq-default gc-cons-threshold 402653184
               file-name-handler-alist nil
               gc-cons-percentage 0.6
               auto-window-vscroll nil
               message-log-max 16384)

 (add-hook 'after-init-hook
           `(lambda ()
              (setq file-name-handler-alist file-name-handler-alist-old
                    gc-cons-threshold 800000
                    gc-cons-percentage 0.1)
              (garbage-collect)) t)

#+END_SRC

Ease the font caching during GC. #+begin_src emacs-lisp (setq inhibit-compacting-font-caches t) #+end_src

Emacs can inform us when the garbage collection is happening. I do not want to see this anymore... it was useful to understand the behavior for configuration. #+BEGIN_SRC emacs-lisp (setq garbage-collection-messages nil) #+END_SRC

*** collector magic hack

Enforce a sneaky GC strategy to minimize GC interference with the
activity. During normal use a high GC threshold is set, when
idling GC is immediately triggered and a low threshold is set.

#+BEGIN_SRC emacs-lisp
  (use-package gcmh
    :ensure t
    :disabled t
    :init
    (setq gcmh-verbose nil)
    :config
    (gcmh-mode 1))
#+END_SRC

** manage external services

Very interesting package that help us to have some instances of external processes running and keep track of it all. I often need to enable the VPN of my company to work remotely, this suits nicely.

#+BEGIN_SRC emacs-lisp (use-package prodigy :ensure t :config (prodigy-define-service :name "Captalys VPN" :command "captalys-vpn" :tags '(captalys) :stop-signal 'sigkill :kill-process-buffer-on-stop t)

   (prodigy-define-service
     :name "Blog"
     :command "lein ring server"
     :cwd "~/bartuka-blog"
     :stop-signal 'sigkill
     :tags '(blog)
     :kill-process-buffer-on-stop t)

   (prodigy-define-tag
     :name 'captalys
     :ready-message "Initialization Sequence Completed")
   (prodigy-define-tag
     :name 'blog
     :ready-message "Started server on port 3000"))

#+END_SRC

  • Aesthetics

    Look and fill of several aspects of Emacs: mode-line, fonts, specific faces, fringe, and more.

** cleaning

Since I never use the mouse with GNU Emacs, I prefer not to use
invasive graphical elements.
#+begin_src emacs-lisp
  (when window-system
    (menu-bar-mode -1)
    (tool-bar-mode -1)
    (scroll-bar-mode -1))
#+end_src

Emacs convention is to show help and other inline documentation in
the message area. Show help there instead of OS tooltip.
#+BEGIN_SRC emacs-lisp
  (when (display-graphic-p)
    (tooltip-mode -1))
#+END_SRC

Let's remove some crunchy messages at startup time.
#+begin_src emacs-lisp
  (setq inhibit-splash-screen t
        inhibit-startup-echo-area-message t)
#+end_src

Enabling some builtin modes that are very helpful e.g. highlight
the positions of open/close of parenthesis, prettify symbols for
now basically converts a fn to a lambda symbol, but I intend to
expand the list of converted symbols.

#+begin_src emacs-lisp
  (show-paren-mode t)
  (global-prettify-symbols-mode t)
  (blink-cursor-mode 0)
#+end_src

#+begin_src emacs-lisp
  (use-package simple
    :ensure nil
    :delight auto-fill-mode
    :config
    (add-hook 'text-mode-hook #'auto-fill-mode))
#+end_src

** theme and faces

The color theme is always a complicated matter. I've been trying
several ones, most recently I had settle with Protesilaos
=modus-{operandi,vivendi}= packages, but now I want to try =dakrone=
for a while. =deprecated= already. I will be using the default
white one.

Find out what face something at point have.
#+BEGIN_SRC emacs-lisp
  (defun what-face (pos)
    (interactive "d")
    (let ((face (or (get-char-property (point) 'read-face-name)
                    (get-char-property (point) 'face))))
      (if face (message "Face: %s" face) (message "No face at %d" pos))))
#+END_SRC

Change the highlight color for selection text.
#+BEGIN_SRC emacs-lisp
  (set-face-attribute 'region nil :background "#D5F0D5")
#+END_SRC

Make cursor the width of the character it is under.
#+BEGIN_SRC emacs-lisp
  (setq x-stretch-cursor t)
#+END_SRC

Allow only one theme at a time
#+BEGIN_SRC emacs-lisp
  (setq custom-theme-allow-multiple-selections nil)
#+END_SRC

Set the custom theme path
#+BEGIN_SRC emacs-lisp
  (setq custom-theme-directory (concat user-emacs-directory "themes"))

  (dolist
      (path (directory-files custom-theme-directory t "\\w+"))
    (when (file-directory-p path)
      (add-to-list 'custom-theme-load-path path)))
#+END_SRC

*** buffer based theming

#+BEGIN_SRC emacs-lisp
  (use-package load-theme-buffer-local
    :ensure nil
    :about I am using a custom version located at /lisps folder of this setup.
    :commands (load-theme-buffer-local))
#+END_SRC

*** download themes **** organic green

A light theme with a light-green background.

I enjoyed so much this theme, that I started contributing to the
source code. Right now, I am modernizing the structure and color
pallets to be more organized and comprehensive.

**** cyberpunk

 Real dark theme.
 #+begin_src emacs-lisp
   (use-package cyberpunk-theme
     :ensure t
     :disabled t
     :config
     (load-theme 'cyberpunk t))
 #+end_src

**** zenburn

 #+begin_src emacs-lisp
   (use-package zenburn-theme
     :ensure t
     :disabled t
     :config
     (load-theme 'zenburn t))
 #+end_src

**** monokai

 #+begin_src emacs-lisp
   (use-package monokai-theme
     :ensure t
     :defer t)

 #+end_src

**** tomorrow night

 #+begin_src emacs-lisp
   (use-package color-theme-sanityinc-tomorrow
     :ensure t
     :defer t)
 #+end_src

*** default theme

Let's activate the default theme, I might change this very often.
#+BEGIN_SRC emacs-lisp
  (add-hook 'after-init-hook
    (lambda ()
      (interactive)
      (load-theme 'organic-green t)))
#+END_SRC

** time

#+BEGIN_SRC emacs-lisp (use-package time :ensure nil :init (setq display-time-default-load-average nil display-time-format "%Hh%M " display-time-day-and-date t) :config (display-time-mode t)) #+END_SRC

** font

redefine the size of the font. #+begin_src emacs-lisp (when (member "Monaco" (font-family-list)) (set-face-attribute 'default nil :font "Monaco" :height 120) (setq default-frame-alist '((font . "Monaco-12")))) #+end_src

** mode line

*** menu

This package implements a menu that lists enabled minor-modes, as
well as commonly but not currently enabled minor-modes. It can be
used to toggle local and global minor-modes, to access
mode-specific menus, and to get help about modes.

#+BEGIN_SRC emacs-lisp
  (use-package minions
    :ensure t
    :config
    (minions-mode 1))
#+END_SRC

** fringe

Control the fringe around the frame.
#+BEGIN_SRC emacs-lisp
  (fringe-mode '(10 . 1))
#+END_SRC

Preview line numbers when prompting for line number.
#+BEGIN_SRC emacs-lisp
  (define-advice goto-line (:before (&rest _) preview-line-number)
    "Preview line number when prompting for goto-line."
    (interactive
     (lambda (spec)
       (if (and (boundp 'display-line-numbers)
                (not display-line-numbers))
           (unwind-protect
               (progn (display-line-numbers-mode)
                      (advice-eval-interactive-spec spec))
             (display-line-numbers-mode -1))
         (advice-eval-interactive-spec spec)))))
#+END_SRC
  • Defaults

    Many changes in the default behavior of Emacs, not able to group anywhere else.

    I ran into this little tidbit while reading Sacha Chu'a posts from Emacs. You can find the whole discussion [[https://emacs.stackexchange.com/questions/28736/emacs-pointcursor-movement-lag/28746][here]] but the idea is that =next-line= defun triggers =line-move-partial= which leads to excessive processing. By setting the variable below, the speed of using =next-line= gets very cut down. #+BEGIN_SRC emacs-lisp (setq auto-window-vscroll nil) #+END_SRC

    Do not clutter my =init.el= file with customized variables. #+begin_src emacs-lisp (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) (when (file-exists-p custom-file) (load custom-file)) #+end_src

    Show current key-sequence in minibuffer, like vim does. Any feedback after typing is better UX than no feedback at all. #+BEGIN_SRC emacs-lisp (setq echo-keystrokes 0.2) #+END_SRC

    Allow pasting selection outside of Emacs #+BEGIN_SRC emacs-lisp (setq x-select-enable-clipboard t) #+END_SRC

    Say you copied a link from your web browser, then switched to Emacs to paste it somewhere. Before you do that, you notice something you want to kill. Doing that will place the last kill to the clipboard, thus overriding the thing you copied earlier. We can have a kill ring solution:

    #+BEGIN_SRC emacs-lisp (setq save-interprogram-paste-before-kill t) #+END_SRC

    #+begin_src emacs-lisp (setq custom-safe-themes t)

    (defalias 'cquit 'cider-quit) (defalias 'yes-or-no-p 'y-or-n-p)

    ;; built in htop #+end_src

    Don’t use tabs to indent and fix some indentation settings #+BEGIN_SRC emacs-lisp (use-package emacs :ensure nil :config (setq-default tab-always-indent 'complete) (setq-default indent-tabs-mode nil tab-width 4 fill-column 70)) #+END_SRC

    Enable some built in modes to add critical functionality to Emacs. More explanation about them will follow in future.

    #+begin_src emacs-lisp (delete-selection-mode t) (pending-delete-mode t) (column-number-mode 1) (global-auto-revert-mode)

    ;; real emacs knights don't use shift to mark things (setq shift-select-mode nil) #+end_src

    set warning of opening large files to 100MB #+BEGIN_SRC emacs-lisp (setq-default large-file-warning-threshold 100000000) #+END_SRC

    do not add double space after periods [[http://www.reddit.com/r/emacs/comments/2l5gtz/real_sentence_in_emacs/][Real sentence in Emacs : emacs]] #+BEGIN_SRC emacs-lisp (setq-default sentence-end-double-space nil) #+END_SRC

    more defaults #+BEGIN_SRC emacs-lisp (setq-default user-mail-address "[email protected]" user-full-name "Wanderson Ferreira" disabled-command-function nil) #+END_SRC

** ediff

 #+BEGIN_SRC emacs-lisp
   (setq ediff-diff-options "-w")
   (setq ediff-split-window-function 'split-window-horizontally)
   (setq ediff-window-setup-function 'ediff-setup-windows-plain)

#+END_SRC

** word wrapping

Word wrapping #+BEGIN_SRC emacs-lisp (setq-default word-wrap t truncate-lines t truncate-partial-width-windows nil sentence-end-double-space nil delete-trailing-lines nil require-final-newline t tabify-regexp "^\t* [ \t]+") #+END_SRC

Favor hard-wrapping in text modes #+BEGIN_SRC emacs-lisp (defun bk/auto-fill () "My autofill setup for text buffers." (auto-fill-mode t) (delight 'auto-fill-mode))

(add-hook 'text-mode-hook #'bk/auto-fill)

#+END_SRC

** backup

This enables file backups to N versions of saves, as opposed to only backing up the very first save. I don't re-launch emacs that often so this is necessary to get useful backups.

#+BEGIN_SRC emacs-lisp (setq backup-directory-alist `(("." . ,(concat user-emacs-directory "backups"))) vc-make-backup-files t version-control t kept-old-versions 0 kept-new-versions 10 delete-old-versions t backup-by-copying t) #+END_SRC

** recentf

This is a built-in mode that keeps track of the files you have opened allowing you go back to them faster. It can also integrate with a completion framework to populate a =virtual buffers= list.

#+BEGIN_SRC emacs-lisp (use-package recentf :ensure nil :init (setq recentf-max-saved-items 50 recentf-max-menu-items 15 recentf-show-file-shortcuts-flag nil recentf-auto-cleanup 'never) :config (recentf-mode t)) #+END_SRC

** save place

Save place remembers your location in a file when saving files. #+begin_src emacs-lisp (require 'saveplace) (setq save-place-mode (expand-file-name "saveplace" user-emacs-directory)) (save-place-mode 1) #+end_src

** save history

Keeps a record of actions involving the minibuffer. This is of paramount important to a fast and efficient workflow involving any completion framework that leverages the built-in mechanisms.

#+begin_src emacs-lisp (use-package savehist :ensure nil :config (setq savehist-file "~/.emacs.d/savehist" history-length 30000 history-delete-duplicates nil savehist-additional-variables '(search-ring regexp-search-ring) savehist-save-minibuffer-history t) (savehist-mode 1)) #+end_src

** uniquify

Uniquify buffer names dependent on file name. Emacs's traditional method for making buffer names unique adds <2>, <3>, etc to the end of (all but one of) the buffers. This settings change the default behavior.

#+BEGIN_SRC emacs-lisp (use-package uniquify :ensure nil :config (setq uniquify-buffer-name-style 'post-forward-angle-brackets uniquify-separator " * " uniquify-after-kill-buffer-p t uniquify-strip-common-suffix t uniquify-ignore-buffers-re "^\*")) #+END_SRC ** extended command

=smex= is an improved version of =extended-command= or =M-x=

#+begin_src emacs-lisp (use-package smex :ensure t :config (smex-initialize)) #+end_src

** case switch

#+begin_src emacs-lisp (use-package fix-word :ensure t :config (global-set-key (kbd "M-u") #'fix-word-upcase) (global-set-key (kbd "M-l") #'fix-word-downcase) (global-set-key (kbd "M-c") #'fix-word-capitalize)) #+end_src

** registers

Emacs registers are compartments where you can save text, rectangles, positions, and other things for later use. Once you save text or a rectangle in a register, you can copy it into the buffer once or many times; once you save a position in a register, you can jump back to that position once or many times.

For more information: `C-h r' and then letter i to search for registers and the amazing video from [[https://youtu.be/u1YoF4ycLTY][Protesilaos]].

The prefix to all commands of registers is C-x r

| command | description | |---------------------+-------------------------------------| | M-x view-register R | see what register R contains | | C-x r s | save region to register | | C-x r i | insert text from a register | | C-x r n | record a number defaults to 0 | | C-x r + | increment a number from register | | C-x r SPC | record a position into register | | C-x r j | jump to positions or windows config | | C-x r w | save a window configuration | | C-x r f | save a frame configuration |

Important note: the data saved into the register is persistent as long as you don't override it.

The way to specify a number, is to use an universal argument e.g. C-u C-x n

Clean all the registers you saved. #+BEGIN_SRC emacs-lisp (defun bk/clear-registers () "Remove all saved registers." (interactive) (setq register-alist nil)) #+END_SRC

#+begin_src emacs-lisp (set-register ?e '(file . "~/.emacs.d/README.org")) (set-register ?t '(file . "~/org/todo.org")) (set-register ?c '(file . "~/.emacs.d/docs/cheatsheet.org"))

#+end_src

** abbreviation

#+begin_src emacs-lisp (use-package abbrev :ensure nil :delight abbrev-mode :config (setq-default abbrev-mode t))

(defun bk/add-region-local-abbrev (start end) "Go from START to END and add the selected text to a local abbrev." (interactive "r") (if (use-region-p) (let ((num-words (count-words-region start end))) (add-mode-abbrev num-words) (deactivate-mark)) (message "No selected region!")))

(global-set-key (kbd "C-x a l") 'bk/add-region-local-abbrev)

(defun bk/add-region-global-abbrev (start end) "Go from START to END and add the selected text to global abbrev." (interactive "r") (if (use-region-p) (let ((num-words (count-words-region start end))) (add-abbrev global-abbrev-table "Global" num-words) (deactivate-mark)) (message "No selected region!")))

(global-set-key (kbd "C-x a g") 'bk/add-region-global-abbrev) #+end_src

** imenu

Change some defaults of =imenu=.

#+BEGIN_SRC emacs-lisp (require 'imenu)

 (setq imenu-auto-rescan 1
       imenu-auto-rescan-maxout 600000
       imenu-max-item-length 600
       imenu-use-markers t
       imenu-max-items 200)

#+END_SRC

The objectives of this package is to provide a way to choose buffer indexes in a specific mode. What is a buffer index? Basically we have a function that will find "interesting" positions in your buffer that you might want to jump there, something like function definitions, headlines in outline mode, class definitions, etc.

#+BEGIN_SRC emacs-lisp (use-package imenu-anywhere :ensure t) #+END_SRC

** ibuffer

It provides a way of filtering and then grouping the list of buffers that you currently have open. About the configuration below:

| Default | Explanation | |-------------------+------------------------------------------------------------| | ibuffer-expert | Stop asking for confirmation after every action in Ibuffer | | ibyffer-auto-mode | Keeps the buffer list up to date |

#+begin_src emacs-lisp (use-package ibuffer :ensure nil :init (setq ibuffer-expert t) (setq ibuffer-show-empty-filter-groups nil) (setq ibuffer-saved-filter-groups '(("Main" ("Directories" (mode . dired-mode)) ("Rest" (mode . restclient-mode)) ("Docker" (or (mode . docker-compose-mode) (mode . dockerfile-mode))) ("Programming" (or (mode . clojure-mode) (mode . emacs-lisp-mode) (mode . sql-mode) (mode . python-mode))) ("Browser" (or (name . "qutebrowser:*") )) ("Slack" (name . "*Slack")) ("Org" (mode . org-mode)) ("Markdown" (or (mode . markdown-mode) (mode . gfm-mode))) ("Git" (or (mode . magit-blame-mode) (mode . magit-cherry-mode) (mode . magit-diff-mode) (mode . magit-log-mode) (mode . magit-process-mode) (mode . magit-status-mode))) ("Emacs" (or (name . "^\Help\$") (name . "^\Custom.") (name . "^\Org Agenda\$") (name . "^\info\$") (name . "^\scratch\$") (name . "^\Backtrace\$") (name . "^\Messages\$")))))) :config (add-hook 'ibuffer-mode-hook (lambda () (ibuffer-auto-mode 1) (ibuffer-switch-to-saved-filter-groups "Main")))) #+end_src

Package =ibuffer-vc= let you filter the Ibuffer by projects definitions (in my case, every folder that has a =.git= folder inside is considered a project).

#+BEGIN_SRC emacs-lisp (use-package ibuffer-vc :ensure t :after ibuffer :config (define-key ibuffer-mode-map (kbd "/ V") 'ibuffer-vc-set-filter-groups-by-vc-root)) #+END_SRC

Increasing the width of each column in ibuffer. Some buffers names are very large in EXWM.

#+BEGIN_SRC emacs-lisp (setq ibuffer-formats '((mark modified read-only " " (name 60 60 :left :elide) ; change: 60s were originally 18s " " (size 9 -1 :right) " " (mode 16 16 :left :elide) " " filename-and-process) (mark " " (name 16 -1) " " filename))) #+END_SRC

#+RESULTS:

** minibuffer

The following setting prevent the minibuffer to grow, therefore it will be always 1 line height.

#+begin_src emacs-lisp (setq resize-mini-windows nil) (setq max-mini-window-height 1) #+end_src

*** get more space for editing

Stole this from Sacha Chua's configuration, sometimes you want to
be able to do fancy things with the text that you are entering
into the minibuffer. Sometimes you just want to be able to read
it, specially when it comes to lots of text. This binds =C-M-e= in
a minibuffer.
#+begin_src emacs-lisp
  (use-package miniedit
    :ensure t
    :config
    (miniedit-install))
#+end_src

** calendar

#+BEGIN_SRC emacs-lisp (use-package calendar :ensure nil :hook (calendar-today-visible . calendar-mark-today) :config (setq calendar-latitude -23.5475 calendar-longitude -46.63611 calendar-location-name "Sao_Paulo, Brazil" calendar-mark-holidays-flag t)) #+END_SRC

** webjump

Provide a nice keyboard interface to web pages of your choosing.

Adding urban dictionary to webjump. #+BEGIN_SRC emacs-lisp (eval-after-load "webjump" '(add-to-list 'webjump-sites '("Urban Dictionary" . [simple-query "www.urbandictionary.com" "http://www.urbandictionary.com/define.php?term=" ""])))

(global-set-key (kbd "C-c j") 'webjump) #+END_SRC

** authentication source

Auth Source is a generic interface for common backends such as your operating sysetm's keychain and your local ~/.authinfo file. Auth Source solves the problem of mapping passwords and usernames to hosts.

Debugging auth issues #+BEGIN_SRC emacs-lisp (setq auth-source-debug t) #+END_SRC

We need to tell auth-source where to look for secrets. #+BEGIN_SRC emacs-lisp (setq auth-sources '((:source "~/.emacs.d/secrets/.authinfo"))) #+END_SRC

GPG

#+BEGIN_SRC emacs-lisp (use-package pinentry :ensure t) (use-package epa :ensure nil :config (setq epa-pinentry-mode 'loopback) (pinentry-start)) #+END_SRC ** enable the disabled commands

#+begin_src emacs-lisp (put 'downcase-region 'disabled nil) (put 'upcase-region 'disabled nil) (put 'narrow-to-region 'disabled nil) #+end_src

  • Hydras

    This package has a very nice name once you know what it does! This is a package that can be used to tie related commands into a family of short bindings with a common prefix - a [[https://github.com/abo-abo/hydra][Hydra]].

    #+BEGIN_SRC emacs-lisp (use-package hydra :ensure t) #+END_SRC

  • Help and Info

** info

#+begin_src emacs-lisp (use-package info :ensure t :bind ("C-h C-i" . info-lookup-symbol) :config (add-hook 'Info-mode-hook #'(lambda () (setq buffer-face-mode '(:family "Bookerly")) (buffer-face-mode) (text-scale-adjust 1)))) #+end_src

** customization to info-mode

#+BEGIN_SRC emacs-lisp :noweb yes (eval-after-load 'Info-mode '(progn <> <>)) #+END_SRC

*** define keys :properties: :header-args: :noweb-ref info-define :tangle no :end:

#+BEGIN_SRC emacs-lisp
  (define-key Info-mode-map "w" 'forward-word)
  (define-key Info-mode-map "b" 'backward-word)
  (define-key Info-mode-map "t" 'hydra-info-to/body)
  (define-key Info-mode-map "u" 'Info-history-back)
  (define-key Info-mode-map "H" 'Info-history-back)
#+END_SRC

*** hydras :properties: :header-args: :noweb-ref info-hydras :tangle no :end:

#+BEGIN_SRC emacs-lisp
  (defun ora-Info-hook ())

  (defun ora-open-info (topic bname)
    "Open info on TOPIC in BNAME."
    (if (get-buffer bname)
        (progn
          (switch-to-buffer bname)
          (unless (string-match topic Info-current-file)
            (Info-goto-node (format "(%s)" topic))))
      (info topic bname)))

  (defhydra hydra-info-to (:hint nil :color teal)
      "
  _o_rg e_l_isp _e_macs _h_yperspec"
      ("o" (ora-open-info "org" "*org info*"))
      ("l" (ora-open-info "elisp" "*elisp info*"))
      ("e" (ora-open-info "emacs" "*emacs info*"))
      ("h" (ora-open-info "gcl" "*hyperspec*")))
#+END_SRC
  • Editing Text

** defaults

See also =bidi-paragraph-direction=; setting that non-nil might speed up redisplay. #+BEGIN_SRC emacs-lisp (setq bidi-paragraph-direction 'left-to-right) #+END_SRC

*** key bindings

Default movement keys

**** move and mark by paragraph

 Use =M-{= and =M-}= to move forward or backward by paragraph. Use
 =M-h= to mark (highlight) the current paragraph.

*** very large files

Since I am using EXWM, I might open very large files, there is a
package to help Emacs handle this kind of files.

#+BEGIN_SRC emacs-lisp
  (use-package vlf
    :ensure t
    :defer t)
#+END_SRC

I found a good paper about =log files= in Emacs where they mention
=vlf= package. This [[https://writequit.org/articles/working-with-logs-in-emacs.html][paper]] is very worth reading nevertheless.

*** eldoc #+begin_src emacs-lisp (use-package eldoc :ensure nil :delight eldoc-mode :init (setq eldoc-idle-delay 0.1 eldoc-echo-area-use-multiline-p nil) (eldoc-mode 1) :config (add-hook 'prog-mode-hook 'turn-on-eldoc-mode)) #+end_src

*** subword

#+BEGIN_SRC emacs-lisp
  (use-package subword
    :ensure nil
    :delight subword-mode)
#+END_SRC

** extra features

*** change inner

#+begin_src emacs-lisp (use-package change-inner :homepage https://github.com/magnars/change-inner.el :about vim's `ci' command, building on expand-region :ensure t) #+end_src

*** expand region

Expand or reduce region selection semantically. Supports all
languages that I work with inside Emacs.

#+begin_src emacs-lisp
  (use-package expand-region
    :homepage https://github.com/magnars/expand-region.el
    :about Extension to increase selected region by semantic units
    :ensure t
    :requires hydra
    :init
    (setq er--show-expansion-message t
          expand-region-fast-keys-enabled nil)
    :bind (("C-=" . er/expand-region)
           ("C-c =" . bk/expand-region/body))
    :config

    (defhydra bk/expand-region (:color pink :hint nil)
      "
   ^Expand/Discard^                ^Mark^
  ─^──────────────^────────────────^────^─────────────────
   _e_ or _+_: expand region         _(_:      inside pairs
   _r_ or _-_: reduce region         _)_:      around pairs
   _g_:      exit hydrant          _q_ or _'_: inside quotes
   _G_:      discard region, exit  _Q_ or _\"_: around quotes
   ^ ^    ^ ^                        _p_:      paragraph"
      ("e" er/expand-region)
      ("+" er/expand-region)
      ("r" er/contract-region)
      ("-" er/contract-region)
      ("p" er/mark-paragraph)
      ("(" er/mark-inside-pairs)
      (")" er/mark-outside-pairs)
      ("q" er/mark-inside-quotes)
      ("'" er/mark-inside-quotes)
      ("Q" er/mark-outside-quotes)
      ("\"" er/mark-outside-quotes)
      ("g" ignore :exit t)
      ("G" #'(lambda () (interactive) (deactivate-mark)) :exit t)))
#+end_src

*** jump to char

#+begin_src emacs-lisp (use-package avy :homepage https://github.com/abo-abo/avy :about Jump to things in Emacs tree-style :ensure t :config (avy-setup-default) :bind (("C-." . avy-goto-char-timer))) #+end_src

[[https://github.com/cute-jumper/avy-zap][avy-zap]] is a nice package to use zap to char with avy. Basically deleting everything from point to another char. #+begin_src emacs-lisp (use-package avy-zap :ensure t :bind (("M-z" . avy-zap-to-char-dwim) ("M-Z" . avy-zap-up-to-char-dwim))) #+end_src

*** move through edit points

Emacs leaves a trail of breadcrumbs (the mark ring) through which
we can navigate to hop around to places you've been in the buffer.
A nice alternative is to move round through points at which you
made edits in a buffer.

#+BEGIN_SRC emacs-lisp
  (use-package goto-chg
    :ensure t
    :config
    (global-set-key (kbd "C-c b ,") 'goto-last-change)
    (global-set-key (kbd "C-c b .") 'goto-last-change-reverse))
#+END_SRC

Now we can use =C-c b ,= and =C-c b .= to go back and forth
through the edit points in your buffer. It takes you through your
undo history without undoing anything.

** highlights *** symbols Very often is useful to highlight some symbols. #+BEGIN_SRC emacs-lisp (use-package highlight-symbol :ensure t :delight highlight-symbol-mode :hook ((highlight-symbol-mode . highlight-symbol-nav-mode) (prog-mode . highlight-symbol-mode)) :custom (highlight-symbol-highlight-single-occurrence nil) (highlight-symbol-idle-delay 0.25) (highlight-symbol-on-navigation-p t)) #+END_SRC

*** browse kill ring

#+begin_src emacs-lisp
  (use-package browse-kill-ring
    :ensure t
    :commands browse-kill-ring)
#+end_src

** utf-8

No one knows why this is not the default already.

#+BEGIN_SRC emacs-lisp (prefer-coding-system 'utf-8) (setq locale-coding-system 'utf-8) (set-language-environment "UTF-8") (set-default-coding-systems 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) #+END_SRC

** multiple cursors

[[https://github.com/magnars/multiple-cursors.el][Multiple cursors]] is a very nice package that lets you create several cursors that all do the same thing as you type.

#+begin_src emacs-lisp (use-package multiple-cursors :ensure t :bind (("C->" . mc/mark-next-like-this) ("C-<" . mc/mark-previous-like-this) ("S-" . mc/add-cursor-on-click) ("C-c m" . bk/hydra-multiple-cursors/body)) :requires hydra :config

   (defhydra bk/hydra-multiple-cursors (:hint nil :color pink)
     "
  ^Select^                 ^Discard^                     ^Edit^               ^Navigate^
 ─^──────^─────────────────^───────^─────────────────────^────^───────────────^────────^─────────
  _M-s_: split lines       _M-SPC_:  discard current      _&_: align           _(_: cycle backward
  _s_:   select regexp     _b_:      discard blank lines  _#_: insert numbers  _)_: cycle forward
  _n_:   select next       _d_:      remove duplicated    ^ ^                  ^ ^
  _p_:   select previous   _q_ or _g_: exit hydrant       ^ ^                  ^ ^
  _C_:   select next line  _G_:      exit mc mode"
     ("M-s" mc/edit-ends-of-lines)
     ("s" mc/mark-all-in-region-regexp)
     ("n" mc/mark-next-like-this-word)
     ("p" mc/mark-previous-like-this-word)
     ("&" mc/vertical-align-with-space)
     ("(" mc/cycle-backward)
     (")" mc/cycle-forward)
     ("M-SPC" mc/remove-current-cursor)
     ("b" mc/remove-cursors-on-blank-lines)
     ("d" mc/remove-duplicated-cursors)
     ("C" mc/mark-next-lines)
     ("#" mc/insert-numbers)
     ("q" mc/remove-duplicated-cursors :exit t)
     ("g" mc/remove-duplicated-cursors :exit t)
     ("G" mc/keyboard-quit :exit t)))

 (use-package mc-extras
   :ensure t
   :after multiple-cursors)

#+end_src

To use =mc/edit-lines= you need to highlight the lines on which you wish to have cursors and use =C-c m c=. Now you can edit away and press enter when you are done to exit multiple cursors.

There is this amazing [[http://emacsrocks.com/e13.html][video]] from magnars showing off multiple cursors features.

However, occasionally the best way to get the cursors where you want them is with the mouse. With the following code, =C-S-= adds a new cursor. ** custom functions

Several helper functions to ease the day-to-day work of editing text.

*** smart move to beginning of visible line (or not)

Very nice default.

#+begin_src emacs-lisp
  ;; `C-a' first takes you to the first non-whitespace char as
  ;; `back-to-indentation' on a line, and if pressed again takes you to
  ;; the actual beginning of the line.
  (defun smarter-move-beginning-of-line (arg)
    "Move depending on ARG to beginning of visible line or not.
    From https://emacsredux.com/blog/2013/05/22/smarter-navigation-to-the-beginning-of-a-line/."
    (interactive "^p")
    (setq arg (or arg 1))
    (when (/= arg 1)
      (let ((line-move-visual nil))
        (forward-line (1- arg))))
    (let ((orig-point (point)))
      (back-to-indentation)
      (when (= orig-point (point))
        (move-beginning-of-line 1))))

  (global-set-key [remap move-beginning-of-line] 'smarter-move-beginning-of-line)
#+end_src

*** unfill paragraph

I used it sometimes when yanking text written in Emacs to paste in
other external apps such as gmail and I don't want the "break
line" to be at 70th column there.

#+BEGIN_SRC emacs-lisp
  (defun unfill-paragraph ()
    "Takes a multi-line paragraph and makes it into a single line of text."
    (interactive)
    (let ((fill-column (point-max)))
      (fill-paragraph nil)))
#+END_SRC

*** unfill region

#+BEGIN_SRC emacs-lisp
  (defun unfill-region (beg end)
    "Unfill the region, joining text paragraphs into a single logical line."
    (interactive "*r")
    (let ((fill-column (point-max)))
      (fill-region beg end)))
#+END_SRC

*** duplicate line or region

#+BEGIN_SRC emacs-lisp
  (defun duplicate-current-line-or-region (arg)
    "Duplicates the current line or region ARG times.
  If there's no region, the current line will be duplicated."
    (interactive "p")
    (save-excursion
      (if (region-active-p)
          (duplicate-region arg)
        (duplicate-current-line arg))))

  (defun duplicate-region (num &optional start end)
    "Duplicates the region bounded by START and END NUM times.
  If no START and END is provided, the current region-beginning
  region-end is used."
    (interactive "p")
    (let* ((start (or start (region-beginning)))
           (end (or end (region-end)))
           (region (buffer-substring start end)))
      (goto-char start)
      (dotimes (i num)
        (insert region))))

  (defun duplicate-current-line (num)
    "Duplicate the current line NUM times."
    (interactive "p")
    (when (eq (point-at-eol) (point-max))
      (goto-char (point-max))
      (newline)
      (forward-char -1))
    (duplicate-region num (point-at-bol) (1+ (point-at-eol))))
#+END_SRC

Let's bind the top level function to a sensible key.
#+BEGIN_SRC emacs-lisp
  (global-set-key (kbd "C-c 2") 'duplicate-current-line-or-region)
#+END_SRC

** web paste

#+BEGIN_SRC emacs-lisp (use-package webpaste :ensure t :config (setq webpaste-provider-priority '("ix.io" "dpaste.org"))) #+END_SRC

  • Completions ** minibuffer

    The optimal way of using Emacs is through searching and narrowing selection candidates. Spend less time worrying about where things are on the screen and more on how fast you can bring them into focus.

    Minibuffer is the place for extended command interaction. Whether it is about input to a prompt, performing search, executing functions or dealing with buffers.

    General config for the minibuffers #+BEGIN_SRC emacs-lisp (use-package minibuffer :ensure nil :init (setq completion-styles '(basic partial-completion) completion-category-defaults nil completion-cycle-threshold 3 completion-flex-nospace nil completion-ignore-case t read-buffer-completion-ignore-case t read-file-name-completion-ignore-case t completions-format 'vertical enable-recursive-minibuffers t read-answer-short t resize-mini-windows t) :config (defun bk/describe-symbol-at-point (&optional arg) "Get help (documentation) for the symbol at point." (interactive "P") (let ((symbol (symbol-at-point))) (when symbol (describe-symbol symbol))) (when arg (let ((help (get-buffer-window "Help"))) (when help (if (not (eq (selected-window) help)) (select-window help) (select-window (get-mru-window)))))))

     (defun bk/focus-minibuffer ()
       "Focus the active minibuffer."
       (interactive)
       (let ((mini (active-minibuffer-window)))
         (when mini
           (select-window mini))))
    
     (defun bk/completions-kill-save-symbol ()
       "Add symbol-at-point to the kill ring."
       (interactive)
       (kill-new (thing-at-point 'symbol)))
    
     (file-name-shadow-mode t)
     (minibuffer-depth-indicate-mode t)
     (minibuffer-electric-default-mode t)
    
     :bind (:map completion-list-mode-map
                 ("h" . bk/describe-symbol-at-point)
                 ("w" . bk/completions-kill-save-symbol)
                 ("n" . next-line)
                 ("p" . previous-line)
                 ("f" . next-completion)
                 ("b" . previous-completion)
                 ("M-v" . bk/focus-minibuffer)))
    

    #+END_SRC

*** ivy

Yeah, I migrated from Ido to Ivy. Let's enjoy new features, speed,
and comfort that Ivy provides. 

#+BEGIN_SRC emacs-lisp
  (use-package ivy
    :ensure t
    :init
    (setq ivy-use-virtual-buffers t
        ivy-height 13
        ivy-wrap t
        ivy-magic-slash-non-match-action nil
        ivy-initial-inputs-alist nil
        ivy-on-del-error-function #'ignore
        ivy-use-selectable-prompt t
        ivy-display-style 'fancy
        ivy-count-format "%d/%d "
        ivy-virtual-abbreviate 'full
        ivy-extra-directories '("./"))
    :config
    (ivy-mode +1))
#+END_SRC

**** Counsel

 #+BEGIN_SRC emacs-lisp
   (use-package counsel
     :ensure t
     :bind
     (("M-x". counsel-M-x)
      ("C-x C-m" . counsel-M-x)
      ("C-x C-i" . counsel-imenu)
      ("C-c g p" . counsel-git-grep)
      ("C-x C-r" . counsel-recentf)))
 #+END_SRC

*** icomplete

#+begin_src emacs-lisp
  (use-package icomplete
    :ensure nil
    :config
    (icomplete-mode +1))
#+end_src

** company mode

Company is a text completion framework for Emacs. The name stands for "complete anything". It uses pluggable back-ends and front-ends to retrieve and display completion candidates.

#+begin_src emacs-lisp (use-package company :ensure t :delight company-mode :init (setq company-show-numbers t company-idle-delay 0.25 company-require-match 'never company-dabbrev-downcase nil company-dabbrev-ignore-case t company-minimum-prefix-length 2 company-transformers '(company-sort-by-occurrence)) :config (add-hook 'after-init-hook 'global-company-mode)) #+end_src

Also, we numbered all the candidates and the following code will enable us to choose the candidate based on its number. This solution was stolen from [[https://oremacs.com/2017/12/27/company-numbers/][link]] with some customization and simplification to provide only what I saw useful.

#+begin_src emacs-lisp (defun ora-company-number () "Choose the candidate based on his number at candidate list." (interactive) (let* ((k (this-command-keys)) (re (concat "^" company-prefix k))) (if (cl-find-if (lambda (s) (string-match re s)) company-candidates) (self-insert-command) (company-complete-number (string-to-number k)))))

 (defun ora-activate-number ()
   "Activate the number-based choices in company."
   (interactive)
   (let ((map company-active-map))
     (mapc
      (lambda (x)
        (define-key map (format "%d" x) 'ora-company-number))
      (number-sequence 0 9))
     ;; (define-key map (kbd "<return>") nil)
     ))

 (eval-after-load 'company
   '(ora-activate-number))

#+end_src

*** completion help

#+BEGIN_SRC emacs-lisp
  (use-package company-quickhelp
    :ensure t
    :after company
    :init
    (setq company-quickhelp-delay nil)
    :config
    (company-quickhelp-mode t)
    :bind (:map company-active-map
                ("M-h" . company-quickhelp-manual-begin)))
#+END_SRC

*** company roam backend

#+BEGIN_SRC emacs-lisp
  (use-package company-org-roam
    :ensure t
    :after company
    :config
    (push 'company-org-roam company-backends))
#+END_SRC

** hippie expand

[[https://www.emacswiki.org/emacs/HippieExpand][Hippie Expand]] is a more feature complete completion engine than the default dabbrev engine. The main feature I use over =dabbrev= is that is supports a wide range of backends for finding completions - =dabbrev= only looks at currently open buffers.

#+BEGIN_SRC emacs-lisp (setq hippie-expand-try-functions-list '(try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-complete-lisp-symbol-partially try-complete-lisp-symbol)) #+END_SRC

Then we override =dabbrev-expand='s keybinding to use =hippie-expand= instead. #+BEGIN_SRC emacs-lisp (define-key (current-global-map) [remap dabbrev-expand] 'hippie-expand) #+END_SRC

  • Window

    A window is an area of the screen that is used to display a buffer. In Emacs Lisp, windows are represented by a special Lisp object type.

    Windows are grouped into frames. Each frame contains at least one window; the user can subdivide it into multiple, non-overlapping windows to view several buffers at once.

    Emacs uses the word "window" with a different meaning than in graphical desktop environments and window systems, such as the X Window System. When Emacs is run on X, each of its graphical X windows is an Emacs frame. When Emacs is run on a text terminal, the frame fills the entire terminal screen.

** scrolling

Improve the scroll experience on Emacs #+BEGIN_SRC emacs-lisp (defun bk/scroll-up () "Scroll only specific amount of lines. I don't like the defaults of whole screen." (interactive) (scroll-up-command 8))

 (defun bk/scroll-down ()
   "Scroll only specific amount of lines. I don't like the defaults of whole screen."
   (interactive)
   (scroll-down-command 8))

 (global-set-key (kbd "C-v") #'bk/scroll-up)
 (global-set-key (kbd "M-v") #'bk/scroll-down)

#+END_SRC

** popwin

 [[https://github.com/emacsorphanage/popwin][popwin]] is a popup window manager for Emacs which makes you free
 from the hell of annoying buffers such like =*Help*=,
 =*Completions*=, and etc.

 #+begin_src emacs-lisp
   (use-package popwin
     :ensure t
     :config
     (push '("*cider-error*" :dedicated t :position bottom :stick t :noselect nil :height 0.4)
           popwin:special-display-config)
     (push '("*cider-doc*" :dedicated t :position bottom :stick t :noselect nil :height 0.4)
           popwin:special-display-config)
     (global-set-key (kbd "C-z") popwin:keymap)
     (popwin-mode 1))
 #+end_src

 | Key    | Command                             |
 |--------+-------------------------------------|
 | b      | popwin:popup-buffer                 |
 | l      | popwin:popup-last-buffer            |
 | o      | popwin:display-buffer               |
 | C-b    | popwin:switch-to-last-buffer        |
 | C-p    | popwin:original-pop-to-last-buffer  |
 | C-o    | popwin:original-display-last-buffer |
 | SPC    | popwin:select-popup-window          |
 | s      | popwin:stick-popup-window           |
 | 0      | popwin:close-popup-window           |
 | f, C-f | popwin:find-file                    |
 | e      | popwin:messages                     |
 | C-u    | popwin:universal-display            |
 | 1      | popwin:one-window                   |

** ace window

Ease the task of changing window quickly.

#+begin_src emacs-lisp
  (use-package ace-window
    :ensure t
    :config
    (global-set-key (kbd "C-c o") 'ace-window))
#+end_src

Don't popup certain buffers
#+BEGIN_SRC emacs-lisp
  (add-to-list 'display-buffer-alist
	   (cons "\\*Async Shell Command\\*.*"
		 (cons #'display-buffer-no-window nil)))
#+END_SRC

#+caption: ace-window dispatch operations
| key | Function             |
|-----+----------------------|
| s   | aw-swap-window       |
| 2   | aw-split-window-vert |
| 3   | aw-split-window-horz |
| x   | aw-delete-window     |
| ??  | aw-dispatch-help     |

** custom functions

Toggle window from:

=Window A= =++++++++= =Window B=

to

=Window A : Window B=

#+begin_src emacs-lisp (defun toggle-window-split () (interactive) (if (= (count-windows) 2) (let* ((this-win-buffer (window-buffer)) (next-win-buffer (window-buffer (next-window))) (this-win-edges (window-edges (selected-window))) (next-win-edges (window-edges (next-window))) (this-win-2nd (not (and (<= (car this-win-edges) (car next-win-edges)) (<= (cadr this-win-edges) (cadr next-win-edges))))) (splitter (if (= (car this-win-edges) (car (window-edges (next-window)))) 'split-window-horizontally 'split-window-vertically))) (delete-other-windows) (let ((first-win (selected-window))) (funcall splitter) (if this-win-2nd (other-window 1)) (set-window-buffer (selected-window) this-win-buffer) (set-window-buffer (next-window) next-win-buffer) (select-window first-win) (if this-win-2nd (other-window 1))))))

 (global-set-key (kbd "C-x |") 'toggle-window-split)

#+end_src

When splitting windows open the previous buffer in it. #+begin_src emacs-lisp (defun bk/vsplit-last-buffer () "Split the window vertically and display the previous buffer." (interactive) (split-window-vertically) (other-window 1 nil) (switch-to-next-buffer))

 (defun bk/hsplit-last-buffer ()
   "Split the window horizontally and display the previous buffer."
   (interactive)
   (split-window-horizontally)
   (other-window 1 nil)
   (switch-to-next-buffer))

 (global-set-key (kbd "C-x 2") 'bk/vsplit-last-buffer)
 (global-set-key (kbd "C-x 3") 'bk/hsplit-last-buffer)

#+end_src

** clean it up after some time.

#+begin_src emacs-lisp (use-package midnight :ensure t :config (midnight-delay-set 'midnight-delay "4:00am") (midnight-mode +1)) #+end_src

** perspective

Perspective offers a new way to manage the display of windows and buffers.

#+begin_src emacs-lisp (use-package perspective :ensure t :init (setq persp-sort 'access) :config (persp-mode +1)) #+end_src

** same window

Same window buffers #+BEGIN_SRC emacs-lisp (add-to-list 'same-window-buffer-names "SQL") (add-to-list 'same-window-buffer-names "Help") (add-to-list 'same-window-buffer-names "Apropos") (add-to-list 'same-window-buffer-names "Process List") #+END_SRC

** winner

Winner is a built-in tool that keeps a record of buffer and window layout changes. It then allows us to move back and forth in the history of said changes. The mnemonic is related to Emacs default commands to operating on windows (C-x 4) and the undo operations with [uU] letter.

There are some buffers that winner will not restore, I list them in the winner-boring-buffers.

#+BEGIN_SRC emacs-lisp (use-package winner :ensure nil :hook (after-init . winner-mode) :init (setq winner-dont-bind-my-keys t) (setq winner-boring-buffers '("Completions" "Compile-Log" "inferior-lisp" "Fuzzy Completions" "Apropos" "Help" "cvs" "Buffer List" "Ibuffer" "esh command on file")) :bind (("C-x 4 u" . winner-undo) ("C-x 4 U" . winner-redo))) #+END_SRC

** resize

#+BEGIN_SRC emacs-lisp (use-package windresize :ensure t :commands (windresize)) #+END_SRC

  • Alerts ** alert

    Alert is a growl-workalike for Emacs which uses a common notification interface and multiple, selectable styles, whose use is fully customized by the user.

    #+BEGIN_SRC emacs-lisp (use-package alert :config (setq alert-default-style 'libnotify alert-log-messages t)) #+END_SRC

** user configuration

Several packages uses Alert for sending notifications, so you have full control over them by customizing =alert-user-configuration=.

*** slack notifications This was stolen from [[https://endlessparentheses.com/keep-your-slack-distractions-under-control-with-emacs.html][endless parentheses]] and adapt accordingly.

Shuts up!
#+begin_src emacs-lisp
  (eval-after-load 'alert
    '(add-to-list 'alert-user-configuration
                  '(((:category . "slack"))
                    log nil)))
#+end_src

Channels that I wish to only log the messages in the *Alert*
buffer.
#+BEGIN_SRC emacs-lisp
  (eval-after-load 'alert
    '(add-to-list 'alert-user-configuration
                  '(((:title . "\\(beginners\\|datomic\\|clojure\\|clojurescript\\|off-topic\\|datascript\\|core-async\\)")
                     (:category . "slack"))
                    log nil)))
#+END_SRC

However, there are a couple of important channels I would like to
be notified about anything, so add a rule for them.
#+BEGIN_SRC emacs-lisp
  (eval-after-load 'alert
    '(add-to-list 'alert-user-configuration
                  '(((:title . "\\(reitit\\|sql\\)")
                     (:category . "slack"))
                    libnotify nil)))
#+END_SRC

There are a few channel where I only need to pay attention if
explicitly mentioned.
#+BEGIN_SRC emacs-lisp
  (eval-after-load 'alert
    '(add-to-list 'alert-user-configuration
                  '(((:message . "@bartuka\\|Wanderson")
                     (:title . "\\(beginners\\)")
                     (:category . "slack"))
                    libnotify nil)))
#+END_SRC

*** telegram notifications

Let's start by telling alert *not* to notify anything.
#+BEGIN_SRC emacs-lisp
  (eval-after-load 'alert
    '(add-to-list 'alert-user-configuration
                  '(((:mode . "telega-chat-mode"))
                    log nil)))
#+END_SRC

However, if someone explicitly mention me, tell me pls.
#+BEGIN_SRC emacs-lisp
  (eval-after-load 'alert
    '(add-to-list 'alert-user-configuration
                  '(((:message . "@bartuka\\|Wanderson")
                     (:mode . "telega-chat-mode"))
                    libnotify nil)))
#+END_SRC

** custom functions

Some packages are too noisy. #+BEGIN_SRC emacs-lisp (defun suppress-messages (func &rest args) "Suppress message output from FUNC." (cl-flet ((silence (&rest args1) (ignore))) (advice-add 'message :around #'silence) (unwind-protect (apply func args) (advice-remove 'message #'silence)))) #+END_SRC

  • Dired

    Dired is very smart and usually finds the correct intent for some situations, and all of this is able through the DWIM variable. For example, if two buffers are open in the "dired" mode in different folders, if you git M to rename a file, it will move the file from folder A to B.

    #+BEGIN_SRC emacs-lisp (setq dired-dwim-target t) #+END_SRC

    Add the following to have file sizes given in "human-readable" format. #+BEGIN_SRC emacs-lisp (setq dired-listing-switches "-alh") #+END_SRC

    Omit certain files. #+BEGIN_SRC emacs-lisp (setq dired-omit-files (rx (or (seq bol (? ".") "#") (seq bol "." eol)))) #+END_SRC

** hide details

#+begin_src emacs-lisp (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode) (dired-sort-toggle-or-edit))) #+end_src

** guidelines

Group of guidelines to help me remember dired functionalities

*** mark files in dired

A very nice feature is to be able to edit Dired buffers as regular
Emacs buffers. You can make several activities bearable using it,
for more details follow this [[https://www.masteringemacs.org/article/wdired-editable-dired-buffers][guide]].

You can mark in Dired buffer based on a search using =% m=. By using
the letter =t= we can toggle the marked files. There is also the
command =k= that hide all the mark file from the current view.

You can always go back by pressing the better =g=

#+caption: commands from dired discovered in the process of narrowing
| chord | description                         |
|-------+-------------------------------------|
| % m   | mark files based on search          |
| t     | toggle mark                         |
| k     | hide marked files                   |
| g     | rebuild the original tree           |
| i     | list the content of a sub-directory |
| C-x u | dired undo                          |

*** replace text in multiple files

Start dired and mark files as described in [[Mark files in Dired]],
then use =Q= to run =query-replace= on all marked files.

** functions

Some custom functions for Dired.

#+begin_src emacs-lisp (require 'dired-x)

   (defun bk/dired-xdg-open ()
     "Open the file at point with xdg-open."
     (interactive)
     (let ((file (dired-get-filename nil t)))
       (message "Opening %s..." file)
       (call-process "xdg-open" nil 0 nil file)
       (message "Opening %s done" file)))

   (eval-after-load 'dired
     '(define-key dired-mode-map (kbd "O") 'bk/dired-xdg-open))

#+end_src

#+BEGIN_SRC emacs-lisp (defun bk/dired-directories-first () "Sort dired listings with directories first." (save-excursion (let (buffer-read-only) (forward-line 2) (sort-regexp-fields t "^.$" "[ ]." (point) (point-max))) (set-buffer-modified-p nil)))

   (advice-add 'dired-readin :after #'bk/dired-directories-first)

#+END_SRC

M-up is nicer in dired if it moves to the third line - straight to the "..", which M-down is nicer if it moves to the last file and finally C-a moving back to start of files.

#+BEGIN_SRC emacs-lisp (defun dired-back-to-top () (interactive) (beginning-of-buffer) (next-line 2) (dired-back-to-start-of-files))

 (defun dired-back-to-bottom ()
   (interactive)
   (end-of-buffer)
   (next-line -1)
   (dired-back-to-start-of-files))

 (defun dired-back-to-start-of-files ()
   (interactive)
   (backward-char (- (current-column) 2)))

#+END_SRC

Let's bind the functions defined above so it can take effect in dired. #+BEGIN_SRC emacs-lisp (eval-after-load 'dired '(progn (define-key dired-mode-map (kbd "M-p") 'dired-back-to-top) (define-key dired-mode-map (kbd "M-n") 'dired-back-to-bottom) (define-key dired-mode-map (kbd "C-a") 'dired-back-to-start-of-files))) #+END_SRC

  • Bookmark

    #+begin_src emacs-lisp (require 'bookmark) (setq bookmark-default-file (expand-file-name "bookmarks" user-emacs-directory) bookmark-save-flag 1) #+end_src

  • TRAMP

    If TRAMP makes backup files, they should be better be kept locally than remote. #+BEGIN_SRC emacs-lisp (setq tramp-backup-directory-alist backup-directory-alist) #+END_SRC

  • Version Control Sane config for =ediff= which is basically removing noisy highlights, avoiding crazy multi-frames setup, ignoring some whitespaces and windows should be side-by-side.

    #+BEGIN_SRC emacs-lisp (use-package ediff :init (setq ediff-highlight-all-diffs nil) (setq ediff-window-setup-function 'ediff-setup-windows-plain) (setq ediff-diff-options "-w") (setq ediff-split-window-function 'split-window-horizontally)) #+END_SRC

** TODO magit

A git porcelain inside Emacs. Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain, look for more info at [[https://github.com/magit/magit][here]].

#+begin_src emacs-lisp :noweb yes
  (use-package magit
    :ensure t
    :init
    <<magit-setup>>
    :config
    (add-to-list 'magit-no-confirm 'stage-all-changes))
#+end_src

*** magit setup :properties: :header-args: :noweb-ref magit-setup :tangle no :end:

#+BEGIN_SRC emacs-lisp
  (setq magit-diff-refine-hunk t
        magit-revert-buffers 'silent
        magit-commit-arguments '("--verbose")
        magit-process-popup-time 10)
#+END_SRC

*** magit hydra

And what about another hydra? Magit deserves everything.
#+BEGIN_SRC emacs-lisp
  (defhydra hydra-magit (:color blue)
    ("q" nil "quit" :column "Magit")
    ("b" magit-blame "blame" :column "Do")
    ("c" magit-clone "clone" :column "Do")
    ("i" magit-init "init" :column "Do")
    ("s" magit-status "status" :column "Do")
    ("t" git-timemachine "time-travel" :column "TimeMachine"))

  (global-set-key (kbd "C-c g g") 'hydra-magit/body)
#+END_SRC

*** forge

Very detailed [[https://magit.vc/manual/forge/][manual]] about working with Github and Gitlab from
Magit.
#+begin_src emacs-lisp
  (use-package forge
    :ensure t)
#+end_src

** git config

[[https://github.com/magit/git-modes][gitconfig]] is a major mode for editing =gitconfig= files.
#+BEGIN_SRC emacs-lisp
  (use-package gitconfig-mode
:ensure t
:config
(require 'gitconfig-mode))
#+END_SRC

** git ignore

[[https://github.com/magit/git-modes][git-modes]] has a major mode for editing =gitignore= files.
#+BEGIN_SRC emacs-lisp
  (use-package gitignore-mode
:ensure t
:config
(require 'gitignore-mode))
#+END_SRC

** time machine

#+begin_src emacs-lisp
  (use-package git-timemachine :ensure t)
#+end_src

** visual identification

Show differences between local and remote repo.

#+BEGIN_SRC emacs-lisp (use-package diff-hl :ensure t :init (setq diff-hl-side 'left) :config (add-hook 'dired-mode-hook 'diff-hl-dired-mode) (diff-hl-flydiff-mode) (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh) (global-diff-hl-mode)

   (custom-set-faces
    '(diff-hl-change ((t (:background "#3a81c3"))))
    '(diff-hl-insert ((t (:background "#7ccd7c"))))
    '(diff-hl-delete ((t (:background "#ee6363"))))))

#+END_SRC ** miscellaneous

#+BEGIN_SRC emacs-lisp (use-package browse-at-remote :ensure t) (use-package gitconfig-mode :ensure t) (use-package gitignore-templates :ensure t)

#+END_SRC ** custom functions

*** visit pull request

#+begin_src emacs-lisp
  (defun bk/visit-pull-request-url ()
    "Visit the current branch's PR on Github."
    (interactive)
    (browse-url
     (format "https://github.com/%s/pull/new/%s"
             (replace-regexp-in-string
              "\\`.+github\\.com:\\(.+\\)\\.git\\'" "\\1"
              (magit-get "remote"
                         (magit-get-remote)
                         "url"))
             (magit-get-current-branch))))
#+end_src
  • Search

** wgrep

#+BEGIN_SRC emacs-lisp (use-package wgrep :ensure t) #+END_SRC

** visual regexp

#+begin_src emacs-lisp (use-package visual-regexp :ensure t :bind (("C-c r" . vr/replace) ("C-c %" . vr/query-replace) ("<C-m> /" . vr/mark))) #+end_src

** grep fullscreen

This function help me day by day, every single version of my setup had this beauty in it.

#+BEGIN_SRC emacs-lisp (defun bk/rgrep-fullscreen (regexp &optional files dir confirm) "Open grep in full screen, saving windows and searching for REGEXP. in FILES and DIR without CONFIRM." (interactive (progn (grep-compute-defaults) (let* ((regexp (grep-read-regexp)) (files (grep-read-files regexp)) (dir (ido-read-directory-name "Base directory: " nil default-directory t)) (confirm (equal current-prefix-arg '(4)))) (list regexp files dir confirm)))) (window-configuration-to-register ?$) (rgrep regexp files dir confirm) (switch-to-buffer "grep") (delete-other-windows) (goto-char (point-min)))

 (defun rgrep-quit-window ()
   "Simply jump to the register where all your windows are."
   (interactive)
   (kill-buffer)
   (jump-to-register ?$))

 (defun rgrep-goto-file-and-close-rgrep ()
   "Go to file and close rgrep window."
   (interactive)
   (compile-goto-error)
   (kill-buffer "*grep*")
   (delete-other-windows)
   (message "Type C-x r j $ to return to pre-rgrep windows."))

#+END_SRC

** ripgrep

#+BEGIN_SRC emacs-lisp
  (use-package rg
    :ensure t
    :config
    (rg-define-search bk/search-git-root-or-dir
      :query ask
      :format regexp
      :files "everything"
      :dir (let ((vc (vc-root-dir)))
	     (if vc
		 vc
	       default-directory))
      :confirm prefix
      :flags ("--hidden -g !.git"))
    :bind
    ("M-s g" . bk/search-git-root-or-DIR))
#+END_SRC

** isearch

You can invoke it using =C-s= and typing your desired search
string. Also, if you want to use the regexp flavour you can use
=M-C-s=.

Run =C-h k C-s= yo get an /awesome/ help menu with all the extra
keys you can use with =isearch=. These are the ones I use the
most:

| Keybindings                   | Description                                |
|-------------------------------+--------------------------------------------|
| C-s                           | search forward                             |
| C-r                           | search backward                            |
| M-C-s                         | search forward using regexp                |
| M-C-r                         | search backward using regexp               |
| C-s C-w                       | search word at point                       |
| M-s                           | is a prefix while in isearch mode          |
| (while isearch activated) M-r | turn your regular isearch into regexp mode |
| M-s .                         | search for thing at point                  |
| M-s o                         | get the results in occur buffer            |
| M-s h r                       | highlight regexp                           |
| M-s h u                       | undo the highlight                         |
| C-s M-r                       | toggle regexp search                       |

** occur

Let's use an =occur= snippet from [[https://oremacs.com/2015/01/26/occur-dwim/][(or emacs]]. It will offer as the default candidate:

  • the current region, if it's active
  • the current symbol, otherwise

#+BEGIN_SRC emacs-lisp (defun occur-dwim () "Call `occur' with a sane default." (interactive) (push (if (region-active-p) (buffer-substring-no-properties (region-beginning) (region-end)) (let ((sym (thing-at-point 'symbol))) (when (stringp sym) (regexp-quote sym)))) regexp-history) (call-interactively 'occur))

 (global-set-key (kbd "M-s o") 'occur-dwim)

#+END_SRC

** google this

Artur Malabarba has a nice package called =google-this= which provides a set of functions for querying google from emacs.

#+BEGIN_SRC emacs-lisp (use-package google-this :ensure t :delight google-this-mode :config (google-this-mode 1)) #+END_SRC

This package provides a set of functions under the prefix =C-c /=. The simplest is =C-c / RET= which prompts you for a search in the minibuffer, with a default search based on the text around the point.

| Keys | Function | |----------------+---------------------------------------| | C-c / SPC | google-this-region | | C-c / a | google-this-ray | | C-c / c | google-this-translate-query-or-region | | C-c / e | google-this-error | | C-c / f | google-this-forecast | | C-c / g | google-this-lucky-search | | C-c / i | google-this-lucky-and-insert-url | | C-c / m | google-maps | | C-c / n | google-this-noconfirm | | C-c / r | google-this-cpp-reference | | C-c / s | google-this-symbol | | C-c / t | google-this | | C-c / w | google-this-word | | C-c / | google-this-search |

  • Shell

** TODO eshell mode

*** change defaults

#+begin_src emacs-lisp
  (use-package eshell
    :ensure nil
    :config
    (setq eshell-hist-ignoredups t
          eshell-ls-initial-args "-h"))
#+end_src

*** clear buffer

#+begin_src emacs-lisp
  (defun eshell-clear-buffer ()
    "Clear the terminal buffer."
    (interactive)
    (let ((inhibit-read-only t))
      (erase-buffer)
      (eshell-send-input)))

  (add-hook 'eshell-mode-hook
            (lambda ()
              (local-set-key (kbd "C-l") 'eshell-clear-buffer)))

#+end_src

*** bookmark #+begin_src emacs-lisp (use-package eshell-bookmark :ensure t :config (add-hook 'eshell-mode-hook 'eshell-bookmark-setup)) #+end_src

*** aliases

#+begin_src emacs-lisp
  (require 'em-alias)
  (add-hook 'eshell-mode-hook
            (lambda ()
              (eshell/alias "e" "find-file $1")
              (eshell/alias "ee" "find-file-other-window $1")))
#+end_src

** shell mode

#+begin_src emacs-lisp (use-package shell :bind (:map shell-mode-map ("" . comint-previous-input) ("" . comint-next-input)) :init (dirtrack-mode) (setq explicit-shell-file-name "/bin/bash") :config (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)) #+end_src

  • General Programming

    Sometimes I place some TODO and FIXME words in the middle of my code so I can come back to it latter and work on the subjects. The following snippet will highlight these words to help me identify them.

    #+BEGIN_SRC emacs-lisp (add-hook 'prog-mode-hook (defun bk--add-watchwords () (font-lock-add-keywords nil `(("\<\(FIX\(ME\))?\|TODO\)" 1 font-lock-warning-face t))))) #+END_SRC

    There is a package to help cycle quotes when in strings. #+BEGIN_SRC emacs-lisp (use-package cycle-quotes :ensure t :commands (cycle-quotes)) #+END_SRC

** toggle between src and tests

Toggle Test allows you to quickly switch between test and test subject. This is very useful tool to have when you are TDDing.

  • Allows you to quickly navigate between test and source files
  • It creates the test or source file if it not exists
  • If there are many choices, the package present them to us
  • This is language agnostic, therefore you need to configure it.
  • You can work with multiple projects at the same time.

#+begin_src emacs-lisp (use-package toggle-test :ensure t :init (setq tgt-open-in-new-window nil) :config (global-set-key (kbd "s-t") 'tgt-toggle)

   ;; the setup lives in a .dir-locals.el now.
   ;;(put 'tgt-projects 'safe-local-variable #'listp)
   (add-to-list 'tgt-projects '((:root-dir "/home/wand/platform/banker")
                                (:src-dirs "src")
                                (:test-dirs "test")
                                (:test-suffixes "_test"))))

#+end_src

This is an example of =.dir-locals.el= content file. #+begin_example ((nil . ((tgt-projects . (((:root-dir "~/foo/bar") (:src-dirs "src") (:test-dirs "test") (:test-suffixes "_test"))))))) #+end_example

** whitespaces

Control your whitespaces!

#+BEGIN_SRC emacs-lisp (require 'whitespace) (setq whitespace-style '(trailing lines space-before-tab indentation space-after-tab)) (setq whitespace-line-column 100) (whitespace-mode +1) #+END_SRC

A less intrusive ‘delete-trailing-whitespaces’ on save.

#+BEGIN_SRC emacs-lisp (use-package ws-butler :ensure t :delight ws-butler-mode :config (add-hook 'prog-mode-hook #'ws-butler-mode)) #+END_SRC

*** hungry delete

Hungry delete mode
#+begin_src emacs-lisp
  (use-package hungry-delete
    :ensure t
    :config
    (add-hook 'prog-mode-hook 'hungry-delete-mode))
#+end_src

** parenthesis *** paredit

Paredit is great, it brings structural editing to lisps,
maintaining the syntactical correctness of your code.


Follow [[http://danmidwood.com/content/2014/11/21/animated-paredit.html][this]] animated guide to paredit to learn more.

#+begin_src emacs-lisp
  (use-package paredit
    :ensure t
    :pin melpa
    :bind (:map paredit-mode-map
                ("[")
                ("M-k" . paredit-raise-sexp)
                ("M-I" . paredit-splice-sexp)
                ("C-c ( n" . paredit-add-to-next-list)
                ("C-c ( p" . paredit-add-to-previous-list))
    :bind (:map emacs-lisp-mode-map ("<return>" . paredit-newline))
    :bind (:map lisp-mode-map ("<return>" . paredit-newline))
    :config
    (add-hook 'emacs-lisp-mode-hook 'enable-paredit-mode)
    (add-hook 'lisp-mode-hook 'enable-paredit-mode)
    (add-hook 'clojure-mode-hook 'enable-paredit-mode)
    (add-hook 'cider-mode-hook 'enable-paredit-mode))

#+end_src

*** DISABLED smartparens

[[https://github.com/Fuco1/smartparens][Smartparens]] is a minor mode that deals with parens pairs and tries to be smart about it. I am a paredit user for a long time, I decided to switch to smartparens to experiment this new package which seems to have many more features than paredit. I've been here for almost 6 months now, I am yet not sold out in the smartparens idea, for some reason I like the feel of paredit. Still need to dedicate more time to use this in its fullest.

#+begin_src emacs-lisp (use-package smartparens :ensure t :delight smartparens-strict-mode :disabled t :init (setq sp-highlight-pair-overlay nil sp-base-key-bindings 'paredit sp-autoskip-closing-pair 'always sp-hybrid-kill-entire-symbol nil) :config (add-hook 'lisp-mode-hook #'smartparens-strict-mode) (add-hook 'emacs-lisp-mode-hook #'smartparens-strict-mode)

   (with-eval-after-load "smartparens"
     ;; remove some pairs
     (sp-pair "'" nil :actions :rem)
     (sp-pair "`" nil :actions :rem)

     ;; include new wrap of pairs
     (sp-pair "(" ")" :wrap "M-(")
     (sp-pair "[" "]" :wrap "M-[")

     (sp-use-paredit-bindings)

     (sp-local-tag 'markdown-mode "c" "```clojure" "```")
     (sp-local-tag 'markdown-mode "e" "```elisp" "```")
     (sp-local-tag 'markdown-mode "b" "```bash" "```")
     (sp-local-tag 'markdown-mode "p" "```python" "```")

     (define-key smartparens-mode-map (kbd "M-p") 'sp-prefix-pair-object)))

#+end_src

I stole this from [[http://xenodium.com/emacs-smartparens-auto-indent/index.html][here]], where Alvaro Ramirez is exemplifying a nice feature of Xcode about auto-indent after opening parens. For sure we should be able to do that in smartparens:

#+begin_src emacs-lisp (defun indent-between-pair (&rest _ignored) (newline) (indent-according-to-mode) (forward-line -1) (indent-according-to-mode))

 (eval-after-load 'smartparens-strict-mode
   '(progn
      (sp-local-pair 'prog-mode "{" nil :post-handlers '((indent-between-pair "RET")))
      (sp-local-pair 'prog-mode "[" nil :post-handlers '((indent-between-pair "RET")))
      (sp-local-pair 'prog-mode "(" nil :post-handlers '((indent-between-pair "RET")))))

#+end_src ** folding

*** folding based on indentation and syntax

[[https://github.com/gregsexton/origami.el][Origami]] is a text folding minor mode for Emacs.
#+BEGIN_SRC emacs-lisp
  (use-package origami
    :ensure t
    :commands (origami-toggle-node))
#+END_SRC

There is a vast set of commands to enable the manipulation of
folds.

#+caption: what can it do?
| function                        | desctiption                             |
|---------------------------------+-----------------------------------------|
| origami-toggle-node             | toggle open or closed a fold node       |
| origami-show-only-node          | close everything but the folds at point |
| origami-recursively-toggle-node | acts like org-mode header collapsing    |
| origami-undo                    | undo the last undone folding operation  |
| origami-redo                    | redo the last undone folding operation  |

Let's build a hydra for it too.
#+BEGIN_SRC emacs-lisp
  (defhydra bk/hydra-origami (:color red)
    "
    _o_pen node    _n_ext fold       toggle _f_orward
    _c_lose node   _p_revious fold   toggle _a_ll
    "
    ("o" origami-open-node)
    ("c" origami-close-node)
    ("n" origami-next-fold)
    ("p" origami-previous-fold)
    ("f" origami-forward-toggle-node)
    ("a" origami-toggle-all-nodes)
    ("t" origami-toggle-node))

  (global-set-key (kbd "C-x @") 'bk/hydra-origami/body)
#+END_SRC

*** fold regions based on selection

Syntax based folding is great and all but sometimes I need to fold
some random piece of text and [[https://github.com/mrkkrp/vimish-fold][Vimish]] fold is great for that.

#+BEGIN_SRC emacs-lisp
  (use-package vimish-fold
    :ensure t
    :commands (vimish-fold-toggle
               vimish-fold))
#+END_SRC

Let's make a hydra for vimish fold.
#+BEGIN_SRC emacs-lisp
  (defhydra bk/hydra-vimish-fold (:color red :hint nil)
    "
   _f_: fold  _u_: unfold  _r_: refold  _t_: toggle  _d_: delete    _n_: next      _q_: quit
            _U_: Unfold  _R_: Refold  _T_: Toggle  _D_: Delete    _p_: previous
    "
    ("f" vimish-fold)
    ("u" vimish-fold-unfold)
    ("r" vimish-fold-refold)
    ("t" vimish-fold-toggle)
    ("d" vimish-fold-delete)
    ("U" vimish-fold-unfold-all)
    ("R" vimish-fold-refold-all)
    ("T" vimish-fold-toggle-all)
    ("D" vimish-fold-delete-all)
    ("n" vimish-fold-next-fold)
    ("p" vimish-fold-previous-fold)
    ("q" nil :color blue))
#+END_SRC

Bind the hydra to a key.
#+BEGIN_SRC emacs-lisp
  (global-set-key (kbd "C-c @") 'bk/hydra-vimish-fold/body)
#+END_SRC

** go to definition

*** dumb jump

[[https://github.com/jacktasia/dumb-jump][Dump jump]] is a simple package that uses the =grep= or =ag= to jump
to the source of the symbol at point. This is the fallback when
language specific navigation is not possible.

#+BEGIN_SRC emacs-lisp
  (use-package dumb-jump
    :ensure t
    :bind (("C-c ." . dumb-jump-go))
    :config
    (dumb-jump-mode 1))
#+END_SRC

** documentation

[[https://zealdocs.org/][Zeal]] is a nice little app that stores documents offline for reference inspired by Dash which only works on Mac. Let's bring that to Emacs.

You need to install Zeal in your machine, =yaourt -S zeal=.

#+BEGIN_SRC emacs-lisp

 (use-package zeal-at-point
   :ensure t
   :bind (("C-c I" . zeal-at-point))
   :config
   (add-hook 'clojure-mode-hook
             (lambda ()
               (setq zeal-at-point-docset "clojure"))))

#+END_SRC ** programming languages *** clojure

Unfortunately, Emacs does not have a builtin major mode for Clojure, however we have a great community that support any programming language available in the world as a major mode of emacs rsrs.

The intent of a major mode is basically provide font-lock, indentation, navigation and refactoring for the target programming language.

**** prettify symbols

 Pretty symbols for Clojure removed from spacemacs clojure layer.
 #+begin_src emacs-lisp
   (defun clojure/fancify-symbols (mode)
     "Pretty symbols for Clojure's anonymous functions and sets,
      like (λ [a] (+ a 5)), ƒ(+ % 5), and ∈{2 4 6}."
     (font-lock-add-keywords mode
       `(("(\\(fn\\)[\[[:space:]]"
          (0 (progn (compose-region (match-beginning 1)
                                    (match-end 1) "λ"))))
         ("(\\(partial\\)[\[[:space:]]"
          (0 (progn (compose-region (match-beginning 1)
                                    (match-end 1) "Ƥ"))))
         ("(\\(comp\\)[\[[:space:]]"
          (0 (progn (compose-region (match-beginning 1)
                                    (match-end 1) "∘"))))
         ("\\(#\\)("
          (0 (progn (compose-region (match-beginning 1)
                                    (match-end 1) "ƒ"))))
         ("\\(#\\){"
          (0 (progn (compose-region (match-beginning 1)
                                    (match-end 1) "∈")))))))
 #+end_src

**** clojure mode

At the =clojure-mode= website recommends us to use the MELBA Stable bundle because the MELPA version is following a development branch of the library. As this mode is very important for me right now, I would like to stick to the more stable branch.

#+begin_src emacs-lisp (use-package clojure-mode :ensure t :delight (clojure-mode "λ") :init (setq clojure-align-forms-automatically nil) :config

  (defadvice clojure-test-run-tests (before save-first activate)
    (save-buffer))

  (defadvice nrepl-load-current-buffer (before save-first activate)
    (save-buffer))

  (add-hook 'clojure-mode-hook #'eldoc-mode)
  (add-hook 'clojure-mode-hook #'subword-mode)

  (dolist (m '(clojure-mode clojurescript-mode
                            clojurec-mode
                            clojurex-mode))
    (clojure/fancify-symbols m)))

#+end_src

The previous setting =clojure-align-forms-automatically= makes the following example a default behavior and you don't need to manually align the values. NOTE: this is an experiment, 90% of the time this happened to me, that was the default behavior I wanted. Let's see how much the other 10% will annoy me now. EDIT: These 10% are really bad, I turned it off again.

#+BEGIN_SRC clojure (def my-map {:a-key 1 :other-key 2})

;; after C-c SPC
(def my-map
  {:a-key     1
   :other-key 2})

#+END_SRC

**** clojure refactor There are several incredible examples of refactoring in the [[https://github.com/clojure-emacs/clojure-mode][clojure-mode]] website.

 1. TODO: Study refactoring support in clojure-mode.

Provides additional refactoring support, but as we see from the =clojure-mode= github page, all these extra functionalities are migrating to the clojure mode package.

#+begin_src emacs-lisp (use-package clj-refactor :ensure t :delight clj-refactor-mode :after clojure-mode :init (setq cljr-favor-prefix-notation nil cljr-auto-sort-ns nil) (setq cljr-magic-require-namespaces '(("io" . "clojure.java.io") ("set" . "clojure.set") ("walk" . "clojure.walk") ("zip" . "clojure.zip") ("time" . "clj-time.core") ("log" . "clojure.tools.logging") ("json" . "cheshire.core") ("client" . "org.httpkit.client") ("http" . "clj-http.core") ("a" . "clojure.core.async") ("jdbc" . "next.jdbc") ("s" . "clojure.spec.alpha") ("gen" . "clojure.spec.gen.alpha"))) :config (add-hook 'clojure-mode-hook (lambda () (clj-refactor-mode t) (cljr-add-keybindings-with-prefix "C-c C-m")))) #+end_src

**** eval sexp fu

 #+begin_src emacs-lisp
   (use-package eval-sexp-fu
     :ensure t
     :config
     (use-package cider-eval-sexp-fu
       :ensure t))
 #+end_src

**** additional font lock

We also improved the font-locking for built-in methods and macros of clojure.

#+begin_src emacs-lisp (use-package clojure-mode-extra-font-locking :ensure t :after clojure-mode :config (require 'clojure-mode-extra-font-locking)) #+end_src

Now comes the real deal for Clojure development, CIDER extends Emacs with support for interactive programming in Clojure. It basically connects the buffer to a nREPL and communicate back-and-forth to provide functionalities such as code completion, documentation, navigation, debugging, running tests, and many more.

 1. TODO:  Study cider mode

**** cider

#+begin_src emacs-lisp (use-package cider :ensure t :pin melpa-stable :after clojure-mode :init (setq cider-mode-line " CIDER" cider-repl-result-prefix ";; => " cider-save-file-on-load nil cider-prompt-for-symbol nil cider-repl-use-clojure-font-lock t cider-repl-display-in-current-window t cider-repl-use-pretty-printing t cider-auto-select-error-buffer t cider-auto-select-test-report-buffer nil cider-test-show-report-on-success t cider-repl-pop-to-buffer-on-connect nil cider-stacktrace-default-filters '(tooling dup)) :config (add-hook 'cider-mode-hook #'eldoc-mode) (add-hook 'cider-repl-mode-hook #'cider-company-enable-fuzzy-completion) (add-hook 'cider-mode-hook #'cider-company-enable-fuzzy-completion)) #+end_src

When cider is not connected, I usually use some commands that makes no sense in =clojure-mode= and receive a non-sense error message that I never understand what is happening or even worse it just hands without no feedback.

I will borrow the idea from Alex Baranosky and create a dummy function to provide some useful feedback message to my future self.

#+begin_src emacs-lisp (defun bk/nrepl-warn-when-not-connected () (interactive) (message "Oops! You're not connected to an nREPL server. Please run M-x cider or M-x cider-jack-in to connect")) #+end_src

And bind this to the most common keys that requires cider activated.

#+begin_src emacs-lisp (define-key clojure-mode-map (kbd "C-x C-e") 'bk/nrepl-warn-when-not-connected) (define-key clojure-mode-map (kbd "C-c C-k") 'bk/nrepl-warn-when-not-connected) (define-key clojure-mode-map (kbd "C-c C-z") 'bk/nrepl-warn-when-not-connected) #+end_src

**** kaocha runner

 Package for running Kaocha tests via CIDER
 #+begin_src emacs-lisp
   (use-package kaocha-runner
     :ensure t
     :after clojure-mode)
 #+end_src

**** custom functions

***** bk/repl for testing ideas fast

  Often I need to fire a repl and investigate some properties better, I
  have a =temp= project setup in my machine a simple =lein new temp=
  where I have some libraries already in the =project.clj= dependency
  available. The following function helps me get there quickly and
  require some frequent namespaces.

  #+begin_src emacs-lisp
    (defun bk/repl ()
      "Start an interactive repl in a temp project"
      (interactive)
      (cider-jack-in '(:project-dir "/home/wand/temp"))
      (add-hook 'cider-connected-hook
            (lambda ()
          (cider-repl-set-ns "user")
          (cider-nrepl-sync-request:eval "(require '[clj-time.core :as t])")
          (cider-nrepl-sync-request:eval "(require '[clj-http.core :as client])")
          (cider-nrepl-sync-request:eval "(require '[org.httpkit.client :as http])")
          (cider-nrepl-sync-request:eval "(require '[clojure.core.async :as a])")
          (cider-nrepl-sync-request:eval "(require '[cheshire.core :as json])"))))
  #+end_src

***** great users with a nice random clojure docstring Let's make a nice usage of =babashka= scripting for clojure and print a random doc-string message in the initial of my Emacs session. #+begin_src emacs-lisp (let ((clj-docstring (shell-command-to-string "docstring.clj"))) (when clj-docstring (setq initial-scratch-message clj-docstring))) #+end_src

The =docstring.clj= content is pretty small and it required [[https://github.com/borkdude/babashka][babashka]]
to be installed, the content:

#+BEGIN_SRC clojure
  #!/usr/bin/env bb

  (require '[clojure.repl])

  (defmacro random-doc []
    (let [sym (-> (ns-publics 'clojure.core) keys rand-nth)]
      (if (:doc (meta (resolve sym)))
        `(clojure.repl/doc ~sym)
        `(random-doc))))

  (random-doc)
#+END_SRC

I added the new file to my PATH variable. That's all.

#+begin_src emacs-lisp
  (defun bk/clj-random-docstring ()
    "Random doc-string into new buffer."
    (interactive)
    (let ((docstring (shell-command-to-string "docstring.clj"))
          (buffer-name "*Clojure Random Docs*"))
      (when (get-buffer buffer-name)
        (kill-buffer buffer-name))
      (get-buffer-create buffer-name)
      (with-current-buffer buffer-name (insert docstring))
      (switch-to-buffer-other-window buffer-name)
      (special-mode)))
#+end_src

***** clojure display error buffer

  #+begin_src emacs-lisp
    (defun bk/cider-display-error-buffer (&optional arg)
      "Displays the *cider-error* buffer in the current window.
    If called with a prefix argument, uses the other window instead."
      (interactive "P")
      (let ((buffer (get-buffer cider-error-buffer)))
        (when buffer
          (funcall (if (equal arg '(4))
                       'switch-to-buffer-other-window
                     'switch-to-buffer)
                   buffer))))
  #+end_src

Clojure rocks! *** common lisp

#+begin_src emacs-lisp
  (use-package slime
    :ensure t
    :config
    (setq inferior-lisp-program "sbcl")
    (slime-setup '(slime-fancy slime-quicklisp slime-asdf)))
#+end_src

*** elisp

Some general packages to improve the already great experience with
Elisp. There are already incredible advice's on code development
in Elisp at the official documentation: [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Tips.html#Tips][here]].

**** nameless

 Hide package namespace in your emacs-lisp code. Check the github
 page from [[https://github.com/Malabarba/Nameless][Malabarba]].
 
 #+begin_src emacs-lisp
   (use-package nameless
     :ensure t
     :config
     (add-hook 'emacs-lisp-mode-hook #'nameless-mode))
 #+end_src

**** tips and tricks

 Most of this section was stolen from John Wiegley [[https://youtu.be/QRBcm6jFJ3Q][talk]]:

 1. master =paredit=
 2. =C-M-x= will evaluate the definition while your cursor is
    anywhere inside the forms
 3. M-; will open an eval option in the minibuffer
 4. =C-x C-e= pp-eval-last-sexp
 5. Enable, debug-on-error if necessary
    1. enable edebug
       1. SPC move you forward
       2. ? will provide which keys you have available
       3. you can call (debug) inside any form
 6. 

*** python

#+BEGIN_SRC emacs-lisp
  (defun bk/elpy-setup ()
    (pyvenv-activate "~/miniconda3")
    (delete `elpy-module-django elpy-modules)
    (delete `elpy-module-highlight-indentation elpy-modules))

  (use-package elpy
    :ensure t
    :config
    (add-hook 'python-mode-hook #'elpy-enable)
    (add-hook 'python-mode-hook #'bk/elpy-setup))

  (use-package py-autopep8
    :ensure t
    :after elpy
    :init
    (setq py-autopep8-options '("--max-line-length=250"))
    :config
    (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save))
#+END_SRC

*** sql

#+begin_src emacs-lisp (use-package sqlup-mode :ensure t :config (add-hook 'sql-mode-hook 'sqlup-mode) (add-hook 'sql-interactive-hook 'sqlup-mode) (add-to-list 'sqlup-blacklist "name")) #+end_src

This Emacs library provides commands and a minor mode for easily reformating SQL using external programs such as pgformatter which can be installed in Arch Linux using =yaourt -S pgformatter-git=

#+begin_src emacs-lisp (use-package sqlformat :ensure t :init (setq sqlformat-command 'pgformatter) :config (add-hook 'sql-mode-hook 'sqlformat-on-save-mode)) #+end_src

Indentation is also important

#+begin_src emacs-lisp (use-package sql-indent :ensure t :delight sql-mode "Σ " :after (:any sql sql-interactive-mode) :config (add-hook 'sql-mode-hook 'sqlind-minor-mode)) #+end_src

*** latex

#+BEGIN_SRC emacs-lisp (use-package tex :defer t :ensure auctex :config (setq TeX-view-program-selection '((output-pdf "PDF Tools")) TeX-view-program-list '(("PDF Tools" TeX-pdf-tools-sync-view)) TeX-source-correlate-start-server t)

  (add-hook 'TeX-after-compilation-finished-functions
            #'TeX-revert-document-buffer))

#+END_SRC

#+BEGIN_SRC emacs-lisp (use-package reftex :ensure t :config (setq reftex-cite-prompt-optional-args t))

(setq TeX-auto-save t
      TeX-parse-self t
      TeX-save-query nil
      TeX-PDF-mode t)

#+END_SRC

#+BEGIN_SRC emacs-lisp (add-hook 'LaTeX-mode-hook 'visual-line-mode) (add-hook 'LaTeX-mode-hook 'flyspell-mode) (add-hook 'LaTeX-mode-hook 'Latex-math-mode) (add-hook 'LaTeX-mode-hook 'turn-on-reftex)

(with-eval-after-load 'tex
  (add-to-list 'safe-local-variable-values
               '(TeX-command-extra-options . "-shell-escape")))

#+END_SRC *** tla plus

Using formal math to specify programs? I have to check this out!!

#+begin_src emacs-lisp
  (use-package tla-mode
    :ensure nil
    :mode "\.tla$")

#+end_src

** linters

=Flycheck= is a modern on-the-fly syntax checking extension for GNU Emacs, intended as replacement for the older Flymake.

#+begin_src emacs-lisp (use-package flycheck :ensure t :config (setq flycheck-check-syntax-automatically '(mode-enabled save)))

 (use-package flycheck-clj-kondo :ensure t)

#+end_src

A very important command you should remember is =C-c ! v= or (=M-x flycheck-verify-setup=) that can help you verify for your current mode if everything is fine with your linter and it's backend.

The following package implements a minor-mode for displaying errors from Flycheck right below their reporting location, using overlays.

#+begin_src emacs-lisp (use-package flycheck-inline :ensure t :after flycheck :config (add-hook 'flycheck-mode-hook #'flycheck-inline-mode)) #+end_src

Integrate [[Unified Modeling Language]] with flycheck to automatically check the syntax of your plantuml files on the fly.

#+begin_src emacs-lisp (use-package flycheck-plantuml :ensure t :after flycheck :config (flycheck-plantuml-setup)) #+end_src

** unified modeling language

The UML is a general-purpose, developmental, modeling language in the field of software engineering that is intended to provide a standard way to visualize the design of a system.

1. any activities (jobs)
2. individual components of the system
3. how the system will run
4. how entities interact with others
5. external user interfaces

The UML diagrams represent two different views of a system model

- *Static* (or structural) view: emphasizes the static structure of
  the system using objects, attributes, operations and
  relationships. It includes class diagrams and composite structure
  diagrams.
- *Dynamic* (or behavioral) view: emphasizes the dynamic behavior
  of the system by showing collaborations among objects and changes
  to the internal states of objects. This view includes sequence
  diagrams, activity diagrams and state machine diagrams.

Let's see a very interesting cheatsheet now:

[[./images/uml-1.png]]

[[./images/uml-2.png]]

[[./images/uml-3.png]]

The internal setup in order to use it will happen though =PlantUML= which has an specific syntax but is very easy to pick it up, follow examples at the official documentation at [[https://plantuml.com/][webpage]].

#+begin_src emacs-lisp (use-package plantuml-mode :ensure t :mode ("\.plantuml\'" "\.puml\'") :init (setq org-plantuml-jar-path "/home/wand/plantuml.jar") :config (require 'ob-plantuml)) #+end_src

** how do I do it?

Do you find yourself constantly Googling for how to do basic programming tasks? Suppose you want to know how to format a date in bash. Why open your browser and read through blogs when you can just =M-x howdoi RET format date bash RET=.

#+BEGIN_SRC emacs-lisp (defun bk/howdoi () "Call `howdoi' and ask for help" (interactive) (let* ((query (read-from-minibuffer "Query: ")) (docstring (shell-command-to-string (concat "howdoi " query))) (buffer-name "How do I do it?")) (when (get-buffer buffer-name) (kill-buffer buffer-name)) (get-buffer-create buffer-name) (with-current-buffer buffer-name (insert docstring)) (switch-to-buffer-other-window buffer-name) (special-mode))) #+END_SRC

Do not forget to install the command line utility. =yaourt -S howdoi=

** custom functions

*** align blocks

Emacs has the built-in command =align-regexp= to align via regular
expression. However, it is not very straightforward, especially
since I don't know much Emacs regular expressions. Hence, let's
use some wrapper functions to ease the life in the moment of
danger =)

#+BEGIN_SRC emacs-lisp
  (defun bk/align-whitespace (start end)
    "Align columns by whitespace"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\)\\s-" 1 0 t))

  (defun bk/align-ampersand (start end)
    "Align columns by ampersand"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\)&" 1 1 t))

  (defun bk/align-quote-space (start end)
    "Align columns by quote and space"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\).*\\s-\"" 1 0 t))

  (defun bk/align-equals (start end)
    "Align columns by equals sign"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\)=" 1 0 t))

  (defun bk/align-comma (start end)
    "Align columns by comma"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\)," 1 1 t))

  (defun bk/align-dot (start end)
    "Align columns by dot"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\)\\\." 1 1 t))

  (defun bk/align-colon (start end)
    "Align columns by equals sign"
    (interactive "r")
    (align-regexp start end
                  "\\(\\s-*\\):" 1 0 t))
#+END_SRC
  • Additional Major Modes

    I started to craft a emacs theme, and to do that I had to enable =rainbow-mode= to help me identifying RGB colors. Very useful in this circumstances. #+BEGIN_SRC emacs-lisp (use-package rainbow-mode :ensure t :commands (rainbow-mode)) #+END_SRC

** rest client

#+begin_src emacs-lisp (use-package restclient :ensure t :config (add-to-list 'auto-mode-alist '("\.restclient\'" . restclient-mode)))

(use-package company-restclient :ensure t :after company :config (add-to-list 'company-backends 'company-restclient))

#+end_src *** create a tmp restclient buffer

#+BEGIN_SRC emacs-lisp
  (defun bk/restclient ()
    "Open the restclient buffer."
    (interactive)
    (with-current-buffer (get-buffer-create "*restclient*")
      (restclient-mode)
      (pop-to-buffer (current-buffer))))
#+END_SRC

** edn

Emacs lisp library for reading and writing the data format edn. #+begin_src emacs-lisp (use-package edn :ensure t) #+end_src

** markdown

 #+BEGIN_SRC emacs-lisp
   (use-package markdown-mode
     :ensure t
     :config
     (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
     (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
     (add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode)))
 #+END_SRC

 #+BEGIN_SRC emacs-lisp
   (eval-after-load 'markdown-mode
 '(progn
    ;; `pandoc' is better than obsolete `markdown'
    (when (executable-find "pandoc")
      (setq markdown-command "pandoc -f markdown"))))
 #+END_SRC

 Edit markdown code block like Org.
 #+BEGIN_SRC emacs-lisp
   (use-package edit-indirect
     :ensure t
     :defer t)
 #+END_SRC

** json

#+begin_src emacs-lisp (use-package json-mode :ensure t :config (add-to-list 'auto-mode-alist '("\.json\'" . json-mode))) #+end_src

** xml

#+begin_src emacs-lisp (require 'nxml-mode)

 (push '("<\\?xml" . nxml-mode) magic-mode-alist)

 ;; pom files should be treated as xml files
 (add-to-list 'auto-mode-alist '("\\.pom$" . nxml-mode))

 (setq nxml-child-indent 4
       nxml-attribute-indent 4
       nxml-auto-insert-xml-declaration-flag nil
       nxml-bind-meta-tab-to-complete-flag t
       nxml-slash-auto-complete-flag t)

#+end_src

** yaml

Unfortunately, I have to deal with YAML files on my daily basis. #+BEGIN_SRC emacs-lisp (use-package yaml-mode :ensure t :config (add-hook 'yaml-mode-hook 'whitespace-mode) (add-hook 'yaml-mode-hook 'subword-mode)) #+END_SRC

** makefile

#+BEGIN_SRC emacs-lisp (use-package make-mode :ensure t :mode (("Makefile" . makefile-gmake-mode))) #+END_SRC

  • PDF

PDF Tools is, among other things, a replacement of DocView for PDF files. The key difference is that pages are not pre-rendered by e.g. ghostscript and stored in the file-system, but rather created on-demand and stored in memory.

#+begin_src emacs-lisp (use-package pdf-tools :ensure t :defer 1 :magic ("%PDF" . pdf-view-mode) :init (pdf-tools-install :no-query))

(use-package pdf-view :ensure nil :after pdf-tools :bind (:map pdf-view-mode-map ("C-s" . isearch-forward) ("d" . pdf-annot-delete) ("h" . pdf-annot-add-highlight-markup-annotation) ("t" . pdf-annot-add-text-annotation)) :custom (pdf-view-display-size 'fit-page) (pdf-view-resize-factor 1.1) (pdf-view-use-unicode-ligther nil)) #+end_src

  • Org mode

    Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.

** literate programming

[[https://en.wikipedia.org/wiki/Literate_programming][Literate Programming]] is the art of preparing programs for human readers.

"Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a /computer/ what to do, let us concentrate rather on explaining to /humans/ what we want the computer to do." - Donald E. Knuth, 1984.

*** what is noweb?

[[https://www.cs.tufts.edu/~nr/noweb/][noweb]] is designed to meet the needs of literate programmers while
remaining as simple as possible.

The gist of using =noweb= is that in your source blocks you have
labels like =<<imports>>=, that refer to other named code blocks
that get substituted in place of the label.

** table of contents

#+begin_src emacs-lisp (use-package toc-org :ensure t :init (setq toc-org-max-depth 3) :config (add-hook 'org-mode-hook 'toc-org-mode)) #+end_src

I need to control the window that pops up when I open the Org Src buffer to edit code. #+BEGIN_SRC emacs-lisp (setq org-src-window-setup 'current-window) #+END_SRC

** configuration *** defaults

When using =RET= over a link, please go to it.

#+begin_src emacs-lisp (setq org-return-follows-link t) #+end_src

Please, disable =flycheck= from org-src buffers. We always have errors in there related to some emacs-lisp checkers. Here is how to disable it.

#+begin_src emacs-lisp (defun disable-flycheck-in-org-src-block () (setq-local flycheck-disabled-checkers '(emacs-lisp-checkdoc)))

 (add-hook 'org-src-mode-hook 'disable-flycheck-in-org-src-block)

#+end_src

**** manipulating sections

Let's enable [[http://notesyoujustmightwanttosave.blogspot.com/2011/12/org-speed-keys.html][Org Speed Keys]]. The main purpose of Speed Keys is to
speed up the execution of the most common tasks you do in Org
Mode - like outline navigation, visibility cycling, and structure
editing. They also support basic clock commands and meta data
editing, however, in order to use them, the cursor needs to be at
the beginning of a headline.

#+BEGIN_SRC emacs-lisp
  (setq org-use-speed-commands t)
#+END_SRC

List of most randy commands:

| Key   | Description                                                      |
|-------+------------------------------------------------------------------|
| #     | toggle COMMENT-in for an org-header                              |
| s     | toggles narrowing to a subtree i.e. hide the rest of the doc     |
| I/O   | clock In/Out to the task defined by the current heading          |
| u     | jumping upwards to the parent heading                            |
| c     | for cycling structure below current heading, or C cycling global |
| i     | insert a new same-level heading below current heading            |
| w     | refile current heading                                           |
| t     | cycle through the available TODO states                          |
| ^     | sort children of the current subtree                             |
| n/p   | for next/previous visible heading                                |
| f/b   | for next/previous same-level heading                             |
| D/U   | move a heading Down/Up                                           |
| L/R   | recursively promote (move leftwards) or demote (more rightwards) |
| 1,2,3 | to mark a heading with priority                                  |

**** seamless Navigation Between Source Blocks

Toggle editing org-mode source blocks.
#+BEGIN_SRC emacs-lisp
  (global-set-key (kbd "s-e") #'org-edit-special)
  (define-key org-src-mode-map (kbd "s-e") #'org-edit-src-exit)
#+END_SRC

*** capture

#+begin_src emacs-lisp
  (require 'org-capture)
  (setq org-directory "/home/wand/org"
        org-confirm-babel-evaluate nil
        org-agenda-files (list "/home/wand/org/todo.org"
                               "/home/wand/gcal-captalys.org"))

  (setq org-todo-keywords
        '((sequence "TODO(t)" "|" "DOING(d)" "|" "DONE(D)" "|" "CANCELLED(C)")
          (sequence "STUDY(s)" "|" "STUDIED(S)")
          (sequence "ACT(a)" "|" "ACTED(A)")))

  (setq org-capture-templates
        '(("c" "Capture some concise actionable item and exist" entry
           (file+headline "todo.org" "Task list without a defined date")
           "* TODO [#B] %^{Title}\n :PROPERTIES:\n :CAPTURED: %U\n :END:\n\n %i %l" :immediate-finish t)
          ("t" "Task of importance with a tag, deadline, and further editable space" entry
           (file+headline "todo.org" "Task list with a date")
           "* %^{Scope of task||TODO [#A]|STUDY [#A]|Act on} %^{Title} %^g\n DEADLINE: %^t\n :PROPERTIES:\n :CONTEXT: %a\n:CAPTURED: %U\n :END:\n\n %i %?")))

  (setq org-agenda-window-setup 'only-window)

   ;;; after calling the `org-todo', the org mode tries to store some
   ;;; sort of a "note" using `org-store-log-note' function. I want that
   ;;; every modification done in my todo file save the file right after.
  (advice-add 'org-deadline :after (lambda (&rest _rest) (org-save-all-org-buffers)))
  (advice-add 'org-schedule :after (lambda (&rest _rest) (org-save-all-org-buffers)))
  (advice-add 'org-todo :after (lambda (&rest _rest) (org-save-all-org-buffers)))
  (advice-add 'org-store-log-note :after (lambda (&rest _rest) (org-save-all-org-buffers)))

#+end_src

*** babel

#+BEGIN_SRC emacs-lisp
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (ledger . t)
     (sql . t)
     (clojure . t)))
#+END_SRC

*** structure templates

The "Easy Templates" as often is mentioned, is the standard way in
Emacs to handle inline code blocks when writing in literate
programming style.

You can find all the different available templates by `C-h v
org-structure-template-alist`.

This works in Emacs 26, but I am deprecating this now because of
my new usage of Emacs 27 and the new way of defining structure
templates.
#+BEGIN_SRC emacs-lisp
  ;; (add-to-list 'org-structure-template-alist
  ;;      (list "elisp" (concat "#+BEGIN_SRC emacs-lisp\n"
  ;;                "?\n"
  ;;                "#+END_SRC")))
#+END_SRC

#+BEGIN_SRC emacs-lisp
  (add-to-list 'org-structure-template-alist
               '("elisp" . "src emacs-lisp"))
#+END_SRC

*** reveal.js

There an exhaustive documentation about Reveal.js in the github
[[https://gitlab.com/oer/org-re-reveal][repository]], please follow the link if more is necessary.

#+begin_src emacs-lisp
  (use-package org-re-reveal
    :ensure t
    :after org
    :custom
    (org-reveal-mathjax t)
    (org-reveal-root "http://cdn.jsdelivr.net/reveal.js/3.0.0/"))
#+end_src

** habits

Emacs org-habits function enables you:

  • to specify any number of habits, each with different, sometimes less regular frequencies

  • to track when you perform a habit and when you should next perform it and finally

  • to visualize if you are performing according to the specifications you have set

    #+begin_src emacs-lisp (add-to-list 'org-modules 'org-habit t)

    (setq org-treat-insert-todo-heading-as-state-change t org-log-into-drawer t)

    #+end_src

*** [documentation] repeated tasks

Highlights from the official documentation on [[https://orgmode.org/manual/Repeated-tasks.html][repeated tasks]]. Some
tasks need to be repeated again and again, Org helps to organize
such tasks using a so-called repeater in a =DEADLINE=, =SCHEDULE=
or plain timestamps.

#+begin_example
  ** TODO Pay the rent
     DEADLINE: <2020-04-21 Tue +1m>
#+end_example

The =+1m= is repeater; the intended interpretation is that the
task has a deadline on 2020/04/21 and repeats itself every (one)
month.

#+caption: table of different repeater
| repeater | periodicity |
|----------+-------------|
| y        | yearly      |
| w        | weekly      |
| d        | daily       |
| h        | hourly      |

** journal

Let's use [[https://750words.com/][750words]] to write a personal journal. As part of the process, I want my journal entries to be fully encrypted because privacy is important.

  • =org-journal-encrypt-journal=, if set to =t= has the effect of transparently encrypting/decrypting the journal files as they are written to disk.
  • =org-journal-enable-encryption=, if set to =t=, enables integration with =org-crypt=, so it automatically adds a =:crypt= tag to new journal entries. This has the effect of automatically encrypting those entries upon save, replacing them with a blob of gpg-encrypted text which has to be further decrypted with =org-decrypt-entry= in order to read or edit them again... too much for now.

#+BEGIN_SRC emacs-lisp (use-package org-journal :ensure t :init (setq org-journal-dir "/home/wand/.journal" org-journal-file-format "%Y/%m/%Y%m%d" org-journal-date-format "%A, %Y-%m-%d" org-journal-encrypt-journal t org-journal-enable-encryption nil org-journal-enable-agenda-integration t) :bind ("C-c j" . org-journal-new-entry)) #+END_SRC

=wc-mode= allows counting characters and words, both on demand and continuously. It also allows setting up a word/character goal. #+BEGIN_SRC emacs-lisp (use-package wc-mode :ensure t :hook (org-journal-mode . wc-mode) :config (setq wc-word-goal 750)) #+END_SRC

*** what is a personal journal?

- This is between you and you
- It's all about writing, and getting into your brain
- It's not blogging or status updating
- Way to think out loud without having to worry about half-formed
  ideas, random tangents, private stuff, and all the other things
  our heads that we often filter out before ever voicing them or
  writing about them
- It's a daily brain dump

*** writeroom

A package to help us concentrate in the writing by removing
everything from the screen and centralizing the text being
written.

#+BEGIN_SRC emacs-lisp
  (use-package writeroom-mode
    :ensure t
    :init
    (setq writeroom-width 150))
#+END_SRC

** presentation

[[https://github.com/eschulte/epresent][epresent]] is a simple presentation mode for Emacs Org-mode. Epresent leverages exiting Org-mode features like inline image display, inline latex fragments, and in-buffer code fontification to generate very nice looking presentations directly from within Emacs.

#+BEGIN_SRC emacs-lisp (use-package epresent :ensure t) #+END_SRC

  • call =epresent-run= on an org-buffer
  • press =t= / =1= to view the top level of the presentation
  • navigate the presentation with =n/f=, =p/b=
  • scroll with =k= and =l=
  • use =c= and =C= to navigate between code blocks, =e= to edit them, =x= to make it run, and =s= / =S= to toggle their visibility
  • quit with =q=

** agenda

*** defaults #+begin_src emacs-lisp (with-eval-after-load "org" (require 'org-agenda) (setq org-agenda-fontify-priorities t org-agenda-include-diary t org-agenda-inhibit-startup t org-agenda-log-mode-items '(closed clock state) org-agenda-ndays 1 org-agenda-persistent-filter t org-agenda-show-all-dates t)) #+end_src

*** DISABLED - gmail agenda

I am following this post from [[http://pragmaticemacs.com/emacs/how-i-view-my-google-calendar-agenda-in-emacs/][pragmatic emacs]] to setup =gcalcli=
to handle your google agenda. Let's see if I can make this
through. ==FAILED== I will try something else =)

Let's see if is possible to sync Google Calendar with Org mode.
The Org-gcal library enable you to fetch, post, edit and sync
events from your calendar.

There is a bit of setup outside Emacs to make it work, you can
follow the step-by-step guide on [[https://github.com/myuhe/org-gcal.el][Org Gcal Readme]] page.

#+BEGIN_SRC emacs-lisp
  (use-package org-gcal
    :ensure t
    :disabled true
    :config
    (setq org-gcal-client-id (auth-source-pick-first-password
                              :host "gcal.com"
                              :user "client-id")
          org-gcal-client-secret (auth-source-pick-first-password
                                  :host "gcal.com"
                                  :user "client-secret")
          org-gcal-file-alist '(("[email protected]" . "~/gcal-captalys.org"))
          org-gcal-notify-p nil))
#+END_SRC


There are a couple of commands to remember:
#+caption: cheatsheet for Org Calendar
| command                  | description                                                                       |
|--------------------------+-----------------------------------------------------------------------------------|
| org-gcal-sync            | sync between org and gcal, before syncing, execute `org-gcal-fetch'               |
| org-gcal-fetch           | fetch google calendar events and populate org-gcal-file-alist                     |
| org-gcal-post-at-point   | post/edit org block at point to google calendar                                   |
| org-gcal-delete-at-point | delete gcal event at point                                                        |
| org-gcal-refresh-token   | refresh the oauth token, it expires in 3600s you should refresh in regular basis. |


I got these two hooks from Zemansky to sync things
semi-automatically.

#+BEGIN_SRC emacs-lisp
  ;; (advice-add 'org-gcal-sync :around #'suppress-messages)
  ;; (add-hook 'org-agenda-mode-hook (lambda () (org-gcal-sync)))
  ;;  not very good integration! many callback errors are getting back.

#+END_SRC

The other way around, integrating Org bullets to Gmail seems to
work but with very basic functionalities. I wish I could create a
full appointment entry with invitations, location, and correct
duration. For now, I will keep using Google's UI to do that.

** beamer

#+BEGIN_SRC emacs-lisp (require 'ox-beamer) (require 'ox-latex)

 (setq org-export-allow-bind-keywords t)
 (setq org-latex-listings 'minted)

 (add-to-list 'org-latex-packages-alist '("" "minted"))

 (org-babel-do-load-languages
  'org-babel-load-languages
  '((python . t) (C . t) (ruby . t) (js . t)))

 (setq org-latex-pdf-process
       '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
         "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
         "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))

#+END_SRC ** tips and tricks *** compute difference between two dates.

From M-x tpis (@iLemming) in Org-mode
- use =C-c != to enter timestamps
- use =S-<arrows>= to move between days
- use =M-<arrows>= to move between months
- Place =-= between them (to make it a range)
- =C-c C-y= to =org-evaluate-time-range=
- with a prefix argument inserts it into the buffer.

*** insert template for documenting a meeting

#+begin_src emacs-lisp
  (defun bk/meeting-minute ()
    "Insert Org template to create a meeting minute."
    (interactive)
    (insert-file "~/.emacs.d/docs/org-template-meeting.org"))
#+end_src

*** export to asciidoc

#+begin_src emacs-lisp
  (use-package ox-asciidoc
    :ensure t
    :config
    (require 'ox-asciidoc))
#+end_src
  • Second brain

** Org Roam

#+BEGIN_SRC emacs-lisp (use-package org-roam :ensure t :hook (after-init . org-roam-mode) :init (setq org-roam-directory "/home/wand/all/permanent") (setq org-roam-dailies-capture-templates '(("d" "daily" plain (function org-roam-capture--get-point) "" :file-name "dailies/%<%Y-%m-%d>" :unnarrowed t :head "#+TITLE: %<%Y-%m-%d>\n#+STARTUP: showall\n#+roam_tags: fleeting")))

   (setq org-roam-capture-templates
         '(("l" "literature" plain #'org-roam-capture--get-point "%?"
            :file-name "literature/%<%Y%m%d%H%M%S>-${slug}"
            :head "#+title: ${title}\n#+created_at: %U\n#+STARTUP: showall\n#+roam_tags: literature"
            :unnarrowed t)

           ("p" "permanent" plain #'org-roam-capture--get-point "%?"
            :file-name "%<%Y%m%d%H%M%S>-${slug}"
            :head "#+title: ${title}\n#+created_at: %U\n#+STARTUP: showall\n#+roam_tags: permanent"
            :unnarrowed t)))
   :bind (("C-c n c" . org-roam-capture)
          ("C-c n t" . org-roam-dailies-today)
          :map org-roam-mode-map
          ("C-c n f" . org-roam-find-file)
          :map org-mode-map
          ("C-c n i" . org-roam-insert)
          ("C-c n I" . org-roam-insert-immediate)))

#+END_SRC

** Protocol

#+BEGIN_SRC emacs-lisp (use-package org-roam-server :ensure nil :config (require 'org-roam-protocol)) #+END_SRC

** Enable local files

#+BEGIN_SRC emacs-lisp (setq org-roam-server-enable-access-to-local-files t org-roam-server-webserver-prefix "/home/wand" org-roam-server-webserver-address "127.0.0.1:8887/" org-roam-server-webserver-supported-extensions '("pdf" "mp4" "ogv" "mkv")) #+END_SRC

  • Tip of the day

    I really like this idea from Prelude, about giving the user some useful tip about Emacs. I will try to reproduce some here.

    First, the list of useful tips. #+begin_src emacs-lisp (defvar bk-tips '("Press <C-c ;> to activate avy char-based navigation." )) #+end_src

    Then the function to display it. #+begin_src emacs-lisp (defun bk-tip-of-the-day () "Display a random entry from `bk-tips'." (interactive) (when (and bk-tips (not (window-minibuffer-p))) (random t) (message (concat "Bartuka tip: " (nth (random (length bk-tips)) bk-tips))))) #+end_src

    Run from time to time. #+begin_src emacs-lisp (run-at-time 10 (* 10 60) #'bk-tip-of-the-day) #+end_src

  • Projects

    Let's define a nice hydra that I've been using for a while now. #+begin_src emacs-lisp (use-package projectile :ensure t :delight '(:eval (concat " " (projectile-project-name))) :requires hydra :init (setq projectile-completion-system 'ivy projectile-indexing-method 'hybrid projectile-enable-caching t projectile-sort-order 'access-time) :config (defhydra bk/hydra-projects (:color blue) ("q" nil "quit" :column "Projectile")

      ("b" projectile-switch-to-buffer "list" :column "Buffers")
      ("K" projectile-kill-buffers "kill all" :column "Buffers")
      ("S" projectile-save-project-buffers "save all" :column "Buffers")
    
      ("d" projectile-find-dir "directory" :column "Find")
      ("D" projectile-dired "root" :column "Find")
      ("f" projectile-find-file "file" :column "Find")
      ("p" projectile-switch-project "project" :column "Find")
    
      ("r" projectile-replace "replace" :column "Search")
      ("R" projectile-replace-regexp "regexp replace" :column "Search")
      ("g" bk/rgrep-fullscreen "grep" :column "Search"))
    
    (projectile-mode t)
    :bind
    ("C-c p" . bk/hydra-projects/body))
    

    #+end_src

  • Spelling

** correct your spelling errors on the fly

#+begin_src emacs-lisp (defun bk/spell-buffer-pt-BR () "Spell check in portuguese." (interactive) (ispell-change-dictionary "pt_BR") (flyspell-buffer))

 (defun bk/spell-buffer-en ()
   "Spell check in english."
   (interactive)
   (ispell-change-dictionary "en_US")
   (flyspell-buffer))

 (use-package flyspell
   :ensure nil
   :delight flyspell-mode
   :config
   (add-hook 'prog-mode-hook 'flyspell-prog-mode)
   (add-hook 'text-mode-hook 'flyspell-mode)
   (define-key flyspell-mode-map (kbd "C-.") nil))

#+end_src

There is a nice package to help correcting previous words that improve upon the =flyspell-auto-correct-previous-word= function

#+BEGIN_SRC emacs-lisp (use-package flyspell-correct :ensure t :commands (flyspell-correct-word-generic flyspell-correct-previous-word-generic) :config (require 'flyspell-correct-ido) (setq flyspell-correct-interface #'flyspell-correct-ido) :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper))) #+END_SRC

By default the flyspell-correct-wrapper is the most convenient way to use the package because it will jump to the first misspelled word before the point and prompts for correction and gets you back. Calling it with C-u gives ability to correct multiple misspelled words in one run. With C-u C-u changes direction and C-u C-u C-u changes direction and enables multiple corrections. ** using a grammar & style checker

Let's install [[https://github.com/mhayashi1120/Emacs-langtool][a grammar and style checker]]. We get the offline tool from the [[https://languagetool.org/download/LanguageTool-4.9.zip][link]], then relocate it as follows.

#+BEGIN_SRC emacs-lisp (use-package langtool :ensure t :config (setq langtool-language-tool-jar "/home/wand/.emacs.d/var/LanguageTool-4.5/languagetool-commandline.jar")) #+END_SRC

Now we can run =langtool-check= on a grammatically incorrect text which colors errors in red, when we click on them we get the reason why; then we may invoke =langtool-correct-buffer= to quickly use the suggestions to fix each correction, and finally invoke =language-check-done= to stop any remaining red coloring.

Let's verify if our installation is working by using a piece of incorrect text from Language Tool website:

#+BEGIN_EXAMPLE LanguageTool offers spell and grammar checking. Just paste your text here and click the 'Check Text' button. Click the colored phrases for details on potential errors. or use this text too see an few of of the problems that LanguageTool can detecd. What do you thinks of grammar checkers? Please not that they are not perfect. Style issues get a blue marker: It's 5 P.M. in the afternoon. The weather was nice on Thursday, 27 June 2017 --uh oh, that's the wrong date ;-) #+END_EXAMPLE

#+BEGIN_SRC emacs-lisp ;; ;; Quickly check, correct, then clean up /region/ with M-^

 ;; (add-hook 'langtool-error-exists-hook
 ;;   (lambda ()
 ;;     (langtool-correct-buffer)
 ;;     (langtool-check-done)
 ;;   ))

 ;; (global-set-key "\M-^" 'langtool-check)

#+END_SRC ** synonyms

Synosaurus is a thesaurus frontend for Emacs with pluggable backends. It has basically three commands:

| Key | Commands | Description | |-----------+-------------------------------+----------------------| | C-c C-s l | synosaurus-lookup | query you for a word | | C-c C-s r | synosaurus-choose-and-replace | | | C-c C-s i | synosaurus-choose-and-insert | |

#+BEGIN_SRC emacs-lisp

 (use-package synosaurus
   :ensure t
   :init (synosaurus-mode)
   :config
   (setq synosaurus-choose-method 'popup)
   :bind
   ("M-#" . synosaurus-choose-and-replace))

#+END_SRC

The thesaurus is powered by the Wordnet =wn= tool, which can be invoked without an internet connection.

#+BEGIN_SRC shell yaourt -S wordnet-common #+END_SRC

Let's use Wordnet as a dictionary via the [[https://github.com/gromnitsky/wordnut][wordnut]] package. #+BEGIN_SRC emacs-lisp (use-package wordnut :ensure t :bind ("M-!" . wordnut-lookup-current-word)) #+END_SRC

Some keys you can use inside the =WordNut= buffer.

| Key | Description | |--------------+-------------------------------------------------------| | Enter | Lookup a word under the cursor | | o | A tooltip w/ a sense for the current lexical category | | / | new search | | l, r | move backward/forward in history | | h | view history | | q | hide buffer | | M-up, M-down | move between sections | | Space | Page Down | | b, Backspace | Page Up |

** translate

To assist in language learning, it may be nice to have Emacs interface to Google translate e.g. invoke =google-translate-at-point=.

#+BEGIN_SRC emacs-lisp (use-package google-translate :ensure t :config (require 'google-translate-smooth-ui) (global-set-key (kbd "s-g t") #'google-translate-smooth-translate))

 ;; temporary fix for error args-out-of-range
 ;; https://github.com/atykhonov/google-translate/issues/98
 (defun google-translate-json-suggestion (json)
   "Retrieve from JSON (which returns by the
 `google-translate-request' function) suggestion. This function
 does matter when translating misspelled word. So instead of
 translation it is possible to get suggestion."
   (let ((info (aref json 7)))
     (if (and info (> (length info) 0))
         (aref info 1)
       nil)))

#+END_SRC

** typing

Practice touch typing using =speed-type=. #+BEGIN_SRC emacs-lisp (use-package speed-type :ensure t) #+END_SRC

Running =M-x speed-type-region= on a region of text, or =M-x speed-type-buffer= on a whole buffer, or just =M-x speed-type-text= will produce the selected region, buffer, or random text for practice.

A better alternative is to use [[https://www.emacswiki.org/emacs/TypingOfEmacs][Typing of Emacs]] which is far more interactive. #+BEGIN_SRC emacs-lisp (use-package typing :ensure t) #+END_SRC

There are a few external websites that can help you with that too, [[https://typing.io/][Typing.io]] is the most recommended for Programmers. Check it out!

  • Snippets

    Yasnippet is a template system for Emacs. It allows you to type an abbreviation and automatically expand it into function templates.

    #+begin_src emacs-lisp (use-package yasnippet :ensure t :delight yas-minor-mode :config (yas-global-mode +1) (define-key yas-minor-mode-map (kbd "") nil) (define-key yas-minor-mode-map (kbd "TAB") nil) (define-key yas-minor-mode-map (kbd "C-c y") #'yas-expand)) #+end_src

    But since some specific version, yasnippet does not bundles snippets directly, you have to get them from third-party packages.

    #+begin_src emacs-lisp ;;; a snippet collection maintained by AndreaCrotti. (use-package yasnippet-snippets :ensure t) (use-package clojure-snippets :ensure t :defer t) #+end_src

    I want to rely more on snippets on my day-to-day, therefore I need way to visualize if there is an existent snippet for a particular situation. You can do that with `M-x yas/describe-table'.

    I will place that in my cheatsheet too and a nice shortcut: C-c s.

    #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-c s") (lambda () (interactive) (yas/describe-tables) (other-window 1)))

    #+END_SRC

    Jump to end of snippet definition

    #+BEGIN_SRC emacs-lisp (define-key yas-keymap (kbd "") 'yas-exit-all-snippets) #+END_SRC

  • Docker

#+begin_src emacs-lisp (use-package docker :ensure t :bind ("C-c d" . docker))

(use-package docker-tramp :ensure t)

(use-package dockerfile-mode :ensure t :config (add-to-list 'auto-mode-alist '("Dockerfile\'" . dockerfile-mode)) (add-to-list 'auto-mode-alist '("DockerfileDev\'" . dockerfile-mode)))

(use-package docker-compose-mode :ensure t :config (add-to-list 'auto-mode-alist '("docker-compose[^/]*\.yml\'" . docker-compose-mode)))

(defun bk/dockerfile-add-build-args () "Add env variables to your docker build." (interactive) (let* ((vars (read-from-minibuffer "sequence of <envName>=<envValue>: ")) (split-vars (split-string vars " "))) (setq dockerfile-build-args nil) (dolist (v split-vars) (add-to-list 'dockerfile-build-args v)) (setq docker-build-history-args vars)))

(defun bk/docker-compose-custom-envs () "Add usual env variables to Emacs environment." (interactive) (let* ((idu (shell-command-to-string "id -u")) (idg (shell-command-to-string "id -g")) (uid (string-join (vector (string-trim idu) ":" (string-trim idg))))) (setenv "WEBSERVER_PORT" "3000") (setenv "CURRENT_UID" uid) (message "setenv WEBSERVER_PORT=3000 CURRENT_UID=$(id -u):$(id -g) done!")))

(defun bk/docker-cleanup-buffers () "Delete all the docker buffers created." (interactive) (kill-matching-buffers "docker" nil t))

#+end_src

  • Social Networks ** rss feed

    I like to read about programming, but Emacs and Clojure are by far the most interesting communities I know so far, therefore, my feeds have many links from these subjects.

    #+BEGIN_SRC emacs-lisp (use-package elfeed :ensure t :commands (elfeed elfeed-update) :bind ("C-x w" . elfeed)) #+END_SRC

    #+name: elfeed-basic-config #+begin_src emacs-lisp :tangle no (setq-default elfeed-search-filter "@3-week-ago +unread") #+end_src

    Using the =minions= mode I am able to correctly see which modes are enabled at a specific buffer. I found several global modes enabled at =elfeed-search= which might be consuming resources.

    #+name: elfeed-mode-disabled #+BEGIN_SRC emacs-lisp (defun bk/elfeed-disable-mode-setup () (interactive) (abbrev-mode -1) (company-mode -1) (smart-shift-mode -1) (yas-minor-mode -1) (dired-async-mode -1) (diff-hl-flydiff-mode -1) (global-auto-revert-mode -1))

    (add-hook 'elfeed-show-mode-hook 'bk/elfeed-disable-mode-setup) (add-hook 'elfeed-search-update-hook 'bk/elfeed-disable-mode-setup) #+END_SRC

*** load config

Lazy loading all the parts of my elfeed setup.

#+BEGIN_SRC emacs-lisp :noweb yes (require 'elfeed) (require 'cl-lib) (require 'elfeed-search) (require 'elfeed-db)

 <<elfeed-basic-config>>
 <<elfeed-mode-disabled>>
 <<elfeed-newsletters>>
 <<elfeed-scoring>>
 <<elfeed-filters>>
 <<elfeed-automatic-update>>
 <<elfeed-starred>>
 <<elfeed-youtube>>

#+END_SRC

*** elfeed newsletters :properties: :header-args: :noweb-ref elfeed-newsletters :tangle no :end:

Configure the Elfeed RSS reader with an Org-mode file. Yet, I
tried to maintain my boring long list of feeds, but this does not
make sense at all. Hard to find info, not repeat yourself, and
even tagging.

#+BEGIN_SRC emacs-lisp
  (use-package elfeed-org
    :ensure t
    :after elfeed
    :init
    (setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed.org")
          rmh-elfeed-org-tree-id "elfeed")
    :config
    (elfeed-org))
#+END_SRC

*** filter :properties: :header-args: :noweb-ref elfeed-filters :tangle no :end:

By default, s run a live filter and you can type something like "Xah" to dynamically narrow the list of stories to those containing that string. The only problem is that you need an extra whitespace before the word, " Xah", let's fix that.

#+BEGIN_SRC emacs-lisp (defun bk/elfeed-search-live-filter-space () "Insert space when running elfeed filter" (interactive) (let ((elfeed-search-filter (concat elfeed-search-filter " "))) (elfeed-search-live-filter)))

 (define-key elfeed-search-mode-map (kbd "/") #'bk/elfeed-search-live-filter-space)

#+END_SRC

#+BEGIN_SRC emacs-lisp (define-key elfeed-search-mode-map "h" (lambda () (interactive) (elfeed-search-set-filter (default-value 'elfeed-search-filter)))) #+END_SRC

Tagging automatic as podcasts #+BEGIN_SRC emacs-lisp (defun ime-elfeed-pocast-tagger (entry) (when (elfeed-entry-enclosures entry) (elfeed-tag entry 'podcast)))

 (add-hook 'elfeed-new-entry-hook #'ime-elfeed-pocast-tagger)

#+END_SRC

*** automatic Update :properties: :header-args: :noweb-ref elfeed-automatic-update :tangle no :end:

Toggle automatic update of elfeed newsletters.

#+BEGIN_SRC emacs-lisp (defvar bk--update-elfeed-timer nil)

 (defun bk/toggle-update-elfeed ()
   "Toggle automatic elfeed update from 25/25 min."
   (interactive)
   (let ((repeat-rate (* 60 25)))
     (if bk--update-elfeed-timer
         (progn
           (cancel-timer bk--update-elfeed-timer)
           (setq bk--update-elfeed-timer nil)
           (message "Elfeed automatic update disabled..."))
       (setq bk--update-elfeed-timer
             (run-at-time 5 repeat-rate 'elfeed-update))
       (message "Elfeed automatic update enabled..."))))

 (add-hook 'after-init-hook 'bk/toggle-update-elfeed)

#+END_SRC

Enable visual-line-mode in elfeed buffers. #+BEGIN_SRC emacs-lisp (add-hook 'elfeed-show-mode-hook 'visual-line-mode) #+END_SRC

*** star and unstar :properties: :header-args: :noweb-ref elfeed-starred :tangle no :end:

This was got from [[http://pragmaticemacs.com/emacs/star-and-unstar-articles-in-elfeed/][pragmatic emacs]].

#+BEGIN_SRC emacs-lisp
  (defun bk/elfeed-star ()
    "Apply starred to all selected entries."
    (interactive)
    (let* ((entries (elfeed-search-selected))
           (tag (intern "starred")))
      (cl-loop for entry in entries do (elfeed-tag entry tag))
      (mapc #'elfeed-search-update-entry entries)
      (unless (use-region-p) (forward-line))))

  (defun bk/elfeed-unstar ()
    "Remove starred tag from all selected entries."
    (interactive)
    (let* ((entries (elfeed-search-selected))
           (tag (intern "starred")))
      (cl-loop for entry in entries do (elfeed-untag entry tag))
      (mapc #'elfeed-search-update-entry entries)
      (unless (use-region-p) (forward-line))))

  (defface elfeed-search-starred-title-face
    '((t :foreground "#f77"))
    "Marks a starred Elfeed entry.")

  (push '(starred elfeed-search-starred-title-face)
        elfeed-search-face-alist)

#+END_SRC

I bind these to the keys "*" to add a star and "8" to remove the
star.

#+BEGIN_SRC emacs-lisp
  (define-key elfeed-search-mode-map (kbd "*") 'bk/elfeed-star)
  (define-key elfeed-search-mode-map (kbd "8") 'bk/elfeed-unstar)
#+END_SRC


Now you can look for the starred feeds by pressing "S".
#+BEGIN_SRC emacs-lisp
  (defalias 'elfeed-toggle-star (elfeed-expose #'elfeed-search-toggle-all 'star))
  (define-key elfeed-search-mode-map (kbd "S") #'elfeed-toggle-star)
#+END_SRC

*** youtube :properties: :header-args: :noweb-ref elfeed-youtube :tangle no :end:

#+BEGIN_SRC emacs-lisp
  (defun ambrevar/elfeed-play-with-mpv ()
    "Play entry link with mpv."
    (interactive)
    (let ((entry (if (eq major-mode 'elfeed-show-mode) elfeed-show-entry (elfeed-search-selected :single)))
          (quality-arg "")
          (quality-val (completing-read "Max height resolution (0 for unlimited): " '("0" "480" "720") nil nil)))
      (setq quality-val (string-to-number quality-val))
      (message "Opening %s with height≤%s with mpv..." (elfeed-entry-link entry) quality-val)
      (when (< 0 quality-val)
        (setq quality-arg (format "--ytdl-format=[height<=?%s]" quality-val)))
      (start-process "elfeed-mpv" nil "mpv" quality-arg (elfeed-entry-link entry))))

  (defun ambrevar/elfeed-open-with-eww ()
    "Open in eww with `eww-readable'."
    (interactive)
    (let ((entry (if (eq major-mode 'elfeed-show-mode) elfeed-show-entry (elfeed-search-selected :single))))
      (eww  (elfeed-entry-link entry))
      (add-hook 'eww-after-render-hook 'eww-readable nil t)))

  (defvar ambrevar/elfeed-visit-patterns
    '(("youtu\\.?be" . ambrevar/elfeed-play-with-mpv)
      ("phoronix" . ambrevar/elfeed-open-with-eww))
    "List of (regexps . function) to match against elfeed entry link to know
  whether how to visit the link.")

  (defun ambrevar/elfeed-visit-maybe-external ()
    "Visit with external function if entry link matches `ambrevar/elfeed-visit-patterns',
  visit otherwise."
    (interactive)
    (let ((entry (if (eq major-mode 'elfeed-show-mode)
                     elfeed-show-entry
                   (elfeed-search-selected :single)))
          (patterns ambrevar/elfeed-visit-patterns))
      (while (and patterns (not (string-match (caar patterns) (elfeed-entry-link entry))))
        (setq patterns (cdr patterns)))
      (cond
       (patterns
        (funcall (cdar patterns)))
       ((eq major-mode 'elfeed-search-mode)
        (call-interactively 'elfeed-search-show-entry))
       (t (elfeed-show-visit)))))

  (define-key elfeed-search-mode-map "v" #'ambrevar/elfeed-play-with-mpv)
  (define-key elfeed-search-mode-map "c" 'elfeed-search-untag-all-unread)
  (define-key elfeed-show-mode-map "b" #'ambrevar/elfeed-visit-maybe-external)
#+END_SRC

*** score :properties: :header-args: :noweb-ref elfeed-scoring :tangle no :end:

#+BEGIN_SRC emacs-lisp
  (defun score-elfeed-entry (entry)
    (let ((title (elfeed-entry-title entry))
          (content (elfeed-deref (elfeed-entry-content entry)))
          (score 0))
      (cl-loop for (pattern n) in '(("software\\|programming\\|design\\|systems" 1)
                                 ("clojure" 1)
                                 ("emacs.*clojure\\|clojure.*emacs" 2))
            if (string-match pattern title)
            do (incf score n)
            if (string-match pattern content)
            do (incf score n))
      (message "%s - %s" title score)
      (setf (elfeed-meta entry :my/score) score)
      (cond
       ((= score 1)
        (elfeed-tag entry 'relevant))
       ((= score 2)
        (elfeed-tag entry 'important))
       ((> score 2)
        (elfeed-tag entry 'urgent)))
      entry))

  (defface relevant-elfeed-entry
    `((t :background ,(color-lighten-name "LightBlue1" 40)))
    "Maks a relevant Elfeed entry.")

  (defface important-elfeed-entry
    `((t :background ,(color-lighten-name "orange1" 40)))
    "Marks a important Elfeed entry.")

  (defface urgent-elfeed-entry
    `((t :background ,(color-lighten-name "OrangeRed2" 40)))
    "Marks an urgent Elfeed entry.")

  (add-hook 'elfeed-new-entry-hook 'score-elfeed-entry)

  (push '(relevant relevant-elfeed-entry) elfeed-search-face-alist)
  (push '(important important-elfeed-entry) elfeed-search-face-alist)
  (push '(urgent urgent-elfeed-entry) elfeed-search-face-alist)

  (define-key elfeed-search-mode-map (kbd "U")
    (lambda () (interactive)
      (elfeed-search-set-filter "@6-months-ago +unread +urgent")))

  (define-key elfeed-search-mode-map (kbd "I")
    (lambda () (interactive)
      (elfeed-search-set-filter "@6-months-ago +unread +important")))

  (define-key elfeed-search-mode-map (kbd "R")
    (lambda () (interactive)
      (elfeed-search-set-filter "@6-months-ago +unread +relevant")))

  (define-key elfeed-search-mode-map (kbd "C")
    (lambda () (interactive)
      (elfeed-search-set-filter "@6-months-ago +unread")))
#+END_SRC

** slack

Slack from Emacs? :O Why not? I am having a terrible time configuring all my workspaces lately. Therefore, it sounds like a perfect opportunity to leverage the best tool for the job once again.

#+BEGIN_SRC emacs-lisp (use-package slack :ensure t :disabled t :init (setq slack-buffer-emojify t slack-prefer-current-team t slack-request-timeout 30 slack-buffer-create-on-notify t slack-buffer-function #'switch-to-buffer slack-completing-read-function #'ido-completing-read) :config (slack-register-team :name "captalysdev" :default t :modeline-enabled t :visible-threads t :token (auth-source-pick-first-password :host "slack.com" :user "captalysdev") :subscribed-channels '(onboarding geral dev atlas garantias-e-cobranca) :full-and-display-names t)

 (slack-register-team
  :name "clojurians"
  :token (auth-source-pick-first-password
          :host "slack.com"
          :user "clojurians")
  :subscribed-channels '(beginners reitit sql))

 :config
 ;; go to any channel with `C-x j`
 (define-key ctl-x-map "j" #'slack-select-rooms)
 (define-key slack-mode-map (kbd "C-;") ":+1:"))

#+END_SRC

Bring up the mentions menu with `@', and insert a space afterwards. #+BEGIN_SRC emacs-lisp (eval-after-load 'slack '(define-key slack-mode-map "@" (defun endless/slack-message-embed-mention () (interactive) (call-interactively #'slack-message-embed-mention) (insert " ")))) #+END_SRC

CRUD on messages #+BEGIN_SRC emacs-lisp (eval-after-load 'slack '(progn (define-key slack-mode-map (kbd "C-c C-d") #'slack-message-delete) (define-key slack-mode-map (kbd "C-c C-e") #'slack-message-edit) (define-key slack-mode-map (kbd "C-c C-k") #'slack-channel-leave))) #+END_SRC

Circe is a client for IRC in Emacs. It tries to have sane defaults, and integrates well with the rest of the editor.

#+BEGIN_SRC emacs-lisp (use-package circe :ensure t) #+END_SRC

Emojify is an Emacs extension to display emojis. #+BEGIN_SRC emacs-lisp (use-package emojify :ensure t :delight emojify-mode :config (setq emojify-display-style 'image emojify-emoji-styles '(unicode) emojify-point-entered-behaviour 'echo) (global-emojify-mode 1)) #+END_SRC

How to use Slack on emacs? Some terminology from the website:

| Function | Description | |----------------------------+------------------------------------------------------------------------------------| | im | an IM (instant message) is a direct message between you and exactly one other user | | channel | A channel is a slack channel which you are a member of | | group | Any chat (direct message or channel) which isn't an IM is a group | | slack-register-team | set team configuration and create team | | slack-change-current-team | change slack-current-team var | | slack-start | do authorize and initialze | | slack-ws-close | turn off websocket connection | | slack-group-select | select group from list | | slack-im-select | select direct message from list | | slack-channel-select | select channel from list | | slack-group-list-update | update group list | | slack-channel-list-update | update channel list | | slack-message-embed-mentio | use to mention to user | | slack-file-upload | uploads a file |

*** custom functions **** take me directly to a specific chat room

 #+begin_src emacs-lisp
   (defun bk/slack-move-direct-to-specific-room (team channel)
     "Open the buffer of the specified CHANNEL in a TEAM, without leaving the current TEAM."
     (let* ((alist (mapcar #'(lambda (team) (cons (slack-team-name team)
                                             (oref team token)))
                           (hash-table-values slack-teams-by-token)))
            (token (cdr (-first (lambda (v) (equalp (car v) team)) alist)))
            (team (slack-team-find-by-token token))
            (room (-first (lambda (room) (equalp (slack-room-name room team) channel))
                          (slack-team-channels team))))
       (when team
         (slack-team-connect team)
         (slack-room-display room team))))

   (defun bk/slack-move-to-reitit ()
     "Take me to reitit discussions."
     (interactive)
     (bk/slack-move-direct-to-specific-room "clojurians" "reitit"))

   (defun bk/slack-move-to-beginners ()
     "Take me to beginners discussions."
     (interactive)
     (bk/slack-move-direct-to-specific-room "clojurians" "beginners"))
 #+end_src

** telegram

One more chat service that we need to stay in touch with friends and community.

#+BEGIN_SRC emacs-lisp (use-package telega :ensure t :delight (telega-chat-mode "Telegram") :init (setq telega-animation-play-inline nil telega-chat-reply-prompt "R>> " telega-chat-use-markdown-version 2) :config (custom-set-faces '(telega-msg-heading ((t (:overline t :weight bold)))))) #+END_SRC

I will also enable the contrib packages provides in the github repo. I copied the interesting ones to me in the =lisps/= folder. #+begin_src emacs-lisp (require 'telega-alert) (telega-alert-mode t)

 (require 'telega-dired-dwim)


 (use-package all-the-icons :ensure t)
 (require 'telega-url-shorten)
 (add-hook 'telega-load-hook 'global-telega-url-shorten-mode)

#+end_src

Enabling emoji completions in chat buffer

Take a look at the mode-line in chat buffers #+BEGIN_SRC emacs-lisp (setq telega-chat-mode-line-format '((:eval (telega-chatbuf-mode-line-unread)) (:eval (telega-chatbuf-mode-line-marked)) (:eval (telega-chatbuf-mode-line-members nil)) (:eval (telega-chatbuf-mode-line-pinned-msg 20)))) #+END_SRC

** spotify

#+BEGIN_SRC emacs-lisp (use-package helm-spotify-plus :ensure t :defer t) #+END_SRC

** twitter

The possible features includes:

  • viewing various timelines
  • posting tweets
  • following and removing users
  • marking tweets as favorites

Use Twitter from within Emacs! #+BEGIN_SRC emacs-lisp (use-package twittering-mode :ensure t :config (setq twittering-timer-interval 3600 twittering-icon-mode t twittering-use-master-password t)) #+END_SRC

How to use:

  1. Execute =M-x twit= to run twittering-mode.
  2. Basic key bindings are as follows:
    1. =V= : open or switch to another timeline by =timeline-spec=
    2. =u= : post a reply to the pointed tweet
    3. =RET= : post an organic retweet
    4. =C-c RET= : post an official/native retweet
    5. =d= : send a direct message
    6. =C-c C-w= : delete the pointed tweet
    7. =j= : go to next tweet

More on usage [[https://github.com/hayamiz/twittering-mode][here]].

  • Weather

    Weather forecast stolen from [[http://pragmaticemacs.com/emacs/weather-in-emacs/][pragmatic emacs]]. #+BEGIN_SRC emacs-lisp (use-package wttrin :ensure t :init (setq wttrin-default-cities '("São Paulo" "London")) :config (require 'wttrin)) #+END_SRC

    By default =wttrin= prompts you to choose the city from your list when it starts. This function starts with the first city on your list. I also have a problem with color-theme because I use a too light one.

    #+BEGIN_SRC emacs-lisp (defun bk/weather () "Open the weather in your first city in `wttrin-default-cities'." (interactive) (wttrin-query (car wttrin-default-cities)) (load-theme-buffer-local 'deeper-blue (get-buffer "wttr.in - São Paulo"))) #+END_SRC

  • Pomodoro

    For many people, time is an enemy. We race against the clock to finish assignments and meet deadlines. The Pomodoro technique teaches you to work with time, instead of struggling against it.

    1. Choose a task you would like to get done
    2. Set the pomodoro for 25 minutes
    3. Work on the task until the Pomodoro rings
    4. When the Pomodoro rings, put a checkmark on a paper
    5. Take a short break (5 minutes in my setup)
    6. Every 4 pomodoros, take a longer break (15 minutes in my setup)

    #+BEGIN_SRC emacs-lisp (require 'pomidor) #+END_SRC

  • Financial

    Ledger mode is a major-mode for editing files in the format used by the =ledger= command-line accounting system. It also provides automated support for some =ledger= workflows, such as reconciling transactions, or running certain reports.

    #+BEGIN_SRC emacs-lisp (use-package ledger-mode :ensure t :mode ("\.dat\'" "\.ledger\'" "\ledger\'") :custom (ledger-clear-whole-transactions t) :config (require 'ledger-mode)) #+END_SRC

    NOTE: in order to use this mode, =ledger= must be installed in your system.

    Some help functions from [[https://github.com/awalker4/.dotfiles/blob/master/emacs.d/config.org][here]].

    #+BEGIN_SRC emacs-lisp (defun bk/clean-leader-on-save () (interactive) (if (eq major-mode 'ledger-mode) (let ((curr-line (line-number-at-pos))) (ledger-mode-clean-buffer) (line-move (- curr-line 1)))))

    (defun bk/ledger-increment-date () (interactive) (bk/ledger-change-date 1))

    (defun bk/ledger-decrement-date () (interactive) (bk/ledger-change-date -1))

    (defun bk/ledger-change-date (num) (save-excursion (ledger-navigate-beginning-of-xact) (let* ((beg (point)) (end (re-search-forward ledger-iso-date-regexp)) (xact-date (filter-buffer-substring beg end))) (delete-region beg end) (insert (format-time-string "%Y/%m/%d" (time-add (bk/encoded-date xact-date) (days-to-time num)))))))

    (defun bk/encoded-date (date) (string-match "\([0-9][0-9][0-9][0-9]\)/\([0-9][0-9]\)/\([0-9][0-9]\)" date) (let* ((fixed-date (concat (match-string 1 date) "-" (match-string 2 date) "-" (match-string 3 date))) (d (parse-time-string fixed-date))) (encode-time 0 0 0 (nth 3 d) (nth 4 d) (nth 5 d))))

    (add-hook 'before-save-hook 'bk/clean-leader-on-save) (eval-after-load 'ledger-mode '(progn (define-key ledger-mode-map (kbd "C-M-.") 'bk/ledger-increment-date) (define-key ledger-mode-map (kbd "C-M-,") 'bk/ledger-decrement-date))) #+END_SRC

    Linter for the ledger mode. Very very useful to understand if you filled everything's right.

    #+BEGIN_SRC emacs-lisp (use-package flycheck-ledger :ensure t :config (add-hook 'ledger-mode-hook 'flycheck-mode)) #+END_SRC

    You can use =C-c C-b= to popup the =calc= mode and perform some math with the number at point to fix it.

    Register to get into the ledger file quickly. #+BEGIN_SRC emacs-lisp (set-register ?l '(file . "~/.ledger")) #+END_SRC

** ledger explanation

  • Double entry system: All money has a source and destination account
  • Five accounts
    • Assets : what you have
    • Expenses : what you expends
    • Income : what you earns
    • Liabilities : what you owe
    • Equity : what you worth
  • Net worth = Assets - Liabilities
  • Net income = Income - Expenses

*** plaintext accounting with the ledger ecosystem

[[https://youtu.be/FJtaM43PgXQ][Youtube]]

- **Why accounting?**
  - To know what you have
    - across all accounts
    - had at some point in the past
    - how much you can spend
  - legally required for most businesses
- **Double-entry accounting**
  - account: label describing an amount of something
    - assets      : bank accounts, wallet, investments
    - income      : paychecks, dividends, interest
    - expenses    : groceries, taxes, donations
    - liabilities : mortgage, credit cards, student loans
    - equity      : for everything else like opening balances
  - debit
    - the deduction of value from an account
  - credit
    - the addition of value to an account
  - transaction
    - a collection of credits and debits with a timestamp to
      describe when the transaction is effective
    - all transaction must balance, equals to 0 at the end
- **Why ledger?**
  - intimate knowledge of every transaction
  - track everything
  - its just text
  • Guru

    Let's force learning proper Emacs #+begin_src emacs-lisp (use-package guru-mode :ensure t :config (guru-mode 1)) #+end_src

    If you think that this is too aggressive, please don't! rsrs I am kidding, you can use the option =guru-warn-only= to =t= and be ashamed of yourself.

  • Advice

    When you need to modify a function defined in another library.

    [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html][Adivice]] feature lets you add to the existing definition of a function, by advising the function. This is a cleaner method than redefining the whole function.

** pop to mark When popping the mark, continue popping until the cursor actually moves. Also, if the last command was a copy - skip past all the expand-region craft. #+BEGIN_SRC emacs-lisp (defadvice pop-to-mark-command (around ensure-new-position activate) (let ((p (point))) (when (eq last-command 'save-region-or-current-line) ad-do-it ad-do-it ad-do-it) (dotimes (i 10) (when (= p (point)) ad-do-it))))

 (setq set-mark-command-repeat-pop t)

#+END_SRC

** yank indent

This was stolen from [[https://github.com/milkypostman/dotemacs/blob/master/init.el][here.]] The idea is to indent yanked regions in specific modes that you can define.

#+BEGIN_SRC emacs-lisp (defvar yank-indent-modes '(prog-mode js2-mode) " Modes in which to indent regions that are yanked (or yank-popped)")

 (defvar yank-advised-indent-threshold 1000
   " Threshhold (# chars) over which indentation does not automatically occur.")

 (defun yank-advise-indent-function (beg eng)
   "Do indentation, as long as the region isn't too large."
   (if (<= (- end beg) yank-advised-indent-threshold)
       (indent-region beg end nil)))

 (defadvice yank (after yank-indent activate)
   "If current mode is one of `yank-indent-modes', indent yanked text."
   (if (and (not (ad-get-arg 0))
            (member major-mode yank-indent-modes))
       (let ((transient-mark-mode nil))
         (yank-advise-indent-function (region-beginning) (region-end)))))

 (defadvice yank-pop (after yank-pop-indent activate)
   "If the current mode is one of `yank-indent-modes', indent yanked text."
   (if (and (not (ad-get-arg 0))
            (member major-mode yank-indent-modes))
       (let ((transient-mark-mode nil))
         (yank-advise-indent-function (region-beginning) (region-end)))))

 (defun yank-unindented ()
   (interactive)
   (yank 1))

#+END_SRC

  • Recording

    Tool for capturing screen-casts directly from Emacs.

    1. To use it, simply call =M-x camcorder-record=
    2. A new smaller frame will popup and recording starts
    3. When you're finished, git =F12=

    You can also convert the file to a =gif= by issuing the command =M-x comcorder-convert-to-gif=

    #+begin_src emacs-lisp (use-package camcorder :ensure t) #+end_src

** timing

Count up time and show remainder time at mode-line.

#+begin_src emacs-lisp ;; (use-package stopwatch ;; :ensure nil) #+end_src

  • Logs

** commands logs

#+begin_src emacs-lisp (use-package command-log-mode :ensure t :commands command-log-mode) #+end_src

  • Custom Functions ** shell *** kubernetes

    #+BEGIN_SRC emacs-lisp (defun eshell/kg (&rest args) "Find status of pods in ARGS." (let* ((env (car args))) (with-current-buffer "eshell" (insert "kubectl get pods -n " env) (eshell-send-input))))

    (defun get-pod-name (pod env)
      "Get POD name from correct ENV."
      (let ((res (eshell-command-result (concat "kubectl get pods -n " env))))
        (string-match (concat pod ".*") res 0)
        (car (split-string (match-string 0 res) " "))))
    
    (defun eshell/kl (&rest args)
      "Get logs from PODS and ENVS in ARGS."
      (let* ((pod (car args))
             (env (car (cdr args)))
             (pod-name (get-pod-name pod env)))
        (with-current-buffer "*eshell*"
          (insert "kubectl logs -n " env " " pod-name " " pod "-" env " -f")
          (eshell-send-input))))
    

    #+END_SRC *** keys i use to work with

    #+begin_src emacs-lisp (defun bk/load-private-keys () "Personal keys I use to work and whatnot" (interactive) (let ((client-key (shell-command-to-string "base64 /home/wand/CaptalysPlatform.key")) (qi-key (shell-command-to-string "base64 /home/wand/qitech_captalys_homolog.key.pub"))) (setenv "CLIENT_PRIVATE_KEY" client-key) (setenv "QI_PUBLIC_KEY" qi-key)) (message "CLIENT_PRIVATE_KEY and QI_PUBLIC_KEY were loaded"))

    ;; load them!!
    (bk/load-private-keys)
    

    #+end_src

** http-based *** find my current ip

#+begin_src emacs-lisp (defvar url-http-end-of-headers) (defun bk/ip () "Find my current public IP address." (interactive) (let* ((endpoint "https://api.ipify.org") (myip (with-current-buffer (url-retrieve-synchronously endpoint) (buffer-substring (+ 1 url-http-end-of-headers) (point-max))))) (kill-new myip) (message "IP: %s" myip))) #+end_src

** editing *** what? sudo!

#+BEGIN_SRC emacs-lisp (defun bk/sudo-edit (&optional arg) "Function to edit file with super-user with optional ARG." (interactive "P") (if (or arg (not buffer-file-name)) (find-file (concat "/sudo:root@localhost:" (read-file-name "File: "))) (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))) #+END_SRC *** eval and replace

#+BEGIN_SRC emacs-lisp
  (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)))))
#+END_SRC

*** insert today's date

#+BEGIN_SRC emacs-lisp
  (defun bk/insert-today-date ()
    "Insert today date as YYYY-MM-DD."
    (interactive)
    (insert (format-time-string "%Y/%m/%d")))
#+END_SRC

*** kill all the comments

#+BEGIN_SRC emacs-lisp
  (defun comment-kill-all ()
    "Function to kill all comments in a buffer."
    (interactive)
    (save-excursion
      (goto-char (point-min))
      (comment-kill (save-excursion
                      (goto-char (point-max))
                      (line-number-at-pos)))))
#+END_SRC

** buffer *** go to scratch buffer

#+BEGIN_SRC emacs-lisp
  (defun bk/scratch-buffer ()
    "Function to change buffer to scratch buffer."
    (interactive)
    (let ((buf (get-buffer "*scratch*")))
      (if buf
          (switch-to-buffer buf)
        (switch-to-buffer (get-buffer-create "*scratch*"))
        (lisp-interaction-mode))))

  (global-set-key (kbd "C-c b s") #'bk/scratch-buffer)
#+END_SRC

*** kill buffer and the file associated

#+BEGIN_SRC emacs-lisp (defun bk/kill-buffer-and-file (buffer-name) "Removes file connected to current buffer and kills buffer." (interactive "bKill buffer and its file:") (let* ((buffer (get-buffer buffer-name)) (filename (buffer-file-name buffer))) (if (not (and filename (file-exists-p filename))) (error "Buffer '%s' is not visiting a file!" buffer-name) (delete-file filename) (kill-buffer buffer)))) #+END_SRC *** rename current buffer and file associated

#+BEGIN_SRC emacs-lisp
  (defun bk/rename-current-buffer-file ()
    "Renames current buffer and file it is visiting."
    (interactive)
    (let* ((name (buffer-name))
           (filename (buffer-file-name))
           (new-name (read-file-name "New name: " filename)))
      (if (get-buffer new-name)
          (error "A buffer named '%s' already exists!" new-name)
        (rename-file filename new-name 1)
        (rename-buffer new-name)
        (set-visited-file-name new-name)
        (set-buffer-modified-p nil)
        (message "File '%s' sucessfully renamed to '%s'"
                 name (file-name-nondirectory new-name)))))
#+END_SRC

** miscellaneous *** generate password

#+BEGIN_SRC emacs-lisp
  (defun generate-password ()
    "Generate a 16-digit password."
    (interactive)
    (kill-new
     (s-trim (shell-command-to-string
              " openssl rand -base64 32 | tr -d /=+ | cut -c -16")))
    (message "Password in kill ring!"))
#+END_SRC
  • Keys

** free keys?

Which keys are free? #+begin_src emacs-lisp (use-package free-keys :ensure t :commands free-keys) #+end_src

** hint

#+begin_src emacs-lisp (use-package which-key :ensure t :delight which-key-mode :init (setq which-key-use-C-h-commands t which-key-separator " - " which-key-show-prefix 'echo which-key-popup-type 'side-window) :config (which-key-mode)) #+end_src

** global definitions

#+begin_src emacs-lisp (global-set-key (kbd "M-i") 'change-inner) (global-set-key (kbd "M-o") 'change-outer) (global-set-key (kbd "C-c e") 'eshell) (global-set-key (kbd "C-c C-k") 'eval-buffer) (global-set-key (kbd "C-x C-b") 'ibuffer) (global-set-key (kbd "C-c t") 'org-capture) (global-set-key (kbd "C-c a") 'org-agenda) (global-set-key (kbd "C-x p") 'pop-to-mark-command)

 ;; by default C-x k prompts to select which buffer should be selected.
 (global-set-key (kbd "C-x k") (lambda ()
              (interactive)
              (kill-buffer (current-buffer))))

#+end_src

** cast

Show current command and its key in the mode line #+BEGIN_SRC emacs-lisp (use-package keycast :homepage https://github.com/tarsius/keycast :ensure t :defer t) #+END_SRC

#+RESULTS:

** key frequency

Monitor my new habits key-wise. #+BEGIN_SRC emacs-lisp (use-package keyfreq :ensure t :init (setq keyfreq-excluded-commands '(self-insert-command abort-recursive-edit forward-char backward-char previous-line next-line org-self-insert-command)) :config (keyfreq-mode +1) (keyfreq-autosave-mode +1)) #+END_SRC

  • Emms

    [[https://www.gnu.org/software/emms/][GNU/Emms]] is the Emacs multimedia system. Emms displays and plays multimedia from within Emacs using a variety of external players and from different sources.

    #+BEGIN_SRC emacs-lisp (use-package emms :ensure t :init (setq emms-seek-seconds 10) :config (require 'emms-setup) (require 'emms-player-mpv) (emms-standard) (emms-default-players)) #+END_SRC

** mode line cycle

Display the emms mode line as a ticker. I am listening to several podcasts where the whole link of the podcast is displayed at the mode-line. I can't see the time-elapsed listen to stuff, this is bad.

A package to solve this problem: #+BEGIN_SRC emacs-lisp (use-package emms-mode-line-cycle :ensure t :after emms :config (emms-mode-line 1) (emms-playing-time 1) (emms-mode-line-cycle 1)) #+END_SRC

  • Exwm

    Emacs as my full operating system is just too great. I have a small problem recently with this setup, I use an 60% Anne Pro 2 keyboard and its well known to be very but very buggy. The experience of the keyboard itself is incredible, but the firmware behind it is just unbearable, for some reason after hitting some keys my Emacs was halting. oO yes, complete halt for no reason whatsoever, seems like XKB and this firmware is not getting along nicely.

** lxde

I found an alternative to fix this issue by using EXWM alongside with LXDE. There are two files: =~/.config/lxsession/LXDE/autostart= #+BEGIN_SRC conf @pcmanfm --desktop-off --profile LXDE @compton -b & #+END_SRC

=~/.config/lxsession/LXDE/desktop.conf= #+BEGIN_SRC conf [Session] window_manager=emacs disable_autostart=no polkit/command=lxpolkit clipboard/command=lxclipboard xsettings_manager/command=build-in proxy_manager/command=build-in keyring/command=ssh-agent quit_manager/command=lxsession-logout lock_manager/command=lxlock terminal_manager/command=lxterminal quit_manager/image=/usr/share/lxde/images/logout-banner.png quit_manager/layout=top

[GTK]
iXft/Antialias=1
iXft/Hinting=1
sXft/HintStyle=hintslight
sXft/RGBA=rgb
sNet/ThemeName=Clearlooks
sNet/IconThemeName=nuoveXT2
iNet/EnableEventSounds=1
iNet/EnableInputFeedbackSounds=1
sGtk/ColorScheme=
sGtk/FontName=Sans 10
iGtk/ToolbarStyle=3
iGtk/ToolbarIconSize=3
iGtk/ButtonImages=1
iGtk/MenuImages=1
iGtk/CursorThemeSize=18
sGtk/CursorThemeName=DMZ-White

[Mouse]
AccFactor=20
AccThreshold=10
LeftHanded=0

[Keyboard]
Delay=500
Interval=30
Beep=1

[State]
guess_default=true

[Dbus]
lxde=true

[Environment]
menu_prefix=lxde-

#+END_SRC

And don't forget to change the content of =~/.xinitrc= to =exec startlxde=.

** additional Functions

Ok, now let's start with EXWM configuration. #+BEGIN_SRC emacs-lisp (defun bk/keepmenu () "Call password manager." (interactive) (start-process-shell-command "pwd" nil "keepmenu"))

(defun bk/lock-screen ()
  (interactive)
  (start-process-shell-command "lock" nil "xscreensaver-command -lock"))

(defun bk/qutebrowse ()
  (interactive)
  (start-process-shell-command "browser" nil "qutebrowser"))

#+END_SRC

** exwm basics #+BEGIN_SRC emacs-lisp (use-package exwm :ensure t :disabled true :init (setq exwm-workspace-number 4 exwm-workspace-show-all-buffers nil exwm-layout-show-all-buffers t) :config (display-battery-mode t)

;; setting floating window boarder
(setq exwm-floating-border-width 3)

(require 'exwm)
(exwm-input-set-simulation-keys
 '(([?\C-p] . [up])
   ([?\C-n] . [down])
   ([?\C-f] . [right])
   ([?\C-b] . [left])
   ([?\C-s] . [\C-f])
   ([?\M-w] . [\C-c])
   ([?\C-y] . [\C-v])
   ([?\C-w] . [\C-x])))

(setq exwm-input-global-keys
      `(([?\s-r] . exwm-reset)
        ([?\s-w] . exwm-workspace-switch)
        ,@(mapcar (lambda (i)
                    `(,(kbd (format "s-%d" i)) .
                      (lambda ()
                        (interactive)
                        (exwm-workspace-switch-create ,i))))
                  (number-sequence 0 9))))

(exwm-input-set-key (kbd "s-p") #'bk/keepmenu)
(exwm-input-set-key (kbd "s-d") #'dmenu)
(exwm-input-set-key (kbd "C-c l") #'bk/lock-screen)

(exwm-enable)

(require 'exwm-config)
(exwm-config-ido)

;; universal Get-me-outta-here
(push ?\C-g exwm-input-prefix-keys)
(exwm-input-set-key (kbd "C-g") #'keyboard-quit))

#+END_SRC

*** window manager

Now that I am using Emacs as my window manager I can use the meta
keys to provide operations over the windows itself, in other days,
there were reserved to i3wm operations.

#+BEGIN_SRC emacs-lisp (eval-after-load "exwm" '(progn (exwm-input-set-key (kbd "s-x") #'exwm-input-toggle-keyboard) (exwm-input-set-key (kbd "s-h") #'windmove-left) (exwm-input-set-key (kbd "s-j") #'windmove-down) (exwm-input-set-key (kbd "s-k") #'windmove-up) (exwm-input-set-key (kbd "s-l") #'windmove-right))) #+END_SRC

I made a change in =qutebrowser= so every tab open is a new window of qutebrowser, therefore I can search for the tabs using =C-x b= from Emacs.

=:set -t tabs.tabs_are_window true=

More settings for qutebrowser can be found [[https://www.qutebrowser.org/doc/help/settings.html][here]].

Disabling floating window #+BEGIN_SRC emacs-lisp (eval-after-load "exwm" '(setq exwm-manage-force-tiling t)) #+END_SRC

** edit text fields

Ag has a very nice package to help us out in EXWM, the feature is similar in usage to Org-SRC-Blocks, therefore you press =C-c '= on input text boxes of other external apps and another window pops up so you can have all the Emacs under the finger while editing.

#+BEGIN_SRC emacs-lisp (use-package exwm-edit :ensure t :after (exwm) :config (exwm-input-set-key (kbd "C-s-e") #'exwm-edit--compose)) #+END_SRC

** app runner

  #+BEGIN_SRC emacs-lisp
    (use-package dmenu
      :ensure t
      :after (exwm)
      :commands (dmenu))

#+END_SRC

** multiple screens

Stolen from [[https://www.reddit.com/r/emacs/comments/cyuqbp/exwm_multimonitor_setup/][reddit]] answer, however the original function is heavily customized to the authors setup, therefore I modified the appropriate bits.

After some time working with the code I decided to try to make a package out of it. However, there are several moving peaces yet, however, is already useful for me.

Work in Progress nevertheless...

#+BEGIN_SRC emacs-lisp (eval-after-load "exwm" '(progn (require 'exwm-monitors)

      (exwm-monitors-define-screen-info
       :name "eDP1"
       :width 1600
       :height 900)

      (exwm-monitors-define-spec
       :name "home"
       :pred (list :only '("eDP1" "HDMI1"))
       :action (list '("eDP1" :off)
                     '("HDMI1" :right)))

      (defun bk/turn-x1-carbon-on ()
        (interactive)
        (exwm-monitors-define-spec
         :name "home"
         :pred (list :only '("eDP1" "HDMI1"))
         :action (list '("eDP1" :auto)

                       '("HDMI1" :right)))
        (exwm-monitors-initial-setup))

      (exwm-monitors-initial-setup)))

#+END_SRC

** system package

Oh, this is nice! I can control =pacman= from Emacs.

#+BEGIN_SRC emacs-lisp (use-package system-packages :ensure t :config (setq system-packages-use-sudo t)) #+END_SRC

** notification daemon

I need a notification daemon to alert me about all the statefull things changing around me. For now, I will use [[https://dunst-project.org/][Dunst]].

#+BEGIN_SRC emacs-lisp (call-process-shell-command "nohup dunst >/dev/null &" nil 0) #+END_SRC

There is a function to send an alert to the daemon. #+BEGIN_SRC emacs-lisp (defun dunst-alert (header string &rest objects) "Send an alert to the Dunst daemon." (let ((string (funcall #'format string objects)) (command (format "notify-send -a "%s" "%s"" header string))) (call-process-shell-command command nil 0))) #+END_SRC

** window behaviour

In stock Emacs, EXWM uses =char mode= and =line mode= to distinguish between using the keyboard to control an application vs using the keyboard to control the application's buffer.

Rename buffers to match the X11 window class or title: #+BEGIN_SRC emacs-lisp (defun exwm-rename-buffer () (interactive) (exwm-workspace-rename-buffer (concat exwm-class-name ":" (if (<= (length exwm-title) 30) exwm-title (concat (substring exwm-title 0 29))))))

 (add-hook 'exwm-update-class-hook 'exwm-rename-buffer)
 (add-hook 'exwm-update-title-hook 'exwm-rename-buffer)

#+END_SRC

Window dividers make Emacs look far less sloppy, and provide divisions between windows that are significantly more visible. The color is grabbed from the mode line for consistency. #+BEGIN_SRC emacs-lisp (eval-after-load "exwm" '(progn (setq window-divider-default-right-width 3) (let ((color (face-background 'mode-line))) (dolist (face '(window-divider-first-pixel window-divider-last-pixel window-divider)) (set-face-foreground face color))) (window-divider-mode 1))) #+END_SRC ** key bindings

"Global key bindings" in EXWM work essentially anywhere, including buffers that are currently in char mode. The bindings below should be fairly straightforward. #+BEGIN_SRC emacs-lisp #+END_SRC

Regular keys to control audio using the package pulseaudio. #+BEGIN_SRC emacs-lisp (use-package pulseaudio-control :ensure t :after (exwm) :config (exwm-input-set-key (kbd "<XF86AudioLowerVolume>") #'pulseaudio-control-decrease-volume)

   (exwm-input-set-key
    (kbd "<XF86AudioRaiseVolume>")
    #'pulseaudio-control-increase-volume)

   (exwm-input-set-key
    (kbd "<XF86AudioMute>")
    #'pulseaudio-control-toggle-current-sink-mute))

#+END_SRC

Control the backlight level #+BEGIN_SRC emacs-lisp (use-package emacs :ensure nil :after (exwm) :config (exwm-input-set-key (kbd "<XF86MonBrightnessDown>") (lambda () (interactive) (start-process-shell-command "bdown" nil "xbacklight -dec 10")))

   (exwm-input-set-key
    (kbd "<XF86MonBrightnessUp>")
    (lambda () (interactive)
      (start-process-shell-command "bdown" nil "xbacklight -inc 10"))))

#+END_SRC

More binding definitions #+BEGIN_SRC emacs-lisp (defun bk/qutebrowser () "Open the browser" (interactive) (start-process-shell-command "brw" nil "qutebrowser"))

 (defun bk/fix-caps-and-key-rate ()
   "Capslock is another ctrl and key rate need to be higher"
   (interactive)
   (start-process-shell-command "caps" nil "setxkbmap -layout us -variant alt-intl -option ctrl:nocaps")
   (start-process-shell-command "krate" nil "xset r rate 300 50")
   (message "Ctrl and key rate fixed!"))

 (use-package emacs
   :ensure nil
   :after (exwm)
   :config
   (exwm-input-set-key (kbd "s-q") #'bk/qutebrowser)
   (exwm-input-set-key (kbd "C-c k") #'bk/fix-caps-and-key-rate))

#+END_SRC

System tray #+BEGIN_SRC emacs-lisp (defun exwm-bk/nm-applet () (interactive) (start-process-shell-command "applt" nil "nm-applet"))

 (defun exwm-bk/bluetooth ()
   (interactive)
   (start-process-shell-command "bl-applt" nil
                                "blueman-applet"))

 (defun exwm-bk/xscreensaver ()
   (interactive)
   (start-process-shell-command "xs" nil
                                "xscreensaver -no-splash"))

 (defun exwm-bk/key-rate ()
   (interactive)
   (start-process-shell-command "key-rate" nil
                                "xset r rate 300 50"))

 (defun exwm-bk/nocaps ()
   (interactive)
   (start-process-shell-command "nocaps" nil
                                "setxkbmap -layout us -variant alt-intl -option ctrl:nocaps"))

 (use-package exwm-systemtray
   :ensure nil
   :after (exwm)
   :init
   (setq exwm-systemtray-height 20)
   :config
   (exwm-systemtray-enable)
   (add-hook 'exwm-init-hook 'exwm-bk/nm-applet t)
   (add-hook 'exwm-init-hook 'exwm-bk/bluetooth t)
   (add-hook 'exwm-init-hook 'exwm-bk/xscreensaver)
   (add-hook 'exwm-init-hook 'exwm-bk/key-rate)
   (add-hook 'exwm-init-hook 'exwm-bk/nocaps))

#+END_SRC

*** Logging out with LXDE #+BEGIN_SRC emacs-lisp (defun exwm-logout () (interactive) (recentf-save-list) (save-some-buffers) (start-process-shell-command "logout" nil "lxsession-logout")) #+END_SRC

** important commands

| Keys | Command | Description | |------+----------------------------+---------------------------------------------| | - | exwm-workspace-move-window | send current window to a specific workspace |

  • References

    1. [[https://github.com/ch11ng/exwm/wiki][EXWM User Guide]]
    2. [[https://github.com/bvk/config/blob/master/emacs/wm.el][EXWM config with support for external monitor]]
    3. [[https://www.reddit.com/r/emacs/comments/6huok9/exwm_configs/][Reddit EXWM Configs?]]
    4. [[https://github.com/agzam/dot-spacemacs/tree/master/layers/ag-exwm][Ag layer for EXWM]]
    5. [[https://github.com/kinleyd/configs/blob/master/init.el][Another great emacs.d focusing on EXWM]]
    6. [[https://www.reddit.com/r/emacs/comments/74hetz/emacs_everywhere/][Emacs Everywhere]] - by u/ambrevar. Very nice post on reddit.
    7. https://ambrevar.xyz/emacs/
    8. [[https://github.com/wasamasa/dotemacs/blob/master/init.org][Literate emacs ]] - by wasamasa
    9. [[https://github.com/farlado/dotemacs][Far from sane literate Emacs]] - by farlado
    10. [[http://pragmaticemacs.com/all-posts/][Pragmatic Emacs]] - Amazing blog with lots of Emacs customizations