From c2778f0f713cc885087d6302196e421596ff248e Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Thu, 21 Aug 2014 00:23:56 +0200 Subject: Add Emacs config --- emacs/.emacs.d/init.org | 960 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 960 insertions(+) create mode 100644 emacs/.emacs.d/init.org (limited to 'emacs/.emacs.d/init.org') diff --git a/emacs/.emacs.d/init.org b/emacs/.emacs.d/init.org new file mode 100644 index 0000000..1031ae2 --- /dev/null +++ b/emacs/.emacs.d/init.org @@ -0,0 +1,960 @@ +#+TITLE: Emacs init +#+PROPERTY: tangle init2.el +#+STARTUP: showall +#+OPTIONS: author:nil num:nil toc:nil +#+MACRO: key @@html:$1@@@@ascii:`$1'@@ +#+HTML_HEAD: + +* About this file + + Inspired by such other projects as the literal Emacs init from [[http://sachac.github.io/.emacs.d/Sacha.html][Sacha + Chua]] and also from [[http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html][Grant Rettke]], here is my Emacs initialization + file. + + *Note:* This is not my entire Emacs initialization file. It's a + work-in-progress. To keep on top of any changes to this file, or any + other part of my Emacs init, I recommend you follow [[http://code.ryuslash.org/dot/tom/emacs/][This project]] + ([[http://code.ryuslash.org/dot/tom/emacs/atom/?h=master][Atom feed]]), which is where I keep my configuration. + +** Preparation + + I could use org-babel to load this file, but I don't like my + initialization file being dependent on too many things, especially + big things, and org is a big thing. It may be strange for you to + read this, as I have placed my entire Emacs configuration in an + org-mode file, but here are the make targets I use to tangle and + subsequently byte-compile my init file: + + #+BEGIN_SRC makefile :tangle no + %.elc: %.el + emacs -Q -batch -eval "(byte-compile-file \"$<\")" + + init.el: init.org + emacs -Q -batch -l "ob-tangle" -eval "(org-babel-tangle-file \"init.org\") + #+END_SRC + + Executing the second target (either through make, or manually) will + get you my Emacs initialization file in plain Emacs Lisp. + + *Note:* If you look at this file in it's org-mode form you will + notice that I actually tangle ~init.org~ into ~init2.el~. This is a + temporary measure so that I can gradually move my configuration + from my existing ~init.el~ file into ~init.org~ without much trouble. + Once I've emptied out my ~init.el~ I will instruct babel to tangle + into ~init.el~, this code already reflects that. + +** The ~oni:~ prefix + + To keep my functions and variables from ever accidentally + interfering with other packages or Emacs internal variables I + prefix all the functions I write and variables I declare with ~oni:~. + You don't have to copy it if you copy anything from this file, as + long as you do it consistently. + +* Use lexical binding + + For some of these functions, and general coolness, lexical binding + is a must. Without it, closures cannot be made. + + #+BEGIN_SRC emacs-lisp :padline no + ;; -*- lexical-binding: t -*- + #+END_SRC + +* Set some personal information + + This information is used by some emacs commands and modules to make + your life easier. + + #+BEGIN_SRC emacs-lisp + (setq user-full-name "Tom Willemse" + user-mail-address "tom@ryuslash.org") + #+END_SRC + +* Clean up some UI elements + + Some elements are only really useful if you use the mouse. Which I + don't, not if I can help it. Only when browsing the web or using the + odd graphical application do I touch the mouse, and even then as + little as I can. + +** Menu bar + + The menu bar is one of the UI elements which work best with mouses. + Sure you can change your toolkit's key bindings to allow you to + more easily navigate, but {{{key(M-x)}}} or {{{key(M-`)}}}[fn:1] + are easier if you don't use the mouse. Long story short: It has got + to go. + + #+BEGIN_SRC emacs-lisp + (menu-bar-mode -1) + #+END_SRC + +** Tool bar + + The toolbar is another such thing, and it takes up quite a bit more + space too. Icons can look pretty cool, but in the end if you're not + going to click them they don't really server much of a purpose. + Again: It has got to go. + + #+BEGIN_SRC emacs-lisp + (tool-bar-mode -1) + #+END_SRC + +** Blinking cursor + + I suppose a blinking cursor doesn't get lost very easily. But on + the other hand, it can induce quite a few more headaches. + + I've noticed that I don't really lose my cursor position all that + much, really, so there doesn't seem to be any point in making it + blink. Here we go again: It has got to go. + + #+BEGIN_SRC emacs-lisp + (blink-cursor-mode -1) + #+END_SRC + +** Line numbers + + As I'm currently using svg-mode-line-themes[fn:2] for my ~mode-line~ I + don't need to show these. Also I didn't really use them much, I + don't often need to know what line I'm on. + + #+BEGIN_SRC emacs-lisp + (line-number-mode -1) + #+END_SRC + +** Tooltips + + Tooltips are another one of those UI elements that aren't quite + keyboard-friendly. As usually this information is shown just as well + in the echo area, this is not necessary. + + #+BEGIN_SRC emacs-lisp + (tooltip-mode -1) + #+END_SRC + +** Cursor type + + I prefer using a bar as a cursor, as opposed to a box. Using a bar + is a better way of representing the location of the cursor, in my + opinion. + + #+BEGIN_SRC emacs-lisp + (setq-default cursor-type 'bar) + #+END_SRC + +** Cursors in inactive windows + + I use a bar cursor that's already pretty thin, so having an even + thinner one in inactive windows is not very clear. Even when I + was using a box cursor I didn't like seeing a hollow box everywhere + my focus /wasn't/. + + #+BEGIN_SRC emacs-lisp + (setq-default cursor-in-non-selected-windows nil) + #+END_SRC + +** Long lines + + Sometimes, very long lines can't help but show up in code. The + default of wrapping lines around to the next line and showing an + image in the fringe is very visually disturbing to me when looking + at code[fn:3]. So I prefer to have it just run off the screen. + + #+BEGIN_SRC emacs-lisp + (setq-default truncate-lines t) + #+END_SRC + +** The default frame + + Usually, most of these settings would be done with functions like + =set-frame-font= or =scroll-bar-mode=, but working with the Emacs + Daemon sometimes creates extra complications, because you might + start a graphical environment at some point (I usually do + immediately), but the startup process isn't. + +*** Internal border + + Set the internal border width to 0. This makes a small difference, + with my current setup it causes my window's width to increase from + 120 to 121. Small, I know, but I'm very greedy when it comes to + screen space. + + #+NAME: default-frame-internal-border + #+BEGIN_SRC emacs-lisp :tangle no + (internal-border-width . 0) + #+END_SRC + +*** A fantastic font + + I've tried several fonts, and all of them were nice, but came up + short on some way. Some didn't have italic variants, some had + dotted zeroes instead of dashed zeroes, some even had entirely + clear zeroes which make them look like ~O~'s, others had + boring-looking parentheses[fn:4]. Not Fantasque Sans + Mono[fn:5][fn:6], it is awesome. If your web browser supports web + fonts you should also see it used in the code blocks here. + + For normal Emacs setups you might use the =set-frame-font= function + like so: + + #+BEGIN_SRC emacs-lisp :tangle no + (set-frame-font "Fantasque Sans Mono 13" nil t) + #+END_SRC + + However, this doesn't work when running Emacs as a Daemon. You + could (especially with lexical binding) add an + =after-make-frame-functions= hook or something similar, but I find + it easier to just specify the font in the =default-frame-alist=. + + #+NAME: default-frame-font + #+BEGIN_SRC emacs-lisp :tangle no + (font . "Fantasque Sans Mono:pixelsize=17") + #+END_SRC + +*** Scroll bar + + The scroll-bar is almost just as informative as the current line + number and buffer position information shown in the (my) mode + line. As I don't usually need to know where I am, other than the + current line number occasionally, and I don't use the mouse, the + scroll bar doesn't add anything and only takes up space. Once + more: It has got to go. + + Normally you would use something along the lines of: + + #+BEGIN_SRC emacs-lisp :tangle no + (scroll-bar-mode -1) + #+END_SRC + + However, this doesn't work when running Emacs as a Daemon. So + instead I specify it in the =default-frame-alist=. + + #+NAME: default-frame-scroll-bar + #+BEGIN_SRC emacs-lisp :tangle no + (vertical-scroll-bars . nil) + #+END_SRC + +*** Setting the option + + So I've explained the reasons for each individual setting, but to + get them to work they have to be put in the =default-frame-alist=. + Here is the final setting: + + #+BEGIN_SRC emacs-lisp :noweb yes + (setq default-frame-alist + `(<> + <> + <>)) + #+END_SRC + +** Frame title + + Show the buffer name in the frame title to make multiple frames + identifiable by the buffer they're showing. + + #+BEGIN_SRC emacs-lisp + (setq frame-title-format '(:eval (concat "GNU Emacs: " (buffer-name)))) + #+END_SRC + +** Don't show dialog boxes + + Unfortunately this doesn't remove /all/ dialog boxes, but at least it + keeps some of them from popping up. According to the docstring it + should only change anything for when the mouse is used, which I + don't ever do, but I still feel safer keeping this in my + configuration. + + #+BEGIN_SRC emacs-lisp + (setq use-dialog-box nil) + #+END_SRC + +** Split windows equally + + When splitting windows, give them all an equal amount of space. For + those very few time that I have more than two windows in my Emacs + frame it is much nicer to have each of them get ~33% space instead + of 50%, 25% and 25%. The way I have my desktop set-up I don't ever + split my windows horizontally. + + #+BEGIN_SRC emacs-lisp + (setq window-combination-resize t) + #+END_SRC + +** Keep the cursor steady when scrolling + + When scrolling through the buffer with, for example, {{{key(C-v)}}} + or {{{key(M-v)}}}, I find it much more intuitive to have the cursor + stay in the relative screen position from before. Otherwise I get + confused every time. + + #+BEGIN_SRC emacs-lisp + (setq scroll-preserve-screen-position t) + #+END_SRC + +** Don't show a mode line for completions + + One of the things I dislike about Emacs is its rigidity concerning + windows and other UI elements. One very simple way to make it + /feel/ less so is to show less of it where possible. A mode line for + completion buffers creates more separation than necessary, and I + can't recall a single time where I've used the completion's mode + line for anything. + + #+BEGIN_SRC emacs-lisp + (add-hook 'completion-list-mode-hook + (lambda () (setq mode-line-format nil))) + #+END_SRC + +* Add org-mode appointments to the diary + + Diary offers reminders, which can be useful when scheduling + appointments. + + #+BEGIN_SRC emacs-lisp + (defadvice org-agenda-redo (after ext:org-agenda-redo-add-appts) + "Pressing `r' on the agenda will also add appointments." + (setq appt-time-msg-list nil) + (org-agenda-to-appt)) + #+END_SRC + +* Close ansi-term buffer after exit + + After the ansi-term process ends it leaves a buffer. I don't use + ansi term in such a way that this has ever been useful, so just kill + the ansi-term buffer after the process quits, no matter the exit + status. Usually this comes about when I press {{{kbd(C-d)}}} at the + command prompt. + + #+BEGIN_SRC emacs-lisp + (defadvice term-handle-exit (after oni:kill-buffer-after-exit activate) + "Kill the term buffer if the process finished." + (kill-buffer (current-buffer))) + #+END_SRC + +* Stumpwm integration + + This variable, macro and function help with integrating Emacs and + Stumpwm. They are used by some other functions to make the two seem + extra connected. + + #+BEGIN_SRC emacs-lisp + (defvar oni:stumpish-program + (expand-file-name + "~/.local/share/quicklisp/local-projects/stumpwm/contrib/util/stumpish/stumpish") + "The location of the stumpish executable.") + + (defmacro oni:stumpwm (&rest body) + "Execute BODY in stumpwm." + (declare (indent 0)) + `(call-process oni:stumpish-program nil nil nil + ,(format "eval '%S'" `(progn ,@body)))) + + (defun oni:stumpwm-command (cmd) + "Execute CMD in stumpwm." + (call-process oni:stumpish-program nil nil nil cmd)) + + (defun oni:stumpwm-echo (message) + (call-process oni:stumpish-program nil nil nil (format "echo %s" message))) + #+END_SRC + +** Fall back on stumpwm when moving around + + Using the function specified in [[Stumpwm integration]] wrap the + =windmove-do-window-select= function and catch any error produced, + hoping it's the error that there's no more window to move to and + then request that stumpwm move the focus in the same direction as + windmove would have. + + #+BEGIN_SRC emacs-lisp + (defadvice windmove-do-window-select + (around oni:windmove-stumpwm activate) + "If no window can be moved to, move stumpwm." + (condition-case err + ad-do-it + (error (oni:stumpwm-command + (format "move-focus %s" (ad-get-arg 0)))))) + #+END_SRC + +* Don't just quit Emacs with {{{key(C-x C-c)}}} in the daemon + + When working with Emacs as a daemon, which I do almost all of the + time, I prefer using {{{key(C-x C-c)}}} to close the current frame + instead of the entire session. Before this change I would + occasionally close my session by mistake. + + #+BEGIN_SRC emacs-lisp + (defun oni:close-client-window () + "Close a client's frames." + (interactive) + (server-save-buffers-kill-terminal nil)) + + (when (daemonp) + (global-set-key (kbd "C-x C-c") 'oni:close-client-window)) + #+END_SRC + +* Don't minimize the frame with {{{key(C-z)}}} + + One of the more annoying things that can happen is accidentally + minimizing the frame you're working with. This doesn't really matter + if you're working on a normal stacking window manager, but with a + tiling window manager and no task bar this just causes the Emacs + frame to hang until it is refocused or disappear with no way to get + it back. + + #+BEGIN_SRC emacs-lisp + (when (or window-system (daemonp)) + (global-unset-key (kbd "C-z"))) + #+END_SRC + +* Use the right dictionary + + One of the caveats of using two (or more) languages in a single + installation of Gnus is that ispell sometimes gets confused. Having + come across a stackoverflow question[fn:7] about just this subject + it was easy to modify the source code posted there to come up with + this. + + *Note:* See my [[Function declarations][note]] on function declarations about the use of + =declare-function=. + + #+BEGIN_SRC emacs-lisp + (declare-function message-narrow-to-headers-or-head "message") + (declare-function message-fetch-field "message") + + (defun oni:switch-ispell-dictionary () + (save-excursion + (message-narrow-to-headers-or-head) + (let ((from (message-fetch-field "From"))) + (ispell-change-dictionary + (if (string-match (rx "@aethon.nl>" eol) from) "nl" "en"))))) + + (add-hook 'message-setup-hook 'oni:switch-ispell-dictionary) + #+END_SRC + +* Don't let shr use background color + + Reading mail in Gnus is very nice, but shr has become a little too + good at its job. Add to this the many occasions when a background is + specified without specifying a foreground, plus a color theme that + is the inverse of what is usually expected, and you can get + hard-to-read HTML messages, gray foreground and gray background. + + I've looked at the other possible renderers, but they don't look + very nice compared to shr. So just remove its ability to add + background colors. + + *Note:* See my [[Function declarations][note]] on function declarations about the use of + =declare-function=. + + #+BEGIN_SRC emacs-lisp + (declare-function shr-colorize-region "shr") + + (defun oni:shr-colorize-remove-last-arg (args) + "If ARGS has more than 3 items, remove the last one." + (if (> (length args) 3) + (butlast args) + args)) + + (with-eval-after-load 'shr + (advice-add #'shr-colorize-region :filter-args + #'oni:shr-colorize-remove-last-arg)) + #+END_SRC + +* Optimized ~with-eval-after-load~ + + First offered [[http://www.lunaryorn.com/2013/05/01/byte-compiling-eval-after-load.html][here]] and then later updated [[http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load.html][here]] (when + ~with-eval-after-load~ was added). Makes for very nice on-demand + settings loading. + + #+BEGIN_SRC emacs-lisp + ;; http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load/ + (defmacro stante-after (feature &rest forms) + "After FEATURE is loaded, evaluate FORMS. + + FEATURE may be an unquoted feature symbol or a file name, see + `eval-after-load'." + (declare (indent 1) (debug t)) + `(,(if (or (not byte-compile-current-file) + (if (symbolp feature) + (require feature nil :noerror) + (load feature :no-message :no-error))) + `progn + (message "stante-after: cannot find %s" feature) + 'with-no-warnings) + (with-eval-after-load ',feature ,@forms))) + #+END_SRC + +* Remember SQL input + + Remembering input between sessions is a good thing. + + #+BEGIN_SRC emacs-lisp + (stante-after sql + (setf sql-input-ring-file-name + (expand-file-name "~/.emacs.d/sqliinput"))) + #+END_SRC + +* Lazily load some buffers + + Don't load all buffers right away. Having a lot of buffers and + switching between projects a lot can take up quite a bit of time. + + *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. + + #+BEGIN_SRC emacs-lisp + (defvar desktop-restore-eager) + (setq desktop-restore-eager 5) + #+END_SRC + +* Fix some term keybindings + + =ansi-term= passes along a lot of characters correctly, but things + like =forward-delete-word= are not, by default. This is confusing when + you see one thing and another is sent. Passing the correct keys + directly to the terminal fixes this problem. + + *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 term-raw-map) + (declare-function term-send-raw-string "term") + + (defun oni:set-term-keys () + (cl-flet ((zcommand (key) + (lambda () + (interactive) (term-send-raw-string key)))) + (define-key term-raw-map + (kbd "C-") (zcommand "\C-H")))) + + (add-hook 'term-mode-hook #'oni:set-term-keys) + #+END_SRC + +* Ask for a ~y~ or ~n~, not ~yes~ or ~no~. + + Emacs starts out asking for you to type ~yes~ or ~no~ with most + important questions. It is possible that this is used for such + important questions where accidentally saying ~yes~ when you meant ~no~ + would be catastrophic (or at least could be). However, I've never + (so far) had this problem, and I find it quite tedious to have to + write out ~yes~ or ~no~ and then press {{{kbd(RET)}}}, give me a simple + ~y~ or ~n~ with no {{{kdb(RET)}}} required and I'm quite happy. + + #+BEGIN_SRC emacs-lisp + (defalias 'yes-or-no-p 'y-or-n-p) + #+END_SRC + +* Use =hippie-expand=, not =dabbrev-expand= + + I've never actually used =dabbrev-expand=, and only rarely use + =hippie-expand= really, but since =hippie-expand= also includes a + =dabbrev= expander and a lot more than just that, it seems alright to + do this. + + #+BEGIN_SRC emacs-lisp + (defalias 'dabbrev-expand 'hippie-expand) + #+END_SRC + +* Setting up =load-path= + + First, to help, I create a function that takes a path, adds it to + =load-path= and then checks to see if there is a file named + ~loaddefs.el~ in the given path. If there is, it loads it. This + ~loaddefs.el~ file is something that is created from autoload cookies + in the files in some of these paths. + + Since the =load-path= is also important during byte-compilation, this + function should be defined both at run-time and compile-time. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (defun oni:loadpath-add-and-autoload (path) + "Add PATH to `load-path' and load a `loaddefs.el' if it exists." + (add-to-list 'load-path path) + (let ((loaddefs (concat path "/loaddefs.el"))) + (when (file-exists-p loaddefs) + (load loaddefs))))) + #+END_SRC + + After that I add some directories to my =load-path= so I can use these + libraries when wanted. One of these is the ~site-lisp~ directory in my + ~.emacs.d~ directory, which is where I keep most of my personal + non-ELPA modules (like module-specific initialization files). There + are also some directories I include in ~vendor-lisp~, which is where I + keep modules that I didn't write myself and, for some reason, can't + or don't want to use ELPA for. Again it is important to realize that + this information is relevant both at run-time and compile-time, so + we wrap it with an =eval-and-compile=. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (mapc #'oni:loadpath-add-and-autoload + '("~/.emacs.d/site-lisp" + "~/.emacs.d/vendor-lisp/mozrepl" + "~/.emacs.d/vendor-lisp/eap" "/usr/share/emacs/site-lisp" + "/usr/lib/node_modules/tern/emacs/" + "~/.emacs.d/vendor-lisp/habitrpg.el"))) + #+END_SRC + +* Some unconditional settings + + Here are some settings that either need to be changed before certain + modules load, or that don't belong in any specific module. + +** Gnus init file + + I put my gnus initialization file right where I put all my + module-specific initialization files. Gnus is special, though: It + loads the file every time you start it. That keeps it from using a + simple =(eval-after-load 'gnus '(load "gnus-init"))=. + + *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. + + #+BEGIN_SRC emacs-lisp + (defvar gnus-init-file) + (setq gnus-init-file "~/.emacs.d/site-lisp/gnus-init") + #+END_SRC + +** Turn off bidirectional text + + To speed things up a little, and because I have no contacts at all + (so far) who use right-to-left text, there is no reason for me to + use bidirectional text. For this reason I tell Emacs to always use + left-to-right by default, instead of checking each paragraph. + + #+BEGIN_SRC emacs-lisp + (setq-default bidi-paragraph-direction 'left-to-right) + #+END_SRC + +** Don't use tabs + + There is a war going on out there. Actually there are several, but + the one I'm talking about here is the one about tabs vs. spaces. I + have been deeply entrenched in the spaces camp for quite a while. + Indentation always gets screwy for me if I don't use the exact same + =tab-width= everyone else uses. I just like the consistency of using + spaces. + + #+BEGIN_SRC emacs-lisp + (setq-default indent-tabs-mode nil) + #+END_SRC + +** Use four spaces for indentation + + I once, long ago, started out with using eight spaces for each + level of indentation. Although I think, technically, I was using + tabs. This means that even just 3 levels of indentation take up a + /huge/ amount of space that can't be used for anything else. Since I + also try to limit the length of the lines in my code, this can make + for very little code per line. + + I also tried (and enjoyed) two spaces, but after a while, looking + at bigger files, I noticed that it all becomes a blur. Two spaces + is not a big-enough visual difference to make code read nicely, in + my opinion. + + So far, I have quite enjoyed four spaces for most code[fn:8]. + + #+BEGIN_SRC emacs-lisp + (setq-default tab-width 4) + #+END_SRC + +** Keep the message buffer from growing too large + + Keep at most one-thousand messages in the ~*Messages*~ buffer. I can + leave my Emacs session running for quite long times, sometimes + days, at a time. If there are a lot of messages it can get a little + tricky to manage/search. + + #+BEGIN_SRC emacs-lisp + (setq message-log-max 1000) + #+END_SRC + +** Don't start =elnode= when Emacs starts + + Elnode is an awesome project and I'm still looking for a moment + where I have the inspiration and time to actually do something with + it. I started at some point, but then I couldn't get the cookies to + work and I switched over to using Common Lisp, only to eventually + stop developing the project because there was not chance of it + seeing any use in the foreseeable future. + + There is one little annoyance, though, and that is the fact that + elnode will start itself up when Emacs starts. I don't want that. + + This bit of code can't be put in an =eval-after-load= or anything + like that because by the time it would be evaluated, elnode would + already have started. + + *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. + + #+BEGIN_SRC emacs-lisp + (defvar elnode-do-init) + (setq elnode-do-init nil) + #+END_SRC + +* Show python package name instead of file name + + When working with python, knowing which package I'm in usually tells + me more about what I'm doing than the file name, especially when + working with django where almost every app will have a ~tests.py~ and + a ~models.py~. Of course =uniquify= fixes this pretty well too, though + in this case, it's less cool (imo). + + First we define two functions that help us determine the package + name of the current file and the parent package name of the current + file. Finally we define a third function which determines the full + package name of the current buffer. + + #+BEGIN_SRC emacs-lisp + (defun oni:python--get-current-module-name () + "Get the name of the current python module. + + This is very simply just the filename of the current buffer with + the extension and pyath removed." + (file-name-sans-extension + (file-name-nondirectory (buffer-file-name)))) + + (defun oni:python--get-parent-module-name (&optional dir) + "This gets the currend file's parent module. + + This function recursively gathers the parent package name of + either DIR or the current buffer's file name. Any directory where + an `__init__.py' file is found is considered to be a package. + + This function returns either the parent package, with its + parents, or nil if the current directory isn't a python + package.." + (let* ((base (directory-file-name + (file-name-directory (or dir (buffer-file-name))))) + (package (file-name-nondirectory base))) + (if (file-exists-p (concat base "/__init__.py")) + (let ((parent (oni:python--get-parent-module-name base))) + (if parent + (concat parent "." package) + package)) + nil))) + + (defun oni:python-package-name () + (let ((current-module (oni:python--get-current-module-name))) + (if (file-exists-p "__init__.py") + (concat (oni:python--get-parent-module-name) + "." current-module) + current-module))) + #+END_SRC + + After all this we make Emacs show the package name rather than the + file name in the mode-line. + + #+BEGIN_SRC emacs-lisp + (defun oni:python-package-buffer-identification () + "Have `mode-line-buffer-identification' show the python package name." + (setq mode-line-buffer-identification + '(:eval (oni:python-package-name)))) + + (add-hook 'python-mode-hook #'oni:python-package-buffer-identification) + #+END_SRC + +* Add some known symbols for .conkerorrc/init.js to js2-mode + + Conkeror has a lot of functions, and I don't like seeing them all as + unknowns. So add them to known symbols. + + *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. + + #+BEGIN_SRC emacs-lisp + (defvar js2-additional-externs) + + (defun oni:js2-add-conkeror-symbols () + "Add known/used conkeror symbols to additional externs." + (when (string-suffix-p ".conkerorrc/init.js" (buffer-file-name)) + (setq js2-additional-externs + '( ;; Functions + "add_hook" "check_buffer" "co_return" "content_buffer" + "define_browser_object_class" "define_key" "define_webjump" + "dumpln" "get_current_profile" "get_home_directory" + "get_recent_conkeror_window" + "hints_minibuffer_annotation_mode" "interactive" "load_spec" + "load_spec_uri_string" "load_url_in_new_buffer" "make_file" + "make_uri" "mode_line_adder" + "open_download_buffer_automatically" "prefix_completer" + "read_browser_object" "register_user_stylesheet" + "remove_hook" "require" "send_http_request" "session_pref" + "shell_command_blind" "theme_load" + ;; Variables + "Cc" "Ci" "browser_object_history_url" "browser_object_links" + "buffer_count_widget" "buffer_icon_widget" "content_buffer" + "content_buffer_form_keymap" "content_buffer_normal_keymap" + "content_buffer_text_keymap" "content_policy_accept" + "content_policy_bytype" "content_policy_reject" "cwd" + "default_base_keymap" "default_global_keymap" + "downloads_status_widget" "external_content_handlers" + "hint_digits" "load_paths" "read_buffer_show_icons" + "read_url_handler_list" "session_auto_save_auto_load" + "theme_load_paths" "title_format_fn" "url_remoting_fn" + ;; Keyword argument + "$alternative" "$browser_object" "$completer" "$completions" + "$initial_value" "$options" "$prompt" "$sort_order" + "$use_bookmarks" "$use_history" "$use_webjumps")))) + + (add-hook 'js2-init-hook #'oni:js2-add-conkeror-symbols) + #+END_SRC + +* Teach eww about tags + + Strangely enough, ~eww~ doesn't seem to be aware of == 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
+
+* 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
+    (defvar geiser-default-implementation)
+
+    (with-eval-after-load 'geiser
+      (setq geiser-default-implementation 'guile))
+  #+END_SRC
+
+* Setup eww-lnum
+
+  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
+
+* Don't compile scss files
+
+  By default =scss-mode= tries compiling a file each time it's saved. I
+  don't have SCSS properly installed globally so this always fails,
+  highly annoying.
+
+  #+BEGIN_SRC emacs-lisp
+    (defvar scss-compile-at-save)
+
+    (with-eval-after-load 'scss-mode
+      (setq scss-compile-at-save nil))
+  #+END_SRC
+
+* 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
+
+* 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/
-- 
cgit v1.2.3-54-g00ecf