3

macOS's text input system has long supported custom keyboard shortcuts via ~/Library/KeyBindings/DefaultKeyBinding.dict. I have used this successfully for years to make text editing more Emacs-like, but there is one feature I have never been able to get to work: the yankAndSelect: method. It never cycles through the kill ring for me; it always only yanks the last-killed item. I am looking for help to make it work.

Here is how I tested it. First, I set NSTextKillRingSize using this command in a terminal:

defaults write -g NSTextKillRingSize -int 20

(I've also tried -string instead of -int in the command above, but it makes no difference in the behavior.) Next, I removed everything from my DefaultKeyBinding.dict file and left only this:

{
  "^y" = (yankAndSelect:);
}

Note that I leave controlk bound to its default text system action (which is to kill to the end of the line). Finally, I rebooted, just to be absolutely sure nothing unexpected persisted.

Based on many sources, such as Apple's documentation, the two documents on customizing the Cocoa text system and the list of selectors by Jacob Rus from 2006, Brett Terpstra's KeyBindings, and random other people's pages on the web, it seems that the following behavior should be seen (as described by Brett Terpstra):

  1. Open TextEdit (restart it if it was already open)
  2. Type a line of text, move the cursor to the start of the line, type controlk
  3. Write another line with different text, and repeat step 2
  4. Do it one more time
  5. On a blank line, type controly. This should paste the last line you killed
  6. Type controly again, and the pasted text should be replaced by the second line you killed
  7. Again, and you should see the first line. Continuing repetitions will cycle through the kill ring.

This is not what happens in my use. Instead, what happens is that step #6 does not paste the 2nd-to-last kill, but rather the most recent (3rd) kill – always. It is as if there is no kill ring at all, and yankAndSelect: always only yanks the most recent kill.

This is 100% repeatable behavior in every system (macOS 10.13, and an almost-fresh 10.14 VM) and every application that respects DefaultKeyBinding.dict (not only TextEdit) that I've tried.

What more must be done to get yankAndSelect: to cycle through the kill ring?

1
  • Interestingly, it seems to work properly if you write the preference just for a single app. For instance, defaults write com.apple.TextEdit NSTextKillRingSize -string 5 causes the kill ring to work properly just in TextEdit. So it might be some sort of issue with global preferences.
    – aaplmath
    Dec 29, 2020 at 1:22

1 Answer 1

2
+100

Update: It seems that on some versions of macOS, setting the configuration globally doesn't work; instead, use defaults write com.apple.TextEdit NSTextKillRingSize -string 6 (replacing com.apple.TextEdit with the desired application and 6 with the desired kill ring size) to set it on a per-app basis. Additionally, it appears that NSTextKillRingSize must be no greater than 16 or it will not work.


Original answer:

The issue appears to lie in how the defaults CLI handles the global defaults domain. Specifically, you want to write to the correct host's global defaults (i.e., yours), which it seems doesn't occur by default. (I still don't fully understand the intricacies of how all this works.) To accomplish this, replace your current defaults write command with the following:

defaults -currentHost write -g NSTextKillRingSize -string 6

This worked for me on Big Sur 11.1.

7
  • I appreciate this effort. The command does not seem to work for me (on 10.13.6), nor the other variant using the specific app code, but I want to do more testing with another computer, clean environment, rebooting, etc. It's hopeful to have confirmation that it still does work for recent OSes, at least for other people!
    – mhucka
    Dec 31, 2020 at 1:26
  • @mhucka One thing I've noticed is its "cycling" behavior is somewhat erratic—if you press control+y multiple times consecutively (i.e., without pressing return/deselecting the text) with several items in the kill ring, does it cycle through them then?
    – aaplmath
    Dec 31, 2020 at 22:04
  • No; in fact, pressing it consecutively is actually what I've been doing all along. (Leaving the selected text selected is what I assumed one had to do in order to get it replaced with the previous yank.)
    – mhucka
    Jan 1, 2021 at 18:06
  • SOLVED. You're not going to believe this. If you use a value greater than 16, it does not work; if you use 16 or less, it works. In addition, I have to use the version in your earlier comment (defaults write com.apple.TextEdit ... rather than defaults -currentHost write), but with that combination, it worked everywhere I tried it on 10.13 and 10.14. If you could update this answer to say something about the single app vs. -currentHost, I'll be happy to award the bonus.
    – mhucka
    Jan 1, 2021 at 18:49
  • 1
    Aha! I actually originally used 6 in my answer and then changed it to 20 to match yours…whoops! I'll update my answer.
    – aaplmath
    Jan 1, 2021 at 18:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .