Mohamed Aziz Knani configuration file

Table of Contents

1 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 bbastov'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.

2 Initialize

2.1 Personal Information

(setq user-full-name "Mohamed Aziz Knani"
  user-mail-address "medazizknani@gmail.com")

2.2 Package sources

Initialize package

(require 'package)
(package-initialize)

If the system has gnutls use ssl.

(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))))

2.3 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))

2.4 Look and feel

Define themes

(defconst dark-theme 'tao-yin)
(defconst light-theme 'leuven)
(tool-bar-mode   0)
(menu-bar-mode   0)

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

(add-hook 'after-init-hook (lambda ()
                             (load-theme dark-theme)))

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


Set no-fringes mode

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

2.5 Add load paths

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

3 Helm

Enable helm

(require 'helm)
(helm-mode 1)

Add some keybindings for helm.

(global-set-key (kbd "M-x") #'helm-M-x)
(global-set-key (kbd "C-x r b") #'helm-filtered-bookmarks)
(global-set-key (kbd "C-x C-f") #'helm-find-files)

show kill ring keybinding

(global-set-key (kbd "C-c y") '(lambda ()
                                 (interactive)
                                 (helm-show-kill-ring)))

4 Dired

(require 'dired)

4.1 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)

4.2 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)))

4.3 Switches

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

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

4.4 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)))))))))))

4.5 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))

4.6 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 bbastov 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)))

4.7 Dired async

I like using dired async

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

4.8 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)

4.9 Some other stuff

Some other stuff like dwim and dired-fixups

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

5 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" . ("#python"
                                                           "#python-eve"
                                                           "#pocoo"
                                                           "#emacs"
                                                           "#gnu"
                                                           "#django"
                                                           "#crypto"
                                                           "##programming"))
                                    ("oftc.net" . ("#suckless"
                                                       "#debian"))))

5.1 Hide from mode-line

(erc-track-mode nil)
(setq  erc-track-position-in-mode-line nil
       erc-mode-line-format "")

6 Eshell

6.1 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)

6.2 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)))))))))

7 Email

I use mu4e for Mail

(require 'mu4e)

set the mail directory

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

load file with email configuration

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

set the user email address

(setq mu4e-user-mail-address-list
      (mapcar (lambda (account) (cadr (assq 'user-mail-address account)))
              my/mu4e-account-alist))
(setq mu4e-sent-messages-behavior 'delete)

update mail using offlineimap

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

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)

7.1 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)))

7.2 Offlineimap configuration

This is not Emacs specific but I just wanted to throw it here

here is my .offlineimaprc

  [general]
accounts = Gmail
maxconnections = 3
maxsyncaccounts = 1
pythonfile = ~/.offlineimap.py

[Account Gmail]
localrepository = Local
remoterepository = Remote

[Repository Local]
type = Maildir
localfolders = ~/Maildir

[Repository Remote]
type = Gmail
remoteuser = medazizknani@gmail.com
remotepasseval = get_password_emacs("imap.gmail.com", "medazizknani@gmail.com", "993")
realdelete = no

folderfilter = lambda foldername: foldername not in ['[Gmail]/Spam', '[Gmail].Tous les messages', '[Gmail].Suivis', '[Gmail]/Important']

remotepass = password

holdconnectionopen = true
keepalive = 60
sslcacertfile = /etc/ssl/certs/ca-certificates.crt


[Account MAKCock]
localrepository = LocalCock
remoterepository = RemoteCock

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

[Repository RemoteCock]
type = IMAP
remotehost = mail.cock.li
remoteuser = mak@cock.li
remotepasseval = get_password_emacs("mail.cock.li", "mak@cock.li", "993")
realdelete = no
remotepass = password
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

7.3 Async smtp send function

(require 'smtpmail-async)

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

7.4 Disable duplicates

This happens with gmail and offlineimap

(setq mu4e-headers-skip-duplicates t)

7.5 Multiple mail

I use multiple mail accounts

the code is apdated from here it takes advantage of mu4e contexts

sets the current account and the last read account

(defvar my/mu4e-last-read-account "")
(defvar my/mu4e-current-account nil)

the function that sets accounts

(defun my/mu4e-set-account ()
  "Set the account for composing a message."
  (interactive)
  (let* ((account
          (if mu4e-compose-parent-message
              (let ((maildir (mu4e-message-field mu4e-compose-parent-message :maildir)))
                (string-match "/\\(.*?\\)/" maildir)
                (match-string 1 maildir))
            (completing-read (format "Compose with account: (%s) "
                                     (mapconcat #'(lambda (var) (if (string= (car var) my/mu4e-last-read-account)
                                                               (format "[%s]" (car var))
                                                             (car var)))
                                                my/mu4e-account-alist "/"))
                             (mapcar #'(lambda (var) (car var)) my/mu4e-account-alist)
                             nil t nil nil (caar my/mu4e-account-alist))))
         (account-vars (cdr (assoc account my/mu4e-account-alist))))
    (progn
      (setq my/mu4e-last-read-account account)
      (setq my/mu4e-current-account account-vars)
      (if account-vars
          (mapc #'(lambda (var)
                    (set (car var) (cadr var)))
                account-vars)
        (error "No email account found")))))

