Skip to content

Latest commit

 

History

History
418 lines (368 loc) · 13.5 KB

init.el.org

File metadata and controls

418 lines (368 loc) · 13.5 KB

initialization

to do

leverage use-package’s :hook parameter

info.

the inspiration for trying an org-mode literate Emacs file came from here: https://github.com/r0man/.emacs.d

this is an opinionated yet minimal setup for someone who wants to try using Emacs for writing OCaml or ReasonML code. One defining characteristic of this project is the fact that it works with Merlin from both opam and reason-cli, and it chooses the version based off of the type of file.

note: this could cause an issue for people who write bucklescript, as that code will be checked against opam’s merlin and not the one from reason-cli. I am unsure of how to tell the difference between bucklescript and ocaml code programmatically.

to use this you must:

  1. install merlin and ocp-indent: opam install merlin ocp-indent
  2. install reason-cli via npm/yarn: npm install -g reason-cli@3.1.0-linux or npm install -g reason-cli@3.1.0-darwin

setup

keybindings

KeybindingModuleFunction
C-h khelpdescribe-key
M-<right>auto-highlight-symbolnext occurrence
M-<left>helmprevious occurrence
C-c bhelmhelm-filtered-bookmarks
C-x C-fhelmhelm-find-files
C-x fhelmhelm-find-files
C-x bhelmhelm-mini
C-x C-bhelmhelm-buffers-list
C-h fhelmhelm-apropos
C-h rhelmhelm-info-emacs
C-h C-lhelmhelm-locate-library
C-c fhelmhelm-recentf
C-h SPChelmhelm-all-mark-rings
C-c h xhelmhelm-register
M-yhelmhelm-show-kill-ring
M-xhelmhelm-M-x
C-c C-lhelmhelm-minibuffer-history
C-shelm-swoophelm-swoop-without-pre-input
C-rhelm-swoophelm-previous-line
C-shelm-swoophelm-next-line
M-.merlinmerlin-locate
M-,merlinmerlin-pop-stack
C-c C-omerlinmerlin-occurrences
C-c C-jmerlinmerlin-jump
C-c imerlinmerlin-locate-ident
C-c C-emerlinmerlin-edit-occurrences

main

use Common Lisp features in Emacs Lisp.

