Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

Latest commit

 

History

History
1473 lines (1168 loc) · 50.4 KB

startup.org

File metadata and controls

1473 lines (1168 loc) · 50.4 KB

yveszoundi emacs Org startup file.

Startup

Enable/Disable UI modes

Avoid the menubar, scrollbar and cursor blinking.

(defun ers/apply-frame-settings ()
  (dolist (mode '(menu-bar-mode tool-bar-mode scroll-bar-mode blink-cursor-mode))
    (when (fboundp mode) (funcall mode -1)))

  (dolist (mode '(show-paren-mode display-time-mode column-number-mode))
    (when (fboundp mode) (funcall mode 1))))

(ers/apply-frame-settings)

Pre-startup

Setup global functions and constants.

(defconst ers-bootstrap-dir (file-name-directory load-file-name)
  "Emacs Rimero Setup bootstrap folder.")

(defconst ers-emacs-dir (file-name-directory (directory-file-name ers-bootstrap-dir))
  "Emacs Rimero Setup root folder.")

(defconst ers-user-filename "ers-user.el"
  "Emacs Rimero Setup user file.")

(defun ers/mkdir-p (dir-path)
  (unless (file-exists-p dir-path)
    (make-directory dir-path t)))

(defun ers/emacs-sub-dir (path-elements)
  (let ((ers-emacs-sub-folder ers-emacs-dir))
    (cl-loop for p in path-elements
             do (setq ers-emacs-sub-folder (file-name-as-directory (concat ers-emacs-sub-folder p))))
    ers-emacs-sub-folder))

(defvar ers-user-file (concat user-emacs-directory ers-user-filename))

(mapc #'(lambda(p) (add-to-list 'load-path p))
      `( ,(ers/emacs-sub-dir '("vendor"))))

;; packages
(require 'package)

(setq package-archives '(("melpa" . "http://melpa.milkbox.net/packages/")))

(package-initialize)

(unless package-archive-contents
  (package-refresh-contents))

Global variables

Setup customization variables.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; global variables defcustoms
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defgroup emacs-rimero-setup nil
  "Emacs rimero setup group."
  :group 'customize
  :prefix "ers-")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Credentials file for netrc authentication
;; Also symblink .authinfo to .netrc for offlineimap
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-secrets-file "~/.authinfo"
  "Secrets file."
  :type 'string
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; environment variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-env-variables
  '(("JAVA_HOME" . "/usr/lib/jvm/java-7-oracle")
    ("EDITOR"    . "emacsclient")
    ("LC_ALL"    . "C")
    ("LANG"      . "en"))
  "Environment variables."
  :type 'symbol
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Projects
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-projectile-folder "~/.emacs.d/data/projectile"
  "Projectile folder."
  :type 'directory
  :group 'emacs-rimero-setup)

(defcustom ers-projectile-cache-filename "projectile.cache"
  "Projectile Cache filename"
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-projectile-bookmarks-filename "projectile-bookmarks.eld"
  "Projectile Bookmarks filename"
  :type 'string
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; blogging
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar personal-blog-name "wordpress-your-netrc-entry-in-dot-autinfo")
(defvar corporate-blog-name "wordpress-your-netrc-entry-in-dot-autinfo")
(defvar personal-blog-url "http://wordpress-site/xmlrpc.php")
(defvar corporate-blog-url "http://wordpress-site/xmlrpc.php")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; indentation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-tab-size 4
  "Number of spaces for tabs."
  :type 'integer
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ui settings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-ui-font
  (cond ((eq system-type 'windows-nt) "Consolas-10")
        ((eq system-type 'darwin)     "Menlo-12:bold")
        ((eq system-type 'gnu/linux)  "DejaVu Sans Mono-12:bold")
        (t                            "Monospace-12:bold"))
  "Font to use."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-ui-theme nil
  "GUI Theme to use."
  :type 'symbol
  :group 'emacs-rimero-setup)

(defcustom ers-ui-theme-console nil
  "Console theme to use."
  :type 'symbol
  :group 'emacs-rimero-setup)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; spelling
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-spelling-aspell-path "/usr/local/bin/aspell"
  "Aspell location for spell-checking."
  :type 'file
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; personal information
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-pim-mail-address "[email protected]"
  "Email address."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-pim-public-mail-address "[email protected]"
  "Public spam email address used for emacs-lisp snippets."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-pim-full-name "MeFirstname MeLastName"
  "Full name."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-pim-organization "My Company"
  "Organization name."
  :type 'string
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; org-mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-org-directory "~/.emacs.d/data/org/"
  "Org-mode folder."
  :type 'directory
  :group 'emacs-rimero-setup)

(defcustom ers-org-archive-location-filename "archive.org::"
  "Org-mode archive location."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-org-notes-filename "notes.org"
  "Org-mode notes file name."
  :type 'string
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; erc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-erc-server "irc.freenode.net"
  "IRC server to use for erc."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-erc-channel-list '(("freenode.net" "##java" "#emacs"))
  "ERC connection information server and channels."
  :type 'symbol
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; jabber
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-jabber-server "talk.google.com"
  "Jabber server."
  :type 'string
  :group 'emacs-rimero-setup)

(defcustom ers-jabber-port 5223
  "Jabber server port."
  :type 'int
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Files
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-ac-histfile "~/.emacs.d/data/ac-comphist.dat"
  "Auto-complete completion data."
  :type 'file
  :group 'emacs-rimero-setup)

(defcustom ers-recentf-file "~/.emacs.d/data/recentf"
  "Recent file list."
  :type 'file
  :group 'emacs-rimero-setup)

(defcustom ers-max-recent-files 300
  "Max number of recent files."
  :type 'integer
  :group 'emacs-rimero-setup)

(defcustom ers-helm-adaptive-history-file "~/.emacs.d/data/helm-adaptative-history-file"
  "Helm adaptative history file"
  :type 'file
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Backups
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-bookmarks-file (expand-file-name  "~/.emacs.d/data/bookmarks")
  "Bookmarks"
  :type 'file
  :group 'emacs-rimero-setup)

(defcustom ers-place-file (expand-file-name  "~/.emacs.d/data/saved-places")
  "Places file."
  :type 'directory
  :group 'emacs-rimero-setup)

(defcustom ers-backup-dir (expand-file-name "~/.emacs.d/data/backups")
  "Backups folder."
  :type 'directory
  :group 'emacs-rimero-setup)

(defcustom ers-auto-save-folder (expand-file-name "~/.emacs.d/data/auto-save-list/")
  "Auto-save folder."
  :type 'directory
  :group 'emacs-rimero-setup)

(defcustom ers-url-cookie-file "~/.emacs.d/data/cookies"
  "Cookies file for url connections."
  :type 'file
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; eshell
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-eshell-dir "~/.emacs.d/data/eshell"
  "Eshell data folder."
  :type 'directory
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; packages
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-packages '()
  "A list of packages to ensure are installed."
  :type 'symbol
  :group 'emacs-rimero-setup)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Programs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom ers-browser-program
  (cond ((eq system-type 'windows-nt) 'browse-url-default-windows-browser)
        ((eq system-type 'darwin)     'browse-url-default-macosx-browser)
        (t                            'browse-url-default-linux-browser))
  "Browser application:"
  :type 'symbol
  :group 'emacs-rimero-setup)

;; JS
(defcustom ers-tern-executable (or (executable-find "tern")
                                   "tern")
  "Tern executable for Javascript completion."
  :type 'string
  :group 'emacs-rimero-setup)

;; Git
(defcustom ers-yagist-token ""
  "Yagist Github token for gists."
  :type 'string
  :group 'emacs-rimero-setup)

Post-startup

Define package utility methods and install default packages.

(defun ers/package-install (pkg)
  "Install a package."
  (unless (package-installed-p pkg)
    (package-install pkg)))

(defun ers/packages-install (pkgs)
  "Install a list of packages."
  (if (listp pkgs)
      (mapc #'ers/package-install pkgs)
    (error "The list of packages must be a list!")))

(ers/packages-install (cons 'use-package ers-packages))

(mapc #'require '(use-package netrc))

(ers/mkdir-p ers-org-directory)

Sane defaults

Setup some emacs defaults.

;; Rebind some keys.
(let ((key-bindings '(("C-s" . isearch-forward-regexp)
                      ("C-r" . isearch-backward-regexp))))
  (cl-loop for key-binding in key-bindings
           do `(bind-key* ,(car key-binding) (cdr key-binding))))

;; Enable disabled commands.
(cl-loop for fn in '(downcase-region upcase-region erase-buffer)
         do (put fn 'disabled nil))

(setq global-auto-revert-non-file-buffers t)

;; Transparently open compressed files.
(auto-compression-mode t)

Backups and bookmarks

Setup backups.

(setq backup-directory-alist         `(("." . ,ers-backup-dir))
      delete-old-versions            t
      kept-new-versions              6
      kept-old-versions              2
      version-control                t
      url-cookie-file                ers-url-cookie-file
      auto-save-list-file-prefix     ers-auto-save-folder
      tramp-auto-save-directory      ers-auto-save-folder)

Bookmarks

Set the bookmarks file and turn-on autosave.

(setq bookmark-default-file ers-bookmarks-file
      bookmark-save-flag    1)

Aliases

Define some basic aliases for commonly used commands.

(defalias 'yes-or-no-p 'y-or-n-p)
(defalias 'serc        'ers/start-erc)

Utility functions

(defun ers/burry-other-buffer ()
  "Close other buffer window."
  (interactive)
  (when (window-parent)
    (other-window -1)
    (bury-buffer)
    (other-window -1)))

(defun ers/eval-and-replace (value)
  "Evaluate the sexp at point and replace it with its value"
  (interactive (list (eval-last-sexp nil)))
  (kill-sexp -1)
  (insert (format "%S" value)))

(defun ers/get-string-from-file (filePath)
  "Return filePath's file content."
  (with-temp-buffer
    (insert-file-contents filePath)
    (buffer-string)))

(defun ers/comment-or-uncomment-line-or-region ()
  "Comment or uncomment the current line or region."
  (interactive)
  (if (region-active-p)
      (comment-or-uncomment-region (region-beginning) (region-end))
    (comment-or-uncomment-region (line-beginning-position) (line-end-position))))

(defun ers/copy-symbol-at-point ()
  "Copy the symbol at point."
  (interactive)
  (let ((b (bounds-of-thing-at-point 'symbol)))
    (when b
      (save-excursion
        (kill-ring-save (car b) (cdr b))))))

(when (eq system-type 'darwin)
  (defvar osx-pbpaste-cmd "/usr/bin/pbpaste"
    "*command-line paste program")

  (defvar osx-pbcopy-cmd "/usr/bin/pbcopy"
    "*command-line copy program")

  (defun osx-pbpaste ()
    "paste the contents of the os x clipboard into the buffer at point."
    (interactive)
    (call-process osx-pbpaste-cmd nil t t))

  (defun osx-pbcopy ()
    "copy the contents of the region into the os x clipboard."
    (interactive)
    (if (or (and (boundp 'mark-active) mark-active)
            (and (fboundp 'region-exists-p) (region-exists-p)))
        (call-process-region
         (region-beginning) (region-end) osx-pbcopy-cmd nil t t)
      (error "region not selected"))))

(defun ers/recompile-init-files()
  "Recompile emacsd files."
  (interactive)
  (byte-recompile-directory user-emacs-directory 0 nil))

Encoding settings

(set-language-environment   'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq locale-coding-system  'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)

(unless (eq system-type 'windows-nt)
  (set-selection-coding-system 'utf-8))

(prefer-coding-system 'utf-8)

Eshell configuration

(setq eshell-directory-name ers-eshell-dir)

;; Set environment variables
(cl-loop for env-var in ers-env-variables
         do (setenv (car env-var) (cdr env-var)))

(use-package exec-path-from-shell
  :ensure exec-path-from-shell
  :if (eq system-type 'darwin)
  :config (progn
            (setq exec-path-from-shell-variables '("PATH" "MANPATH" "SHELL"))
            (exec-path-from-shell-initialize)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; EShell settings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'eshell)

(require 'vc-git)
(defun get-git-branch-name (path)
  (let ((git-directory (concat path "/.git")))
    (if (file-exists-p git-directory)
        (concat " (" (vc-git-mode-line-string git-directory) ") ")
      "")))

(defun get-full-time()
  "Full date and time"
  (format-time-string "%a %d.%m.%y %H:%M:%S" (current-time)))

(setq eshell-prompt-function (lambda nil
                               (concat
                                "\n"
                                (concat "[" (eshell/pwd) "] - " (get-full-time))
                                "\n"
                                (user-login-name)
                                "@"
                                (system-name)
                                (get-git-branch-name (eshell/pwd))
                                " $ " )))

(setq eshell-highlight-prompt       nil
      eshell-history-size           8000
      eshell-path-env               (getenv "PATH")
      eshell-cmpl-cycle-completions nil
      eshell-prompt-regexp          "^[^#$]*[#$] ")

(if (boundp 'eshell-save-history-on-exit)
    (setq eshell-save-history-on-exit t)) ; Don't ask, just save

(if (boundp 'eshell-ask-to-save-history)
    (setq eshell-ask-to-save-history 'always)) ; For older(?) version

(autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)

(defun up (&optional level)
  "Change directory from one up to a level of folders."
  (let* ((path-level (or level 1))
         (path-levels-list (cl-loop for i from path-level downto 1 collect "../"))
         (path-string (apply #'concat path-levels-list)))
    (cd path-string)))

Indentation settings

(setq-default indent-tabs-mode nil)

(defun ers/indentation-apply-style ()
  (cl-loop for elt in '("c-basic-offset"
                        "tab-width"
                        "js2-basic-offset"
                        "js-indent-level"
                        "py-indent-offset"
                        "sgml-basic-offset")
           do (progn
                (eval `(setq-default ,(intern elt) ers-tab-size))
                (eval `(setq ,(intern elt) ers-tab-size)))))

(defun ers/indentation-reset-tab-size (new-tab-size)
  (interactive "nEnter new tab size:\n")
  (setq ers-tab-size new-tab-size)
  (ers/indentation-apply-style))

(ers/indentation-apply-style)

(defun ers/indent-region-or-buffer ()
  "Indents an entire buffer using the default intenting scheme."
  (interactive)

  (if (region-active-p)
      (indent-region (region-beginning) (region-end))
    (progn
      (delete-trailing-whitespace)
      (indent-region (point-min) (point-max) nil)
      (untabify (point-min) (point-max)))))

(bind-key "C-c i" 'ers/indent-region-or-buffer)
(bind-key "RET"   'newline-and-indent)

Org mode settings

org-mode configuration.

(use-package org
  :ensure htmlize
  :init (progn
          (setq org-directory ers-org-directory)

          ;; default settings
          (setq org-archive-location (concat org-directory ers-org-archive-location-filename)
                org-agenda-files (directory-files org-directory t "\.org$")
                org-export-html-postamble nil
                org-ers-notes-file (concat org-directory ers-org-notes-filename))

          ;; org capture menu
          (setq org-capture-templates
                '(("d" "Tasks" entry
                   (file+headline org-ers-notes-file "Tasks")
                   "* TODO %?
SCHEDULED: %^t"          :clock-in t :clock-resume t)

                  ("e" "Quick task" entry
                   (file+headline org-ers-notes-file "Tasks")
                   "* TODO %^{Task}
SCHEDULED: %^t"

                   :immediate-finish t)

                  ("f" "Orientation" entry (file org-ers-notes-file)
                   "* ORIENTATION %? :@orientation:
SCHEDULED: %^t"  :clock-in t :clock-resume t)

                  ("g" "Coding" entry (file org-ers-notes-file)
                   "* CODING%? :@coding:
SCHEDULED: %^t"  :clock-in t :clock-resume t)

                  ("h" "Help" entry (file org-ers-notes-file)
                   "* HELP %? :@help:
SCHEDULED: %^t"  :clock-in t :clock-resume t)


                  ("i" "Phone call" entry (file org-ers-notes-file)
                   "* PHONE %? :@phone:
SCHEDULED: %^t"   :clock-in t :clock-resume t)


                  ("j" "Mail browsing" entry (file org-ers-notes-file)
                   "* EMAIL Browsing :@email:
SCHEDULED: %^t"    :clock-in t :clock-resume t)


                  ("k" "Mail reply" entry (file org-ers-notes-file)
                   "* EMAIL Reply %? :@email:
SCHEDULED: %^t"    :clock-in t :clock-resume t)


                  ("k" "Team Meetings" entry (file org-ers-notes-file)
                   "* TEAM MEETING :@meeting:
SCHEDULED: %^t"    :clock-in t :clock-resume t)


                  ("k" "Other meetings" entry (file org-ers-notes-file)
                   "* MEETING %? :@meeting:
SCHEDULED: %^t"   :clock-in t :clock-resume t)


                  ("l" "Break" entry (file org-ers-notes-file)
                   "* BREAK :@break:
SCHEDULED: %^t"    :clock-in t :clock-resume t)))

          ;; todo states
          (setq org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)" "|" "WAITING(w)")
                                    (sequence "REPORT(r)" "BUG(b)" "KNOWNCAUSE(k)" "|" "FIXED(f)")
                                    (sequence "|" "CANCELED(c)")))

          ;; tags
          (setq org-tag-alist '(("@orientation" . ?a)
                                ("@coding" . ?b)
                                ("@help" . ?c)
                                ("@phone" . ?d)
                                ("@documentation" . ?e)
                                ("@meeting" . ?f)
                                ("@email" . ?g)
                                ("@break" . ?h)))

          ;; require htmlize.el
          (setq org-agenda-exporter-settings'((ps-number-of-columns 2)
                                              (ps-landscape-mode t)
                                              (org-agenda-add-entry-text-maxlines 5)
                                              (htmlize-output-type 'css)))))

Personal information

Personal settings for email.

(setq user-mail-address ers-pim-mail-address
      user-full-name ers-pim-full-name
      message-signature-file "~/.signature")

Programming and related

Shell scripts

Sadly, we may still have to write or edit code running on MS Windows.

(use-package batch-mode
  :ensure    batch-mode
  :mode      ("\\.\\(bat\\)$" . batch-mode))

Version control

Nowadays it’s either SVN(or similar) for legacy systems and Git for anything else.

  • dsvn : dsvn is a subversion mode influenced by pcsv and psvn.
  • magit : Magit is an emacs mode for interacting with the Git version control system.
  • git-timemachine : Step through historic versions of git controlled file using everyone’s favourite editor.
  • yagist.el: Yet another Emacs paste mode, this one for Gist.
(use-package vc-svn
  :ensure    dsvn
  :init      (progn
               (autoload 'svn-status "dsvn" "Run `svn status'." t)
               (autoload 'svn-update "dsvn" "Run `svn update'." t)))

(use-package magit
  :ensure   magit
  :diminish magit-auto-revert-mode
  :init     (defun magit-clone-url ()
              (interactive)
              (let ((git-repo-url (read-from-minibuffer "Enter git repo URL: ")))
                (magit-git-command (concat " clone " git-repo-url)
                                   default-directory)))

  :bind     (("C-x gs" . magit-status)
             ("C-x gc" . magit-clone-url))
  :config   (defadvice magit-status (after magit-status-advice (dir) activate)
              (when (window-parent)
                (delete-other-windows))))

(use-package git-timemachine
  :ensure    git-timemachine
  :bind      ("C-x gt" . git-timemachine))

(use-package yagist
  :ensure    yagist
  :init      (setq yagist-github-token ers-yagist-token))

Project management

Use Projectile for project management.

(use-package projectile
  :ensure    projectile
  :config    (projectile-global-mode t)
  :init      (progn
               ;; create projectile data folder if non-existent
               (ers/mkdir-p ers-projectile-folder)

               ;; set projectile custom variables
               (let* ((ers-projectile-dir (file-name-as-directory ers-projectile-folder))
                      (ers-projectile-cache-file (concat ers-projectile-dir ers-projectile-cache-filename))
                      (ers-projectile-bookmarks-file (concat ers-projectile-dir ers-projectile-bookmarks-filename)))
                 (setq projectile-cache-file          ers-projectile-cache-file
                       projectile-known-projects-file ers-projectile-bookmarks-file
                       projectile-indexing-method     'alien
                       projectile-enable-caching      t)))
  :diminish   projectile-mode)

Completion, matching and suggestions

Hippie-expand

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

(global-set-key "\M- " 'hippie-expand)

Auto-completion settings

Use company-mode for text completion.

(use-package company
  :ensure    company
  :init      (setq company-begin-commands           '()
                   company-show-numbers              t
                   company-selection-wrap-around     t
                   company-tooltip-align-annotations t
                   company-dabbrev-downcase          nil
                   company-dabbrev-ignore-case       nil)
  :config    (add-hook 'after-init-hook 'global-company-mode)
  :bind      ("C-h TAB" . company-complete)
  :diminish  company-mode)

Helm settings

Helm is an incremental completion and selection narrowing framework.

There are couple of interesting integration modules :

(use-package helm
  :ensure    helm

  :config    (setq helm-ff-transformer-show-only-basename nil
                   helm-adaptive-history-file             ers-helm-adaptive-history-file
                   helm-boring-file-regexp-list           '("\\.git$" "\\.svn$" "\\.elc$")
                   helm-yank-symbol-first                 t
                   helm-buffers-fuzzy-matching            t
                   helm-ff-auto-update-initial-value      t
                   helm-input-idle-delay                  0.1
                   helm-idle-delay                        0.1)

  :init      (progn
               (require 'helm-config)
               (helm-mode t)
               (helm-adaptative-mode t)

               (use-package helm-ag
                 :ensure    helm-ag
                 :bind      ("C-c a" . helm-ag))

               (use-package helm-descbinds
                 :ensure    helm-descbinds
                 :bind      ("C-h b"   . helm-descbinds))

               (use-package helm-projectile
                 :ensure    helm-projectile
                 :bind      ("C-c h" . helm-projectile))

               (add-hook 'eshell-mode-hook
                         #'(lambda ()
                             (bind-key "M-p" 'helm-eshell-history eshell-mode-map)))

               (use-package helm-swoop
                 :ensure    helm-swoop
                 :bind      (("C-c o" . helm-swoop)
                             ("C-c M-o" . helm-multi-swoop)))

               (bind-key "C-c C-SPC" 'helm-ff-run-toggle-auto-update helm-find-files-map))

  :bind (("C-x r l" . helm-bookmarks)
         ("C-x C-m" . helm-M-x)
         ("C-h i"   . helm-google-suggest)
         ("M-y"     . helm-show-kill-ring)
         ("C-h a"   . helm-apropos)
         ("C-x C-f" . helm-find-files)
         ("C-x p" .   helm-top)
         ("C-x C-b" . helm-buffers-list))

  :diminish helm-mode)

Groovy and Grails

Settings for Groovy and Grails development.

Groovy mode

(use-package groovy-mode
  :ensure    groovy-mode
  :defer     t
  :mode      ("\\.\\(groovy\\|gradle\\)$" . groovy-mode))

Grails settings

(use-package grails-projectile-mode
  :init      (grails-projectile-global-mode t)
  :diminish  grails-projectile-mode)

XML mode

(use-package nxml-mode
  :init      (setq nxml-slash-auto-complete-flag t
                   nxml-child-indent             ers-tab-size
                   nxml-outline-child-indent     ers-tab-size)
  :defer     t
  :mode      ("\\.\\(pom\\|xsd\\|xsl\\|xslt\\|gsp\\)$" . nxml-mode))

SQL

(require 'sql)
(add-to-list 'auto-mode-alist '("\\.ddl$" . sql-mode))

Clojure

Clojure programming setup.

(use-package clojure-mode
  :ensure    clojure-mode
  :mode      ("\\.\\(clj\\|cljs\\)$" . clojure-mode)
  :init      (defun rename-clojure-modeline ()
               (interactive)
               (setq mode-name "CLJ"))
  :config    (add-hook 'clojure-mode-hook 'rename-clojure-modeline))

(use-package cider
  :ensure    cider
  :pre-init  (setq cider-words-of-inspiration '("NREPL is ready!!"))
  :config    (defalias 'cji 'cider-jack-in)
  :init      (add-hook 'cider-mode-hook 'cider-turn-on-eldoc-mode)
  :diminish  (cider-mode . ""))

Web

(use-package css-mode
  :config    (setq css-indent-offset ers-tab-size))

(use-package emmet-mode
  :ensure    emmet-mode
  :defer     t)

(use-package web-mode
  :ensure    web-mode
  :init      (add-hook 'html-mode-hook 'emmet-mode)
  :config    (setq web-mode-style-padding  ers-tab-size
                   web-mode-script-padding ers-tab-size)
  :mode      ("\\.\\(html\\|htm\\)$" . web-mode))

(use-package json-mode
  :ensure    json-mode
  :config    (bind-keys :map json-mode-map
                        ("C-c i" . json-mode-beautify))
  :mode      ("\\.\\(json\\)$" . json-mode))

(use-package js3-mode
  :ensure    js3-mode
  :init      (setq js3-indent-level          ers-tab-size
                   js3-mode-dev-mode-p       t
                   js3-auto-indent-p         t
                   js3-enter-indents-newline t
                   js3-indent-on-enter-key   t)
  :mode      ("\\.\\(js\\|tern-project\\)$" . js3-mode))

(use-package tern
  :ensure    tern
  :config    (setq tern-command (list (expand-file-name ers-tern-executable))))

(use-package company-tern
  :ensure    company-tern
  :init      (add-to-list 'company-backends 'company-tern)
  :config    (add-hook 'js3-mode-hook 'tern-mode))

Markdown keybindings

(use-package markdown-mode
  :ensure    markdown-mode
  :defer     t
  :mode      ("\\.\\(markdown\\|mdown\\|md\\)$" . markdown-mode))

YAML

YAML markup.

(use-package yaml-mode
  :ensure    yaml-mode
  :defer     t
  :mode      ("\\.yml$" . yaml-mode))

Yasnippets configuration

(use-package yasnippet
  :ensure    yasnippet
  :init      (setq yas-verbosity 1)
  :config    (progn
               (yas-global-mode 1)
               (let* ((yas-elpa-snippets-folder (car (file-expand-wildcards
                                                      (concat user-emacs-directory "elpa/yasnippet-*/snippets"))))
                      (yas-folder-candidates  `(,yas-elpa-snippets-folder
                                                ,(concat user-emacs-directory "snippets")
                                                ,(concat ers-emacs-dir "snippets"))))

                 (cl-loop for p in yas-folder-candidates
                          unless (file-exists-p p)
                          do (cl-delete p yas-folder-candidates))

                 (setq yas-snippet-dirs yas-folder-candidates))
               (yas-reload-all)
               (define-key yas-minor-mode-map (kbd "C-c <tab>") 'yas/insert-snippet))
  :diminish  yas-minor-mode)

Spellchecking configuration

(setq ispell-program-name ers-spelling-aspell-path)

Networking

Web browsing

(setq browse-url-browser-function          ers-browser-program
      browse-url-new-window-flag           t
      browse-url-firefox-new-window-is-tab t)
(bind-key "C-c m ." 'browse-url-at-point)

;; w3m
(use-package w3m
  :ensure    w3m
  :init      (setq w3m-coding-system             'utf-8
              w3m-file-coding-system        'utf-8
              w3m-file-name-coding-system   'utf-8
              w3m-input-coding-system       'utf-8
              w3m-output-coding-system      'utf-8
              w3m-terminal-coding-system    'utf-8
              w3m-use-cookies               t
              w3m-cookie-accept-bad-cookies t)
  :bind      ("C-c m w" . w3m-browse-url))

IRC configuration

(use-package erc
  :config (progn
            (setq erc-kill-buffer-on-part          t
                  erc-server-auto-reconnect        t
                  erc-prompt-for-nickserv-password nil
                  erc-server-coding-system         '(utf-8 . utf-8)
                  erc-autojoin-channels-alist      ers-erc-channel-list
                  erc-kill-queries-on-quit         t
                  erc-default-coding-system        '(utf-8 . utf-8)
                  erc-hide-list                    '("JOIN" "PART" "QUIT" "NICK" "MODE")
                  erc-kill-server-buffer-on-quit   t
                  erc-prompt                       (lambda () (concat (buffer-name) "> ")))

            (require 'erc-spelling)
            (erc-spelling-mode 1)
            
            ;; auto-fill buffer window
            (add-hook 'window-configuration-change-hook
                      '(lambda () (setq erc-fill-column (- (window-width) 2)))))

  :init (defun ers/start-erc ()
          (interactive)
          (erc-autojoin-mode 1)
          (let ((erc-config (netrc-machine (netrc-parse ers-secrets-file) "erc-config" t)))
            (erc :server   ers-erc-server
                 :nick     (netrc-get erc-config "login")
                 :password (netrc-get erc-config "password")))))

Jabber messaging

(use-package jabber
  :ensure    jabber
  :init      (let ((cred (netrc-machine (netrc-parse ers-secrets-file) "jabber" t))
                   (jabber-server ers-jabber-server)
                   (jabber-port   ers-jabber-port))
               (setq jabber-account-list `((,(netrc-get cred "login")
                                            (:password        . ,(netrc-get cred "password"))
                                            (:network-server  . ,jabber-server)
                                            (:connection-type . ssl)
                                            (:port            . ,jabber-port))))
               jabber-history-enabled         t
               jabber-use-global-history      nil
               jabber-history-dir             "~/.emacs.d/data/jabber-history"
               jabber-vcard-avatars-retrieve  nil
               jabber-chat-buffer-show-avatar nil))

Blogging

(use-package org2blog
  :ensure    org2blog
  :config    (setq corporate-blog (netrc-machine (netrc-parse ers-secrets-file) "corporate-blog" t)
                   personal-blog  (netrc-machine (netrc-parse ers-secrets-file) "personal-blog"  t)
                   org2blog/wp-blog-alist `((,corporate-blog-name
                                             :url ,corporate-blog-url
                                             :username (netrc-get corporate-blog "login")
                                             :password (netrc-get corporate-blog "password"))
                                            (,personal-blog-name
                                             :url ,personal-blog-url
                                             :username (netrc-get personal-blog "login")
                                             :password (netrc-get personal-blog "password")))))

Various utilities

(defun setup-aliases (aliases)
  (interactive)
  (dolist (lst aliases)
    (defalias (car lst) (cdr lst))))

(defun add-hooks (hook cb-list)
  "Add a set of function hooks to a hook."
  (mapc #'(lambda (cb) (add-hook hook cb))
        cb-list))

(defun ers/user-emacs-subdir (path-name)
  "sub-directory path in `user-emacs-directory."
  (expand-file-name
   (file-name-as-directory (concat user-emacs-directory path-name))))

(defun emacs-data-file (sub-folder)
  "Emacs file in data directory of .emacs.d."
  (let ((data-folder (concat user-emacs-directory "data")))
    (file-name-as-directory data-folder)))

(defun switch-max-window ()
  (interactive)
  (other-window -1)
  (delete-other-windows))

(bind-key* "C-h o" 'switch-max-window)

(bind-key* "C-x M-k"  '(lambda () (interactive)
                         (let (kill-buffer-query-functions) (kill-buffer))))

(defun rotate-windows ()
  "Rotate your windows"
  (interactive)
  (cond
   ((not (> (count-windows) 1))
    (message "You can't rotate a single window!"))
   (t
    (let ((i 0)
          (num-windows (count-windows)))
      (while  (< i (- num-windows 1))
        (let* ((w1 (elt (window-list) i))
               (w2 (elt (window-list) (% (+ i 1) num-windows)))
               (b1 (window-buffer w1))
               (b2 (window-buffer w2))
               (s1 (window-start w1))
               (s2 (window-start w2)))
          (set-window-buffer w1 b2)
          (set-window-buffer w2 b1)
          (set-window-start w1 s2)
          (set-window-start w2 s1)
          (setq i (1+ i))))))))

(bind-key* "C-h w" 'rotate-windows)

(defun ers/insert-time (&optional date-pattern)
  "Inserts the time given an optional pattern."
  (interactive "P")
  (let ((current-date-pattern (or date-pattern "%a %d.%m.%y %H:%M:%S")))
    (insert (ers/get-date current-date-pattern))))

(defun ers/get-date (date-pattern)
  "Returns a formatted date for a given pattern."
  (format-time-string date-pattern (current-time)))

(defun ers/insert-date-simple ()
  "Inserts the time in year-month-date format."
  (interactive)
  (ers/insert-time "%Y-%m-%d"))

(defun ers/insert-date-raw ()
  "Insert the time in raw format."
  (interactive)
  (ers/insert-time "%Y%m%d.%H%M%S"))

(defun ers/insert-date-full()
  "Inserts the full date and time."
  (interactive)
  (ers/insert-time "%a %d.%m.%y %T"))

(defun open-next-line (arg)
  "Move to the next line and then opens a line.
                                See also `newline-and-indent'."
  (interactive "p")
  (end-of-line)
  (open-line arg)
  (forward-line 1))

(defun open-previous-line (arg)
  "Open a new line before the current one.
                                 See also `newline-and-indent'."
  (interactive "p")
  (beginning-of-line)
  (open-line arg))

(use-package ace-window
  :ensure    ace-window
  :bind      ("C-x o" . ace-window))

(use-package anzu
  :ensure    anzu
  :config    (global-anzu-mode t)
  :diminish  anzu-mode)

(use-package wrap-region
  :ensure    wrap-region
  :config    (wrap-region-global-mode t)
  :diminish  wrap-region-mode)

(use-package undo-tree
  :ensure    undo-tree
  :config    (global-undo-tree-mode t)
  :init      (setq undo-tree-visualizer-relative-timestamps  t
                   undo-tree-visualizer-timestamps           t)
  :diminish  undo-tree-mode)

(use-package expand-region
  :ensure    expand-region
  :bind      ("C-c e" . er/expand-region))

(use-package hl-line
  :init     (add-hook 'prog-mode-hook 'hl-line-mode))

(use-package linum
  :init      (setq linum-format (quote "%4d "))
  :config    (add-hook 'prog-mode-hook 'linum-mode))

(use-package ace-jump-mode
  :ensure    ace-jump-mode
  :bind      (("C-c gw" . ace-jump-word-mode)
              ("C-c gc" . ace-jump-char-mode)
              ("C-c gl" . ace-jump-line-mode))
  :diminish  ace-jump-mode)

(use-package buffer-stack
  :ensure    buffer-stack
  :bind      (("C-c [" . buffer-stack-down)
              ("C-c ]" . buffer-stack-up))
  :config    (buffer-stack-track))

(use-package uniquify
  :config    (setq uniquify-separator           "/"
                   uniquify-buffer-name-style   'forward
                   uniquify-after-kill-buffer-p t
                   uniquify-ignore-buffers-re   "^\\*"))

(use-package saveplace
  :init (progn (setq-default save-place t)
               (setq save-place-file ers-place-file)))

(use-package recentf
  :init (progn (setq recentf-max-menu-items ers-max-recent-files
                     recentf-exclude        '("/tmp" "/ssh:" "\\ido.last" "recentf")
                     recentf-save-file      ers-recentf-file)
               (recentf-mode +1))

  :bind ("C-x C-r" . helm-recentf))

(use-package ls-lisp
  :config (setq ls-lisp-use-insert-directory-program nil
                ls-lisp-dirs-first t
                ls-list-ignore-case t))

(use-package dired
  :defer t
  :init (setq dired-recursive-deletes 'always
              dired-recursive-copies  'always)
  :config (progn
            (put 'dired-find-alternate-file 'disabled nil)
            (defun ers/dired-go-to-first-item ()
              (interactive)
              (goto-char (point-min))
              (dired-next-line 3))

            (defun ers/dired-go-to-last-item ()
              (interactive)
              (goto-char (point-max))
              (dired-previous-line 1))

            (defun copy-file-name-to-clipboard ()
              "Copy the current buffer file name to the clipboard."
              (interactive)
              (let ((filename (if (equal major-mode 'dired-mode)
                                  (dired-filename-at-point)
                                (buffer-file-name))))
                (when filename
                  (kill-new filename)
                  (message "Copied buffer file name '%s' to the clipboard." filename))))

            (bind-keys :map dired-mode-map
                       ("."   .  dired-up-directory)
                       ("@"   .  copy-file-name-to-clipboard )
                       ("M-P" .  ers/dired-go-to-first-item )
                       ("M-N" .  ers/dired-go-to-last-item ))))

(use-package dired-details
  :ensure    dired-details
  :init      (setq-default dired-details-hidden-string "--- ")
  :config    (dired-details-install))

(use-package drag-stuff
  :ensure    drag-stuff
  :bind      (("M-P" . drag-stuff-up)
              ("M-N" . drag-stuff-down)))

(use-package rainbow-delimiters
  :ensure    rainbow-delimiters
  :init      (add-hook 'prog-mode-hook 'rainbow-delimiters-mode))

(use-package ag
  :ensure    ag)

(use-package duplicate-thing
  :ensure    duplicate-thing
  :bind      ("C-c d" . duplicate-thing))

(let ((ers-keybindings `((,(kbd "C-o")     . open-next-line)
                         (,(kbd "C-h M-w") . copy-file-name-to-clipboard)
                         (,(kbd "M-o")     . open-previous-line)
                         (,(kbd "C-x 4 k") . ers/burry-other-buffer)
                         (,(kbd "C-c C-e") . ers/eval-and-replace)
                         (,(kbd "C-c j")   . join-line)
                         (,(kbd "C-c M-j") . (lambda () (interactive)(join-line -1)))
                         (,(kbd "M-t w")   . transpose-words)
                         (,(kbd "M-t l")   . transpose-lines)
                         (,(kbd "M-t s")   . transpose-sexps)
                         (,(kbd "C-x y")   . ers/copy-symbol-at-point)
                         (,(kbd "C-c r")   . revert-buffer)
                         (,(kbd "C-c /")   . ers/comment-or-uncomment-line-or-region))))
  (global-unset-key (kbd "M-t"))
  (dolist (ers-keybinding ers-keybindings)
    (global-set-key (car ers-keybinding) (cdr ers-keybinding))))

(add-hook 'emacs-lisp-mode-hook       'eldoc-mode)
(add-hook 'lisp-interaction-mode-hook 'eldoc-mode)

(use-package eldoc
  :defer     t
  :diminish  eldoc-mode)

(use-package multiple-cursors
  :ensure    multiple-cursors
  :init      (setq mc/list-file "~/.emacs.d/data/mc.el")
  :bind      (("C-c me" . mc/edit-lines)
              ("C-c ma" . mc/mark-all-like-this)))

(use-package smartparens
  :ensure    smartparens
  :init      (progn
               (require 'smartparens)
               (load-library "smartparens-config"))

  :config   (progn
              (smartparens-global-mode t)
              (sp-with-modes '(html-mode sgml-mode nxml-mode web-mode)
                (sp-local-pair "<" ">"))

              (define-key sp-keymap (kbd "C-M-f") 'sp-forward-sexp)
              (define-key sp-keymap (kbd "C-M-b") 'sp-backward-sexp)

              (define-key sp-keymap (kbd "C-M-e") 'sp-up-sexp)
              (define-key sp-keymap (kbd "C-M-d") 'sp-down-sexp)

              (define-key sp-keymap (kbd "C-M-u") 'sp-backward-up-sexp)
              (define-key sp-keymap (kbd "C-M-a") 'sp-backward-down-sexp)

              (define-key sp-keymap (kbd "C-S-a") 'sp-beginning-of-sexp)
              (define-key sp-keymap (kbd "C-S-d") 'sp-end-of-sexp)

              (define-key sp-keymap (kbd "C-M-t") 'sp-transpose-sexp)

              (define-key sp-keymap (kbd "C-M-n") 'sp-next-sexp)
              (define-key sp-keymap (kbd "C-M-p") 'sp-previous-sexp)

              (define-key sp-keymap (kbd "C-M-k") 'sp-kill-sexp)
              (define-key sp-keymap (kbd "C-M-w") 'sp-copy-sexp))

  :diminish smartparens-mode)

(use-package cl-lib-highlight
  :ensure    cl-lib-highlight
  :init      (cl-lib-highlight-initialize))

(use-package ispell
  :init      (defun ispell-line()
               (interactive)
               (ispell-region (line-beginning-position) (line-end-position)))
  :bind      (("C-c sr" . ispell-region)
              ("C-c sb" . ispell-buffer)
              ("C-c sw" . ispell-word)
              ("C-c sl" . ispell-line)))

UI configuration

Misc

(setq visible-bell             t
      display-time-24hr-format t
      use-dialog-box           nil
      default-frame-alist      `((font . ,ers-ui-font)))

(use-package smart-mode-line
  :ensure    smart-mode-line
  :init      (setq sml/theme 'respectful)
  :config    (sml/setup))

(use-package popwin
  :ensure    popwin
  :config    (progn
               (setq display-buffer-function 'popwin:display-buffer)
               (popwin-mode t)))

(defun turn-on-linum-hl-mode-hook ()
  (interactive)
  (hl-line-mode 1)
  (linum-mode 1))

(use-package nxml-mode
  :init      (add-hook 'nxml-mode-hook 'turn-on-linum-hl-mode-hook))

Themes

(defun ers/load-theme (theme-symbol)
  (when (and (boundp theme-symbol)
             (symbol-value theme-symbol))
    (funcall 'load-theme (symbol-value theme-symbol) t)))

(if window-system
    (ers/load-theme 'ers-ui-theme)
  (ers/load-theme 'ers-ui-theme-console))

Fonts

(defun ers/fontify-frame (frame)
  (set-frame-parameter frame 'font ers-ui-font))

(defun ers/set-current-font ()
  (interactive)
  ;; Fontify current frame
  (ers/fontify-frame nil)
  ;; Fontify any future frames
  (push 'ers/fontify-frame after-make-frame-functions))

(if window-system
    (ers/set-current-font))

User settings

(when (file-exists-p ers-user-file)
  (load ers-user-file 'noerror))

(message "emacs-rimero-setup done loading.")