Skip to content

Latest commit

 

History

History
1968 lines (1400 loc) · 50.6 KB

Knani.org

File metadata and controls

1968 lines (1400 loc) · 50.6 KB

Mohamed Aziz Knani configuration file

Introduction

I like very much the idea of literate programming, it appears that Org-mode in Emacs shines in doing this, the code here is tangled into an emacs lisp file and loaded by emacs, I also weave it into an html file and post it on my website.

I suggest you start with a starter kit like bbatsov’s prelude not with mine since I make some decision you might not like.

First backup your old configuration

mv ~/.emacs.d ~/.emacs.d-back

Then can download my config doing:

git clone https://github.com/mohamed-aziz/.emacs.d-new.git ~/.emacs.d

Then install all the dependencies, for now I have no automated way of doing this.

In the beginning this must be found in your init.el, this will just tangle Knani.org, reload init.el and byte compile it.

(require 'org)
(org-babel-tangle-file (concat user-emacs-directory "Knani.org"))
(load-file (concat user-emacs-directory "init.el"))
(byte-compile-file (concat user-emacs-directory "init.el"))

If you are done with changes just re-tangle Knani.org using C-c C-v t.

Initialize

Personal Information

(setq user-full-name "Mohamed Aziz Knani"
  user-mail-address "[email protected]")

Package sources

If the system has gnutls use ssl.

 (require 'package)
 (package-initialize)
 (let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
			 (not (gnutls-available-p))))
	    (url (concat (if no-ssl "http" "https") "://melpa.org/packages/")))
   (add-to-list 'package-archives (cons "melpa" url) t))

 (let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
			 (not (gnutls-available-p))))
	    (url (concat (if no-ssl "http" "https") "://orgmode.org/elpa/")))
   (add-to-list 'package-archives (cons "org" url) t))

from glyph’s blog

(setq tls-program "gnutls-cli")

(let ((trustfile
       (replace-regexp-in-string
        "\\\\" "/"
        (replace-regexp-in-string
         "\n" ""
         (shell-command-to-string "python -m certifi")))))
  (setq tls-program
        (list
         (format "gnutls-cli%s --x509cafile %s -p %%p %%h"
                 (if (eq window-system 'w32) ".exe" "") trustfile))))

Load custom file

Load custom settings

(setq custom-file (expand-file-name "custom.el" user-emacs-directory))

(when (file-exists-p custom-file)
  (load custom-file))

Look and feel

Define themes

(defconst dark-theme 'doom-one)
(defconst light-theme 'doom-one-light)
 (tool-bar-mode   0)
 (menu-bar-mode   0)

 (when (> emacs-major-version 24)
   (scroll-bar-mode 0))

 ;; arabic font
 (when window-system
   (set-fontset-font "fontset-default" '(#x600 . #x6ff)
			 "Kawkab Mono"))

Set no-fringes mode

(set-fringe-style '(0 . 0))

Default font

(set-frame-font "DejaVu Sans Mono 11" nil t)

Add load paths

 (add-to-list 'load-path
		  (expand-file-name "lisp" user-emacs-directory))
 (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")

UI

Beacon

(require 'beacon)
(beacon-mode +1)

Doom

Doom mode-line

(require 'doom-modeline)
(doom-modeline-mode t)
(require 'doom-themes)
(load-theme 'doom-one t)
;; (doom-themes-visual-bell-config)

Ivy

Enable Ivy

(require 'ivy)

(ivy-mode 1)t
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
(global-set-key "\C-s" 'swiper)
(global-set-key (kbd "C-c C-r") 'ivy-resume)
(global-set-key (kbd "<f6>") 'ivy-resume)
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "<f1> f") 'counsel-describe-function)
(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
(global-set-key (kbd "<f1> l") 'counsel-find-library)
(global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
(global-set-key (kbd "<f2> u") 'counsel-unicode-char)
(global-set-key (kbd "C-c g") 'counsel-git)
(global-set-key (kbd "C-c j") 'counsel-git-grep)
(global-set-key (kbd "C-c k") 'counsel-ag)
(global-set-key (kbd "C-x l") 'counsel-locate)
(global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
(define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history)

Dired

(require 'dired)

Keybindings

(define-key dired-mode-map "b" 'emms-add-dired)
(define-key dired-mode-map (kbd "C-c f") 'find-name-dired)
(define-key dired-mode-map (kbd "C-c o") 'crux-open-with)

Hide details

This just hides details and just displays the files and directory names, this can be toggled using ‘(’

(add-hook 'dired-mode-hook '(lambda ()
                            (dired-hide-details-mode)))

Switches

Dired uses the ls program from GNU coreutils to get stuff, so you can do this

(setq dired-listing-switches "-lah")

Download file

An interactive function to download files from here

(require 'url)

(defun download-file (&optional url download-dir download-name)
  (interactive)
  (let ((url (or url
                 (read-string "Enter download URL: "))))
    (let ((download-buffer (url-retrieve-synchronously url)))
      (with-current-buffer download-buffer
        ;; we may have to trim the http response
        (goto-char (point-min))
        (re-search-forward "^$" nil 'move)
        (forward-char)
        (delete-region (point-min) (point))
        (write-file (concat (or default-directory
                                download-dir
                                "~/Downloads"
                                (or download-name
                                    (car (last (split-string url "/" t)))))))))))

Normalize filenames

I have some functions to normalize filenames, this has some bugs though

(defun normalize-name (filename)
  "Replace space with underscore"
  (replace-regexp-in-string " " "_" filename))

(defun dired-do-rename-file ()
  "Call dired-rename-file"
  (let ((file (file-name-base (dired-get-filename nil t))))
    (print file)
    (dired-rename-file file (normalize-name file) nil)))

(defun dired-normalize-name (&optional arg)
  "Normalize files from dired"
  (interactive "P")
  (dired-map-over-marks-check (function dired-do-rename-file) arg 'normalize t)
  (revert-buffer))

Open with xdg-open

This just lets me open files (or directories) with their default applications, it doesn’t support windows though since I don’t think that it has a facility to open files like that.

This is stolen from bbatsov’s crux package

   (defun crux-open-with (arg)
     "Open visited file in default external program.
   When in dired mode, open file under the cursor.
   With a prefix ARG always prompt for command to use."
     (interactive "P")
     (let* ((current-file-name
	       (if (eq major-mode 'dired-mode)
		   (dired-get-file-for-visit)
		 buffer-file-name))
	      (open (pcase system-type
		      (`darwin "open")
		      ((or `gnu `gnu/linux `gnu/kfreebsd) "xdg-open")))
	      (program (if (or arg (not open))
			   (read-shell-command "Open current file with: ")
			 open)))
	 (call-process program nil 0 nil current-file-name)))

Dired async

I like using dired async

(require 'dired-async)
(dired-async-mode 1)

Dired subtree

This requires dired-hacks-utils

(require 'dired-subtree)

(define-key dired-mode-map "i" 'dired-subtree-insert)
(define-key dired-mode-map ";" 'dired-subtree-remove)

Some other stuff

Some other stuff like dwim and dired-fixups

(require 'dired-fixups)
(setq dired-dwim-target t)

ERC

ERC is my default IRC client

(require 'erc)
(require 'erc-log)

(setq erc-log-channels-directory "~/.erc/logs/")
(erc-truncate-mode +1)
(erc-spelling-mode 1)
(setq erc-server-coding-system '(utf-8 . utf-8))
(setq erc-autojoin-channels-alist '(("freenode.net" . (
							   "#emacs"
							   "#gnu"
							   "#crypto"
							   "##programming"))
					("oftc.net" . ("#suckless"
					"#debian"))))

Enable notifications

(require 'erc-desktop-notifications)

Smiley mode

(erc-smiley-enable)

Eshell

Eshell toggle

code from multi-term.el

   (defvar eshell-dedicated-exists-p nil)
   (defun eshell-dedicated-toggle ()
     "Toggle dedicated `multi-term' window."
     (interactive)
     (if (eshell-dedicated-exist-p)
	   (progn
	     (multi-term-dedicated-close)
	     (if (and multi-term-dedicated-close-back-to-open-buffer-p
		      multi-term-dedicated-close-buffer)
		 (switch-to-buffer multi-term-dedicated-close-buffer)
	       ))
	 (if multi-term-dedicated-close-back-to-open-buffer-p
	     (setq multi-term-dedicated-close-buffer (current-buffer)))
	 (multi-term-dedicated-open)
	 ))

   ;;;###autoload
   (defun multi-term-dedicated-select ()
     "Select the `multi-term' dedicated window."
     (interactive)
     (if (multi-term-dedicated-exist-p)
	   (select-window multi-term-dedicated-window)
	 (message "`multi-term' window is not exist.")))

Background makes

from emacswiki

   (defun eshell/ec (&rest args)
     "Use `compile' to do background makes."
     (if (eshell-interactive-output-p)
	   (let ((compilation-process-setup-function
		  (list 'lambda nil
			(list 'setq 'process-environment
			      (list 'quote (eshell-copy-environment))))))
	     (compile (eshell-flatten-and-stringify args))
	     (pop-to-buffer compilation-last-buffer))
	 (throw 'eshell-replace-command
		(let ((l (eshell-stringify-list (eshell-flatten-list args))))
		  (eshell-parse-command (car l) (cdr l))))))
   (put 'eshell/ec 'eshell-no-numeric-conversions t)

Pyvenv integration

Integration of pyvenv within Eshell

(with-eval-after-load 'eshell
  (defvar eshell-path-env)
  (dolist (hook '(pyvenv-post-activate-hooks pyvenv-post-deactivate-hooks))
    (add-hook hook                  ; eshell
              (lambda ()
                (let ((path-env (mapconcat (lambda (x) (or x "."))
                                           exec-path
                                           path-separator)))
                  (setq-default eshell-path-env path-env)
                  (dolist (buffer (buffer-list))
                    (with-current-buffer buffer
                      (and (derived-mode-p 'eshell-mode)
                           (setq eshell-path-env path-env)))))))))

Email

I use mu4e for Mail

(require 'mu4e)

set the mail directory

(setq mu4e-maildir (expand-file-name "~/Maildir"))

load file with email configuration, this has my mu4e contexts:

(load-file (expand-file-name "~/email.el"))
(setq mu4e-sent-messages-behavior 'delete)

update mail using offlineimap

(setq mu4e-get-mail-command "offlineimap -o")

send mail using SMTP, anyways who the fuck uses IMAP to send mails.

Here authinfo.gpg is encrpyted using GNUpg, just make sure you don’t use symmetric encrpytion so that you don’t enter the password every single time (GNUpg caches the passwords using gpg-agent for some time I think)

 (require 'smtpmail)

 (setq message-send-mail-function 'smtpmail-send-it
	  starttls-use-gnutls t
	  smtpmail-auth-credentials (expand-file-name "~/.authinfo.gpg")
	  smtpmail-debug-info t)

Spelling

(add-hook 'mu4e-compose-mode-hook (lambda ()
					 (flyspell-mode)))

Epa integration

(add-hook 'message-mode-hook (lambda ()
			       (epa-mail-mode)))

(add-hook 'mu4e-view-mode-hook (lambda ()
				      (epa-mail-mode)))

(add-hook 'mu4e-compose-mode-hook (lambda ()
					 (epa-mail-mode)))

Offlineimap configuration

It is unrelated to Emacs but I put my .offlineimaprc here.

[general]
accounts = Gmail,MAKCock
pythonfile = ~/.offlineimap.py


[Account Gmail]
localrepository = Local
remoterepository = Remote
autorefresh = 3
status_backend = sqlite
maxconnections = 3
maxsyncaccounts = 3


[Repository Local]
type = GmailMaildir
localfolders = ~/Maildir/KnaniGmail
nametrans = lambda folder: {'archive': '[Gmail].Tous les messages'}.get(folder, folder)

[Repository Remote]
type = Gmail
remoteuser = [email protected]
remotepasseval = get_password_emacs("imap.gmail.com", "[email protected]", "993")
nametrans = lambda folder: {'archive': '[Gmail].Tous les messages'}.get(folder, folder)
folderfilter = lambda x: x not in ['[Gmail]/Spam', '[Gmail]/Tous les messages']
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

[Account MAKCock]
localrepository = LocalCock
remoterepository = RemoteCock
autorefresh = 3
status_backend = sqlite
maxconnections = 3
maxsyncaccounts = 3


[Repository LocalCock]
type = Maildir
localfolders = ~/Maildir/Cock

[Repository RemoteCock]
type = IMAP
remotehost = mail.cock.li
remoteuser = [email protected]
remotepasseval = get_password_emacs("mail.cock.li", "[email protected]", "993")
realdelete = no
holdconnectionopen = true
keepalive = 60
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

as for the get_password_emacs function here it is

import re, os

def get_password_emacs(machine, login, port):
    s = "^machine %s login %s port %s password ([^ ]*)$" % (machine, login, port)
    p = re.compile(s)
    authinfo = os.popen("gpg -q --no-tty -d ~/.authinfo.gpg").read()
    for entry in authinfo.splitlines():
        # return on first match
        if p.search(entry):
            return p.search(entry).group(1)
        else:
            continue

Async smtp send function

This won’t block Emacs hopefully

 (require 'smtpmail-async)
 (setq send-mail-function 'async-smtpmail-send-it
	   message-send-mail-function 'async-smtpmail-send-it)

Disable duplicates

This happens with gmail and offlineimap

(setq mu4e-headers-skip-duplicates t)

Key binding

(global-set-key [(f5)] 'mu4e)

Music

I use EMMS for music, I also have emms-player-mpv to play the thing inside mpv.

(require 'emms-setup)
(emms-all)

;; fallback to mplayer
(define-emms-simple-player mplayer '(file url)
  (regexp-opt '(".ogg" ".mp3" ".wav" ".mpg" ".mpeg" ".wmv" ".wma" ".webm"
		    ".mov" ".avi" ".divx" ".ogm" ".asf" ".mkv" "http://" "mms://"
		    ".aiff"
		    ".rm" ".rmvb" ".mp4" ".flac" ".vob" ".m4a" ".flv" ".ogv" ".pls" ".opus"))
  "mplayer" "-slave" "-quiet" "-really-quiet" "-fullscreen")


(add-to-list 'emms-player-list 'emms-player-mpv)

(add-to-list 'emms-player-mpv-parameters "--vo=null")

(require 'emms-info-libtag)
(setq emms-info-functions '(emms-info-libtag))
;;; below is a nice key command for toggling the music browser
(autoload 'emms-smart-browse "emms-browser.el" "Browse with EMMS" t)

(global-set-key [(f7)] 'emms-smart-browse)

(setq emms-source-file-default-directory "~/Music/")

regex

   (setq emms-player-base-format-list
     '("ogg" "mp3" "wav" "mpg" "mpeg" "wmv" "wma"
	"mov" "avi" "divx" "ogm" "ogv" "asf" "mkv"
	"rm" "rmvb" "mp4" "flac" "vob" "m4a" "ape"
	"flv" "webm" "aif" "dsf"))

   (emms-player-set emms-player-mpv 'regex
		     (apply #'emms-player-simple-regexp emms-player-base-format-list))

I also have this in my mpv configuration

audio-display=no

Insert current track in buffer

     (defun my/emms-insert-current-track ()
	 (interactive)
	 (insert
	  (let* ((data (emms-playlist-current-selected-track))
		 (artist (cdr (assoc 'info-artist data)))
		 (title (cdr (assoc 'info-title data))))
	    (concat title " By " artist))))

mpv config

mpv command line parameters

 (setq emms-player-mpv-parameters
	   '("--quiet" "--really-quiet"))

Thanks to Mike Kazantsev for his help on the EMMS mailing list.

(defun emms-mpv-toggle-vid ()
  (interactive)
  (emms-player-mpv-cmd `(get_property vid)
			    (lambda (vid err)
			      (emms-player-mpv-cmd `(set_property vid ,(if (eq vid ':json-false)
									  1
									0))))))

Covers

I know this exists thanks to Pierre Neidhardt email apparently this was added in version 5.

(setq emms-browser-covers #'emms-browser-cache-thumbnail)

Org

(require 'org)

What to record when a task is marked done

(setq org-log-done 'time)

Org directory

(setq org-directory "~/Documents/org")

For better viewing math equations

(setq org-format-latex-options (plist-put org-format-latex-options :scale 1.7))

setting program for rendering latex fragments

(setq org-preview-latex-default-process 'dvipng)

For easier math symbols input for latex

Org-tangle disable confirmation

(setq  org-confirm-babel-evaluate nil)

Some eye candy stuff

What is olivetti-mode?

(add-hook 'org-mode-hook '(lambda ()
                            (setq left-margin-width 5)
                            (setq right-margin-width 5)
                            (visual-line-mode)
                            (flyspell-mode)))

This is my agenda files

Org personal files:

(load-file (expand-file-name "~/orgfiles.el"))

Keybindings

(global-set-key (kbd "C-c a") 'org-agenda)
;; (define-key org-mode-map (kbd "M-RET") 'org-insert-heading)
(define-key global-map "\C-cc" 'org-capture)
(add-hook 'org-shiftup-final-hook 'windmove-up)
(add-hook 'org-shiftleft-final-hook 'windmove-left)
(add-hook 'org-shiftdown-final-hook 'windmove-down)
(add-hook 'org-shiftright-final-hook 'windmove-right)

C/C++

For working with C/C++/D source code

(org-babel-do-load-languages
 'org-babel-load-languages '((C . t)
				  (shell . t)
				  (calc . t)
				  (python . t)))

Shoot and insert

Utility function I use to take a screenshot of a dosbox window and then inserting the image in a org-mode buffer.

Screenshot

(defun insert-shot ()
  (interactive)
  (let*
      ((filename (concat (format "%04x" (random (expt 16 4))) ".png" )))
    ;; change to window; take shot; and insert it
    (shell-command (concat "wmctrl -a WINXP && import -window $(xdotool getactivewindow) " filename))
    ;; return to emacs
    (shell-command "wmctrl -a Emacs")
    ;; insert image to org file
    (insert (format "
#+CAPTION: caption
#+LABEL: fig:label
#+ATTR_LATEX: :float

[[file:%s]]" filename))))

(define-key org-mode-map (kbd "<f8>") 'insert-shot)

Org crypt

auto crypt org files using EasyPG

(require 'org-crypt)
(org-crypt-use-before-save-magic)

Org modules

Add org-habit

(add-to-list 'org-modules 'org-habit)

Org capture

(setq org-default-notes-file (expand-file-name "~/notes.org"))

Org contacts

mu4e, get email form name

 (defun org-contacts-mu4e-get-name-email ()
   "Get name and email address from Gnus message."
   (if (gnus-alive-p)
	   (gnus-with-article-headers
	     (mail-extract-address-components
	      (or (mail-fetch-field "From") "")))))

Org contacts phone number template:

 (defun org-contacts-template-phone (&optional return-value)
   "Try to return the contact phne for a template.
 If not found return RETURN-VALUE or something that would ask the user."
   (or (cadr (org-contacts-gnus-get-name-email))
	   return-value
	   (concat "%^{PHONE}p")))

org-capture contacts template:

 (add-to-list 'org-capture-templates
		  `("c" "Contacts" entry (file+headline mylifefile "People")
		    "* %(org-contacts-template-name)
 :PROPERTIES:
 :EMAIL: %(org-contacts-template-email)
 :PHONE: %(org-contacts-template-phone)
 :END:"))

Capture web content

 (add-to-list 'org-capture-templates
		  `("w" "Web site" entry
		    (file ,(concat org-directory "/websites.org"))
		    "* %a %^g \n\ncaptured on: %U \n\n%?\n\n%:initial"))

todo template

 (add-to-list 'org-capture-templates
		  `("t" "Todo" entry (file+headline mylifefile "Tasks")
		    "* TODO %?\n  %i\n  %a"))

Template to capture an elfeed-entry copied from skeeto/elfeed#206

 (add-to-list 'org-capture-templates 
		  `("l" "To read" entry (file+headline mylifefile "Bookmarks")
		   "* TODO %?%:description :toread:
 - %:link
 %(when (< 0 (length \"%:elfeed-entry-link\")) (concat \"- web link: \" \"%:elfeed-entry-link\"))"))

Capture web bookmarks

  (add-to-list 'org-capture-templates
		 `("b" "Web site bookmark" entry
		    (file ,(concat org-directory "/bookmarks.org"))
		    "* %a %^g\n\n  %?\n  captured on: %U\n\n%:initial"))

Capture code snippets and computer stuff

 (add-to-list 'org-capture-templates
		  `("T" "Tip" entry (file ,(concat org-directory "/tip.org"))
		    "* %? %^g\n  %x\n  %a\n  captured on: %U\n\n"))

Capture passwords

(add-to-list 'org-capture-templates `("P" "Password" entry (file ,(concat org-directory "/passwords.org.gpg"))
		      "* %^{Title}\n  %^{URL}p %^{USERNAME}p %^{PASSWORD}p"))

Journal

(add-to-list 'org-capture-templates `("j" "Journal" entry (file+olp+datetree mylifefile "Journal")
					   "* %?\nEntered on %U\n  %i\n  %a"))

Blog post

   (defun capture-report-data-file ()
     (let ((name (read-string "Name: ")))
	 (find-file (expand-file-name (format "%s-%s.org"
					      (format-time-string "%Y-%m-%d")
					      name) "/part3/mo/emacs_site/blog/"))))


   (add-to-list 'org-capture-templates
		  `("B"
		     "Blog post"

		     plain
		     (function capture-report-data-file)
		     "#+TITLE: %^{prompt}\n#+DATE: %T\n\n%?"))

This might be deprecated in the future

(require 'org-mu4e)

Capture email:

 (add-to-list 'org-capture-templates 
		  `("e" "Email" entry (file ,(concat org-directory "/email.org"))
		    "* %?%:description :email:\n  - %:link\n  - %:fromto"))

Org protocol capture

Org protocol stuff

(server-start)
(require 'org-protocol)
(require 'org-protocol-capture-html)

template

 (add-to-list 'org-capture-templates 
		   `("p" "Protocol" entry (file+headline ,(concat org-directory "protocol.org") "Inbox")
		     "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?"))

 (add-to-list 'org-capture-templates 
		   `("L" "Protocol Link" entry (file+headline ,(concat org-directory "protocol.org") "Inbox")
					     "* %? [[%:link][%:description]] \nCaptured On: %U"))

Fix org cpature with counsel

     (eval-after-load 'org
	`(load "~/.emacs.d/lisp/org-fix-capture-counsel.el"))

Org contact

Set org contact files

(require 'org-contacts)
(setq  org-contacts-files `(,(concat org-directory "/people.org")))

org-contacts-files

set org

Latex export code stuff

 (setq org-latex-listings 'minted
	   org-latex-packages-alist '(("" "minted"))
	   org-src-fontify-natively t
	   org-latex-pdf-process
	   '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
	     "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))

Org passwords

(setq org-passwords-file (concat org-directory "/passwords.org.gpg"))

Split code block

this function will say if the cursor is any org-block:

   (defun my/org-in-any-block-p ()
     "Return non-nil if the point is in any Org block.

   The Org block can be *any*: src, example, verse, etc., even any
   Org Special block.

   This function is heavily adapted from `org-between-regexps-p'."
     (save-match-data
	 (let ((pos (point))
	       (case-fold-search t)
	       (block-begin-re "^[[:blank:]]*#\\+begin_\\(?1:.+?\\)\\(?: .*\\)*$")
	       (limit-up (save-excursion (outline-previous-heading)))
	       (limit-down (save-excursion (outline-next-heading)))
	       beg end)
	   (save-excursion
	     ;; Point is on a block when on BLOCK-BEGIN-RE or if
	     ;; BLOCK-BEGIN-RE can be found before it...
	     (and (or (org-in-regexp block-begin-re)
		      (re-search-backward block-begin-re limit-up :noerror))
		  (setq beg (match-beginning 0))
		  ;; ... and BLOCK-END-RE after it...
		  (let ((block-end-re (concat "^[[:blank:]]*#\\+end_"
					      (match-string-no-properties 1)
					      "\\( .*\\)*$")))
		    (goto-char (match-end 0))
		    (re-search-forward block-end-re limit-down :noerror))
		  (> (setq end (match-end 0)) pos)
		  ;; ... without another BLOCK-BEGIN-RE in-between.
		  (goto-char (match-beginning 0))
		  (not (re-search-backward block-begin-re (1+ beg) :noerror))
		  ;; Return value.
		  (cons beg end))))))

This function will split the block

   (defun my/org-split-block ()
     "Sensibly split the current Org block at point."
     (interactive)
     (if (my/org-in-any-block-p)
	   (save-match-data
	     (save-restriction
	       (widen)
	       (let ((case-fold-search t)
		     (at-bol (bolp))
		     block-start
		     block-end)
		 (save-excursion
		   (re-search-backward "^\\(?1:[[:blank:]]*#\\+begin_.+?\\)\\(?: .*\\)*$" nil nil 1)
		   (setq block-start (match-string-no-properties 0))
		   (setq block-end (replace-regexp-in-string
				    "begin_" "end_" ;Replaces "begin_" with "end_", "BEGIN_" with "END_"
				    (match-string-no-properties 1))))
		 ;; Go to the end of current line, if not at the BOL
		 (unless at-bol
		   (end-of-line 1))
		 (insert (concat (if at-bol "" "\n")
				 block-end
				 "\n\n"
				 block-start
				 (if at-bol "\n" "")))
		 ;; Go to the line before the inserted "#+begin_ .." line
		 (beginning-of-line (if at-bol -1 0)))))
	 (message "Point is not in an Org block")))

Split if in an org block, add this as an advice to org-meta-return:

   (defun my/org-meta-return-advice (&rest args)
     "Do not call the original function if point is in an Org block."
     (let ((do-not-run-orig-fn (my/org-in-any-block-p)))
	 (when do-not-run-orig-fn
	   (my/org-split-block))
	 do-not-run-orig-fn))
   (advice-add 'org-meta-return :before-until #'my/org-meta-return-advice)

The agenda stuff

Function to print the current agenda view:

    (defun my/print-agenda (bool)
      (interactive
	(list (y-or-n-p "Print the current agenda view ? ")))
      (cond (bool
	      (org-agenda-write "~/file.ps")
	      (async-shell-command "lp ~/file.ps"))))

Org agenda exporter settings

 (setq org-agenda-exporter-settings
	   '((ps-print-color-p 'black-white)
	     (htmlize-output-type 'css)))

Org bullets

(require 'org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))

Org books

Give rating to book:

 (defun my/org-books-rate-book (position rating)
   "Apply RATING to book at given POSITION."
   (interactive "d\nnRating (stars 1-5): ")
   (if (> rating 0)
	   (org-set-property "RATING" (s-repeat rating ""))))

Custom faces

(custom-set-faces
 '(org-block ((t (:height 1.1)))))

Presentations

zpresent is what I use for presentations

(require 'ox-reveal)

(setq org-reveal-root "file:///home/mo/code/reveal.js")

This needs xwidget support

(require 'bodil-revealjs)

Development

Javascript

(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))

Allow not ending with semi-colon

(setq js2-strict-missing-semi-warning nil)

Common Lisp

set inferior lisp program.

 (setq inferior-lisp-program "sbcl"
	   slime-contribs '(slime-fancy))

CL hook:

 (add-hook 'lisp-mode-hook (lambda ()
				(paredit-mode)))

Python

I’m a heavy python user, but my config is less than 2 instructions, which is great since elpy offers tons of things out of the box

(elpy-enable)

(setenv "WORKON_HOME" "/home/mo/.virtualenvs/")

C

Cflow

(autoload 'cflow-mode "cflow-mode")
(setq auto-mode-alist (append auto-mode-alist
				    '(("\\.cflow$" . cflow-mode))))

C++

Setting compile command and recompile key

(add-hook 'c++-mode-hook (lambda ()
                          (when (buffer-file-name)
                            (setq compile-command (concat "g++ -g " (buffer-file-name))))))
(define-key c++-mode-map (kbd "C-c C-r") 'recompile)

Clojure

(add-hook 'clojure-mode-hook (lambda ()
				    (paredit-mode)))

Web dev

I mainly do vuejs, I use ES6, but I use js-mode not js2-mode since MMM-mode doesn’t seem to support it.

(require 'vue-mode)
(require 'emmet-mode)
(require 'web-mode)

(setq js-indent-level 2)

(add-hook 'vue-mode-hook 'emmet-mode)
(add-hook 'css-mode-hook 'emmet-mode)
(add-hook 'web-mode-hook 'emmet-mode)

(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))

Elisp

Enable show-paren and paredit for Emacs lisp code

(add-hook 'emacs-lisp-mode-hook (lambda ()
                                  (show-paren-mode 1)
                                  (paredit-mode 1)))

Pomodoro

I use the pomodoro technique when working on writing or programming projects

(require 'pomodoro) 
(pomodoro-add-to-mode-line)

Prettify symbols

Some stuff to prettify

Prog-mode

  (global-prettify-symbols-mode 1)
  (add-hook 'prog-mode-hook
	       (lambda ()
		 (push '("!="      . ?≠) prettify-symbols-alist)
		 (push '("<="      . ?≤) prettify-symbols-alist)
		 (push '(">="      . ?≥) prettify-symbols-alist)
		 (push '("alpha"   . ) prettify-symbols-alist)
		 (push '("beta"    . ) prettify-symbols-alist)
		 (push '("gamma"   . ) prettify-symbols-alist)
		 (push '("delta"   . ) prettify-symbols-alist)
		 (push '("epsilon" . ) prettify-symbols-alist)
		 (push '("theta"   . ) prettify-symbols-alist)
		 (push '("pi"      . ) prettify-symbols-alist)
		 (push '("sqrt"    . ?√) prettify-symbols-alist)))

Python-mode

  (add-hook 'python-mode-hook
	       (lambda ()
		 (electric-pair-mode 1)
		 (push '("def" . ) prettify-symbols-alist)
		 (push '("sum" . ?∑) prettify-symbols-alist)
		 (push '("**2" . ) prettify-symbols-alist)
		 (push '("**3" . ) prettify-symbols-alist)))

Unprettify at point

(setq prettify-symbols-unprettify-at-point t)

Projectile

(require 'projectile)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(projectile-mode 1)    

use grep only on files tracked by git

(setq projectile-use-git-grep nil)

enable counsel-projectile

(require 'counsel-projectile)
(counsel-projectile-mode 1)

Elfeed

(require 'elfeed)

(load-file (expand-file-name "~/feeds.el"))

set default search filter

(setq  elfeed-search-filter "@1-week-ago +unread")

Magit

I use magit and magithub to work with github

(require 'magit)
;; (require 'magithub)
(global-set-key (kbd "C-x g") 'magit-status)
;; (magithub-feature-autoinject t)
(put 'magit-clean 'disabled nil)

(global-set-key (kbd "<f12>") 'menu-bar-mode)

This needs github’s hub installed.

Images

(require 'image+)

hydra stuff

  (eval-after-load 'image+
    `(when (require 'hydra nil t)
	 (defhydra imagex-sticky-binding (global-map "C-x C-l")
	   "Manipulating Image"
	   ("+" imagex-sticky-zoom-in "zoom in")
	   ("-" imagex-sticky-zoom-out "zoom out")
	   ("M" imagex-sticky-maximize "maximize")
	   ("O" imagex-sticky-restore-original "restore original")
	   ("S" imagex-sticky-save-image "save file")
	   ("r" imagex-sticky-rotate-right "rotate right")
	   ("l" imagex-sticky-rotate-left "rotate left"))))
(imagex-global-sticky-mode 1)

Study

Nov.el

Used to do read files

(require 'nov)
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))

Change font

 (defun my-nov-font-setup ()
   (face-remap-add-relative 'variable-pitch :height 123
				:family "DejaVu Sans Mono"))
 (add-hook 'nov-mode-hook 'my-nov-font-setup)

org-pdfview stuff

(require 'org-pdfview)
 (define-key pdf-view-mode-map
   (kbd "C-c C-e") (lambda ()
			 (interactive)
			 (setq link (plist-get (org-pdfview-store-link) :link))
			 (let ((win (get-window-with-predicate
				     (lambda (window)
				       (with-current-buffer (window-buffer window)
					 (eq major-mode 'org-mode))))))

			   (if win
			       (progn
				 (select-window win)
				 (org-insert-link link link))))))

W3m

Set default search engine

(setq w3m-search-default-engine "duckduckgo")

Key chord

First require key chord

(require 'key-chord)
(key-chord-mode +1)

Switch to previous buffer

from bbatsov’s blog

(defun switch-to-previous-buffer ()
  "Switch to previously open buffer.
Repeated invocations toggle between the two most recently open buffers."
  (interactive)
  (switch-to-buffer (other-buffer (current-buffer) 1)))

(key-chord-define-global "JJ" 'switch-to-previous-buffer)

Find file

(key-chord-define-global "FF" #'counsel-find-file)

Beginning and end of buffer

(key-chord-define-global "jk" 'beginning-of-buffer)
(key-chord-define-global "JK" 'end-of-buffer)

Ace-jump

(key-chord-define-global "jj" 'ace-jump-mode)

Other

Increment and decrements numbers

Functions to replicate the Vim feature to increment and decrement number at point.

(defun number-at-point (fn)
  (skip-chars-backward "0-9")
  (or (looking-at "[0-9]+")
      (error "No number at point"))
  (replace-match (number-to-string (funcall fn (string-to-number (match-string 0))))))

(defun increment-number-at-point()
  (interactive)
  (number-at-point '1+))

(defun decrement-number-at-point()
  (interactive)
  (number-at-point '1-))


(global-set-key (kbd "C-c +") 'increment-number-at-point)
(global-set-key (kbd "C-c -") 'decrement-number-at-point)

To “zoom” in and out using mouse

Sometimes I like to use my mouse for stuff

(global-set-key [C-mouse-4] 'text-scale-increase)
(global-set-key [C-mouse-5] 'text-scale-decrease)

Resize window interactively

Resize windows in speed, I use resize-window it is not position aware, meaning if I’m in the bottom most window it isn’t as natural as if resize from the left most window, this happens also in i3wm so I think it’s normal, also I don’t think it’s hard to implement so I would love to see this feature.

(require 'resize-window)
(global-set-key (kbd "C-c ;") 'resize-window)

Winner

This just returns to the previous window configuration, sadly it doesn’t work as excepted when using perspective mode, I hope it gets fixed though

(winner-mode 1)

yas

(yas-global-mode 1)

expand region

This package is very helpful to navigate code, it’s most helpful in languages that use S-expressions which are mainly lisps, but it also works with C and Javascript

(require 'expand-region)
(global-set-key (kbd "C-c =") 'er/expand-region)

ace-jump mode

(require 'ace-jump-mode)
(define-key global-map (kbd "C-c SPC") 'ace-jump-mode)
(define-key global-map (kbd "C-x SPC") 'ace-jump-mode-pop-mark)

Recreate scratch buffer

just recreates scratch buffer when it’s killed, I got this from the EmacsWiki

(with-current-buffer "*scratch*"
  (lisp-interaction-mode)
  (make-local-variable 'kill-buffer-query-functions)
  (add-hook 'kill-buffer-query-functions 'kill-scratch-buffer))

(defun kill-scratch-buffer ()
  ;; The next line is just in case someone calls this manually
  (set-buffer (get-buffer-create "*scratch*"))
  ;; Kill the current (*scratch*) buffer
  (remove-hook 'kill-buffer-query-functions 'kill-scratch-buffer)
  (kill-buffer (current-buffer))
  ;; Make a brand new *scratch* buffer
  (set-buffer (get-buffer-create "*scratch*"))
  (lisp-interaction-mode)
  (make-local-variable 'kill-buffer-query-functions)
  (add-hook 'kill-buffer-query-functions 'kill-scratch-buffer)
  ;; Since we killed it, don't let caller do that.
  nil)

Backups

Save backups in another directory

(setq backup-directory-alist '(("." . "~/.emacs.d/backup"))
      backup-by-copying t    ; Don't delink hardlinks
      version-control t      ; Use version numbers on backups
      delete-old-versions t  ; Automatically delete excess backups
      kept-new-versions 20   ; how many of the newest versions to keep
      kept-old-versions 5    ; and how many of the old
      )

Web browser

sets my default web browser

(setq browse-url-browser-function 'w3m-browse-url)

Smarter beginning of line

I got this from sacha chua’s config which she got from crux package I think

(defun my/smarter-move-beginning-of-line (arg)
  "Move point back to indentation of beginning of line.

Move point to the first non-whitespace character on this line.
If point is already there, move to the beginning of the line.
Effectively toggle between the first non-whitespace character and
the beginning of the line.

If ARG is not nil or 1, move forward ARG - 1 lines first.  If
point reaches the beginning or end of the buffer, stop there."
  (interactive "^p")
  (setq arg (or arg 1))

  ;; Move lines first
  (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))))

;; remap C-a to `smarter-move-beginning-of-line'
(global-set-key [remap move-beginning-of-line]
                'my/smarter-move-beginning-of-line)

Add timestamp

Adds timestamp before saving each file

(add-hook 'before-save-hook 'time-stamp)

Tramp sudo edit

Use tramp to edit files with root, I got this from bbatsov blog

(defun sudo-edit (&optional arg)
  "Edit currently visited file as root.
With a prefix ARG prompt for a file to visit.
Will also prompt for a file to visit if current
buffer is not visiting a file."
  (interactive "P")
  (if (or arg (not buffer-file-name))
      (find-file (concat "/sudo:root@localhost:"
                         (ido-read-file-name "Find file(as root): ")))
    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))

Company mode

(require 'company)
(add-hook 'after-init-hook 'global-company-mode)

Terminal stuff

Stuff I use when I run Emacs in a terminal emulator

(define-key input-decode-map "\e[1;2A" [S-up])
(define-key input-decode-map "\e[1;2B" [S-down])
;; xclip
(require 'xclip)
(xclip-mode 1)
;; let the terminal decide the background color
(custom-set-faces (if (not window-system) '(default ((t (:background "nil"))))))
;; to avoid delay in terminal
(setq-default xterm-query-timeout nil)

This needs xclip installed on the machine to facilitate copying and pasting between Emacs and other X windows.

Scratch message

(setq initial-scratch-message ";; ╔═╗┌─┐┬─┐┌─┐┌┬┐┌─┐┬ ┬\n;; ╚═╗│  ├┬┘├─┤ │ │  ├─┤\n;; ╚═╝└─┘┴└─┴ ┴ ┴ └─┘┴ ┴\n\n")
(setq inhibit-startup-screen t)

Proced

auto update proced

(defun proced-settings ()
  (proced-toggle-auto-update 1))

Hide some minor modes

Hide some minor modes

   (defvar hidden-minor-modes

     '(flycheck-mode
	 flyspell-mode
	 highlight-parentheses-mode
	 paredit-mode
	 auto-revert-mode
	 which-key-mode
	 abbrev-mode
	 visual-line-mode
	 emmet-mode
	 mmm-mode
	 highlight-indentation-mode
	 elpy-mode
	 projectile-mode
	 dired-async-mode
	 ivy-mode))

   (defun purge-minor-modes ()
     (interactive)
     (dolist (x hidden-minor-modes nil)
	 (diminish x)))

   (add-hook 'after-change-major-mode-hook 'purge-minor-modes)

ace-window

This is like ace-jump but for windows

(require 'ace-window)
(global-set-key (kbd "C-x o") 'ace-window)

set scope to frame

(setq aw-scope 'frame)

Flycheck

(require 'flycheck)
(global-flycheck-mode 1)

require engine-search

Some other packages I require

(require 'engine-search)

Windmove

(global-set-key (kbd "S-<up>") 'windmove-up)
(global-set-key (kbd "S-<down>") 'windmove-down)
(global-set-key (kbd "S-<left>") 'windmove-left)
(global-set-key (kbd "S-<right>") 'windmove-right)

Startup

(switch-to-buffer "*scratch*")

Tea

Timer code for brewing my tea.

(require 'tea-time)
(setq tea-time-sound-command "espeak  \"Your tea is ready\"")
(setq tea-time-sound t)
(define-key global-map "\C-ct" 'tea-time)

Multi term

This will toggle and select a dedicated multi term buffer.

(global-set-key (kbd "C-c x") (lambda ()
                                (interactive)
                                (require 'multi-term)
                                (multi-term-dedicated-toggle)
                                (multi-term-dedicated-select)))

Add term-line-mode and char-line-mode keybindings

(eval-after-load 'multi-term
  `(setq term-bind-key-alist
	      (cons '("C-c C-z" . term-stop-subjob)
		    (cons '("C-c C-k" . term-char-mode)
			  (cons '("C-c C-l" . term-line-mode) term-bind-key-alist)))))

Cursor stuff

(blink-cursor-mode t)
(setq-default cursor-type 'box)

Flip theme function

I use a light theme in the morning with colors and all because I work besides my window and it’s always sunny where I live so a dark color scheme is not good for my eyes.

In the evening I just use a dark theme like most people do

   (defvar *last-theme* dark-theme
     "The last recorded theme")

   (defun flip-theme ()
     (interactive)
     (if (eq light-theme *last-theme*)
	   (progn
	     (setq *last-theme* dark-theme)
	     (disable-theme light-theme)
	     (load-theme dark-theme)
	     (custom-set-faces
	    '(default ((t (:height 113 :stipple nil :background nil :foreground nil :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :width normal :family "DejaVu Sans Mono"))))))
	 (progn
	   (disable-theme dark-theme)
	   (custom-set-faces
	    '(default ((t (:height 113 :stipple nil :background nil :foreground nil :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :width normal :family "DejaVu Sans Mono")))))
	   (setq *last-theme* light-theme)
	   (load-theme light-theme))))

Paredit stuff

(define-key paredit-mode-map (kbd "{") 'paredit-open-curly)

Hl line mode

(global-hl-line-mode 1)

Enable pdf-tools

This replaces docview, it has faster rendering capabilities.

(pdf-tools-install)

midnight colors

(setq pdf-view-midnight-colors '("#5B4636" . "#F4ECD8"))

Make prompts y or n

(fset 'yes-or-no-p 'y-or-n-p)

Setting the executable directory for gtags

(setq ggtags-executable-directory "/usr/bin")

Display current time

(defun get-current-time ()
  (interactive)
  (message (format-time-string "%H:%M %b %d %a")))

Mitigate slow next-line

(setq auto-window-vscroll nil)

Enable ggtags mode

  (add-hook 'c-mode-common-hook
	       (lambda ()
		 (when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
		   (ggtags-mode 1))))

Pinentry

(setq epa-pinentry-mode 'loopback)