(eval-when-compile 
  (require 'cl)
  (require 'cl-lib))

make it so that (,{,[, and ” are auto paired.

(electric-pair-mode t)

make the highlighting/region selected easier to see.

(set-face-attribute 'region nil :background "green")

make the default yes/no y/n instead

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

make elisp bearable

(if (fboundp 'paren-set-mode)
    (paren-set-mode 'sexp)
  (defvar show-paren-style)
  (setq show-paren-style 'expression)
  (show-paren-mode t))
(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)

use utf-8 everywhere!

(prefer-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8)
(setq buffer-file-coding-system 'utf-8)

two performance speedups

  1. https://emacs.stackexchange.com/questions/28736/emacs-pointcursor-movement-lag/28746
  2. https://www.reddit.com/r/emacs/comments/2dgy52/how_to_stop_emacs_automatically_recentering_the/
(setq auto-window-vscroll nil)
(setq scroll-step 1)

make it so that links in Emacs are clickable

(define-globalized-minor-mode global-goto-address-mode goto-address-mode goto-address-mode)
(global-goto-address-mode)

automatically maximize the Emacs window

(add-to-list 'default-frame-alist '(fullscreen . maximized))

use secure defaults

(setq network-security-level 'high)

font-lock is enabled by default, but make sure it is globally applied

(global-font-lock-mode 1)

this turns certain symbols into fonts (lambda -> λ)

(global-prettify-symbols-mode 1)

change the window title to something useful

(setq frame-title-format '(buffer-file-name "%f" "%b"))

turn of the ring-bell functionality

(setq ring-bell-function 'ignore)

text

start wrapping at 80 for text files

(use-package auto-dictionary
  :ensure t
  :init (add-hook 'flyspell-mode-hook (lambda () (auto-dictionary-mode 1))))
(add-hook 'text-mode-hook
	  '(lambda()
	     (turn-on-auto-fill)
	     (set-fill-column 80)
	     (setq-default auto-fill-function 'do-auto-fill)))

use a dictionary! enable flyspell in text mode

(defun enable-flyspell-mode ()
  "Enable Flyspell mode."
  (flyspell-mode 1))

(dolist (hook '(text-mode-hook))
  (add-hook hook 'enable-flyspell-mode))

enable flyspell in programming mode

(defun enable-flyspell-prog-mode ()
  "Enable Flyspell Programming mode."
  (flyspell-prog-mode))

(dolist (hook '(prog-mode-hook))
  (add-hook hook 'enable-flyspell-prog-mode))

don’t print messages when checking words.

(setq flyspell-issue-message-flag nil)

org-mode

use sane defaults for org-mode follow 80-character word-wrap rule also allow for highlighting languages within org-mode using org-babel

  (use-package org
    :ensure t
    :defer 1
    :mode ("\\.org\\'" . org-mode)     
    :config
    (add-hook 'org-mode-hook
	    '(lambda()
	       (turn-on-auto-fill)
	       (set-fill-column 80)
	       (setq-default auto-fill-function 'do-auto-fill)))
    (require 'ob-clojure)
    (setq org-babel-clojure-backend 'cider)
    (setq org-src-fontify-natively t)
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((clojure . t)
       (lisp . t)
	(emacs-lisp . t)
	(haskell . t)
	(latex . t)
	(ledger . t)
	(ocaml . t)
	(python . t)
	(sh . t)
	(sql . t))))

path

automatically get the path for binaries on the current system

 (if (string-equal system-type "windows-nt")
     (progn
	 (setenv "PATH" (concat
			 "C:\\Program Files\\Git\\usr\\bin" ";" ;; Unix tools
			 (getenv "PATH"))))
   (progn
     (use-package exec-path-from-shell
	 :ensure t
	 :config
	 (when (memq window-system '(mac ns x))
	   (exec-path-from-shell-initialize)))))

helm

setup helm and make the global keybindings also setup helm-swoop

(use-package helm
  :ensure t
  :config
  (helm-mode 1)
  (helm-popup-tip-mode 1)
  (helm-autoresize-mode t)
  (setq helm-autoresize-min-height 40)

  (setq helm-M-x-fuzzy-match t)
  (setq helm-buffers-fuzzy-matching t)
  (setq helm-recentf-fuzzy-match t)
  (setq helm-lisp-fuzzy-completion t)

  (setq helm-mini-default-sources '(helm-source-buffers-list
                                    helm-source-recentf
                                    helm-source-bookmarks
                                    helm-source-buffer-not-found))


  (require 'helm-eshell)
  (add-hook 'eshell-mode-hook
	       #'(lambda ()
		   (define-key eshell-mode-map (kbd "M-l")  'helm-eshell-history)))


  ;; (define-key helm-map (kbd "<return>") 'helm-execute-persistent-action)
  ;; (global-set-key (kbd "C-s") #'helm-occur) ; using helm-swoop now
  (global-set-key (kbd "C-c b") #'helm-filtered-bookmarks)
  (global-set-key (kbd "C-c C-b") #'helm-filtered-bookmarks) ; because I am an idiot
  (global-set-key (kbd "C-x C-f") #'helm-find-files)
  (global-set-key (kbd "C-x b") #'helm-mini)
  (global-set-key (kbd "C-x C-b") 'helm-buffers-list)
  (global-set-key (kbd "C-h f") 'helm-apropos)
  (global-set-key (kbd "C-h r") 'helm-info-emacs)
  (global-set-key (kbd "C-h C-l") 'helm-locate-library)
  (global-set-key (kbd "C-c f") 'helm-recentf)
  (global-set-key (kbd "C-h SPC") 'helm-all-mark-rings)
  (global-set-key (kbd "C-c h x") 'helm-register)

  (global-set-key (kbd "M-y") 'helm-show-kill-ring)
  (global-set-key (kbd "M-x") #'helm-M-x)

  (define-key minibuffer-local-map (kbd "C-c C-l") 'helm-minibuffer-history)

  (define-key helm-map [backspace] #'backward-kill-word))

(use-package helm-swoop
  :ensure t
  :config
  (global-set-key (kbd "C-s") 'helm-swoop-without-pre-input)
  (define-key helm-swoop-map (kbd "C-r") 'helm-previous-line)
  (define-key helm-swoop-map (kbd "C-s") 'helm-next-line))

company

use company-mode (not auto-complete) for text-completion

(use-package company
  :ensure t
  :config
  (add-hook 'prog-mode-hook 'company-mode)
  (setq company-dabbrev-downcase 0)
  (setq company-idle-delay 0))

(use-package company-quickhelp
  :ensure t
  :config
  (company-quickhelp-mode 1)
  (define-key company-active-map (kbd "C-c h") #'company-quickhelp-manual-begin))

ml

ocaml

remember that ocp-indent has to be installed via opam!

(let ((opam-share (ignore-errors (car (process-lines "opam" "config" "var" "share")))))
  (when (and opam-share (file-directory-p opam-share))
    (add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share))))

(use-package ocp-indent)

(use-package tuareg
  :ensure t
  :config
  (add-hook 'before-save-hook 'ocp-indent-buffer nil t)
  (setq auto-mode-alist 
	   (append '(("\\.ml[ily]?$" . tuareg-mode)
		     ("\\.topml$" . tuareg-mode))
		   auto-mode-alist)))

reasonml

setup reasonml support and allow for setting merlin-commmand to the reason-cli merlin

  (defun shell-cmd (cmd)
    "Returns the stdout output of a shell command or nil if the command returned
     an error"
    (car (ignore-errors (apply 'process-lines (split-string cmd)))))

  (quelpa '(reason-mode :repo "reasonml-editor/reason-mode" :fetcher github :stable t))
  (use-package reason-mode
    :config
    (let* ((refmt-bin (shell-cmd "which refmt")))
      (when refmt-bin
	 (setq refmt-command refmt-bin)))
    (add-hook
     'reason-mode-hook
     (lambda ()
	(add-hook 'before-save-hook 'refmt-before-save nil t)
	(setq-local merlin-command (shell-cmd "which ocamlmerlin"))
	(merlin-mode))))

merlin

setup merlin to default to opam and add hooks for reason/tuareg/caml-mode

(use-package merlin
  :custom
  (merlin-command 'opam)
  (merlin-completion-with-doc t)
  (company-quickhelp-mode t)
  :config
  (autoload 'merlin-mode "merlin" nil t nil)
  :bind (:map merlin-mode-map
		 ("M-." . merlin-locate)
		 ("M-," . merlin-pop-stack)
		 ("C-c C-o" . merlin-occurrences)
		 ("C-c C-j" . merlin-jump)
		 ("C-c i" . merlin-locate-ident)
		 ("C-c C-e" . merlin-iedit-occurrences))
  :hook
  ;; Start merlin on ml files
  (reason-mode . merlin-mode)
  (tuareg-mode . merlin-mode)
  (caml-mode-hook . merlin-mode))

utop

dynamically choose utop version (opam’s vs reason-cli’s) based on buffer

(defun reason/rtop-prompt ()
  "The rtop prompt function."
  (let ((prompt (format "rtop[%d]> " utop-command-number)))
    (add-text-properties 0 (length prompt) '(face utop-prompt) prompt)
    prompt))

(use-package utop
  :config
  (autoload 'utop "utop" "Toplevel for OCaml" t)
  (autoload 'utop-minor-mode "utop" "Minor mode for utop" t)
  (defun utop-opam-utop () (progn
				(setq-local utop-command "opam config exec -- utop -emacs")
				utop-minor-mode))
  (defun utop-reason-cli-rtop () (progn
					(setq-local utop-command (concat (shell-cmd "which rtop") " -emacs"))
					(setq-local utop-prompt 'reason/rtop-prompt)
					utop-minor-mode))
  :hook
  (tuareg-mode . utop-opam-utop)
  (reason-mode . utop-reason-cli-rtop))

flycheck

right now flycheck-ocaml only supports ocaml, but hopefully it will be extended to reason as well

(use-package flycheck
  :ensure t
  :config
  (global-flycheck-mode))

(use-package flycheck-popup-tip
  :ensure t
  :config
  (flycheck-popup-tip-mode))

(use-package flycheck-ocaml
  :ensure t
  :config
  (add-hook 'tuareg-mode-hook
	       (lambda ()
		 ;; disable Merlin's own error checking
		 (setq-local merlin-error-after-save nil)    
		 ;; enable Flycheck checker
		 (flycheck-ocaml-setup))))