Showing 89 to 92

Emacs tips

#emacs

describe-prefix-bindings

Woah! When was this introduced? Why did no one tell me? Emacs essentially ships a which-key. With vertico/helm/ivy, it's pretty elegant. After typing a prefix, such as C-x, type C-h or ? or F1.

Tips on usage

Do it right the first time around🔗

Duncan, have I not told you that thinking you know something is the most perfect barrier against learning?

–Leto II Atreides

You tend to use the solution you know. If you can copy-paste by pointing and clicking in a certain way, you'll use that solution next time, and the time after that, even if there is a better way.

Knowing a trick bars learning new tricks.

That's why it's best to learn the best way to do it the first time around.

Auto-save-visited-mode in the tens🔗

It's the 2010s. Several operating system have auto-save by default on everything. And it is nice. Think about it: if you learned today the answer to the question, what is a "save" operation?

"Oh, a low-level behind-the-scenes function. What, you want me to call it manually every time? It was obviously written for use in scripts, not for binding to a hotkey. How odd that it comes bound by default, was the keybind designer even an user? I'll automate it away."

(auto-save-visited-mode)
(global-unset-key (kbd "C-x C-s"))
(global-unset-key (kbd "C-x s"))

Constantly learn something difficult🔗

The Tao of Emacs is to constantly be learning something difficult.

The tutorial is your first hurdle, though fortunately the most frustrating. You'll be settling down into a habit of taking on such hurdles, of sitting down with the manual and learning. Whether you learn about a built-in package, like Calc, an external package like Helm, or even a community config like Spacemacs, it's always the same story. It's like being back in the tutorial. "How does any of this work?"

And that's a good thing.

The secret to improving at a skill is to retain some degree of conscious control over it while practicing–to force oneself to stay out of autopilot.

– Moonwalking with Einstein: The Art and Science of Remembering Everything

The above principle, called deliberative practice, is why some say to avoid repetitive tasks in Emacs, and find the smart, efficient way to do each and every thing. Unless you're in the middle of a conference, you almost certainly have time, and it will pay off.

Suppose you want to stand on the shoulders of giants, to find the best way to interact with a computer, by co-opting all the best things other people have done. The first step is to get Emacs. That's where people like you have always went, so there's a lot of prior work in its ecosystem not present elsewhere.

Suppose further that after all the cards are down, you want to end up ahead of someone who sticks with "software for the masses", i.e. you want the time investment to pay off. It's not easy, because Emacs can invite yak-shaving and NIH syndrome, but even aside from that, it may never pay off for you if you postpone learning smart tricks in favour of familiar methods.

Want to save time?

  • Don't get distracted by attempts to get your color theme or modeline just so. Though it can feel like learning, it's a whole different class of activity from going through the Calc manual.
  • Learn the popular packages early. I mean packages like smartparens, yasnippet. It's the gift that keeps on giving. It's also painful to see a five-year Emacs user still be managing parens manually.
    • Learn them all, don't defer something until five years later. Think of it like catching Pokemon. The tutorial is your first Pokemon, and smartparens is maybe your second or fifth or fifteenth pokemon. But you must catch a few hundred before you can think of slowing down. There's that much useful stuff! Invest, it gives compound interest.
  • Quit having premature opinions. If someone else's figured out a neat way to do things, hop in the fire and learn their way. Afterward, it's OK to have an opinion.
  • To minimize NIH syndrome and the amount of private code (to which no-one can contribute), maintain your configuration on top of someone else's and submit patches upstream. You'll probably migrate several times, encountering a ton of solutions you wouldn't otherwise. That means you will be a whiz at Git and Magit.
    • Try to co-opt their way as much as possible every time, making your own config as small a "delta" as possible. It's painful, bur your neurons will add the necessary connections, and then it will be banal.
  • Spin packages out of your own code to reduce the amount you have to maintain alone.
  • Blog about neat tricks you discover. This both helps other people, and helps you.

The Eshell manual says this:

