Creation and conservation of computer files (C3F)

Table of Contents

1 Audience 1

Who should be reading this? Possibly…

  • Entire document: Software engineers who want to do the above 2
  • Decisions & Assembly: Existing Emacs users… daily usage and non-trivial customization An interest in using cask and org-mode literate programming are the only thing that would motivate anyone to read this really.

This is an unfunished and experimental document. All successes with it may be attributed to all of the folks who provided these wonderful tools. All failures with it may be attributed to me.

Why should they be reading this?

The expectations of life depend upon diligence; the mechanic that would perfect his work must first sharpen his tools. 3

2 Cogito ergo sum 4

What was I thinking?

creation
"the act of producing or causing to exist" 5
conservation
"prevention of injury, decay, waste, or loss" 6
computer files
"a file maintained in computer-readable form" 7

3 Means 8

How do most people do it?

COTS
edit, VI, Emacs, IntelliJ Idea, Visual Studio 9
Bespoke
custom software 10

4 Madness 11

What about their raison detre? 12

  • Wonderful, wonderful stock tooling, 80%
  • Can tool-makers build it perfectly for us all? 13

5 Goal

What is my measure of success?

To provide an environment in which the creation and conservation of computer files may occur with ease

6 Decision

GNU Emacs is an extensible, customizable text editor 14

7 Methodology 15

How will I customize it?

Agile 16

  • Product Backlog
  • Sprint Backlog
  • Review, Refine, and Reiterate
  • COTS libraries
  • Capture rationale and reasons along with things I did or didn't do and why
  • Includes links to everything

Note: How you break up the initialization of a system like Emacs is mostly personal preference. Although org-mode (Babel) lets you tell a story, I was coming from a pretty structured config file to begin with. In the future, it might be interesting to look at this system from scratch in terms of doing literate programming. Fortunately, it provides that freedom out of the box.

7.1 Medium

How will explain what I did?

  • Audience-appropriate presentations
  • Reproducible research
  • Reusable data structures

8 Developmental Values

8.1 Traits

  • ☑ Pleasing user experience
  • ☑ Pervasive orthogonality 17

8.2 Coding

  • ☑ Completion
  • ☑ Debugging
  • ☑ Intellisense
  • ☑ Templates

8.3 Editing

  • ☑ Auto-indenting
  • ☑ Binary file editing, hex editor
  • ☑ Code folding
  • ☑ Code formatting
  • ☑ Diff'ing
  • ☐ Heavily used languages: ☑ CSS, ☑ Elisp, ☑ HTML, ☑ Graphviz, ☑ JSON, ☑ JavaScript, ☑ Make, ☑ Markdown, ☐ R, ☑ Scheme, ☑ shell
  • ☑ Incremental selection
  • ☑ LaTeX
  • ☑ SEXP Support
  • ☑ Spell-checking
  • ☑ Structured navigation
  • ☑ Syntax highlighting
  • ☑ Tab management

8.4 Development

  • ☑ Build tools: make
  • ☑ Copyright notice, analysis, and standards
  • ☑ Dependency management
  • ☑ Diagramming
  • ☑ UML
  • ☑ Version control: git, svn, bzr, cvs, rcs
  • ☑ Workflow

9 Operational Values

9.1 Fonts

  • ☑ Focus on easily-screen-readable, mono-spaced
  • ☑ Research suggests that san-serif fonts are easier to read 18 , 19 , 20 , 21 , 22 , 23
  • ☑ Research suggests that color doesn't matter; only contrast 24, 25 , 26 , 27 , 28 , 29 , 30 , 31
  • ☑ Unicode support is critical

9.2 Images

  • ☑ Ascii art

9.3 Spreadsheet

  • ☑ Calculation
  • ☑ Data management
  • ☑ Import/Export

9.4 Files

  • ☑ Auto-save & synchronize
  • ☑ Encryption
  • ☑ File-system/directory management
  • ☑ Project structure
  • ☑ Search everywhere

9.5 Commands

  • ☑ Key recording
  • ☑ Macros
  • ☑ History of all things: files, commands, cursor locations
  • ☑ Undo

9.6 Publishing

  • ☑ Code
  • ☑ Multiple formats: HTML, JS, PDF

9.7 Terminal

  • ☑ Cross-platform shell
  • ☑ Games

9.8 Remote file access and management

  • ☑ SSH
  • ☑ SCP

10 Decisions

Given values and restrictions, review, identify, and evaluate available options.

10.1 Font (Appearance)

The studies cited above indicate that the two major factors that contribute to readabilty of a document are contrast and font-face. Sayre's law 32 however demands that any number of other things are critical to how your IDE looks! That is OK. This section captures some of the basics to getting the system looking how I like it.

