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
.
(setq user-full-name "Mohamed Aziz Knani"
user-mail-address "[email protected]")
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 settings
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
(load custom-file))
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-to-list 'load-path
(expand-file-name "lisp" user-emacs-directory))
(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
(require 'beacon)
(beacon-mode +1)
Doom mode-line
(require 'doom-modeline)
(doom-modeline-mode t)
(require 'doom-themes)
(load-theme 'doom-one t)
;; (doom-themes-visual-bell-config)
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)
(require 'dired)
(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)
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)))
Dired uses the ls program from GNU coreutils to get stuff, so you can do this
(setq dired-listing-switches "-lah")
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)))))))))))
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))
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)))
I like using dired async
(require 'dired-async)
(dired-async-mode 1)
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 like dwim and dired-fixups
(require 'dired-fixups)
(setq dired-dwim-target t)
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"))))
(require 'erc-desktop-notifications)
(erc-smiley-enable)
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.")))
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)
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)))))))))
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)
(add-hook 'mu4e-compose-mode-hook (lambda ()
(flyspell-mode)))
(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)))
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
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)
This happens with gmail and offlineimap
(setq mu4e-headers-skip-duplicates t)
(global-set-key [(f5)] 'mu4e)
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 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))))))
I know this exists thanks to Pierre Neidhardt
email apparently this was added in version 5.
(setq emms-browser-covers #'emms-browser-cache-thumbnail)
(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
(setq org-confirm-babel-evaluate nil)
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"))
(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)
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)))
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)
auto crypt org files using EasyPG
(require 'org-crypt)
(org-crypt-use-before-save-magic)
Add org-habit
(add-to-list 'org-modules 'org-habit)
(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 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"))
Set org contact files
(require 'org-contacts)
(setq org-contacts-files `(,(concat org-directory "/people.org")))
org-contacts-files
set org
(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"))
(setq org-passwords-file (concat org-directory "/passwords.org.gpg"))
- Note taken on [2018-08-24 Fri 23:15]
Copied from https://scripter.co/splitting-an-org-block-into-two/
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)
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)))
(require 'org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
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-set-faces
'(org-block ((t (:height 1.1)))))
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)
(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
Allow not ending with semi-colon
(setq js2-strict-missing-semi-warning nil)
set inferior lisp program.
(setq inferior-lisp-program "sbcl"
slime-contribs '(slime-fancy))
CL hook:
(add-hook 'lisp-mode-hook (lambda ()
(paredit-mode)))
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/")
(autoload 'cflow-mode "cflow-mode")
(setq auto-mode-alist (append auto-mode-alist
'(("\\.cflow$" . cflow-mode))))
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)
(add-hook 'clojure-mode-hook (lambda ()
(paredit-mode)))
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))
Enable show-paren and paredit for Emacs lisp code
(add-hook 'emacs-lisp-mode-hook (lambda ()
(show-paren-mode 1)
(paredit-mode 1)))
I use the pomodoro technique when working on writing or programming projects
(require 'pomodoro)
(pomodoro-add-to-mode-line)
Some stuff to prettify
(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)))
(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)))
(setq prettify-symbols-unprettify-at-point t)
(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)
(require 'elfeed)
(load-file (expand-file-name "~/feeds.el"))
set default search filter
(setq elfeed-search-filter "@1-week-ago +unread")
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.
(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)
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)
(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))))))
(setq w3m-search-default-engine "duckduckgo")
First require key chord
(require 'key-chord)
(key-chord-mode +1)
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)
(key-chord-define-global "FF" #'counsel-find-file)
(key-chord-define-global "jk" 'beginning-of-buffer)
(key-chord-define-global "JK" 'end-of-buffer)
(key-chord-define-global "jj" 'ace-jump-mode)
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)
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 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)
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-global-mode 1)
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)
(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)
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)
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
)
sets my default web browser
(setq browse-url-browser-function 'w3m-browse-url)
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)
Adds timestamp before saving each file
(add-hook 'before-save-hook 'time-stamp)
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))))
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
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.
(setq initial-scratch-message ";; ╔═╗┌─┐┬─┐┌─┐┌┬┐┌─┐┬ ┬\n;; ╚═╗│ ├┬┘├─┤ │ │ ├─┤\n;; ╚═╝└─┘┴└─┴ ┴ ┴ └─┘┴ ┴\n\n")
(setq inhibit-startup-screen t)
auto update proced
(defun proced-settings ()
(proced-toggle-auto-update 1))
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)
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)
(require 'flycheck)
(global-flycheck-mode 1)
Some other packages I require
(require 'engine-search)
(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)
(switch-to-buffer "*scratch*")
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)
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)))))
(blink-cursor-mode t)
(setq-default cursor-type 'box)
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))))
(define-key paredit-mode-map (kbd "{") 'paredit-open-curly)
(global-hl-line-mode 1)
This replaces docview, it has faster rendering capabilities.
(pdf-tools-install)
midnight colors
(setq pdf-view-midnight-colors '("#5B4636" . "#F4ECD8"))
(fset 'yes-or-no-p 'y-or-n-p)
(setq ggtags-executable-directory "/usr/bin")
(defun get-current-time ()
(interactive)
(message (format-time-string "%H:%M %b %d %a")))
(setq auto-window-vscroll nil)
(add-hook 'c-mode-common-hook
(lambda ()
(when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
(ggtags-mode 1))))
(setq epa-pinentry-mode 'loopback)