The role of a command shell is to give you more control over what your computer does for you. Not everyone needs this amount of control, and it does come at a cost: Learning the necessary script commands to express what you want done. A complicated query, such as [an example above this paragraph], takes time to learn. But if you find yourself using your computer frequently enough, it is more than worthwhile in the long run. Any tool you use often deserves the time spent learning to master it.

Decide if you agree with that sentence: "Any tool you use often deserves the time spent learning to master it."

When it comes to the tool that is your computer, a fully general information-processing system, that you use often
 worth it?

Do not be a purist unnecssarily

Unless you are using EXWM, do not be a purist. For example, instead of learning about Emacs 27's tabs facility and taking months to decide on a hotkey for it because you have a hundred other Emacs facilities to learn about at the same time, spawn a new Emacs frame when you need a new "tab" (did you realize they can all be fullscreened simultaneously?) and use the foreign window manager's ability to switch between frames of the same app. In GNOME, that's M-`. It's quick to get started with and works predictably.

List from a set of lines

I looked for a function that would make an Org list out of a set of lines. I found something much more general. Let that be a lesson: when a package hasn't included a way to do a thing, perhaps that's because Emacs already ships a general way to do things of that sort.

For example, rectangle-mark (C-x SPC) the beginnings of these lines:

line1
line2
line3
line4
line5

Then do C-t (string-rectangle) and write "- " or anything you want.

Tips for initfiles

sentence-end-double-space🔗

So, this little guy, sentence-end-double-space. You know it, right? From the Emacs manual:

If you want to use just one space between sentences, you can set the variable ‘sentence-end-double-space’ to ‘nil’ to make the sentence commands stop for single spaces. However, this has a drawback: there is no way to distinguish between periods that end sentences and those that indicate abbreviations. For convenient and reliable editing, we therefore recommend you follow the two-space convention. The variable ‘sentence-end-double-space’ also affects filling.

If you look closely, you can see the double spaces in that very quote.

This has its roots in the era of typewriters. When I first learned of it, I thought it might be nice and endeavored to follow it, but ran into a big issue. Namely:

  • when the variable is true, sentences that don't end in a double space get skipped over by commands like forward-sentence and kill-sentence. Lots of people only type one space, so that's inconvenient when I edit their files.
  • when the variable is nil, every double space I write gets eliminated by fill-paragraph.

So I gave up, and joined the one-space crowd.

I thought there should be a way to modify fill-paragraph, but my Lisp-fu wasn't up to it back then. It just goes to show how little the non-Lisper is able to do in Emacs. Here's the solution:

(defun my-fill-paragraph-noclobber ()
  "Like `fill-paragraph', but pretend that
`sentence-end-double-space' is non-nil to avoid clobbering
existing double spaces."
  (interactive)
  (let ((sentence-end-double-space t))
    (call-interactively #'fill-paragraph)))

Or if you like unfill-toggle (that MELPA package is only three small defuns, by the way):

(defun my-fill-unfill-respect-double-space ()
  "Toggle filling/unfilling of the current region, or current
paragraph if no region is active.  Also pretend that
`sentence-end-double-space' is non-nil to avoid clobbering
existing double spaces. See `fill-paragraph' for what a prefix
command will do."
  (interactive)
  (let ((deactivate-mark nil)
        (fill-column (if (eq last-command this-command)
                         (prog1 most-positive-fixnum
                           (setq this-command nil))
                       fill-column))
        (sentence-end-double-space t))
    ;; For whatever reason, `fill-paragraph-function' does not get consulted in
    ;; org buffers, so we have to do this manually, even though we don't have
    ;; to call `lisp-fill-paragraph' explicitly in lisp buffers.
    (if (eq major-mode 'org-mode)
        (call-interactively #'org-fill-paragraph)
      (call-interactively #'fill-paragraph))))

Easy check for initfile errors before you restart🔗

(defun my-compile-and-drop ()
  "Compile buffer to see any errors, but don't write an .elc.
Original inspiration was to catch erroneous sexps
like (global-set-key \"c-x c\"...) that would break init, not for nitpicking things
that work, so `byte-compile-warnings' is temporarily overridden."
  (interactive)
  (when (eq major-mode #'emacs-lisp-mode)
    (cl-letf ((byte-compile-dest-file-function (lambda (_) (null-device)))
              (byte-compile-warnings '(suspicious))
              (inhibit-message t))
      (byte-compile-file (buffer-file-name)))))

(add-hook 'after-save-hook #'my-compile-and-drop)

Repeat last command N times

You know about numeric arguments – typing C-u 8 M-t or M-8 M-t would call M-t 8 times.

I'm not good at planning ahead like this. I'd rather choose how many times to do it after the fact. I'm fond of the repeat command, but it has to be spammed to do it many times – it does not take a numeric argument!

Assuming that we have the following key bindings (because putting them under a chord is insane)

  • <f1> for universal-argument
  • <f2> for repeat

the normal command sequence would look like

f1 8 M-t

and you could easily patch repeat to take a standard numeric prefix, enabling

M-t f1 8 f2

but I want a numeric postfix, enabling

M-t f2 8

The following snippet lets you do just that. Unfortunately it's limited to repeating up to 9 times, if you can extend it please teach me! I think typing e.g. 90 should first repeat 9, then undo 9 times and repeat 90 times instead.

(defun repeat-digit-times ()
  "Repeat the last command an amount of times, only up to 9
  because this command only works when you bind it to the keys 0-9.
  To do something 10 or more times, use the usual digit arguments."
  (interactive)
  ;; bits pasted from `repeat'
  (when (eq last-repeatable-command 'repeat)
    (setq last-repeatable-command repeat-previous-repeated-command))
  (when (eq last-repeatable-command 'repeat-digit-times)
    (message "I thought it was impossible to end up here"))
  ;; bits pasted from `digit-argument'
  (let* ((char (if (integerp last-command-event)
                   last-command-event
                 (get last-command-event 'ascii-character)))
         (digit (- (logand char ?\177) ?0)))
    (dotimes (i digit) (call-interactively #'repeat))))

(setq post-repeat-map (make-sparse-keymap))
(dotimes (i 10)
  (define-key post-repeat-map (kbd (int-to-string i)) #'repeat-digit-times))

(defun enable-post-repeat-map ()
  (set-transient-map post-repeat-map))

;; (add-function :after #'repeat #'enable-post-repeat-map)

A builtin way of doing this would be a keyboard macro; apparently, calling <f4> (kmacro-end-or-call-macro) with a numeric prefix 8 will run the macro 8 times. However, it's too many keystrokes:

M-t f3 f2 f1 8 f4

Eshell: prompt with timestamp

Not a big fan of long file paths in the prompt. We have the modeline for that. So I change the prompt to something more appropriate: a timestamp.

It's not straightforward. Everyone who has had the bright idea of a timestamped command prompt has run into the issue of updating it when you run a command, so that the timestamp accurately matches the time you ran it instead of the time the prompt appeared on screen, which could have been days ago. Here you go. (setc embark-prompter #'embark-completing-read-prompter)

(defun my-eshell-timestamp-update ()
  "When added to `eshell-pre-command-hook', the first string --:-- in the
prompt becomes a timestamp like 13:59 after you run a command."
  (save-excursion
    (forward-line -1)
    (when-let* ((unfilled-timestamp "--:--")
                (end (search-forward unfilled-timestamp nil t))
                (beg (- end (length unfilled-timestamp)))
                (inhibit-read-only t))
      (delete-region beg end)
      (insert (format-time-string "%H:%M"))
      (add-text-properties beg (point) '(font-lock-face eshell-prompt)))))

(with-eval-after-load 'eshell
  (add-hook 'eshell-pre-command-hook #'my-eshell-timestamp-update)
  (setq eshell-prompt-regexp (rx bol (repeat 7 nonl) " Sir? ")
        eshell-prompt-function (lambda () (concat "[--:--] Sir? "))))

Universal key for universal arg

This snippet is particularly justified with my as yet unpublished package github.com/meedstrom/deianira.

(my-before-keybinds
  ;; Normally, only C-u does universal-arg. Bind M-u and others too. Now we can do
  ;; M-u 5 M-f instead of C-u 5 M-f.
  (general-def "s-u"   #'universal-argument)
  (general-def "M-u"   #'universal-argument)
  (general-def "C-M-u" #'universal-argument)

  ;; general-def doesn't work with (format)
  (dolist (x (string-to-list "1234567890"))
    ;; Unbind C-1234567890 and co. Too good to waste on `digit-argument'.
    (global-unset-key (kbd (format "C-%c" x)))
    (global-unset-key (kbd (format "M-%c" x)))
    (global-unset-key (kbd (format "C-M-%c" x)))
    ;; After C-u/M-u/s-u, ensure that holding down the modifier makes no diff.
    ;; Now we can do M-u M-5 M-f as well as M-u 5 M-f.
    (define-key universal-argument-map (kbd (format "C-%c" x))   #'digit-argument)
    (define-key universal-argument-map (kbd (format "M-%c" x))   #'digit-argument)
    (define-key universal-argument-map (kbd (format "C-M-%c" x)) #'digit-argument)
    (define-key universal-argument-map (kbd (format "s-%c" x))   #'digit-argument)))

Toggle abnormal parts of config

(defvar my-normie-p nil)

(defun my-normie-toggle ()
  (interactive)
  (if my-normie-p (my-abnormalize) (my-normalize)))

(defun my-normalize ()
  (interactive)
  (setq my-normie-p t)
  (cua-mode)
  (abbrev-mode 0)
  (show-paren-mode 0)  ;; problem: this is buffer local
  (show-smartparens-global-mode 0)
  (global-company-mode 0)
  (rainbow-delimiters-mode 0)
  (objed-mode 0)
  (when-fbound* (aggressive-indent-mode 0))
  ;; (global-unset-key (kbd "<f13>"))
  ;; (global-unset-key (kbd "<f14>"))
  ;; (global-unset-key (kbd "<f15>"))
  (define-key key-translation-map (kbd "[") nil)
  (define-key key-translation-map (kbd "]") nil)
  (define-key key-translation-map (kbd "(") nil)
  (define-key key-translation-map (kbd ")") nil)
  ;; (my-disable-all-themes)
  ;; (load-theme 'base16-darktooth t)
  ;; (my-theme-mods)
  )

(defun my-abnormalize ()
  (interactive)
  (setq my-normie-p nil)
  (cua-mode 0)
  (when (featurep 'objed)
    (objed-mode))
  ;; we should keep track of the buffer where we turned normie on and reenable buffer-local things there specifcially
  ;; (my-reenable-when-default abbrev-mode) ;; started causing error for no reason
  (global-company-mode)
  (show-paren-mode)
  ;; cries about unknown variables
  ;; (my-reenable-when-default show-smartparens-mode)
  ;; (my-reenable-when-default aggressive-indent-mode)
  (define-key key-translation-map (kbd "[") (kbd "("))
  (define-key key-translation-map (kbd "]") (kbd ")"))
  (define-key key-translation-map (kbd "(") (kbd "["))
  (define-key key-translation-map (kbd ")") (kbd "]"))
  )

What has triggered me into learning🔗

  • Typing filenames by hand e.g. in the shell
    • Problem: I know Emacs ought to be able to know which filename I want, because it's open in another buffer
    • Solution: my-insert-other-buffer-file-name, or a properly customized hippie-expand/company
  • Multiline flashcard (org-drill/anki-editor) entries
    • Problem: Why did I experience that as so much worse than a simple list?
    • Solution: Learn some hotkeys for navigating Org headings
      1. Jump to parent headline (cognate to sp-backward-up-sexp?)
      2. Jump to next headline (cognate to sp-next-sexp?)
      3. Jump to next headline of upper level (composition of 1 & 2) (cognate to sp-up-sexp?)
      4. Jump to child headline (cognate to sp-down-sexp?)
  • Skimming many files in a directory
    • Problem: Not fun typing C-x C-f and scrolling thru the list all over again for each file
    • Solutions:
      • next-file-in-dir
      • learn that dired can open many files at once. Then next-buffer or quit-window to leaf thru them
  • Having to call async-shell-command to run a program to open a file whose name is right there (in dired for example)
    • Problem: Not as convenient as a normal file manager, which can just double click
    • Solution: my-dired-open-file-with-default-tool or crux-open-with
  • Browsing a filesystem tree with C-x C-f, then realizing I want to open the candidate location in a shell instead
    • Solution: embark, or just rapid switch between dired and shell
  • My problem with org-fc, org-noter

Documentation ideas

delete-blank-lines and just-one-space are cognates

Should have docstring tips about each other. See also join-line.

Created (3 years ago)

Writing

Some links on writing:

From Paul Graham's Writing, Briefly:

I think it's far more important to write well than most people realize. Writing doesn't just communicate ideas; it generates them. If you're bad at writing and don't like to do it, you'll miss out on most of the ideas writing would have generated.

As for how to write well, here's the short version: Write a bad version 1 as fast as you can; rewrite it over and over; cut out everything unnecessary; write in a conversational tone; develop a nose for bad writing, so you can see and fix it in yours; imitate writers you like; if you can't get started, tell someone what you plan to write about, then write down what you said; expect 80% of the ideas in an essay to happen after you start writing it, and 50% of those you start with to be wrong; be confident enough to cut; have friends you trust read your stuff and tell you which bits are confusing or drag; don't (always) make detailed outlines; mull ideas over for a few days before writing; carry a small notebook or scrap paper with you; start writing when you think of the first sentence; if a deadline forces you to start before that, just say the most important sentence first; write about stuff you like; don't try to sound impressive; don't hesitate to change the topic on the fly; use footnotes to contain digressions; use anaphora to knit sentences together; read your essays out loud to see (a) where you stumble over awkward phrases and (b) which bits are boring (the paragraphs you dread reading); try to tell the reader something new and useful; work in fairly big quanta of time; when you restart, begin by rereading what you have so far; when you finish, leave yourself something easy to start with; accumulate notes for topics you plan to cover at the bottom of the file; don't feel obliged to cover any of them; write for a reader who won't read the essay as carefully as you do, just as pop songs are designed to sound ok on crappy car radios; if you say anything mistaken, fix it immediately; ask friends which sentence you'll regret most; go back and tone down harsh remarks; publish stuff online, because an audience makes you write more, and thus generate more ideas; print out drafts instead of just looking at them on the screen; use simple, germanic words; learn to distinguish surprises from digressions; learn to recognize the approach of an ending, and when one appears, grab it.

Is there a boilerplate preamble for science papers?🔗

I was thinking of inserting something like this in my next science articles and writing in active voice, breaking the norm. By Yudkowsky:

Journal articles are often written in passive voice. (Pardon me, some scientists write their journal articles in passive voice. It's not as if the articles are being written by no one, with no one to blame.) It sounds more authoritative to say "The subjects were administered Progenitorivox" than "I gave each college student a bottle of 20 Progenitorivox, and told them to take one every night until they were gone." If you remove the scientist from the description, that leaves only the all-important data. But in reality the scientist is there, and the subjects are college students, and the Progenitorivox wasn't "administered" but handed over with instructions. Passive voice obscures reality.

Often when I read a study in the passive voice, I will anyway want to ask "and how did you administer Progenitorivox? When? What words did you use? What order did you talk to the subjects in? Why? Where?", so it is not wasted verbiage to include all that from the start. Actually it compresses the writing, as much of the information is communicated implicitly when you use active voice, so there is no need to write a sequence of passive-voice statements like "The location was
 The time was
 The method was
". A third argument is that it's generally more pleasant to read, which should be a high goal of any scientific writing: what's not accessible to laymen may as well not exist (it scares off indie peer-review, will not be understood even by those in your field, will not spread, etc). Sure, this isn't fiction you're writing, but fiction is written to be easy to read, so your article should read like fiction as far as possible; saying it looks like fiction is the same as saying it's well-written!

And here's Orwell:

When one watches some tired hack on the platform mechanically repeating the familiar phrases—bestial, atrocities, iron heel, bloodstained tyranny, free peoples of the world, stand shoulder to shoulder—one often has a curious feeling that one is not watching a live human being but some kind of dummy
 A speaker who uses that kind of phraseology has gone some distance toward turning himself into a machine. The appropriate noises are coming out of his larynx, but his brain is not involved, as it would be if he were choosing his words for himself


What is above all needed is to let the meaning choose the word, and not the other way around. In prose, the worst thing one can do with words is surrender to them. When you think of a concrete object, you think wordlessly, and then, if you want to describe the thing you have been visualising you probably hunt about until you find the exact words that seem to fit it. When you think of something abstract you are more inclined to use words from the start, and unless you make a conscious effort to prevent it, the existing dialect will come rushing in and do the job for you, at the expense of blurring or even changing your meaning. Probably it is better to put off using words as long as possible and get one's meaning as clear as one can through pictures and sensations.

Which would not affect the article's style visibly to others, but has implications for how to write and read articles. Be aware that a researcher may just be stringing words together and letting the words do a portion of their thinking. There's a second reason to be skeptical of recycled prose: it indicates the author has other purposes in mind than research, e.g. graduating or getting published. And when you want to describe your research, ask yourself "What did you research? Was it useful? Do you care about it? How was it done? Were the methods good? What information do you want to give to humankind?" and for each answer, do not think any words.

And there's something Jaynes said about backing up proofs overmuch. But that's for another day.

Related

  • English

What links here

Created (3 years ago)

What you can't say

Paul Graham has a seminal essay (paulgraham.com/say.html). A short quote by C. S. Lewis touches on the same area:

Every age has its own outlook. It is specially good at seeing certain truths and specially liable to make certain mistakes. We all, therefore, need the books that will correct the characteristic mistakes of our own period. And that means the old books. All contemporary writers share to some extent the contemporary outlook—even those, like myself, who seem most opposed to it. Nothing strikes me more when I read controversies of past ages than the fact that both sides were usually assuming without question a good deal which we should now absolutely deny. They thought that they were as completely opposed as two sides could be, but in fact they were all the time secretly united—united with each other and against earlier and later ages—by a great mass of common assumptions. We may be sure that the characteristic blindness of the twentieth century—the blindness about which posterity will ask, “But how could they have thought that?”—lies where we have never suspected it, and concerns something about which there is untroubled agreement between Hitler and President Roosevelt or between Mr. H. G. Wells and Karl Barth. None of us can fully escape this blindness, but we shall certainly increase it, and weaken our guard against it, if we read only modern books. Where they are true they will give us truths which we half knew already. Where they are false they will aggravate the error with which we are already dangerously ill. The only palliative is to keep the clean sea breeze of the centuries blowing through our minds, and this can be done only by reading old books.

(Disclaimer: I don't know much about C.S. Lewis beyond the above quote)

It's funny because we can obviously find at least two other categories to read as palliatives. C. S. Lewis was open to reading different times, but I presume he still only exposed himself to the perspectives of European men, since that
 is what tends to happen when an European reads old books. Different times, but not different places, nor different perspectives in his own time, like those of women or minorities or other cultures. The scary part is I can believe that those palliatives didn't even occur to him.

Related

What links here

Created (3 years ago)

ESS4

#emacs

  • C-c C-p
  • C-c C-d a (ess-display-help-apropos)
  • C-c C-d v (ess-display-vignettes)

Do not ever print out ?help output in the R console. Use C-c C-v (ess-help). Once showing help for some object you can also press a to do apropos (??) search or v to display vignettes.

Do not ever type R code to install packages. Use C-c C-e i (ess-install-library) or ess-devtools-*.

Wanna find out more commands? Place cursor in the console, do <f1 b> (counsel-describe-bindings), type "ess".

For each command you're curious about, spawn a buffer with C-M-m or use ivy-resume to get back to the ivy prompt.

Created (3 years ago)
Showing 89 to 92