# -- Default template
#+TITLE: ALEC's a Language for Expressing Creativity (ALEC)
#+DATE: <2014-02-24 MON>
#+AUTHOR: Grant Rettke
#+EMAIL: gcr@wisdomandwonder.com
#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline author:t c:nil
#+OPTIONS: creator:comment d:(not "LOGBOOK") date:t e:t email:nil f:t inline:t
#+OPTIONS: num:t p:nil pri:nil stat:t tags:t tasks:t tex:t timestamp:t toc:5
#+OPTIONS: todo:t |:t
#+STARTUP: showeverything
#+CREATOR: Emacs 24.4.1 (Org mode 8.2.10)
#+DESCRIPTION: This document realizes ALEC using Emacs.
#+EXCLUDE_TAGS: noexport
#+KEYWORDS: literate programming, reproducible research, programming language, lisp, elisp, ide, emacs, babel, org-mode
#+LANGUAGE: en
#+SELECT_TAGS: export
# -- ASCII template
# -- HTML template
#+OPTIONS: html-link-use-abs-url:nil html-postamble:auto html-preamble:t
#+OPTIONS: html-scripts:t html-style:t html5-fancy:nil tex:t
#+CREATOR: Emacs 24.3.1 (Org mode 8.2.7)
#+HTML_CONTAINER: div
#+HTML_DOCTYPE: xhtml-strict
#+HTML_HEAD:
#+HTML_HEAD_EXTRA:
#+HTML_LINK_HOME:
#+HTML_LINK_UP:
#+HTML_MATHJAX:
#+INFOJS_OPT: view:info toc:5
#+LATEX_HEADER:
# -- Latex template
#+DATE: <2014-02-24 MON>
#+OPTIONS: texht:t
#+LATEX_CLASS: article
#+LATEX_CLASS_OPTIONS: [letterpaper, 10pt]
#+LATEX_HEADER: \usepackage[paperwidth=8.5in, paperheight=11in, hmargin=0.5in, vmargin=0.5in]{geometry}
#+LATEX_HEADER_EXTRA:
#+STARTUP: showeverything
* Start Up
:PROPERTIES:
:noweb-ref: Start-Up
:END:
There are things that must occur during start… *before* everything else.
Load the newer version of a file: bytecode or lisp. This says a lot. In the
users guide it explains why you may want this turned off. That way you can
develop code and try it out to see how it works and comare it to the old version
which had been byte-compiled. I am not doing that here.
#+begin_src emacs-lisp
(setq load-prefer-newer t)
#+end_src
* Run-time
:PROPERTIES:
:noweb-ref: Runtime-Check
:END:
Reproducibility is both the foundation of all good science, and, the thing that
allows us to tell, and enjoy, jokes. This system is a little of both
Paging through hundreds of Emacs related posts in my memory banks, there is a
common decision shared with the reader /not/ to upgrade the Emacs version. This
could be out of laziness, which makes total sense, and another good reason is
that every new release brings change. Despite the fact that we are subject to
decay, which is /just/ change, most humans don't like either. Change often brings
pain, and hard work. To help alleviate some of the pain, this system will
attempt to capture its configuration at a particular state in time to facilitate
reproducibility. In practice, it will be a bit liberal, though.
This system will only start with the correct version of Emacs, v24.4
#+begin_src emacs-lisp
(defun gcr/emacs-version-check ()
"Enforce version compliance."
(interactive)
(when (not (and (= emacs-major-version 24)
(= emacs-minor-version 4)))
(error
"Incorrect Emacs runtime. Expected v24.4. Found v%s.%s"
(number-to-string emacs-major-version)
(number-to-string emacs-minor-version))))
(gcr/emacs-version-check)
#+end_src
* Provisioning
:PROPERTIES:
:noweb-ref: Provisioning
:END:
** Background
In /the old days/, the way that you managed software packages for Emacs was to do
it manually because there was no software distribution system available. In my
case, I just put everything inside of a Subversion project and moved on. That
actually worked fine, but I didn't like committing compiled code, and handling
updates was always a hassle depending on how files and the directory structure
had changed. Fortunately that all changed with the introduction of Package and
ELPA.
When I first cut my system over to ELPA I went with GNU ELPA and Marmalade.
Eventually I found that they weren't the right thing for me since the former had
a very small collection and the latter, strangely, had exactly what I wasn't
looking for. About that time, MELPA was starting to really gain momentum.
MELPA is really a community and a belief-system in addition to being a package
repository. They value structure and form, and make sure that the package
builds, and then they do the building for you. They are doing great things to
create, nurture, and guide the community to define a higher standard for package
quality. Around that time, too I got fed up with manually installing and
worrying whether I had the packages installed or not, so after figuring that
there was something better than some custom code that I wrote, I looked at Cask.
Cask is a declarative approach for expressing dependencies. That sounds fancy
but it isn't. Cask just makes it really easy to obtain ELPA packages from
different repositories. One reason that I really like is that you see all of
your packages in a single place rather than sprinkled about all over your
initialization file. It also lowers the bar for new users to with just one line
of code add a new repository. Something funny happened though, the more I
learned about Emacs and the community, the more I found the need to manage
software not hosted in MELPA.
MELPA is perfect at what it does, and it is still evolving. Rather than try to
plan for everything, they decided to solve 80% of most problems for most people
and that is super. Now they are looking at how to handle versioned packages by
hosting a stable repository that uses Git tags, and that is super, too. What
about software that doesn't live in a package though?
You start finding code all over not in packages. EmacsWiki is the exception
given that MELPA supports that. What about random Emacs-Lisp code you find out
on the 'Net? That question got me motivated to learn about other people's
approaches for package management. That is where I learned about EL-Get.
EL-Get is powerful, and flexible, and concise. What it lacks in community
momentum, it makes up for in raw power. When I find code that doesn't live in
packages, and may never, then I start setting up EL-Get to grab it for me.
Based upon what I've read, it had its time in the sun. Its power is still true,
and its value is a great, because it truly succeeds at the goals that it set out
on.
The first time I set up Cask, it was the only option for easily specifying which
repository you wanted to use for installing a package. It was great. Then, I got
the bug to be able to easily collaborate with others by sending them a single
initialization file. Kind of a theoretical goal, but there is *one* person with
whom I want to collaborate that makes it completely make sense. More than a year
after switching from Subversion to Cask, I dug into the options out there today.
My foray into EL-Get was kind of a mistake, since its role had changed in the
community between then and its inception. I spent a lot of time not being
productive there. Then I figured that Cask would be fine, but at the time
it did not run easily on Windows, which is really important to me. Based on
that, I quit pursuing Cask as an option. From what I read, Cask does now run
easily on Windows, but I am not revisiting it for now.
One mistake that I made here was assuming that recipes would be the same between
EL-Get and Cask. Doh! Of course they wouldn't be. The nice side-effect here
though was learning the power of EL-Get. It is very powerful.
The great news as of 24.4 is that Package inside of Emacs allows you to specify
the source repository from which to install a package. This is a hugely
important feature and I am thrilled on all user's behalf's. The old problem was
that sometimes you might want the stable version of Foo and something you want
the development version of Foo. The problem was that you never quite knew which
one you would get because the packages lived in *both* repositories! Now, it is no
longer an issue, and one of the reasons that I don't need to use Cask anymore.
Package should do it all, and it will, below. That was my plan. It failed.
My approach was simple. First I identified all of the packages that I used that
were available on MELPA Stable. Then added MELPA Stable as a repository and
added all of those packages to =package-pinned-packages=. To help me out, I also
added a separate entry just to pull MELPA packages that were not ELPA packages.
On this setup, it worked about %75 of the time. I couldn't figure out why. I
tried every permutation. I removed entries. It wasn't enough. It never worked
right. Here is what it did:
What is happening is simple
- Delete the ELPA directory
- Start this system
- Packages that are pinned to MELPA Stable are installed from MELPA
Long ago Steve Purcell asked someone on GitHub why they want stable. I don't
recall the exact conversation. Perhaps I asked something. His answer was really
simple. It was something like "Going with the TRUNK tends to be fine. If it
breaks, it usually gets fixed quickly". I understood. I just *really* wanted to
try the /reproducible research/ thing with this system. I was very gung-ho about
it. It didn't work out though. Then I started loading everything from MELPA. At
that point, everything worked _perfectly_. I tested it 5 times. I look forward to
seeing how it works out in the future. It is certainly consistent with what
Purcell shared.
** Steps
*** Package
Before doing any work with Package it must be initialized. Failure to do so is
the easiest way to waste time and achieve nothing.
#+begin_src emacs-lisp
(package-initialize)
#+end_src
Use the Org ELPA repository. I won't lock down the version here, I just want it
to be stable. In the Org configuration, I'll at warning for specific features.
#+begin_src emacs-lisp
(add-to-list 'package-archives
'("org" . "http://orgmode.org/elpa/") t)
#+end_src
GNU stuff is always good.
#+begin_src emacs-lisp
(add-to-list 'package-archives
'("gnu" . "http://elpa.gnu.org/packages/"))
#+end_src
MELPA is critical.
#+begin_src emacs-lisp
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/") t)
#+end_src
If Package+ is not installed, then install it. First the package list has to be
refreshed so that Package knows about the new packages.
#+begin_src emacs-lisp
(package-refresh-contents)
(unless (package-installed-p 'package+)
(package-install 'package+))
#+end_src
This is the list of packages that should be installed automatically and loaded.
Any packages not listed here that Package+ finds are removed.
#+begin_src emacs-lisp
(package-manifest
'ace-jump-mode
'ace-link
'ace-window
'aggressive-indent
'alert
'anchored-transpose
'anzu
'ascii-art-to-unicode
'auctex
'auto-complete
'auto-complete-chunk
'autotetris-mode
'boxquote
'clips-mode
'ctable
'diff-hl
'diminish
'dired-details+
'dired-imenu
'ess
'ess-R-data-view
'ess-R-object-popup
'esup
'exec-path-from-shell
'expand-region
'f
'figlet
'fill-column-indicator
'flx-ido
'flycheck
'fuzzy
'geiser
'google-this
'graphviz-dot-mode
'highlight-tail
'htmlize
'ido-hacks
'ido-ubiquitous
'ido-vertical-mode
'imenu+
'imenu-anywhere
'inlineR
'json-reformat
'key-chord
'langtool
'lexbind-mode
'magit
'markdown-mode
'metaweblog
'move-text
'multiple-cursors
'neotree
'nyan-mode
'ob-sml
'org-ac
'org-plus-contrib
'osx-browse
'package+
'pandoc-mode
'plantuml-mode
'polymode
'pos-tip
'pretty-mode
'projectile
'r-autoyas
'rainbow-delimiters
's
'smartparens
'smex
'sml-mode
'smooth-scrolling
'solarized-theme
'sparkline
'sqlup-mode
'string-edit
'stripe-buffer
'undo-tree
'unicode-fonts
'vagrant
'web-mode
'wrap-region
'writegood-mode
'xml-rpc
'yaml-mode
)
#+end_src
Why doesn't the =F= package get loaded correctly? The directory is in the
=load-path=. The auto-load is in there. It is only on my machine. I will look
into this.
This manual step used to use =load=. That was a mistake. It relied upon specifying
the package directory. The package directory can change on every install so I
had to update this line every time. That was stupid. =load-library= searches for
libraries by name. It works.
#+begin_src emacs-lisp
(load-library "f")
#+end_src
*** el-get
EL-Get handles things that don't easily fit anywhere else.
Initialize EL-Get.
#+begin_src emacs-lisp
(add-to-list 'load-path "~/.emacs.d/el-get/el-get")
(unless (require 'el-get nil 'noerror)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/dimitri/el-get/master/el-get-install.el")
(goto-char (point-max))
(eval-print-last-sexp)))
#+end_src
#+begin_src emacs-lisp
(setq gcr/el-get-packages nil)
#+end_src
=org-show= [fn:5de243c0: https://github.com/jkitchin/jmax/blob/master/org-show.org]
looks like the prefect presentation tool for me. jkitchin is just… he is one a
sweet wavelength. This presentation tool makes it really, really easy to present
in a very /Emacs/ way. It is worth discussing a bit why I got this module in this
manner:
- =org-show= is distributed as an org file
- It requires tangling to produce a emacs-lisp file for utilization by emacs
- John explains how to do so in the file itself via =org-babel-load-file=
- This works fine on a vanilla, =org= setup
- I do not have a vanilla, =org= setup
- I do not know the issue and I am not going to debug it for now
- The approach here than is to:
- Obtain the file
- Start =emacs= with the =raw= setup defined in this document, which is nothing
but =org= … and from there, tangle =org-show=
- It is manual and that is OK for now
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name org-show
:type http
:url "https://raw.githubusercontent.com/jkitchin/jmax/master/org/org-show.org"
:website "https://github.com/jkitchin/jmax/blob/master/org/org-show.org"
:description "simple presentations in org-mode"))
(add-to-list 'gcr/el-get-packages 'org-show)
#+end_src
Make it really easy to remind yourself and others what EMACS really stands for
(in this case it is fun).
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name emacs-name
:type http
:url "http://www.splode.com/~friedman/software/emacs-lisp/src/emacs-name.el"
:features emacs-name
:autoloads nil
:website "http://www.splode.com/"
:description "emacs acronym expansions"))
(add-to-list 'gcr/el-get-packages 'emacs-name)
#+end_src
It is not good to flame people on the Internet. It is good to /know/ what it is
all about, and here is a way to see some examples of the absurdity of it all.
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name flame
:type http
:url "http://www.splode.com/~friedman/software/emacs-lisp/src/flame.el"
:features flame
:autoloads nil
:website "http://www.splode.com/"
:description "automatic generation of flamage, as if we needed more"))
(add-to-list 'gcr/el-get-packages 'flame)
#+end_src
People love horoscopes, so, provide them.
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name horoscope
:type http
:url "http://www.splode.com/~friedman/software/emacs-lisp/src/horoscope.el"
:features horoscope
:autoloads t
:website "http://www.splode.com/"
:description "generate horoscopes"))
(add-to-list 'gcr/el-get-packages 'horoscope)
#+end_src
James Parry [fn:c99fd633: https://en.wikipedia.org/wiki/James_Parry] must always
be honored.
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name kibologize
:type http
:url "http://www.splode.com/~friedman/software/emacs-lisp/src/kibologize.el"
:features kibologize
:autoloads nil
:website "http://www.splode.com/"
:description "generate ravings about kibology, in the style of kibo"))
(add-to-list 'gcr/el-get-packages 'kibologize)
#+end_src
You might not always remember your shopping list, but we will remember it for
you… though not necessarily for wholesale.
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name shop
:type http
:url "http://www.splode.com/~friedman/software/emacs-lisp/src/shop.el"
:features shop
:autoloads nil
:website "http://www.splode.com/"
:description "generate random shopping lists"))
(add-to-list 'gcr/el-get-packages 'shop)
#+end_src
Do you remember when those great AT&T adds were on television and it changed
your life and bought you a kitten? You will.
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name youwill
:type http
:url "http://www.splode.com/~friedman/software/emacs-lisp/src/youwill.el"
:features youwill
:autoloads t
:website "http://www.splode.com/"
:description "generate meaningless marketing hype"))
(add-to-list 'gcr/el-get-packages 'youwill)
#+end_src
A swimming-pool screen-saver.
#+begin_src emacs-lisp
(add-to-list
'el-get-sources
'(:name swimmers
:type http
:url "http://www.cb1.com/~john/computing/emacs/lisp/games/swimmers.el"
:features swimmers
:autoloads nil
:website "http://www.cb1.com/~john/"
:description "Draw a swimming-pool screensaver"))
(add-to-list 'gcr/el-get-packages 'swimmers)
#+end_src
#+begin_src emacs-lisp
(add-to-list 'el-get-sources '(:name emacs-uuid
:type github
:pkgname "nicferrier/emacs-uuid"))
(add-to-list 'gcr/el-get-packages 'emacs-uuid)
(add-to-list 'el-get-sources '(:name emacs-world-time-mode
:type github
:pkgname "nicferrier/emacs-world-time-mode"))
(add-to-list 'gcr/el-get-packages 'emacs-world-time-mode)
#+end_src
Today the recipe didn't work, =el-get= couldn't find it. That is pretty bizarre
because /nothing changed/. The recipe still lives here [fn:b7460ca0: https://github.com/dimitri/el-get/blob/master/recipes/sicp.rcp].
Because this is broken for some unknown reason, I'm omitting it and will simply
fix it the /next/ time that I want to run it.
#+begin_quote
=(add-to-list 'gcr/el-get-packages 'sicp)=
#+end_quote
As el-get to make sure that those desired packages are installed.
#+begin_src emacs-lisp
(el-get 'sync gcr/el-get-packages)
#+end_src
* Ends & Means
There are so many ways to customize a system. Is intent or pragmatics more
important? In my philosophy, the nature of the /end/ is contained within the
properties of the /means/ themselves. They are inseparable. The traits are
the fundamental aspects of this system. They are things that are critical, they
are *everything*. Here my goal is to capture both the means and the ends.
These are the minimum fundamental features to allow for the fluid delivery and
execution of the creative experience within this medium.
The capture occurs sequentially. The ends are listed first though, because they
are much more meaningful and inspiring to me than the means, at least in "listed
here form". Their execution, of course, is much more visceral and fun!
The means used to be broken up into highly categorical sections. It made sense,
but it didn't read well. It might make sense from a reference perspective, but
that was about it. This document focuses more on the flow. Since the fundamental
means /ought/ to be concise, they are intended to be read at a single sitting.
* Ends (ALEC)
This system has changed who I am and how I think. Because it is easier to focus
on the tools rather than the intent, on the means versus the ends, I focus on this
system, this configuration of Emacs. My system is a provider, a realization, of
a language for expressing creativity. 𝔸𝕃𝔼ℂ. ALEC's a Language for Expressing
Creativity. That is a truly and utterly beautiful thing to ponder.
The expression of creativity is why we are born human. Five of our senses go out
into the world searching, always searching. In our time-space, the expressions
that may be consumed by the eye (paintings, graphic arts) and consumed by the
ear (music) are so, so lovely, and easy for us to understand (How do you address
someone whose /true/ name is Symphony?). We are here to let that voice sing, and
we want all five senses to help do it, for the maximization of expressivity.
The song, that sweet celestial song, is sometimes more difficult for people to
hear. The honey-kissed embrace of one's love feels different than a song, and
different than laughing at a joke, but they are all the creative act. Gardening,
selling, collecting, tending… they are all part of the creative act that makes
us again be born human. We always seem to focus on the configuration of those
actions (time, space, causality, and identity), the build of those tools,
necessary to perform the creative act. With time and patience, we will know the
true nature of things. Part of the path is indeed attaining mastery. Mastery
over ourselves, mostly, by some way that is gentle and kind. That action, that
attempt, for me, has partially culminated in the aggregation of a lifetime of
mastery of tools and programming languages and ideas and studies and training
and collaboration and mystery and magic and laughing, in this birth, in the
artifact called ALEC, and ALEC can only be expressed, for me, for now, with
Emacs.
This system is no longer "Emacs". It is not its disparate packages. They are
tools, yes, and more importantly, they are expressions of creativity. Together
in Emacs, in ALEC, they are composed, like parts of a symphony, together, to
allow for the ultimate in the act of creative expression. The tools themselves
possess these traits, both in their implementation and their intent. That is
traditional, in that, the properties and traits expressed by these "words",
these compositional units, have the properties and traits of the things
expressed by these "words". "Words" is the most expressive element that I can
think of right now, for things that can be atoms, and yet be combined to form
sentences, something larger and more expressive, in a particular language,
which itself can quite magically express ideas, about itself, or about anything
else in existence.
It is like watching a beautiful lotus blooming, spreading its pedals, having
been nourished by the fertile soil, protected in its pond, knowing that it must
strive to reach higher, nurtured by Mother Sun. The very act, the ultimate act
of creative expression, that very action contains itself and is culminated by
itself. It is that which it is trying to achieve, and to be that, is to do that,
for itself and for all of creation. This ultimate act of creative expression, is
present in the manifestation of Emacs and the packages and the users who come
together to form a perfect symphony of creative expression in a form that
may be captured and represented as a computer file, so humble and modest, just
like a small seed of a proud and mighty Redwood tree that will eventually reach
hundreds and hundreds of feet into the sky and towards Mother Sun, contains
that which it will become in it's own existence, so too does it contain its own
beautiful destiny in the seeds of beauty and creative expression that are
produced with ALEC (in every form, not just the one described by this document
of course!).
The blossoming of the expression of the computational act, and the petals that
opened in the form of the Turing's machine, Church's Lambda calculus, and
Post's Tag System, are beautiful, and still, are only petals, that
carry the sweet fragrance, because a fragrance is part of a moment, which is
finite, as is every configuration of this reality. The beauty is still as sweet.
The key is seeing the inherent beauty, the source without start and without end,
and then being able to see that in everyone and everything.
That thing, which was present before the expression of creativity, and will
exist after it, which is not subject to the laws of time, space, causality, and
identity, is the point that everyone surely wishes to re-visit. That quest,
/the/ great motivator of the most softly spoken and heartfelt desire, itself is
surely yet another expression of /that which is gentle and kind/. The steps taken
on that quest, despite being driven by that perfect intent, are /still/ subject to
the four boundaries of this reality. Those actions, defined by configurations,
like the petals of the lotus, retaining its sweet fragrance, can, will, and must
fade, but, we will shine on in the sweet embrace of Mother Sun, knowing that
loving and warm embrace of sweet perfection, in our one, and true, home.
** The desire
"I want". If only all conversations would start out with a clear goal in mind.
All too often we waste our own, and other people's time talking and simply
trying to figure out what it is what we want. For most of us, "it", is that
thing that will solve all of our problems in life and make us happy. Technology
is no exception.
The perfect integrated development environment is a topic of constant
conversation. For good reason, for most of us it is our only tool. Unlike
carpenters and wood-workers who have a bevy of interesting and delightful tools,
we are stuck with but one. Fortunately for us, our singular tool allows
limitless creation, of tools and more. Alan Kay said it so well [fn:2e3b75ad: https://www.cs.indiana.edu/~rpjames/]:
#+BEGIN_QUOTE
The computer is a medium that can dynamically simulate the details of any other
medium, including media that cannot exist physically. It is not a tool, although
it can act like many tools. The computer is the first metamedium, and as such it
has degrees of freedom for representation and expression never before
encountered and as yet barely investigated. The protean nature of the computer
is such that it can act like a machine or like a language to be shaped and
exploited.
#+END_QUOTE
Even more succinctly, my measure of success is to:
#+BEGIN_CENTER
To provide a self-suportable environment in which the creation and conservation
of computer files may occur with ease
#+END_CENTER
As of writing, although there are many nice options out there, none of them
come within even light-years, of power that you are granted for working with a
computer as that metamedium, that GNU Emacs [fn:54b16b1c: https://www.gnu.org/software/emacs/]. With that in mind,
the following is what I actually want to do with it.
** The story
The creativity that you apply and capture to assemble your system… this is where
all of the fun stuff is. Let me elaborate, everything in your artifacts are
valuable because they tell the story. Actually, they tell the story about a
story, a story that has yet to occur and also a story that has previously
occurred. It is here, where the actions lives, that all of those things are
learned, practiced, suffered accordingly from, and reveled in! In other words,
it is yet another story, a fun one.
If you haven't noticed by now, either by hearing rumors, reading accounts, or
learning of it yourself: human beings are story-oriented. Your ability to
successfully function in and contribute to society will be directly proportional
to your ability to listen to stories, tell others' stories, live your life such
that you have new stories to tell, and capture them in some form of persistent
storage. Stories grant us the power to learn from others wisdom that was
painfully acquired thousands of years ago, and it gives you a chance to
contribute the results of your hard work, for the future of humanity, too. A
belief system about the value of story-telling is essential, critical, and
mandatory to successfully achieve your goals with literate programming.
As I change, the story will change, and the action will change. The cycle will
never end.
Nevertheless, I will attempt to do my best here with the good part of me being
a flawless, rational, and logical human being to:
- Deliver a supportable system
- Deliver an adaptable system
- Deliver an expandable system
** Inspirations
- Eric Weisstein :: Creator of MathWorld [fn:f0123b05: http://mathworld.wolfram.com/about/author.html]
* Means
:PROPERTIES:
:noweb-ref: Means
:END:
These are features that I consider critical to getting this system up and
running. The original intent of this heading was to identify the minimal core
configuration required to build this very system. It was more of the "keep it
lean" line of thinking, entirely without justification of course. An interesting
thing happened, learning. Once that core is built up, it just makes total, total
sense to build on it. It feels totally natural, and even "obvious" to do so. Not
out of boredom, but rather, out of ease-of-use. Because of this learning, I am a
lot more comfortable with including things that before I felt were superficial.
That is the power in the composition of the layers of ideas and features, they
become means that build upon each others. The hardest part is knowing the best
way to delineate those layers, if at all. Perhaps they should simply best be
just enjoy, and not pondered or revealed.
My personal goal is to keep the tangling of this document to less than 30
seconds. It needs to be fast to allow the operator to remain /in the flow/ and to
maximize creative expression. This is a human problem solved by a technological
implementation. It is a work in progress. Whatever the case, I will keep to this
goal because without it, the operators starts to be unnecessary constricted.
No matter what… no matter what, the tangling must be done in 30 seconds or less.
That is the one, only, and single thing that I ever allow influence the design
and implementation of ALEC in this manifestation because to do anything else
would be to seriously constrain its operator.
** Functions & Constants
#+begin_src emacs-lisp
(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))
(defmacro gcr/on-gnu/linux (statement &rest statements)
"Evaluate the enclosed body only when run on GNU/Linux."
`(when (eq system-type 'gnu/linux)
,statement
,@statements))
(defmacro gcr/on-osx (statement &rest statements)
"Evaluate the enclosed body only when run on OSX."
`(when (eq system-type 'darwin)
,statement
,@statements))
(defmacro gcr/on-gnu/linux-or-osx (statement &rest statements)
"Evaluate the enclosed body only when run on GNU/Linux or OSX."
`(when (or (eq system-type 'gnu/linux)
(eq system-type 'darwin))
,statement
,@statements))
(defmacro gcr/on-windows (statement &rest statements)
"Evaluate the enclosed body only when run on Microsoft Windows."
`(when (eq system-type 'windows-nt)
,statement
,@statements))
(defmacro gcr/on-gui (statement &rest statements)
"Evaluate the enclosed body only when run on GUI."
`(when (display-graphic-p)
,statement
,@statements))
(defmacro gcr/not-on-gui (statement &rest statements)
"Evaluate the enclosed body only when run on GUI."
`(when (not (display-graphic-p))
,statement
,@statements))
(defmacro gcr/diminish (mode)
"Diminish this mode after it is loaded."
(interactive)
`(eval-after-load ,mode
(diminish ,mode)))
(defvar gcr/delete-trailing-whitespace-p t
"Should trailing whitespace be removed?")
(defun gcr/delete-trailing-whitespace ()
"Delete trailing whitespace for everything but the current line.
If `gcr/delete-trailing-whitespace-p' is non-nil, then delete the whitespace.
This is useful for fringe cases where trailing whitespace is important."
(interactive)
(when gcr/delete-trailing-whitespace-p
(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/set-org-babel-default-header-args (property value)
"Easily set system header arguments in org mode.
PROPERTY is the system-wide value that you would like to modify.
VALUE is the new value you wish to store.
Attribution: URL `http://orgmode.org/manual/System_002dwide-header-arguments.html#System_002dwide-header-arguments'"
(setq org-babel-default-header-args
(cons (cons property value)
(assq-delete-all property org-babel-default-header-args))))
(defun gcr/set-org-babel-default-inline-header-args (property value)
"See `gcr/set-org-babel-default-header-args'; same but for inline header args."
(setq org-babel-default-inline-header-args
(cons (cons property value)
(assq-delete-all property org-babel-default-inline-header-args))))
(defun gcr/set-org-babel-default-header-args:R (property value)
"See `gcr/set-org-babel-default-header-args'; same but for R.
This is a copy and paste. Additional languages would warrant a refactor."
(setq org-babel-default-header-args:R
(cons (cons property value)
(assq-delete-all property org-babel-default-header-args:R))))
(defun gcr/ispell-org-header-lines-regexp (h)
"Help ispell ignore org header lines."
(interactive)
(cons (concat "^#\\+" h ":") ".$"))
(defun gcr/ispell-a2isra (block-def)
"Add to the ispell skip region alist the BLOCK-DEF."
(interactive)
(add-to-list 'ispell-skip-region-alist block-def))
(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/insert-timestamp* ()
"Produces and inserts a near-full ISO 8601 format timestamp."
(interactive)
(insert (format-time-string "%Y-%m-%dT%T")))
(defun gcr/insert-datestamp ()
"Produces and inserts a partial ISO 8601 format timestamp."
(interactive)
(insert (format-time-string "%Y-%m-%d")))
(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/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/kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
#+end_src
Might be worth investing in new behavior here such that:
- When the cursor is inside of a comment block, call =comment-indent-new-line=
- Else, call =sp-newline=
#+begin_src emacs-lisp
(defun gcr/newline ()
"Locally binds newline."
(local-set-key (kbd "RET") 'sp-newline))
#+end_src
#+begin_src emacs-lisp
(defun gcr/describe-thing-in-popup ()
"Display help information on the current symbol.
Attribution: URL `http://www.emacswiki.org/emacs/PosTip'
Attribution: URL `http://blog.jenkster.com/2013/12/popup-help-in-emacs-lisp.html'"
(interactive)
(let* ((thing (symbol-at-point))
(help-xref-following t)
(description (with-temp-buffer
(help-mode)
(help-xref-interned thing)
(buffer-string))))
(gcr/on-gui (pos-tip-show description nil nil nil 300))
(gcr/not-on-gui (popup-tip description
:point (point)
:around t
:height 30
:scroll-bar t
:margin t))))
(defun gcr/indent-curly-block (&rest _ignored)
"Open a new brace or bracket expression, with relevant newlines and indent. Src: https://github.com/Fuco1/smartparens/issues/80"
(newline)
(indent-according-to-mode)
(forward-line -1)
(indent-according-to-mode))
(defun beginning-of-line-dwim ()
"Toggles between moving point to the first non-whitespace character, and
the start of the line. Src: http://www.wilfred.me.uk/"
(interactive)
(let ((start-position (point)))
;; see if going to the beginning of the line changes our position
(move-beginning-of-line nil)
(when (= (point) start-position)
;; we're already at the beginning of the line, so go to the
;; first non-whitespace character
(back-to-indentation))))
(defun gcr/lazy-new-open-line ()
"Insert a new line without breaking the current line."
(interactive)
(beginning-of-line)
(next-line)
(newline)
(previous-line))
(defun gcr/smart-open-line ()
"Insert a new line, indent it, and move the cursor there.
This behavior is different then the typical function bound to return
which may be `open-line' or `newline-and-indent'. When you call with
the cursor between ^ and $, the contents of the line to the right of
it will be moved to the newly inserted line. This function will not
do that. The current line is left alone, a new line is inserted, indented,
and the cursor is moved there.
Attribution: URL `http://emacsredux.com/blog/2013/03/26/smarter-open-line/'"
(interactive)
(move-end-of-line nil)
(newline-and-indent))
(defun gcr/narrow-to-region* (boundary-start boundary-end fun)
"Edit the current region in a new, cloned, indirect buffer.
This function is responsible for helping the operator to easily
manipulate a subset of a buffer's contents within a new buffer. The
newly created clone buffer is created with `clone-indirect-buffer',
so all of its behaviors apply. You may care specifically about the
fact that the clone is really just a 'view' of the source buffer, so
actions performed within the source buffer or its clone(s) are
actually occurring only within the source buffer itself. When the
dynamic extent of this function is entered, the operator is prompted
for a function to call to make upon entering the new buffer. The intent
is to specify the desired mode for the new buffer, for example by
calling `scheme-mode', but any function may be called.
The subset chosen for manipulation is narrowed by
`narrow-to-region'. When the clone buffer is created, the lines in
which the start and end of the boundary occur are included at the
end the new clone buffer name to serve as a reminder for its
'true source'. The intent is to facilitate going back from the clone
buffer to the source buffer with knowledge of where it originated.
BOUNDARY-START and BOUNDARY-END are provided by delegation of this
function to `interactive'. FUN is provided interactively by the
operator via the modeline in the same manner. See Info node
`(elisp) Eval' for more on why `funcall' was used here instead of
`eval' for calling the selected function.
Attribution: URL `http://demonastery.org/2013/04/emacs-narrow-to-region-indirect/'
Attribution: URL `http://paste.lisp.org/display/135818Attribution'"
(interactive "*r\naMode name? ")
(let* ((boundary-start (if (< boundary-start 1) (point-min)
boundary-start))
(boundary-end (if (<= boundary-end boundary-start) (point-max)
boundary-end))
(new-name (concat
(buffer-name)
"⊃"
(number-to-string (line-number-at-pos boundary-start))
"-"
(number-to-string (line-number-at-pos boundary-end))))
(buf-name (generate-new-buffer-name new-name))
(fun (if (fboundp fun) fun
'fundamental-mode)))
(with-current-buffer (clone-indirect-buffer buf-name +1 +1)
(narrow-to-region boundary-start boundary-end)
(deactivate-mark)
(goto-char (point-min))
(funcall fun))))
(defun gcr/insert-ellipsis ()
"Insert an ellipsis into the current buffer."
(interactive)
(insert "…"))
(defun gcr/insert-noticeable-snip-comment-line ()
"Insert a noticeable snip comment line (NSCL)."
(interactive)
(if (not (bolp))
(message "I may only insert a NSCL at the beginning of a line.")
(let ((ncl (make-string 70 ?✂)))
(newline)
(previous-line)
(insert ncl)
(comment-or-uncomment-region (line-beginning-position) (line-end-position)))))
(defun gcr/dired-copy-filename ()
"Push the path and filename of the file under the point to the kill ring.
Attribution: URL `https://lists.gnu.org/archive/html/help-gnu-emacs/2002-10/msg00556.html'"
(interactive)
(message "Added %s to kill ring" (kill-new (dired-get-filename))))
(defun gcr/dired-copy-path ()
"Push the path of the directory under the point to the kill ring."
(interactive)
(message "Added %s to kill ring" (kill-new default-directory)))
(defun gcr/file-exists-not-symlink (f)
"True if F exists and is not a symlink."
(interactive)
(and (file-exists-p f)
(not (file-symlink-p f))))
(defun gcr/file-exists-is-symlink (f)
"True if F exists and is a symlink."
(interactive)
(and (file-exists-p f)
(file-symlink-p f)))
(progn
(defvar my-read-expression-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map read-expression-map)
(define-key map [(control ?g)] #'minibuffer-keyboard-quit)
(define-key map [up] nil)
(define-key map [down] nil)
map))
(defun my-read--expression (prompt &optional initial-contents)
(let ((minibuffer-completing-symbol t))
(minibuffer-with-setup-hook
(lambda ()
(emacs-lisp-mode)
(use-local-map my-read-expression-map)
(setq font-lock-mode t)
(funcall font-lock-function 1))
(read-from-minibuffer prompt initial-contents
my-read-expression-map nil
'read-expression-history))))
(defun my-eval-expression (expression &optional arg)
(interactive (list (read (my-read--expression ""))
current-prefix-arg))
(if arg
(insert (pp-to-string (eval expression lexical-binding)))
(pp-display-expression (eval expression lexical-binding)
"*Pp Eval Output*"))))
(defun gcr/util-ielm ()
"Personal buffer setup for ielm.
Creates enough space for one other permanent buffer beneath it."
(interactive)
(split-window-below -20)
(other-window 1)
(ielm)
(set-window-dedicated-p (selected-window) t))
(defun gcr/util-eshell ()
"Personal buffer setup for eshell.
Depends upon `gcr/util-ielm' being run first."
(interactive)
(split-window-below -10)
(other-window 1)
(eshell)
(set-window-dedicated-p (selected-window) t))
(defvar gcr/util-state nil "Track whether the util buffers are displayed or not.")
(defun gcr/util-state-toggle ()
"Toggle the util state."
(interactive)
(setq gcr/util-state (not gcr/util-state)))
(defun gcr/util-start ()
"Perhaps utility buffers."
(interactive)
(gcr/util-ielm)
(gcr/util-eshell)
(gcr/util-state-toggle))
(defun gcr/util-stop ()
"Remove personal utility buffers."
(interactive)
(if (get-buffer "*ielm*") (kill-buffer "*ielm*"))
(if (get-buffer "*eshell*") (kill-buffer "*eshell*"))
(gcr/util-state-toggle))
(defun gcr/ielm-auto-complete ()
"Enables `auto-complete' support in \\[ielm].
Attribution: URL `http://www.masteringemacs.org/articles/2010/11/29/evaluating-elisp-emacs/'"
(setq ac-sources '(ac-source-functions
ac-source-variables
ac-source-features
ac-source-symbols
ac-source-words-in-same-mode-buffers))
(add-to-list 'ac-modes 'inferior-emacs-lisp-mode)
(auto-complete-mode 1))
(defun gcr/uuid-string ()
"Insert a string form of a UUID."
(interactive)
(insert (uuid-to-stringy (uuid-create))))
(defun yf/org-electric-dollar nil
"When called once, insert \\(\\) and leave point in between.
When called twice, replace the previously inserted \\(\\) by one $.
from Nicolas Richard
Date: Fri, 8 Mar 2013 16:23:02 +0100
Message-ID: <87vc913oh5.fsf@yahoo.fr>"
(interactive)
(if (and (looking-at "\\\\)") (looking-back "\\\\("))
(progn (delete-char 2)
(delete-char -2)
(insert "$"))
(insert "\\(\\)")
(backward-char 2)))
(defun endless/sharp ()
"Insert #' unless in a string or comment.
SRC: URL `http://endlessparentheses.com/get-in-the-habit-of-using-sharp-quote.html?source=rss'"
(interactive)
(call-interactively #'self-insert-command)
(let ((ppss (syntax-ppss)))
(unless (or (elt ppss 3)
(elt ppss 4))
(insert "'"))))
(defun gcr/chs ()
"Insert opening \"cut here start\" snippet."
(interactive)
(insert "--8<---------------cut here---------------start------------->8---"))
(defun gcr/che ()
"Insert closing \"cut here end\" snippet."
(interactive)
(insert "--8<---------------cut here---------------end--------------->8---"))
(defmacro gcr/measure-time (&rest body)
"Measure the time it takes to evaluate BODY.
Attribution Nikolaj Schumacher: URL `https://lists.gnu.org/archive/html/help-gnu-emacs/2008-06/msg00087.html'"
`(let ((time (current-time)))
,@body
(message "%.06f" (float-time (time-since time)))))
(defun gcr/create-non-existent-directory ()
"Attribution URL: `https://iqbalansari.github.io/blog/2014/12/07/automatically-create-parent-directories-on-visiting-a-new-file-in-emacs/'"
(let ((parent-directory (file-name-directory buffer-file-name)))
(when (and (not (file-exists-p parent-directory))
(y-or-n-p (format "Directory `%s' does not exist. Create it?" parent-directory)))
(make-directory parent-directory t))))
(defun gcr/occur-dwim ()
"Call `occur' with a mostly sane default.
Attribution Oleh Krehel (abo-abo): URL `http://oremacs.com/2015/01/26/occur-dwim/'"
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(let ((sym (thing-at-point 'symbol)))
(when (stringp sym)
(regexp-quote sym))))
regexp-history)
(call-interactively 'occur))
#+end_src
Emacs lets you set up buffers that won't be re-sized or moved. That is really a
nice option because sometimes you actually don't care. For me, I end up writing
Emacs Lisp and working in the shell so much that it finally dawned on me that I
ought to make permanent buffers for them.
The height of the buffer is:
- 1 row for the name of the mode
- 1 row for a space between the input and the mode name
- =n= for everything else
- there is a mininum
The buffer height it set up in the functions right now and if I end up creating
more then perhaps it would be time to refactor those hard codings.
For now, all of that code may be easily utilized via =gcr/util-cycle=.
#+begin_src emacs-lisp
(defun gcr/util-cycle ()
"Display or hide the utility buffers."
(interactive)
(if gcr/util-state
(gcr/util-stop)
(gcr/util-start)))
#+end_src
Unfill paragraph: because I should have quit doing this by hand 400 posts ago.
#+begin_src emacs-lisp
(defun sacha/unfill-paragraph (&optional region)
"Takes a multi-line paragraph and makes it into a single line of text.
ATTRIBUTION: SRC https://github.com/sachac/.emacs.d/blob/gh-pages/Sacha.org#unfill-paragraph"
(interactive (progn
(barf-if-buffer-read-only)
(list t)))
(let ((fill-column (point-max)))
(fill-paragraph nil region)))
#+end_src
** Color Theme
The solarized theme is the perfect theme for everything, especially bozhidar's
release. It is soft and gentle yet easy to read in any situation.
#+begin_src emacs-lisp
(setq solarized-distinct-fringe-background +1)
(setq solarized-high-contrast-mode-line +1)
(setq solarized-use-less-bold +1)
(setq solarized-use-more-italic nil)
(setq solarized-emphasize-indicators nil)
(load-theme 'solarized-dark)
#+end_src
** Windows
Menu bars are not required.
Curiously, I've come to like the menu bar specifically when working with other
people!
#+begin_src emacs-lisp
(menu-bar-mode +1)
#+end_src
For some reason, on OSX dialogues don't work and essentially end up locking up
Emacs! Here [fn:af30569b: https://superuser.com/questions/125569/how-to-fix-emacs-popup-dialogs-on-mac-os-x] is the solution:
#+begin_src emacs-lisp
(gcr/on-osx
(defadvice yes-or-no-p (around prevent-dialog activate)
"Prevent yes-or-no-p from activating a dialog"
(let ((use-dialog-box nil))
ad-do-it))
(defadvice y-or-n-p (around prevent-dialog-yorn activate)
"Prevent y-or-n-p from activating a dialog"
(let ((use-dialog-box nil))
ad-do-it)))
#+end_src
** Environment
On OSX, I learned that when you start the GUI version of Emacs that it doesn't
inherit the =ENVIRONMENT=. This is the solution.
#+begin_src emacs-lisp
(require 'exec-path-from-shell)
(gcr/on-osx (exec-path-from-shell-initialize))
#+end_src
#+RESULTS:
For a while I went on a quest to get the =Message= buffer to include time-stamps
on each entry. EmacsWiki had some decent approaches but none of them worked
right for me and I didn't want to dig further. Eventually though I got tired of
having to pay close attention to the minibuffer or =Messages= for stuff and
just started looking for GUI options. The plan is to have =Messages= for most
stuff and if there are alerts by any definition then I want that to be an
option. First choice was todochiku [fn:4f2e6828: http://melpa.milkbox.net/#/todochiku] due to the high download count but
two issues, it didn't work and it is not used by anything else. Alert [fn:fd4688ce: http://melpa.milkbox.net/#/alert],
on the other hand, is, and also lives on Github meaning that it is maintainable.
#+begin_src emacs-lisp
(require 'alert)
(setq alert-fade-time 10)
(gcr/on-gui
(gcr/on-osx
(setq alert-default-style 'growl)))
(setq alert-reveal-idle-time 120)
#+end_src
On Windows, you need to specify a specific shell so that Emacs can talk to
other programs in the correct manner:
#+begin_src emacs-lisp
(gcr/on-windows
(setq shell-file-name "cmdproxy.exe"))
#+end_src
Enable the =super= key-space:
#+begin_src emacs-lisp
(gcr/on-osx
(setq mac-control-modifier 'control)
(setq mac-command-modifier 'meta)
(setq mac-option-modifier 'super))
(gcr/on-windows
(setq w32-lwindow-modifier 'super)
(setq w32-rwindow-modifier 'super))
#+end_src
** Code folding
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 [fn:c3cd65d8: http://emacs.wordpress.com/2007/01/16/quick-and-dirty-code-folding/]
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: [fn:425c5a43: http://www.emacswiki.org/emacs/OutlineMode][fn:80e6214c: http://www.emacswiki.org/emacs/FoldingMode][fn:160: https://github.com/zenozeng/yafolding.el][fn:82e77bec: http://cedet.sourceforge.net/].
If you know org-mode, then using that style of control makes it easier to use
then the built in bindings for hideshow [fn:30f9d745: https://www.gnu.org/software/emacs/manual/html_node/emacs/Hideshow.html], on which hideshow-org is built. After using this for a while, it came not to be the right
thing for me. There is no mode hook. It failed when I wanted to bind it to
something other than =TAB=. So, using the built in hideshow turned out to be the
best option.
#+begin_src emacs-lisp
(setq hs-hide-comments-when-hiding-all +1)
(setq hs-isearch-open +1)
(defun display-code-line-counts (ov)
"Displaying overlay content in echo area or tooltip"
(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)
(defadvice goto-line (after expand-after-goto-line activate compile)
"How do I get it to expand upon a goto-line? hideshow-expand affected block when using goto-line in a collapsed buffer."
(save-excursion
(hs-show-block)))
#+end_src
** Buffers
Show line numbers everywhere. [fn:bab178f9: http://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/linum.el?h=emacs-24]
This may slow things down somewhere, sometime, and if it does, I will deal with
it then. Well, at least this is how I used to do it. Some modes didn't handle
things well and for some reason this mode wouldn't turn off. Oh well, I will
manually enable it for desired modes! it will dynamically adjust the
number gutter, and this irritating to have that shift occur. Fix it to 5 numbers,
and if I start working with files that have 100K+ lines then I will change it.
Set =linum-format= via customize.
#+begin_src emacs-lisp
(global-linum-mode -1)
#+end_src
Activate syntax highlighting everywhere. [fn:0dc4ff83: https://www.gnu.org/software/emacs/manual/html_node/emacs/Font-Lock.html]
#+begin_src emacs-lisp
(global-font-lock-mode 1)
#+end_src
Window navigation isn't something that I do a ton of… but I still want it to be
a nice option when I use IRC and want separate windows. ace-window makes this
easy:
#+begin_src emacs-lisp
(setq aw-keys '(?a ?s ?d ?f ?j ?k ?l ?\;))
#+end_src
Visualize parentheses a certain way. [fn:b352291c: https://www.gnu.org/software/emacs/manual/html_node/emacs/Matching.html]
#+begin_src emacs-lisp
(setq blink-matching-paren nil)
(show-paren-mode +1)
(setq show-paren-delay 0)
(setq show-paren-style 'expression)
#+end_src
Don't use audible bells, use visual bells. [fn:00bb2e9a: https://www.gnu.org/software/emacs/manual/html_node/elisp/Beeping.html]
#+begin_src emacs-lisp
(setq ring-bell-function 'ignore)
(setq visible-bell +1)
#+end_src
This post [fn:ea94a54c: http://www.wisdomandwonder.com/link/8533/avoiding-window-takeover-in-emacs] got me thinking that perhaps it was wrong of me to be happy
with simply re-positioning all of my windows after their layout gets changed.
Probably, I'm just a simple user and never run into this problem, or perhaps
my layout is so simple that restoring it is not a big deal. That said, I've
been having a nagging feeling about how exactly I plan to utilize ERC now that
I've got it set up and simply avoided the topic for a while. Now is the time to
address it. Reading more about winner-mode [fn:13e4e7a4: https://www.gnu.org/software/emacs/manual/html_node/emacs/Window-Convenience.html] [fn:f0518791: http://irreal.org/blog/?p=1557], though, has sort
of got me wondering why I never pursued something like this before now. This
package /continues/ to be massively under-recognized for its simplicity and
consequent power.
#+begin_src emacs-lisp
(winner-mode +1)
#+end_src
When the time is right, I'll look into Workgroups for Windows [fn:874dad92: https://github.com/tlh/workgroups.el]
or its friends.
The cursor should not blink. [fn:5873530d: https://www.gnu.org/software/emacs/manual/html_node/emacs/Cursor-Display.html]
#+begin_src emacs-lisp
(blink-cursor-mode 0)
(gcr/on-gui
(setq-default cursor-type 'box))
(setq x-stretch-cursor 1)
#+end_src
Make deleting an entire line work how you may
expect [fn:f3160ceb: http://www.wilfred.me.uk/.emacs.d/init.html#sec-3-7]
#+begin_src emacs-lisp
(defadvice kill-line (around kill-line-remove-newline activate)
(let ((kill-whole-line t))
ad-do-it))
#+end_src
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 [fn:cbacf0d5: https://github.com/alpaker/Fill-Column-Indicator]. 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. My final solution to be able to use this package was to generate
two Emacs configuration files, one for general use and one just for doing
exports.
Make it really obvious where the 80th column sits. [fn:acc1a645: http://stable.melpa.org/#/fill-column-indicator]
#+begin_src emacs-lisp
(setq-default fill-column 80)
#+end_src
Something that I never missed from Idea was version control status info in the
fringe, just never used it. Then when I saw it [fn:27efe175: https://github.com/dgutov/diff-hl] in Emacs, I got curious about how
it /may/ be used. So, I installed it. Curious to see how it will facilitate
communicating the status of this document. Initial experiences has me thinking
that it is actually much nicer than I figured, so I will enable it globally
for a while.
#+begin_src emacs-lisp
(global-diff-hl-mode)
#+end_src
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.
The library: [fn:29f58393: https://github.com/magnars/expand-region.el]
#+begin_src emacs-lisp
(require 'expand-region)
#+end_src
How to jump to locations in a buffer in an easier way than by using the built
in key bindings? Science… that is how.
v1.
This package [fn:bb3b4f83: https://github.com/winterTTr/ace-jump-mode] searches for the character for which you are searching at
the start of a word, highlights matches, and presents you with the letter to
press to jump to the match. You may also search in the middle of words. The key
to using this to utilize =pop-mark= to get back to where you were.
v2.
Navigating a buffer was never slow… until learning about
ace-jump-mode [fn:e4201d0c: https://github.com/winterTTr/ace-jump-mode/wiki/AceJump-FAQ]. The idea is so deceptively simple, and when you grok
it, you will be truly shocked. The author sums it up quite succinctly
#+begin_src emacs-lisp
(autoload
'ace-jump-mode
"ace-jump-mode"
"Emacs quick move minor mode"
t)
(autoload
'ace-jump-mode-pop-mark
"ace-jump-mode"
"Ace jump back:-)"
t)
(eval-after-load "ace-jump-mode"
'(ace-jump-mode-enable-mark-sync))
(define-key global-map (kbd "C-x SPC") 'ace-jump-mode-pop-mark)
#+end_src
Keep open files open across sessions. [fn:1d393334: https://www.gnu.org/software/emacs/manual/html_node/emacs/Saving-Emacs-Sessions.html#Saving-Emacs-Sessions]
You need to be really thoughtful here because =desktop-mode= stores *all* buffer
information. Most of the time this is exactly what you want and then you forgot
about it because it /just works/ so well. The trouble comes when you reconfigure
the mode and restart Emacs and those old buffer settings are re-loaded when you
really wanted the new settings loaded.
#+begin_src emacs-lisp
(desktop-save-mode 1)
(setq desktop-restore-eager 10)
#+end_src
Automatically save every buffer associated with a file [fn:893e2436: http://marmalade-repo.org/packages/real-auto-save]. This is another
IntelliJ holdover. The built in auto-save in Emacs wasn't something that I
needed, and this does the right thing. There is a bit more though to it,
namely because the interval is only 20s I still want/need to be sure that
the file is saved /before/ doing anything like running code or doing a build
As such, before most operations, all buffers with files attached are saved
/first/. When I switched to =package= again and used
=el-get= to install this instead of =melpa=, =real-auto-save= quit working. Gosh.
Found [fn:7d587f95: http://lexfridman.com/blogs/research/2011/06/26/auto-save-files-in-emacs/]
which gives me what I want, since I seemingly couldn't figure that out
myself in the past!
#+begin_src emacs-lisp
(setq auto-save-default t)
(setq make-backup-files nil)
(setq auto-save-visited-file-name t)
(setq auto-save-interval 05)
(setq auto-save-timeout 05)
#+end_src
Bozhidar shared how to get even more default save behavior similar to Idea [fn:e6e85738: http://batsov.com/articles/2012/03/08/emacs-tip-number-5-save-buffers-automatically-on-buffer-or-window-switch/].
#+begin_src emacs-lisp
(defadvice switch-to-buffer (before gcr/save-all-file-buffers-now activate)
(when buffer-file-name (gcr/save-all-file-buffers)))
(defadvice other-window (before other-window-now activate)
(when buffer-file-name (gcr/save-all-file-buffers)))
(defadvice windmove-up (before other-window-now activate)
(when buffer-file-name (gcr/save-all-file-buffers)))
(defadvice windmove-down (before other-window-now activate)
(when buffer-file-name (gcr/save-all-file-buffers)))
(defadvice windmove-left (before other-window-now activate)
(when buffer-file-name (gcr/save-all-file-buffers)))
(defadvice windmove-right (before other-window-now activate)
(when buffer-file-name (gcr/save-all-file-buffers)))
#+end_src
Make two buffers with the same file name open distinguishable. [fn:de75200e: https://www.gnu.org/software/emacs/manual/html_node/emacs/Uniquify.html]
#+begin_src emacs-lisp
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)
#+end_src
Support transparent AES encryption of buffers. [fn:5743c74c: http://ccrypt.sourceforge.net/#emacs]
See also for library paths [fn:58592a74: https://www.gnu.org/software/emacs/manual/html_node/emacs/Lisp-Libraries.html]
#+begin_src emacs-lisp
(gcr/on-osx
(add-to-list 'load-path "/usr/local/Cellar/ccrypt/1.10/share/emacs/site-lisp"))
(gcr/on-windows
(add-to-list 'load-path "C:\\opt\\ccrypt-1.10.cygwin-i386\\"))
(gcr/on-gnu/linux
(warn "Please configure ccrypt."))
(require 'ps-ccrypt "ps-ccrypt.el")
#+end_src
With modern VCS, backup files aren't required. [fn:4c56e8e0: https://www.gnu.org/software/emacs/manual/html_node/elisp/Making-Backups.html]
#+begin_src emacs-lisp
(setq backup-inhibited 1)
#+end_src
Ban white-space at end of lines, globally. [fn:cb5158b0: https://www.gnu.org/software/emacs/manual/html_node/emacs/Useless-Whitespace.html]
#+begin_src emacs-lisp
(add-hook 'write-file-hooks
(lambda ()
(gcr/delete-trailing-whitespace)))
#+end_src
The world is so rich with expressivity. Although Unicode may never capture all
of the worlds symbols, it comes close. [fn:01abb328: https://www.gnu.org/software/emacs/manual/html_node/emacs/International.html#International] [fn:0f1757b6: https://www.gnu.org/software/emacs/manual/html_node/emacs/Recognize-Coding.html] [fn:0242be7c: https://www.gnu.org/software/emacs/manual/html_node/emacs/Output-Coding.html]
#+begin_src emacs-lisp
(prefer-coding-system 'utf-8)
(gcr/on-gui
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
(gcr/on-windows
(set-clipboard-coding-system 'utf-16le-dos)))
#+end_src
The value =default-process-coding-system= seems to be set automatically, and it is
worth noting here that two things need to be set namely buffer coding and
process coding and that both seem to be set [fn:96d1a4e4: http://permalink.gmane.org/gmane.emacs.ess.general/8332].
Emacs has a powerful buffer tracking change system. Unfortunately, I don't
understand any of it. Undo should "just work".
#+begin_src emacs-lisp
(require 'undo-tree)
(global-undo-tree-mode 1)
(gcr/diminish 'undo-tree-mode)
#+end_src
Sometimes it is a problem when you haven't got a newline ending a file with
source code before it… org-mode is one such case. Require that every file have a
final newline before saving it.
#+begin_src emacs-lisp
(setq require-final-newline t)
#+end_src
Speaking of line endings just read this [fn:21bec4d5: https://www.reddit.com/r/emacs/comments/2g6huy/how_to_default_to_crlf_endings_for_windowscentric/].
If I ever want to force line ending type based on file name, then that is how.
For a long time I wanted auto-revert everywhere and for some reason gave up on
adding it. What the heck? I am human.
#+begin_src emacs-lisp
(global-auto-revert-mode 1)
#+end_src
This [fn:d95e8aea: http://endlessparentheses.com/permanent-auto-indentation.html]
post suggest that wanting to "never have unindented code again" is "aggressive".
Well, perhaps that is a bit strong? However, it is certainly interesting and
perhaps even controversial. Nobody wants to be locked down in their editor with
their code. Perhaps the bondage and discipline language user would disagree? I
don't mind, in regards to editors and code at least! Using this approach doesn't
prevent you from doing anything in particular other than poorly indenting code.
This will be a fun experiment and I will start out with emacs-lisp and ℝ to see
how it goes. Generally the experiment has gone well, and it is not it's own
package, and it uses autoload so there is no more code here.
Dealing with markup that uses tags is pretty easy per-mode as you do it once and
you are done. In modes liks =org= though you tend to have more evolutionary steps
in your document so you end up wrapping things after the fact a lot.
=wrap-region= [fn:fd94462d: https://github.com/rejeep/wrap-region.el] makes this
easy, fast, and intuitive. Well it lets /you/ do it, which is just as good!
Thoughts:
- Should mode setting be defined here?
- Will try for now
- Should =wrap-region-remove-wrapper= be specified?
- Won't for now can just undo.
#+begin_src emacs-lisp
(require 'wrap-region)
(gcr/diminish 'wrap-region-mode)
(wrap-region-add-wrapper "*" "*" nil 'org-mode) ;; bold
(wrap-region-add-wrapper "/" "/" nil 'org-mode) ;; italic
(wrap-region-add-wrapper "_" "_" nil 'org-mode) ;; underlined
(wrap-region-add-wrapper "=" "=" nil 'org-mode) ;; verbatim
(wrap-region-add-wrapper "~" "~" nil 'org-mode) ;; code
(wrap-region-add-wrapper "+" "+" nil 'org-mode) ;; strike-through
;; (wrap-region-add-wrapper "«" "»" "w" 'org-mode) ;; noweb blocks
#+end_src
Usually you actually need two scratch buffers, one for Emacs lisp and one for
text:
#+begin_src emacs-lisp
(let ((text-buffer (get-buffer-create "*text*")))
(with-current-buffer text-buffer
(text-mode)
(insert "Shall we play a game?")
(beginning-of-line)))
#+end_src
A lot of times you write things that involves quoting large chunks from other
documents. I'm thinking this is more spur of the moment… like in emails.
However, this may occur anywhere I suppose. Perhaps coding is another place? At
least when you are not doing LP it would be more likely. This [fn:4ab3a68a: https://github.com/davep/boxquote.el]
seems like a nice way to make it obvious when I insert quoted text:
#+begin_src emacs-lisp
(require 'boxquote)
#+end_src
The more that I use this package, the more obvious it becomes how insanely
useful it is.
How you move around lines in a file is configurable. My preference is that if I
am on the end of a line, and I go up or down, then I want to go to the end of
line on that new line. Specifically, I do not want to account for anything
special about the character I am dealing with. This is what most folks would
expect:
#+begin_src emacs-lisp
(setq track-eol +1)
(setq line-move-visual nil)
#+end_src
Sometimes you want to swap two pieces of text within a buffer. This library
makes it very simple to do that by selecting what you want to swap, starting
the anchored transpose, and then choosing its destination.
#+begin_src emacs-lisp
(global-set-key [?\C-x ?t] 'anchored-transpose)
(autoload 'anchored-transpose "anchored-transpose" nil t)
#+end_src
For a long while I used =tabbar= [fn:11b925fe: http://www.emacswiki.org/emacs/TabBarMode]
and found it to be quite nice. You may easily cycle through specific types of
files and specific types of buffers of your choice. It is a very easy to use
and nice feature. Years ago, it helped me out a lot for transitioning to Emacs.
Eventually, I just no longer felt the need for it… and still I think very
highly of it. For the longest time, I would only keep a handful of buffers open.
It was probably because of my VIMentality. That is what everyone says,
attributing everything to the editor that they are using. It was really my
choice though not the editor's choice! Nonetheless, with time, I was able to
leave more buffers open and got more curious about them, so I first turned
to =buffer-menu=, and soon wanted more. How much more? I didn't know, and I
still don't, but I will use =ibuffer= [fn:167d949c: http://www.emacswiki.org/emacs/IbufferMode] [fn:29b94e55: http://emacs-fu.blogspot.fr/2010/02/dealing-with-many-buffers-ibuffer.html]
to let me do it. Joking aside, purcell's approach [fn:e46c420a: https://github.com/purcell/ibuffer-vc]
to group buffer's by their vc
root directory and show their vc status. This is kind of a dream come true, that
is exactly what I had wanted. Every time you need something good, purcell
already has a solution for it. This workflow is nearly identical to how I use
stathon [fn:d801c7b7: https://github.com/grettke/stathon], the only difference
being that the latter knows about all files rather than file just open in the
buffer. Perhaps =projectile= will grow to include something that reports vc
status? Let me check. =projectile-vc= is pretty close!
#+begin_src emacs-lisp
(require 'ibuffer)
#+end_src
Having the buffer move up and down one line at a time is generally nice and fine
(especially with a mouse). It is really unpleasant though when you get up to or
down into the next page while scolling with the cursor because the entire
contents of you screen just *jump* quite uncomfortably. My preference here is to
keep the cursor 10 lines or so from the top or the bottom. This is a preference
that cycles over the years… but I always come back to turning it on again.
#+begin_src emacs-lisp
(require 'smooth-scrolling)
#+end_src
Sometimes it is difficult to comprehend tabular data inside of a buffer, so make
it easier.
#+begin_src emacs-lisp
(require 'stripe-buffer)
#+end_src
Not sure where to put this right now, but I want all buffers savd before this
system exits as the default behavior.
The default behavior of this system is that all buffers with files attached
are always saved, especially before exiting the system.
#+begin_src emacs-lisp
(defadvice save-buffers-kill-terminal (before save-before-save-buffers-kill-terminal first activate)
"Save all buffers before save-buffers-kill-terminal calls."
(gcr/save-all-file-buffers))
#+end_src
#+begin_quote
In my world, sentences end with a single space. This makes sentence navigation commands work for me. [fn:85c41faf: https://github.com/sachac/.emacs.d/blob/gh-pages/Sacha.org]
#+end_quote
#+begin_src emacs-lisp
(setq sentence-end-double-space nil)
#+end_src
Visual-line-mode is really, really great. When it is running, I don't need
to know about it.
#+begin_src emacs-lisp
(gcr/diminish 'visual-line-mode)
#+end_src
Hide-show is another sweet mode that I don't need to know is running.
#+begin_src emacs-lisp
(eval-after-load "hideshow" '(diminish 'hs-minor-mode))
#+end_src
** Frames
Make the title frame something special.
#+begin_src emacs-lisp
(gcr/on-osx (setq frame-title-format '("𝔸𝕃𝔼ℂ")))
(gcr/on-windows (setq frame-title-format '("ALEC")))
#+end_src
The scroll bars are actually quite nice. Despite that, I don't actually
use them, but I think that others would like them. The only problem is that
the current theme doesn't color the bars (not sure if any do), so it has to be
turned off.
#+begin_src emacs-lisp
(scroll-bar-mode 0)
#+end_src
The tool bars used to be not very nice, but now they are. I really do like this
because it often provides useful things. Illogically, I don't like to see it.
#+begin_src emacs-lisp
(tool-bar-mode -1)
#+end_src
Let the mouse-wheel move the cursor in a sane manner.
#+begin_src emacs-lisp
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
(setq mouse-wheel-progressive-speed nil)
(setq mouse-wheel-follow-mouse +1)
#+end_src
** File-system management (GUI)
Not quite sure where this should go yet. Finder is [fn:dbe73f8c: https://en.wikipedia.org/wiki/Finder_(software)] is just fine (Fine-der?), and
the curiosity is still there for an in-Emacs solution. Speedbar [fn:c05b9cba: http://www.emacswiki.org/emacs/SpeedBar] and
SrSpeedbar [fn:41a6cbbc: http://www.emacswiki.org/emacs/SrSpeedbar] look nice, as does [fn:8cc3a263: https://github.com/jaypei/emacs-neotree]. The thing is though that
with stuff like =projectile=, you really don't need to worry about hierarchical
file-system navigation anymore. Instead, it is the familiarity that lingers, not
the need. Lately I've been using =finder= a lot to do file-system stuff. Is it
time to integrate here? Not sure yet. =direx= [fn:85d63d39: https://github.com/m2ym/direx-el]
also seems nice.
Finally I ran into real scenario. This will sound kind of trivial, but it is
valuable: I had 5-10 directories that I wanted to work with. I wasn't sure
which ones I would want to inspect so I had to dig around. I ended up keeping
3-5 of them open at a time as I was comparing their contents. This really wasn't
suitable for any combination of any command-line or Emacs tools. It is exactly
what I would need a GUI to do, so now I am curious about if or how I would do
this inside of Emacs. Is =dired= an option here? No, not right now. OIC there
are so many options [fn:4c7d24d1: https://stackoverflow.com/questions/3538064/nerdtree-for-emacs]! What about =eshell=?
That doesn't really suit the use case, either. Just watched this [fn:a34be4d5: https://www.youtube.com/watch?v=NKtocCAWxiE]
and it seems like a fine place to start. Just used it for 5 minutes and I can
already see that it is wonderful for my use case.
#+begin_src emacs-lisp
(require 'neotree)
#+end_src
** File-system/directory management (Console)
The last file or file-system management tool that I used wast Norton Commander [fn:729276f2: https://en.wikipedia.org/wiki/Norton_Commander]
and then Midnight Commander [fn:1cf538c0: https://www.midnight-commander.org/], 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 file-system; 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 [fn:b1078e9e: http://www.emacswiki.org/DiredDetails], 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
scheduled, and then executed, upon your command. Files can be viewed in modify
or read-only mode, too. There is an idea of =mark-in 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 [fn:7b0e8e3b: https://www.gnu.org/software/emacs/manual/html_node/elisp/Regular-Expressions.html]
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 time-stamp, 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 date-time.
=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 handy tool that you need once in
a while but definitely do need.
#+begin_src emacs-lisp
(setq dired-listing-switches "-alh")
(setq dired-recursive-deletes +1)
(require 'dired-details+)
(setq-default dired-details-hidden-string "")
(defun gcr/dired-mode-hook ()
"Personal dired customizations."
(local-set-key "c" 'gcr/dired-copy-filename)
(local-set-key "]" 'gcr/dired-copy-path)
(diff-hl-dired-mode)
(load "dired-x")
(turn-on-stripe-buffer-mode)
(stripe-listify-buffer))
(add-hook 'dired-mode-hook 'gcr/dired-mode-hook)
#+end_src
Try to guess the target directory for operations.
#+begin_src emacs-lisp
(setq dired-dwim-target t)
#+end_src
After dabbling, something happened that really changed my mind. These three
articles changed everything: [fn:87e72370: http://www.masteringemacs.org/articles/2014/04/10/dired-shell-commands-find-xargs-replacement/] [fn:d82e40f9: http://www.masteringemacs.org/articles/2011/03/25/working-multiple-files-dired/] [fn:fe52afc4: http://www.masteringemacs.org/articles/2013/10/10/wdired-editable-dired-buffers/].
They just made the power of Dired so obvious, and so easy to use, that it
instantly because delightful to use. That was very, very cool. Even though I
was really, really happy with Finder and Explorer… suddenly it just became so
obvious and pleasant to use Dired. That is so wild.
Key notes when executing shell commands on file selection…
Substitution:
- = ?= :: 1* calls to cmd, each file a single argument
- = *= :: 1 call to =cmd=, selected list as argument
- = *""= :: have the shell expand the * as a globbing wild-card
- Not sure what this means
Synchronicity:
- = …= :: by default commands are called synchronously
- = &= :: execute in parallel
- = ;= :: execute sequentially, asynchronously
- = ;&= :: execute in parallel, asynchronously
Key notes on working with files in multiple directories… use the following:
Use =find= just like you would at the command line and all of the results show
up in a single Dired buffer that you may work with just like you would any other
file appearing in a Dired buffer. The abstraction here becomes so obvious, you
may ask yourself why you never considered such a thing /before/ now (as I did):
#+begin_src emacs-lisp
(require 'find-dired)
(setq find-ls-option '("-print0 | xargs -0 ls -ld" . "-ld"))
#+end_src
Noting that:
- =find-dired= :: is the general use case
- =find-name-dired= :: is for simple, single string cases
And if you want to use the faster Elisp version, that uses lisp regex, use:
- =find-lisp-find-dired= :: for anything
- =find-lisp-find-dired-subdirectories= :: for only directories
Key notes on working with editable buffers…
As the author notes, you probably already instinctually knew what is possible.
After reading his brief and concise exposition, it would be hard /not/ to
intuit what is possible! The options are big if you make a writable file buffer.
Think about using multiple cursors. Done? Well, that is a no-brainer. Once you
grok multiple cursors just =find-dired= what you need and then do what you need
to do to it. Very cool.
- =dired-toggle-read-only, C-x C-q= :: cycle between dired-mode and wdired-mode
- =wdired-finish-edit, C-c C-c= :: commit your changes
- =wdired-abort-changes, C-c ESC= :: revert your changes
#+begin_src emacs-lisp
(require 'wdired)
(setq wdired-allow-to-change-permissions t)
(setq wdired-allow-to-redirect-links t)
(setq wdired-use-interactive-rename +1)
(setq wdired-confirm-overwrite +1)
(setq wdired-use-dired-vertical-movement 'sometimes)
#+end_src
Today I just learned about =image-dired=, why didn't I think to ask before now?
When you selected a bunch of files or directories, you /may/ want to communicate
somewhere your selection somehow. The simplest way to do this is to utilize
=dired-copy-filename-as-kill=. What a nice idea, and its default binding is =w=.
Since I started using a menu bar again, and wanting to get Imenu really
exercised, Dired in Imenu seems like an obvious choice.
#+begin_src emacs-lisp
(require 'dired-imenu)
#+end_src
** Save history of all things
See: [fn:43a849e2: https://www.gnu.org/software/emacs/manual/html_node/emacs/Saving-Emacs-Sessions.html] [fn:ac19c66e: http://fly.srk.fer.hr/~hniksic/emacs/savehist.el] [fn:c39d161c: https://stackoverflow.com/questions/1229142/how-can-i-save-my-mini-buffer-history-in-emacs]
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.
This file keeps track of everything that =savehist= stores for us and doesn't
need to be version controlled so it is checked as a real file.
The file that =savehist= stores its stuff in is not under version control.
The check for the file may no longer be required. Savehist used to store its
history in ~/.emacs.d/savehist. I think I copied that from emacs-fu. Recently
their API updated. My code to store this setting in that file broke. When it
broke Savehist just saved its stuff in the default file. That works. I didn't
even notice it. That is fine with me. I am leaving it alone. I kept this check
code in place to check that the default history file is there.
#+begin_src emacs-lisp
(defconst gcr/savehist-file-store "~/.emacs.d/history")
(defun gcr/warn-savehist-file-store ()
"Warn of savehist misconfiguration."
(interactive)
(unless (gcr/file-exists-not-symlink gcr/savehist-file-store)
(warn "Can't seem to find a savehist store file where it was expected at: %S. Savehist should continue to function normally; but your history may be lost."
gcr/savehist-file-store)))
#+end_src
=savehist= configuration follows.
#+begin_src emacs-lisp
(gcr/warn-savehist-file-store)
(setq savehist-save-minibuffer-history 1)
(setq savehist-additional-variables
'(kill-ring
search-ring
regexp-search-ring))
(savehist-mode +1)
#+end_src
** Spell-checking
See: [fn:4fc20d0a: https://www.gnu.org/software/emacs/manual/html_node/emacs/Spelling.html] [fn:b6f544fd: http://www.emacswiki.org/emacs/InteractiveSpell] [fn:e620b160: http://blog.binchen.org/posts/what-s-the-best-spell-check-set-up-in-emacs.html] [fn:8ce1e37a: http://melpa.milkbox.net/#/ac-ispell]
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 flyspell 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 is there
most UNI*, running =ispell= from Emacs just does the right thing.
Even after reading this later, I agree with it despite the fact that I
constantly wax and wane between wanting to use it and finding something
/better/ despite having no criteria by which to truly judge in the first place.
The =aspell= personal directionary is version controlled.
These Aspell artifacts are valuable. Treat them appropriately. Don't place
junk in them. Review them periodically. Weed out bad entries.
#+begin_src emacs-lisp
(defconst gcr/aspell-personal-dictionary "~/.aspell.en.pws")
(defun gcr/warn-aspell-personal-dictionary ()
"Warn of aspell misconfiguration: personal dictionary."
(interactive)
(unless (gcr/file-exists-is-symlink gcr/aspell-personal-dictionary)
(warn
"Can't seem to find an aspell personal dictionary where it was expected at: %S. aspell should continue to function normally; but your personal dictionary will not be used."
gcr/aspell-personal-dictionary)))
(gcr/warn-aspell-personal-dictionary)
#+end_src
So is the personal replacement dictionary. This is a copy and paste of the
previous section. It is obviously a candidate for cleanup.
#+begin_src emacs-lisp
(defconst gcr/aspell-personal-replacement-dictionary "~/.aspell.en.prepl")
(defun gcr/warn-aspell-personal-replacement-dictionary ()
"Warn of aspell misconfiguration: personal replacement dictionary."
(interactive)
(unless (gcr/file-exists-is-symlink gcr/aspell-personal-replacement-dictionary)
(warn
"Can't seem to find an aspell personal replacement dictionary where it was expected at: %S. aspell should continue to function normally; but your personal replacement dictionary will not be used."
gcr/aspell-personal-replacement-dictionary)))
(gcr/warn-aspell-personal-replacement-dictionary)
#+end_src
** Syntax checking
It is a great feature. Flyspell never interested me though because of so many
negative reports and it just didn't seem that important. Well, that was before
breaking this document for the N^{th} time! There is a need, and Flycheck [fn:88ce9bae: https://github.com/flycheck/flycheck]
seems to be the best of the best out there.
#+begin_src emacs-lisp
(require 'flycheck)
(add-hook 'after-init-hook #'global-flycheck-mode)
(gcr/diminish 'flycheck-mode)
#+end_src
** Templating
See: [fn:c3b8f741: https://github.com/capitaomorte/yasnippet]
Code completion 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.
=yas= snippets directory is not version controlled.
#+begin_src emacs-lisp
(require 'yasnippet)
#+end_src
Remaining configuration follows.
#+begin_src emacs-lisp
(yas-global-mode 1)
(gcr/diminish 'yas-minor-mode)
#+end_src
=yas= shouldn't use =TAB=.
#+begin_src emacs-lisp
(defun gcr/yas-minor-mode-hook ()
"Personal customizations."
(define-key yas-minor-mode-map (kbd "") nil)
(define-key yas-minor-mode-map (kbd "TAB") nil)
(define-key yas-minor-mode-map (kbd "s-4") 'yas-expand))
(add-hook 'yas-minor-mode-hook 'gcr/yas-minor-mode-hook)
#+end_src
** White-space management
See: [fn:1283938f: https://www.gnu.org/software/emacs/manual/html_node/emacs/Useless-Whitespace.html]
Do you need to see tabs and other control characters? Usually, yes.
#+begin_src emacs-lisp
(require 'whitespace)
(setq whitespace-style '(trailing lines tab-mark))
(setq whitespace-line-column 80)
(global-whitespace-mode 1)
(gcr/diminish 'global-whitespace-mode)
(gcr/diminish 'whitespace-mode)
#+end_src
** Mark and Region
When you start typing and text is selected, replace it with what you are typing,
or pasting, or whatever. [fn:626951e5: https://www.gnu.org/software/emacs/manual/html_node/emacs/Using-Region.html]
#+begin_src emacs-lisp
(delete-selection-mode 1)
#+end_src
** Modeline
When you load modes, most of them show up in the modeline. After you read
their name a few thousand times, you eventually quite forgetting that you
loaded them and need a diminished reminder. [fn:0a48462d: http://marmalade-repo.org/packages/diminish]
#+begin_src emacs-lisp
(require 'diminish)
#+end_src
The modeline is capable of so many things. Though I use it for few, I value it
greatly. Even the generic, optional options [fn:dc1e3869: https://www.gnu.org/software/emacs/manual/html_node/emacs/Optional-Mode-Line.html] are nice.
Show the file size.
#+begin_src emacs-lisp
(size-indication-mode)
#+end_src
It is nice to see the column number, if you are counting columns (not calories).
#+begin_src emacs-lisp
(column-number-mode 1)
#+end_src
Humans posess the technology to enable to track time and date in a watchpiece.
For fear of damaging either the watchpiece or the computer itself, I quite
wearing watches long ago. That was a mistake. Put on a time piece and turn off
date and time status on the host OS and inside of Emacs. This source block
is kept for reference, and excluded from the generated configuration.
#+begin_src emacs-lisp :noweb-ref ignore
(setq display-time-format "%R %y-%m-%d")
(display-time-mode +1)
#+end_src
Over time you start to, as which everything else in Emacs, think about
configuring it "better". Simple things like the file state indicator [fn:c6a0c2b8: http://ergoemacs.org/emacs/modernization_mode_line.html]
is one of the first to jump out at you. In my case I've made some nice changes
via the built-in mechanisms. Powerline [fn:8090ede6: https://github.com/milkypostman/powerline] really got me thinking though
just because it is so stunning with the use of XPM [fn:7aca939e: https://en.wikipedia.org/wiki/X_PixMap]. Reading through
it though, it would require some real digging in, and the documentation doesn't
say much and I wasn't sure that I wanted to pursue that much right now.
Simple mode line [fn:75606d43: https://github.com/Bruce-Connor/smart-mode-line/] says all the right things, I like their documentation
and am not sure whether or not it knows the right things to highlight, or not.
How does it know? Clearly there are many ideas [fn:d5ddabf6: http://www.emacswiki.org/emacs/ModeLineConfiguration] on how to customize the
modeline. How may we be sure that they are doing it right and displaying
everything that mode expects them to possibly be displaying? Like most things
it is just trust, and verify. For now it is easier to stick with the built in,
and grow it organically. Perhaps more importantly, I /do/ like the built-in
modeline style.
** Speed
As of <2014-07-05 Sat>, there is, as one would expect, quite a focus on speeding
up Emacs. What is the definition of speeding it up? Well, that depends. Like any
UX designer knows, it is all subjective. Is a lazy-load to make startup feel
fast making it faster? It depends. What struck me is the trend for the last few
years to =autoload= basically everything in packages. That is a curious step
because I prefer =require= to make it obvious what we are doing. Either way,
speed matters and all of these topics got me wanting at least to know what is
going on with Emacs in terms of speed… by some measure.
Emacs Start Up Profiler (ESUP) [fn:cd3051f0: https://github.com/jschaf/esup]
does just what it says, and I use it here. For now I do not want to
record startup times becase I've got no question that I want to be answered yet.
As of <2014-07-05 Sat> the startup is =3.181sec=.
#+begin_src emacs-lisp
(autoload 'esup "esup" "Emacs Start Up Profiler." nil)
#+end_src
** Minibuffer
You will want to configure this at some point.
Make it easier to answer questions.
#+begin_src emacs-lisp
(fset 'yes-or-no-p 'y-or-n-p)
#+end_src
It often displays so much information, even temporarily, that it is nice to give
it some room to breath. [fn:3e4cb9f3: https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer-Edit.html]
#+begin_src emacs-lisp
(setq resize-mini-windows +1)
(setq max-mini-window-height 0.33)
#+end_src
Allow recursive commands-in-commands show help me keep track of the levels of
recursion.
#+begin_src emacs-lisp
(setq enable-recursive-minibuffers t)
(minibuffer-depth-indicate-mode 1)
#+end_src
** Searching / Finding / Replacing [fn:350ccf16: http://repo.or.cz/w/emacs.git/blob_plain/HEAD:/lisp/ido.el] [fn:137: https://github.com/lewang/flx]
*** Searching
Perhaps an odd topic, but how you handle spaces when performing an interactive
search is a choice:
#+begin_src emacs-lisp
(setq isearch-lax-whitespace +1)
(setq isearch-regexp-lax-whitespace +1)
#+end_src
Make searches case-insensitive.
#+begin_src emacs-lisp
(setq-default case-fold-search +1)
#+end_src
*** Finding
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. Something I had been curious about
but forgotten and stumbled upon again was vertical ido listing, and I added that
back to see how it goes. My initial reaction was that I had wanted this all
along, though the transition from looking left-right to top-down was a little
unsettling.
#+begin_src emacs-lisp
(require 'ido)
(require 'flx-ido)
(ido-mode 1)
(require 'ido-hacks nil +1)
(require 'ido-ubiquitous)
(ido-ubiquitous-mode +1)
(setq ido-create-new-buffer 'always)
(flx-ido-mode +1)
(setq ido-use-faces nil)
(require 'ido-vertical-mode)
(ido-vertical-mode +1)
(setq ido-vertical-define-keys 'C-n-C-p-up-down-left-right)
#+end_src
*** Replacing
When I use search and replace I just keep doing it until the buffer loops
around. Replacing stops so that works fine. Searching loops around continually.
I have to pay attention to that looping. I am doing it wrong. Anzu is doing it
right by showing you what is happening.
#+begin_src emacs-lisp
(require 'anzu)
(global-anzu-mode +1)
(global-set-key (kbd "M-%") 'anzu-query-replace)
(global-set-key (kbd "C-M-%") 'anzu-query-replace-regexp)
(setq anzu-mode-lighter "")
(setq anzu-deactivate-region t)
(setq anzu-search-threshold 1000)
(setq anzu-replace-to-string-separator " => ")
#+end_src
=anzu-replace-at-cursor-thing= is interesting. I might do exactly the same thing
with Multiple Cursors instead. It is great having options.
Solarized already has [[https://github.com/bbatsov/solarized-emacs/blob/master/solarized.el#L526][support]] for Anzu. I don't like it. I could only configure
it using Customize.
** Sudo
Most of the time I work inside Emacs. I never liked how it handled opening up
files owned by root. I never did anything about it. Instead I just used VI.
Last week I was editing a HOSTS file. I wanted to double check the
domain name I had entered. I didn't know how in VI. I did know how in Emacs.
VI is great and I'll never un-learn the five commands that I learned twenty
years ago. I will always use it on freshly set up systems. I will always use it
on systems without my personal Emacs configuration. It will always be a valuable
tool for me.
On systems where I've got Emacs running all of the time it is stupid not to use
it for files that require sudo. A while ago I made that choice and said that I
would change when it makes sense. Now it makes sense.
I tried this [fn:0474d420: http://emacsredux.com/blog/2013/04/21/edit-files-as-root/]
out. When I typed in the root password and hit enter I got the error
#+begin_example
E RET is undefined
#+end_example
It looks like "E" got defined as a prefix key? My first reaction was "oh well".
I don't remember that. I am not very interested in fixing it. That means that it
is time for some carbohydrates. After searching I found only two posts. The
second one [fn:f1ce823e: https://lists.gnu.org/archive/html/help-gnu-emacs/2005-08/msg00140.html] was
the best. It explained how to find out what key-bindings could be activated given
the key(s) that you have already typed. *WOW*. That is a /big deal/. Type your
keys and hit =C-h=. Of course you do. With that tip it got real clear real fast
where the error lie:
#+begin_example
Major Mode Bindings Starting With E:
key binding
--- -------
E S Prefix Command
E S C Prefix Command
E S C SPC Prefix Command
E S C SPC y gcr/paste-from-x-clipboard
Global Bindings Starting With E:
key binding
--- -------
#+end_example
In other words, the error occurred between the chair and the keyboard. Of course
it did.
#+begin_src emacs-lisp
(gcr/on-gnu/linux-or-osx
(defadvice ido-find-file (after find-file-sudo activate)
"Find file as root if necessary.
Attribution: SRC `http://emacsredux.com/blog/2013/04/21/edit-files-as-root/'"
(unless (and buffer-file-name
(file-writable-p buffer-file-name))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))))
#+end_src
** Popups
If possible, use a better pop-up [fn:002bce83: https://github.com/auto-complete/popup-el] . Pos-tip should help [fn:bd72503b: https://github.com/pitkali/pos-tip].
Have mixed feelings about this. First, glad it is here, and a lot of packages do
use it. Eventually I'll need to set up a larger font.
#+begin_src emacs-lisp
(require 'pos-tip)
(gcr/on-windows
(ignore-errors
(pos-tip-w32-max-width-height)))
#+end_src
My desire was to have =pos-tip= use the current theme values, but I couldn't
figure out how and the folks online weren't quite sure either… it wasn't
worth pursuing and I copied the values straight out of the theme itself.
[[https://github.com/bbatsov/solarized-emacs/blob/master/solarized.el#L1989][This]] was added to the theme config, but I prefer non-bold colors, so I will
leave this for now.
#+begin_src emacs-lisp
(setq pos-tip-foreground-color "#073642")
(setq pos-tip-background-color "#839496")
#+end_src
** Intellisense (Auto Completion) [fn:a5ec7f2e: http://cx4a.org/software/auto-complete/]
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 build a system
without it (unless you are using Java, then you need IntelliJ). Still it is
quite nice to have popup documentation. Still wanting a nice documentation
popup, I think that yet again Purcell and friends make our lives easier.
Thus far, auto-complete has worked fine. More than a few blog-posts do mention
company-mode [fn:87ff338a: https://company-mode.github.io/], so I read up on it. It seems quite nice, but right now I
haven't got a reason to explore it further though.
This package is not happy running under Org Mode, FYI, for some reason.
Still having some mixed feelings about what engine to use to display the popups.
Popup itself is quite easy for me to read since it uses the same font as
everything else. That alone makes it perfect. Still, the idea of having real
popups is intriguing. Either way, both do work, so I will customize as needed.
Until I customize the pos-tip font to make it bigger, though, I will stick with
the old-fashioned style.
#+begin_src emacs-lisp
(require 'fuzzy)
(require 'auto-complete)
(require 'auto-complete-config)
(setq ac-quick-help-prefer-pos-tip nil)
(ac-config-default)
(setq ac-auto-start nil)
(ac-set-trigger-key "TAB")
(gcr/diminish 'auto-complete-mode)
#+end_src
Auto-completion for .-separated words [fn:ab4081de: https://github.com/tkf/auto-complete-chunk] seems like a good idea, so I will
put it here and not worry too much about what header this lives in. The source
explains how to use this feature… it must be specified what is allowed per-mode
- which makes sense.
#+begin_src emacs-lisp
(require 'auto-complete-chunk)
#+end_src
** Symbolic Expression Management [fn:60c9aa87: https://github.com/Fuco1/smartparens]
There are a lot of nice options [fn:f3efaa48: http://www.emacswiki.org/emacs/ParEdit] [fn:65635705: http://www.emacswiki.org/emacs/ElectricPair] [fn:3407e119: https://github.com/rejeep/wrap-region.el] [fn:143: https://code.google.com/p/emacs-textmate/] [fn:2c32e1ab: https://github.com/capitaomorte/autopair]. 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 configuration 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?
#+BEGIN_QUOTE
I object to doing things that computers can do.
#+END_QUOTE
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). =sp-show-pair-from-inside=
is kind of interesting. How it works is that normally when your cursor is to the
right of a bracket, then the entire expression is highlighted. My assumption is
to make it easy for you to see the scope of the s-exp. When you move forward, to
the right of that opening bracket, then that highlight goes away. When you set
this flag to non-nil, you get a different behavior where just the bracket is
highlighted. Not sure how this would help, but still it is kind of interesting
to me because it keep your focus. My use case is that you find an s-exp that you
want to edit and start doing it, and in that case I wouldn't use this flag.
However, say you had wanted to edit and moved the cursor one char forward and
were interrupted. Perhaps you would this kind of highlight so when you come back
there is still some indicator. From a user-perspective, it just seemed
interesting.
#+begin_src emacs-lisp
(require 'smartparens-config)
(show-smartparens-global-mode +1)
(gcr/diminish 'smartparens-mode)
(setq sp-show-pair-from-inside nil)
#+end_src
Recently I learned of [fn:64fbc8ec: https://github.com/promethial/paxedit] Paxedit.
"One command /just works/ *everywhere*!". Good to know. Once you get on-board with
structural editing, you do, kind of want it /everywhere/.
** Evaluation
#+begin_src emacs-lisp
(setq-default eval-expression-print-level nil)
#+end_src
Allow these commands:
#+begin_src emacs-lisp
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
#+end_src
** Version control / Git
All version control systems basically work
fine in Emacs version control (VC) abstraction layer, and I like it a lot.
What made me focus on Git and how I work with it though was two things:
1-I use that for hours and hours at work and home and 2-I had been using
a standalone Git UI and I felt like it was kind of stupid not to use
something built into Emacs. This will require further research.
One thing that I did find that I wanted though was that despite having set auto
save to occur quite frequently, it was still possible to initiate a VC action
without the buffering being saved. My solution for that is that before *every*
VC action, at least the current buffer must be saved. This is OK because I
believe that VC actions only occur on a per-file basis, versus command line VC
operations. Then I added he same thing for diff.
#+begin_src emacs-lisp
(defadvice vc-next-action (before save-before-vc first activate)
"Save all buffers before any VC next-action function calls."
(gcr/save-all-file-buffers))
(defadvice vc-diff (before save-before-vc-diff first activate)
"Save all buffers before vc-diff calls."
(gcr/save-all-file-buffers))
(defadvice vc-ediff (before save-before-vc-ediff first activate)
"Save all buffers before vc-ediff calls."
(gcr/save-all-file-buffers))
(defadvice vc-revert (before save-before-vc-revert first activate)
"Save all buffers before vc-revert calls."
(gcr/save-all-file-buffers))
#+end_src
The log edit buffer is only used in VC mode I think, and needs to some
configuration.
#+begin_src emacs-lisp
(defun gcr/log-edit-mode-hook ()
"Personal mode bindings for log-edit-mode."
(gcr/untabify-buffer-hook)
(gcr/disable-tabs)
(fci-mode))
(add-hook 'log-edit-mode-hook 'gcr/log-edit-mode-hook)
(defun gcr/log-edit-mode-hook-local-bindings ()
"Helpful bindings for log edit buffers."
(local-set-key (kbd "C-;") 'log-edit-done))
(add-hook 'log-edit-mode-hook 'gcr/log-edit-mode-hook-local-bindings)
#+end_src
=magit= also should have a similar configuration. Magit is very important.
Eventually it will go under its own heading.
Save every buffer with a file attached before starting Magit. This is how it is
done with VC up above.
#+begin_src emacs-lisp
(defadvice magit-status (before save-before-magit first activate)
"Save all buffers before using Magit."
(gcr/save-all-file-buffers))
#+end_src
Make sure Magit knows that I read the warning. It wasn't instructions.
#+begin_src emacs-lisp
(setq magit-last-seen-setup-instructions "1.4.0")
#+end_src
#+begin_src emacs-lisp
(defun gcr/git-commit-commit ()
"Allow commit message to save before committing."
(interactive)
(save-buffer)
(git-commit-commit))
(defun gcr/git-commit-mode-hook ()
"Personal customizations."
(local-set-key (kbd "C-;") 'gcr/git-commit-commit))
(add-hook 'git-commit-mode-hook 'gcr/git-commit-mode-hook)
#+end_src
The commit messages are not formatted for all vc providers, so just don't use
the default message at all for [[http://debbugs.gnu.org/cgi/bugreport.cgi?bug%3D18954][now]].
#+begin_src emacs-lisp
(eval-after-load 'log-edit
'(remove-hook 'log-edit-hook 'log-edit-insert-message-template))
#+end_src
This current configuration that kind of maximizes speed, doesn't account for
multiple changes that need to be committed. Learning more about =magit= by using
it I thought that I should change the current =vc= workflow over to use =magit=
for committing. Comparing =vc= and =magit=, I decided that the current approach
is still fine because it works so quickly, because I mostly change single files
at a time, and when I don't, =magit= is so fast and intuitive, that there is no
need to port over my mappings or something into =magit=. At least, that is my
current plan for now. Magit is a really, really nice tool. It is pretty clear to
me though that my assessment of it says more about my ability to use Emacs than
it says about =magit=. Only after skinning my knuckles on Emacs, in a more
painful way, am I finally able to appreciate stuff like this.
Git ignore files are just text files.
#+begin_src emacs-lisp
(add-to-list 'auto-mode-alist '(".gitignore$" . text-mode))
#+end_src
Diminish Magit's auto-revert mode.
#+begin_src emacs-lisp
(eval-after-load "magit" '(diminish 'magit-auto-revert-mode))
#+End_src
** Command execution helper [fn:e2221a4d: https://github.com/nonsequitur/smex/]
When I call commands, I usually end up running the same commands over and over.
There are of course key-bindings 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.
#+begin_src emacs-lisp
(require 'smex)
(smex-initialize)
#+end_src
Tell =magit= about git working copies that =projectile= knows about [fn:b7cb4360: https://iqbalansari.github.io/blog/2014/02/22/switching-repositories-with-magit/].
#+begin_src emacs-lisp
(eval-after-load "projectile"
'(progn (setq magit-repo-dirs (mapcar (lambda (dir)
(substring dir 0 -1))
(remove-if-not (lambda (project)
(file-directory-p (concat project "/.git/")))
(projectile-relevant-known-projects)))
magit-repo-dirs-depth 1)))
#+end_src
** Rectangle / Cursors [fn:8d7c694f: https://www.gnu.org/software/emacs/manual/html_node/emacs/Rectangles.html] [fn:178: https://github.com/magnars/multiple-cursors.el]
Once in a very long while I have the need to modify rectangles. Only once in a
while because one may use the key recorder to do most of the same work. There
are a few options [fn:e9f56c39: http://www.emacswiki.org/emacs/RectangleCommands],
and that bothers me, so I didn't choose any of them. This version of Emacs comes
with an edit mode.
Working here thought got me thinking about other folks perspectives, and I
ended up here [fn:9c0a4159: http://emacsrocks.com/e13.html]. This is a strangely intriguing feature. It is quite
versatile as long as you have got a mental model for things. The difference is
that if you are OK with key macros, imagine that multiple-cursors is kind of a
way to use keyboard macros while making it very visible and dynamic and
also using the cursor location along with that interactivity.
#+begin_src emacs-lisp
(require 'multiple-cursors)
#+end_src
** Font
The studies cited above indicate that the two major factors that contribute to
readability of a document are contrast and font-face. Sayre's law [fn:17910758: https://en.wikipedia.org/wiki/Sayre's_law] 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 =*Messages*= 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
finally 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. As of this writing
there are no less than 3 packages that provide solarized. After reading their
documentation quite closely it came down something relatively simple: face
support. Trying to set up help pop-ups to look decent I noticed that =auto-complete=
and =popup= looked horrible. Reading through the different versions, there was
only one [fn:c886e5f6: https://github.com/bbatsov/solarized-emacs] package that provided so many faces that I needed and the
others did not so the decision was easy.
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
occurrences of flagged strings, for example replacing the world =lambda= with
the symbol \lambda.
Based upon the above research, use the DejaVu font family.
#+begin_src emacs-lisp
(defconst gcr/font-base "DejaVu Sans Mono" "The preferred font name.")
#+end_src
Months and months and months after that delightful research I was stunned to
learn of [fn:6f3a8ca3: http://irreal.org/blog/?p=2828] the [[https://github.com/rolandwalker/unicode-fonts][unicode-fonts]]. It
seems that it will make all of my Unicode dreams come true. Can't wait to fall
asleep now! One thing I am actualy really excited about is to be able to use
Emacs for Tamil and Sanskrit.
#+begin_src emacs-lisp
(require 'unicode-fonts)
(unicode-fonts-setup)
#+end_src
Here are the Unicode fonts that I am using, with the specific download links
that I used to install on my system:
| Name | Version | URL | Comments |
|---------+---------+-----+---------------------------|
| [[http://sourceforge.net/projects/dejavu/files/dejavu/2.34/dejavu-fonts-ttf-2.34.tar.bz2][DejaVu]] | 2.43 | [[http://sourceforge.net/projects/dejavu/files/dejavu/2.34/dejavu-fonts-ttf-2.34.tar.bz2][.]] | Modern classic |
| [[http://users.teilar.gr/~g1951d/][Symbola]] | 7.17 | [[http://users.teilar.gr/~g1951d/Symbola.zip][.]] | Neat |
| [[http://www.quivira-font.com/][Quivira]] | 4.0 | [[http://www.quivira-font.com/files/Quivira.otf][.]] | Amazing |
| [[https://code.google.com/p/noto/][Noto]] | ? | [[http://noto.googlecode.com/git/fonts/individual/hinted/NotoSans-Regular.ttc][1]] [[http://noto.googlecode.com/git/fonts/individual/unhinted/NotoSansSymbols-Regular.ttf][2]] | Has morese code, and more |
To test it I ran =view-hello-file= and =M-x list-charset-chars RET unicode-bmp RET=.
It may not be the most scientific approach, but it is clear that there is more
character support then before! All of the Tamil letters are there, though I
wasn't able to download the font apparently OSX has font support built it.
Perhaps humorously, finally we have support for 💩.
Set a font size that may easily be read, on $\frac{1}{2}$ of a high resolution
screen, 80 columns wide.
#+begin_src emacs-lisp
(defvar gcr/font-size 10 "The preferred font size.")
(gcr/on-osx (setq gcr/font-size 17))
(gcr/on-windows (setq gcr/font-size 13))
#+end_src
Convert common ASCII values into Unicode representations /for display only/.
#+begin_src emacs-lisp
(require 'pretty-mode)
#+end_src
When it is /typing time/, do not show the mouse cursor. Be at ease, it will
return once you move it again. The mouse is a /good thing/, but it doesn't mean
that you have to stare at it all of the time!
#+begin_src emacs-lisp
(setq make-pointer-invisible +1)
#+end_src
Load font utilities when on a GUI.
#+begin_src emacs-lisp
(gcr/on-gui
«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)))
(gcr/update-font))
#+end_src
** Project management [fn:7a558748: http://batsov.com/projectile/]
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. Somehow I forgot
how much I liked it because it is so easy to just use =ido-find-file= for
things. After reading a blog post, I revisited the difference between that and
=projectile-find-file= … well the latter has its place as it makes it much
simpler only to deal with files that are known to be project files.
#+begin_src emacs-lisp
(projectile-global-mode 1)
(gcr/diminish 'projectile-mode)
#+end_src
** Emacs Speaks Statistics (ESS) [fn:3bba0c0c: http://ess.r-project.org/] [fn:25441790: https://en.wikipedia.org/wiki/Emacs_Speaks_Statistics] [fn:a2ae633d: http://www.emacswiki.org/emacs/EmacsSpeaksStatistics] [fn:b28cb112: http://blog.revolutionanalytics.com/2011/08/ess.html] [fn:353ffc35: http://blog.revolutionanalytics.com/2014/03/emacs-ess-and-r-for-zombies.html] [fn:3b20a6da: https://rstudio-pubs-static.s3.amazonaws.com/2246_6f220d4de90c4cfda4109e62455bc70f.html]
This section takes about 15 seconds to tangle.
Get =ESS= loaded before doing anything with it in here or out there.
#+begin_src emacs-lisp
(require 'ess-site)
#+end_src
For a minimalist release history, read the news file [fn:7be08525: http://ess.r-project.org/Manual/news.html].
For a brief, brief overview and release history, read the readme [fn:1b644ec0: http://ess.r-project.org/Manual/readme.html].
For a comprehensive overview, read the manual [fn:adfd9a4c: http://ess.r-project.org/Manual/ess.html].
In it:
- 𝕊 refers to any language in the family.
- ℝ is what I'm interested in.
- First 2.5 pages do some nice expectation-setting.
- Generally seems like a highly rich development environment with support for
editing, debugging, and support with everything that you would expect from
the best of Emacs.
- Manual covers most requested variables for configuring, but the customize
facility covers more, and mentions that either way you should avoid doing so
until you have used =ESS= for a while.
- Check that =ess= is installed with a call to =ess-version=.
#+begin_src emacs-lisp
(defconst gcr/ess-version "14.11")
(defun gcr/warn-ess-version ()
"Warn of ess misconfiguration."
(interactive)
(when (not (version= ess-version gcr/ess-version))
(warn "Insufficient ess-mode requirements. Expected %S. Found: %S " gcr/ess-version ess-version)))
(gcr/warn-ess-version)
#+end_src
ℝ first notes:
- ℝ will start ℝ via =Emacs=
- Multiple =ESS= processes may run simultaneously, and may be selected by a
specific language via their buffer name that has a number appended, or may be
accessed via a menu using =ess-request-a-process=.
- =ESS= works transparently on remote machines using =TRAMP= to manage a remote
ℝ instance. An example is provided for Amazon. Means exist for supporting remote
graphical displays or redirecting to a file. Excellent support seems to exist
to quite flexibly support unexpected things like starting an =ESS= supported
program in a plain old shell and being able to convert it to an =ESS= supported
buffer.
Various user interaction stuff:
- Return sends the input from wherever you hit return, nice.
- =M-{= and =M-}= cycle through commands you ran
- =M-h= select a whole "paragraph", a block in their terms
- =C-x [= moves through the previous ESS sessions, =C-x ]= forward.
- =C-c C-p= and =C-c C-n= cycle through previous commands.
- How is this different than the other one?
- =C-c RET= copies an old command to the prompt without running it
- Great idea
- Keep your session transcript pruned
- =ess-transcript-clean-region= removes non-commands from a transcript for you
- Previous command look-up can be done by completion via =comint-*-matching=.
- =M-p= and =M-n= seem to work just fine though.
- Previous command execution, by name, offset, or just the last one, are by =!=
- This feature is actually quite rich and a real regexen style system.
Always show eldoc for ℝ stuff, everywhere it may.
#+begin_src emacs-lisp
(setq ess-eldoc-show-on-symbol t)
#+end_src
Various session interaction stuff
- Show objects in the work-space: =C-c C-x=
- Search for what libraries are available to the work-space: =C-c C-s=
- Load file with source: =C-c C-l=
- Visit errors: =C-c '= and =C-x '=
- Show help on an object: =C-c C-v=
- Quit: =C-c C-q=
- Abort: =C-c C-c=
- Switch between the console and the most recent file buffer: =C-c C-z=
Sending code to the ESS process
- =ess-eval-region-or-line-and-step=: Eval the region, or the line, move to next
line
- =C-M-x=: Eval the current region, function, or paragraph
- =C-c C-c=: Do that and then go to the next line
- =C-c C-j=: Eval the current line
- =C-c M-j=: Eval line and jump to the console
- =C-c C-f=: Eval the currently selected function
- =C-c M-f=: Eval the currently selected function and jump to the console
- =C-c C-r=: Eval the region
- =C-c M-r=: Eval the region and jump to the console
- =C-c C-b=: Eval the buffer
- =C-c M-b=: Eval the buffer and jump to the console
- You can do all this stuff from transcript files, too.
- My thought is that I never, ever will and if I do need to, I'm looking up the
commands again as I don't want to make a habit of doing that kind of
thing (running old transcripts).
Editing objects and functions:
- =C-c C-e C-d=: Edit the current object
- =C-c C-l=: Load source file into the ESS process
- =TAB= Indents/re-formats or completes code.
- =M-;=: Correctly indents the current comment
Help mode inside of ESS:
- =C-c C-v=: =ess-display-help-on-object=: Get help on anything
- =?=: Show commands available in help mode
- =h=: Show help for a different object. Currently focused object defaults.
- =n= and =p=: Cycle through sections
- =l=: Eval the current line in the console; usually sample code.
- =r=: Eval current region, too
- =q=: Quit out of that buffer
- =k=: Kill that buffer
- =x=: Kill that buffer and return to ESS
- =i=: Get info on a package
- =v=: Show vignettes
- =w=: Show current help page in browser
Completion:
- =TAB=: Complete anything
- =M-?=: Show completions available
- =ess-resynch=: Refreshes the completion cache
*ess-tracebug* start
#+begin_src emacs-lisp
(setq ess-use-tracebug t)
#+end_src
For all =ess-tracebug= stuff, the map prefix is =C-c C-t=
<2014-11-11 Tue>
The documentation for =ess-tracebug-help= provides all of this documentation that
I copied from the website into here. Someday I should clean this up!
Breakpoints =ess-dev-map=:
- b =ess-bp-set= :: Set BP (repeat to cycle BP type)
- B =ess-bp-set-conditional= :: Set conditional BP
- k =ess-bp-kill= :: Kill BP
- K =ess-bp-kill-all= :: Kill all BPs
- o =ess-bp-toggle-state= :: Toggle BP state
- l =ess-bp-set-logger= :: Set logger BP
- n =ess-bp-next= :: Goto next BP
- p =ess-bp-previous= :: Goto previous BP
Note: =C-= prefixed equivalents are also defined
Debugging =ess-dev-map=:
- ` =ess-show-traceback= (also on C-c ) :: Show traceback
- ~ =ess-show-call-stack= (also on C-c ~) :: Show callstack
- e =ess-debug-toggle-error-action= :: Toggle error action (repeat to cycle)
- d =ess-debug-flag-for-debugging= :: Flag for debugging
- u =ess-debug-unflag-for-debugging= :: Unflag for debugging
- w =ess-watch= :: Watch window
Note: =C-= prefixed equivalents are also defined)
Interactive Debugging =ess-debug-minor-mode-map=:
- M-C =ess-debug-command-continue= :: Continue
- M-C-C =ess-debug-command-continue-multi= :: Continue multi
- M-N =ess-debug-command-next= :: Next step
- M-C-N =ess-debug-command-next-multi= :: Next step multi
- M-U =ess-debug-command-up= :: Up frame
- M-Q =ess-debug-command-quit= :: Quit debugging
Navigation to errors (general Emacs functionality):
- =C-x `=, =M-g n :: =next-error=
- =M-g p= :: =previous-error=
*ess-tracebug* stop
- Be sure to specify this per-project.
#+begin_src emacs-lisp
(setq ess-tracebug-search-path '())
#+end_src
- Make error navigation simpler
#+begin_src emacs-lisp
(define-key compilation-minor-mode-map [(?n)] 'next-error-no-select)
(define-key compilation-minor-mode-map [(?p)] 'previous-error-no-select)
#+end_src
- The font size for watched variables.
#+begin_src emacs-lisp
(setq ess-watch-scale-amount -1)
#+end_src
Data viewing:
- *Never* rely upon on the REPL for data viewing
- Will mix up exploratory code with data
- Can't easily distinguish between code and data
- Distracting you
- Breaking your flow
- Sometimes
- You end up somewhere
- And the =ess= buffer cursor is at the top!
- No problem, call =ess-switch-to-end-of-ESS=
- Make it easier to know what object values are.
- =ess-describe-object-at-point=
#+begin_src emacs-lisp
(setq ess-describe-at-point-method 'tooltip)
#+end_src
- Visualize just about anything.
- =ess-R-object-popup=
#+begin_src emacs-lisp
(require 'ess-R-object-popup)
#+end_src
- Rdired is another way to work with object
- =ess-rdired=
- View, delete, plot, and update buffer (ala /revert/) are single key commands
#+begin_src emacs-lisp
(autoload 'ess-rdired "ess-rdired")
#+end_src
- Visualize data frames better.
- =ess-R-dv-ctable=
- =ess-R-dv-pprint=
#+begin_src emacs-lisp
(require 'ess-R-data-view)
#+end_src
- inlineR
- /Not/ a competitor to =org-mode=
- Ultra lightweight LP, really
#+begin_src emacs-lisp
(require 'inlineR)
#+end_src
Documentation:
- Whole section on native documentation; I'll re-visit as needed.
- Roxygen, too.
=ess-developer= helps you to easily work within specific name-spaces.
Rutils: key-bindings to aid real usage
- =C-c C-. l=: List all packages in all available libraries.
- =C-c C-. r=: List available packages from repositories listed by =getOptions(‘‘repos’’)=
in the current R session.
- =C-c C-. u=: Update packages in a particular library lib and repository repos.
- =C-c C-. a=: Search for a string using apropos.
- =C-c C-. m=: Remove all R objects.
- =C-c C-. o=: Manipulate R objects; wrapper for =ess-rdired=.
- =C-c C-. w=: Load a workspace file into R.
- =C-c C-. s=: Save a work-space file.
- =C-c C-. d=: Change the working directory for the current R session.
- =C-c C-. H=: Use =browse-url= to navigate R HTML documentation.
=ess-mode-silently-save= is worth a million bucks; usually I have to hand code
this.
As of <2014-01-31 Fri>, you need to manually load ESS when you pull it from
MELPA [fn:8dece4ca: https://stat.ethz.ch/pipermail/ess-help/2014-January/009705.html]. That is totally fine with me, that is really the best way to load stuff.
Out of curiosity, I read more about it here [fn:c5cac42b: https://github.com/milkypostman/melpa/issues/6], but that occurred before
this previous post made by the maintainers. Even the source code in
=ess-autoloads.el= has a license from 2012, which is before the aforementioned
post. As such, this configuration step seems correct and necessary for now.
Additionally, this how the user manual expects a typical manual setup to be
configured.
Looked a tiny bit at how R hackers are formatting their code [fn:9039b33e: https://google-styleguide.googlecode.com/svn/trunk/Rguide.xml] [fn:da0df786: http://adv-r.had.co.nz/Style.html].
The simple (dumb) part of me suspects that C++ formatting is generally just fine [fn:5b466d0c: https://stackoverflow.com/questions/7502540/make-emacs-ess-follow-r-style-guide].
There is strangely nice discussion about where temp files may be stored;
specifically for cases where you edit identically-named objects and want to keep
them in the same directory but per-project. That is not the need now, and it is
nice to know that it is an option.
Store history files and dump files in a single known location. If that location
doesn't exist, then make it.
#+begin_src emacs-lisp
(setq gcr/r-dir "~/.R/")
(defun gcr/make-warn-R-dir ()
"Handle of R directory misconfiguration."
(interactive)
(unless (f-directory? gcr/r-dir)
(progn
(message "Couldn't find %S… creating it." gcr/r-dir)
(f-mkdir gcr/r-dir))))
(gcr/make-warn-R-dir)
(setq ess-history-directory gcr/r-dir)
(setq ess-source-directory gcr/r-dir)
#+end_src
Since I'm using ℝ for everything, configure /everything/ to be using ℝ.
#+begin_src emacs-lisp
(setq inferior-ess-program "R")
(setq inferior-R-program-name "R")
(setq ess-local-process-name "R")
#+end_src
Always start =ess= within the curent =emacs= frame, it doesn't need to be separate.
#+begin_src emacs-lisp
(setq inferior-ess-same-window nil)
(setq inferior-ess-own-frame nil)
#+end_src
Help buffers all belong in the same frame.
#+begin_src emacs-lisp
(setq ess-help-own-frame nil)
#+end_src
When =ess= starts, or when ℝ starts, it takes the current directory as its
working directory. This is totally fine; so don't ask what the working directory
should be.
#+begin_src emacs-lisp
(setq ess-ask-for-ess-directory nil)
#+end_src
My preference is for ESS to quit and not ask me whether or not I am sure. There
is an intentional line-break after the closing round bracket because that is the
approach of the original value here.
#+begin_src emacs-lisp
(setq inferior-ess-exit-command "q('no')
")
#+end_src
When commands are executed, display their output within the current buffer,
rather than to a new dedicated buffer for them.
#+begin_src emacs-lisp
(setq ess-execute-in-process-buffer +1)
#+end_src
When you cycle between a the ℝ buffer and the script, you get to the process
buffer, you will go to the end of the buffer. This setting is specifically to
handle a buffer that is scrolling when you want to see the last result and will
scroll back after the fact to see the history.
#+begin_src emacs-lisp
(setq ess-switch-to-end-of-proc-buffer t)
#+end_src
Use typical auto completion in buffers here, but don't do it when the
next char is a symbol or closed paren.
#+begin_src emacs-lisp
(setq ess-tab-complete-in-script +1)
(setq ess-first-tab-never-complete 'symbol-or-paren-or-punct)
#+end_src
Use =ido= completion whenever possible.
#+begin_src emacs-lisp
(setq ess-use-ido t)
#+end_src
Handle rdoc and rmd files, though I have never used them… yet.
#+begin_src emacs-lisp
(add-to-list 'auto-mode-alist '("\\.rd\\'" . Rd-mode))
(add-to-list 'auto-mode-alist '("\\.Rmd$" . r-mode))
#+end_src
Use =eldoc= for this mode. Always show it when the point is on a symbol.
Try to keep help strings at 10 chars or less.
#+begin_src emacs-lisp
(setq ess-use-eldoc t)
(setq ess-eldoc-show-on-symbol t)
(setq ess-eldoc-abbreviation-style 'normal)
#+end_src
Make it really easy to search the ℝ archives for anything.
#+begin_src emacs-lisp
(local-set-key (kbd "C-c C-. S") 'ess-rutils-rsitesearch)
#+end_src
Make it really easy to do common stuff for ℝ with good keybindings.
#+begin_src emacs-lisp
(require 'ess-rutils)
(setq ess-rutils-keys +1)
#+end_src
=r-autoyas= does argument completion. I had it working nice, and didn't use it for
a while, and now it doesn't work. This needs some TLC.
#+begin_src emacs-lisp
(require 'r-autoyas)
(setq r-autoyas-debug t)
(setq r-autoyas-expand-package-functions-only nil)
(setq r-autoyas-remove-explicit-assignments nil)
#+end_src
These functions are metioned, and I am not sure where or how to use them yet,
but Vitalie Spinu mentioned them as being useful:
- =comint-previous-matching-input-from-input=
- =comint-history-isearch-backward-regexp=
Personal customizations for this mode. For some currently unknown reason,
=smartparens= only runs when you call =smartparens-strict-mode= and not
=turn-on-smartparens-strict-mode= like it does everywhere else.
For a while I used =ess-eval-buffer-and-go=, but now I know that it is insanely
faster to use =ess-eval-buffer= instead. Previously I've read people saying that,
and it is true.
Save two spaces showing function information in the mini-buffer.
#+begin_src emacs-lisp
(setq ess-ac-R-argument-suffix "=")
#+end_src
When I started to standardize arrows across modes, I recalled the =ess=
documentation and was also reminded [fn:645cef99: http://www.r-bloggers.com/a-small-customization-of-ess/]
here how easy it is to customize it.
Not sure where I put the notes, but long ago I researched the ℝ coding
standards. [[http://stackoverflow.com/questions/7502540/make-emacs-ess-follow-r-style-guide][This post]] by Eddelbuettel led me to believe that the ℝ [[http://cran.r-project.org/doc/manuals/R-ints.html#R-coding-standards][standard]]
definition is the best. That made me think that =RRR= would be the best because
it has identical settings to the =C++= style at the time of the post. That makes
sense to me. I only want to change one thing to make Magrittr chains easier to
read. The stock =RRR= indenting makes expressions trail off to the right forever.
Here is how, make a copy of =RRR= and change one property.
#+begin_src emacs-lisp
(setq gcr/ess-style
(copy-alist
(assoc 'RRR ess-style-alist)))
(setf (nth 0 gcr/ess-style) 'GCR)
(setf (cdr
(assoc 'ess-continued-statement-offset
(cdr gcr/ess-style)))
0)
(add-to-list 'ess-style-alist gcr/ess-style)
(setq ess-default-style 'GCR)
#+end_src
#+begin_src emacs-lisp
(defun gcr/ess-mode-hook ()
(local-set-key (kbd "s-e") 'ess-switch-to-end-of-ESS)
(local-set-key (kbd "s-x") 'r-autoyas-expand)
(local-set-key (kbd "s-p") 'ess-R-object-popup)
(local-set-key (kbd "s-v o") 'ess-describe-object-at-point)
(local-set-key (kbd "s-v d") 'ess-rdired)
(local-set-key (kbd "s-v cc") 'ess-R-dv-ctable)
(local-set-key (kbd "s-v cp") 'ess-R-dv-pprint)
(setq ess-S-assign-key (kbd "C-,"))
(ess-toggle-S-assign-key t)
(ess-toggle-underscore nil)
(local-set-key (kbd "C-.") (lambda () (interactive) (insert " -> ")))
(local-set-key (kbd "C-M-,") (lambda () (interactive) (insert " <<- ")))
(local-set-key (kbd "C-M-.") (lambda () (interactive) (insert " ->> ")))
(key-chord-define-local (kbd ",.") (lambda () (interactive) (insert " %<>% ")))
(local-set-key (kbd "s-.") (lambda () (interactive) (insert " %>% ")))
(local-set-key (kbd "C-0") 'ess-eval-buffer)
(turn-on-pretty-mode)
(r-autoyas-ess-activate)
(visual-line-mode)
(smartparens-strict-mode t)
(gcr/untabify-buffer-hook)
(fci-mode)
(hs-minor-mode 1)
(linum-mode)
(gcr/turn-on-r-hide-show)
(aggressive-indent-mode)
(lambda () (add-hook 'ess-presend-filter-functions
(lambda ()
(warn
"ESS now supports a standard pre-send filter hook. Please update your configuration to use it instead of using advice.")))))
(add-hook 'ess-mode-hook 'gcr/ess-mode-hook)
(defun gcr/turn-on-r-hide-show ()
"Attribution: SRC https://github.com/mlf176f2/EmacsMate/blob/master/EmacsMate-ess.org"
(when (string= "S" ess-language)
(set (make-local-variable 'hs-special-modes-alist) '((ess-mode "{" "}" "#" nil nil)))
(hs-minor-mode 1)
(when (fboundp 'foldit-mode)
(foldit-mode 1))
(when (fboundp 'fold-dwim-org/minor-mode)
(fold-dwim-org/minor-mode))))
(defun gcr/Rd-mode-hook ()
(gcr/ess-mode-hook))
(add-hook 'Rd-mode-hook 'gcr/Rd-mode-hook)
(defun gcr/inferior-ess-mode-hook ()
(gcr/ess-mode-hook))
(add-hook 'inferior-ess-mode-hook 'gcr/inferior-ess-mode-hook)
(defun gcr/ess-rdired-mode-hook ()
"Personal customizations."
(interactive)
(turn-on-stripe-buffer-mode)
(stripe-listify-buffer))
(add-hook 'ess-rdired-mode-hook 'gcr/ess-rdired-mode-hook)
#+end_src
This [fn:1ffa40c2: http://www.r-bloggers.com/a-small-customization-of-ess/]
post shares a nice setup for the assignment key; primarily if
you use underscores in your variable names, which I do on occasions. After
coding like this for just 10 short minutes it drove me nuts and that is totally
counter intuitive to me; I never would have expected that having to type two
characters to do an assignment would give me nuts. Anyway, the default behavior
is just fine; hit underscore twice gives you an underscore, and one gives you an
assignment!
*Philosophy*
The current =ESS= maintainers philosophies about how to maintain an ℝ code-base
make sense to me and are virtually the same as my own. Quite simply, the rule is
that the code artifacts are the single source of system definition. Consequently,
the system should be configured in this manner:
We want to keep dump files after loading them; never delete them. The idea
is that if we use them, then they are a valid part of the system definition and
need to be kept.
#+begin_src emacs-lisp
(setq ess-keep-dump-files +1)
#+end_src
=ESS= allows us to quite easily modify live 𝕊 objects and functions. It provides
this functionality via =ess-dump-object-into-edit-buffer=. These changes are
considered to be experimental, and not part of the master record according to
our philosophy. As such, we don't care to know that these new versions ever
existed and their record will be forgotten from history. In other words, that
new, modified version of the object or function, is never saved to a file for
later reuse.
#+begin_src emacs-lisp
(setq ess-delete-dump-files nil)
#+end_src
Since our systems are entirely file-based, the entirety of the system most
likely lives in different files. Before loading any file for sourcing, save
any ESS source buffers. This approach is in addition to two other things:
(1) Emacs is auto-saving every file buffer quite frequently and (2) there is
advice before every manual =eval= call so that the buffers and their files stay
in sync. Yes, it is really that important.
#+begin_src emacs-lisp
(setq ess-mode-silently-save +1)
#+end_src
During the experimental mode of system development, you are likely to hack on
things using an ESS buffer associated with a file. Things can happen quite
unexpectedly, and it is easier to know that the code that you have =eval='d is
the value that is actually currently saved on-disk. You get it by now, that is
my personal preference. It is just a lot easier IMHO to know that your files are
persisted and my be stored in your VCS and that things "look are right".
#+begin_src emacs-lisp
(defadvice ess-eval-region-or-line-and-step (before before-ess-eval-region-or-line-and-step activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-region-or-function-or-paragraph (before before-ess-eval-region-or-function-or-paragraph activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-region-or-function-or-paragraph-and-step (before before-ess-eval-region-or-function-or-paragraph-and-step activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-line (before before-ess-eval-line activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-line-and-go (before before-ess-eval-line-and-go activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-function (before before-ess-eval-function activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-function-and-go (before before-ess-eval-function-and-go activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-region (before before-ess-eval-region activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-region-and-go (before before-ess-eval-region-and-go activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-buffer (before before-ess-eval-buffer activate)
(gcr/save-all-file-buffers))
(defadvice ess-eval-buffer-and-go (before before-ess-eval-buffer-and-go activate)
(gcr/save-all-file-buffers))
#+end_src
Don't save the workspace when you quit ℝ and don't restore *ANYTHING* when you
start it, either. This adheres to the philosopy that the system is file based.
Period.
#+begin_src emacs-lisp
(setq inferior-R-args "--no-save --no-restore")
#+end_src
Indent curly brackets correctly:
=smartparens= is serving me well. In this mode it is for curly, round, and square brackets. =ESS= handles indenting mostly right, too. One thing was unpleasant, though. When you define a new function, hitting return brings the curely bracket down to the newline but doesn't give it an empty line and indent the cursor one indentation over so that you may begin implementing the function. That is a big hassle; 4 unnecessary keystroke, it is really distracting and takes you out of the flow. It is such a little thing yet it is so powerfully distracting. It is like a mosquito in your tent! Searching for a solution revealed that I am not alone here.
This post [fn:32fe93bc: http://www.emacswiki.org/emacs/ESSAutoParens] handles brackets,
indentation quite well [fn:5f2adfb8: http://emacs.1067599.n5.nabble.com/indentation-not-working-if-parentheses-are-already-closed-td283806.html] but doesn't provide the behavior that I want.
This post [fn:47104806: https://stackoverflow.com/questions/18420933/enabling-mode-specific-paren-indentation-in-emacs-prelude] captured exactly what I was facing, yet didn't end with a
solution which was kind of shocking. Searching some more I ended up here [fn:cd67477f: https://github.com/Fuco1/smartparens/issues/80], and this seems like the
ideal solution by the author of smartparens himself. This is probably a common thing
as I found another post
with exactly my situation referencing that aforementioned solution, too [fn:2c7c401d: https://github.com/bbatsov/prelude/issues/374]. This is a nice generalizable
approach that should serve me well for just about everything in this solution-area. Here [fn:5a732a42:: https://github.com/rdallasgray/graphene/blob/master/graphene-smartparens-config.el] is a post
showing a more advanced usage that handles context which is nice to know is an option.
#+begin_src emacs-lisp
(sp-local-pair 'ess-mode "{" nil :post-handlers '((gcr/indent-curly-block "RET")))
#+end_src
=ESS= executes code in another process. That is no secret. When displaying output
from that code running in another process though, it can look like Emacs is
locking up. That is not the case [fn:2fbb65bd: https://stackoverflow.com/questions/2770523/how-can-i-background-the-r-process-in-ess-emacs].
What is happening that Emacs is waiting for the output. Configure this mode to
continue to accept user input, which is obviously critical, but don't wait for
the process to provide its output. Instead, all output is printed after the last
input lines. What we gain is perceived speed, and what we lose is the nice
sequential this/that/this/that we get from a typical REPL interaction. As I
write this, I'm not totally sure how this will work, but the documentation and
post are consistent and describe what I had wanted here so I will give it a try
and see how it goes.
#+begin_src emacs-lisp
(setq ess-eval-visibly 'nowait)
#+end_src
Michael explained how to use a richer =eval-expression=, and then showed how to
do the same thing in ℝ. This is the original post, and it will work once I am
on the next version of =emacs= that has the new advice library. Until then, I
won't include this.
#+begin_example
(advice-add
'debugger-record-expression :around
(lambda (f exp) (interactive
(list (read (my-read--expression "Record Eval: "))))
(funcall f exp))
'((name . use-my-read--expression)))
#+end_example
** Org
This section takes about 15 seconds to tangle.
*** Discussion
Late into the development process I ran into some export to HTML issues.
After tracking down the source, I learned that tracking down the source of the
issue in the source itself was out of scope for me. My solution was to break out
the org-mode configuration into its own block so that I could generate two
Emacs configuration files. Doing so with a different section was easier, so
that is how I did it.
Tangling can take more than a few minutes; so there is some advice to report on
it just to me understand what is happening and that it is working. Another way
to perform this monitoring would have been to use around advice. What I ran
into is that on HTML export around works fine, but on tangling it did not. This is
something that I chose not to investigate; instead I reverted the tangling
advice to two separate commands and that seems to work fine.
Org mode, like most of Emacs more powerful modes, slowly grows on you, in
pleasant and intuitive ways. Pretty soon, you fall in love with it. After
using it for 50+ hours or so you start wanting some easier way to navigate then
by typing in the commands over and over (doesn't matter how you re-run them).
Reading the miscellaneous section, I learned about speed keys [fn:40a1962e: http://orgmode.org/manual/Speed-keys.html#Speed-keys] [fn:d064d3d8: http://notesyoujustmightwanttosave.blogspot.com/2011/12/org-speed-keys.html].
Wonderful, just wonderful.
Visualizing hierarchical lists in a flat manner has been fine for me. Sometimes
though I wanted to depth-based view, but didn't think much more of it. Reading
abouto org-mode, I came upon =org-indent-mode= [fn:20c464a3: http://orgmode.org/manual/Clean-view.html#Clean-view], and decided to give
it a try for a while because it is kind of easier to read. Both modes are
nice, and thus far I'm switching back and force as I feel like it. Once I
opened my eyes and learned about =org-hide-leading-stars= though, I really
found happiness.
One topic relating to color themes is that of how code should look within
a source block in an org file. There was a thread asking about how to
make the block coloring "better". It was interesting because it revealed my
preference to myself namely that source blocks should be a muted Gray in
the document because it shouldn't draw much attention, but in the editor of
course you get the highlighting that you want. That is really my personal
preference, nonetheless, =org-src-fontify-natively= is still always an option.
Over the past six months I think, this approach has worked out well. Nonetheless
I got curious about how things /might/ be with coloring turned on. Generally, it
looks fine. Strangely though, even with the =solarized= these it is kind of
distracting. Beyond sharing that observation, I won't quantify it any more than
that. The biggest thing for me is that I only want to edit source blocks in
their "real" mode because:
- The real mode is present and as such
- All mode specific bindings are present
- Worth mentioning twice because if I don't have helpers on then I will not
match brackets manually!
- I've broken code so many times making "quick fixes" and breaking the bracket
matching it is exhausting
- Sending code to REPLs
- May not sound like much, but those three things are very, very huge in my
work-flow
The good news is that for doing code reviews and stuff, I can always turn on
that fontification.
On a somewhat similar thread, =(setq org-src-tab-acts-natively t)= would make it
easier to edit source blocks outside of the vehicle offered by =org-edit-src-code=.
Since my intent is never to edit blocks outside for their proper mode though, I
will not enable that.
This approach of mine, I think I touch upon it elsewhere… at some point I would
like to refactor this whole document.
This [fn:d58f4050: http://home.fnal.gov/~neilsen/notebook/orgExamples/org-examples.html] article is really fascinating in that crams a ton of information
into a tiny space. It also is kind of fun to read because it simultaneously
teaches you so many new things, yet at the same time re-teaches or re-educates
you about things that you already knew but didn't know that you could or should
be using in these additional manners.
The HTML export of org documents has an optional JavaScript supported display [fn:49c014be: http://orgmode.org/manual/JavaScript-support.html].
Not sure how I ended up on this, but it is actually a very nice option. The
info style view is nice once you read the directions. The folding interface
is also interesting; I tried out all 3 generation options but didn't find
anything that I specifically liked. Perhaps it is a familiarity or comfort
level with GNU styled docs or the key-bindings.
Don't use =org= for time-tracking, but if I ever do then [fn:0276223e: https://github.com/koddo/org-clock-statusbar-app]
this is nice to know of.
*** Configuration
For this feature to work, it must come /before/ any =org= load statements
#+begin_src emacs-lisp
(setq org-list-allow-alphabetical +1)
#+end_src
**** Org
=org= intelligently chose not to =autoload= everything. The most noticeable
things in the require statements for =org= are that:
- Only a few exporters come built in hence the need to require them
- =htmlize= is required for pretty HTML export of code
<2014-11-18 Tue>
There is a development occurring here, figuring out how to migrate off of Cask
for package management. Thus far, el-get seems to handle everything, but for
org. Because org is the only package that I will ever install via package, it
goes here for now. I didn't stick with that, and moved it to package 100% <2014-11-20 Thu>.
#+begin_src emacs-lisp
(require 'org)
(require 'ox-beamer)
(require 'ox-md)
(require 'htmlize)
#+end_src
Exports to Confluence are very very helpful.
#+begin_src emacs-lisp
(require 'ox-confluence)
#+end_src
=htmlize= should eventually be moved out of this =org= block into its own re-usab.e
section. It does need configuring both for =org= and also for general use. I like
to be able to copy-and-paste its generated HTML into other documents, and =css= is
the easiest way to achieve it. At some future date, it would be nice to developer
a proper style sheet to handle any situation. The problem is that right now I don't
have enough situations to based a design upon, just the desire to do so.
My preference for styling HTML documents has been the same as all printable documents:
black and white. When you do a =htmlize= export in batch-mode, there is no bufer
style information to be exported, so you get nice black-and-white code formatting. This
is an acceptable approach, but I am getting close to setting up a style to product just
what I want for HTML export. It is close enough to almost require investment to address
it.
#+begin_src emacs-lisp
(setq htmlize-output-type 'inline-css)
(setq org-html-htmlize-output-type htmlize-output-type)
#+end_src
=org-show= need special handling, see the install for details.
#+begin_src emacs-lisp
(let ((pkg 'org-show))
(gcr/on-gui
(if (not (el-get-package-is-installed pkg))
(warn "You wanted %S to be installed, but it isnt. Fix this." pkg)
(let ((fil (concat (el-get-package-directory pkg) "org-show.el")))
(if (not (f-exists? fil))
(warn "You wanted %S to exist, but it doesn't. Fix this." fil)
(load fil)))))
(gcr/not-on-gui (warn "You wanted %S to be loaded, but it won't be… it doesn't work without a GUI for some reason." pkg)))
#+end_src
Building =org= documents is intimately tied to:
- The =org= version
- The =init= version used to configure org
- Check the former
- Perhaps someday the latter should be checked?
#+begin_src emacs-lisp
(defconst gcr/org-version "8.2.10")
(defun gcr/warn-org-version ()
"Warn of org misconfiguration."
(interactive)
(when (not (version= (org-version) gcr/org-version))
(warn "Insufficient org-mode requirements. Expected %S. Found: %S " gcr/org-version (org-version))))
(gcr/warn-org-version)
#+end_src
Make sure that exported files are Unicode UFT-8.
#+begin_src emacs-lisp
(setq org-export-coding-system 'utf-8)
#+end_src
Do not preserve line-breaks when exporting instead let the destination
format handle it as it sees fit.
#+begin_src emacs-lisp
(setq org-export-preserve-breaks nil)
#+end_src
My personal TODO workflow is pretty tame, and it is defined below.
#+begin_src emacs-lisp
(setq org-todo-keywords
'((sequence "TODO" "IN-PROGRESS" "WAITING" "REVIEW" "DONE")))
#+end_src
When running in a GUI, I would like linked images to be displayed inside of
Emacs.
#+begin_src emacs-lisp
(setq org-startup-with-inline-images (display-graphic-p))
#+end_src
When exporting anything, do not insert the exported content intto the kill ring.
#+begin_src emacs-lisp
(setq org-export-copy-to-kill-ring nil)
#+end_src
Use =ido= completion in =org=.
#+begin_src emacs-lisp
(setq org-completion-use-ido +1)
#+end_src
=org= lets you use single letter commands to do stuff on headers. I like to use
=c= for cycling the header expansion.
#+begin_src emacs-lisp
(setq org-use-speed-commands +1)
#+end_src
Ask before execution of shell links. This may look inconsistent given that I allow
evaluation. It just looks inconsistent.
#+begin_src emacs-lisp
(setq org-confirm-shell-link-function 'y-or-n-p)
#+end_src
Ask before execution of emacs-lisp links. This may look inconsistent given that
I allow evaluation. It just looks inconsistent.
#+begin_src emacs-lisp
(setq org-confirm-elisp-link-function 'y-or-n-p)
#+end_src
Make sure that incomplete TODO entries prevent the enclosing parent from every
turning to DONE.
#+begin_src emacs-lisp
(setq org-enforce-todo-dependencies +1)
#+end_src
Allow the mouse to do =org= things like expand and collapse headings.
#+begin_src emacs-lisp
(gcr/on-gui
(require 'org-mouse))
#+end_src
Use unicode characters to visualize things like right arrow eg \rarr.
#+begin_src emacs-lisp
(setq org-pretty-entities +1)
#+end_src
Use a real ellipsis to render an ellipsis for =org= stuff like showing that a
header is collapsed.
#+begin_src emacs-lisp
(setq org-ellipsis "…")
#+end_src
It is easy to see indentation of headlines without having to count asertisks, so
don't show them, only show the significant and last one.
#+begin_src emacs-lisp
(setq org-hide-leading-stars +1)
#+end_src
Display emphasized text as you would in a WYSIWYG editor.
#+begin_src emacs-lisp
(setq org-fontify-emphasized-text +1)
#+end_src
Highlight LaTeX markup.
Normally, I don't do any syntax highlighting, as I believe that should be
delegated to source buffers, thinking that to do otherwise is distracting.
However, I already do configure subscripts and Greek letters to be displayed
with syntax highlighting, because I want to indicate to the human reader that
they are special, and specifically /not/-Unicode. Do the same thing for
#+begin_src emacs-lisp
(setq org-highlight-latex-and-related '(latex script entities))
#+end_src
There is an auto-complete provider for org-mode [fn:a94049d3: https://github.com/aki2o/org-ac]. Nice as I didn't even
think to check. Perhaps a check should go on the standard setup list. This seems
to work when you type out things like block definitions; and it won't apply
to EasyTemplate generated regions. =auto-complete= will still work on them,
though:
#+begin_src emacs-lisp
(require 'org-ac)
(org-ac/config-default)
#+end_src
Footnote management is an important topic. Thanks to Richard [fn:44cb98d6: https://lists.gnu.org/archive/html/emacs-orgmode/2014-04/msg00172.html], there
is a concise approach for this, which I've pasted here:
#+begin_example
I use the inline footnote syntax [fn:: ...] for just this reason. I
think easy migration of non-inline footnotes would be a nice feature to
add to Org, though doing it right would be non-trivial.
A strategy that another user once described to me for dealing with this
problem is the following:
1) Use a regexp search and replace to re-number the footnotes
in the region of the text you want to move, giving them high numbers
(e.g., prefixing each with "9999").
2) Use Org to re-sort the footnotes in the original file, so that the
newly-renumbered footnotes all appear at the end.
3) Move the text and the footnotes to the new file, which should now be
easy, since the footnotes are all grouped together.
4) In the new file, use Org to re-number the footnotes back to something
normal.
This sounded like a pretty good idea to me, though I haven't had a need
to try it myself.
Hope that helps!
Best,
Richard
#+end_example
#+begin_src emacs-lisp
(setq org-footnote-define-inline +1)
(setq org-footnote-auto-label 'random)
(setq org-footnote-auto-adjust nil)
(setq org-footnote-section nil)
#+end_src
This is an amazingly easy way to screw up your document. The more you edit
org docs, the more you realize how you must truly protect it:
#+begin_src emacs-lisp
(setq org-catch-invisible-edits 'error)
#+end_src
Though I am not deliving deep, it is hard not to want to customize some stuff
and perhaps this is the start:
#+begin_src emacs-lisp
(setq org-loop-over-headlines-in-active-region t)
#+end_src
By default I never want a table of contents generated. It is so easy to enable
it with a property, it will be fine to turn it off.
#+begin_src emacs-lisp
(setq org-export-with-toc nil)
#+end_src
It is /almost always/ faster to work with org documents when they are fully
expanded. Anyway, the structure cycling makes it really, really easy to get an
/outline view/ again.
#+begin_src emacs-lisp
(setq org-startup-folded "nofold")
#+end_src
When images are displayed in the buffer, display them in their actual size. My
goal is to use other tools to make the image compliant what I want rather than
have to mess and fiddle with image resizing in =org=.
#+begin_src emacs-lisp
(setq org-image-actual-width t)
#+end_src
Hide the delimeter for emphasized text. This may break table alignment.
#+begin_src emacs-lisp
(setq org-hide-emphasis-markers +1)
#+end_src
Realign tables automatically.
#+begin_src emacs-lisp
(setq org-startup-align-all-tables +1)
#+end_src
**** Babel
There is a hook for things to do after a source block has been executed. These
are my preferences for what should happen. This tip appeared in
this [fn:edec422c: https://lists.gnu.org/archive/html/emacs-orgmode/2014-07/msg00309.html]
discussion and Nick Dokos agreed here
that [fn:32dff2df: http://article.gmane.org/gmane.emacs.orgmode/88741]
that it is the ideal approach because it does /not/ interfere with export.
This thread [fn:5863d9db: https://lists.gnu.org/archive/html/emacs-orgmode/2015-01/msg00534.html] explained
the correct approach as of <2015-01-22 Thu>, which meant a simpler function call.
#+begin_src emacs-lisp
(defun gcr/org-babel-after-execute-hook ()
"Personal settings for the `org-babel-after-execute-hook'."
(interactive)
(org-redisplay-inline-images))
(add-hook 'org-babel-after-execute-hook 'gcr/org-babel-after-execute-hook)
#+end_src
Load the =ob-sml= package. Perhaps some day it will end up in the mainline.
#+begin_src emacs-lisp
(require 'ob-sml nil 'noerror)
#+end_src
Tell =org= that it may evaluate all of the listed languages.
#+begin_src emacs-lisp
(org-babel-do-load-languages
'org-babel-load-languages
'((calc . t)
(css . t)
(dot . t)
(ditaa . t)
(emacs-lisp . t)
(js . t)
(latex . t)
(lilypond . t)
(makefile . t)
(org . t)
(perl . t)
(python . t)
(plantuml . t)
(R . t)
(scheme . t)
(sh . t)
(sml . t)
(sql . t)))
#+end_src
There is a way to disable property inheritance that speeds up tangling a lot.
The problem is that you lose property inheritance which is unacceptable. Never,
never allow that.
#+begin_src emacs-lisp
(setq org-babel-use-quick-and-dirty-noweb-expansion nil)
#+end_src
You may display syntax highlighting for code in source blocks. I don't.
#+begin_src emacs-lisp
(setq org-src-fontify-natively nil)
#+end_src
On export, maintain the literal spacing as found in the source block. Obviously
this is important for makefiles. It is really important everywhere because
anything else would violate the law of least surprise.
#+begin_src emacs-lisp
(setq org-src-preserve-indentation +1)
#+end_src
When source blocks are exported, do not indent them arbitrarily. This does
nothing given that the previous setting is non-null; however I believe that I
set this for a reason that I may no longer recall.
#+begin_src emacs-lisp
(setq org-edit-src-content-indentation 0)
#+end_src
When edit mode is exited, the option exists to automatically remove empty
opening and closed lines for the source block. Never do this.
#+begin_src emacs-lisp
(setq org-src-strip-leading-and-trailing-blank-lines nil)
#+end_src
For code blocks that I use a *lot*, add templates for source blocks because my
current approach is to do a =\n?\n"))
#+end_src
OOTB the templates are all upper case. Case shouldn't matter inside of =org=,
but on my system it breaks =org=. This needs to be investigated, and until then
I will just downcase all of the templates.
#+begin_src emacs-lisp
(mapc (lambda (asc)
(let ((org-sce-dc (downcase (nth 1 asc))))
(setf (nth 1 asc) org-sce-dc)))
org-structure-template-alist)
#+end_src
It looks like ℝ is going to be another one, but don't process it to downcase it…
order matters here.
#+begin_src emacs-lisp
(add-to-list
'org-structure-template-alist
'("r" "#+begin_src R\n?\n#+end_src" ""))
(add-to-list
'org-structure-template-alist
'("p" "#+begin_src plantuml\n?\n#+end_src" ""))
(add-to-list
'org-structure-template-alist
'("sh" "#+begin_src sh\n?\n#+end_src" ""))
#+end_src
Sometimes tangling and exporting takes a long time and I would like to see some
status messages. Shell commands can report duration, too.
#+begin_src emacs-lisp
(defadvice org-babel-tangle (before org-babel-tangle-before activate)
(gcr/save-all-file-buffers)
(message (concat "org-babel-tangle BEFORE: <"
(format-time-string "%Y-%m-%dT%T%z")
">"))
(setq gcr/tmp (current-time)))
(defadvice org-babel-tangle (after org-babel-tangle-after activate)
(let* ((dur (float-time (time-since gcr/tmp)))
(msg (format "Tangling complete after: %.06f seconds" dur)))
(message (concat "org-babel-tangle AFTER: <"
(format-time-string "%Y-%m-%dT%T%z")
">"))
(message msg)
(gcr/on-gui (alert msg :title "org-mode"))))
(defadvice org-ascii-export-as-ascii (before org-ascii-export-as-ascii-before activate)
(gcr/save-all-file-buffers))
(defadvice org-html-export-to-html (before before-org-html-export-to-html activate)
(gcr/save-all-file-buffers)
(message (concat "org-html-export-to-html BEFORE: <"
(format-time-string "%Y-%m-%dT%T%z")
">")))
(defadvice org-html-export-to-html (after after-org-html-export-to-html activate)
(message (concat "org-html-export-to-html AFTER: <"
(format-time-string "%Y-%m-%dT%T%z")
">")))
#+end_src
Sacha implemented a nice feature to export Unicode checkboxes correctly from
=org=. That will get into the release. Use the workaround and warn when it is no
longer needed. Now it is in the release. Thanks Sacha and =org= team!
#+begin_src emacs-lisp
(setq org-html-checkbox-type 'unicode)
#+end_src
Before exporting to PDF, save all buffers to make sure that everything is a
known good state.
#+begin_src emacs-lisp
(defadvice org-latex-export-to-pdf (before org-latex-export-to-pdf-before activate)
(gcr/save-all-file-buffers))
#+end_src
There is a performance issue with tangling when header property inheritance is
enabled. Eric explained that [fn:419e4704: https://lists.gnu.org/archive/html/emacs-orgmode/2014-06/msg00719.html] there may be performance gains if some
of the header properties are not considered. The list below defines what will
be allowed, and everything else will be removed.:
#+begin_src emacs-lisp
(let* ((allowed '(exports
file
noweb
noweb-ref
session
tangle))
(new-ls
(--filter (member (car it) allowed)
org-babel-common-header-args-w-values)))
(setq org-babel-common-header-args-w-values new-ls))
#+end_src
When source blocks are evaluated, their results get stored in a result area,
typically for display. If the results are small, they are displayed with colons
instead of an =example= block. My preference is to *always* place them in an
example block.
#+begin_src emacs-lisp
(setq org-babel-min-lines-for-block-output 0)
#+end_src
I've got auto-save enabled for every buffer that has a file attached to it so I
rarely every think about saving a file. When you edit source code in =org-mode=
though and do it in a major-mode buffer for that code, =auto-complete= doesn't
apply because it isn't associated with a buffer. The following turns on auto-
save from this buffer back to the source =org= document. This value is
aggressively set to 1 because sometimes in haste you switch out of an =org= edit
buffer and then want to get back into it, and if you changes in it are not saved
they can be destroyed. You are asked if =Emacs= should, but it is not always
obvious why it shouldn't.
#+begin_src emacs-lisp
(setq org-edit-src-auto-save-idle-delay 1)
#+end_src
The source editing buffer may be configured to appear in a few different places.
For a while I really liked =reorganize-frame= because sometimes you want to be
able to see the code you are editing in edition to the rest of the document. At
least that is what I am telling myself. Once I learned you could changed it I
realized that 1 I should have asked if it could be changed and 2 I should have
changed it.
#+begin_src emacs-lisp
(setq org-src-window-setup 'current-window)
#+end_src
When you evaluate code its results are inserted into a =RESULTS= block by
default. The documentation indicates though that you may instead use a name
if the source block has a name, or a cache-id. In either case, both seem to be
better options for traceibility.
#+begin_src emacs-lisp
(setq org-babel-results-keyword "NAME")
#+end_src
=org= has a really nice feature that hitting =C-c C-c= will generally just do
the /right thing/. It is really nice. That feature extends to source blocks of
course. Ironically I had a typo here, typing /of curse/ instead of /of course/.
The thing is that you really, really need to develop a personal workflow, and
then configure the tool to enable it. The more I learn about =org=, the more
leery I am about making it really easy to evaluate code. I want it to be a
really, really specific and decided action to evaluate a code block, so don't
make it so easy as =C-c C-c=.
#+begin_src emacs-lisp
(setq org-babel-no-eval-on-ctrl-c-ctrl-c +1)
#+end_src
=org= already uses the guillemet [fn:086b7602: https://en.wikipedia.org/wiki/Guillemets]
for demarcating noweb references, but it does it using the work-around of just
using less-than and greather-than characters twice. That is fine. Because Emacs
supports Unicode just fine though, tell =org= to use the real symbol.
#+begin_src emacs-lisp
(setq org-babel-noweb-wrap-start "«")
(setq org-babel-noweb-wrap-end "»")
#+end_src
My preference is to rely upon heading property inheritance to define source block
names. That way, you can just do your work knowing "where" you are working and
keep it simple by not having to name everything. That was just fine until I
wrote a document where I needed to name each source block.
It gets easy to forget the source block’s name. Not the end of the world, but very nice to know.
#+begin_src emacs-lisp
(defun gcr/org-edit-src-code-plus-name ()
"Edit the well-described source code block.
Attribution: URL `https://lists.gnu.org/archive/html/emacs-orgmode/2014-09/msg00778.html'"
(interactive)
(let* ((eop (org-element-at-point))
(name (or (org-element-property :name (org-element-context eop))
"ॐ"))
(lang (org-element-property :language eop))
(buff-name (concat "*Org Src " name "[" lang "]*")))
(org-edit-src-code nil nil buff-name)))
#+end_src
It would be nice to be able to use =vc-next-action= when editing source blocks in
the source block edit buffer. Those buffers are new buffers that get the
contents of the source block copied into them, the mode gets loaded, and
additional hooks for this special org mode source editing are run. When editing
is complete, the contents of that buffer are copied back into the source block,
the original contents are removed, and the new ones are inserted. I wasn't sure
how to proceed with this and asked the list. Aaron Ecay explained how to simply
close the buffer first. That is a nice approach because everything will be as
close to normal operational procedures as possible. Jonathan Leech-Pepin showed
how to get a handle on the source buffer, and execute some code in the context
of /that/ buffer. In this case it would mean executing the commit action inside of
the backing buffer. Both are great options, and I am having trouble with both of
them. The former is great because it is exactly how you would do it now. The
latter is great because you would *not* be interrupted with the source block
buffer being closed. At this point, I've only got the former working so that is
where I will start.
#+begin_src emacs-lisp
(defadvice vc-next-action (before vc-next-action-in-org-src-block last activate)
"If in org source block, exit it."
(when (condition-case nil
(org-src-in-org-buffer)
(error nil))
(org-edit-src-exit)))
#+end_src
Not sure where to note this, but I do need to do it somewhere:
#+begin_quote
- babel, document my two modes of use as eval everything and store the results,
replacing them, which is good for documents that use that data, and then the
style I just did for homework which did ":results output silent" when the
intent was more very close to coding, and ultimately using the code to deliver
the consumable product
#+end_quote
Thank you Nicolas Goaziou [fn:486109d1: https://lists.gnu.org/archive/html/emacs-orgmode/2014-11/msg00776.html],
for the beginnings of an =org-lint=. The goal here was to:
1) Report an error if there is a source block without a language
specified
2) Report an error if there is a source block with a language specified
that is *not* present in `org-babel-load-languages'
And, it does.
#+begin_src emacs-lisp
(defun gcr/src-block-check ()
(interactive)
(org-element-map (org-element-parse-buffer 'element) 'src-block
(lambda (src-block)
(let ((language (org-element-property :language src-block)))
(cond ((null language)
(error "Missing language at position %d"
(org-element-property :post-affiliated src-block)))
((not (assoc-string language org-babel-load-languages))
(error "Unknown language at position %d"
(org-element-property :post-affiliated src-block)))))))
(message "Source blocks checked in %s." (buffer-name (buffer-base-buffer))))
#+end_src
In [[https://emacs.stackexchange.com/questions/7844/org-mode-have-flycheck-resolve-relative-config-while-editing-code-blocks][this]] post, the author explains how he would source block buffers to appear to
have a file name so that FlyCheck can do its thing correctly. It is really
simple. I have not thorougly tested it. I tested it once.
#+begin_src emacs-lisp
(defadvice gcr/org-edit-src-code-plus-name (around set-buffer-file-name activate compile)
(let ((file-name (buffer-file-name)))
ad-do-it
(setq buffer-file-name file-name)))
#+end_src
Why isn't this code documented? I replaced it with =gcr/org-edit-src-code-plus-name=.
#+begin_src emacs-lisp
(setq org-edit-src-code nil)
#+end_src
***** Core Babel Configuration
****** Comments [fn:1e1a7e1f: http://orgmode.org/manual/comments.html#comments]
There is always a question of how to instill traceability in your artifacts. org
provides =:comments= for that. Tangling with that value set to =link=,
for example, would add a prefix and postfix comment to the tangled file with the
name of the header from which the generated file was tangled. When I tangle the
.emacs.el, then it puts something like this for that:
#+begin_quote
~;; [[file:~/git/bitbucket-grettke/home/TC3F.org::*Fully%20Loaded%20System][Fully\ Loaded\ System:1]]~
file contents go here
;; Fully\ Loaded\ System:1 ends here
#+end_quote
When you follow the link, it will take you right back to the block that
specified the tangling of the document. That is a start, though not super for
tracking down details of where the code snippets really originated down to the
source blocks themselves.
Trying to understand the other settings, I found =both= to look like this:
#+begin_quote
;; Fully Loaded System
;; Convert decisions into a runnable system.
~;; [[file:~/git/bitbucket-grettke/home/TC3F.org::*Fully%20Loaded%20System][Fully\ Loaded\ System:1]]~
file contents go here
;; Fully\ Loaded\ System:1 ends here
#+end_quote
=noweb= looks like, well I'm going to put a couple examples, because this
is the best setting. This provides was 99% of org mode literate programmers
want which is traceability back from every tangled piece of code to the original
document.
#+begin_quote
;; [[file:~/git/bitbucket-grettke/home/TC3F.org::*Windows%20%5Bfn:38%5D][nil]]
;; [[file:~/git/bitbucket-grettke/home/TC3F.org::*Windows%20%5Bfn:38%5D][nil]]
;; [[file:~/git/bitbucket-grettke/home/TC3F.org::*Frames%20%5Bfn:46%5D][nil]]
#+end_quote
After all of this research, I found that doing noweb-ref tangling, the source
locations are not included, so it is no very useful to include comments, and
I removed them, at least for now. I am not sure how I want to use them right
now.
The type of information that you provide as meta-data is up to you and depends
upon your mental model for your org document. My mental model is mostly to use
headings as the logical area for addressing a particular /concern/ satisfied by
that portion of my Emacs configuration, so the tangling comments reflect that.
In other words, in this document at least, I rarely name source blocks because
the header name is the "true name", and closing the tangle comment with the
source block name is really confusing because it usually is =nil=. The org
links are fine, too, because they convey all of the necessary information
whether you are using org or not. It is more likely that most readers will not
use org links, so they come second.
As it happens, that didn't really work out as I had hoped. The =link= style
works, and =noweb= does not. Not sure why and not digging further, so sticking
with that. Also, I had customized the links, and did that incorrectly, so I
removed those, too. When Eric said that one part of it wasn't implemented, I
didn't to dig into what was working anymore than I had already because it has
already been many hours invested.
Now I've got weeks invested and I'm shocked to find that using links in the
tangled file is worse then useless, it is actually harmful. It just doesn't
help, atleast in the sytems that I am tangling. As such I am no longer using
it.
<2014-11-02 Sun>
Well, just read a post of another person using it (many months after I retired
it), and I think that I want to try keeping it around. My problem was probably
between my keyboard and chair so I will give it another go.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-header-args :comments "noweb")
#+end_src
****** Results [fn:1625d11f: http://orgmode.org/manual/results.html#results]
Always display results like you would seem them in a REPL.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-header-args :results "output replace")
#+end_src
****** Exports [fn:7dad95aa: http://orgmode.org/manual/exports.html#exports]
Export both code blocks and results in exports.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-header-args :exports "both")
#+end_src
****** Noweb [fn:3da67e2d: http://orgmode.org/manual/noweb.html#noweb]
Expand noweb references before the block is tangled or evaluated, but
exported. This embraces the notion that you are telling the right thing to the
computer and the right thing to the human. This is the only proper setting to
do so.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-header-args :noweb "no-export")
#+end_src
****** Padline [fn:508104fc: http://orgmode.org/manual/padline.html]
Deals with inserted code blocks and whether or not you havep padding around
them. For a while I liked that, to make it easier to see. Then I used comments
to make it clear, but I may or may not use them. Finally, I decided that not to
make it easier for that form of the code to read for humans, because that is
what the LP document is for.
<2014-11-02 Sun>
After doing that, which totally made sense, I decided to give tangle comments a
go again, and although we are still generating for a computer, it can be nice
when =de-tangling= to have some space.
<2015-03-29 Sun>
Reading the documentation, I see that this setting is required for
=org-babel-tangle-jump-to-org= to work.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-header-args :padline "yes")
#+end_src
****** Eval [fn:f6ab36a6: http://orgmode.org/manual/eval.html#eval]
This is probably the single most important configuration parameter for your
document's source blocks. Initially, that value is obscured by the need to
configure the rich variety of other options though, and this parameter is often
visited during the second eighty percent of your investment in =org-babel= when
you are "in the thick" of it.
Still trying to make sense of it all myself, I am adhering to a lightweight
user-story driven configuration of this feature, as I believe that it is the
only way that it will make sense to me. The key goal here for me is to:
- Define typical usage scenarios
- Identify key traits
- Realize those traits in my workflow
The current configuration is more like:
- Default allows for super fast code execution messages storing the results
- Any form of reproducibl research including for example a tiny, tiny bit of
code necessary to get a =knitr= like setup =:header-args: :results output silent=
******* Story A: Messages
20% of my time spent composing email or mailing list messages. Those messages
may be composed of plain text with some nice markup. They also might have
references and citations. The big value comes with superb code block definition
and execution facilities. Those messages are short-lived; they are never stored
in =git= and unlikely to even end up on the file-system.
My work-flow here is:
- Compose the =org= document
- Prepare necessary buffers for code evaluation, or not, intentionally
- Execute (weave) source blocks and store the results within the document
- Export to the destination format
******* Story B: Notes
40% of my time is spent taking notes. It is so delightful to do so here. A lot
of those notes are for programming languages so the workflow is nearly identical
to =A=. The actions for navigating among source blocks is used all
of the time to quickly navigate the document's source code, reflecting more
thoughtfulness while working with the document. There is more concern here,
because the document is stored in =git= and long-lived, it will be published
many times. An important approach here is that I like to make a clear and
concise distinction of the responsibilities of tangling and exporting because I
don't like surprises. I want to know how source blocks results were generated,
and when, as well as details about the export itself. This is a scope
restriction that opens up space to make better sense of the workflow of the
document itself. At its simplest, I just want to see a date-time showing when
the document was published for example.
My workflow here is:
- Compose the =org= document
- Prepare necessary buffers for code evaluation, or not, intentionally
- Execute (weave) source blocks and store the results within the document
- Export to the destination format
- Evaluate in-line source code relevant to that particular exportation
******* Story C: Documents
40% of my time is spent managing documents. In my case, it is this document.
There are others, but they are minute in comparison. This is the storehouse,
proving ground, and production deployment environment for every though, idea,
dream, and goal that I can come up with in regards to TC3F. It shares the same
traits as =A= and =B=, and adds many more.
The first addition is the utilization of =no-web= to tangle source code and also
tangle executable source code. The document evolution has relied heavily upon
this feature. It has allow amazing flexibility. It is so critical that it must
always be available.
The second addition is a different scope of concern. My desire to make the
tangling and exportation of this document is to have it more controlled. Unsure,
I waver between restricting evaluation of code blocks by default and enabling
over the entire document and simply allowing it globally. I don't like
accidentally evaluating source blocks and getting their results, but I suppose
that I may rely upon my commits to reveal my error. I suppose that my big
takeaway here is that I want it simple, and want to be able to lock things down
if necessary.
******* Study
Studying the scenarios, the desires seem clear. There is a combination of
agility and scope that ought to make productivity go up. The essence may be
better expressed in terms of responsibilities based upon my preferences
expressed above:
- A document is responsible for
- Defining source blocks
- Configuring their execution environments
- Displaying their results
- Execution of this document is responsible for
- Evaluating source blocks
- Collecting results of evaluation
- Tangling is responsible for combining source blocks
- In this file
- For output blocks
- For inclusion in source definitions used in function calls
- In a new file
- Exporting is responsible for
- Converting this document to a new presentation format
- Only in-line source blocks may be evaluated during exploration
- Be explicit about the difference eg
- Execution results as stored in the document
- Exportation results are stored in the export document
- Key difference for people to make sense of things
******* Preface to Tooling
The next task is to convert the studies desired into a configuration to realize
them. At first blush the configuration options will seem confusing. The best
approach is to "play" with the configurations to learn and finalize your
approach. That is how I ended up with this configuration. All of the
configuration it based upon that combination of need and desire and how the
system itself works. At best, it will only make sense in this context. Over
time, it will make more sense. That period of evolution and growth is reflected
in the =org= documentation itself for example when you read about =ditaa= in regards
to exporting [fn:14fb5203: http://orgmode.org/manual/Exporting-code-blocks.html].
The more familiar and comfortable with =org= one becomes, the more sense mentions
such as that make.
******* A More Concise Goal (Making Sense of Things)
This facilitate my personal model for =LP= with org for evaluation modes. There
are only two of them, =A= and =B=.
Mode =A= allow execution to occur where the results are likely to be captured
within the document. The single responsibility of that mode is to perform and
capture the entirety of the computation. That really sums it up. All computation
is done here because it is time and context sensitive. The document in that form
will serve as a snapshot in time. If you run ℝ code then capture the results and
plots and also the version of itself and the packages used. If you have
versioned links for your data set, then report it here. Think of future users
of your research as archeologists trying to piece together what you did; you
should make their job really easy. This is a self contained computational unit,
and its results, too. Include everything that matters for your computation.
Consider Vagrant [fn:28698f18: http://www.vagrantup.com/] regardless of how much
slower it may run on a virtual. How you defined this document and computed it
and captured the results are all *one* thing that needs to both be considered and
captured in its entirety.
Mode =B= is a little simpler. All of the hard work has been done. Everything just
mentioned has been done. This is purely responsible for publishing. Perhaps you
want to submit it to a journal, that is publishing. Perhaps you want to post it
on a blog, that is publishing. Publishing has different concerns. You want to
know about the environment used to perform the publishing, like the tools and
the time. Perhaps you want to more about the computer is was published on. All
of those aspects unique to that even of publishing should be included during
export. The operator really needs to get on-board with the idea of computational
artifacts vs reporting artifacts. For example if you execute mode =A= then you
need to store all of its generated artifacts. That includes data, but also
graphics that you reference in the document itself. Hopefully you are
questioning my claim here. You should! You area asking "Why should I when if I
can reproduce the results?!". Great question. The answer only makes sense
according to the philosophy I am embracing. Mode =A= defines both the computational
unit and its constituent output. That is a single /thing/, a single /thing document/.
Now that I am writing this, I am having questions about my claim here, and I will
explore them as my understanding is bettered. For now, I am sticking with this
because for example I know that I can use PNG anywhere. Well, questions arise
because I am unsure how I would publishing to the web without re-generating SVG
output vs PNG for web vs PS for LaTeX. Definitely something I will need to
explore and for now I am sticking with the plan. Just had lunch and reflected
upon the fact that there is clearly distinction between the results of your
computation and how you wish to present them, and when. My feeling is that my
approach is acceptable in that the computation and generation of summary
results is definitely a separate goal from providing it in a particular
publishing format and surely more experience needs to be accumulated here.
Perhaps the simplest thing to do for greater flexibility is to:
- In =A=
- Perform the computation
- Capture the results of the computation
- Produces images and so forth
- In =B=
- Convert to a new format
- Perhaps utilize the results of computation to present differently
The key questions are:
- May you?
- Yes you may
- Should you?
- Perhaps
- It seems easier to separate concerns into computation and presentation
That is why evaluation is available on export, to capture aspects unique of
export itself, and *not* of the computation. To realize this, the operator must be
very thoughtful and aware of the execution model of the document. As it stands,
you may separate the time of execution of code blocks and also their results.
This is a subtle yet hugely important idea. You may utilize this feature and
idea anyway you please, but I will use it a certain way. All computational
evaluation and results storage will occur for source blocks in =A=. That is the
goal. However, we do not want that to occur for in-line source blocks in mode =A=.
That is possible and doable. This will make it easy for the operator of the d
document to *see* the difference between code is for =A= versus =B= because the latter
will never have its results stored within the source document.
A strict separation between the =A= and =B=, roughly computation and export, must be maintained. It is the only way to make sense of how to use =org= as a tool here.
One mode is responsible for computation, and the other is responsible for
reporting. All of the following configuration is performed in order to realize
this goal of A:computation vs B:publishing (exporting).
******* Putting the Pieces Together
Make it crystal clear that if the operator wants to evaluate source blocks then
she may do so. It is a fundamental right of every =org= mode user and the default
configuration shall allow it. If she wants restrictions, then they may easily be
added to the document itself.
#+begin_src emacs-lisp
(setq org-confirm-babel-evaluate nil)
(gcr/set-org-babel-default-header-args :eval "always")
#+end_src
Separate evaluation into two distinct phases or modes that of =A= for computation
and =B= for presentation/publishing/exportation (still unsure of the best name
given the existing terms both inside and outside of =org=).
During exportation, only evaluate inline source blocks.
#+begin_src emacs-lisp
(setq org-export-babel-evaluate 'inline-only)
#+end_src
During exportation, evaluate the blocks and replace the source blocks with the
resulting value. This gives you exactly what you would expect; the documents
look like plain old documents because they are exactly that.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-inline-header-args :eval "always")
(gcr/set-org-babel-default-inline-header-args :results "value replace")
#+end_src
****** ℝ Specific
Always use the current ℝ session for evaluation.
#+begin_src emacs-lisp
(gcr/set-org-babel-default-header-args:R :session "*R*")
#+end_src
Then I read this [fn:16e26884: http://comments.gmane.org/gmane.emacs.orgmode/32814].
*WOW*. That is worth another millions bucks for Eric's prolific contribution to
humanity with org-babel.
**** KOMA-Script
I enjoy writing letters. I enjoy reading letters. LaTeX produces letters that
are easy to print and read. Org provides a [[http://orgmode.org/worg/exporters/koma-letter-export.html][KOMA Script exporter]] for [[https://www.ctan.org/pkg/koma-script?lang%3Den][koma-script]].
The Org documentation mentions that the user should read the [[http://orgmode.org/cgit.cgi/org-mode.git/plain/contrib/lisp/ox-koma-letter.el][ox-koma-letter.el]]
header documentation.
The [[https://www.ctan.org/pkg/babel?lang%3Den][babel]] packages is mentioned in the Org documentation. The package
documentation explains that it should be used with LaTeX, but not XeTeX. Some
time ago I decided to stick with LaTeX.
Load the KOMA exporter.
#+begin_src emacs-lisp
(eval-after-load 'ox '(require 'ox-koma-letter))
#+end_src
- Understanding KOMA and how to use it
- There are 4 ways to set letter metadata, listed "from the most specific to
the most general" (not sure exactly what this statement means, and the conclusion of my notes tries to make sense of what is really going on here and what is the best way to do things)
- Org option lines (ORG)
- Separate Org latex classes (LTX)
- Emacs Lisp variables (LISP)
- Letter Class Option files (LCO)
- Notes and thoughts on the ways to use it
- LTX
- By following the setup directions, you do this, creating "my-letter" class
- Familiar and easy if you already know LaTeX
- At some point in your workflow, you *must* define a class to use, anyway
- Very easy to do, just define the class template and set =org-koma-letter-default-class=
- ORG
- Simple way that makes it very easy to just focus on the document content
- This metadata takes highest priority in the workflow
- So you should set your typical defaults in LISP or LCO and customize it
here. This is exactly what I wanted to know.
- This lets you do your tweaking in each unique file while relying on the
most common defaults defined elsewhere
- LISP
- Very familiar style of configuring things
- LCO
- LCO == Letter Class Option filess
- LCO files are TeX
- They are included in the generated TeX source code from the letter
- Gives *full* access to KOMA-Script
- Big deal, because not everything is exposed through ORG or LISP
- Also gives full access to any and all TeX and LaTeX code
- LCO files are a KOMA-Script thing, so they are a LaTeX thing
-
#+begin_quote
Letter metadata set in LCO files overwrites letter metadata set in Emacs
variables but not letter metadata set in the Org file.
#+end_quote
- When you include multiple LCO files, they are evaluted LIFO. Properties
are set as they first appear, and are not set again. Say you include
"MyGeneralStuffForAnyLetter.lco" and then include
"MyStuffSpecificToThisLetter.lco". The specific stuff will get set first.
Then general stuff will get set last.
- Surely there is a better way to phrase this. I will work on that.
- Recommendations
- What is the easiest way to starat using KOMA-Script based on what you know
today?
- If you don't know any of the approaches
- Then choose between learning LaTeX and Org
- If you only know LaTeX
- Then you will use the LTX/LCO metadata approach
- If you only know ORG
- Then you will use the ORG metadata approach
- If you only know ORG and LISP
- Then you will use the LISP approach for general metadata and the ORG
approach specific metadata
- If you know LTX/LCO, ORG, and LISP
- Then you have total flexibility
- The fact is that
- ORG settings always trump LTX/LCO and LISP
- LISP settings are a subset of all of the settings available in
KOMA-Script, so you will always have to fall back to LTX/LCO if you want
to use unexposed features
- LCO files are just plain old LaTeX, which you already know
- So the best thing to do
- Is to use ORG for letter-specific settings
- And LTX for general settings
- Everything is a lot simpler this way because
- One less metadata approach to keep track of
- All KOMA-Script features are present
- Need to learn details of KOMA-Script package anyway
Configure the default class.
[[https://tex.stackexchange.com/questions/102922/how-can-i-get-us-letter-output-from-koma-scripts-scrlttr2-class][This]] post explains how to default the US letter size. That is the likely default
for my printed correspondence.
#+begin_src emacs-lisp
(eval-after-load 'ox-koma-letter
'(progn
(add-to-list 'org-latex-classes
'("my-letter"
"\\documentclass[paper=letter, pagesize, fontsize=10pt, parskip]{scrlttr2}
\\usepackage[english]{babel}
\\usepackage[osf]{mathpazo}"))
(setq org-koma-letter-default-class "my-letter")))
#+end_src
There are two formats for the letters: [[http://orgmode.org/w/?p%3Dworg.git%3Ba%3Dblob%3Bf%3Dexporters/koma-letter-new-example.org%3Bh%3D180a9a0e10dd8f7483a67946daf36732c316f821%3Bhb%3D180a9a0e10dd8f7483a67946daf36732c316f821][heading-based]] and [[http://orgmode.org/w/?p%3Dworg.git%3Ba%3Dblob%3Bf%3Dexporters/koma-letter-example.org%3Bh%3De21b8b00c3e895be9dd573d02ea84b08796296a3%3Bhb%3De21b8b00c3e895be9dd573d02ea84b08796296a3][property-based]].
Set up my default LCO files.
#+begin_src emacs-lisp
(setq org-koma-letter-class-option-file "UScommercial9 KomaDefault")
#+end_src
**** ispell
Doing literate programming a *lot*… it is a hassle to spell-check source blocks,
so don't. Actually, there are lots of things that I probably don't want to check
and this list is growing. All of the entries are explained here.
Never ispell org source blocks:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("^#\\+begin_src ". "#\\+end_src$"))
#+end_src
Never ispell org source blocks defined in upper case:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("^#\\+BEGIN_SRC ". "#\\+END_SRC$"))
#+end_src
Never ispell org example blocks:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("^#\\+begin_example ". "#\\+end_example$"))
(add-to-list 'ispell-skip-region-alist '("^#\\+BEGIN_EXAMPLE ". "#\\+END_EXAMPLE$"))
#+end_src
Properties block in org do not need to be ispelled
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("\:PROPERTIES\:$" . "\:END\:$"))
#+end_src
Footnotes in org should not be ispelled:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("\\[fn:.+:" . "\\]"))
#+end_src
Footnoes in org that have http links that are line breaked should not be
ispelled:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("^http" . "\\]"))
#+end_src
Verbatim regions in org mode should not be ispelled:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("=.*" . ".*="))
#+end_src
In org I often use bold text in lists, and they should never be ispelled because
they are usually abbreviations or other non-words:
#+begin_src emacs-lisp
(add-to-list 'ispell-skip-region-alist '("- \\*.+" . ".*\\*: "))
#+end_src
Most of the default org export properties should be ignored because they are not
words and I may ispell them manually when desired:
#+begin_src emacs-lisp
(let (void)
(--each
'("ATTR_LATEX"
"AUTHOR"
"CREATOR"
"DATE"
"DESCRIPTION"
"EMAIL"
"EXCLUDE_TAGS"
"HTML_CONTAINER"
"HTML_DOCTYPE"
"HTML_HEAD"
"HTML_HEAD_EXTRA"
"HTML_LINK_HOME"
"HTML_LINK_UP"
"HTML_MATHJAX"
"INFOJS_OPT"
"KEYWORDS"
"LANGUAGE"
"LATEX_CLASS"
"LATEX_CLASS_OPTIONS"
"LATEX_HEADER"
"LATEX_HEADER_EXTRA"
"OPTIONS"
"SELECT_TAGS"
"STARTUP"
"TITLE")
(gcr/ispell-a2isra (gcr/ispell-org-header-lines-regexp it))))
#+end_src
**** Hooks
Configure =org= mode hooks to make it easy to do the most commonly performed
operations.
Bit of a mystery that I couldn't =local-set-key= with one particular binding.
Found a way that /does/ work with the help of Jorge and Peak. I'm OK with it
remaining a mystery for now.
#+begin_src emacs-lisp
(define-key org-mode-map (kbd "C-,") (lambda () (interactive) (insert " \\larr ")))
#+end_src
#+begin_src emacs-lisp
(defun gcr/org-mode-hook ()
(local-set-key (kbd "C-1") 'org-narrow-to-subtree)
(local-set-key (kbd "M-1") 'widen)
(local-set-key (kbd "C-2") 'gcr/org-edit-src-code-plus-name)
(local-set-key (kbd "C-3") 'org-table-edit-field)
(local-set-key (kbd "s-h") 'org-babel-check-src-block)
(local-set-key (kbd "s-i i") 'org-babel-insert-header-arg)
(local-set-key (kbd "s-j") 'org-babel-previous-src-block)
(local-set-key (kbd "s-k") 'org-babel-next-src-block)
(local-set-key (kbd "s-l") 'org-babel-demarcate-block)
(local-set-key (kbd "s-;") 'org-babel-view-src-block-info)
(local-set-key (kbd "s-b x") 'org-babel-expand-src-block)
(local-set-key (kbd "s-b s") 'org-babel-switch-to-session)
(local-set-key (kbd "s-b c") 'org-babel-switch-to-session-with-code)
(local-set-key (kbd "s-o") 'org-babel-execute-maybe)
(local-set-key (kbd "s-t") 'org-babel-tangle)
(local-set-key (kbd "s-x") 'org-babel-do-key-sequence-in-edit-buffer)
(local-set-key (kbd "s-w w") 'org-export-dispatch)
(local-set-key (kbd "s-") 'org-babel-execute-buffer)
(local-set-key (kbd "s-i d") 'org-display-inline-images)
(local-set-key (kbd "s-i r") 'org-remove-inline-images)
(local-set-key (kbd "C-.") (lambda () (interactive) (insert " \\rarr ")))
(local-set-key (kbd "$") 'yf/org-electric-dollar)
(when (and (fboundp 'guide-key-mode) guide-key-mode)
(guide-key/add-local-guide-key-sequence "C-c")
(guide-key/add-local-guide-key-sequence "C-c C-x")
(guide-key/add-local-highlight-command-regexp "org-"))
(fci-mode)
(gcr/untabify-buffer-hook)
(turn-on-stripe-table-mode)
(linum-mode)
(wrap-region-mode t))
(add-hook 'org-mode-hook 'gcr/org-mode-hook)
#+end_src
Configure the =org= =babel= source code editing buffer with a key to make it
easy to exit. This is consistent with the approach of "same to exit as enter".
#+begin_src emacs-lisp
(defun gcr/org-src-mode-hook ()
(local-set-key (kbd "C-2") 'org-edit-src-exit)
(visual-line-mode))
(add-hook 'org-src-mode-hook 'gcr/org-src-mode-hook)
#+end_src
** Keyboard
Echo keystrokes immediately:
#+begin_src emacs-lisp
(setq echo-keystrokes 0.02)
#+end_src
* Keybindings
:PROPERTIES:
:noweb-ref: Keybindings
:END:
Key-Chord [fn:93a799cf: http://melpa.org/#/key-chord] everything. It's
documentation gives /the/ tip: keep chords limited to two fingers on the same hand
if you can. I'll expand on this to use two hands, intionally, to specify the
urgency of the operation about to be performed. The package /just works/ exactly
as you would expect, and it is delightful. It is really fast, too. I tried out
Key-Combo [fn:6f1e75f8: https://github.com/uk-ar/key-combo] and it seems really
great. I just couldn't get it working quickly though, so I didn't try migrating
beyond the hour or two that I invested.
Think of Key-Chord as letting you add modifier keys *anywhere* and *anyhow* you want
(be open minded here). Be pretty careful in chord specification though. My rough
approach is:
- *CLOSE* (continuity keys)
- Use alphanumeric/symbol key-chords when
- The combination is obvious… like ".." \rarr "…"
- There is *no* chance that it could inadvertently be pressed; recalling that
/both/ directions must be considered
- Excluding alphanumeric leaves; =` - = [ ] \ ; ' , . /=
- Likely offenders: =- = ; ' , .=
- Leaving: =` [ ] \ /=
- Left hand: 12x5
- Right hand only: 7x5
- 95 possible if this is right
- Preferences: [, ], \…
- Likelihood of usage? low
- Choosing a global mapping that works in all modes will involve a lot of
work
- Tough to choose these when =META= keys are easily within reach instead
- *NEAR*
- Goal is to minimize finger travel
- Keys used most frequently
- In order of preference:
- C-#keys :: 10
- C-F keys :: 6 (3 easily in reach on one hand)
- *FAR* (discontinuity keys)
- Super:any-one :: (12+10+11+26)=59
- *FURTHER*
- Use =[S|C|M|S]F:5+= keys :: 8x4=32 bindings
#+begin_src emacs-lisp
(require 'key-chord)
(key-chord-mode 1)
(setq key-chord-two-keys-delay 0.1)
#+end_src
=M-x= truly is the Emacs command line [fn:d0a5f045: https://aaronhawley.livejournal.com/28413.html].
Sometimes you want to temporarily bind keys. Haven't much of a need yet myself,
but when the time comes, this [fn:685d5985: https://github.com/abo-abo/centimacro]
looks like a great option to have.
Generally disallow stomping of global key-mappings unless it makes sense to me
(thank you Stefan Monnier for pointing out that referencing the map variable
is all it takes):
#+begin_src emacs-lisp
(defadvice global-set-key (before check-keymapping activate)
(let* ((key (ad-get-arg 0))
(new-command (ad-get-arg 1))
(old-command (lookup-key global-map key)))
(when
(and
old-command
(not (equal old-command new-command))
(not (equal old-command 'digit-argument))
(not (equal old-command 'negative-argument))
(not (equal old-command 'ns-print-buffer))
(not (equal old-command 'move-beginning-of-line))
(not (equal old-command 'execute-extended-command))
(not (equal new-command 'execute-extended-command))
(not (equal old-command 'ns-prev-frame))
(not (equal old-command 'ns-next-frame))
(not (equal old-command 'mwheel-scroll))
(not (equal new-command 'diff-hl-mode))
(not (equal new-command 'my-eval-expression))
(not (equal old-command 'list-buffers))
(not (equal new-command 'gcr/vc-map))
(not (equal new-command 'projectile-find-file))
)
(warn "Just stomped the global-map binding for %S, replaced %S with %S"
key old-command new-command))))
#+end_src
These key-bindings are custom for me and I've been using them for so long, and
that makes it rig+1ht. There are always opportunities for improvement, though.
Recently it dawned on me that it is poor-form to waste 3 function keys on
the same task, so I rebound =F1= to different modifiers that I hope are
consistent, and free up space, too. My preference is to leave =F5=, =F6, and
=F7= generally unbound and available for similar operations that are performed
in most programming modes. For example, =F5= will execute code in any Lisp-like
environment.
Guide:
- NON-DISRUPTIVE :: hands on home, no finger strain, C-[(2|3)|(9|0)]
- SLIGHTLY-DISRUPTIVE :: hands on home, slight finger strain, C-[1|-]
- DISRUPTIVE :: hands on keyboard, not home, palms are home
- VERY-DISRUPTIVE :: hands on keyboard, not home, palms are moved from home
** NON-DISRUPTIVE
Easily select regions:
#+begin_src emacs-lisp
(global-set-key (kbd "C-'") 'er/expand-region)
#+end_src
ace-jumping is frequent, too, and this one is perfect all home keys same,
dominant strong hand:
#+begin_src emacs-lisp
(key-chord-define-global "jk" 'ace-jump-mode)
#+end_src
Using =ace-jump= will introduce a new idea to you of easily jumping around
within a buffer. From you, from wherever you jump /to/, you need jump /back/.
Make it really really easy to do so.
#+begin_src emacs-lisp
(key-chord-define-global "m," 'ace-jump-mode-pop-mark)
#+end_src
multiple cursor mode… I kept these together because until I make an image, it
would be too confusing to keep them in the non and slightly disruptive sections,
as they are clearly that:
#+begin_src emacs-lisp
(global-set-key (kbd "M-9") 'mc/edit-lines)
(global-set-key (kbd "M-0") 'mc/mark-next-like-this)
(global-set-key (kbd "M--") 'mc/mark-all-like-this)
(global-set-key (kbd "M-8") 'mc/mark-previous-like-this)
#+end_src
ace-window is frequent, is beginning to adhere to a pattern of dual approaches:
#+begin_src emacs-lisp
(key-chord-define-global "nm" 'ace-window)
#+end_src
Save 3 bytes:
#+begin_src emacs-lisp
(key-chord-define-global "3." 'gcr/insert-ellipsis)
#+end_src
Indent with spaces for the likely scenario:
#+begin_src emacs-lisp
(key-chord-define-global "4 " (lambda () (interactive) (insert " ")))
#+end_src
German umlauts for a, o, and u:
#+begin_src emacs-lisp
(key-chord-define-global (concat "A" "{") (lambda () (interactive) (insert "ä")))
(key-chord-define-global (concat "A" "}") (lambda () (interactive) (insert "Ä")))
(key-chord-define-global (concat "O" "{") (lambda () (interactive) (insert "ö")))
(key-chord-define-global (concat "O" "}") (lambda () (interactive) (insert "Ö")))
(key-chord-define-global (concat "U" "{") (lambda () (interactive) (insert "ü")))
(key-chord-define-global (concat "U" "}") (lambda () (interactive) (insert "Ü")))
#+end_src
Arrows, so many:
#+begin_src emacs-lisp
(global-set-key (kbd "C-,") (lambda () (interactive) (insert "←")))
(global-set-key (kbd "C-.") (lambda () (interactive) (insert "→")))
#+end_src
Nice for UML, and French?
#+begin_src emacs-lisp
(key-chord-define-global "<<" (lambda () (interactive) (insert "«")))
(key-chord-define-global ">>" (lambda () (interactive) (insert "»")))
#+end_src
It is great to =ace-jump= to things. How about making deletions of contiguous text
as easy and fast?! This library will makes deletes blazingly fast!y
#+begin_src emacs-lisp
(key-chord-define-global "jl" 'ace-jump-zap-up-to-char)
(key-chord-define-global "j;" 'ace-jump-zap-to-char)
#+end_src
Jumping to lines actually happens a lot. When you look at this layout, remember,
or rather consider, that what you jump to, or navigate to, is layered in the
sense that the granularity of your actions changes and all actions provided here
are helpful for those different situations. This used to be =kc-df= but I typed
=df= for data.frame so I had to change it, as well as the following which used to
be =cv=. That wasn't good either because it is a painful reach. I need to document
the lessons learned above. df-jk make so much more sense, though, and I came
back to this to recall why I made this choice. This is an exploration question
again because the simplicity and symmettry of df-jk is simpler. I am going to
try using shift as a modifier key in the key-chord space. I'll use capital
letters. Upon typing that I realized that I don't like this idea, it takes this
binding from a non-disruptive to slightly-disruptive. I'll leave this alone
again.
#+begin_src emacs-lisp
(key-chord-define-global "fg" 'goto-line)
#+end_src
In the same spirit of poppping the mark with =ace-jump=, follow a similar appraoch
for =goto-line=.
#+begin_src emacs-lisp
(key-chord-define-global "vb" 'pop-to-mark-command)
#+end_src
Do nearly a =IKJL= style up/down/left/right arrow key, using using chords, saves a
trip.
You might wonder why I would use this when ace-jump-window is available? Good
question. Sometimes you know exactly what buffer you want, so jump to it, and
sometimes you just don't, and that is when you do it this way:
#+begin_src emacs-lisp
(key-chord-define-global "JK" (lambda () (interactive) (other-window 1)))
(key-chord-define-global "KL" (lambda () (interactive) (next-buffer)))
(key-chord-define-global "L:" (lambda () (interactive) (previous-buffer)))
#+end_src
Web-searches occur quite frequently once you've a nice work-flow established.
The keys in that mode are:
- w :: word
- s :: symbol
- l :: line
- r :: region
#+begin_src emacs-lisp
(key-chord-define-global "gt" 'google-this-mode-submap)
#+end_src
These actions appear in order of importance, and thus frequency of use
Do the /right thing/ for getting to the start of the line!
#+begin_src emacs-lisp
(global-set-key (kbd "C-a") 'beginning-of-line-dwim)
#+end_src
I use VC quite frequently. This is easy to reach, and does what must be done:
#+begin_src emacs-lisp
(global-set-key (kbd "C-;") 'vc-next-action)
#+end_src
Check =git= status:
#+begin_src emacs-lisp
(global-set-key (kbd "C-M-;") 'magit-status)
#+end_src
You don't moves lines or regions a ton, but when you do, you usually can't use
the arrow keys per mode, so use chords instead.
#+begin_src emacs-lisp
(key-chord-define-global "yu" 'move-text-up)
(key-chord-define-global "hj" 'move-text-down)
#+end_src
Now that =ispell= is configured nicely, I use it /all/ the time. Make that easy.
First tried "is" for "ispell". Loved it. Then remembered that it is a common
key combination. Forehead smack!
#+begin_src emacs-lisp
(key-chord-define-global "qp" 'ispell)
(key-chord-define-global "qo" 'ispell-word)
#+end_src
W for Writegood.
#+begin_src emacs-lisp
(key-chord-define-global "wm" 'writegood-mode)
(key-chord-define-global "wl" 'writegood-grade-level)
(key-chord-define-global "wz" 'writegood-reading-ease)
#+end_src
Use the default Langtool bindings.
#+begin_src emacs-lisp
(define-prefix-command 'gcr/langtool-map)
(key-chord-define-global "qk" 'gcr/langtool-map)
(define-key gcr/langtool-map "c" 'langtool-check-buffer)
(define-key gcr/langtool-map "C" 'langtool-correct-buffer)
(define-key gcr/langtool-map "j" 'langtool-goto-previous-error)
(define-key gcr/langtool-map "k" 'langtool-show-message-at-point)
(define-key gcr/langtool-map "l" 'langtool-goto-next-error)
(define-key gcr/langtool-map "q" 'langtool-check-done)
#+end_src
Easily browse URLs. Surely there is a more refind way. This is the first step.
#+begin_src emacs-lisp
(key-chord-define-global "wm" 'writegood-mode)
#+end_src
Occur has 3 cases. I like to use it to explore the unknown.
#+begin_src emacs-lisp
(global-set-key (kbd "M-s p") 'gcr/occur-dwim)
#+end_src
Comment and uncomment anything:
#+begin_src emacs-lisp
(key-chord-define-global "qi" 'gcr/comment-or-uncomment)
#+end_src
** SLIGHTLY-DISRUPTIVE
Anything having to do with version control differences:
#+begin_src emacs-lisp
(define-prefix-command 'gcr/vc-map)
(global-set-key (kbd "s-d") 'gcr/vc-map)
(define-key gcr/vc-map "h" 'diff-hl-mode)
(define-key gcr/vc-map "e" 'vc-ediff)
(define-key gcr/vc-map "d" 'vc-diff)
(define-key gcr/vc-map "u" 'vc-revert)
#+end_src
smex integration points:
#+begin_src emacs-lisp
(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)
#+end_src
Try to open a file just in this project:
#+begin_src emacs-lisp
(global-set-key (kbd "C-x C-p") 'projectile-find-file)
#+end_src
auto-completeness
#+begin_src emacs-lisp
(global-set-key (kbd "C-4") 'auto-complete)
#+end_src
Switching buffers occurs so frequently that this needs to be here, and perhaps
I will know I need a better binding later.
#+begin_src emacs-lisp
(key-chord-define-global "sb" 'ido-switch-buffer)
#+end_src
ace-window navigation:
#+begin_src emacs-lisp
(global-set-key (kbd "C--") 'ace-window)
#+end_src
Make it easy to enter Unicode stuff.
Total hack warning, may use the =2= key somewhere else, but, until that happens,
this is the perfect place to put it. So, it isn't a hack!
#+begin_src emacs-lisp
(define-prefix-command 'gcr/two-key-map)
(global-set-key (kbd "s-2") 'gcr/two-key-map)
#+end_src
#+begin_src emacs-lisp
(define-prefix-command 'gcr/double-struck-map)
(define-key gcr/two-key-map "s" 'gcr/double-struck-map)
(define-key gcr/double-struck-map "A" (lambda () (interactive) (insert "𝔸")))
(define-key gcr/double-struck-map "B" (lambda () (interactive) (insert "𝔹")))
(define-key gcr/double-struck-map "C" (lambda () (interactive) (insert "ℂ")))
(define-key gcr/double-struck-map "D" (lambda () (interactive) (insert "𝔻")))
(define-key gcr/double-struck-map "E" (lambda () (interactive) (insert "𝔼")))
(define-key gcr/double-struck-map "F" (lambda () (interactive) (insert "𝔽")))
(define-key gcr/double-struck-map "G" (lambda () (interactive) (insert "𝔾")))
(define-key gcr/double-struck-map "H" (lambda () (interactive) (insert "ℍ")))
(define-key gcr/double-struck-map "I" (lambda () (interactive) (insert "𝕀")))
(define-key gcr/double-struck-map "J" (lambda () (interactive) (insert "𝕁")))
(define-key gcr/double-struck-map "K" (lambda () (interactive) (insert "𝕂")))
(define-key gcr/double-struck-map "L" (lambda () (interactive) (insert "𝕃")))
(define-key gcr/double-struck-map "M" (lambda () (interactive) (insert "𝕄")))
(define-key gcr/double-struck-map "N" (lambda () (interactive) (insert "ℕ")))
(define-key gcr/double-struck-map "O" (lambda () (interactive) (insert "𝕆")))
(define-key gcr/double-struck-map "P" (lambda () (interactive) (insert "ℙ")))
(define-key gcr/double-struck-map "Q" (lambda () (interactive) (insert "ℚ")))
(define-key gcr/double-struck-map "R" (lambda () (interactive) (insert "ℝ")))
(define-key gcr/double-struck-map "S" (lambda () (interactive) (insert "𝕊")))
(define-key gcr/double-struck-map "T" (lambda () (interactive) (insert "𝕋")))
(define-key gcr/double-struck-map "U" (lambda () (interactive) (insert "𝕌")))
(define-key gcr/double-struck-map "V" (lambda () (interactive) (insert "𝕍")))
(define-key gcr/double-struck-map "W" (lambda () (interactive) (insert "𝕎")))
(define-key gcr/double-struck-map "X" (lambda () (interactive) (insert "𝕏")))
(define-key gcr/double-struck-map "Y" (lambda () (interactive) (insert "𝕐")))
(define-key gcr/double-struck-map "Z" (lambda () (interactive) (insert "ℤ")))
(define-key gcr/double-struck-map "a" (lambda () (interactive) (insert "𝕒")))
(define-key gcr/double-struck-map "b" (lambda () (interactive) (insert "𝕓")))
(define-key gcr/double-struck-map "c" (lambda () (interactive) (insert "𝕔")))
(define-key gcr/double-struck-map "d" (lambda () (interactive) (insert "𝕕")))
(define-key gcr/double-struck-map "e" (lambda () (interactive) (insert "𝕖")))
(define-key gcr/double-struck-map "f" (lambda () (interactive) (insert "𝕗")))
(define-key gcr/double-struck-map "g" (lambda () (interactive) (insert "𝕘")))
(define-key gcr/double-struck-map "h" (lambda () (interactive) (insert "𝕙")))
(define-key gcr/double-struck-map "i" (lambda () (interactive) (insert "𝕚")))
(define-key gcr/double-struck-map "j" (lambda () (interactive) (insert "𝕛")))
(define-key gcr/double-struck-map "k" (lambda () (interactive) (insert "𝕜")))
(define-key gcr/double-struck-map "l" (lambda () (interactive) (insert "𝕝")))
(define-key gcr/double-struck-map "m" (lambda () (interactive) (insert "𝕞")))
(define-key gcr/double-struck-map "n" (lambda () (interactive) (insert "𝕟")))
(define-key gcr/double-struck-map "o" (lambda () (interactive) (insert "𝕠")))
(define-key gcr/double-struck-map "p" (lambda () (interactive) (insert "𝕡")))
(define-key gcr/double-struck-map "q" (lambda () (interactive) (insert "𝕢")))
(define-key gcr/double-struck-map "r" (lambda () (interactive) (insert "𝕣")))
(define-key gcr/double-struck-map "s" (lambda () (interactive) (insert "𝕤")))
(define-key gcr/double-struck-map "t" (lambda () (interactive) (insert "𝕥")))
(define-key gcr/double-struck-map "u" (lambda () (interactive) (insert "𝕦")))
(define-key gcr/double-struck-map "v" (lambda () (interactive) (insert "𝕧")))
(define-key gcr/double-struck-map "w" (lambda () (interactive) (insert "𝕨")))
(define-key gcr/double-struck-map "x" (lambda () (interactive) (insert "𝕩")))
(define-key gcr/double-struck-map "y" (lambda () (interactive) (insert "𝕪")))
(define-key gcr/double-struck-map "z" (lambda () (interactive) (insert "𝕫")))
(define-key gcr/double-struck-map "0" (lambda () (interactive) (insert "𝟘")))
(define-key gcr/double-struck-map "1" (lambda () (interactive) (insert "𝟙")))
(define-key gcr/double-struck-map "2" (lambda () (interactive) (insert "𝟚")))
(define-key gcr/double-struck-map "3" (lambda () (interactive) (insert "𝟛")))
(define-key gcr/double-struck-map "4" (lambda () (interactive) (insert "𝟜")))
(define-key gcr/double-struck-map "5" (lambda () (interactive) (insert "𝟝")))
(define-key gcr/double-struck-map "6" (lambda () (interactive) (insert "𝟞")))
(define-key gcr/double-struck-map "7" (lambda () (interactive) (insert "𝟟")))
(define-key gcr/double-struck-map "8" (lambda () (interactive) (insert "𝟠")))
(define-key gcr/double-struck-map "9" (lambda () (interactive) (insert "𝟡")))
#+end_src
Pop up help:
#+begin_src emacs-lisp
(global-set-key (kbd "s-p") 'gcr/describe-thing-in-popup)
#+end_src
Code-folding:
#+begin_src emacs-lisp
(global-set-key (kbd "M-3") 'hs-toggle-hiding)
#+end_src
Do smart new line inside, indenting given the mode:
#+begin_src emacs-lisp
(global-set-key (kbd "s-") 'gcr/smart-open-line)
#+end_src
A lot of times you have the need to just go to the next line, and indent it, and
start typing. For years I just went to the end of the current like, hit return,
and well there you are. Mentally I should have profiled it by now that it should
be a simple action, so now it is.
#+begin_src emacs-lisp
(global-set-key (kbd "M-") 'gcr/lazy-new-open-line)
#+end_src
Use a nicer =eval-expression= approach.
#+begin_src emacs-lisp
(global-set-key (kbd "M-:") 'my-eval-expression)
#+end_src
List buffers in a more rich way.
#+begin_src emacs-lisp
(global-set-key (kbd "C-x C-b") 'ibuffer)
#+end_src
Toggle utility buffers
#+begin_src emacs-lisp
(key-chord-define-global "f9" 'gcr/util-cycle)
#+end_src
** VERY DISRUPTIVE
F10 should be left alone.
Start NeoTree:
#+begin_src emacs-lisp
(global-set-key (kbd "") 'neotree-toggle)
#+end_src
These do get used a lot believe it or not:
#+begin_src emacs-lisp
(global-set-key (kbd "M-7") 'gcr/insert-timestamp)
(global-set-key (kbd "s-7") 'gcr/insert-timestamp*)
(global-set-key (kbd "C-7") 'gcr/insert-datestamp)
#+end_src
I used to use =F5= to run code. Probably because of various editors that I had
used before. I do want that familiarity, because I use those functions a lot
for a certain style of developing. I will use =C-F5=.
Manage every font size:
#+begin_src emacs-lisp
(gcr/on-gui
(global-set-key (kbd "s-") 'gcr/text-scale-increase)
(global-set-key (kbd "M-") 'gcr/text-scale-decrease))
#+end_src
Thank [[http://oremacs.com/2015/03/15/search-with-apropos/][Oleh]] getting us up to speed on all of the =apropos= areas.
Thank you [[https://disqus.com/by/disqus_COwPSAc69c/][Phil]] for the map.
Thank you [[http://irreal.org/blog/?p%3D3792][Jon]] for reminding us.
I have only ever used =apropos=. It was not very often. Great to know of the
available granularity.
#+begin_src emacs-lisp
(global-set-key (kbd "M-") 'apropos-map)
(define-prefix-command 'apropos-map nil "Apropos (a(propos),d(documentation),c(ommand),i(nfo),l(ibrary),v(ariable))")
(define-key apropos-map (kbd "a") 'apropos)
(define-key apropos-map (kbd "d") 'apropos-documentation)
(define-key apropos-map (kbd "c") 'apropos-command)
(define-key apropos-map (kbd "i") 'info-apropos)
(define-key apropos-map (kbd "l") 'apropos-library)
(define-key apropos-map (kbd "v") 'apropos-variable)
#+end_src
Helper stuff:
#+begin_src emacs-lisp
(global-set-key (kbd "C-") 'emacs-index-search)
(global-set-key (kbd "S-") 'elisp-index-search)
(global-set-key (kbd "C-") 'imenu-anywhere)
#+end_src
Re-size the current windows [fn:7293bf39: http://www.emacswiki.org/emacs/WindowResize]:
#+begin_src emacs-lisp
(global-set-key (kbd "s-") 'shrink-window)
(global-set-key (kbd "s-") 'enlarge-window)
(global-set-key (kbd "s-") 'enlarge-window-horizontally)
(global-set-key (kbd "s-") 'shrink-window-horizontally)
#+end_src
*Always* leave =F5= open. It is discussed above.
Update the world clocks:
#+begin_src emacs-lisp
(global-set-key (kbd "") 'list-world-time)
#+end_src
Always leave =F11= open.
* Modes
:PROPERTIES:
:noweb-ref: Modes
:END:
v1:
The stuff that I commonly use may
-eventually want to end up in =prog-mode=, but I'm still not sure what really
-uses that and how I may being re-factoring.
v2:
The programming modes have some redundancy. Sometimes I feel like it ought to be
refactored. Other times I feel like it is not worth the effort because the flavor
you want for seemingly similar mode configurations may be very different once
you think about it for a little while.
** C Language Integrated Production System (CLIPS) [fn:d383cc00: http://clipsrules.sourceforge.net/]
CLIPS is a very special thing. OSS, expertly developed and used. Truly a hidden
gem among the muck. =clips-mode= [fn:36f704bf: https://github.com/grettke/clips-mode]
has had a long life behind it, and only some time ago the folks at MELPA helped
me to get it in there as the original maintainers were not to be found nor did
the folks at that university reply to emails about licensing and lineage.
#+begin_src emacs-lisp
(require 'clips-mode)
#+end_src
** Comint
=comint-mode= is only maybe the second most important thing for making Emacs
really, really special.
#+begin_src emacs-lisp
(setq comint-scroll-to-bottom-on-input 'this)
(setq comint-scroll-to-bottom-on-output 'others)
(setq comint-move-point-for-output 'others)
(setq comint-show-maximum-output t)
(setq comint-scroll-show-maximum-output t)
(setq comint-move-point-for-output t)
#+end_src
This configuration had been working fine for a long time. The intent was for it
to be crystal clear that the prompt line in comint buffers would be read only.
This turned out to be a mistake; though I am not sure why, when, or how it
became a mistake. Nonetheless, this should be left alone. The way the issue here
manifested was that all ℝ buffers opened by =ess= were 100% read only which
obviously is a *big issue* if you actually want to use! ROFL
#+begin_src emacs-lisp
(setq comint-prompt-read-only nil)
#+end_src
** CSS
#+begin_src emacs-lisp
(defun gcr/css-modehook ()
(fci-mode)
(visual-line-mode)
(gcr/untabify-buffer-hook)
(local-set-key (kbd "RET") 'newline-and-indent))
(add-hook 'css-mode-hook 'gcr/css-modehook)
#+end_src
** Emacs Lisp
Make it obvious whether or not it is lexically scoped [fn:c4baca78: http://marmalade-repo.org/packages/lexbind-mode] or not and don't
show that message whenever you enter a scratch buffer [fn:dfc44625: https://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html].
You may read more about Lisp Doc here [fn:d9e2a4de: https://www.gnu.org/software/emacs/manual/html_node/emacs/Lisp-Doc.html].
You may read more about default console messages here [fn:e67fd3ff: https://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html].
=eval-expression= gets really, really handy once you get into the Emacs
lifecycle. My goal was to enable =smartparens= in the minibuffer, and it didn't
work. I posted a question on it, and Drew Adams drew.adams@oracle.com explained
how =icicle= provides a better version of =eval-expression=, and how in lieu of
that, =pp-eval-expression= is even better. Michael Heerdegen shared his solution [fn:321475a6: https://lists.gnu.org/archive/html/help-gnu-emacs/2014-07/msg00135.html] for a rich modeline evaluator.
#+begin_src emacs-lisp
(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 "s-l eb") 'gcr/elisp-eval-buffer)
(local-set-key (kbd "s-l ep") 'eval-print-last-sexp)
(local-set-key (kbd "s-l td") 'toggle-debug-on-error)
(local-set-key (kbd "s-l mef") 'macroexpand)
(local-set-key (kbd "s-l mea") 'macroexpand-all)
(local-set-key (kbd "s-p") 'gcr/describe-thing-in-popup)
(local-set-key (kbd "M-:") 'my-eval-expression)
(local-set-key (kbd "#") 'endless/sharp))
(require 'lexbind-mode)
(defun gcr/emacs-lisp-mode-hook ()
(gcr/elisp-mode-local-bindings)
(lexbind-mode)
(turn-on-eldoc-mode)
(gcr/diminish 'eldoc-mode)
(aggressive-indent-mode))
(add-hook 'emacs-lisp-mode-hook 'gcr/emacs-lisp-mode-hook)
(setq initial-scratch-message nil)
#+end_src
** Eshell [fn:063471c9: https://www.gnu.org/software/emacs/manual/html_mono/eshell.html] [fn:46b52b8f: http://www.masteringemacs.org/articles/2010/12/13/complete-guide-mastering-eshell/] [fn:ed7a113f: http://www.khngai.com/emacs/eshell.php]
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 seamlessly 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
separate 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=.
#+begin_src emacs-lisp
(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 "Protovision… I have you now.")
(setq pcomplete-cycle-completions nil)))
(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\\)\\'"))))
#+end_src
The =eshell= configuration is a version controlled directory
#+begin_src emacs-lisp
(defconst gcr/eshell-dir "~/.emacs.d/eshell")
(defun gcr/warn-eshell-dir ()
"Warn of eshell misconfiguration."
(interactive)
(unless (and (f-symlink? gcr/eshell-dir)
(f-directory? gcr/eshell-dir))
(warn
"Could not find the eshell directory at: %S. Eshell will continue to function albeit without your customizations."
gcr/eshell-dir)))
(gcr/warn-eshell-dir)
#+end_src
#+begin_src emacs-lisp
(setq eshell-prompt-regexp "^.+@.+:.+> ")
(setq eshell-prompt-function
(lambda ()
(concat
(user-login-name)
"@"
(system-name)
":"
(eshell/pwd)
"> ")))
#+end_src
** Files
Try to visit a non-existence file and get prompted to create its parent
directories.
#+begin_src emacs-lisp
(add-to-list 'find-file-not-found-functions #'gcr/create-non-existent-directory)
#+end_src
** Graphviz [fn:d05878c1: http://www.graphviz.org/] [fn:4c7193c2: http://marmalade-repo.org/packages/graphviz-dot-mode] [fn:04ffff20: http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-dot.html]
#+begin_src emacs-lisp
(defun gcr/graphviz-dot-mode-hook ()
"Personal mode bindings for Graphviz mode."
(fci-mode)
(visual-line-mode))
(add-hook 'graphviz-dot-mode-hook 'gcr/graphviz-dot-mode-hook)
#+end_src
An example:
#+begin_src dot :file ./images/graphviz.png :noweb-ref no-tangle
digraph graphviz {
rankdir=LR;
label="On Action.";
begin [label="Identify the topic.", shape=doublecircle];
dailyuse [label="Act upon it.", shape=doublecircle; style=filled];
begin -> dailyuse [label="Consideration"];
}
#+end_src
#+NAME:
[[file:./images/graphviz.png]]
** Grammar
Never though that S&W [fn:be320540: http://www.amazon.com/gp/product/0205632645?ie=UTF8&tag=ucmbread-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0205632645]
would find a home here. It shall because of Matt Might [fn:d7db4b2f: http://matt.might.net/articles/shell-scripts-for-passive-voice-weasel-words-duplicates/],
thank you very much, and Writegood-Mode [fn:0afa6fb0: http://bnbeckwith.com/code/writegood-mode.html]. The [[https://github.com/bnbeckwith/writegood-mode][GitHub]] page has more
useful notes. Sacha added to it [fn:9dd85741: https://github.com/sachac/artbollocks-mode].
#+begin_src emacs-lisp
(require 'writegood-mode)
#+end_src
LanguageTool [fn:94814ced: https://www.languagetool.org/] and
Langtool [fn:e27e3c52: https://github.com/mhayashi1120/Emacs-langtool] work well
togethern.
#+begin_src emacs-lisp
(require 'langtool)
(setq langtool-language-tool-jar (concat (getenv "EELIB") "/LanguageTool-2.8/languagetool-commandline.jar"))
(setq langtool-mother-tongue "en")
(setq langtool-java-bin (concat (getenv "JAVA_HOME") "/bin/java"))
#+end_src
** Help
My usage pattern for help is to display it, learn what I wish, and move on by
closing the buffer. Make this work-flow easier [fn:2c2d78bc: https://emacs.stackexchange.com/questions/7471/change-focus-to-help-buffer-after-running-describe-mode].
#+begin_src emacs-lisp
(setq help-window-select t)
#+end_src
** ibuffer
#+begin_src emacs-lisp
(defun gcr/ibuffer-hook ()
"Personal customizations"
(interactive)
(ibuffer-vc-set-filter-groups-by-vc-root)
(unless (eq ibuffer-sorting-mode 'alphabetic)
(ibuffer-do-sort-by-alphabetic)))
(add-hook 'ibuffer-hook 'gcr/ibuffer-hook)
(setq ibuffer-formats
'((mark modified read-only vc-status-mini " "
(name 18 18 :left :elide)
" "
(size 9 -1 :right)
" "
(mode 16 16 :left :elide)
" "
(vc-status 16 16 :left)
" "
filename-and-process)))
#+end_src
** IELM [fn:2ef924b6: https://www.gnu.org/software/emacs/manual/html_node/emacs/Lisp-Interaction.html] [fn:8a08ea9e: http://www.emacswiki.org/emacs/InferiorEmacsLispMode] [fn:5c199b8d: http://emacs-fu.blogspot.com/2011/03/ielm-repl-for-emacs.html]
=my-eval-expression= makes that task pretty pleasant. The =*scratch*= buffer is
also really nice, too. =eval-last-sexp= obviously is a great option, too.
Sometimes, though, you want a REPL. Typically it is because you want to play
with stuff or have a record of the results that doesn't involve using
=eval-print-last-sexp=. Because I have the utility buffer set up in here, it
makes it quite unobtrusive and pleasant to use =ielm=.
My setup here tries to re-use as much as possible for the standard =lispy= mode
setup. That means I use my return handler, so when you want to evalute code in
here use =ielm-send-input= instead.
This [fn:aee1d8fd: http://www.masteringemacs.org/articles/2010/11/29/evaluating-elisp-emacs/]
is a *must-read* article.
Joseph G. Gay explained that what makes IELM so powerful is that you may execute
commands /within/ the scope of a different buffer. Using =ielm-change-working-buffer=
changes the current working buffer to something else.
That character is "MATHEMATICAL DOUBLE-STRUCK CAPITAL E".
#+begin_src emacs-lisp
(defun gcr/ielm-mode-hook ()
"Personal customizations."
(interactive)
(gcr/ielm-auto-complete))
(setq ielm-noisy nil)
(setq ielm-prompt "𝔼LISP> ")
(add-hook 'ielm-mode-hook 'gcr/ielm-mode-hook)
#+end_src
** Imenu [fn:58de53db: https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html] [fn:6024eee8: http://www.emacswiki.org/emacs/ImenuMode]
For a while I didn't use the menu bar. Then I started using Imenu via IDO.
Make it real easy to utilize the things that imenu provides, but make it keyboard
driven and available anywhere [fn:dff17af6: http://melpa.milkbox.net/#/imenu-anywhere].
This is a little bit different than =idomenu= [fn:78d70829: http://melpa.milkbox.net/#/idomenu] which is also very nice. The difference
between them is that the latter collects tags across all open buffers of the
type as the current buffer which is very nice.
#+begin_src emacs-lisp
(require 'imenu-anywhere)
#+end_src
That was really nice. It got me curious again about how it might fit since I am
using the menu bar again and it seems like a nice thing when working with other
people.
Configure Imenu to my preference:
#+begin_src emacs-lisp
(setq imenu-sort-function 'imenu--sort-by-name)
#+end_src
It was pretty clear even before trying it out that =imenu+= was a good idea [fn:b6404e93: http://www.emacswiki.org/emacs/imenu%2b.el].
#+begin_src emacs-lisp
(require 'imenu+)
#+end_src
I had originally set up Imenu my making request to add its menu in every mode
hook so I had it appearing in a bunch of places. That worked fine until the
first time I tried tangling a file… which didn't work. The error message was
kind of revealing =The mode `' does not support Imenu= which was interesting
because I had recently added =imenu= before which tangling worked fine.
Testing it out with my simple org init file by removing the Imenu calls revealed
the problem. What cause the problem, I'm still not sure, but the solution is
only to use Imenu to modes that support it via =font-lock-mode=.
#+begin_src emacs-lisp
(defun gcr/try-to-add-imenu ()
"Add Imenu to modes that have `font-lock-mode' activated.
Attribution: SRC http://www.emacswiki.org/emacs/ImenuMode"
(condition-case nil (imenu-add-to-menubar "Imenu") (error nil)))
(add-hook 'font-lock-mode-hook 'gcr/try-to-add-imenu)
#+end_src
** Info [fn:c9bf4a1e: http://www.emacswiki.org/emacs/InfoMode]
Once you accept Emacs and learn to enjoy Info files you may want to be able to
navigate them quickly, even if you haven't read the user manual as I have not.
ace-link [fn:4023603c: https://github.com/abo-abo/ace-link] is really a nice way to do that.
#+begin_src emacs-lisp
(ace-link-setup-default)
#+end_src
A numeric prefix argument will open up unique Info buffers [fn:0c0a1803: http://mbork.pl/2014-12-27_Info_dispatch]. Of course it will. Of course it will!
That explains how to make it easy to use multiple Info buffers per topic. This
article makes it easier too using Hydra [fn:68eae9c6: http://oremacs.com/2015/03/17/more-info/].
** Javascript [fn:152bafed: https://en.wikipedia.org/wiki/ECMAScript] [fn:42427fc4: http://www.emacswiki.org/emacs/JavaScriptMode]
=auto-complete= often needs a symlink from =javascript-mode= to =js-mode= added.
That link is not version controlled, nor is it created via the API as it makes
the check simpler.
#+begin_src emacs-lisp
(defun gcr/js-mode-hook ()
(local-set-key (kbd "RET") 'newline-and-indent)
(setq js-indent-level 2)
(fci-mode)
(visual-line-mode)
(gcr/untabify-buffer-hook)
(linum-mode))
(add-hook 'js-mode-hook 'gcr/js-mode-hook)
#+end_src
** LilyPond [fn:6d06e6b9: http://lilypond.org/]
All of my experience with musical notation is through GuitarPro [fn:3945829a: http://www.guitar-pro.com/en/index.php?pg=accueil-2&utm_expid=13369301-5.jyDTwdKfQ_CCdEqtpCIynQ.1&utm_referrer=https%3A%2F%2Fwww.google.com%2F]
and even there I'm a baby user. Despite that, I've been curious about
music theory for a long time and this seems like a good way to take a dip.
At first, it didn't seem to work. then I "rebooted" and it seemed to
work, but not in org HTML export. This will require further research.
** Lispy
A lot of people have downloaded =rainbow-delimiters=, 25377 as of <2014-07-26 Sat>.
The documentation is nice. =solarized= has support for it. The documentation says
something very specific:
#+begin_quote
The default colors are intentionally subtle; they are unobtrusive enough to make the mode worth looking at even if you usually don’t like rainbow parentheses modes.
#+end_quote
Well, that is me, so I am going to install it too.
#+begin_src emacs-lisp
(require 'rainbow-delimiters)
#+end_src
#+begin_src emacs-lisp
(defconst lispy-modes
'(clips-mode-hook
emacs-lisp-mode-hook
geiser-repl-mode-hook
ielm-mode-hook
lisp-interaction-mode-hook
scheme-mode-hook))
(dolist (h lispy-modes)
(add-hook h 'turn-on-smartparens-strict-mode)
(add-hook h 'gcr/newline)
(add-hook h 'gcr/disable-tabs))
(dolist (h lispy-modes)
(when (not (member h '(ielm-mode-hook)))
(add-hook h 'turn-on-pretty-mode)
(add-hook h 'gcr/untabify-buffer-hook)
(add-hook h 'fci-mode)
(add-hook h (function (lambda () (hs-minor-mode 1))))
(add-hook h 'linum-mode)
(add-hook h 'visual-line-mode)
(add-hook h (function (lambda ()
(add-hook 'local-write-file-hooks
'check-parens))))))
#+end_src
** Make [fn:da03efe9: https://www.gnu.org/software/make/manual/make.html] [fn:202: http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-makefile.html] [fn:203: http://www.emacswiki.org/emacs/MakefileMode]
#+begin_src emacs-lisp
(defun gcr/make-modehook ()
(fci-mode)
(whitespace-turn-on)
(visual-line-mode)
(local-set-key (kbd "RET") 'newline-and-indent))
(add-hook 'makefile-mode-hook 'gcr/make-modehook)
#+end_src
** Markdown [fn:e43df485: http://jblevins.org/projects/markdown-mode/]
I used to think that since org-mode exports to just about everything, that my
Markdown usage will be mostly limited to working with files on Github so I
turned on Github Flavored Markdown [fn:0b358cc2: https://help.github.com/articles/github-flavored-markdown] mode for README.md
files that are likely to appear on Github. That is fine and it doesn't interfere
with normal Markdown and also I'm getting more interested in Pandoc so it is
nice to have normal Markdown available easily here. GFM seems is in the release
now.
#+begin_src emacs-lisp
(autoload 'markdown-mode "markdown-mode"
"Major mode for editing Markdown files" +1)
(add-to-list 'auto-mode-alist '("\.markdown'" . gfm-mode))
(add-to-list 'auto-mode-alist '("\.md'" . gfm-mode))
(defun gcr/markdown-mode-hook ()
"Markdown mode customizations."
(interactive)
(fci-mode)
(visual-line-mode)
(local-set-key (kbd "RET") 'newline-and-indent))
(add-hook 'markdown-mode-hook 'gcr/markdown-mode-hook)
#+end_src
** Occur
Make it really easy to read search results!
#+begin_src emacs-lisp
(defun gcr/occur-mode-hook ()
"Personal customizations."
(interactive)
(turn-on-stripe-buffer-mode)
(stripe-listify-buffer))
(add-hook 'occur-mode-hook 'gcr/occur-mode-hook)
#+end_src
** Pandoc [fn:d8e34067: http://johnmacfarlane.net/pandoc/]
Heard good things about =pandoc-mode= [fn:0cacccd8: https://github.com/joostkremers/pandoc-mode] and I am really looking forward to
finding where dharma leads me with this. The mode documentation is here [fn:592907bc: https://joostkremers.github.io/pandoc-mode/].
Good 'old autoloads mean nothing to see here.
** Polymode [fn:918c4a07: https://github.com/vitoshka/polymode]
#+begin_quote
Object oriented framework for multiple emacs modes based on indirect buffers
#+end_quote
The status quo for LP with ℝ is =knitr= and my goal is to get first-class support
here. Started by reading the home page, I started
initial setup and a TODO. The literature on the page is seemingly directed more
at someone developing new modes. That seems pretty useful from any perspetive,
and I am going to include important points following.
#+begin_quote
it is worth emphasizing the distinctions between chunks and chunkmodes. Chunks are fragments of text and there might be multiple chunks of the same type in the buffer. In contrast, there is only one chunkmode of some specific type and multiple chunks of this type "share" this chunkmode
#+end_quote
and also
#+begin_quote
things like =poly-XXX-mode-map= and =poly-XXX-mode-hook= work just as expected
#+end_quote
Perhaps a path do understanding the nature of the mode is in "Defining New
Polymodes"
#+begin_quote
In order to define a new polymode =poly-cool-mode= you first have to define or clone a chunkmode object to represent the hostmode, and one or more chunkmodes to represent innermodes. Then define the polymode object =pm-poly/cool= pointing to previously defined host and inner chunkmodes.
#+end_quote
The example given is of a latex and noweb system:
- Define a host mode of a =pm-bchunkmode= for =latex= which is capable of containing embedded languages
- Define a =pm-hbtchunkmode= for =noweb= inner language
- Defines regexen for identifying a block of this type ala noweb syntax
- Define a =pm-polymode-one= using bo them
Another example is given showing how you can re-use a host mode. Say you wanted
a mode for noweb that could contain chunks of ℝ instead of latex. You can clone
the noweb inner-mode definition and then define a new plymode. The vagueness
here is intentional because I didn't try it myself. Although I didn't dig deep
at all into the details, it is clearly a rich and powerful library. At the very
least, it is nice documentation to be read. The next ste is to set it up.
The functionality that I'm primarily interested in seems to be here [fn:aee1cbde: https://github.com/vitoshka/polymode/blob/master/modes/poly-R.el].
Skimming it a few things jump out:
- There is a base language definition
- Therer are *many* host modes for seemingly every markup out there
- Noweb, Markdown, Rapport, Yaml, HTML, Knitr, Brew, RC++, C++R, R-Help,
Rd, R shell, ESS combinations
It is not obvious to me how to set it up. This [fn:3dc322e2: http://blog.revolutionanalytics.com/2014/03/emacs-ess-and-r-for-zombies.html]
seems to indicate that one should do as I have done, read the home page, and
then go online for tips. Now, I have. This [fn:d1979851: http://johnstantongeddes.org/open%20science/2014/03/26/Rmd-polymode.html] post
was very helpful. A little unsure where to go from here, this https://stat.ethz.ch/pipermail/ess-help/2014-May/009926.html post indicates
that there are, just as the code said, 4 weaves that may be important:
- knitR
- knitR-ESS
- Sweave
- Sweave-ESS
Opened up a .Rmd document. Called =polymode-weave= and chose =knitR-ESS=. It
generated the corrent =.md= file.
Opened up a ℝ help buffer and the Examples section was formatted correctly.
Later I saw that I should have also read:
- [fn:ea37e53b: http://comments.gmane.org/gmane.emacs.ess.general/6994]
- Release post
- Good discussion, provides both context and ideas
- [fn:3133d97b: http://thread.gmane.org/gmane.emacs.ess.general/8155]
- Read this back then and it only makes sense now after reading the documentation
- Very thoughtful and flexible and good
- Other potentially interesting discussions
Load and specify file auto modes:
#+begin_src emacs-lisp
(require 'poly-R)
(require 'poly-markdown)
(add-to-list 'auto-mode-alist '("\\.Rmd" . poly-markdown+r-mode))
#+end_src
Specify some keymaps that are nearly what I have for =org= for the same tasks:
#+begin_src emacs-lisp
(define-key polymode-mode-map (kbd "s-e E") 'polymode-set-exporter)
(define-key polymode-mode-map (kbd "s-e e") 'polymode-weave)
(define-key polymode-mode-map (kbd "s-w s") 'polymode-set-weaver)
(define-key polymode-mode-map (kbd "s-w w") 'polymode-weave)
(define-key polymode-mode-map (kbd "s-w p") 'polymode-show-process-buffer)
(define-key polymode-mode-map (kbd "s-j") 'polymode-previous-chunk)
(define-key polymode-mode-map (kbd "s-k") 'polymode-next-chunk)
(define-key polymode-mode-map (kbd "s-o k") 'polymode-kill-chunk)
(define-key polymode-mode-map (kbd "s-o i") 'polymode-insert-new-chunk)
(define-key polymode-mode-map (kbd "s-o m") 'polymode-mark-or-extend-chunk)
(define-key polymode-mode-map (kbd "s-o t") 'polymode-toggle-chunk-narrowing)
#+end_src
** Ruby [fn:e9aab149: https://www.ruby-lang.org/en/]
My first setup of Ruby is primarily for Vagrant, so I didn't dig super deep into
the options. The defaults will be just fine.
Chef now, too.
#+begin_src emacs-lisp
(defun gcr/ruby-mode-hook ()
(interactive)
(fci-mode)
(gcr/untabify-buffer-hook)
(visual-line-mode)
(fci-mode)
(turn-on-smartparens-strict-mode)
(local-set-key (kbd "RET") 'newline-and-indent)
(hs-minor-mode 1)
(linum-mode))
(add-hook 'ruby-mode-hook 'gcr/ruby-mode-hook)
#+end_src
** Scheme [fn:5c0b0c3e: http://library.readscheme.org/index.html]
You should probably only use Geiser, forever. [fn:d27bd96d: http://www.nongnu.org/geiser/] Some day I would like to
explore =ac-geiser= [fn:6d6fbd53: https://github.com/xiaohanyu/ac-geiser].
#+begin_src emacs-lisp
(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 "") 'gcr/scheme-eval-buffer))
(add-hook 'scheme-mode-hook 'gcr/scheme-mode-local-bindings)
(add-to-list 'auto-mode-alist '("\\.scm\\'" . scheme-mode))
(add-to-list 'auto-mode-alist '("\\.rkt\\'" . scheme-mode))
(add-to-list 'auto-mode-alist '("\\.ss\\'" . scheme-mode))
(add-to-list 'auto-mode-alist '("\\.sls\\'" . scheme-mode))
(add-to-list 'auto-mode-alist '("\\.sps\\'" . scheme-mode))
#+end_src
** Sh(hell)
"Major mode for editing shell scripts."
#+begin_src emacs-lisp
(defun gcr/sh-mode-hook ()
"Personal customizations."
(interactive)
(turn-on-smartparens-strict-mode)
(turn-on-pretty-mode)
(gcr/untabify-buffer-hook)
(gcr/disable-tabs)
(fci-mode)
(whitespace-turn-on)
(visual-line-mode)
(hs-minor-mode 1)
(local-set-key (kbd "RET") 'newline-and-indent))
(add-hook 'sh-mode-hook 'gcr/sh-mode-hook)
#+end_src
** Shell
"Major mode for interacting with an inferior shell."
#+begin_src emacs-lisp
(defun gcr/shell-mode-hook ()
"Personalizations."
(interactive)
(turn-on-smartparens-strict-mode)
(turn-on-pretty-mode)
(gcr/disable-tabs)
(fci-mode)
(whitespace-turn-on)
(visual-line-mode)
(hs-minor-mode 1)
(local-set-key (kbd "RET") 'newline-and-indent))
(add-hook 'shell-mode-hook 'gcr/shell-mode-hook)
#+end_src
** Standard ML (SML) [fn:eb5c01ac: https://en.wikipedia.org/wiki/Standard_ML]
=sml-mode= has its documentation here [fn:e31e1b22: http://www.smlnj.org/doc/Emacs/sml-mode.html] and package here [fn:185e62bd: http://elpa.gnu.org/packages/sml-mode.html].
I am not shy about including stuff that defaults fine in the mode when its
purpose is to educate the reader who /doesn't/ bother to read the mode
definition.
#+begin_src emacs-lisp
(require 'sml-mode)
(defun gcr/sml-mode-hook ()
"Personal settings."
(interactive)
(turn-on-pretty-mode)
(turn-on-smartparens-strict-mode)
(local-set-key (kbd "RET") 'newline-and-indent)
(gcr/untabify-buffer-hook)
(gcr/disable-tabs)
(fci-mode)
(hs-minor-mode 1)
(visual-line-mode))
(add-hook 'sml-mode-hook 'gcr/sml-mode-hook)
(setq sml-indent-level 2)
(setq sml-rightalign-and t)
(setq sml-electric-pipe-mode t)
(setq sml-program-name "sml")
#+end_src
=pretty-mode= will give us Unicode symbols for arrows and stuff, so this mode
doesn't need to handle it.
#+begin_src emacs-lisp
(setq sml-font-lock-symbols nil)
#+end_src
When SML starts up, it loads =sml-config-file= by default. Perhaps some day I
would have such a prelude.
=sml-max-name-components= is kind of interesting… I will assume that it is fine
for now because until I know better, it is.
Like all programming modes… save everything before evaluating code.
#+begin_src emacs-lisp
(defadvice sml-prog-proc-load-file (before beforesml-prog-proc-load-file activate)
(gcr/save-all-file-buffers))
#+end_src
** Strings
Sometimes we keep code inside of strings inside of another language. HQL for
example. Make it easy to edit those strings without worrying about escaping
everything. String-edit provides a nice helper here.
** Structured Query Language (SQL) [fn:a018350e: https://en.wikipedia.org/wiki/SQL]
Sometimes it is really nice to have SQL keywords written all upper-case.
Seriously. Although it is kind of a learning-phase where you must do that, you
really grow out of it at some point. Despite that, sometimes it is nice to have.
=slqup-mode= [fn:be68b5d2: https://github.com/Trevoke/sqlup-mode.el] does just
this for you. I love the package definition:
#+begin_quote
Its sole purpose is to make your life easier when writing SQL.
#+end_quote
What a great goal!
#+begin_src emacs-lisp
(require 'sqlup-mode)
#+end_src
There is a =sql-mode= [fn:e151d946: http://www.emacswiki.org/emacs/SqlMode]
of course, and surely I will need to set it up one day.
** Table
Tables don't sound that exciting, but try running the world without a tabular
data representation! Not so easy huh?
SAKURAI Masashi has made it easy for us in Emacs with =ctable=.
#+begin_src emacs-lisp
(require 'ctable)
(defun gcr/ctbl:table-mode-hook ()
"Personal customization"
(interactive))
(add-hook 'ctbl:table-mode-hook 'gcr/ctbl:table-mode-hook)
#+end_src
** TeX [fn:5bb50e18: https://en.wikipedia.org/wiki/TeX] / LaTeX [fn:a13f106f: [[https://en.wikipedia.org/wiki/LaTeX]]] / ConTeXt [fn:8a78f8ab: https://en.wikipedia.org/wiki/ConTeXt]
AUCT_{E}X is the mode that makes it possible to work with all of these fine tools.
Visiting their website I took their advice of reading the Info document in Emacs
by first installing it via Homebrew. That was my mistake since the prerequisites
page starts by explaining that this mode is 100% Elisp and that you should use
ELPA to install it. I started over again with the setup. When you read the
documentation, the first page explains how to load the mode and associate files
with modes but you should ignore that because when you configure it via ELPA,
everything "just works". Installation mostly involved the prerequisites.
This version of Emacs is modern. For TeX, on Linux, I've always used TeX Live [fn:841d4205: https://www.tug.org/texlive/] and on OSX I've always used
MacTeX [fn:490cc248: https://www.tug.org/mactex/]. Ghostscript comes with
both either via =apt-get= or =homebrew=. =texinfo= didn't seem necessary so I
did not pursue installing it.
Enable most of the stuff we need, given that I don't yet know what we need but
the manual helps us here.
#+begin_src emacs-lisp
(setq TeX-auto-save t)
(setq TeX-parse-self t)
#+end_src
The "Quick Start" lists the most frequent operations, and I think that I will
get the PDF for them. Looking at just this tiny, tiny bit of effort to get
AUCTeX working… it is just so inspiring to see the plethora of amazingly
wonderful tools out there /free/ for all to use.
For a start, I will just do some basic stuff that I do for most modes.
#+begin_src emacs-lisp
(defun gcr/TeX-mode-hook ()
"Settings applicable to every AUCTeX supported mode."
(interactive)
(turn-on-smartparens-strict-mode)
(gcr/disable-tabs)
(fci-mode)
(linum-mode))
(add-hook 'TeX-mode-hook 'gcr/TeX-mode-hook)
#+end_src
Enable parse on load.
#+begin_src emacs-lisp
(setq TeX-parse-self t) ;
#+end_src
Enable parse on save.
#+begin_src emacs-lisp
(setq TeX-auto-save t) ;
#+end_src
Never save tabs because AUCTeX has a hard time with them.
#+begin_src emacs-lisp
(setq TeX-auto-untabify t)
#+end_src
Before letting this mode process any file, save all buffers:
#+begin_src emacs-lisp
(defadvice TeX-command-master (before before-TeX-command-master activate)
(gcr/save-all-file-buffers))
#+end_src
My typical preference is to easily work with XDVI during development and PDF for
deployment. My want had been to turn PDF generation on, while at the same time
still producing a DVI file. To do that, I did something like this:
#+begin_src emacs-lisp
(setq TeX-PDF-mode +1)
(setq TeX-DVI-via-PDFTeX +1)
#+end_src
Don't prompt me every time I run =C-c C-c= about saving the file, instead, just
save it [fn:b2655f5c: http://mbork.pl/2015-01-10_A_few_random_Emacs_tips].
#+begin_src emacs-lisp
(setq TeX-save-query nil)
#+end_src
Start the proper mode for LCO files.
#+begin_src emacs-lisp
(add-to-list 'auto-mode-alist '("\\.lco?\\'" . TeX-latex-mode))
#+end_src
** Text
#+begin_src emacs-lisp
(defun gcr/text-mode-hook ()
(fci-mode)
(visual-line-mode)
(gcr/untabify-buffer-hook))
(add-hook 'text-mode-hook 'gcr/text-mode-hook)
#+end_src
** Vagrant [fn:a83cf3b8: http://www.vagrantup.com/]
Vagrant is quite nice. Perhaps a bit preemptively, I'm trying to get Emacs setup
nice for what I already know I must do.
This belongs in this heading I believe:
#+begin_src emacs-lisp
(add-to-list 'auto-mode-alist '("Vagrantfile$" . ruby-mode))
#+end_src
Nice package [fn:ccaa2275: https://github.com/ottbot/vagrant.el] for working with Vagrant; hundreds of people already using
it. No configuration even necessary.
** Web [fn:857fba7f: https://en.wikipedia.org/wiki/HTML]
JSON support is included here, too. As you go about your business you read about
features that seem nice or you really didn't actively think about. One such
opportunity/mistake I am guilty of is using various web-based tools to
accomplish thing for example formatting a JSON string, like this
={"foo":10, "bar":20, "baz":50}= example. For whatever
reason, that is always just the way that I had done it. Reading irreal a nice
option/reminder was posted for a JSON formatter [fn:9d35fd56: https://github.com/gongo/json-reformat]
#+begin_src emacs-lisp
(require 'web-mode)
(setq web-mode-enable-block-partial-invalidation t)
(setq web-mode-engines-alist
'(("ctemplate" . "\\.html$")))
(defun gcr/web-mode-hook ()
(whitespace-turn-off)
(rainbow-turn-off)
(visual-line-mode)
(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)
(require 'json-reformat)
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.json\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
#+end_src
** Web browsing
Browse URLs in a real browser; nothing against W3C. [fn:44dd271e: https://www.gnu.org/software/emacs/manual/html_node/emacs/Browse_002dURL.html]
EWW looks interesting, too [fn:4c24a298: http://lars.ingebrigtsen.no/2013/06/16/eww/]
#+begin_src emacs-lisp
(setq browse-url-browser-function 'browse-url-generic)
(gcr/on-gnu/linux (setq browse-url-generic-program "chromium-browser"))
(gcr/on-osx
(setq browse-url-browser-function 'browse-url-default-macosx-browser)
(require 'osx-browse)
(osx-browse-mode 1))
(gcr/on-windows
(setq browse-url-browser-function 'browse-url-default-windows-browser))
#+end_src
Searching for things on the world wide web is a daily occurrence. There are a
lot of helper functions out there to search Google, but there is a package that
does it all, and this is it:
#+begin_src emacs-lisp
(require 'google-this)
(google-this-mode 1)
(gcr/diminish 'google-this-mode)
#+end_src
** TRAMP [fn:4997f5f8: https://www.gnu.org/software/tramp/]
TRAMP stands for "Transparent Remote (file) Access, Multiple Protocol". It is
really, really beautiful.
#+begin_src emacs-lisp
(setq tramp-default-user "gcr")
(setq tramp-default-method "ssh")
#+end_src
** YAML
Thank you, Kitchenplan.
#+begin_src emacs-lisp
(require 'yaml-mode)
(add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.yaml$" . yaml-mode))
(defun gcr/yaml-mode-hook ()
"Helpful behavior for YAML buffers."
(interactive)
(turn-on-smartparens-strict-mode)
(local-set-key (kbd "RET") 'newline-and-indent)
(gcr/disable-tabs)
(turn-on-pretty-mode)
(gcr/untabify-buffer)
(fci-mode)
(hs-minor-mode 1)
(linum-mode)
(visual-line-mode))
#+end_src
** Diagramming, UML creation, Workflow
How you perform these tasks 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 [fn:5f9306fa: http://www.emacswiki.org/emacs/ArtistMode] is plenty fine for diagramming and stuff. Graphviz also works well [fn:93e16211: http://www.graphviz.org/].
Ditaa is sort of the next level up [fn:b6f5f0cc: http://ditaa.sourceforge.net/], and finally PlantUML [fn:245: http://plantuml.sourceforge.net/]. 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-mode just shines so, so brightly.
As of writing, I'm undecided NOW how best to
standardizing 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, ASCII or UTF-8, just works.
- Graphviz: Graphically 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.
- [[https://github.com/tj64/puml][This]] may help
ditaa was my first pick for usage for the blaring simplicity and power of it.
org-mode provides a setup [fn:69c0caad: http://orgmode.org/worg/org-contrib/babel/languages/ob-doc-ditaa.html]document 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; thank you [fn:c8388777: http://www.craiglarman.com/wiki/index.php?title=Books_by_Craig_Larman] Craig Larman
#+begin_src ditaa :file ./images/auap.png :noweb-ref no-tangle
+----------+1 1…3+------+
| Sailboat +◆----------+ Mast |
+-----+----+ +------+
◆1
|
| 1…2+------+
+----------------+ Hull |
+------+
This is not a sailboat
#+end_src
#+RESULTS:
[[file:./images/auap.png]]
This [fn:cb5475bf: http://www.gnuvola.org/software/aa2u/]
=ascii-art-to-unicode= tool also is interesting.
Sparkline graphs [fn:8d44474a: http://en.wikipedia.org/wiki/Sparkline] look
interesting. Although I'm not sure where or how I will use them right now, I
want them to be available when the time is right. Also I am curious about where
they may fit in =org=.
#+begin_src emacs-lisp
(require 'sparkline)
#+end_src
*** Setup
**** ditaa
The =ditaa= library file is not version controlled.
#+begin_src emacs-lisp
(defconst gcr/ditaa-jar (concat (getenv "EELIB") "/ditaa0_9.jar"))
(defun gcr/warn-ditaa-jar ()
"Warn of ditaa misconfiguration."
(interactive)
(unless (f-exists? gcr/ditaa-jar)
(warn
"Can't seem to find a ditaa jar where it was expected at: %S. Ditaa will not function without it. Download a copy here: http://sourceforge.net/projects/ditaa/"
gcr/ditaa-jar)))
(gcr/warn-ditaa-jar)
(setq org-ditaa-jar-path gcr/ditaa-jar)
#+end_src
#+begin_src emacs-lisp
(add-to-list 'auto-mode-alist '("\\.asc" . artist-mode))
(add-to-list 'auto-mode-alist '("\\.art" . artist-mode))
(add-to-list 'auto-mode-alist '("\\.asc" . artist-mode))
#+end_src
**** plantuml
=plantuml= needs a full directory path. It is easier to address it here.
#+begin_src emacs-lisp
(defconst gcr/plantuml-jar (concat (expand-file-name (getenv "EELIB")) "/plantuml.8026.jar"))
#+end_src
The rest of the configuration is vanilla.
#+begin_src emacs-lisp
(defun gcr/warn-plantuml-jar ()
"Warn of plantuml misconfiguration."
(interactive)
(unless (f-exists? gcr/plantuml-jar)
(warn
"Can't seem to find a plantuml jar where it was expected at: %S. Plantuml will not function without it. Download a copy here: http://plantuml.sourceforge.net/"
gcr/plantuml-jar)))
(gcr/warn-plantuml-jar)
(setq plantuml-jar-path gcr/plantuml-jar)
(require 'plantuml-mode)
(eval-after-load "ob-plantuml"
(setq org-plantuml-jar-path gcr/plantuml-jar))
(defun gcr/plantuml-mode-hook ()
"Personal settings."
(interactive)
(turn-on-pretty-mode)
(turn-on-smartparens-strict-mode)
(local-set-key (kbd "RET") 'newline-and-indent)
(gcr/untabify-buffer-hook)
(gcr/disable-tabs)
(fci-mode)
(hs-minor-mode 1)
(linum-mode)
(wrap-region-mode t)
(turn-on-stripe-table-mode))
(add-hook 'plantuml-mode-hook 'gcr/plantuml-mode-hook)
#+end_src
Just read the user manual:
Note to self, for any image generation keep in mind how this
#+begin_example
(org-display-inline-images nil t)
#+end_example
is being used. =org= has hook for post rendering so Emacs is always up to date.
In this mode I have no such solution, so I will probably forget while inside.
- Sequence diagrams
- Very feature rich
- Images immediately convey a lot of information about the tool here
- Chose a simple example, no all encompassing
- Tested, worked
#+begin_src plantuml :file ./images/pumlseqd.png :noweb-ref ignore :exports results
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response
#+end_src
#+NAME:
[[file:./images/pumlseqd.png]]
- Use case diagrams
- Actor variable aliasing, very thoughtful
- Tested, worked
#+begin_src plantuml :file ./images/pumlucd.png :noweb-ref ignore :exports results
left to right direction
skinparam packageStyle rect
actor customer
actor clerk
rectangle checkout {
customer -- (checkout)
(checkout) .> (payment) : include (help) .> (checkout) : extends (checkout) -- clerk
}
#+end_src
#+NAME:
[[file:./images/pumlucd.png]]
- Class diagram
- Value this greatly for all sorts of ideas not just classes
- =hode=, =show=, and =include= are mentioned
- Could be a great reuse mechanism combined with noweb and tangling
- Spotted characters might be useful to indicating other things
- Example is data which is clearly a first-class citizen
- Six package visualization types
- Packaging vs. namespaceing is nice
- Good support for splitting large images among output pages
- Tested, works, added TODO for =org-display-images-call= after generation
#+begin_src plantuml :file ./images/pumlcd.png :noweb-ref ignore :exports results
title This is not a sailboat
scale 200 width
Sailboat "1" *-- "1..3" Mast
Sailboat "1" *-- "1..3" Hull
#+end_src
#+NAME:
[[file:./images/pumlcd.png]]
- Activity diagrams
- May indicate top to bottom flow using =top=
- May label arrows
- May force arrow direction
- Sweet if/else structure for branching
- Partition construct looks very useful
- New syntax [fn:e81de35c: http://plantuml.sourceforge.net/activity2.html]
seems good and there are more examples
- Next chapter covers the new syntax, so using that
- Tested, works
#+begin_src plantuml :file ./images/pumlad.png :noweb-ref ignore :exports results
start
partition Initialization {
:read config file;
:init internal variable;
}
partition Running {
:wait for user interaction;
:print information;
}
stop
#+end_src
#+NAME:
[[file:./images/pumlad.png]]
- Component diagrams
- Might be good to use the names to define all of the diagram entity types
- Need to find out what is "modern" UML, or at least, modern for me
- Might be a nice summary tool
- Tested, works
#+begin_src plantuml :file ./images/pumlcod.png :noweb-ref ignore :exports results
[First component]
[Another component]
() "First Interface"
() "Another interface" as Interf2
DataAccess - [First Component]
[First Component] ..> HTTP : use
#+end_src
#+NAME:
[[file:./images/pumlcod.png]]
- State diagrams
- Such a sweet tool
- Works OK
#+begin_src plantuml :file ./images/pumlstd.png :noweb-ref ignore :exports results
[*] --> State1
State1 --> [*]
State1 : this is a string State1 : this is another string
#+end_src
#+NAME:
[[file:./images/pumlstd.png]]
- Object diagrams
- How different from class?
- Works, all stuff is there but I didn't bring it
#+begin_src plantuml :file ./images/pumlod.png :noweb-ref ignore :exports results
object Object01
object Object02
Object01 <|-- Object02
#+end_src
#+NAME:
[[file:./images/pumlod.png]]
- Commands
- Header and footer values
- Zoom level
- Creole markup for most text elements
- Lists, and sub-lists
- Horizontal lines, will appears in most containers
- Headings
- Plain old HTML
- Tables, LaTeX style
- OpenIconic icons [fn:2f694b60: https://useiconic.com/open] anywhere
- For fonts and colors
- You can change just about everything
- You may nest definitions, nice
- =monochrome true= option
- Nice if you are printing
- Or just don't want any colors anyway
- Internationalization
- Full Unicode character support
* Libraries
:PROPERTIES:
:noweb-ref: Libraries
:END:
** Generally nice
- Dash / Dash-Functional
Not totally sure where this belongs, but dash [fn:9d300103: https://github.com/magnars/dash.el] is something that a lot
of the packages I use require, and it is an excellent library, so it needs
recognition in this document.
#+begin_src emacs-lisp
(eval-after-load "dash" '(dash-enable-font-lock))
#+end_src
- f [fn:dc91c0cb: https://github.com/rejeep/f.el]
#+begin_src emacs-lisp
(require 'f)
#+end_src
Use the API to indicte things /to the reader/:
- =f-exists?= vs. =f-symlink?=
Because *I* can't seem to remember this critical and key detail on how files
work, here is an example. It says:
- Every symlink is a file
- Every file is not a symlink
#+begin_src emacs-lisp :noweb-ref no-tangle
(setq a-tmp-file (make-temp-file "~/"))
(setq a-tmp-link (concat a-tmp-file "-LINK"))
(make-symbolic-link a-tmp-file a-tmp-link 'overwrite)
(print (setq no-file "/infinity"))
(print (f-exists? no-file))
(print a-tmp-file)
(print (f-exists? a-tmp-file))
(print (f-file? a-tmp-file))
(print (f-symlink? a-tmp-file))
(print a-tmp-link)
(print (f-exists? a-tmp-link))
(print (f-file? a-tmp-link))
(print (f-symlink? a-tmp-link))
#+end_src
#+RESULTS:
#+begin_example
"/infinity"
nil
"/Users/gcr/3655Wbk"
t
t
nil
"/Users/gcr/3655Wbk-LINK"
t
t
t
#+end_example
- s [fn:017b522b: https://github.com/magnars/s.el]
Starting to think that I might want a "useful library" section, because I just
added the =xml-rpc= [fn:0c0b84fd: http://melpa.milkbox.net/#/xml-rpc] library here because it is clearly useful:
#+begin_src emacs-lisp
(require 'xml-rpc)
#+end_src
metaweblog is necessary for org2blog, too:
#+begin_src emacs-lisp
(require 'metaweblog)
#+end_src
- Various
- =uuid=
- Make it easy to get some. Somes you really need them!
#+begin_src emacs-lisp
(require 'uuid)
#+end_src
** Built-in
pcase [fn:e76be200: http://www.emacswiki.org/emacs/PatternMatching] provides pattern-matching macros. This is very nice whether
you've already used something like this before, or not!
** Characters / Unicode
unidecode [fn:2a08dd99: https://github.com/sindikat/unidecode] does its best to
convert UTF-8 to ASCII; then I found that it wouldn't load so I removed it.
If you've verused a character terminal then you already know that
figlet [fn:81c97c99: http://www.figlet.org/] is a mandatory tool.
This [fn:08208a82: https://bitbucket.org/jpkotta/figlet] package makes it nice
to use. It has all the stuff you /would/ want to do, like figletify stuff.
It even has a little helper function to show you how the fonts look… beccause
you /know/ that you would have ended up writing something like that yourself if
it wreren't here:
#+begin_src emacs-lisp
(require 'figlet)
#+end_src
Make sure =figlet= may be found on OSX via Brew.
#+begin_src emacs-lisp
(setq figlet-font-directory "/usr/local/bin/")
#+end_src
* Jokes
:PROPERTIES:
:noweb-ref: Jokes
:END:
These are things that I consider critical to keeping things light-hearted.
#+begin_src emacs-lisp
(require 'nyan-mode)
#+end_src
Make it look like you are typing at light speed. I had to start =calculator-mode=
before running this in order for it to be happy.
#+begin_src emacs-lisp
(require 'highlight-tail)
#+end_src
Take "zoning out" to a whole new level.
#+begin_src emacs-lisp
(require 'zone)
#+end_src
For when you want to watch /someone else/ play Tetris instead of yourself,
call =autotetris=.
* Customize
:PROPERTIES:
:noweb-ref: Customize
:END:
*This must come before manually set variables*
This approach needs further research as it seems to work but I am not sure what
kind of trouble I could cause by doing this so I know that it may cause some
such trouble!
For example, sometimes values I set in here get stomped on. That is probably
because the call to =custom-set-variables= occurs /after/ the packages are loaded
specifying them. Right now I am still not totally sure because of
=eval-after-load= blocks.
#+begin_src emacs-lisp
(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 ("8aebf25556399b58091e533e455dd50a6a9cba958cc4ebb0aab175863c25b9a4" default)))
'(display-time-world-list (quote (("America/Chicago" "Chicago") ("Asia/Kolkata" "Kolkata") ("Asia/Kuala_Lumpur" "Kuala Lumpur"))))
'(ess-R-font-lock-keywords (quote ((ess-R-fl-keyword:modifiers . t) (ess-R-fl-keyword:fun-defs . t) (ess-R-fl-keyword:keywords . t) (ess-R-fl-keyword:assign-ops . t) (ess-R-fl-keyword:constants . t) (ess-fl-keyword:fun-calls) (ess-fl-keyword:numbers) (ess-fl-keyword:operators) (ess-fl-keyword:delimiters) (ess-fl-keyword:= . t) (ess-R-fl-keyword:F&T))))
'(inferior-R-font-lock-keywords (quote ((ess-S-fl-keyword:prompt . t) (ess-R-fl-keyword:messages . t) (ess-R-fl-keyword:modifiers . t) (ess-R-fl-keyword:fun-defs . t) (ess-R-fl-keyword:keywords . t) (ess-R-fl-keyword:assign-ops . t) (ess-R-fl-keyword:constants . t) (ess-fl-keyword:matrix-labels . t) (ess-fl-keyword:fun-calls) (ess-fl-keyword:numbers) (ess-fl-keyword:operators) (ess-fl-keyword:delimiters) (ess-fl-keyword:= . t) (ess-R-fl-keyword:F&T))))
'(linum-format "%5d")
'(osx-browse-guess-keystrokes (quote ("s-b k")))
'(osx-browse-url-keystrokes (quote ("s-b u"))))
(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.
'(anzu-mode-line ((t (:foreground "#073642" :weight bold)))))
#+end_src
* Tangling
** .emacs.el
My document style does not let itself to tangling-comments.
#+begin_src emacs-lisp :tangle .emacs.el :comments no
«Start-Up»
«Customize»
«Runtime-Check»
«Provisioning»
«Means»
«Keybindings»
(gcr/on-windows
«Windows-Helper-Bindings»)
«Modes»
«Libraries»
«Jokes»
#+end_src
** eshell/alias
This file can't contain comment lines in =sh= or =emacs-lisp= and I don't want
to find out why so don't include =org= comments.
Be sure to link =~/.emacs.d/eshell= here.
#+begin_src sh :tangle eshell/alias :comments no
alias bbc ~/git/github-grettke/stathon/stathon.py ~/git/bitbucket-grettke/ | grep True
alias clear recenter 0
alias d 'dired $1'
alias ff find-file $1
alias g git $*
alias gb git branch $*
alias gbc ~/git/github-grettke/stathon/stathon.py ~/git/github-grettke/ | grep True
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
#+end_src
* Portability
Portability is a trait of something that may be easily moved. Here it is between
operating systems. The =gcr/on= prefixed functions have provided portability just
fine until now. Now I am spending a lot more tim working on Windows and my
existing setup *reduced* by ability to realize the goals of this sytem. The fastest
way to define the deficits in my setup is to simply address the solutions. They
follow.
** Windows
- Install the 32bit Emacs distribution straight from GNU
- There are others. Do not use them.
- Extract it to =~/apps= and add the =bin= dir to the exported =PATH=
- Export =HOME= set to your preference
- Your home dir =C:\Users\user= works fine
- Run =addpm= to add Emacs to the application menu
- Install [[http://sourceforge.net/projects/ezwinports/][EZWinPorts]]
- Want normal Windows users to have a chance so not using MSYS or CYGWIN
- Stuff to install
- GNUTLS
- LibPNG
- make with guile
- Install [[http://aspell.net/win32/][Aspell Win32]]
- Add to PATH
- Install the English dictionary
- Installer /should/ successfully identify the Aspell install directory and
install the =dict= and =data= into the corect location
- Keyboard setup
- Goal was to utilize my current keybindings and make no changes
- This system uses Super all over the place and maps the WindowsKey to Super
- Windows maps a number of actions to WindowsKey
- A Windows configuration is /supposed/ to remove those bindings, but it does
not. They conflict with my existing bindings and I wasn't going to change
after using them for one year. After spending 4 hours trying to find a work
around, I pursued a more simplistic strategy that is defined in a code
block under this heading
- [[http://www.graphviz.org/Download..php][Graphviz]]
- Grabbed from their home page
- Installed via the MSI
- Added bin dir to path
- Install [[http://imagemagick.org/][ImageMagick]]
There are many options for keymapping in Windows. [[https://code.google.com/p/keymapper/][KeyMapper]] and [[https://sharpkeys.codeplex.com/][SharpKeys]] used
to satisfy my requirements, but then quit doing so. Quite simply, they did not
work /for me/ on Windows 8.1 despite having worked fine for years on 7. [[http://www.autohotkey.com/][AutoHotKey]]
(AHK) now performs the task correctly.
I need to do the simplest possible thing here. I /want/ to do it /the right way/ and
just deal with low-level key-codes, but that is a poor use of time so I am not.
I wanted to figure how to to use AHK to make Enter send Enter when pushed once and
to make it act as the Control key when held. I didn't have enough time so I am
making my RightShift key act as Enter. I will post to the forums to find out how.
To avoid generating key combinations that activate the default Windows keybinding
events I am using a super simple strategy of and where:
- Make WindowsKey act as to Super
- Issue is that Super keybindings activate default Windows actions
- Solution is to make WindowsKey instead send MetaSuper
- *Control-super* does not work and I don't know why
- That is why I am using Meta here
- In this sytem must define additional keybindings "on Windows" that do the
the same thing with the new =M-s-= bindings
- This heading exists to define both
- For now doing it manually, no automation, no reuse, just fix what doesn't
work
GitForWindows seems to work fine adding the *safe* stuff to the PATH, but not
more. Emacs gets started with =runemacs= and picks up the =PATH= correctly. =vc= works
fine but =magit= does not. I will investigate this.
Thus far, swapping capslock with leftcontrol and enter with rightcontrol has
been pleasant. It is very doable since Windows keyboards have all of the required
controls! The Macbook, though, does not, hence the need for the program to make
enter perform double-duty. It would be really great if we had that on Windows
too. After spending a combined six hours or so looking at approaches and
evaluating them I didn't find one that I worked. At that point, I felt that it
was no longer a valuable pursuit. As such, on Winboxen I'll go with this and
on Macs I'll go with that. Simpler.
For the record, some researched areas:
- All of the site literature
- Really, really work reading
- Feels haphazard but it will make sense after reading it all
- Searched all forum posts for similar needs
- [[http://www.autohotkey.com/board/topic/103044-one-key-acting-as-a-modifier-but-also-as-a-hotkey/?hl%3D%252Bemacs#entry637897][One key acting as a modifier but also as a hotkey]]
- Exactly what I want
- Not exactly what I need
- [[http://www.autohotkey.com/board/topic/113282-emacs-pincky/?hl%3D%252Bemacs#entry662239][emacs pincky]]
- Good to know
- Doens't work
- [[https://github.com/boblu/EmacsEverywhere/blob/master/EmacsEverywhere.ahk][emacseverywhere]]
- Nice to know
- Not exactly what I want
- http://www.autohotkey.com/docs/Tutorial.htmTutorial
- Talked about how to handle a key press, using a loop
- Interesting because that is definitely "one way" and there are others
- Eg: The following example clicks the left mouse button repeatedly while the user is holding down the F1 key
- Hotkeys talked about how to get a key to do one thing when held and released
and another when using in combinationt
- At least how I am reading it
- Here is the whole example
- Still not what I need
#+begin_quote
You can define a custom combination of two keys (except joystick buttons) by using " & " between them. In the below example, you would hold down Numpad0 then press the second key to trigger the hotkey:
#+end_quote
#+begin_src sh
Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
Numpad0 & Numpad2::Run Notepad
#+end_src
#+begin_quote
In the above example, Numpad0 becomes a prefix key; but this also causes Numpad0 to lose its original/native function when it is pressed by itself. To avoid this, a script may configure Numpad0 to perform a new action such as one of the following:
#+end_quote
#+begin_src sh
Numpad0::WinMaximize A ; Maximize the active/foreground window.
Numpad0::Send {Numpad0} ; Make the release of Numpad0 produce a Numpad0 keystroke.
#+end_src
#+begin_quote
The presence of one of the above hotkeys causes the release of Numpad0 to perform the indicated action, but only if you did not press any other keys while Numpad0 was being held down.
#+end_quote
Since I can't be the /only/ Emacs Windows user would like something like this for
the Windows Emacs build, there could be an opportunity to group-sponsor the
addition to AHK. Right now I am not pursuing leading such an effort. Perhaps you
are?
If you are connecting to a Windows box from an OSX box running Karabiner using
Microsoft Remote Desktop then you must disable AHK. You won't be able to use the
key.
*** Testing
- Windows 7
- No installation issues
- Works perfectly
- Windows 8.1
- Package installation issues both for Package and ElGet
- Unsure, will do more testing
*** Helper Bindings
:PROPERTIES:
:noweb-ref: Windows-Helper-Bindings
:END:
YAS.
#+begin_src emacs-lisp
(defun gcr/ymh-h ()
(define-key yas-minor-mode-map (kbd "M-s-4") 'yas-expand))
(add-hook 'yas-minor-mode-hook 'gcr/ymh-h)
#+end_src
ESS ignore until needed.
ORG.
#+begin_src emacs-lisp
(defun gcr/omh-h ()
(local-set-key (kbd "M-s-h") 'org-babel-check-src-block)
(local-set-key (kbd "M-s-i") 'org-babel-insert-header-arg)
(local-set-key (kbd "M-s-j") 'org-babel-previous-src-block)
(local-set-key (kbd "M-s-k") 'org-babel-next-src-block)
(local-set-key (kbd "M-s-l") 'org-babel-demarcate-block)
(local-set-key (kbd "M-s-;") 'org-babel-view-src-block-info)
(local-set-key (kbd "M-s-b s") 'org-babel-switch-to-session)
(local-set-key (kbd "M-s-b c") 'org-babel-switch-to-session-with-code)
(local-set-key (kbd "M-s-o") 'org-babel-execute-maybe)
(local-set-key (kbd "M-s-t") 'org-babel-tangle)
(local-set-key (kbd "M-s-x") 'org-babel-do-key-sequence-in-edit-buffer)
(local-set-key (kbd "M-s-w w") 'org-export-dispatch)
(local-set-key (kbd "M-s-") 'org-babel-execute-buffer)
(local-set-key (kbd "M-s-i d") 'org-display-inline-images)
(local-set-key (kbd "M-s-i r") 'org-remove-inline-images))
(add-hook 'org-mode-hook 'gcr/omh-h)
#+end_src
Emacs-lisp.
#+begin_src emacs-lisp
(defun gcr/emh-h ()
(local-set-key (kbd "M-s-l eb") 'gcr/elisp-eval-buffer)
(local-set-key (kbd "M-s-l ep") 'eval-print-last-sexp)
(local-set-key (kbd "M-s-l td") 'toggle-debug-on-error)
(local-set-key (kbd "M-s-l mef") 'macroexpand)
(local-set-key (kbd "M-s-l mea") 'macroexpand-all)
(local-set-key (kbd "M-s-p") 'gcr/describe-thing-in-popup)
)
#+end_src
Various.
#+begin_src emacs-lisp
(global-set-key (kbd "M-s-d h") 'diff-hl-mode)
(global-set-key (kbd "M-s-d e") 'vc-ediff)
(global-set-key (kbd "M-s-d d") 'vc-diff)
(global-set-key (kbd "M-s-d u") 'vc-revert)
(global-set-key (kbd "M-s-2") 'gcr/two-key-map)
(global-set-key (kbd "M-s-p") 'gcr/describe-thing-in-popup)
(global-set-key (kbd "M-s-") 'gcr/smart-open-line)
(global-set-key (kbd "M-s-7") 'gcr/insert-timestamp*)
(global-set-key (kbd "M-s-") 'gcr/text-scale-increase)
(global-set-key (kbd "M-s-") 'enlarge-window)
(global-set-key (kbd "M-s-") 'shrink-window)
(global-set-key (kbd "M-s-") 'enlarge-window-horizontally)
(global-set-key (kbd "M-s-") 'shrink-window-horizontally)
#+end_src
Polymode ignore until needed.
*** AutoHotKey
AHK has been fragile in these ways:
- Wheel even mapping works fine for a day and quits working
- It hasn't worked since
- Putting the configuration file in =~/Documents= works
- Putting it in =~/= does not work
- Sometimes the left control and caps-lock swap gets reversed
- Observations
- Using this setup worked perfectly for a while because I used it only on my
home machine
- Once I used it for a while at work that changed everything because
- The keyboard was layed out differently
- 99% of my work was inside of VMWare
- With that in mind I set up the two different profiles
- They need to be refactored, and splitting them up is the first step
- AHK seems to make itself when running both in the host and in a guest VM
- The caps-lock swap often becomes confused and the caps lock turns on causing
hilarious consequences
- For this reason, there are two configurations
- One for Windows "on the metal"
- One for Windows "on a VM"
Fixes:
- Rebooting
[[http://www.autohotkey.com/docs/Hotkeys.htm][Hotkey documentation.]]
- =#=: Windows logo key
- =!=: Alt
- =^=: Control
- ~+~: Shift
I could not disable the Windows key on Windows 7. I made many attempts and all
failed. When I try some s-l and lock the screen I need to remember that I've got
a binding on M-s-l. That patterns remains the same. The bindings that I removed
follow: the correct binding and a failed remedy. The problem is that Windows
processes the key events before they reach AHK.
**** Common Config
:PROPERTIES:
:noweb-ref: AutoHotKey-Common-Config
:END:
#+begin_src sh
Capslock::LCtrl
LCtrl::CapsLock
Enter::RCtrl
,*RCtrl::Enter
,*AppsKey::Enter
#b::!#b
#d::!#d
#e::!#e
#l::!#l
#p::!#p
#t::!#t
^+l::#l
#+end_src
**** OTM Config
#+begin_src src :tangle AutoHotKeyOTM.ahk :comments no
WheelUp::
Send {WheelDown}
Return
WheelDown::
Send {WheelUp}
Return
«AutoHotKey-Common-Config»
#+end_src
**** OAV Config
After months of trial and error, I decided that I will make this work. What I
mean is that the bindings should be the same whether AHK is running OTM or OAV.
The one thing that never seems to work is the these wheel mouse bindings. So,
they are in OTM and not OAV. This is good because they are nearly identical.
#+begin_src src :tangle AutoHotKeyOAV.ahk :comments no
«AutoHotKey-Common-Config»
#+end_src
** OSX
[[https://pqrs.org/osx/karabiner/][Karabiner]] provides a quite perfect /Return to Control_L (+ When you type Return
only, send Return)/ to make the return key send "return" when struck and released
and to act as the "control" key when held and chorded.
*** Keyboard
- Use all F keys as standard function keys: yes
Modifier keys:
- caps lock \rarr control
- control \rarr caps lock
- option \rarr option (apple style)
- command \rarr command (apple style)
- Shortcuts
Alone, F11 and F12
=Apple->System Preferences->Keyboard->Shortcuts->Mission Control= un-check "Show Desktop" =F11= and "Show Dashboard" =F12=.
Mission Control, F1 and F8
=Apple->System Preferences->Keyboard->Shortcuts->Keyboard= un-check "Turn keyboard access on or off" =^F1= and "Move focus to status menus" =^F8=.
- <2015-03-29 Sun>
- Better yet, [[https://github.com/grettke/osx-provision][automate]] most of this.
* Reminders
- *NEVER* edit source blocks outside of their editor mode
- *Guaranteed* issues will occur if it is LISP
- Treat source blocks amazingly delicately and thoughtfully
because if you don't then you will break your system
- The flow is
- First make the new changes directly in the code
- Verify that they work
- *Then* place them in this document
- Only use in-line footnotes unless your document is very very small
- Footnotes in org-mode are really, really great. Before you really get into using
them, take a bit of time to think about how you want to use them.
- If you have 5 footnotes or less, then don't think anymore about it. If more then
read on.
- This topic is not unique to org first of all, it just isn't something that you
consider much until it is too late. Once you get into the org life-cycle, you start
tossing and slinging document and code fragments with ease, especially while
re-factoring. This is all find and well, until you realize that your footnotes will
be left sad and alone, abandoned for some cruel fate. In particular, it will break
your document.
- The better way is to define them all in-line; that will allow simple and easy
re-factoring in a quite pleasant manner.
- No comments in generated source code ever; barring a few special cases.
- Always keep every kind of URL in a form that you may tell Ispell to ignore
else you will get lose in the jungle of spell-checking and quit doing it.
- For key, always use a finger that doesn't require a stretch or hand reposition.
For example, I can use my "ring finger" to reach =-=, ~=~, and =DEL= so I
should never stretch to do that with my "pinkie".
- There are modes like ergoemacs [fn:6218cfd6: https://ergoemacs.github.io/] for
doing this gradually
* Confessions
<2014-11-20 Thu T10:56:21>
Looking back and this document, I am getting jealous of the clean and concise
/final documents/ that people present on their ideal configurations. I wonder how
they communicate the value of their approach, and do so without covering the
whole history of their approach that demonstrates why their approach is ideal.
Case in point, this document. I thought about reducing it to an
/optimized version/ that was /lightweight/ and /fresh/. I had no reason to do this, of
course, just the desire. Without thinking too deeply, I started looking at where
I might /trim the fat/. Very, very quickly, I found that I could not make sense of
any of the configuration *without* the history of why I made that configuration.
Don't get me wrong, I can read English and read the APIs, so I know the
functions and variables are. What I'm saying here is that, I don't remember why
I did it /this/ way instead of the five other ways that would also have worked.
Those things that I did not do, make what I do, valuable. The document is taking
on a new form, as a friend, and record-keeper, and story-teller, and without
those friends, this document becomes little more than a configuration file that
can very easily be converted to HTML! This has and continues to be a fascinating
experience!
<2014-11-22 Sat>
There are have actually been many versions of this system. I think that I
touched on them up above well enough. More have come and gone, though. Perhaps
they are not worth mentioning? What is worth mentioning is the motivation for
those tangents (branches, at best). This idea, this desire, crept into my mind
that I could "do it better". That is a fine idea, that is why we accomplish
anything in life, because of the desire. The thing is that when I sought to
satisfy that desire, it became clear that at best it was the wrong time and at
worst there was no value to that desire. Now, still, it manifests in the form of
"I should create a totally stable and /professional/ system!". To what end? Well,
there is a real end, I never want the system to break after an update because I
want to collaborate with others and I never want them to see breakage. So, that
is a fine reason. The approach is where I got it wrong. Yet again, for at least
the third time, I wanted to do a total "clean slate" re-write of this system.
Generally, the rewrite starts out well and goes well because my mastery of the
tools is better than before. The problem is that the tools just don't
c-synchronize correctly together (non-technical term). They just don't gel
together right and things don't wory right in very, very bizarre ways. Mostly it
has to do with package loading. After a few hours, I blow away the changes and
try again. The more I work, the more I feel like this system is an organic
entity, the product of thousands, that has its own ebb and flow, and pushing it
in one direction versus another yields often time pleasant and other time quite
surprising results. I will focus on that which I am in control of, how *I* react,
and move this forward a little more slowly.
<2014-11-22 Sat>
Oops I did it again, I made changes to the generated files, tested them, and
didn't bring them back into the source file (this document). When I get tired,
that happens.
This goal of making things easier has been quite an adventure. It revealed a lot
about myself and the tech. I am still human, and that is fine. None of the tools
will think for you, so you definitely need to have a plan or no tool will ever
succeed (more reports from captain obvious live on the 6 o'clock news!).
The richness of the Emacs ecosystem is so vast and varied. There is so much, and
so little, that you /need/ to know to be productive. It is kind of magical and
mysterious, if you are open to seeing it at least.
The more I think about it, I am just telling myself stories about reuse, here.
There isn't really a need. No one else will re-use it. The value would be in the
collaboration, not the tool. Why does the desire always precede the reason?
<2015-01-03 Sat>
Since the passage on the means of this system was capture… things have been
content, and, quiet. I greatly, greatly look forward to enjoying collaborations
with other people, expressing their selves, too, in the future.
<2015-01-03 Sat>
Added three new headings under one second-level heading.
Before the addition:
=Tangling complete after: 43.274528 seconds=
After the addition:
=Tangling complete after: 43.953333 seconds=
# LocalWords: Savehist emacs fu API sudo MELPA purcell bbatsov ELPA LCO AHK
# LocalWords: VM