= HTML tags.
Luckily it's trivial to teach it. It does know about == HTML
tags, and basically I just want == tags to be treated almost as
== tags, so to do that we just have to define a =shr-tag-code=
function. I've copied the =shr-tag-pre= function and removed the calls
to =ensure-newline=, because == tags are inline tags.
In order to remain a little future-proof, it should only be done if
it doesn't already exist.
*Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=.
*Note:* See my [[Function declarations][note]] on function declarations about the use of
=declare-function=.
#+BEGIN_SRC emacs-lisp
(defvar shr-folding-mode)
(declare-function shr-indent "shr")
(declare-function shr-generic "shr")
(with-eval-after-load 'shr
(unless (fboundp 'shr-tag-code)
(defun shr-tag-code (cont)
(let ((shr-folding-mode 'none))
(shr-indent)
(shr-generic cont)))))
#+END_SRC
*** Setup eww-lnum
#+BEGIN_SRC emacs-lisp :tangle no
(depends-on "eww-lnum")
#+END_SRC
As recommended in the [[https://github.com/m00natic/eww-lnum][README]], set the keys in the =eww-mode-map=.
#+BEGIN_SRC emacs-lisp
(defvar eww-mode-map)
(with-eval-after-load 'eww
(define-key eww-mode-map "f" 'eww-lnum-follow)
(define-key eww-mode-map "F" 'eww-lnum-universal))
#+END_SRC
** Scheme
I really like programming in Lisp. One of the more comfortable
Lisps is Scheme because most of the implementations I've worked
with are more like other compiled or interpreted languages, whereas
Common Lisp usually re-compiles on every load. Aside from that,
there are some neat programs written in some scheme dialects and of
course scsh is the most awesome shell scripting language ever
conceived.
*** Use scheme-mode for scsh interpreted files
Set the major mode for files interpreted by scsh (for example, by
having ~#!/usr/local/bin/scsh~ at the top) to use =scheme-mode=.
#+BEGIN_SRC emacs-lisp
(add-to-list 'interpreter-mode-alist '("scsh" . scheme-mode))
#+END_SRC
*** Set default scheme implementation
Set the default implementation for geiser to guile so it doesn't ask
which implementation to use every time.
#+BEGIN_SRC emacs-lisp
(stante-after geiser-impl
(setq geiser-default-implementation 'guile))
#+END_SRC
** SCSS
SCSS is a CSS preprocessor that makes writing CSS files much more
fun. Add autocompletion and some custom imenu function.
#+BEGIN_SRC emacs-lisp
(add-hook 'scss-mode-hook 'auto-complete-mode)
(add-hook 'scss-mode-hook 'scss-imenu-setup)
#+END_SRC
** Dired
Dired is an excellent file manager.
*** Change listings in dired
The number of bytes a file is doesn't usually tell me much when it's
something like ~292837~. I prefer seeing just how many Kb or Mb a
certain file is. I also don't need to see the ~.~ and ~..~ directories
when I insert directories into the current dired buffer, as there is
a great chance that the current and parent directory are already
shown in the buffer.
#+BEGIN_SRC emacs-lisp
(defvar dired-subdir-switches)
(with-eval-after-load 'dired
(setq dired-listing-switches "-alh"
dired-subdir-switches "-Alh"))
#+END_SRC
** PHP
I occasionally write PHP for work. Not usually in my free time, but
there are some open source PHP projects that I sometimes tinker
with.
*** Show tabs and spaces in indent
I'm working with some WordPress plugins nowadays and their style
guide insists on using tabs, not spaces... I'd like to know that
I'm following this rule.
#+BEGIN_SRC emacs-lisp
(add-hook 'php-mode-hook #'oni:whitespace-only-tabs)
#+END_SRC
** Web
Web mode is good for files that contain a lot of HTML, CSS and
JavaScript together. Most other major modes or multi-major modes
don't quite do it.
*** Turn off the fill column indicator
~web-mode~ has some quirks, such as not being able to handle the
fact that ~fci-mode~ puts a red line at the 80-column margin. This is
annoying to say the least.
#+BEGIN_SRC emacs-lisp
(declare-function fci-mode "fci-mode")
(add-hook 'web-mode-hook (turn-off fci-mode))
#+END_SRC
*** Show tabs in indentation
Just like in ~php-mode~ I want to see the tabs.
#+BEGIN_SRC emacs-lisp
(add-hook 'web-mode-hook #'oni:whitespace-only-tabs)
#+END_SRC
*** Use tabs for indentation
Set =indent-tabs-mode= for ~web-mode~ as well.
#+BEGIN_SRC emacs-lisp
(defvar web-mode-code-indent-offset)
(defvar web-mode-markup-indent-offset)
(add-hook 'web-mode-hook
(change-settings indent-tabs-mode t
web-mode-code-indent-offset 4
web-mode-markup-indent-offset 4))
#+END_SRC
*** Use it for Embedded Ruby HTML files
Use it for ~.html.erb~ files.
#+BEGIN_SRC emacs-lisp
(oni:eval-after-init
(add-to-list 'auto-mode-alist '("\\.html\\.erb$" . web-mode)))
#+END_SRC
*** Use it for HTML-heavy PHP files
I have to work with a lot of PHP and HTML interspersed. This makes
a difficult case since ~php-mode~ very deliberately doesn't support
that very well. On the other hand I really don't like ~web-mode~ for
PHP /without/ any HTML in it. So I decided to name the files that
contain mostly HTML with some PHP ~.html.php~ and have them load
~web-mode~ instead of ~php-mode~, whilst keeping the association for
plain ~.php~ files as it is.
Something tricky about doing this is that if this setting gets
evaluated /before/ ~php-mode~ is loaded it'll be further down the list
from ~php-mode~'s definition. This would cause the ~php-mode~ auto
mode definition from being accepted first (since ~.html.php~ also
matches ~.php~) and consequently render this definition useless.
#+BEGIN_SRC emacs-lisp
(oni:eval-after-init
(add-to-list 'auto-mode-alist '("\\.html\\.php$" . web-mode)))
#+END_SRC
** PO mode
Autoload =po-mode=, because it didn't come with an autloads file or
cookie.
#+BEGIN_SRC emacs-lisp
(autoload 'po-mode "po-mode" nil t)
#+END_SRC
Automatically enable =po-mode= for files that end in =.po= or that have
a =.po= extension followed by others (such as =.po.erb=).
#+BEGIN_SRC emacs-lisp
(add-to-list 'auto-mode-alist '("\\.po\\'\\|\\.po\\." . po-mode))
#+END_SRC
** Magit
Recently Magit gained the annoying habit of producing a /huge/ warning
message whenever you don't tell it that you've already seen it. To
tell it you've already seen the message you need to specify the
following.
#+BEGIN_SRC emacs-lisp
(eval-and-compile
(defvar magit-last-seen-setup-instructions "1.4.0"))
#+END_SRC
I use a =defvar= here in order to keep the byte-compiler from
complaining about an undefined variable. It needs to be specified
before magit is loaded otherwise magit will keep complaining.
*** Project directory
I keep all my projects in =~/projects/=, so Magit shouldn't have to
look anywhere else.
#+NAME: magit-repo-dirs
#+BEGIN_SRC emacs-lisp :tangle no
(setq magit-repository-directories '("~/projects/"))
#+END_SRC
*** Show fine differences
I like to see all the little differences in diffs that I can. They
really help reading diffs. I also just want to see them on all
diffs and not the selected one, which would make an unnecessary
amount of navigation required to properly read the diffs.
#+NAME: magit-diff-refine-hunk
#+BEGIN_SRC emacs-lisp :tangle no
(setq magit-diff-refine-hunk 'all)
#+END_SRC
*** Delay setting
The settings in the previous sections should only be set after
Magit has loaded.
#+BEGIN_SRC emacs-lisp :noweb yes
(stante-after magit
<>
<>)
#+END_SRC
** Circe
:PROPERTIES:
:header-args: :tangle site-lisp/circe-init.el
:END:
I used to use ERC mostly because I didn't really use IRC at all and
it was basically the first IRC client in Emacs that was presented
to me, it being built-in and all. When I started to use IRC more
and wanted to customize the way it looks more I was surprised to
find that it wasn't all that easy. A friend of mine was using Circe
and he helped me figure out how to get started with customizing
Circe the way I wanted it. So now I use Circe.
These settings will be tangled to =site-lisp/circe-init.el= and
loaded when Circe is loaded.
*** Require the needed libraries
In order to keep compiler warnings to a minimum, require the
libraries that are used in the configuration of Circe.
#+BEGIN_SRC emacs-lisp
(require 'lui)
(require 'circe)
(require 's)
#+END_SRC
*** Clean-up the display of messages
I once saw a very clean and simple weechat configuration on
[[https://www.reddit.com/r/unixporn][/r/unixporn]] and really wanted to have something similar. This was
the start of my disappointment in ERC, I couldn't figure out how
to change the way messages were printed. With a little help I did
find out how to do it in Circe.
First we create a variable to store the length of the longest
known nick, so we can properly align all messages. This variable
should be buffer-local because each IRC chat will have different
users with different length names. We start with a length of ~0~
because we don't know what the shortest nick there is going to be.
#+BEGIN_SRC emacs-lisp
(defvar oni:circe-longest-nick 0)
(make-variable-buffer-local 'oni:circe-longest-nick)
#+END_SRC
Then we write the function that will print the most important
messages, the ones people send, including me. Whenever we get a
message or send a message, we check the length of the nick with
the last recorded maximum length. If the new nick is longer that
any previous ones we set this new length as the longest known
length and adjust =lui-fill-type= accordingly. This ensures that
continuation lines are indented to the correct column.
#+BEGIN_SRC emacs-lisp
(defun oni:circe-say-formatter (&rest keywords)
(let* ((nick (plist-get keywords :nick))
(len (length nick)))
(when (> len oni:circe-longest-nick)
(setq oni:circe-longest-nick len)
(setq-local lui-fill-type (make-string (+ len 3) ?\ )))
(format "%s %s" (s-pad-left oni:circe-longest-nick " " nick)
(plist-get keywords :body))))
#+END_SRC
I use this formatter both for messages I send myself and incoming
messages, because they should basically look the same.
#+BEGIN_SRC emacs-lisp
(setq circe-format-self-say #'oni:circe-say-formatter
circe-format-say #'oni:circe-say-formatter)
#+END_SRC
The rest of the formatting functions are basically the same,
except they don't need to change the known size of nicks because
they don't print the nick in the same column, instead they usually
print something like "***" to indicate that it is a system message
and not a user message. We do pad whatever they print with the
same number of spaces to keep them right-justified with the nicks.
#+BEGIN_SRC emacs-lisp
(defun oni:circe-action-formatter (&rest keywords)
(format "%s %s %s" (s-pad-left oni:circe-longest-nick " " "*")
(plist-get keywords :nick)
(plist-get keywords :body)))
(defun oni:circe-server-message-formatter (&rest keywords)
(format "%s %s" (s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :body)))
(defun oni:circe-server-join-in-channel-formatter (&rest keywords)
(format "%s Join: %s (%s) joined %s"
(s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :nick)
(plist-get keywords :userinfo)
(plist-get keywords :channel)))
(defun oni:circe-server-join-formatter (&rest keywords)
(format "%s %s joined the channel"
(s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :nick)))
(defun oni:circe-server-quit-formatter (&rest keywords)
(format "%s %s quit IRC: %s"
(s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :nick)
(plist-get keywords :reason)))
(defun oni:circe-server-quit-channel-formatter (&rest keywords)
(format "%s %s left %s: %s"
(s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :nick)
(plist-get keywords :channel)
(plist-get keywords :reason)))
(defun oni:circe-server-part-formatter (&rest keywords)
(format "%s %s parted %s: %s"
(s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :nick)
(plist-get keywords :channel)
(plist-get keywords :reason)))
(defun oni:circe-server-nick-change-formatter (&rest keywords)
(format "%s %s is now known as %s"
(s-pad-left oni:circe-longest-nick " " "***")
(plist-get keywords :old-nick)
(plist-get keywords :new-nick)))
(setq circe-format-self-action #'oni:circe-action-formatter)
(setq circe-format-action #'oni:circe-action-formatter)
(setq circe-format-server-message #'oni:circe-server-message-formatter)
(setq circe-format-server-join-in-channel
#'oni:circe-server-join-in-channel-formatter)
(setq circe-format-server-join #'oni:circe-server-join-formatter)
(setq circe-format-server-quit #'oni:circe-server-quit-formatter)
(setq circe-format-server-quit-channel
#'oni:circe-server-quit-channel-formatter)
(setq circe-format-server-part #'oni:circe-server-part-formatter)
(setq circe-format-server-nick-change
#'oni:circe-server-nick-change-formatter)
#+END_SRC
*** Automatically join some channels
I started using IRC because #mowedline was started and I felt
obligated to join it as I was one of two known Mowedline users at
the time. So now that's the one I'm usually active in. I do like
to keep an eye on #emacs from time to time and #ninthfloor in case
something happens there, though usually not.
#+BEGIN_SRC emacs-lisp
(setq circe-network-options
`(("Freenode"
:nick "ryuslash"
:channels ("#emacs" "#mowedline" "#ninthfloor"))))
#+END_SRC
*** Change the time-stamp
I use only a small window to view the IRC channel I'm in usually,
the default format put the time-stamp just a little too far to the
right and would always cause either line truncation or filling to
the next line. So I put the time-stamp in the right margin so it's
always to the right of all messages and no messages can run under
it, so essentially it has it's own column.
#+BEGIN_SRC emacs-lisp
(setq lui-time-stamp-position 'right-margin)
(setq lui-time-stamp-format "%H:%M")
#+END_SRC
Give the right margin just enough room to show the time-stamps, no
more, no less.
#+BEGIN_SRC emacs-lisp
(defun oni:set-circe-margin-width ()
(setq right-margin-width 5))
(add-hook 'lui-mode-hook #'oni:set-circe-margin-width)
#+END_SRC
*** Clean-up the channel buffers further
When chatting with people in an IRC channel, there really isn't
much need for any information in the mode-line. This is mostly
because the channel I'm most active on always has its own window.
Visual line mode is very handy to have in chats, in case I type
very long lines. And the =wrap-prefix= is set so that when I do type
long lines, they are filled nicely to the circe prompt.
#+BEGIN_SRC emacs-lisp
(defun oni:remove-mode-line ()
(setq mode-line-format nil))
(defun oni:set-circe-prompt-wrap-prefix ()
(setq wrap-prefix " "))
(add-hook 'circe-channel-mode-hook #'oni:remove-mode-line)
(add-hook 'circe-channel-mode-hook #'oni:set-circe-prompt-wrap-prefix)
(add-hook 'circe-channel-mode-hook 'visual-line-mode)
#+END_SRC
*** Show #mowedline in a frame without minibuffer
When I'm chatting on #mowedline I do so in a separate small
window. This window needs no minibuffer as I do very little
actualy Emacsy things in it. Just typing a little and reading. So
far I only do this with #mowedline. In order to specifically show
it in a frame without a minibuffer I use =display-buffer-alist= to
specify how to show it. The function called dynamically binds
=default-frame-alist= to add a =minibuffer= element with the value
=nil= (meaning, no minibuffer). I can't do this in the regular
=default-frame-alist= because I want all other frames to show up
/with/ a minibuffer. It then creates a new frame and switches to the
given buffer in it.
#+BEGIN_SRC emacs-lisp
(defun oni:display-in-minibufferless-frame (buffer _)
(let ((default-frame-alist default-frame-alist))
(push '(minibuffer . nil) default-frame-alist)
(let ((frame (make-frame)))
(select-frame frame)
(switch-to-buffer buffer))))
(add-to-list 'display-buffer-alist
'("^\#mowedline$" oni:display-in-minibufferless-frame))
#+END_SRC
* Minor mode customization
Many minor modes also offer a bit of customization possibilities.
** Robe
#+BEGIN_SRC emacs-lisp :tangle no
(depends-on "robe")
#+END_SRC
Robe is a Ruby completion and documentation lookup library.
*** Adding completions to autocomplete
To add Robe completions to autocomplete whenever robe is started,
I use the =robe-mode-hook= to enable this so that it doesn't try to
get any completions when robe isn't running.
#+BEGIN_SRC emacs-lisp
(add-hook 'robe-mode-hook #'ac-robe-setup)
#+END_SRC
** Eldoc
Seeing the arguments to a function whilst typing its name is
excellent.
*** Show eldoc when evaluating expressions
Thanks to [[http://endlessparentheses.com/sweet-new-features-in-24-4.html][this post]] it was brought to my attention that eldoc mode
can be enabled when evaluating expressions using {{{key(M-:)}}}.
I vaguely remember having had this before, I just don't know how or
why it stopped working.
#+BEGIN_SRC emacs-lisp
(add-hook 'eval-expression-minibuffer-setup-hook #'eldoc-mode)
#+END_SRC
** Electric pair
Electric pairing of delimiters is one of those features that is
just so essential to my feeling comfortable with an editor. Most of
the time I don't even use it, really. It's just that I'm so used to
having it and when I /do/ expect it to be there it is so frustrating
when it's not, or when it doesn't work properly.
This functionality, much like [[Electric indent]] isn't something I
want enabled in all modes, though for different reasons, and for a
time there was only the global =electric-pair-mode=. Again I'm very
happy that a local version was added.
The reason that I don't want it enabled for all modes is that some
modes (mostly Lisp-like language modes) have better alternatives.
But most non-Lisp-like language modes I really do need to have it.
#+BEGIN_SRC emacs-lisp
(add-hook 'c-mode-hook #'electric-pair-local-mode)
(add-hook 'coffee-mode-hook #'electric-pair-local-mode)
(add-hook 'css-mode-hook #'electric-pair-local-mode)
(add-hook 'haml-mode-hook #'electric-pair-local-mode)
(add-hook 'java-mode-hook #'electric-pair-local-mode)
(add-hook 'js2-mode-hook #'electric-pair-local-mode)
(add-hook 'lua-mode-hook #'electric-pair-local-mode)
(add-hook 'python-mode-hook #'electric-pair-local-mode)
(add-hook 'ruby-mode-hook #'electric-pair-local-mode)
(add-hook 'scss-mode-hook #'electric-pair-local-mode)
(add-hook 'sh-mode-hook #'electric-pair-local-mode)
#+END_SRC
*** Remove whitespace when closing delimiters
In =electric-pair-mode=, skip over and delete white space if it stands
between the cursor and the closing delimiter.
#+BEGIN_SRC emacs-lisp
(setq electric-pair-skip-whitespace 'chomp)
#+END_SRC
** Electric indent
Automatically indenting code upon typing certain characters can be
very useful for certain modes where the indentation level can
easily be determined. One of the first things I liked about Emacs
was the way the {{{key(TAB)}}} key worked: It indents to the
"proper" level of indentation, instead of adding a tab character.
It quickly grew into a habit to press tab several times when
editing a line or a block of code. Electric indent is just an
extension of this that, for the most part, allows me to forget
about pressing tab.
It doesn't fit all modes though. When I worked in Python a lot I
was fighting the electric indent a lot more than it was helping me.
This is because instead of scope influencing indentation as in most
languages I've worked with, indentation determines scope in Python,
as anyone who's looked at it for more than a minute or two will
know. This means that any line can usually have several "proper"
indentation levels, depending on the meaning of meaning of that
line.
So, almost all modes use =electric-indent-local-mode=, but a few
don't. So I'm also very happy that recently this mode was added,
because =electric-indent-mode= is a global minor mode and I only want
to use it in some 99% of the available modes.
#+BEGIN_SRC emacs-lisp
(add-hook 'css-mode-hook #'electric-indent-local-mode)
(add-hook 'js2-mode-hook #'electric-indent-local-mode)
(add-hook 'php-mode-hook #'electric-indent-local-mode)
(add-hook 'ruby-mode-hook #'electric-indent-local-mode)
(add-hook 'scss-mode-hook #'electric-indent-local-mode)
(add-hook 'sh-mode-hook #'electric-indent-local-mode)
#+END_SRC
*** Switch keys back
When =electric-indent-mode= is enabled the default function bound to
{{{key(C-j)}}} (=electric-newline-and-maybe-indent=) stops indenting
after adding a newline, whilst {{{key(RET)}}} starts doing it.
Since I use {{{key(C-j)}}} almost exclusively and don't use
{{{key(RET)}}} at all, it's really not useful to me. So I want to
switch the two when =electric-indent-mode= is enabled.
This is very simple. First I define a simple function that checks
if the =electric-indent-mode= variable is set (which it should be if
the mode is turned on) and if so I set the proper keys /locally/. If
=electric-indent-mode= is /not/ set, which happens when the mode is
turned off, I remove the local keybindings.
#+BEGIN_SRC emacs-lisp
(defun oni:switch-newline-keys ()
"Switch the `C-j' and `RET' keys in the local buffer."
(if electric-indent-mode
(progn
(local-set-key (kbd "C-j") 'newline)
(local-set-key (kbd "RET") 'electric-newline-and-maybe-indent))
(local-unset-key (kbd "C-j"))
(local-unset-key (kbd "RET"))))
#+END_SRC
And then I add it to the electric indent mode's hook.
#+BEGIN_SRC emacs-lisp
(add-hook 'electric-indent-local-mode-hook #'oni:switch-newline-keys)
#+END_SRC
** Auto completion
#+BEGIN_SRC emacs-lisp :tangle no
(depends-on "auto-complete")
#+END_SRC
I'm not a great fan of any type of auto completion functionality in
programming. I think it's basically only good for getting really
long names in your file faster. I started programming in C#, in
Visual Studio, and they have their very powerful Intellisense
mechanism, which I used a lot. What I noticed though was that it
was keeping me from learning the APIs. Whenever I wrote some code,
all but the most basic and most-used calls I wrote from memory.
Many others were done after a few seconds of browsing through the
Intellisense pop-up.
Because of this, I disable the normal auto-complete pop-up.
#+NAME: auto-complete-dont-show
#+BEGIN_SRC emacs-lisp :tangle no
(setq ac-auto-show-menu nil)
#+END_SRC
On the rare occasion that I do call up the pop-up to see what the
completions I have available to me are, I don't want it to show the
quick help. The quick help usually shows up as a big extra pop-up
next to the completion list and it gets very messy when combined
with some other modes that add overlays to the buffer.
#+NAME: auto-complete-no-quickhelp
#+BEGIN_SRC emacs-lisp :tangle no
(setq ac-use-quick-help nil)
#+END_SRC
To keep the byte-compiler from complaining about undefined
variables, I only want this to be done after =auto-complete= is
loaded, not sooner.
#+BEGIN_SRC emacs-lisp :noweb yes
(stante-after auto-complete
<>
<>)
#+END_SRC
** Highlight indentation
#+BEGIN_SRC emacs-lisp :tangle no
(depends-on "hl-indent")
#+END_SRC
Some languages base their ideas of scope on levels of indentation.
When these languages get long functions/branches it can get tricky
to see where these blocks end. Of course if you have such large
functions you might have other problems, but this is sometimes out
of your hands. To help, I use =hl-indent-mode=.
For other languages it might look fun for a little while as well,
but since they don't care about indentation as much it can
sometimes get messy.
First, =hl-indent-mode= doesn't have an =;;;###autoload= cookie for its
main entry-point, so I add it manually:
#+BEGIN_SRC emacs-lisp
(autoload 'hl-indent-mode "hl-indent" nil t)
#+END_SRC
Then I enable it for the languages I want.
#+BEGIN_SRC emacs-lisp
(add-hook 'python-mode-hook #'hl-indent-mode)
(add-hook 'yaml-mode-hook #'hl-indent-mode)
(add-hook 'haml-mode-hook #'hl-indent-mode)
#+END_SRC
** Django helper
:PROPERTIES:
:ORDERED: t
:END:
#+BEGIN_SRC emacs-lisp :tangle no
(depends-on "pony-mode")
#+END_SRC
Autoload =pony-mode= because it doesn't come with an autoload cookie.
#+BEGIN_SRC emacs-lisp
(autoload 'pony-mode "pony-mode" nil t)
#+END_SRC
Turn on =compilation-shell-minor-mode= when =pony-mode= is enabled.
#+BEGIN_SRC emacs-lisp
(defun oni:turn-on-compilation-shell-for-pony ()
"Turn on option `compilation-shell-minor-mode' for `pony-minor-mode'."
(add-hook 'pony-minor-mode-hook 'compilation-shell-minor-mode nil t))
(add-hook 'comint-mode-hook #'oni:turn-on-compilation-shell-for-pony)
#+END_SRC
** Automatic syntax checking on-the-fly
#+BEGIN_SRC emacs-lisp :tangle no
(depends-on "flycheck")
(depends-on "flycheck-cask")
(depends-on "flycheck-commit-check" :git "git://github.com/ryuslash/flycheck-commit-check.git")
#+END_SRC
Flycheck provides awesome syntax checkers for many languages.
Enable it for the languages I use.
#+BEGIN_SRC emacs-lisp
(add-hook 'haml-mode-hook 'flycheck-mode)
(add-hook 'emacs-lisp-mode-hook 'flycheck-mode)
(add-hook 'git-commit-mode-hook 'flycheck-mode)
(add-hook 'go-mode-hook 'flycheck-mode)
(add-hook 'html-mode-hook 'flycheck-mode)
(add-hook 'js2-mode-hook 'flycheck-mode)
(add-hook 'lua-mode-hook 'flycheck-mode)
(add-hook 'perl-mode-hook 'flycheck-mode)
(add-hook 'php-mode-hook 'flycheck-mode)
(add-hook 'python-mode-hook 'flycheck-mode)
(add-hook 'rst-mode-hook 'flycheck-mode)
(add-hook 'ruby-mode-hook 'flycheck-mode)
(add-hook 'rust-mode-hook 'flycheck-mode)
(add-hook 'sh-mode-hook 'flycheck-mode)
(add-hook 'texinfo-mode-hook 'flycheck-mode)
#+END_SRC
Whenever flycheck is started, try using it with Cask.
#+BEGIN_SRC emacs-lisp
(add-hook 'flycheck-mode-hook 'flycheck-cask-setup)
#+END_SRC
Load my own git commit checker.
#+NAME: flycheck-commit-checker
#+BEGIN_SRC emacs-lisp :tangle no
(require 'flycheck-commit-check)
#+END_SRC
Disable certain checkers.
#+NAME: flycheck-delete-checkers
#+BEGIN_SRC emacs-lisp :tangle no
(mapc (lambda (c) (delq c flycheck-checkers))
'(python-pylint python-pyflakes))
#+END_SRC
Set the highlighting mode to columns so I can see (if possible)
where errors/warnings belong.
#+NAME: flycheck-columns
#+BEGIN_SRC emacs-lisp :tangle no
(setq flycheck-highlighting-mode 'columns)
#+END_SRC
Try not to display the errors. A jumpy echo area makes me nervous
and {{{key(C-c ! l)}}} is a nicer way to look at it usually. It
still doesn't keep it from being displayed, only when nothing else
is displayed though.
#+NAME: flycheck-display
#+BEGIN_SRC emacs-lisp :tangle no
(setq flycheck-display-errors-function (lambda (_) nil))
#+END_SRC
Do most of these things after flycheck is loaded.
#+BEGIN_SRC emacs-lisp :noweb yes
(stante-after flycheck
<>
<>
<>
<>)
#+END_SRC
* Final touches
These options and calls need to come last so they don't interfere
with the rest of the initialization process, or get interfered with.
** Load custom file
I don't really use the Emacs customization interface much, but I
have used it as a kind-of persistent datastore, specifically for
desktop-registry[fn:9]. I do very much like the idea of it, it's a
very cool thing to have. I also use ~custom.el~ for storing some
things that I really can't store in a public viewing location like
this file or the git repository it lives in.
#+BEGIN_SRC emacs-lisp
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)
#+END_SRC
* Notes
Here are some random or somewhat general notes about things you may
run into when looking through my Emacs init.
** Vacuous defvar
A =defvar= without a value like =(defvar some-variable)= tells the
byte-compiler that the variable will appear, but doesn't give it a
value. It should only count for the file where it is used and once
the file with the /actual/ =defvar= is loaded it will be populated with
its value, contrary to what would happen if you'd given it a value
before loading its original file.
** Function declarations
The function =declare-function= tells the byte-compiler where to find
a certain function. This keeps the byte-compiler from complaining
about certain functions possibly not being defined at run-time.
* Footnotes
[fn:1] This runs =tmm-menubar=, which lets you navigate the menubar in a
text-driven way. I don't ever use it because I know what all my
favorite functions are called, but it seems a great deal more
efficient than having to click on everything.
[fn:2] https://github.com/sabof/svg-mode-line-themes
[fn:3] It works fine for me with something like jabber chats and the
like.
[fn:4] I like to program in Lisp, parentheses are important to me!
Parentheses should be nice and round, not almost like bars!
[fn:5] https://github.com/belluzj/fantasque-sans
[fn:6] Used to be Cosmic Sans Neue Mono, the name changed because
people misread it as "Comic" (me included, which was the original
reason I checked it out, for laughs) and hate Comic Sans, and also
because there was already a Cosmic Sans font as well, which could
cause confusion.
[fn:7] http://stackoverflow.com/questions/22175214/automatically-switch-language-in-gnus-depending-on-recipient
[fn:8] I still use 2 spaces for some languages, like HTML.
[fn:9] http://code.ryuslash.org/desktop-registry/about/