Skip to content
A literate emacs configuration for C#, python, ivy, yasnippet, ...
Branch: master
Clone or download

README.md

Table of Contents

  1. Overview
    1. Quick start
    2. Why a literate configuration
    3. init.el, short and sweet
      1. Loading the custom file first
      2. Customizing the configuration
  2. My Configuration
    1. A preamble
    2. General packages
      1. Speed up line movement
      2. Use Ctrl-Z for personal bindings
      3. Docker
      4. flycheck
      5. synosaurus
      6. diminish
      7. yaml-mode
      8. bind-key
      9. helpful
      10. savehist
      11. Themes and mode line
      12. For demonstrations
      13. which-key
      14. Very large files
      15. Groovy
      16. Other useful packages
  3. company-mode Configuration
  4. ivy/swiper Configuration
  5. prescient Configuration
  6. yasnippet Configuration
  7. magit/git configuration
  8. org-mode Configuration
    1. org-mode export hacks for HTML and Markdown
    2. Use of babel
  9. LSP configuration
  10. python configuration
    1. The tale of two IDEs
      1. elpy IDE
      2. lsp-mode IDE
    2. Python IDE-agnostic configuration
  11. Java configuration
  12. Additional bits-o-configuration
    1. Limit the length of which-function
    2. my-ansi-term
    3. Understand file type by shebang
    4. React to screen width changes
    5. Additional Configuration

Overview

This is my literate and portable Emacs initialization.

Quick start

Simply

  1. git clone this repository into ~/.emacs.d: git clone https://github.com/Atman50/emacs-config.git =/.emacs.d

  2. start Emacs

That's it.

Starting Emacs for the first time on a new machine loads all the packages/configuration loads. It takes some time on this first load since all the packages referenced need to download and compile. On subsequent Emacs invocations startup time is much better. The ability to simply clone and start is what makes this configuration portable. Note that some of the Emacs customization (see custom.el) are system (file system) dependent. I handle this by using git to create a stash of the localized changes for custom.el and then apply it whenever I take updated configurations from the repository.

Why a literate configuration

Well mostly I wanted to learn how to do it, but also I was having issues with managing my initialization/configuration. FWIW this is the approach that I came up with. My init.el file is simple and relies on the fact that customizations are saved to its own file and that these customizations are read in before the packages are loaded.

What I've gotten out of all this work is a portable and documented configuration that works well for me. Please feel free to take whatever portion(s) you wish from this and make it your own.

I have tried to make this configuration 100% portable meaning that on a new system (Linux or Windows at this point) with Emacs installed. I simple git clone this repository to ~/.emacs.d and then fire up Emacs. Should work every time.

init.el, short and sweet