This is function insert the signature, I'm not sure why this doesn't happen by default, this is a fast hack, clearly it needs more debugging

(defun my/mu4e-execute-account-vars ()
  "docstring"
  (when my/mu4e-current-account
    (progn
      (mapc #'(lambda (var)
                (set (car var) (cadr var)))
            my/mu4e-current-account))
    (when (string= "*draft*"  (buffer-name))
      (when message-signature
        (message-insert-signature)))))
(add-hook 'mu4e-compose-mode-hook 'my/mu4e-execute-account-vars)

set the keybinding

(global-set-key (kbd "C-x c") 'my/mu4e-set-account)

8 Perspective

I was a heavy GNU screen user, and before that Tmux, well not anymore since I found that I can do that inside Emacs

(require 'perspective)

(setq persp-initial-frame-name "dev")
(persp-mode t)

8.1 Perspectives

This is my perspectives (or virtual desktops)

;; (persp-switch "irc")
(with-perspective "email"
  (mu4e)
  ;; the easy way, feasible also with emacs-async
  (sleep-for 1))

(with-perspective "files"
  (dired "~/"))

(with-perspective "org"
  (org-agenda-list)
  (sleep-for 1)
  (delete-other-windows)
  (switch-to-buffer "*Org Agenda*"))

(with-perspective "eshell"
  (eshell))

(require 'proced)
(with-perspective "proced"
  (proced)
  (delete-other-windows)
  (switch-to-buffer "*Proced*"))

8.2 Show only current perspective

(defun persp-update-modestring ()
  "Update `persp-modestring' to reflect the current perspectives.
Has no effect when `persp-show-modestring' is nil."
  (when persp-show-modestring
    (let ((open (list (nth 0 persp-modestring-dividers)))
          (close (list (nth 1 persp-modestring-dividers)))
          (sep (nth 2 persp-modestring-dividers)))
      (if persp-curr
          (setq persp-modestring
                (append open (list (persp-format-name (persp-name persp-curr)))
                        close))
        (setq persp-modestring nil)))))

9 Music

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

(require 'emms-setup)
(emms-standard)
(emms-default-players)
;; 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")

(define-emms-simple-player mpv '(file url streamlist playlist)
  (concat "\\`\\(http\\|mms\\)://\\|"
          (emms-player-simple-regexp
           "ogg" "mp3" "wav" "mpg" "mpeg" "wmv" "wma"
           "mov" "avi" "divx" "ogm" "ogv" "asf" "mkv"
           "rm" "rmvb" "mp4" "flac" "vob" "m4a" "ape"
           "flv" "webm" "m4b" "m4p" "m4v" "m4r" "3gp"
           "aac" "aiff"))
  "mpv" "--quiet" "--really-quiet")

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

(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/")

I also have this in my mpv configuration

audio-display=no

If someone has an elegant function to resize covers and display it inside emms-browser, I would be very happy if you email it to me.

9.1 Perspective

(with-perspective "music"
  (emms-smart-browse))

9.2 Covers

This piece of code doesn't always work, also I need a way around imagemagick to resize all covers

(defun my-emms-covers (dir type)
  "Choose album cover in DIR deppending on TYPE.
Small cover should be less than 80000 bytes.
Medium - less than 120000 bytes."
  (let* ((pics (directory-files-and-attributes
                dir t "\\.\\(jpe?g\\|png\\|gif\\|bmp\\)$" t))
         (pic (car pics))
         (pic-size (nth 8 pic)))
    (let (temp)
      (cond
       ((eq type 'small)
        (while (setq temp (cadr pics))
          (let ((temp-size (nth 8 temp)))
            (if (< temp-size pic-size)
                (setq pic temp
                      pic-size temp-size)))
          (setq pics (cdr pics)))
        (if (<= (or pic-size 80001) 80000)
            (car pic)))
       ((eq type 'medium)
        (if (and pic (setq temp (cadr pics)))
            (progn
              (setq pics (cdr pics))
              (let ((temp-size (nth 8 temp)))
                (let ((small temp)
                      (small-size temp-size))
                  (if (< pic-size small-size)
                      (setq small pic
                            small-size pic-size
                            pic temp
                            pic-size temp-size))
                  (while (setq temp (cadr pics))
                    (setq temp-size (nth 8 temp))
                    (cond
                     ((< temp-size small-size)
                      (setq pic small
                            pic-size small-size
                            small temp
                            small-size temp-size))
                     ((< temp-size pic-size)
                      (setq pic temp
                            pic-size temp-size)))
                    (setq pics (cdr pics)))
                  (car (if (<= pic-size 120000) pic
                         small)))))
          (car pic)))
       ((eq type 'large)
        (while (setq temp (cadr pics))
          (let ((temp-size (nth 8 temp)))
            (if (> temp-size pic-size)
                (setq pic temp
                      pic-size temp-size)))
          (setq pics (cdr pics)))
        (car pic))))))


(add-hook 'emms-playlist-mode-hook
          (lambda ()
            (setq emms-browser-covers 'my-emms-covers)))

10 Org

(require 'org)

What to record when a task is marked done

(setq org-log-done 'time)

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 'dvisvgm)

For easier math symbols input for latex

10.1 Org-tangle disable confirmation

(setq  org-confirm-babel-evaluate nil)

10.2 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"))

10.3 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)

10.4 org-trello sutff

(require 'org-trello)

(setq org-trello-files
      `(,(concat org-directory "/work.org")))

10.5 C/C++

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

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

10.6 Hylang

(require 'ob-hy)
(org-babel-do-load-languages
 'org-babel-load-languages '((hy . t)))

10.7 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)

10.8 Org crypt

auto crypt org files using EasyPG

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

10.9 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 ,(concat org-directory "/people.org"))
               "* %(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 ,(concat org-directory "/tasks.org"))
               "* TODO %?\n  %i\n  %a"))

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  #+BEGIN_SRC\n%x\n  #+END_SRC\n  %a\n  captured on: %U\n\n"))

10.9.1 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"))

10.10 Org contact

Set org contact files

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

org-contacts-files

set org

10.11 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"))

10.12 Custom faces

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

11 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)

12 Development

12.1 Javascript

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

Allow not ending with semi-colon

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

12.2 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)))

12.3 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/vEnvs/")

12.4 C

12.4.1 Cflow

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

12.5 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)

12.6 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)

12.7 Elisp

Enable show-paren and paredit for Emacs lisp code

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

12.8 Hylang

(require 'hy-mode)
(add-hook 'hy-mode-hook (lambda ()
                          (show-paren-mode 1)
                          (paredit-mode 1)
                          (set (make-local-variable 'company-backends) '(company-hy))))

13 Pomodoro

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

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

14 Prettify symbols

Some stuff to prettify

14.1 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)))

14.2 Python-mode

(add-hook 'python-mode-hook
          (lambda ()
            (push '("def" . ?ƒ) prettify-symbols-alist)
            (push '("sum" . ?∑) prettify-symbols-alist)
            (push '("**2" . ?²) prettify-symbols-alist)
            (push '("**3" . ?³) prettify-symbols-alist)))

14.3 Unprettify at point

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

15 Projectile

(require 'projectile)

(projectile-mode 1)    

use grep only on files tracked by git

(setq projectile-use-git-grep 1)

enable helm-projectile

(require 'helm-projectile)
(helm-projectile-on)

16 Elfeed

(require 'elfeed)

(setq elfeed-feeds
      '("http://nullprogram.com/feed/"
        "http://planet.emacsen.org/atom.xml"
        "http://reddit.com/r/emacs/.rss"
        "http://irreal.org/blog/?feed=rss2"))

17 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.

18 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)

19 Key chord

First require key chord

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

19.1 Switch to previous buffer

from bastov'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)

19.2 Find file

(key-chord-define-global "FF" 'helm-find-files)

19.3 Beginning and end of buffer

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

19.4 Ace-jump

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

20 Other

20.1 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)

20.2 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)

20.3 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)

20.4 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)

20.5 yas

(yas-global-mode 1)

20.6 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)

20.7 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)

20.8 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)

20.9 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
      )

20.10 Web browser

sets my default web browser

(setq browse-url-browser-function 'browse-url-generic
      browse-url-generic-program "icecat")

20.11 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)

20.12 Add timestamp

Adds timestamp before saving each file

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

20.13 Tramp sudo edit

Use tramp to edit files with root, I got this from bbastov 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))))

20.14 Company mode

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

20.15 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.

20.16 Scratch message

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

20.17 Proced

auto update proced

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

20.18 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
    dired-async-mode
    helm-mode))

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

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

20.19 ace-window

This is like ace-jump but for windows

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

styling the leading char

(set-face-attribute 'aw-leading-char-face nil :height 400)

set scope to frame

(setq aw-scope 'frame)

20.20 Flycheck

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

20.21 require engine-search

Some other packages I require

(require 'engine-search)

20.22 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)

20.23 Startup

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

20.24 Tea

Timer code for brewing my tea.

You need the say program (it comes with GNUstep).

(require 'tea-time)
(setq tea-time-sound-command "espeak -vde+f5  \"Es ist teezeit mein Kapitän\"")
(setq tea-time-sound t)
(define-key global-map "\C-ct" 'tea-time)

20.25 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)))))

20.26 Cursor stuff

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

20.27 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))
    (progn
      (disable-theme dark-theme)
      (setq *last-theme* light-theme)
      (load-theme light-theme))))

20.28 Paredit stuff

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

20.29 Hl line mode

(global-hl-line-mode 1)

20.30 Enable pdf-tools

This replaces docview, it has faster rendering capabilities.

(pdf-tools-install)

20.31 Make prompts y or n

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

20.32 Setting the executable directory for gtags

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

Author: Mohamed Aziz Knani

Created: 2018-03-08 Thu 19:16

Validate