This is a san-serif, portable, massively Unicode supported font. You may easily change the font size using gcr/text-scale-increase and gcr/text-scale-decrease; font information appears in the =*Message=* buffer and also the mini-buffer. The font size will be the same everywhere; as it is easier to work between graphic and console mode with that consistency. You may bypass that using the built in functions. The color theme seems to provide excellent contrast, though I can't decipher what the creator is actually saying about them. For a while I went between the light and dark solarized theme, and finaly accepted that I'm happy with light for documents and dark for programs. That is not scientific, and I'm OK with that. Fortunately you can theme per buffer. Unfortunately, it doesn't quite work perfectly. It wasn't a big deal until it broke org's export to HTML. Since I needed that especially for right now, I decided to stick with the dark theme, as it is more familiar.

Sometimes you don't like how a characters looks, or don't have access to Unicode. In such cases, pretty-mode displays substitutions for certain occurences of flagged strings, for example replacing the world lambda with the symbol λ.

(defconst gcr/font-base "DejaVu Sans Mono" "The preferred font name.")
(defvar gcr/font-size 10 "The preferred font size.")
(load-theme 'solarized-dark)
(require 'pretty-mode)

10.2 UXO (Traits, user experience/orthogonality)

10.2.1 Windows 33

Menu bars are not required. 34

(menu-bar-mode 0)

Make it really obvious where the 80th column sits. 35

(setq-default fill-column 80)

The cursor should not blink. 36

(blink-cursor-mode 0)
(when (display-graphic-p)
  (setq-default cursor-type 'box))
(setq x-stretch-cursor 1)

Show line numbers everywhere. 37

(global-linum-mode 1)

Activate syntax highlighting everywhere. 38

(global-font-lock-mode 1)

Visualize parentheses a certain way. 39

(setq blink-matching-paren nil)
(show-paren-mode t)
(setq show-paren-delay 0)
(setq show-paren-style 'expression)

Don't use audible bells, use visual bells. 40

(setq ring-bell-function 'ignore)
(setq visible-bell t)

10.2.2 Frames 41

Make the title frame something special. 42

(setq frame-title-format '("the ultimate..."))

The scroll bars are actually quite nice. 43

(scroll-bar-mode 1)

The tool bars are not very nice. 44

(tool-bar-mode 0)

Browse URLs in a real browser; nothing against W3C. 45

(setq browse-url-browser-function 'browse-url-generic)
(setq browse-url-generic-program "chromium-browser")

Let the mousewheel move the cursor in a sane manner. 46

(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
    (setq mouse-wheel-progressive-speed nil)

10.2.3 Buffers 47

It is nice to have an indicator of the right column that indicates the maximum depth of the line. My favorite package is fill-column-indicator 48. Its use shows up in almost all of the modes. While working on this build though the export to HTML included junk characters, so I had to disable it, at least in Lispy modes.

Keep open files open across sessions. 49

(desktop-save-mode 1)
(setq desktop-restore-eager 10)

Automatically save every buffer associated with a file. 50

(require 'real-auto-save)

Make two buffers with the same file name open distinguishable. 51

(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)

Support transparent AES encryption of buffers. 52 See also for library paths 53

(add-to-list 'load-path "/usr/share/emacs/site-lisp/ccrypt")
(require 'ps-ccrypt "ps-ccrypt.el")

With modern VCS, backup files aren't required. 54

(setq backup-inhibited 1)

The built in auto save isn't required either because of the above. 55

(setq auto-save-default nil)

Ban whitespace at end of lines, globally. 56

(add-hook 'write-file-hooks
          '(lambda ()
             (gcr/delete-trailing-whitespace)))

The world is so rich with expressivity. Although Unicode may never capture all of the worlds symbols, it comes close. 57 , 58 , 59

(prefer-coding-system 'utf-8)
(when (display-graphic-p)
  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

Emacs has a powerful buffer tracking change system. Unfortunately, I don't understand any of it. Undo should "just work".

(require 'undo-tree)
(global-undo-tree-mode 1)
(eval-after-load "diminish"
  '(progn
     (eval-after-load "undo-tree"
       '(diminish 'undo-tree-mode "↺"))))

10.2.4 Modeline 60

The modlines is capable of so many things. Though I use it for few, I value it greatly.

It is nice to see the column number, if you are counting columns (not calories). 61

(column-number-mode 1)

It is a pain to look at the clock in the GUI bar. 62

(display-time-mode 1)
(setq display-time-format "%l:%M%p")

When you load modes, most of them show up in the minibuffer. After you read their name a few thousand times, you eventually quite forgetting that you loaded them and need a diminished reminder. 63

(require 'diminish)

10.2.5 Mark and Region 64

When you start typing and text is selected, replace it with what you are typing, or pasting, or whatever. 65

(delete-selection-mode 1)

10.2.6 Minibuffer 66

You will want to configure this at some point.

Make it easier to answer questions.

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

It often displays so much information, even temporarily, that it is nice to give it some room to breath. 67

(setq resize-mini-windows t)
(setq max-mini-window-height 0.33)

10.3 Modes (functionality)

The purpose of this section is to put some visiblity on the modes, how they are used, and where.

10.3.1 Custom variables

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(custom-safe-themes (quote ("fc5fcb6f1f1c1bc01305694c59a1a861b008c534cae8d0e48e4d5e81ad718bc6" default))))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

10.3.2 Configuration

  1. Intellisense (Auto Completion) 68

    Can you thrive and profit without auto-completion? Surely. The feature is kind of a comfort blanket for most of us; you will never fail to bild a system without it (unless you are using Java, then you need IntelliJ). Still it is quite nice to have popup documentation.

    (require 'fuzzy)
    (require 'auto-complete)
    (require 'auto-complete-config)
    (ac-config-default)
    (setq ac-auto-start nil)
    (ac-set-trigger-key "TAB")
    (eval-after-load "diminish"
      '(progn
         (eval-after-load "auto-complete"
           '(diminish 'auto-complete-mode "↝"))))
    
  2. Whitespace management 69

    Do you need to see tabs and other control characters? Usually, yes.

    (require 'whitespace)
    (setq whitespace-style '(trailing lines tab-mark))
    (setq whitespace-line-column 80)
    (global-whitespace-mode 1)
    (eval-after-load "diminish"
      '(progn
         (eval-after-load "whitespace"
           '(diminish 'global-whitespace-mode "ᗣ"))
         (eval-after-load "whitespace"
           '(diminish 'whitespace-mode ""))))
    
  3. Color visualizing 70

    Nothing against the multitude of RGB hex value web finder web pages… it is just convenient to have it built right in.

    (require 'rainbow-mode)
    (eval-after-load "diminish"
      '(progn
         (eval-after-load "rainbow-mode"
           '(diminish 'rainbow-mode "ω"))))
    
  4. Templating 71

    Code complating is nice to have; but the second you install it and learn how to use it, you will never find the need to again. Accept it and move on.

    (require 'yasnippet)
    (yas-load-directory (concat (cask-elpa-dir)
                                "/yasnippet-20140306.5/snippets"))
    (eval-after-load "diminish"
      '(progn
         (eval-after-load "yasnippet"
           '(diminish 'yas-minor-mode "✂"))))
    (yas-global-mode 1)
    
  5. Searching / Finding 72 , 73

    There are many ways to easily find what you need, for a command, for a file, and this mode seems to be a quite nice way.

    (require 'ido)
    (require 'flx-ido)
    (ido-mode 1)
    (ido-everywhere 1)
    (setq ido-create-new-buffer 'always)
    (flx-ido-mode 1)
    (setq ido-use-faces nil)
    
  6. Project management 74

    Not everyone likes projects, but I do. There is no perfect middle ground though, that is until this library came along. It is such a joy to use.

    (projectile-global-mode 1)
    (eval-after-load "diminish"
      '(progn
         (eval-after-load "projectile"
           '(diminish 'projectile-mode "⌕"))))
    
  7. Expression Management 75

    There are a lot of nice options 76 , 77 , 78 , 79 , 80. For the longest time, paredit was all that I used, but then I started using Emacs for everyone else besides Lisp and was kind of stymied not having great expression management tools. Smartparens seems to have emerged as king, so here it sits. While I was setting up the new config I set this up last… that was a major mistake. After using a good symbolic expression management tool, you quickly forget the nightmare of having to keep expressions balanced yourself. Sure we did fine with VI… but it is so nice to have the tool do it for you. Remember what Olin Shivers said?

    I object to doing things that computers can do.

    You get a lot of niceties that you would expect like balanced brackets and since there is a strict mode it acts just like Paredit. Additionally you may wrap selections with pairs, auto-escape strings that occur within other strings, and showing matching pairs (of any supported form).

    (require 'smartparens-config)
    (smartparens-global-strict-mode +1)
    (show-smartparens-global-mode +1)
    (eval-after-load "diminish"
      '(progn
         (eval-after-load "smartparens"
           '(diminish 'smartparens-mode "⚖"))))
    
  8. Remote file access 81

    TRAMP stands for "Transparent Remote (file) Access, Multiple Protocol". It is really, really beautiful.

    (setq tramp-default-user "gcr")
    
  9. Selection style 82

    IntelliJ Idea is yet again to blame for being awesome; even the author of this library suffers, or rather enjoys, this phenomenon. When you make a selection of text you typically want to do it in a smart way, selecting the first logical block, then expanding logically outwards, and so on. It could mean selecting a variable, then its definition statement, and then the entire code block for example. Before now I really never had many uses for the C-u universal argument functionality for method calls, but if you pass in a negative value before calling er/expand-region it will have the nice feature of reversing its incremental selection.

    (require 'expand-region)
    (global-set-key (kbd "C-=") 'er/expand-region)
    
  10. File-system/directory management 83

    The last file or filesyste management tool that I used wast Norton Commander 84 and then Midnight Commander 85, but my usage was pretty basic. Beyond those basics, I can do even more, basic stuff, in bash. Lately I've wanted something a little more consistent, powerful, and memorable, and that led me here. Dired is a user-interface for working with your filesystem; you select files and directories and then choose what to do with them. The ability to customize what you see is included out of the box, and there are additional helper packages 86, too.

    You can use the usual machinery to work with the files. Highlight a region and operation selections occur for all files in that region. Commands are sheduled, and then executed, upon your command. Files can be viewed in modify or read-only mode, too. There is an idea of =mark=ing files, which is to select them and perform operations on the marked files. There are helper methods for most things you can think if like directories or modified-files or whatever, meaning you can use regexen to mark whatever you like however you like. If that suits you, then don't be afraid of using the regular expression builder 87 that is built into Emacs. Bulk marked file operations include additionally copying, deleting, creating hard links to, renaming, modifying the mode, owner, and group information, changing the timestamp, listing the marked files, compressing them, decrypting, verifying and signing, loading or byte compiling them (Lisp files).

    g updates the current buffer; s orders the listing by alpha or datetime.

    find-name-dired beings the results back into Dired, which is nifty.

    Wdired lets you modify files directly via the UI, which is interesting. Image-Dired lets you do just that.

    = creates a new directory. dired-copy-filename-as-kill stores the list of files you have selected in the kill ring. dired-compare-directories lets you perform all sorts of directory comparisons, a handly tool that you need once in a while but definitely do need.

    (setq dired-listing-switches "-alh")
    (setq dired-recursive-deletes  +1)
    (require 'dired-details+)
    (setq-default dired-details-hidden-string "")
    
  11. Save history of all things 88 , 89 , 90

    It is nice to have commands and their history saved so that every time you get back to work, you can just re-run stuff as you need it. It isn't a radical feature, it is just part of a good user experience.

    (setq savehist-file "~/.emacs.d/savehist")
    (savehist-mode +1)
    (setq savehist-save-minibuffer-history +1)
    (setq savehist-additional-variables
          '(kill-ring
            search-ring
            regexp-search-ring))
    
  12. Code folding 91 , 92

    Code folding really isn't a hugely important function. You just use it once in a while and you notice it when you don't have it. For years I used this 93 and it is fine, but I figured I ought to stick with a more feature rich option, just to give it a try. Here are some of the other options: 94, 95, 96, 97. If you know org-mode, then using that style of control makes it easier to use then the built in bindings.

    (setq hs-hide-comments-when-hiding-all +1)
    (setq hs-isearch-open t)
    (require 'hideshow-org)
    ; Displaying overlay content in echo area or tooltip
    (defun display-code-line-counts (ov)
          (when (eq 'code (overlay-get ov 'hs))
            (overlay-put ov 'help-echo
                         (buffer-substring (overlay-start ov)
                                          (overlay-end ov)))))
    
        (setq hs-set-up-overlay 'display-code-line-counts)
    ; How do I get it to expand upon a goto-line?
    (defadvice goto-line (after expand-after-goto-line
                                    activate compile)
            "hideshow-expand affected block when using goto-line in a collapsed buffer"
            (save-excursion
               (hs-show-block)))
    
  13. Copyright 98

    Copyright management includes only two problems: keeping the near up to date and choosing the right one. The built in functions will insert a generic copyright and also update the year, and that is pretty nice. It would be nice to have something like this 99 created, though. Even an OSS license chooser would be nice 100, but I haven't found a nice option yet.

  14. Spellchecking 101

    There are two ways to spell-check: run-at-a-time or interactive. Both delegate the actual checking to aspell, ispell, and hunspell. Both styles are quite nice options, and flyspeel will even integrated with compilers to help report those kinds of errors to you, too, but my personal preference for now is run-at-a-time. The taxpayers didn't pay so much to make flyspell have to do all the hard work for me. aspell most UNI*, running ispell from Emacs just does the right thing.

  15. Binary file editing 102 , 103

    Long ago it was quite common to edit binary files if not for adding lots of cheats to games then to see CAFEBABE written in Java class files (if you can't enjoy either of those things then you are too serious). Hexl mode comes built into Emacs, and it is great to know that it is there.

  16. Games 104

    Sometimes you need a break, and you aren't a gamer any more, but that doesn't mean you can't have fun. life and doctor alone will give you something to ponder and practice not taking too seriously.

  17. LaTeX 105 , 106

    There is great support for LaTeX via AUCTeX and Ebib. For a while I used TeXWorks 107 and I was and remain very happy with it. Two things drew me back to Emacs for doing TeX primarily org-mode support for Ebib for managing my citation database. There is nothing more to it than that. This secion is a bit bare at the moment, as I will be filling it up as I move back to doing my work here. Perhaps a bigger project is figuring out where XeTeX fits in my future. 108 RefTeX looks too quite helpful 109 especially considering how well it seems to integrate with org-mode.

  18. Command execution helper 110

    When I call commands, I usually end up running the same commands over and over. There are of course keybdings to deal with this, and also command history. What I really prefer though is just being able to type an abbreviation for the command to access it, like org-html-export-to-html for example. Smex makes it happen.

    (require 'smex)
    (smex-initialize)
    (global-set-key (kbd "M-x") 'smex)
    (global-set-key (kbd "M-X") 'smex-major-mode-commands)
    (global-set-key (kbd "C-c C-c M-x") 'execute-extended-command)
    

10.3.3 Application Modes 111 , 112

When I set about on this project, I had ideas about how this document would look. The decent ideas worked out well. The good ideas were bad, and the unexpected ideas were delightful. I had though that athis section would be very graphical, but the more I work on it, the simpler it seems to be when you split it up in the respective sections. Originally I had wanted to use org tables for nearly everything, but now I question that desire (thought it is a great feature). The mistake that I made was not new to me and is suffered by all macro writers… guessing the solution instead of waiting for experience and extracting it from there. As it turns out, I am human.

  1. Auto Modes 113
    (setq auto-mode-alist
          (append
           '(("\\.scm\\'" . scheme-mode)
             ("\\.rkt\\'" . scheme-mode)
             ("\\.ss\\'" . scheme-mode)
             ("\\.sls\\'" . scheme-mode)
             ("\\.sps\\'" . scheme-mode)
             ("\\.html\\'" . web-mode)
             ("\\.json\\'" . web-mode)
             ("\\.asc" . artist-mode)
             ("\\.art" . artist-mode)
             ("\\.asc" . artist-mode))
           auto-mode-alist))
    
  2. All modes

    Anything that should always happen goes here.

    (add-hook 'before-save-hook 'whitespace-cleanup)
    
  3. Text
    (defun gcr/text-mode-hook ()
      (rainbow-mode)
      (turn-on-real-auto-save)
      (fci-mode)
      (gcr/untabify-buffer-hook))
    
    (add-hook 'text-mode-hook 'gcr/text-mode-hook)
    
  4. Org 114 , 115
    (require 'org)
    
    (defun gcr/org-mode-hook ()
      (fci-mode)
      (gcr/untabify-buffer-hook))
    
    (add-hook 'org-mode-hook 'gcr/org-mode-hook)
    
    (setq org-todo-keywords
          '((sequence "TODO" "IN-PROGRESS" "WAITING" "REVIEW" "DONE")))
    
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((css . t)
       (dot . t)
       (ditaa . t)
       (emacs-lisp . t)
       (js . t)
       (latex . t)
       (org . t)
       (plantuml . t)
       (R . t)
       (scheme . t)
       (sh . t)))
    
    (setq org-confirm-babel-evaluate nil)
    
    (setq org-startup-with-inline-images nil)
    
    (require 'htmlize)
    
    (setq org-completion-use-ido t)
    
    (setq org-footnote-auto-adjust t)
    
    (when (not (string-equal (org-version) "8.2.5h"))
      (display-warning
       'org-mode
       (concat
        "Requirements not met. Expected 8.2.5h. Found " (org-version))
       :emergency))
    
  5. Graphviz 116 , 117 , 118
    (let ((f (concat (cask-elpa-dir)
                     "/graphviz-dot-mode-20120821.1441/graphviz-dot-mode.el")))
      (if (file-exists-p f)
          (load-file f)
        (warn "Could not locate a lib file for Graphviz support: %s" f)))
    
  6. Lispy
    (defconst lispy-modes '(emacs-lisp-mode-hook
                            ielm-mode-hook
                            lisp-interaction-mode-hook
                            scheme-mode-hook
                            geiser-repl-mode-hook))
    
    (dolist (h lispy-modes)
      (add-hook h 'rainbow-mode))
    
    (dolist (h lispy-modes)
      (when (not (member h '(ielm-mode-hook)))
        (add-hook h 'turn-on-pretty-mode)
        (add-hook h 'gcr/newline)
        (add-hook h 'turn-on-real-auto-save)
        (add-hook h 'gcr/untabify-buffer-hook)
        (add-hook h 'gcr/disable-tabs)
        ; Adds 3 characters to newlines in org-html-export-to-html
        ; (add-hook h 'fci-mode)
        (add-hook h 'hs-org/minor-mode +1)))
    
  7. Emacs Lisp

    Make it obvious whether or not it is lexically scoped 119 or not and don't show that message whenever you enter a scratch buffer 120.

    (defun gcr/elisp-eval-buffer ()
      "Intelligently evaluate an Elisp buffer."
      (interactive)
      (gcr/save-all-file-buffers)
      (eval-buffer))
    
    (defun gcr/elisp-mode-local-bindings ()
      "Helpful behavior for Elisp buffers."
      (local-set-key (kbd "<f5>") 'gcr/elisp-eval-buffer)
      (local-set-key (kbd "<f6>") 'eval-print-last-sexp))
    
    (require 'lexbind-mode)
    
    (defun gcr/elisp-mode-hook ()
      (gcr/elisp-mode-local-bindings)
      (lexbind-mode)
      ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Lisp-Doc.html
      (turn-on-eldoc-mode))
    
    (add-hook 'emacs-lisp-mode-hook 'gcr/elisp-mode-hook)
    
    ;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html
    (setq initial-scratch-message nil)
    
  8. Scheme 121

    You should probably only use Geiser, forever. 122

    (require 'geiser)
    (setq geiser-active-implementations '(racket))
    
    (defun gcr/scheme-eval-buffer ()
      "Save and then evaluate the current Scheme buffer with Geiser."
      (interactive)
      (gcr/save-all-file-buffers)
      (geiser-mode-switch-to-repl-and-enter))
    
    (defun gcr/scheme-mode-local-bindings ()
      "Helpful behavior for Scheme buffers."
      (local-set-key (kbd "<f5>") 'gcr/scheme-eval-buffer))
    
    (add-hook 'scheme-mode-hook 'gcr/scheme-mode-local-bindings)
    
  9. Javascript 123 , 124
    (defun gcr/js-mode-hook ()
      (local-set-key (kbd "RET") 'newline-and-indent)
      (setq js-indent-level 2)
      (turn-on-real-auto-save)
      (fci-mode)
      (gcr/untabify-buffer-hook))
    
    (add-hook 'js-mode-hook 'gcr/js-mode-hook)
    
    ; ln -s ./javascript-mode ./js-mode
    (let ((f (concat (cask-elpa-dir)
                     "/auto-complete-20140208.653/dict/js-mode")))
      (if (file-exists-p f)
          (load-file f)
        (warn "Could not locate a lib file for auto-complete JavaScript support: %s" f)))
    
  10. Web 125

    JSON support is included here, too.

    (require 'web-mode)
    (setq web-mode-engines-alist
          '(("ctemplate" . "\\.html$")))
    
    (defun gcr/web-mode-hook ()
      (whitespace-turn-off)
      (rainbow-turn-off)
      (local-set-key (kbd "RET") 'newline-and-indent)
      (setq web-mode-markup-indent-offset 2)
      (setq web-mode-css-indent-offset 2)
      (setq web-mode-code-indent-offset 2)
      (setq web-mode-indent-style 2)
      (setq web-mode-style-padding 1)
      (setq web-mode-script-padding 1)
      (setq web-mode-block-padding 0)
      (gcr/untabify-buffer-hook))
    
    (add-hook 'web-mode-hook 'gcr/web-mode-hook)
    
  11. CSS
    (defun gcr/css-modehook ()
      (fci-mode +1)
      (whitespace-turn-on)
      (rainbow-turn-on)
      (gcr/untabify-buffer-hook)
      (local-set-key (kbd "RET") 'newline-and-indent))
    
    (add-hook 'css-mode-hook 'gcr/css-modehook)
    
  12. Make
    (defun gcr/make-modehook ()
      (fci-mode +1)
      (whitespace-turn-on)
      (rainbow-turn-on)
      (local-set-key (kbd "RET") 'newline-and-indent) ())
    
    (add-hook 'makefile-mode-hook 'gcr/make-modehook)
    
  13. Markdown 126

    Since org-mode exports to just about everything; my Markdown usage will be mostly limited to working with files on Github.

    (autoload 'markdown-mode "markdown-mode"
       "Major mode for editing Markdown files" t)
    
    (add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode))
    

10.3.4 Diagramming, UML creation, Workflow

How you perform these taks is entirely up to you. There are a lot of good options both inside and outside of Emacs. For the general cases, I like the ones that are built in and play nice, especially with org-mode. At its simplest, artist-mode 127 is plenty fine for diagramming and stuff. Graphviz also works well 128. Ditaa is sort of the next level up 129, and finally PlantUML 130. They are all good options at different times, and they all work with org-mode. Everything I will publish will go through org-mode. org-modes just shines so, so brightly.

As of writing, I'm undecided onw how best to standarding on a solution in this area. The good thing is that each tool is a good fit depending upon what you want to accomplish:

  • artist-mode: Anything in ultra portable text, asii or utf-8, just works.
  • Graphviz: Graphicaly and lays things out automatically.
  • Ditaa: Graphical but based on ascii diagrams.
  • PlantUML: Includes full breadth of UML options, everything: sequence, use case, class, activity, component, state, and object.

ditaa was my first pick for usage for the blaring simplicity and power of it. org-mode provides a setup 131document that I followed. It required installing a JRE and that was about it. artist-mode is automatically loaded for the source block. The example below 132 is much better than my hello world business.

ditaa-simple.png

  1. Setup
    (setq org-ditaa-jar-path "~/java/jar/ditaa0_9.jar")
    

10.4 Operation (Keybindings/Keymaps) 133

These keybindings are custom for me and I've been using them for so long, and that makes it right.

(global-set-key (kbd "C-t") 'gcr/previous-window)
(global-set-key (kbd "C-S-t") 'gcr/next-window)

(global-set-key (kbd "C-c /") 'ac-complete-filename)

(global-set-key (kbd "<C-M-tab>") 'yas/expand)

(global-set-key (kbd "<f1>") 'kmacro-start-macro)
(global-set-key (kbd "<f2>") 'kmacro-end-macro)
(global-set-key (kbd "<f3>") 'kmacro-end-and-call-macro)
                                        ; F4 is free
                                        ; Keep F5 free per mode
                                        ; Keep F6 free per mode
                                        ; Keep F7 free per mode
                                        ; F8 is free
                                        ; F9 is free
                                        ; F10 is free
(global-set-key (kbd "<f11>") 'gcr/insert-timestamp)
(global-set-key (kbd "<f12>") 'gcr/comment-or-uncomment)

(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)

10.5 Shells 134 , 135 , 136

If you've never learned bash or korn or c-shell, then you are missing out on having some good fun… I mean work, getting work done. That said, I'm a baby when it comes to really using them. It seemed like a good idea to learn some of them well, and one that works seamnlessly with Emacs seems like a great idea. Since it is just another Elisp program, it has access to the same scope as everything else running inside Emacs. The resources on this tool are a bit varied and all valuable so I included all of them. The big takeaway is that you've got a "normal" looking shell interface whose commands work transparently with Elisp commands… and that can bey very pleasant.

Command completion is available. Commands input in eshell are delegated in order to an alias, a built in command, an Elisp function with the same name, and finally to a system call. Semicolons deparate commands. which tells you what implementation will satisfy the call that you are going to make. The flag eshell-prefer-lisp-functions does what it says. $$+ is the result of the last command. Aliases live in =eshell-aliases-file. History is maintained and expandable. eshell-source-file will run scripts. Since Eshell is not a terminal emulator, you need to tell it about any commands that need to run using a terminal emulator, like anything using curses by adding it to to eshell-visual-commands.

10.5.1 Control Files

alias clear recenter 0
alias d 'dired $1'
alias g git $*
alias gb git branch $*
alias gco git checkout $*
alias gpom git push origin master
alias gst git status
alias la ls -lha $*
alias ll ls -lh $*
alias s ssh $*
alias top proced

10.5.2 Config 137 , 138org-

(setq eshell-prefer-lisp-functions nil
      eshell-cmpl-cycle-completions nil
      eshell-save-history-on-exit t
      eshell-cmpl-dir-ignore "\\`\\(\\.\\.?\\|CVS\\|\\.svn\\|\\.git\\)/\\'")

(eval-after-load 'esh-opt
  '(progn
     (require 'em-cmpl)
     (require 'em-prompt)
     (require 'em-term)
     (setenv "PAGER" "cat")
     (add-hook 'eshell-mode-hook
               '(lambda () (message "Entering Eshell…")))
     (add-to-list 'eshell-visual-commands "ssh")
     (add-to-list 'eshell-visual-commands "tail")
     (add-to-list 'eshell-command-completions-alist
                  '("tar" "\\(\\.tar|\\.tgz\\|\\.tar\\.gz\\)\\'"))))

(setq eshell-prompt-function
  (lambda nil
    (concat
     "[" (user-login-name) "@" (getenv "HOSTNAME") ":"
     (eshell/pwd)
     "]$ ")))

11 Assembly

11.1 Prerequisites

11.1.1 Runtime

The entirety of this system is configured for a particular version of Emacs running on Linux and it is not worth fooling around if we aren't running there. It is important enough to at least check and notify the user if those requirements are not met, but not serious enough to kill the editor, and the user ought to have a chance at knowing what is going on.

(when (or
       (not (= emacs-major-version 24))
       (not (= emacs-minor-version 3))
       (not (string-equal system-type "gnu/linux")))
  (display-warning
   'platform
   (concat
    "Requirements not met. Expected v24.3 on Linux. Found v"
    (number-to-string emacs-major-version) "."
    (number-to-string emacs-minor-version) " on " (symbol-name system-type))
   :emergency))

11.1.2 Cask 139

Install required packages first using Cask 140.

;-*-Emacs-Lisp-*-

(source gnu)

(depends-on "rainbow-mode")

(source marmalade)

(depends-on "real-auto-save")

(source melpa)

(depends-on "color-theme-solarized")

(depends-on "fill-column-indicator")

(depends-on "fuzzy")
(depends-on "auto-complete")

(depends-on "yasnippet")

(depends-on "diminish")

(depends-on "flx-ido")
(depends-on "projectile")

(depends-on "geiser")

(depends-on "smartparens")

(depends-on "undo-tree")

(depends-on "htmlize")

(depends-on "pretty-mode")

(depends-on "lexbind-mode")

(depends-on "web-mode")

(depends-on "expand-region")

(depends-on "dired-details+")

(depends-on "hideshow-org")

(depends-on "markdown-mode")

(depends-on "smex")

(source org)

(depends-on "org-plus-contrib")

Tell Emacs how to use Cask.

(require 'cask "~/.cask/cask.el")
(cask-initialize)

11.2 Layout

Convert decisions into a runnable system.

<<runtime-check>>
<<custom-variables>>
<<utility-block>>
<<cask-block>>
<<font-block>>
<<uxo-windows-decision>>
(when (display-graphic-p)
  <<uxo-frames-decision>>)
<<uxo-buffers-decision>>
<<uxo-modeline-decision>>
<<uxo-mark-region-decision>>
<<uxo-minibuffer-decision>>
<<diagramming-decision>>
<<modes-config-decision>>
<<shells-decision>>
<<modes-application-decision>>
<<keymaps-decision>>

11.3 Font block

(when (display-graphic-p)
  <<font-decision>>
  (defun gcr/font-ok-p ()
    "Is the configured font valid?"
    (interactive)
    (member gcr/font-base (font-family-list)))
  (defun gcr/font-name ()
    "Compute the font name and size string."
    (interactive)
    (let* ((size (number-to-string gcr/font-size))
           (name (concat gcr/font-base "-" size)))
      name))
  (defun gcr/update-font ()
    "Updates the current font given configuration values."
    (interactive)
    (if (gcr/font-ok-p)
      (progn
        (message "Setting font to: %s" (gcr/font-name))
        (set-default-font (gcr/font-name)))
    (message (concat "Your preferred font is not available: " gcr/font-base))))
  (defun gcr/text-scale-increase ()
    "Increase font size"
    (interactive)
    (setq gcr/font-size (+ gcr/font-size 1))
    (gcr/update-font))
  (defun gcr/text-scale-decrease ()
    "Reduce font size."
    (interactive)
    (when (> gcr/font-size 1)
      (setq gcr/font-size (- gcr/font-size 1))
      (gcr/update-font)))
  (global-set-key (kbd "C-M-;") 'gcr/text-scale-increase)
  (global-set-key (kbd "C-M-j") 'gcr/text-scale-decrease)

  (global-set-key (kbd "C-M-'") 'gcr/text-scale-increase)
  (global-set-key (kbd "C-M-;") 'gcr/text-scale-decrease)

  (gcr/update-font))

11.4 Utility fuctions

    (defun gcr/previous-window ()
      "Move focus to the previous window."
      (interactive)
      (other-window 1))

    (defun gcr/next-window ()
      "Move focus to the next window."
      (interactive)
      (other-window -1))

    (defun gcr/insert-timestamp ()
      "Produces and inserts a full ISO 8601 format timestamp."
      (interactive)
      (insert (format-time-string "%Y-%m-%dT%T%z")))

    (defun gcr/comment-or-uncomment ()
      "Comment or uncomment the current line or selection."
      (interactive)
      (cond ((not mark-active) (comment-or-uncomment-region (line-beginning-position)
                                                          (line-end-position)))
            ((< (point) (mark)) (comment-or-uncomment-region (point) (mark)))
            (t (comment-or-uncomment-region (mark) (point)))))

    (defun gcr/no-control-m ()
      "Aka dos2unix."
      (interactive)
      (let ((line (line-number-at-pos))
            (column (current-column)))
        (mark-whole-buffer)
        (replace-string "
      " "")
        (goto-line line)
        (move-to-column column)))

    (defun gcr/untabify-buffer ()
    "For untabifying the entire buffer."
    (interactive)
    (untabify (point-min) (point-max)))

(defun gcr/untabify-buffer-hook ()
  "Adds a buffer-local untabify on save hook"
  (interactive)
  (add-hook
     'after-save-hook
     (lambda () (gcr/untabify-buffer))
     nil
     'true))

    (defun gcr/disable-tabs ()
      "Disables tabs."
      (setq indent-tabs-mode nil))

    (defun gcr/save-all-file-buffers ()
      "Saves every buffer associated with a file."
      (interactive)
      (dolist (buf (buffer-list))
        (with-current-buffer buf
          (when (and (buffer-file-name) (buffer-modified-p))
            (save-buffer)))))

    (defun gcr/delete-trailing-whitespace ()
      "Apply delete-trailing-whitespace to everything but the current line."
      (interactive)
      (let ((first-part-start (point-min))
            (first-part-end (point-at-bol))
            (second-part-start (point-at-eol))
            (second-part-end (point-max)))
        (delete-trailing-whitespace first-part-start first-part-end)
        (delete-trailing-whitespace second-part-start second-part-end)))

  (defun gcr/newline ()
    "Locally binds newline."
    (local-set-key (kbd "RET") 'sp-newline))

12 How it works

This is a very simple program. Loading up C3F.org into a modern version of Emacs running a modern version of org-mode and running org-babel-tangle will output the Cask and .emacs.el files. You will link them as you see fit.

The assembly section is the only aspect of the document where sequencing matters, everything else is composed and constructed independently where it should all "just work".

13 Must Reads 141 , 142

14 La trahison des images 143

Where else has this acronym shown up?

#cc33ff
bright purple color 144
Commander, U.S. Third Fleet
WWII navy 145
A spasmogenic fragment
a peptide 146

15 Observations

  • This config was developed organically quite differently from the original idea
  • Literate programming allowed an insanely flexible and freeing experience
  • This one short experience for me made a powerful, positive impression on me

Footnotes:

Author: Grant Rettke

Created: 2014-03-12 Wed 22:42

Emacs 24.3.1 (Org mode 8.2.5h)

Validate