11  (setq custom-file (expand-file-name "custom.el" user-emacs-directory))
12  (load custom-file t)
13  (prefer-coding-system 'utf-8)
14  (unless (boundp 'package-user-dir)
15    (unless (boundp 'package-archive-contents)
16      (package-initialize))
17    (unless (assoc 'use-package package-archive-contents)
18      (package-refresh-contents)
19      (package-install (elt (cdr (assoc 'org-plus-contrib package-archive-contents)) 0))
20      (package-install (elt (cdr (assoc 'use-package package-archive-contents)) 0))))
21  (setq use-package-enable-imenu-support t)
22  (require 'use-package)
23  (use-package org)
24  (defcustom my/cfg-file (concat user-emacs-directory "README")
25    "The base name for the .org file to use for Emacs initialization."
26    :group 'my-configuration
27    :type 'string)
28  (when (file-newer-than-file-p (concat my/cfg-file ".org") (concat my/cfg-file ".el"))
29    (org-babel-tangle-file (concat my/cfg-file ".org")))
30  (load my/cfg-file)
Line Explained
11 Breaking the custom setting out into its own file allows it to be loaded in the next line
12 Load the custom file. All custom settings will now be honored by packages when loaded.
13 Just a fix for ELPA packages with (certain?) Unicode characters in them.
14 If there's no `'package-user-dir` defined; `package.el` isn't loaded
15 If there's no `'package-archive-contents` defined; package archives have not been read
16 Initialize the package system
17 If we've not load loaded the definition for the `use-package` ELPA package, then
18 Refresh (read) the package archives. Note: `'package-archives` from `custom.el` **key** here
19 Load up the org-mode. The pre-packaged org-mode does not have Babel!
20 Set the variable to allow `use-package` to use counsel for imenus
21 Require `use-package`
22 Make sure `use-package` is available
23 Make sure `org` is available
24 Create customizable config variable
25
26 … it's nice having a customizable group for personal configuration settings
27
28 If the .el file doesn't exist or is older than this file then…
29 … create the tangled output of this file
30 Load the tangled output of this file

Loading the custom file first

One of the nicest things about Emacs is the extensive and quite useful customization engine. You can customize variables and faces with ease and make the settings work for you.

Loading the customized variables before the package (using use-package of course) means that you can now use the customization facility in Emacs to modify the variables and have them stick between Emacs invocations. I see lots of configurations with the :config section of a use-package invocation performing variable setting. The problem with this is that if you want to change it using Emacs, the loading of the customizations first causes your new customizations getting overwritten on the next start of Emacs. You can do it in the reverse order; use-package first, then customize, but then you couldn't customize the variable using the customization system.

Therefore I try to minimize use-package customizations and mostly use the custom.el file.

The most important custom variable for this configuration is package-archives, which is used by the loading of the various extension packages used by this configuration.

Symbol Name Value
package-archives (("gnu" . "https://elpa.gnu.org/packages/")
 ("melpa" . "https://melpa.org/packages/")
 ("org" . "https://orgmode.org/elpa/"))
use-package-enable-imenu-support t

Customizing the configuration

I've started to use the defcustom function to describe those "variables that impact initialization" and are all placed into the 'my-configuration group. Each of the configuration variables can be accessed using M-x customize-group my-configuration. This allows me to select features to turn on or off selectively and make them sticky if so desired.

Another reason to load the customization file first.

My Configuration

Here are my configuration bits. All of the following code snippets are tangled from this file into an .el file that gets loaded from the initialization file. Feel free to take as little or as much as you like from here.

A preamble

First make sure that we are doing lexical scoping for speed. See Some Performance Advantages of Lexical Scope blog.

;;; README.el --- a file generated from README.org - do not edit by hand!!!!
;; -*- lexical-binding: t; -*-
;;; Commentary:
;;;     Org tangled from README.org. Edit the org file to chnage this configuration
;;; Code:

This is a little piece of code that I picked up that might make things faster when downloading and installing all the packages. This turns down the garbage collector during the use-package loading when it has to do some compiling. Set it back when done with init.

(setq gc-cons-threshold 64000000)
(add-hook 'after-init-hook (lambda () (setq gc-cons-threshold 800000)))

General packages

Here are some general packages I use

Speed up line movement

I ran into this little tidbit while reading Sacha Chua's posts from Emacs. It is described here, but to summarize the next-line defun triggers line-move-partial which leads to excessive processing. By setting the variable here, the speed of using next-line gets very cut down.

(setq auto-window-vscroll nil)

Use Ctrl-Z for personal bindings

Ctrl-c was supposed to be left for personal customization but seems to get used more than it should, therefore I've started to bind things to Ctrl-Z, which had the annoying and useless minimize functionality.

(bind-keys :map global-map                      ;; get rid of pesky "\C-z" and use for personal bindings
           :prefix-map my-ctrl-z-prefix-map
           :prefix "C-z"
           ("C-d" . dired-jump)
           ("c"   . comment-region)
           ("d"   . docker)
           ("f"   . magit-find-file-other-window)
           ("g"   . magit-status)
           ("h a" . helpful-at-point)
           ("h c" . helpful-command)
           ("h C" . helpful-callable)
           ("h f" . helpful-function)
           ("h k" . helpful-key)
           ("h m" . helpful-macro)
           ("h v" . helpful-variable)
           ("l"   . magit-log-buffer-file)
           ("n"   . linum-mode)
           ("r"   . revert-buffer)
           ("t"   . toggle-truncate-lines)
           ("u"   . uncomment-region))

Docker

I manage a lot of docker stuff. The docker package is quite useful.

(use-package docker)

flycheck

I've abandoned flymake (built-in) with flycheck (see flycheck a flymake replacement).

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

synosaurus

This is a free synonyms plug-in for Emacs that uses Wordnet brought to you by Princeton University. Note that you will have to install Wordnet on your system and add it to your path to make this package work properly.

(use-package synosaurus)

diminish

Handy mode to make the modeline more succinct by allowing a diminished mode line string. Sometimes the fact that mode is there is fine and it doesn't need to be on the mode line (diminish it to "").

(use-package diminish
  :defer t)

yaml-mode

(use-package yaml-mode)

bind-key

Much better binding capabilities (in later versions this is already loaded via use-package).

(use-package bind-key
  :defer t)

helpful

Helpful provides contextual help and other features. Here are two blogs that provide good information: initial Helpful blog and Helpful, one year in. More in-depth help along with lots of other information like references, edebug capabilities, …

(use-package helpful)

savehist

A great built-in that allows us to have a history file. This means certain elements are saved between sessions of Emacs. This history file is kept in ~/.emacs.d/savehist. Note that in later versions of Emacs this package is already built-in, so check the built-ins before issuing the use-package. In later versions of Emacs seems the savehist package is built-in so ignore annoying errors.

(unless (package-built-in-p 'savehist)
  (use-package savehist
    :defer t))

Set the following variables to control savehist (use customize).

Symbol Name Value
savehist-file "~/.emacs.d/savehist"
savehist-additional-variables (tablist-named-filter kill-ring search-ring regexp-search-ring)
savehist-mode t

Themes and mode line

My progression of modelines has gone from powerline to moody and now doom. The doom-modeline package is pretty good and not as much fuss as I had with moody. All the stuff I need there and makes this configuration much easier. You must go install the fonts from the all-the-icons package (which is loaded as a dependency) according to the instructions found on the doom-modeline website: Run M-x all-the-icons-install-fonts and then, on Windows, install the font ttf file by right clicking on it and doing install.

(use-package leuven-theme
  :config
  (load-theme 'leuven t))

(use-package doom-modeline
  :hook (after-init . doom-modeline-mode))

The current modifications I make to the doom-modeline default face settings when using the leuven-theme are doom-modeline-buffer-modified and doom-modeline-project-dir. You can look in the custom.el file for those settings.

For demonstrations

These packages are useful when doing presentations.

(use-package command-log-mode :defer t)

which-key

Perhaps one of the most useful extensions, this little gem will provide a list in the mini-buffer of the relevant keystrokes and the functions to which they are bound (or a prefix). Many times I've found unknown features by simply looking at the various options. This is, IMO, a great way to learn Emacs key-bindings.

(use-package which-key :diminish "")
(use-package which-key-posframe)
Symbol Name Value
which-key-mode t
which-key-posframe-mode t
which-key-posframe-poshandler posframe-poshandler-frame-bottom-left-corner

Very large files

Since I deal with potentially gigantic log files, this package allows the file to be carved up and 'paged' through. Get to the vlf stuff through the default prefix C-c C-v.

(use-package vlf
  :defer t
  :pin melpa)

I got the vlf package from a really good paper on how to use Emacs to deal with logs. If you currently or are going to deal with logs in your day to day, then this article is invaluable. I've yet to adopt some of the other features described by the article but I have no need as of yet. Soon maybe.

Groovy

Since I'm doing more and more work with Jenkins adding support for Groovy is, well, groovy.

(use-package groovy-mode)
Symbol Name Value
groovy-indent-offset 2

Other useful packages

OK, a little tired of documenting each package on it's own. These packages are just generally useful. Some of these packages have become so useful that they've found their way into the list of Emacs built-in packages. In those cases, the package is checked here against the list of built-ins to avoid warnings when loading a later version of Emacs.

(use-package realgud)           ;; A "better" gud
(use-package projectile
  :bind
  (:map projectile-mode-map
        ("C-c p"   . projectile-command-map)        ;; traditional binding
        ("C-z C-p" . projectile-command-map)        ;; my binding
        ("C-z p"   . projectile-command-map))       ;; all paths get to projectile
  :config
  (projectile-mode t))
(use-package ibuffer-projectile :defer t)
(use-package xterm-color :defer t)
(unless (package-built-in-p 'sh-script)
  (use-package sh-script :defer t))
(unless (package-built-in-p 'desktop)
  (use-package desktop))
(set-variable 'desktop-path (cons default-directory desktop-path))
(use-package lispy
  :config
  (add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1)))
  (add-hook 'minibuffer-setup-hook (lambda () (when (eq this-command 'eval-expression) (lispy-mode 1)))))

(use-package powershell
  :if mswindows-p)

Note that the setting of desktop-path allows the multiple .emacs.desktop files, each in the directory where emacs was started. Although desktop-path is changed outside custom.el, I've included it here in the table below so you can see that the default is augmented with the start-up directory which in this case is ~/.emacs.d.

Customized variables of interest here:

Symbol Name Value
desktop-path ("`/toast/git-repos/lunchbox/" "~/.emacs.d/" "`")
desktop-save-mode t

company-mode Configuration

Use the excellent company-mode modular in-buffer text completion framework. In particular this is used for elpy (python) and java modes, although it is used elsewhere.

(use-package company
  :diminish)

ivy/swiper Configuration

I used to be a helm user, but switched to ivy. Lots of nice features in ivy and very easy to configure comparatively.

(use-package ivy
  :diminish ""
  :bind (:map ivy-minibuffer-map
              ("C-w" . ivy-yank-word)           ;; make work like isearch
              ("C-r" . ivy-previous-line))
  :config
  (ivy-mode 1)
  (setq ivy-initial-inputs-alist nil)           ;; no regexp by default
  (setq ivy-re-builders-alist                   ;; allow input not in order
        '((t . ivy--regex-ignore-order))))
(use-package counsel
  :bind (("C-z j" . counsel-imenu)))
(use-package counsel-projectile
  :config
  (counsel-projectile-mode t))
(use-package counsel-codesearch)
(use-package ivy-hydra)
(use-package swiper
  :bind (("C-S-s" . isearch-forward)  ;; Keep isearch-forward on Shift-Ctrl-s
         ("C-s" . swiper)             ;; Use swiper for search and reverse search
         ("C-S-r" . isearch-backward) ;; Keep isearch-backward on Shift-Ctrl-r
         ("C-r" . swiper)))
(use-package avy
  :bind (("C-:" . avy-goto-char)))

NOTE: posframe IS MESSED UP - NOT TANGLING

(use-package posframe)
(use-package ivy-posframe
  :config
  (setq ivy-display-function #'ivy-posframe-display)
  (ivy-posframe-enable))

I ran into a nice article that fixes a problem that I often have with Ivy: using a name that is not in the list of candidates (for example when trying to write to a buffer to a new file name). To fix this, setting ivy-use-selectable-prompt to t makes going back before the first candidate to a "verbatim" prompt.

Customized variables:

Symbol Name Value
ivy-count-format "(%d/%d) "
ivy-height 20
ivy-mode t
ivy-use-selectable-prompt t
ivy-use-virtual-buffers t

prescient Configuration

prescient provides "simple but effective sorting and filtering for Emacs."

(use-package prescient)
(use-package ivy-prescient)
(use-package company-prescient)

yasnippet Configuration

yasnippet is a truly awesome package. Local modifications should go in ~/.emacs.d/snippets/.

Just love the yasnippet package. I only wish there were more templates out there. Creating new ones and placing them the appropriate (mode-named) subdirectory of ~/.emacs.d/snippets/.

(use-package yasnippet
  :diminish (yas-minor-mode . "")
  :config
  (yas-reload-all)
  ;; fix tab in term-mode
  (add-hook 'term-mode-hook (lambda() (yas-minor-mode -1)))
  ;; Fix yas indent issues
  (add-hook 'python-mode-hook (lambda () (set (make-local-variable 'yas-indent-line) 'fixed)))
  ;; Setup to allow for yasnippets to use code to expand
  (require 'warnings)
  (add-to-list 'warning-suppress-types '(yasnippet backquote-change)))
(use-package yasnippet-snippets)

The following code allows the yasnippet and company to work together. Got this from a fix posted on github which was pointed to by the company mode Wiki page.

(defvar my/company-point nil)
(advice-add 'company-complete-common :before (lambda () (setq my/company-point (point))))
(advice-add 'company-complete-common :after (lambda ()
                                              (when (equal my/company-point (point))
                                                (yas-expand))))

Customizations of interest:

Symbol Name Value
yas-global-mode t

magit/git configuration

The most awesome git porcelain. Most here are part of magit, git-time-machine is not, but well worth using.

(use-package git-commit)
(use-package magit
  ;; Make the default action a branch checkout, not a branch visit when in branch mode
  :bind (:map magit-branch-section-map
              ([remap magit-visit-thing] . magit-branch-checkout)))
(use-package magit-filenotify)
(use-package magit-find-file)
(use-package git-timemachine)

Customized variables:

Symbol Name Value
git-commit-fill-column 78
magit-completing-read-function ivy-completing-read
magit-repository-directories (("~/repos" . 1))

org-mode Configuration

I use org-bullets which used to be part of the org-plus-contrib package but seems to no longer be included . Always throw org-mode buffers into flyspell-mode for live spell checking.

The htmlize package allows the HTML and Markdown exporters to work (underlying code). It also allows to export your files all fontified: for example, you can export all or part of, say, a Python file and it will come out all colorized for publishing.

(use-package org-bullets
  :config
  (add-hook 'org-mode-hook (lambda ()
                             (toggle-truncate-lines -1)
                             (auto-fill-mode 1)
                             (org-bullets-mode))))
(use-package org-autolist)
(use-package htmlize)
(add-hook 'org-mode-hook #'flyspell-mode)
;; (use-package ox-reveal)
;; (require 'ox-reveal)

I've started using ox-reveal for generating presentations from org-mode. Here's a good article on getting started. I've set the org-reveal-root to point to http://cdn.jsdelivr.net/reveal.js/3.0.0/ so that you do not need to install it on your system. If you want to use your own customized theme, see the instructions at https://github.com/hakimel/reveal.js/. NB: I have removed ox-reveal from the normal package load because it has a dependency on the org package, but we already install org-plus-contrib which ox-reveal, I guess, doesn't recognize. Leaving the code here to make it easy to bring in if you are working with reveal.js and presentations.

Customized variables for org-mode:

Symbol Name Value
org-catch-invisible-edits show
org-html-postamble t
org-html-postamble-format (("en" "<p class=\"author\">Author: %a (%e)</p>\n<p class=\"date\">Date: %T</p>\n<p class=\"creator\">%c</p>"))
org-log-done time
org-log-into-drawer t

org-mode export hacks for HTML and Markdown

I export into markdown for github. I do not use the ox-gfm package because when I tried it, it modified the source file because of this file's use of the #+CALL construct (each call adds the table to the source file). So I use the built in ox-md exporter. However, it just indents the code blocks rather put the ```emacs-lisp code snippet prefix and ``` postfix but rather just indents. First we load the library so it turns up in the export menu (C-x C-e). Then we override the output method for the code.

(load-library "ox-md")

(cl-defun org-md-example-block (example-block _contents info)
  "My modified: Transcode EXAMPLE-BLOCK element into Markdown format.
CONTENTS is nil.  INFO is a plist used as a communication
channel."
  (concat "```emacs-lisp\n"
          (org-remove-indentation
           (org-export-format-code-default example-block info))
          "```\n"))

To support the using of dynamic custom vars table using the library of Babel, the export text for Markdown and HTML goes through orgtbl-to-orgtbl which turns the list returned in the an org-mode table. After orgtbl-to-orgtbl, the htmlize package turns it into a HTML table. The adviser changes all the spaces after a <br> into &nbsp; entities and surrounds them with inline HTML. This is necessary because orgtbl-to-orgtbl strips text between the @@ used to inline HTML. The adviser also protects any underscores in the table with inline HTML.

(cl-defun my-md-export-hack(text)
  "Fix up md export on writing my README.org file.
        Converts a <br> followed by zero or more spaces into inline html format.
        For example: an in put of \"hello<br>there<br> my<br>  friend<br>\" becomes
        \"hello@@html:<br>@@there@@html:<br>&nbsp;@@my@@html:<br>&nbsp;&nbsp;@@friend@@html:<br>@@\"
        This function also adds inline HTML around '_' in the text."
  (when (stringp text)
    (let ((result text)
          (replacements '(("<br>\[[:space:]\]*" (lambda (match)
                                                  (concat "@@html:<br>"
                                                          (apply 'concat (make-list (- (length match) 4) "&nbsp;"))
                                                          "@@")))
                          ("\"\\(https?:\[^\"\]*\\)" "\"@@html:<a href=\"\\1\">\\1</a>@@")
                          ("_" "@@html:_@@")
                          ("<\\(p.*?\\)>" "@@html:&lt;\\1&gt;@@")
                          ("</p>" "@@html:&lt;/p&gt;@@"))))
      (cl-loop for rep in replacements do
               (setq result (replace-regexp-in-string (nth 0 rep) (nth 1 rep) result)))
      result)))

(advice-add #'orgtbl-to-orgtbl :filter-return #'my-md-export-hack)

Use of babel

To do literate programming you need to include the languages to "tangle". Here I've added more than just the standard emacs-lisp value. Added Python, PlantUML, and shell.

Symbol Name Value
org-babel-load-languages ((shell . t)
 (plantuml . t)
 (python . t)
 (emacs-lisp . t))

LSP configuration

LSP (Language Server Protocol) is a new Microsoft-defined interface for IDEs:

The Language Server Protocol (LSP) defines the protocol used between an editor or IDE and a language server that provides language features like auto complete, go to definition, find all references etc.

Although I'm currently using elpy for Python, I'll be using LSP for Java development.

(use-package lsp-mode
  :demand t
  :config
  (add-hook 'lsp-after-open-hook #'lsp-enable-imenu)
  (use-package lsp-ui
    :config
    (add-hook 'lsp-mode-hook 'lsp-ui-mode))
  (use-package company-lsp
    :config
    (push 'company-lsp company-backends))
  (add-hook 'lsp-after-initialize-hook (lambda ()
                                         (let ((lsp-cfg `(:pyls (:configurationSources ("flake8")))))
                                           (lsp--set-configuration lsp-cfg)))))

python configuration

At one point I was using anaconda but have switched back to elpy. I really like eply-config that tells you if everything is working properly. I've been using a virtualenv for my python development and couldn't be happier. Perhaps the only thing that bothers me is that when an object is returned, PyCharm will give you list and dictionary methods while eply=/=company does not. Seems to be the only real issue at this point.

The tale of two IDEs

I've decided to take the Language Server Protocol out for a spin. Unfortunately it might be a while before I decide to switch since there are some things I find a little annoying, like initial startup speed of loading a large Python file into Emacs, presumably because lsp-mode is initializing. Either way, the Python IDE is selected using the.

To switch between the two IDEs might take a bit of futzing - I've had to go remove elpy entries from ~/.emacs.d/custom.el to switch to the lsp-mode.

(defcustom my/use-elpy t
  "Setting to t uses elpy as the Python IDE. Set to nil to use lsp."
  :group 'my-configuration
  :type '(choice
          (const :tag "lsp" nil)
          (const :tag "elpy" t)))

elpy IDE

The tried and true elpy Python IDE. I run flycheck rather than flymake now, so rebind the error navigation keys (C-c C-n/C-p).

(when my/use-elpy
  (use-package elpy
    :demand t
    :bind (:map elpy-mode-map
                ("C-c C-p" .  flycheck-previous-error)
                ("C-c C-n" . flycheck-next-error)
                ("C-z ." . elpy-goto-definition))
    :config
    (elpy-enable)
    (add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter")
    (use-package company-jedi
      :config
      (push 'company-jedi company-backends))))

The variable elpy-modules is updated in my custom.el file so that the flymake module is removed:

Symbol Name Value
elpy-modules (elpy-module-company elpy-module-eldoc elpy-module-pyvenv elpy-module-highlight-indentation elpy-module-yasnippet elpy-module-sane-defaults)

lsp-mode IDE

This is a newer mode based on the Language Server Protocol.

(unless my/use-elpy
  (use-package lsp-python))

Python IDE-agnostic configuration

(use-package pylint)
(use-package python-docstring
  :config
  (python-docstring-install))
(use-package python
  :config
  (add-hook 'python-mode-hook (lambda ()
                                (unless my/use-elpy (lsp-python-enable))
                                (company-mode)
                                )))

Customized variables used in this python configuration:

Symbol Name Value
python-check-command "/usr/local/bin/flake8"
python-shell-interpreter "jupyter"
python-shell-interpreter-args "console –simple-prompt"
python-shell-prompt-detect-failure-warning nil
python-shell-prompt-output-regexp "Out\\\[[0-9]+\\]: "
python-shell-prompt-regexp "In \\\[[0-9]+\\]: "

Java configuration

Tried to get LSP working, but to no avail. Using Meghanada mode.

(use-package gradle-mode)
(use-package meghanada
  :bind (:map meghanada-mode-map
              ("C-c C-n" . flycheck-next-error)
              ("C-c C-p" . flycheck-previous-error))
  :config
  (add-hook 'java-mode-hook (lambda () (meghanada-mode t))))

Additional bits-o-configuration

Limit the length of which-function

which-function which is used on the mode-line has no maximum method/function signature. This handy adviser limits the name to 64 characters.

(defcustom  my/which-function-max-width 64
  "The maximum width of the which-function string."
  :group 'my-configuration
  :type 'integer)
(advice-add #'which-function :filter-return
            (lambda (s) (when (stringp s)
                          (if (< (string-width s) my/which-function-max-width) s
                            (concat (truncate-string-to-width s (- my/which-function-max-width 3)) "...")))))

my-ansi-term

Allows me to name my ANSI terms. Was very useful when I used more ANSI shells (so that tabs were interpreted by the shell). Some other modes and shells make this less useful these days.

(cl-defun my-ansi-term (term-name cmd)
  "Create an ansi term with a name - other than *ansi-term* given TERM-NAME and CMD."
  (interactive "sName for terminal: \nsCommand to run [/bin/bash]: ")
  (ansi-term (if (= 0 (length cmd)) "/bin/bash" cmd))
  (rename-buffer term-name))

Understand file type by shebang

When a file is opened and it is determined there is no mode (fundamental-mode) this code reads the first line of the file looking for an appropriate shebang for either python or bash and sets the mode for the file.

(cl-defun my-find-file-hook ()
  "If `fundamental-mode', look for script type so the mode gets properly set.
Script-type is read from #!/... at top of file."
  (if (eq major-mode 'fundamental-mode)
      (ignore-errors
          (save-excursion
            (goto-char (point-min))
            (re-search-forward "^#!\s*/.*/\\(python\\|bash\\).*$")
            (if (string= (match-string 1) "python")
                (python-mode)
              (sh-mode))))))

(add-hook 'find-file-hook 'my-find-file-hook)

React to screen width changes

Because I use posframe quite a bit now (so that the mini-buffer doesn't continue to change sizes, which I find a little annoying), this code reacts to the width changes and will set the custom variables accordingly.

Does not seem to work with newest POSFRAME (as of 2019-05-02). Needs work.

(cl-defun my/window-size-change (&optional _)
  "My very own resize defun for modifying the posframe size"
  (unless (= (window-pixel-width-before-size-change) (window-pixel-width))
    (customize-set-value 'ivy-posframe-width (window-body-width))))
(add-hook 'window-size-change-functions 'my/window-size-change)

Additional Configuration

Setup eldoc mode, use y-or-n-p instead of yes-or-no-p. Key bindings…

(add-hook 'emacs-lisp-mode-hook #'eldoc-mode)   ;; Run elisp with eldoc-mode
(diminish 'eldoc-mode "Doc")                    ;; Diminish eldoc-mode

(fset #'list-buffers #'ibuffer)                 ;; prefer ibuffer over list-buffers
(fset #'yes-or-no-p #'y-or-n-p)                 ;; for lazy people use y/n instead of yes/no

;; Some key bindings
(bind-key "C-x p" #'pop-to-mark-command)
(bind-key "C-h c" #'customize-group)
(bind-key "C-+" #'text-scale-increase)
(bind-key "C--" #'text-scale-decrease)
(bind-key "<up>" #'enlarge-window ctl-x-map)    ;; note: C-x
(bind-key "<down>" #'shrink-window ctl-x-map)   ;; note: C-x
(bind-key "C-z" 'nil ctl-x-map)                 ;; get rid of annoying minimize "\C-x\C-z"

(setq-default ediff-ignore-similar-regions t)   ;; Not a variable but controls ediff

;; Enable some stuff that's normally disabled
(put 'narrow-to-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'scroll-left 'disabled nil)

A post-amble to make the tangled .el file has no errors/warnings.

;;; README.el ends here
You can’t perform that action at this time.