├── Images ├── full-kb-opt-shift.png ├── full-kb-opt.png ├── full-kb-shift.png ├── full-kb.png ├── incremental-search.png ├── keyboard-pref-pane.png ├── laptop-kb-fn-numpad.png ├── laptop-kb-fn.png ├── laptop-kb-opt-shift.png ├── laptop-kb-opt.png ├── laptop-kb-shift.png └── laptop-kb.png ├── KeyBindings ├── BBEdit Bindings.dict ├── Emacs Esc Bindings.dict ├── Emacs Opt Bindings.dict ├── Greek Bindings.dict ├── Leet Binding.dict ├── Leet Bindings.dict └── Windows Bindings.dict ├── cocoa-text.html ├── cocoa-text.md ├── readme.md ├── selectors.html ├── selectors.md └── system-bindings.html /Images/full-kb-opt-shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/full-kb-opt-shift.png -------------------------------------------------------------------------------- /Images/full-kb-opt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/full-kb-opt.png -------------------------------------------------------------------------------- /Images/full-kb-shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/full-kb-shift.png -------------------------------------------------------------------------------- /Images/full-kb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/full-kb.png -------------------------------------------------------------------------------- /Images/incremental-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/incremental-search.png -------------------------------------------------------------------------------- /Images/keyboard-pref-pane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/keyboard-pref-pane.png -------------------------------------------------------------------------------- /Images/laptop-kb-fn-numpad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/laptop-kb-fn-numpad.png -------------------------------------------------------------------------------- /Images/laptop-kb-fn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/laptop-kb-fn.png -------------------------------------------------------------------------------- /Images/laptop-kb-opt-shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/laptop-kb-opt-shift.png -------------------------------------------------------------------------------- /Images/laptop-kb-opt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/laptop-kb-opt.png -------------------------------------------------------------------------------- /Images/laptop-kb-shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/laptop-kb-shift.png -------------------------------------------------------------------------------- /Images/laptop-kb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrus/cocoa-text-system/2ffe09b683041b6c936b830148f512edba33c470/Images/laptop-kb.png -------------------------------------------------------------------------------- /KeyBindings/BBEdit Bindings.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * 4 | * Key Bindings for partial BBEdit emulation, compiled by Jacob Rus 5 | */ 6 | 7 | 8 | /* Incremental search -- uncomment if ISIM is installed */ 9 | /* "@~f" = "ISIM_incrementalSearch:"; /* A-O-f Quick search */ 10 | /* "@~$f" = "ISIM_reverseIncrementalSearch:"; /* A-O-Shft-f Quick search backward */ 11 | 12 | 13 | /* Select line */ 14 | "@l" = "selectParagraph:"; /* C-l Select line */ 15 | 16 | /* Scrolling */ 17 | "^\UF700" = "scrollLineUp:"; /* C-up Scroll up */ 18 | "^\UF701" = "scrollLineDown:"; /* C-down Scroll down */ 19 | "@^\UF700" = ( "scrollLineUp:", /* A-C-up Scroll up 2 lines */ 20 | "scrollLineUp:"); 21 | "@^\UF701" = ( "scrollLineDown:", /* A-C-down Scroll down 2 lines */ 22 | "scrollLineDown:"); 23 | "~^\UF700" = ( "scrollLineUp:", /* A-C-up Scroll up 3 lines */ 24 | "scrollLineUp:", 25 | "scrollLineUp:"); 26 | "~^\UF701" = ( "scrollLineDown:", /* A-C-down Scroll down 3 lines */ 27 | "scrollLineDown:", 28 | "scrollLineDown:"); 29 | "@~^\UF700" = ( "scrollLineUp:", /* A-C-up Scroll up 6 lines */ 30 | "scrollLineUp:", 31 | "scrollLineUp:", 32 | "scrollLineUp:", 33 | "scrollLineUp:", 34 | "scrollLineUp:"); 35 | "@~^\UF701" = ( "scrollLineDown:", /* A-C-down Scroll down 6 lines */ 36 | "scrollLineDown:", 37 | "scrollLineDown:", 38 | "scrollLineDown:", 39 | "scrollLineDown:", 40 | "scrollLineDown:"); 41 | 42 | 43 | /* Page up-down */ 44 | "~\UF700" = "pageUp:"; /* O-up Page up */ 45 | "~\UF701" = "pageDown:"; /* O-down Page down */ 46 | "~$\UF700" = "pageUpAndModifySelection"; /* O-Shft-up Select page up */ 47 | "~$\UF701" = "pageDownAndModifySelection"; /* O-Shft-down Select page down */ 48 | 49 | 50 | /* delete backward-forward */ 51 | "$\U007F" = "deleteForward:"; /* Shft-Del Delete forward */ 52 | "~\U007F" = "deleteWordBackward:"; /* O-Del Delete word backward */ 53 | "~\UF728" = "deleteWordForward:"; /* O-FwdDel Delete word forward */ 54 | "~$\U007F" = "deleteWordForward:"; /* O-Shft-Del Delete word forward */ 55 | 56 | 57 | /* These next few don't work, maddeningly. 58 | * They don't really have a reason to stay in this file. */ 59 | /* "@\U007F" = "deleteToBeginningOfParagraph:"; /* O-Del Delete word backward */ 60 | /* "@\UF728" = "deleteToEndOfParagraph:"; /* O-FwdDel Delete word forward */ 61 | /* "@$\U007F" = "deleteToEndOfParagraph:"; /* O-Shft-Del Delete word forward */ 62 | /* "@~\U007F" = ( "selectToBeginningOfDocument:", /* A-O-Del Delete to beginning of document*/ 63 | /* "delete:"); 64 | /* "@~\U007F" = ( "selectToEndOfDocument:", /* A-O-FwdDel Delete to end of document*/ 65 | /* "delete:"); 66 | /* "@~$\U007F" = ( "selectToEndOfDocument:", /* A-O-Shft-Del Delete to end of document*/ 67 | /* "delete:"); 68 | /* End failure section */ 69 | } -------------------------------------------------------------------------------- /KeyBindings/Emacs Esc Bindings.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* Keybindings for emacs emulation. Compiled by Jacob Rus. 3 | * 4 | * This is a pretty good set, especially considering that many emacs bindings 5 | * such as C-o, C-a, C-e, C-k, C-y, C-v, C-f, C-b, C-p, C-n, C-t, and 6 | * perhaps a few more, are already built into the system. 7 | * 8 | * This file uses Esc for commands that use the meta key, because if the 9 | * option key was used, it would override existing Macintosh key bindings. 10 | */ 11 | 12 | /* We are going to override the Esc binding for complete, so add Esc Esc */ 13 | "\U001B" = {"\U001B" = "complete:";}; /* Esc Esc Complete */ 14 | 15 | /* Ctrl shortcuts */ 16 | "^l" = "centerSelectionInVisibleArea:"; /* C-l Recenter */ 17 | "^/" = "undo:"; /* C-/ Undo */ 18 | "^_" = "undo:"; /* C-_ Undo */ 19 | "^ " = "setMark:"; /* C-Spc Set mark */ 20 | "^\@" = "setMark:"; /* C-@ Set mark */ 21 | "^w" = "deleteToMark:"; /* C-w Delete to mark */ 22 | 23 | /* Incremental search. */ 24 | /* Uncomment these lines If Incremental Search IM is installed */ 25 | /* "^s" = "ISIM_incrementalSearch:"; /* C-s Incremental search */ 26 | /* "^r" = "ISIM_reverseIncrementalSearch:"; /* C-r Reverse incremental search */ 27 | /* "^g" = "abort:"; /* C-g Abort */ 28 | 29 | 30 | /* Meta shortcuts */ 31 | "\U001B" = { 32 | "f" = "moveWordForward:"; /* Esc f Move forward word */ 33 | "b" = "moveWordBackward:"; /* Esc b Move backward word */ 34 | "<" = "moveToBeginningOfDocument:"; /* Esc < Move to beginning of document */ 35 | ">" = "moveToEndOfDocument:"; /* Esc > Move to end of document */ 36 | "v" = "pageUp:"; /* Esc v Page Up */ 37 | "/" = "complete:"; /* Esc / Complete */ 38 | "c" = ( "capitalizeWord:", /* Esc c Capitalize */ 39 | "moveForward:", 40 | "moveForward:"); 41 | "u" = ( "uppercaseWord:", /* Esc u Uppercase */ 42 | "moveForward:", 43 | "moveForward:"); 44 | "l" = ( "lowercaseWord:", /* Esc l Lowercase */ 45 | "moveForward:", 46 | "moveForward:"); 47 | "d" = "deleteWordForward:"; /* Esc d Delete word forward */ 48 | "^h" = "deleteWordBackward:"; /* Esc C-h Delete word backward */ 49 | "\U007F"= "deleteWordBackward:"; /* Esc Bksp Delete word backward */ 50 | "t" = "transposeWords:"; /* Esc t Transpose words */ 51 | 52 | "\@" = ( "setMark:", /* Esc @ Mark word */ 53 | "moveWordForward:", 54 | "swapWithMark"); 55 | "h" = ( "setMark:", /* Esc h Mark paragraph */ 56 | "moveToEndOfParagraph:", 57 | "swapWithMark"); 58 | }; 59 | 60 | /* C-x shortcuts */ 61 | "^x" = { 62 | "u" = "undo:"; /* C-x u Undo */ 63 | "k" = "performClose:"; /* C-x k Close */ 64 | "^f" = "openDocument:"; /* C-x C-f Open (find file) */ 65 | "^x" = "swapWithMark:"; /* C-x C-x Swap with mark */ 66 | "^m" = "selectToMark:"; /* C-x C-m Select to mark*/ 67 | "^s" = "saveDocument:"; /* C-x C-s Save */ 68 | "^w" = "saveDocumentAs:"; /* C-x C-w Save as */ 69 | }; 70 | 71 | } -------------------------------------------------------------------------------- /KeyBindings/Emacs Opt Bindings.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* Keybindings for emacs emulation. Compiled by Jacob Rus. 3 | * 4 | * This is a pretty good set, especially considering that many emacs bindings 5 | * such as C-o, C-a, C-e, C-k, C-y, C-v, C-f, C-b, C-p, C-n, C-t, and 6 | * perhaps a few more, are already built into the system. 7 | * 8 | * BEWARE: 9 | * This file uses the Option key as a meta key. This has the side-effect 10 | * of overriding Mac OS keybindings for the option key, which generally 11 | * make common symbols and non-english letters. 12 | */ 13 | 14 | /* Ctrl shortcuts */ 15 | "^l" = "centerSelectionInVisibleArea:"; /* C-l Recenter */ 16 | "^/" = "undo:"; /* C-/ Undo */ 17 | "^_" = "undo:"; /* C-_ Undo */ 18 | "^ " = "setMark:"; /* C-Spc Set mark */ 19 | "^\@" = "setMark:"; /* C-@ Set mark */ 20 | "^w" = "deleteToMark:"; /* C-w Delete to mark */ 21 | 22 | 23 | /* Incremental search. */ 24 | /* Uncomment these lines If Incremental Search IM is installed */ 25 | /* "^s" = "ISIM_incrementalSearch:"; /* C-s Incremental search */ 26 | /* "^r" = "ISIM_reverseIncrementalSearch:"; /* C-r Reverse incremental search */ 27 | /* "^g" = "abort:"; /* C-g Abort */ 28 | 29 | 30 | /* Meta shortcuts */ 31 | "~f" = "moveWordForward:"; /* M-f Move forward word */ 32 | "~b" = "moveWordBackward:"; /* M-b Move backward word */ 33 | "~<" = "moveToBeginningOfDocument:"; /* M-< Move to beginning of document */ 34 | "~>" = "moveToEndOfDocument:"; /* M-> Move to end of document */ 35 | "~v" = "pageUp:"; /* M-v Page Up */ 36 | "~/" = "complete:"; /* M-/ Complete */ 37 | "~c" = ( "capitalizeWord:", /* M-c Capitalize */ 38 | "moveForward:", 39 | "moveForward:"); 40 | "~u" = ( "uppercaseWord:", /* M-u Uppercase */ 41 | "moveForward:", 42 | "moveForward:"); 43 | "~l" = ( "lowercaseWord:", /* M-l Lowercase */ 44 | "moveForward:", 45 | "moveForward:"); 46 | "~d" = "deleteWordForward:"; /* M-d Delete word forward */ 47 | "^~h" = "deleteWordBackward:"; /* M-C-h Delete word backward */ 48 | "~\U007F" = "deleteWordBackward:"; /* M-Bksp Delete word backward */ 49 | "~t" = "transposeWords:"; /* M-t Transpose words */ 50 | "~\@" = ( "setMark:", /* M-@ Mark word */ 51 | "moveWordForward:", 52 | "swapWithMark"); 53 | "~h" = ( "setMark:", /* M-h Mark paragraph */ 54 | "moveToEndOfParagraph:", 55 | "swapWithMark"); 56 | 57 | /* C-x shortcuts */ 58 | "^x" = { 59 | "u" = "undo:"; /* C-x u Undo */ 60 | "k" = "performClose:"; /* C-x k Close */ 61 | "^f" = "openDocument:"; /* C-x C-f Open (find file) */ 62 | "^x" = "swapWithMark:"; /* C-x C-x Swap with mark */ 63 | "^m" = "selectToMark:"; /* C-x C-m Select to mark*/ 64 | "^s" = "saveDocument:"; /* C-x C-s Save */ 65 | "^w" = "saveDocumentAs:"; /* C-x C-w Save as */ 66 | }; 67 | 68 | } -------------------------------------------------------------------------------- /KeyBindings/Greek Bindings.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * Greek keybinding example, by Jacob Rus. 4 | * 5 | * Note that this is an example, and is not very usable on a 6 | * day-to-day basis. 7 | */ 8 | "a" = ("insertText:", "\U03B1"); /* a alpha */ 9 | "b" = ("insertText:", "\U03B2"); /* b beta */ 10 | "g" = ("insertText:", "\U03B3"); /* g gamma */ 11 | "d" = ("insertText:", "\U03B4"); /* d delta */ 12 | "e" = ("insertText:", "\U03B5"); /* e epsilon */ 13 | "~e" = ("insertText:", "\U03F5"); /* O-e epsilon var */ 14 | "z" = ("insertText:", "\U03B6"); /* z zeta */ 15 | "h" = ("insertText:", "\U03B7"); /* h eta */ 16 | "q" = ("insertText:", "\U03B8"); /* q theta */ 17 | "~q" = ("insertText:", "\U03D1"); /* O-q theta var */ 18 | "i" = ("insertText:", "\U03B9"); /* i iota */ 19 | "k" = ("insertText:", "\U03BA"); /* k kappa */ 20 | "l" = ("insertText:", "\U03BB"); /* l lambda */ 21 | "m" = ("insertText:", "\U03BC"); /* m mu */ 22 | "n" = ("insertText:", "\U03BD"); /* n nu */ 23 | "x" = ("insertText:", "\U03BE"); /* x xi */ 24 | "o" = ("insertText:", "\U03BF"); /* o omicron */ 25 | "p" = ("insertText:", "\U03C0"); /* p pi */ 26 | "r" = ("insertText:", "\U03C1"); /* r rho */ 27 | "~r" = ("insertText:", "\U03F1"); /* O-r rho var */ 28 | "~s" = ("insertText:", "\U03C2"); /* O-s final sigma */ 29 | "s" = ("insertText:", "\U03C3"); /* s sigma */ 30 | "t" = ("insertText:", "\U03C4"); /* t tau */ 31 | "u" = ("insertText:", "\U03C5"); /* u upsilon */ 32 | "f" = ("insertText:", "\U03C6"); /* f phi */ 33 | "~f" = ("insertText:", "\U03D5"); /* O-f phi var */ 34 | "c" = ("insertText:", "\U03C7"); /* c chi */ 35 | "y" = ("insertText:", "\U03C8"); /* y psi */ 36 | "w" = ("insertText:", "\U03C9"); /* w omega */ 37 | 38 | 39 | "A" = ("insertText:", "\U0391"); /* A Alpha */ 40 | "B" = ("insertText:", "\U0392"); /* B Beta */ 41 | "G" = ("insertText:", "\U0393"); /* G Gamma */ 42 | "D" = ("insertText:", "\U0394"); /* D Delta */ 43 | "E" = ("insertText:", "\U0395"); /* E Epsilon */ 44 | "Z" = ("insertText:", "\U0396"); /* Z Zeta */ 45 | "H" = ("insertText:", "\U0397"); /* H Eta */ 46 | "Q" = ("insertText:", "\U0398"); /* Q Theta */ 47 | "I" = ("insertText:", "\U0399"); /* I Iota */ 48 | "K" = ("insertText:", "\U039A"); /* K Kappa */ 49 | "L" = ("insertText:", "\U039B"); /* L Lambda */ 50 | "M" = ("insertText:", "\U039C"); /* M Mu */ 51 | "N" = ("insertText:", "\U039D"); /* N Nu */ 52 | "X" = ("insertText:", "\U039E"); /* X Xi */ 53 | "O" = ("insertText:", "\U039F"); /* O Omicron */ 54 | "P" = ("insertText:", "\U03A0"); /* P Pi */ 55 | "R" = ("insertText:", "\U03A1"); /* R Rho */ 56 | "S" = ("insertText:", "\U03A3"); /* S Sigma */ 57 | "T" = ("insertText:", "\U03A4"); /* T Tau */ 58 | "U" = ("insertText:", "\U03A5"); /* U Upsilon */ 59 | "F" = ("insertText:", "\U03A6"); /* F Phi */ 60 | "C" = ("insertText:", "\U03A7"); /* C Chi */ 61 | "Y" = ("insertText:", "\U03A8"); /* Y Psi */ 62 | "W" = ("insertText:", "\U03A9"); /* W Omega */ 63 | 64 | /*Make sure other letters do nothing*/ 65 | "j" = "noop:"; 66 | "v" = "noop:"; 67 | "J" = "noop:"; 68 | "V" = "noop:"; 69 | } -------------------------------------------------------------------------------- /KeyBindings/Leet Binding.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * Leetspeak keybinding example, by Jacob Rus 4 | * 5 | * You probably don't want to use this as anything other than an example. 6 | * 7 | */ 8 | 9 | "a" = ("insertText:", "4"); 10 | "b" = ("insertText:", "8"); 11 | "c" = ("insertText:", "<"); 12 | "d" = ("insertText:", "o|"); 13 | "e" = ("insertText:", "3"); 14 | "f" = ("insertText:", "ph"); 15 | "g" = ("insertText:", "6"); 16 | "h" = ("insertText:", "|-|"); 17 | "i" = ("insertText:", "¡"); 18 | "j" = ("insertText:", "_|"); 19 | "k" = ("insertText:", "|<"); 20 | "l" = ("insertText:", "1"); 21 | "m" = ("insertText:", "/\\/\\"); 22 | "n" = ("insertText:", "|\\|"); 23 | "o" = ("insertText:", "0"); 24 | "p" = ("insertText:", "|°"); 25 | "q" = ("insertText:", "0_"); 26 | "r" = ("insertText:", "|2"); 27 | "s" = ("insertText:", "z"); 28 | "t" = ("insertText:", "7"); 29 | "u" = ("insertText:", "(_)"); 30 | "v" = ("insertText:", "\\/"); 31 | "w" = ("insertText:", "\\^/"); 32 | "x" = ("insertText:", "×"); 33 | "y" = ("insertText:", "`/"); 34 | "z" = ("insertText:", "%"); 35 | "A" = ("insertText:", "/-\\"); 36 | "B" = ("insertText:", "|3"); 37 | "C" = ("insertText:", "©"); 38 | "D" = ("insertText:", "[)"); 39 | "E" = ("insertText:", "[-"); 40 | "F" = ("insertText:", "/#"); 41 | "G" = ("insertText:", "(y"); 42 | "H" = ("insertText:", "]-["); 43 | "I" = ("insertText:", "]["); 44 | "J" = ("insertText:", "_/"); 45 | "K" = ("insertText:", "|{"); 46 | "L" = ("insertText:", "|_"); 47 | "M" = ("insertText:", "[]\\/[]"); 48 | "N" = ("insertText:", "[]\\[]"); 49 | "O" = ("insertText:", "()"); 50 | "P" = ("insertText:", "|^"); 51 | "Q" = ("insertText:", "(_,)"); 52 | "R" = ("insertText:", "P\\"); 53 | "S" = ("insertText:", "§"); 54 | "T" = ("insertText:", "-|-"); 55 | "U" = ("insertText:", "|_|"); 56 | "V" = ("insertText:", "\\_/"); 57 | "W" = ("insertText:", "\\/\\/"); 58 | "X" = ("insertText:", "><"); 59 | "Y" = ("insertText:", "\|"); 60 | "Z" = ("insertText:", "~/_"); 61 | 62 | /* An exclamation point done right */ 63 | "!" = ("insertText:", "!!11!eleventy-one!1!!!!"); 64 | } -------------------------------------------------------------------------------- /KeyBindings/Leet Bindings.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | * Leetspeak keybinding example, by Jacob Rus 4 | * 5 | * You probably don't want to use this as anything other than an example. 6 | * 7 | */ 8 | 9 | "a" = ("insertText:", "4"); 10 | "b" = ("insertText:", "8"); 11 | "c" = ("insertText:", "<"); 12 | "d" = ("insertText:", "o|"); 13 | "e" = ("insertText:", "3"); 14 | "f" = ("insertText:", "ph"); 15 | "g" = ("insertText:", "6"); 16 | "h" = ("insertText:", "|-|"); 17 | "i" = ("insertText:", "¡"); 18 | "j" = ("insertText:", "_|"); 19 | "k" = ("insertText:", "|<"); 20 | "l" = ("insertText:", "1"); 21 | "m" = ("insertText:", "/\\/\\"); 22 | "n" = ("insertText:", "|\\|"); 23 | "o" = ("insertText:", "0"); 24 | "p" = ("insertText:", "|°"); 25 | "q" = ("insertText:", "0_"); 26 | "r" = ("insertText:", "|2"); 27 | "s" = ("insertText:", "z"); 28 | "t" = ("insertText:", "7"); 29 | "u" = ("insertText:", "(_)"); 30 | "v" = ("insertText:", "\\/"); 31 | "w" = ("insertText:", "\\^/"); 32 | "x" = ("insertText:", "×"); 33 | "y" = ("insertText:", "`/"); 34 | "z" = ("insertText:", "%"); 35 | "A" = ("insertText:", "/-\\"); 36 | "B" = ("insertText:", "|3"); 37 | "C" = ("insertText:", "©"); 38 | "D" = ("insertText:", "[)"); 39 | "E" = ("insertText:", "[-"); 40 | "F" = ("insertText:", "/#"); 41 | "G" = ("insertText:", "(y"); 42 | "H" = ("insertText:", "]-["); 43 | "I" = ("insertText:", "]["); 44 | "J" = ("insertText:", "_/"); 45 | "K" = ("insertText:", "|{"); 46 | "L" = ("insertText:", "|_"); 47 | "M" = ("insertText:", "[]\\/[]"); 48 | "N" = ("insertText:", "[]\\[]"); 49 | "O" = ("insertText:", "()"); 50 | "P" = ("insertText:", "|^"); 51 | "Q" = ("insertText:", "(_,)"); 52 | "R" = ("insertText:", "P\\"); 53 | "S" = ("insertText:", "§"); 54 | "T" = ("insertText:", "-|-"); 55 | "U" = ("insertText:", "|_|"); 56 | "V" = ("insertText:", "\\_/"); 57 | "W" = ("insertText:", "\\/\\/"); 58 | "X" = ("insertText:", "><"); 59 | "Y" = ("insertText:", "\|"); 60 | "Z" = ("insertText:", "~/_"); 61 | 62 | /* An exclamation point done right */ 63 | "!" = ("insertText:", "!!11!eleventy-one!1!!!!"); 64 | } -------------------------------------------------------------------------------- /KeyBindings/Windows Bindings.dict: -------------------------------------------------------------------------------- 1 | { 2 | /* Keybindings for partial windows emulation. Compiled by Jacob Rus. 3 | * 4 | * Steve Jacobs did much of the work on this. 5 | * 6 | * Note that the bindings at the end, for Ctrl-a, Ctrl-n, etc. 7 | * will override OS X defaults. Remove that section if you like. 8 | */ 9 | 10 | 11 | /***** HOME-END KEYS *****/ 12 | 13 | "\UF729" = "moveToBeginningOfLine:"; /* home Beginning of line */ 14 | "\UF72B" = "moveToEndOfLine:"; /* end End of line */ 15 | 16 | "$\UF729" = "moveToBeginningOfLineAndModifySelection:"; 17 | /* Shft-home Select to beginning of line */ 18 | "$\UF72B" = "moveToEndOfLineAndModifySelection:"; 19 | /* Shft-end Select to end of line */ 20 | 21 | "^\UF729" = "moveToBeginningOfDocument:"; /* C-home Beginning of document */ 22 | "^\UF72B" = "moveToEndOfDocument:"; /* C-end End of document */ 23 | 24 | "^$\UF729" = "moveToBeginningOfDocumentAndModifySelection:"; 25 | /* C-Shft-home Select to beginning of document */ 26 | "^$\UF72B" = "moveToEndOfDocumentAndModifySelection:"; 27 | /* C-Shft-end Select to end of document */ 28 | 29 | /***** PAGE UP-PAGE DOWN KEYS *****/ 30 | 31 | "\UF72C" = "pageUp:"; /* page up Page up */ 32 | "\UF72D" = "pageDown:"; /* page dn Page down */ 33 | 34 | "~\UF72C" = "scrollPageUp:"; /* O-pg up Scroll page up */ 35 | "~\UF72D" = "scrollPageDown:"; /* O-pg dn Scroll page down */ 36 | 37 | 38 | /***** DELETE-FORWARD DELETE KEYS *****/ 39 | 40 | "~\U007F" = "undo:"; /* O-Del Undo */ 41 | "~$\U007F" = "redo:"; /* O-Shft-Del Undo */ 42 | 43 | "^\U007F" = "deleteWordBackward:"; /* C-Del Delete word backward */ 44 | "^\UF728" = "deleteWordForward:"; /* C-FwdDel Delete word forward */ 45 | 46 | 47 | /***** DELETE-INSERT(HELP) KEYS *****/ 48 | 49 | /* Note that the Windows "insert" key is the Mac "help" key */ 50 | "$\UF728" = "cut:"; /* Shft-FwdDel Cut */ 51 | "^\UF746" = "copy:"; /* C-Help Copy */ 52 | "$\UF746" = "paste:"; /* Shft-Help Paste */ 53 | 54 | 55 | /***** RETURN KEY *****/ 56 | 57 | "$\U000A" = "insertLineBreak:"; /* Shft-Ret Line break */ 58 | 59 | 60 | /***** F KEYS *****/ 61 | 62 | "\UF704" = "showContextHelp:"; /* F1 Show help */ 63 | 64 | "^\UF707" = "performClose:"; /* C-F4 Close document */ 65 | 66 | /***** ARROWS *****/ 67 | 68 | "^\UF700" = "moveToBeginningOfParagraph:"; /* C-up Move to beginning of paragraph */ 69 | "^\UF701" = "moveToEndOfParagraph:"; /* C-down Move to end of paragraph */ 70 | 71 | "^$\UF700" = "moveToBeginningOfParagraphAndModifySelection:"; 72 | /* C-Shft-up Select to beginning of paragraph */ 73 | "^$\UF701" = "moveToEndOfParagraphAndModifySelection:"; 74 | /* C-Shft-down Select to end of paragraph */ 75 | 76 | "^\UF702" = "moveWordLeft:"; /* C-left Move word left */ 77 | "^\UF703" = "moveWordRight:"; /* C-right Move word right */ 78 | 79 | "$^\UF702" = "moveWordLeftAndModifySelection:"; 80 | /* C-Shft-left Select word left */ 81 | "$^\UF703" = "moveWordRightAndModifySelection:"; 82 | /* C-Shft-right Select word right */ 83 | 84 | 85 | /***** CTRL + LETTERS *****/ 86 | 87 | "^a" = "selectAll:"; /* C-a Select all */ 88 | 89 | "^x" = "cut:"; /* C-x Cut */ 90 | "^c" = "copy:"; /* C-c Copy */ 91 | "^v" = "paste:"; /* C-v Paste */ 92 | 93 | "^z" = "undo:"; /* C-z Undo */ 94 | "^y" = "redo:"; /* C-y Redo */ 95 | 96 | "^s" = "save:"; /* C-s Save */ 97 | "^S" = "saveAs:"; /* C-Shft-s Save as */ 98 | "^p" = "print:"; /* C-p Print */ 99 | 100 | } -------------------------------------------------------------------------------- /cocoa-text.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Cocoa Text System 7 | 84 | 85 |
86 |

Customizing the Cocoa Text System

87 | 88 |

Version 0.8
89 | by Jacob Rus
90 | Monday, 20 March 2006

91 | 92 |

Apple’s Cocoa text system is a complicated beast, but also extremely flexible, 93 | and with a bit of work, it can be molded to match many working styles. This 94 | how-to covers the 2 major ways of customizing the text input system: Default 95 | key bindings, and for still more control, input managers.

96 | 97 |

I’m writing this guide because nothing like it currently exists. There is 98 | incredible room for flexibility in customizing the Cocoa text environment, but 99 | most users—even power-users—have no idea of the available options. This is 100 | mostly because Apple’s documentation is 1) aimed at developers, and 2) often 101 | incomplete or ambiguous. Most users have no idea that they can look at a file 102 | which describes all of the shortcuts on the system, and that they can easily 103 | add their own shortcuts, or replace existing ones with differing 104 | functionality.

105 | 106 |

For instance, one of the most common complaints from new Windows and 107 | Linux/Unix switchers is that many of the shortcuts they are used to, such as 108 | using the Home and End keys to move to the beginning, respectively end, of a 109 | line or document, don’t work as they expect in OS X.

110 | 111 |

For new users, almost every text box you use is a Cocoa text box (or close 112 | enough to act the same as far as we’re concerned) — Safari web form boxes, 113 | the text field in iChat for sending new messages, the documents in Pages or 114 | TextEdit, the email composer in Mail, etc. Note: Some text boxes are not 115 | Cocoa however, so the tricks in this article still aren’t completely 116 | universal. Notably, Microsoft Word, Adobe applications, AppleWorks, and the 117 | text fields in Camino and Firefox won’t work with this hint.

118 | 119 |

I expect that all users of OS X can get something out of this guide. I’m 120 | starting with the basics, so that new users, unfamiliar with the terminal and 121 | the intricacies of OS X can be brought up to speed. But even the most 122 | experienced users should hopefully learn something from this article; I know 123 | I learned several new nifty things while writing it.

124 | 125 |

Disclaimer: it is possible, when mucking around with the text system, to 126 | send applications messages they aren’t expecting. This can cause them to 127 | crash. As long as you stick to standard text selectors, you should be fine, 128 | but I’m not responsible if your program crashes because of a binding you add.

129 | 130 |

Terminology

131 | 132 |

Before delving too deeply into the intricacies of the Cocoa text system, it 133 | helps to understand some programmer jargon.

134 | 135 | 163 | 164 |

Many of these terms crop up in the venerable Emacs editor, so reading 165 | about them in the Emacs context can be enlightening: Buffer, 166 | Key Bindings, Mark, Kill

167 | 168 |

Existing (Default) Functionality

169 | 170 |

Most users of Mac OS X, even long-time Apple geeks, know only a fraction of 171 | the available text system shortcuts. This is a tragedy, as they are consistent 172 | across all applications which use the Cocoa text system, including TextEdit, 173 | Mail, iChat, Safari, and countless third-party applications.

174 | 175 |

Simple Text Insertion

176 | 177 |

One thing every user knows is that when a plain letter is typed (assuming the 178 | input method in use matches the keyboard), that letter is inserted into a 179 | selected text box. When the shift key is held down, letters are capitalized, 180 | and symbol keys input the second symbol shown on them. For instance ‘Shift-]’ 181 | inputs the ‘}’ character.

182 | 183 |

It is possible to see all of the possibilities using the 184 | ‘Keyboard Viewer’ palette:

185 | 186 |

Keyboard viewer--full sized 187 | Keyboard viewer--laptop

188 | 189 |

In addition, the option key, both alone and in conjunction with the shift key, 190 | will change the characters inserted. So ‘Option-y’ inserts a ‘¥’ currency 191 | mark, and ‘Option-Shift-c’ inserts a capital cedilla: ‘Ç’. We can see 192 | how option affects our input options using the Keyboard Viewer:

193 | 194 |

Keyboard viewer--full sized--option key 195 | Keyboard viewer--full sized--shift+option

196 | 197 |

Users with full keyboards have a complete number pad, with an enter key 198 | (instead of return), and symbols used in arithmetic. This number pad is 199 | available to PowerBook and iBook users as well. The numlock key (Fn-F6), 200 | enables the small symbols printed at the lower right corner of powerbook keys 201 | to be input. But even more usefully, those keys can also be used as a number 202 | pad while the Fn key is held down. This is great for typing lots of numeric 203 | data, and also comes in handy when playing games that allow vertical, 204 | horizontal, and diagonal movement via the number pad:

205 | 206 |

Keyboard viewer--laptop--function key

207 | 208 |

Of course, there are a number of standard actions that the above pictures 209 | don’t show. For instance, when you type ‘Command-left’, the insertion 210 | point moves to the beginning of the current line. Also, OS X has a fairly 211 | large number of unix/emacs bindings built in.

212 | 213 |

The complete list of these extra commands takes up too much space for this 214 | page, so I’ve made them into a separate document.

215 | 216 |

Default key bindings

217 | 218 |

OS X has three main files which specify the key bindings used by Cocoa 219 | applications:

220 | 221 |
/System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict
222 | 
223 | /Library/KeyBindings/DefaultKeyBinding.dict
224 | 
225 | ~/Library/KeyBindings/DefaultKeyBinding.dict
226 | 
227 | 228 |

which contain, respectively, the default ‘built-in’ key bindings, system-wide 229 | custom keybindings, and a user’s personalized key bindings. Don’t edit the 230 | built-in /System/Library/ file, as this could seriously hose your machine. 231 | Note that as usual, personalized bindings override the built-in standards.

232 | 233 |

If the DefaultKeyBinding.dict file doesn’t exist, don’t worry. Simply making 234 | a KeyBindings folder in ~/Library, and then adding a new text file should 235 | do the trick.

236 | 237 |

File Format:

238 | 239 |

This file is a normal Property List, which can be created 240 | either with a text editor, such as TextWrangler, Smultron, 241 | or TextMate, or with Apple’s Property List Editor, which is installed 242 | with the developer tools. Property lists are pervasive in OS X, and are used 243 | for all sorts of configuration files, and preferences. Any file which has a 244 | .plist or .dict extension is a property list. Every application has an 245 | info.plist file inside of it which tells OS X what types of files that 246 | application can handle. Smart folders (.savedSearch files) are property 247 | lists. The defaults command, which can be run from the terminal, is a quick 248 | way to edit single items in a property list.

249 | 250 |

There are two types of property lists, old-style NeXT text files, and newer 251 | XML formatted files. I will use the old-style plists in this how-to, because 252 | they are easier to read and understand; they are more compact, with less 253 | distracting markup.

254 | 255 |

The NeXT property list format is a file format that can describe, using 256 | plain text, all of the objects used in Cocoa programs. We specifically care 257 | about 3 types: ‘strings’, ‘lists’, and ‘dictionaries’:

258 | 259 | 280 | 281 |

Every property list has a root dictionary object, which can contain 282 | sub-objects. A simple plist file might look like:

283 | 284 |
{
285 |     /*  ** THIS IS A COMMENT: **
286 |      * 
287 |      * Notice that each line in the dictionary has a 'key' string,
288 |      * and a 'value', which can be a string, a list, or another
289 |      * dictionary.
290 |      */
291 | 
292 |     "My String" = "Hey there!";
293 | 
294 |     "My List" = ("first string", "second string", "final string");
295 | 
296 |     "My Dictionary" = {
297 |         "Sub-string A" = "This is a string inside a dictionary";
298 |         "Sub-list B" = ("This is a list", "inside a dictionary");
299 |     };
300 | }
301 | 
302 | 303 |

This property list has three key-value pairs: a string, a list, and a 304 | dictionary.

305 | 306 |

The format of DefaultKeyBinding.dict

307 | 308 |

The DefaultKeyBindings.dict file is fairly straight-forward. It is a normal 309 | property list, which as keys, uses the requested key bindings, and as values 310 | uses the commands they should execute. For instance, I might want the letter 311 | a to not type ‘a’, but instead insert a tab. If I put the following in my 312 | DefaultKeyBinding.dict, then all Cocoa apps launched afterwards will insert 313 | a tab key instead of an a:

314 | 315 |
{
316 |     /* This will make all a's turn to tabs.  Beware. */
317 |     "a" = "insertTab:";
318 | }
319 | 
320 | 321 |

How to represent bindings

322 | 323 |

But of course, if we could only bind things to letter keys, this wouldn’t 324 | really be so useful, now would it? Fortunately, Apple’s engineers made sure 325 | that every key that you could possibly ever type can be put into a binding.

326 | 327 |

The way it works is simple. For lower-case and capital letters, simply type 328 | the letter into the string. So "y" represents the ‘y’ key, while "T" 329 | represents ‘Shift-t’. For numbers and symbols, including space, the same 330 | holds. So "!" represents ‘Shift-1’, or however you type ‘!’ on your keyboard 331 | layout. To add modifier keys, add a symbol corresponding to that modifier:

332 | 333 |
334 |

"@t" = Command-t
335 | "^t" = Control-t
336 | "~t" = Option-t
337 | "@^T" = Command-Control-Shift-t
338 | "~ " = Option-space

339 |
340 | 341 |

For numbers and symbols, to add the shift key is not as easy as typing a 342 | capital letter, so $ stands for shift. Also, there is a difference between 343 | numbers above the letter keys, and numbers on the keypad. To indicate keypad 344 | keys, use #:

345 | 346 |
347 |

"@$#5" = Command-Shift-Numpad 5
348 | "^6" = Control-6

349 |
350 | 351 |

Note: Lots of bindings with the Command key won’t work. This is done by 352 | Apple to ensure that applications can use these shortcuts for themselves, and 353 | not worry about user key bindings. Some will work, however, such as 354 | ‘Command-right arrow’.

355 | 356 |

There are still 2 limitations: First, what do we do if we want to bind a 357 | literal ‘@’ or ‘#’ symbol? We escape it! By adding a \\ before the symbol, 358 | we can avoid this. At the moment, the only way I can get ‘\’ itself to bind to 359 | anything is by writing it as ‘\U05C’.

360 | 361 |
362 |

"~\\$" = Option-$

363 |
364 | 365 |

Second, if we were limited to symbols and modifiers, we would still cut off 366 | keys like ‘delete’, ‘tab’, and ‘esc’, so any keys that aren’t already covered 367 | can be entered using their unicode values:

368 | 369 |

Unicode values for Apple non-letter keys:

370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 |
Escape: \U001B
 
Tab: \U0009
Backtab: \U0019
 
Return: \U000A
Enter: \U000D
 
Delete: \U007F
 
Up Arrow: \UF700
Down Arrow: \UF701
Left Arrow: \UF702
Right Arrow: \UF703
 
Help: \UF746
Forward Delete:\UF728
Home: \UF729
End: \UF72B
Page Up: \UF72C
Page Down: \UF72D
 
Clear: \UF739
 
F1: \UF704
F2: \UF705
F3: \UF706
F35 \UF726
 
Not on Apple keyboards:
 
Menu: \UF735
406 | 407 |

Notes:

408 | 409 | 419 | 420 |

For a complete list, including some keys that aren’t on current apple 421 | keyboards, but can still be used by OS X, see the Registry 422 | of Apple Unicode corporate-zone characters.

423 | 424 |

In general, the best way I’ve found to discover key’s escape codes is to use 425 | the free Key Codes application from Peter Maurer. The app brings 426 | up a floating palette which prints a log of all the keys typed.

427 | 428 |

More complicated bindings and actions

429 | 430 |

Of course, sometimes we wish we had more keys on the keyboard. Even with all 431 | of the modifier keys, it gets hard to keep different functionality separated, 432 | and things get confused. For this reason, it is possible to use 433 | multiple-keystroke bindings. To this end, instead of binding our first 434 | keystroke to a selector, we bind it to a dictionary, containing the second 435 | keystrokes. Emacs, the UNIX-based text editor, has many such 436 | multiple-keystroke bindings. Therefore, as an example of how this can be done, 437 | we will take Emacs bindings, and try to replicate them in Cocoa Text Widgets.

438 | 439 |

One Emacs command is ‘Control-x, u’, for ‘undo’. Another is ‘Control-x, 440 | Control-s’ for ‘save’. To add this command to our key bindings, we need to 441 | bind ‘Control-x’ to a dictionary of sub-bindings:

442 | 443 |
{
444 |     /* Control-x dictionary */
445 |     "^x  " = {
446 |         "u"  = "undo:";          /* C-x u    =>  undo */
447 |         "^s" = "save:";  /* C-x C-s  =>  save */
448 |     };
449 | }
450 | 
451 | 452 |

Our ‘Control-x’ parent dictionary can have several multiple-keystroke bindings 453 | associated with it. In this way, we can have whole areas of functionality 454 | given to one ‘parent’ key binding, with the resulting action to be determined 455 | by a letter. We can effectively have 4 or 5 keyboards for our bindings!

456 | 457 |

But of course, the number of bindings is not our only limitation so far. We 458 | are also limited by the range of selectors offered by the text box. We often 459 | find ourselves performing complicated actions repeatedly, and would like to 460 | invoke them with single keystroke. Mostly when this happens, Applescript, or 461 | some other programming language is the best solution. On occasion, however, 462 | the text system has enough power and flexibility to do the trick. This is 463 | because, besides single selectors, a binding can also execute a list of 464 | selectors, sequentially.

465 | 466 |

As an example, imagine that I often want to change paragraphs of text to all 467 | capital letters, but I’m tired of selecting the whole paragraph with my 468 | keyboard or mouse. I want ‘Control-Option-u to make my paragraph all 469 | uppercase, and then I want it to start a new paragraph by inserting two new 470 | lines at the end of the paragraph.

471 | 472 |

This (somewhat contrived) action can be broken into steps: 1. Select paragraph 473 | 2. Make all the letters uppercase 3. Move to the end of the paragraph 4. 474 | Insert two new lines.

475 | 476 |

We can make a plist of these directions:

477 | 478 |
{
479 |     "^~u" = ("selectParagraph:",
480 |              "uppercaseWord:",
481 |              "moveToEndOfParagraph:"
482 |              "insertNewline:",
483 |              "insertNewline");
484 | }
485 | 
486 | 487 |

So, with the the ability to map multiple-keystroke bindings to sets of actions 488 | that can perform complicated behaviors, what’s left?

489 | 490 |

Every time you type a key, the Cocoa text system looks for bindings, and if 491 | none are found for the key, it instead passes the keystroke along as a string 492 | input to the insertText: selector. Well, as luck would have it, 493 | Kevin Ballard, from the ##textmate IRC channel on 494 | freenode (a delightful place to chat, incidentally), found a real 495 | gem, that doesn’t seem to be documented anywhere on Apple’s website, or 496 | anywhere else: It is possible to use the insertText: selector as part of a 497 | binding, and thereby bind an arbitrary string to a keystroke. If we bind a 498 | key to a list, containing "insertText:" as one of its strings, the next 499 | string in the list will be inserted into the text field. Example:

500 | 501 |
{
502 |     /* Realize that actually using this will render your a key
503 |        amusingly useless.*/
504 |     "a" = ("insertText:", "some fun text", "moveWordBackward:");
505 | }
506 | 
507 | 508 |

as a DefaultKeyBinding.dict file will make the ‘a’ key type ‘some fun text’, 509 | and then move the insertion point to the beginning of the word ‘text’, instead 510 | of the simply typing an ‘a’, as usual.

511 | 512 |

This is amazingly useful if there are some symbols or strings which must be 513 | entered on a regular basis. For instance, imagine that I sometimes need to 514 | type LaTeX Greek letters, and also sometimes need the associated unicode 515 | symbols (for alpha, beta, etc.). The following DefaultKeyBinding.dict could 516 | reduce this load considerably:

517 | 518 |
{
519 |     /* Greek unicode letters */
520 |     "^g" = {
521 |         "a" = ("insertText:", "\U03B1");
522 |         "b" = ("insertText:", "\U03B2");
523 |         "g" = ("insertText:", "\U03B3");
524 |         "d" = ("insertText:", "\U03B4"); /*
525 |         ...                               */
526 |     }
527 | 
528 |     /* Greek LaTeX letters */
529 |     "^m" = {
530 |         "a" = ("insertText:", "\\alpha");
531 |         "b" = ("insertText:", "\\beta");
532 |         "g" = ("insertText:", "\\gamma");
533 |         "d" = ("insertText:", "\\delta"); /*
534 |         ...                               */
535 |     }
536 | }
537 | 
538 | 539 |

Now, when I type ‘Control-g, a’, ‘α’ will be inserted instead, and when 540 | I type ‘Control-m, g’, ‘\gamma’ will be inserted, etc.

541 | 542 |

It seems like this behavior is just an exception, as I haven’t found any other 543 | selectors which take an argument, but it’s a glorious exception, for which I 544 | can envision some truly creative uses.

545 | 546 |

For instance, if I want to drive some friends bonkers, I could set 547 | DefaultKeyBinding.dict up to ROT13 all of my letters, to enable 548 | “typing in code”. Or I could set it up to allow typing in leetspeak 549 | (“1337”).

550 | 551 |

Most obviously perhaps, I could bind common phrases or code snippets to simple 552 | keystrokes. This would allow systemwide text shortcuts without the need for 553 | third-party applications (though the third party applications out there, 554 | notably Peter Maurer’s Textpander, do a lot more than key 555 | bindings allow).

556 | 557 |

One binding that I made, and it’s one of my favorites, allows me to type 558 | html and xml tags with ease. I have Control-shift-h make a starting and tag 559 | pair out of the word I’ve just finished typing, and put the cursor in the 560 | middle of them. Here’s the code:

561 | 562 |
{
563 |     /* This command will let Ctrl-Shift-H turn the previous word
564 |      * into an HTML/XML opening and closing tag pair. */
565 |     "^H" = ( "setMark:",
566 |              "moveWordBackward:",
567 |              "deleteToMark:",
568 |              "insertText:", "<",
569 |              "yank:",
570 |              "insertText:", ">",
571 |              "setMark:",
572 |              "insertText:", "</",
573 |              "yank:",
574 |              "insertText:", ">",
575 |              "swapWithMark:");
576 | }
577 | 
578 | 579 |

Finally, the possibilities for pranks on coworkers, significant others, etc. 580 | is considerable. For instance, we can set the keyboard up to malfunction on a 581 | couple of letters, maybe a ‘z’ could say “you didn’t 582 | *really* want to type that, did you?”:

583 | 584 |
{
585 |     "z" = ("setMark:",
586 |            "insertText:",
587 |            "you didn't *really* want to type that, did you?",
588 |            "selectToMark:",
589 |            "speakText:");
590 | }
591 | 
592 | 593 |

Moving right along, now that we have the idea of how to form our bindings, we 594 | can get to figuring out exactly which selectors are available to us.

595 | 596 |

Usable selectors

597 | 598 |

It is hard to figure out exactly which selectors a text box, and more 599 | generally, an application, will respond to. There are a huge number of 600 | options, but they are not all documented in one place. This is partly because 601 | if one object in an application doesn’t respond to a particular message, it 602 | will pass the message along to its parent object.

603 | 604 |

Still, we can find a large number of useful selectors by searching through the 605 | documentation we can find, and testing what the selectors do. The biggest 606 | source of selectors that we might want to use is in the NSResponder class — 607 | see its documentation. Specifically, we care about the 608 | ‘Action methods’ section. Also, the documentation for 609 | NSText has some selectors we can use, and many other classes provide useful 610 | selectors as well, such as NSDocumentController and NSWindow.

611 | 612 |

Because there are so many usable selectors, I’m putting them in a separate 613 | page. Here’s a link.

614 | 615 |

Examples

616 | 617 |

I’ve put together some examples of how this could be used. To use one of 618 | these, simply rename the file to DefaultKeyBinding.dict and plop it in the 619 | ~/Library/KeyBindings folder. One of the most common uses of custom key 620 | bindings is emulating another operating system or environment, such as Windows 621 | or Emacs or BBEdit:

622 | 623 | 632 | 633 |

Beyond that, it’s possible make key bindings as pranks. That’s always fun:

634 | 635 | 639 | 640 |

Text System Defaults

641 | 642 |

Besides making our own key bindings, there are a few other nifty changes we 643 | can apply to the Cocoa text system, using the “defaults” system. Apple’s 644 | developer site tells about them. Some of 645 | these defaults are for unimplemented features, and are therefore worthless to 646 | us. There are three defaults however which are of interest to us here. They 647 | can be set using the defaults terminal command. I will show them applying 648 | globally with the -g flag, but it is possible to set them on an application 649 | by application basis, by for instance specifying com.apple.textedit instead 650 | of -g.

651 | 652 | 685 | 686 |

Input Managers

687 | 688 |

NeXT and Apple realized, when they created Cocoa, that many actions could not 689 | be foreseen by their framework developers. The key binding system is great if 690 | we want to stick within the usual sorts of operations on English text, such as 691 | transposing two letters, skipping the end of a paragraph, or upper-casing a 692 | word, and we can combine these simple actions, but sometimes to do what we 693 | want requires more.

694 | 695 |

An input manager is a piece of code which is loaded into every running Cocoa 696 | application. The purpose of an input manager is to extend the text system in 697 | ways not thought of by the application’s original programmers.

698 | 699 |

We’ve all been hearing of late about how input managers can be used for 700 | nefarious purposes, but as long as they stick to modifying the text system, 701 | they mostly stay out of trouble, and they can be incredibly useful. Two input 702 | managers in particular are quite popular:

703 | 704 | 757 | 758 |

Even Lower-Level Hacking: Keyboard Layouts

759 | 760 |

First, we haven’t seen any way to remap modifier keys so far. This can be 761 | easily accomplished using the Keyboard and Mouse preference pane. Click the 762 | ‘modifier keys’ button at the bottom of the view, and a nice sheet pops up. 763 | Mine, which I’ve set to put the keys on a Model M keyboard in the 764 | right places, with ‘Control’ where it belongs next to the ‘A’ key, looks like 765 | this:

766 | 767 |

Keyboard Pref Pane

768 | 769 |

For even finer control over the keyboard, it is possible to create 770 | customized keyboard layouts. These allow any unicode glyphs 771 | to be mapped to the keys on the keyboard, so alternate language scripts can be 772 | entered, etc. This will work across the OS, not just in Cocoa text editors, 773 | but is also a much lower-level change, which means that messing it up could be 774 | much worse. I haven’t actually ever used any layouts other than U.S. on my 775 | PowerBook, so I don’t know how easy this is. There is a pretty nice GUI 776 | editor for this from SIL called Ukelele. It has great 777 | documentation, and should be all that is needed to make custom keyboard 778 | layouts.

779 | 780 |

Finally, for the truly adventurous, it is apparently possible to go even 781 | lower-level than Ukelele, and patch the ADB codes which are registered 782 | by Apple’s USB keyboard drivers. I’m not sure exactly which versions of OS 783 | X this works with, and any hacking at this level requires a serious 784 | disclaimer, as a wrong move here could really mess up your system. But here 785 | are two links at snark.de which discuss such arcane 786 | trickery. Good luck to any who try this. This same guy (Heiko Hellweg) also 787 | made his own keyboard layout, and patched Apple’s keyboard drivers 788 | to give himself a meta key:

789 | 790 |
791 |

“I got myself the Tiger-Version of the ADB Keyboard Driver 792 | (AppleADBKeyboard-238.3.4) and hacked away in XCode. My current setup uses 793 | the obnoxious enter key (between the cursor keys and the right command 794 | key) as the alt modifier (you can do that without a compiler by just 795 | fiddling with info.plist) and turns the original alt-key on the left 796 | onto a META key that sends escape in front of every other key as long as 797 | it is pressed (for this one, i needed to replace 798 | /System/Library/Extensions/AppleADBKeyboard.kext with an actual 799 | modified binary).

800 | 801 |

“Now i can actually type ahead blindly without thinking twice. Contact me, 802 | if you are interested in using this too.”

803 |
804 | 805 |

Needless to say, I wouldn’t advise trying this, unless you know what you are 806 | doing.

807 | 808 | 809 | 810 |

TODO: Much of this list of links is still incomplete

811 | 812 |

Text Editors

813 | 814 |

Free Cocoa text editors for OS X:

815 | 816 | 821 | 822 |

Commercial Cocoa text editors:

823 | 824 | 840 | 841 |

Non-Cocoa text editors for OS X:

842 | 843 | 855 | 856 |

Apple Developer Documentation

857 | 858 |

Apple has some documentation for the key bindings, but all in all it is far 859 | from adequate, especially for regular users, as opposed to competent 860 | Objective-C hackers.

861 | 862 | 882 | 883 |

Third-party documentation

884 | 885 | 896 | 897 |

Key Bindings Editors

898 | 899 | 910 | 911 |

Input Managers

912 | 913 | 920 | 921 | 922 | 923 | 934 |
935 |
Anything I can improve? Send me an email: jacobolus AT gmail
-------------------------------------------------------------------------------- /cocoa-text.md: -------------------------------------------------------------------------------- 1 | Customizing the Cocoa Text System 2 | ================================= 3 | 4 | Version 0.8 5 | by [Jacob Rus][me] 6 | Monday, 20 March 2006 7 | 8 | [me]: http://hcs.harvard.edu/~jrus 9 | 10 | Apple's Cocoa text system is a complicated beast, but also extremely flexible, 11 | and with a bit of work, it can be molded to match many working styles. This 12 | how-to covers the 2 major ways of customizing the text input system: Default 13 | key bindings, and for still more control, input managers. 14 | 15 | I'm writing this guide because nothing like it currently exists. There is 16 | incredible room for flexibility in customizing the Cocoa text environment, but 17 | most users--even power-users--have no idea of the available options. This is 18 | mostly because Apple's documentation is 1) aimed at developers, and 2) often 19 | incomplete or ambiguous. Most users have no idea that they can look at a file 20 | which describes all of the shortcuts on the system, and that they can easily 21 | add their own shortcuts, or replace existing ones with differing 22 | functionality. 23 | 24 | For instance, one of the most common complaints from new Windows and 25 | Linux/Unix switchers is that many of the shortcuts they are used to, such as 26 | using the Home and End keys to move to the beginning, respectively end, of a 27 | line or document, don't work as they expect in OS X. 28 | 29 | For new users, almost every text box you use is a Cocoa text box (or close 30 | enough to act the same as far as we're concerned) -- Safari web form boxes, 31 | the text field in iChat for sending new messages, the documents in Pages or 32 | TextEdit, the email composer in Mail, etc. **Note:** Some text boxes are not 33 | Cocoa however, so the tricks in this article still aren't completely 34 | universal. Notably, Microsoft Word, Adobe applications, AppleWorks, and the 35 | text fields in Camino and Firefox won't work with this hint. 36 | 37 | I expect that all users of OS X can get something out of this guide. I'm 38 | starting with the basics, so that new users, unfamiliar with the terminal and 39 | the intricacies of OS X can be brought up to speed. But even the most 40 | experienced users should hopefully learn something from this article; I know 41 | I learned several new nifty things while writing it. 42 | 43 | **Disclaimer**: it is possible, when mucking around with the text system, to 44 | send applications messages they aren't expecting. This can cause them to 45 | crash. As long as you stick to standard text selectors, you should be fine, 46 | but I'm not responsible if your program crashes because of a binding you add. 47 | 48 | Terminology 49 | ----------- 50 | 51 | Before delving too deeply into the intricacies of the Cocoa text system, it 52 | helps to understand some programmer jargon. 53 | 54 | * The **_[Insertion Point][wp-insertion]_** (sometimes called the *caret*) 55 | is the blinking vertical line that shows where text typed into a text box 56 | will show up. 57 | 58 | * A **_Buffer_** is the text field currently being edited. This might be a 59 | text box in an online form in Safari, or the main window in TextEdit. 60 | 61 | * **_[Key Bindings][wp-bindings]_**, often called 'keyboard shortcuts', 62 | define what happens when any key is typed in an application. For instance, 63 | in a Mac text editor, the 'a' key inserts an `a`, 'Opt-e, e' inserts an 64 | `é`, and 'Ctrl-a' moves the insertion point to the beginning of the 65 | current line. 66 | 67 | * A **_[String][wp-string]_** is a chunk of text, literally a 'string' of 68 | letters. 69 | 70 | * A **_[Method][wp-method]_** is a function that an object (which includes 71 | just about everything in Cocoa) can perform. 72 | 73 | * A **_Selector_** is the name of a method. It is a string. Something like 74 | `"insertTab:"`, or `"save:"` 75 | 76 | * The **_Mark_** is an invisible point somewhere in the document, which can 77 | be set, and then returned to. Marking is the way regions of text were 78 | selected in UNIX text editors back in the days before they could be 79 | highlighted in blue with a mouse drag. 80 | 81 | * To **_Kill_** some text is basically the same as using the 'Cut' command, 82 | but in OS X uses a separate mechanism, that is localized to the current 83 | buffer. By default 'Ctrl-k' kills everything after the insertion point on 84 | the current line. 85 | 86 | * **_Yank_** is the analog of the 'Paste' command. By default, 'Ctrl-y' 87 | yanks back whatever was most recently killed. 88 | 89 | [wp-insertion]: http://en.wikipedia.org/wiki/Insertion_point 90 | [wp-bindings]: http://en.wikipedia.org/wiki/Keyboard_shortcut 91 | [wp-string]: http://en.wikipedia.org/wiki/String_%28computer_science%29 92 | [wp-method]: http://en.wikipedia.org/wiki/Method_%28computer_science%29 93 | 94 | Many of these terms crop up in the venerable [Emacs][emacs] editor, so reading 95 | about them in the Emacs context can be enlightening: [Buffer][em-buffer], 96 | [Key Bindings][em-bindings], [Mark][em-mark], [Kill][em-kill] 97 | 98 | [em-buffer]: http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Buffers 99 | [em-bindings]: http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Key%20Bindings 100 | [em-mark]: http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Mark 101 | [em-kill]: http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Killing 102 | [em-yank]: http://www.cs.cmu.edu/cgi-bin/info2www?(emacs)Yanking 103 | 104 | Existing (Default) Functionality 105 | -------------------------------- 106 | 107 | Most users of Mac OS X, even long-time Apple geeks, know only a fraction of 108 | the available text system shortcuts. This is a tragedy, as they are consistent 109 | across all applications which use the Cocoa text system, including TextEdit, 110 | Mail, iChat, Safari, and countless third-party applications. 111 | 112 | ### Simple Text Insertion ### 113 | 114 | One thing every user knows is that when a plain letter is typed (assuming the 115 | input method in use matches the keyboard), that letter is inserted into a 116 | selected text box. When the shift key is held down, letters are capitalized, 117 | and symbol keys input the second symbol shown on them. For instance 'Shift-]' 118 | inputs the '}' character. 119 | 120 | It is possible to see all of the possibilities using the 121 | '[Keyboard Viewer][apple-kv]' palette: 122 | 123 | [apple-kv]: http://www.apple.com/macosx/tips/keyboard11.html 124 | 125 | ![Keyboard viewer--full sized](Images/full-kb.png) 126 | ![Keyboard viewer--laptop](Images/laptop-kb.png) 127 | 128 | In addition, the option key, both alone and in conjunction with the shift key, 129 | will change the characters inserted. So 'Option-y' inserts a '¥' currency 130 | mark, and 'Option-Shift-c' inserts a capital cedilla: 'Ç'. We can see 131 | how option affects our input options using the Keyboard Viewer: 132 | 133 | ![Keyboard viewer--full sized--option key](Images/full-kb-opt.png) 134 | ![Keyboard viewer--full sized--shift+option](Images/full-kb-opt-shift.png) 135 | 136 | Users with full keyboards have a complete number pad, with an enter key 137 | (instead of return), and symbols used in arithmetic. This number pad is 138 | available to PowerBook and iBook users as well. The numlock key (Fn-F6), 139 | enables the small symbols printed at the lower right corner of powerbook keys 140 | to be input. But even more usefully, those keys can also be used as a number 141 | pad while the Fn key is held down. This is great for typing lots of numeric 142 | data, and also comes in handy when playing games that allow vertical, 143 | horizontal, and diagonal movement via the number pad: 144 | 145 | ![Keyboard viewer--laptop--function key](Images/laptop-kb-fn-numpad.png) 146 | 147 | Of course, there are a number of standard actions that the above pictures 148 | don't show. For instance, when you type 'Command-left', the insertion 149 | point moves to the beginning of the current line. Also, OS X has a fairly 150 | large number of unix/emacs bindings built in. 151 | 152 | The complete list of these extra commands takes up too much space for this 153 | page, so I've made them into a [separate document](system-bindings.html). 154 | 155 | Default key bindings 156 | -------------------- 157 | 158 | OS X has three main files which specify the key bindings used by Cocoa 159 | applications: 160 | 161 | /System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict 162 | 163 | /Library/KeyBindings/DefaultKeyBinding.dict 164 | 165 | ~/Library/KeyBindings/DefaultKeyBinding.dict 166 | 167 | which contain, respectively, the default 'built-in' key bindings, system-wide 168 | custom keybindings, and a user's personalized key bindings. Don't edit the 169 | built-in `/System/Library/` file, as this could seriously hose your machine. 170 | Note that as usual, personalized bindings override the built-in standards. 171 | 172 | If the `DefaultKeyBinding.dict` file doesn't exist, don't worry. Simply making 173 | a `KeyBindings` folder in `~/Library`, and then adding a new text file should 174 | do the trick. 175 | 176 | ### File Format: ### 177 | 178 | This file is a normal [Property List][appledev-plist], which can be created 179 | either with a text editor, such as [TextWrangler][t-w], [Smultron][smultron], 180 | or [TextMate][t-m], or with Apple's Property List Editor, which is installed 181 | with the developer tools. Property lists are pervasive in OS X, and are used 182 | for all sorts of configuration files, and preferences. Any file which has a 183 | `.plist` or `.dict` extension is a property list. Every application has an 184 | `info.plist` file inside of it which tells OS X what types of files that 185 | application can handle. Smart folders (`.savedSearch` files) are property 186 | lists. The `defaults` command, which can be run from the terminal, is a quick 187 | way to edit single items in a property list. 188 | 189 | There are two types of property lists, old-style NeXT text files, and newer 190 | XML formatted files. I will use the old-style plists in this how-to, because 191 | they are easier to read and understand; they are more compact, with less 192 | distracting markup. 193 | 194 | **The NeXT property list format** is a file format that can describe, using 195 | plain text, all of the objects used in Cocoa programs. We specifically care 196 | about 3 types: 'strings', 'lists', and 'dictionaries': 197 | 198 | * A *string* is simply a sequence of letters, numbers, and symbols, 199 | such as: 200 | 201 | "this is a string with some $#@! symbols" 202 | 203 | * A *list* is, like it sounds, a list of other objects, such as 204 | lists or strings: 205 | 206 | ("a", "list", "can", "contain", "many", "strings") 207 | 208 | * A *dictionary* contains pairs of "keys" and "values". Basically, 209 | dictionaries provide a way to name a bunch of objects, and refer 210 | to them by name. Note that while dictionary keys must be strings, 211 | the values can be any type of object. 212 | 213 | {"key1" = "value1"; "key2" = "value2"; "key3" = ("a", "list");} 214 | 215 | * In addition, *comments* can be added to old-style property lists 216 | by enclosing some text in `/*` and `*/` 217 | 218 | Every property list has a root dictionary object, which can contain 219 | sub-objects. A simple plist file might look like: 220 | 221 | { 222 | /* ** THIS IS A COMMENT: ** 223 | * 224 | * Notice that each line in the dictionary has a 'key' string, 225 | * and a 'value', which can be a string, a list, or another 226 | * dictionary. 227 | */ 228 | 229 | "My String" = "Hey there!"; 230 | 231 | "My List" = ("first string", "second string", "final string"); 232 | 233 | "My Dictionary" = { 234 | "Sub-string A" = "This is a string inside a dictionary"; 235 | "Sub-list B" = ("This is a list", "inside a dictionary"); 236 | }; 237 | } 238 | 239 | This property list has three key-value pairs: a string, a list, and a 240 | dictionary. 241 | 242 | ### The format of DefaultKeyBinding.dict ### 243 | 244 | The `DefaultKeyBindings.dict` file is fairly straight-forward. It is a normal 245 | property list, which as keys, uses the requested key bindings, and as values 246 | uses the commands they should execute. For instance, I might want the letter 247 | `a` to not type 'a', but instead insert a tab. If I put the following in my 248 | `DefaultKeyBinding.dict`, then all Cocoa apps launched afterwards will insert 249 | a tab key instead of an `a`: 250 | 251 | { 252 | /* This will make all a's turn to tabs. Beware. */ 253 | "a" = "insertTab:"; 254 | } 255 | 256 | #### How to represent bindings #### 257 | 258 | But of course, if we could only bind things to letter keys, this wouldn't 259 | really be so useful, now would it? Fortunately, Apple's engineers made sure 260 | that every key that you could possibly ever type can be put into a binding. 261 | 262 | The way it works is simple. For lower-case and capital letters, simply type 263 | the letter into the string. So `"y"` represents the 'y' key, while `"T"` 264 | represents 'Shift-t'. For numbers and symbols, including space, the same 265 | holds. So `"!"` represents 'Shift-1', or however you type '!' on your keyboard 266 | layout. To add modifier keys, add a symbol corresponding to that modifier: 267 | 268 | > `"@t"` = Command-t 269 | > `"^t"` = Control-t 270 | > `"~t"` = Option-t 271 | > `"@^T"` = Command-Control-Shift-t 272 | > `"~ "` = Option-space 273 | 274 | For numbers and symbols, to add the shift key is not as easy as typing a 275 | capital letter, so `$` stands for shift. Also, there is a difference between 276 | numbers above the letter keys, and numbers on the keypad. To indicate keypad 277 | keys, use `#`: 278 | 279 | > `"@$#5"` = Command-Shift-Numpad 5 280 | > `"^6"` = Control-6 281 | 282 | **Note:** Lots of bindings with the Command key won't work. This is done by 283 | Apple to ensure that applications can use these shortcuts for themselves, and 284 | not worry about user key bindings. Some will work, however, such as 285 | 'Command-right arrow'. 286 | 287 | There are still 2 limitations: First, what do we do if we want to bind a 288 | literal '@' or '#' symbol? We *escape* it! By adding a `\\` before the symbol, 289 | we can avoid this. At the moment, the only way I can get ‘\’ itself to bind to 290 | anything is by writing it as ‘\\U05C’. 291 | 292 | > `"~\\$"` = Option-$ 293 | 294 | Second, if we were limited to symbols and modifiers, we would still cut off 295 | keys like 'delete', 'tab', and 'esc', so any keys that aren't already covered 296 | can be entered using their unicode values: 297 | 298 | #### Unicode values for Apple non-letter keys: #### 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 |
Escape: \U001B
 
Tab: \U0009
Backtab: \U0019
 
Return: \U000A
Enter: \U000D
 
Delete: \U007F
 
Up Arrow: \UF700
Down Arrow: \UF701
Left Arrow: \UF702
Right Arrow: \UF703
 
Help: \UF746
Forward Delete:\UF728
Home: \UF729
End: \UF72B
Page Up: \UF72C
Page Down: \UF72D
 
Clear: \UF739
 
F1: \UF704
F2: \UF705
F3: \UF706
...
F35 \UF726
 
Not on Apple keyboards:
 
Menu: \UF735
335 | 336 | **Notes:** 337 | 338 | * 'Backtab' is 'Shift-Tab' 339 | * The key labeled 'Backspace' on most PC keyboards is the 'Delete' key 340 | * The 'Num Lock' key on PC keyboards is 'Clear' 341 | * The keys labeled 'Print Screen', 'Scroll Lock', and 'Pause' are 342 | respectively 'F13', 'F14', and 'F15' 343 | * The key labeled 'Insert' is the 'Help' key 344 | * I'm not sure whether the 'Menu' key actually does anything, as I don't own 345 | a keyboard with that key on it. 346 | 347 | For a complete list, including some keys that aren't on current apple 348 | keyboards, but can still be used by OS X, see the [Registry][apple-ucode] 349 | of Apple Unicode corporate-zone characters. 350 | 351 | In general, the best way I've found to discover key's escape codes is to use 352 | the free [Key Codes][keycodes] application from Peter Maurer. The app brings 353 | up a floating palette which prints a log of all the keys typed. 354 | 355 | [keycodes]: http://www.petermaurer.de/nasi.php?section=keycodes 356 | 357 | #### More complicated bindings and actions #### 358 | 359 | Of course, sometimes we wish we had more keys on the keyboard. Even with all 360 | of the modifier keys, it gets hard to keep different functionality separated, 361 | and things get confused. For this reason, it is possible to use 362 | multiple-keystroke bindings. To this end, instead of binding our first 363 | keystroke to a selector, we bind it to a dictionary, containing the second 364 | keystrokes. Emacs, the UNIX-based text editor, has many such 365 | multiple-keystroke bindings. Therefore, as an example of how this can be done, 366 | we will take Emacs bindings, and try to replicate them in Cocoa Text Widgets. 367 | 368 | One Emacs command is 'Control-x, u', for 'undo'. Another is 'Control-x, 369 | Control-s' for 'save'. To add this command to our key bindings, we need to 370 | bind 'Control-x' to a dictionary of sub-bindings: 371 | 372 | { 373 | /* Control-x dictionary */ 374 | "^x " = { 375 | "u" = "undo:"; /* C-x u => undo */ 376 | "^s" = "save:"; /* C-x C-s => save */ 377 | }; 378 | } 379 | 380 | Our 'Control-x' parent dictionary can have several multiple-keystroke bindings 381 | associated with it. In this way, we can have whole areas of functionality 382 | given to one 'parent' key binding, with the resulting action to be determined 383 | by a letter. We can effectively have 4 or 5 keyboards for our bindings! 384 | 385 | But of course, the number of bindings is not our only limitation so far. We 386 | are also limited by the range of selectors offered by the text box. We often 387 | find ourselves performing complicated actions repeatedly, and would like to 388 | invoke them with single keystroke. Mostly when this happens, Applescript, or 389 | some other programming language is the best solution. On occasion, however, 390 | the text system has enough power and flexibility to do the trick. This is 391 | because, besides single selectors, a binding can also execute a list of 392 | selectors, sequentially. 393 | 394 | As an example, imagine that I often want to change paragraphs of text to all 395 | capital letters, but I'm tired of selecting the whole paragraph with my 396 | keyboard or mouse. I want 'Control-Option-u to make my paragraph all 397 | uppercase, and then I want it to start a new paragraph by inserting two new 398 | lines at the end of the paragraph. 399 | 400 | This (somewhat contrived) action can be broken into steps: 1. Select paragraph 401 | 2. Make all the letters uppercase 3. Move to the end of the paragraph 4. 402 | Insert two new lines. 403 | 404 | We can make a plist of these directions: 405 | 406 | { 407 | "^~u" = ("selectParagraph:", 408 | "uppercaseWord:", 409 | "moveToEndOfParagraph:" 410 | "insertNewline:", 411 | "insertNewline"); 412 | } 413 | 414 | So, with the the ability to map multiple-keystroke bindings to sets of actions 415 | that can perform complicated behaviors, what's left? 416 | 417 | Every time you type a key, the Cocoa text system looks for bindings, and if 418 | none are found for the key, it instead passes the keystroke along as a string 419 | input to the `insertText:` selector. Well, as luck would have it, 420 | [Kevin Ballard][kevin], from the [##textmate][tm-channel] IRC channel on 421 | [freenode][freenode] (a delightful place to chat, incidentally), found a real 422 | gem, that doesn't seem to be documented anywhere on Apple's website, or 423 | anywhere else: **It is possible to use the `insertText:` selector as part of a 424 | binding, and thereby bind an arbitrary string to a keystroke.** If we bind a 425 | key to a list, containing `"insertText:"` as one of its strings, the next 426 | string in the list will be inserted into the text field. Example: 427 | 428 | { 429 | /* Realize that actually using this will render your a key 430 | amusingly useless.*/ 431 | "a" = ("insertText:", "some fun text", "moveWordBackward:"); 432 | } 433 | 434 | as a DefaultKeyBinding.dict file will make the 'a' key type 'some fun text', 435 | and then move the insertion point to the beginning of the word 'text', instead 436 | of the simply typing an 'a', as usual. 437 | 438 | [kevin]: http://kevin.sb.org/ 439 | [tm-channel]: irc://irc.freenode.net/##textmate 440 | [freenode]: http://freenode.net/ 441 | 442 | This is amazingly useful if there are some symbols or strings which must be 443 | entered on a regular basis. For instance, imagine that I sometimes need to 444 | type LaTeX Greek letters, and also sometimes need the associated unicode 445 | symbols (for alpha, beta, etc.). The following `DefaultKeyBinding.dict` could 446 | reduce this load considerably: 447 | 448 | { 449 | /* Greek unicode letters */ 450 | "^g" = { 451 | "a" = ("insertText:", "\U03B1"); 452 | "b" = ("insertText:", "\U03B2"); 453 | "g" = ("insertText:", "\U03B3"); 454 | "d" = ("insertText:", "\U03B4"); /* 455 | ... */ 456 | } 457 | 458 | /* Greek LaTeX letters */ 459 | "^m" = { 460 | "a" = ("insertText:", "\\alpha"); 461 | "b" = ("insertText:", "\\beta"); 462 | "g" = ("insertText:", "\\gamma"); 463 | "d" = ("insertText:", "\\delta"); /* 464 | ... */ 465 | } 466 | } 467 | 468 | Now, when I type 'Control-g, a', 'α' will be inserted instead, and when 469 | I type 'Control-m, g', '\gamma' will be inserted, etc. 470 | 471 | It seems like this behavior is just an exception, as I haven't found any other 472 | selectors which take an argument, but it's a glorious exception, for which I 473 | can envision some truly creative uses. 474 | 475 | For instance, if I want to drive some friends bonkers, I could set 476 | `DefaultKeyBinding.dict` up to [ROT13][wp-rot13] all of my letters, to enable 477 | "typing in code". Or I could set it up to allow typing in [leetspeak][wp-leet] 478 | ("1337"). 479 | 480 | Most obviously perhaps, I could bind common phrases or code snippets to simple 481 | keystrokes. This would allow systemwide text shortcuts without the need for 482 | third-party applications (though the third party applications out there, 483 | notably Peter Maurer's [Textpander][textpander], do a lot more than key 484 | bindings allow). 485 | 486 | One binding that I made, and **it's one of my favorites**, allows me to type 487 | html and xml tags with ease. I have Control-shift-h make a starting and tag 488 | pair out of the word I've just finished typing, and put the cursor in the 489 | middle of them. Here's the code: 490 | 491 | { 492 | /* This command will let Ctrl-Shift-H turn the previous word 493 | * into an HTML/XML opening and closing tag pair. */ 494 | "^H" = ( "setMark:", 495 | "moveWordBackward:", 496 | "deleteToMark:", 497 | "insertText:", "<", 498 | "yank:", 499 | "insertText:", ">", 500 | "setMark:", 501 | "insertText:", "", 504 | "swapWithMark:"); 505 | } 506 | 507 | Finally, the possibilities for pranks on coworkers, significant others, etc. 508 | is considerable. For instance, we can set the keyboard up to malfunction on a 509 | couple of letters, maybe a 'z' could [say][apple-speech] "you didn't 510 | \*really\* want to type that, did you?": 511 | 512 | { 513 | "z" = ("setMark:", 514 | "insertText:", 515 | "you didn't *really* want to type that, did you?", 516 | "selectToMark:", 517 | "speakText:"); 518 | } 519 | 520 | [wp-rot13]: http://en.wikipedia.org/wiki/ROT13 521 | [wp-leet]: http://en.wikipedia.org/wiki/Leet 522 | [textpander]: http://www.petermaurer.de/nasi.php?section=textpander 523 | [apple-speech]: http://www.apple.com/macosx/features/speech/ 524 | 525 | Moving right along, now that we have the idea of how to form our bindings, we 526 | can get to figuring out exactly which selectors are available to us. 527 | 528 | ### Usable selectors ### 529 | 530 | It is hard to figure out exactly which selectors a text box, and more 531 | generally, an application, will respond to. There are a huge number of 532 | options, but they are not all documented in one place. This is partly because 533 | if one object in an application doesn't respond to a particular message, it 534 | will pass the message along to its parent object. 535 | 536 | Still, we can find a large number of useful selectors by searching through the 537 | documentation we can find, and testing what the selectors do. The biggest 538 | source of selectors that we might want to use is in the NSResponder class -- 539 | see its [documentation][appledev-nsres]. Specifically, we care about the 540 | 'Action methods' section. Also, the [documentation][appledev-nstext] for 541 | NSText has some selectors we can use, and many other classes provide useful 542 | selectors as well, such as NSDocumentController and NSWindow. 543 | 544 | Because there are so many usable selectors, I'm putting them in a separate 545 | page. [Here's a link](selectors.html). 546 | 547 | ### Examples ### 548 | 549 | I've put together some examples of how this could be used. To use one of 550 | these, simply rename the file to `DefaultKeyBinding.dict` and plop it in the 551 | `~/Library/KeyBindings` folder. One of the most common uses of custom key 552 | bindings is emulating another operating system or environment, such as Windows 553 | or Emacs or BBEdit: 554 | 555 | * Emacs emulation [key bindings with esc as meta key](KeyBindings/Emacs Esc Bindings.dict) 556 | * Emacs emulation [key bindings with opt as meta key](KeyBindings/Emacs Opt Bindings.dict) 557 | * BBEdit emulation [key bindings](KeyBindings/BBEdit Bindings.dict) (far 558 | from complete) 559 | * Windows emulation [key bindings](KeyBindings/Windows Bindings.dict) 560 | (_I'm still working on this one, if someone has a list of windows 561 | default key behaviors, email me: jacobolus \[at\] gmail.com_) 562 | 563 | Beyond that, it's possible make key bindings as pranks. That's always fun: 564 | 565 | * [Leet bindings](KeyBindings/Leet Bindings.dict) 566 | * [Greek bindings](KeyBindings/Greek Bindings.dict) 567 | 568 | Text System Defaults 569 | -------------------- 570 | 571 | Besides making our own key bindings, there are a few other nifty changes we 572 | can apply to the Cocoa text system, using the "defaults" system. Apple's 573 | developer site [tells about them][appledev-text-system-defaults]. Some of 574 | these defaults are for unimplemented features, and are therefore worthless to 575 | us. There are three defaults however which are of interest to us here. They 576 | can be set using the `defaults` terminal command. I will show them applying 577 | globally with the `-g` flag, but it is possible to set them on an application 578 | by application basis, by for instance specifying `com.apple.textedit` instead 579 | of `-g`. 580 | 581 | * `NSTextKillRingSize` 582 | 583 | This default sets the size of the kill ring. It can be set as follows: 584 | 585 | defaults write -g NSTextKillRingSize -string 4 586 | 587 | This changes the size of the "kill ring" which large deleted blocks of 588 | text get copied to. In this case, I have set it to keep track of the 4 589 | most recent such blocks. This means that this text can be cycled through, 590 | and won't be lost as soon as more text is killed. An extra binding is 591 | useful in dealing with a kill ring: `yankAndSelect:`, which cycles through 592 | the kill ring. 593 | 594 | * `NSRepeatCountBinding` 595 | 596 | This one is one of the coolest features of the text system. In emacs, 597 | pressing "Control-u", and then a number, 94 say, and then any other 598 | command, will repeat that command 94 times. It is possible to set OS X to 599 | do the same thing with "Control-u" as follows: 600 | 601 | defaults write -g NSRepeatCountBinding -string "^u" 602 | 603 | Of course, any other binding could be set instead of "Control-u". 604 | 605 | * `NSQuotedKeystrokeBinding` 606 | 607 | This default is normally linked to Control-q. It causes the next 608 | keystroke typed to be passed through the system, without activating any 609 | bindings. For example, if the "Option-v" is bound to scroll up in the 610 | key bindings file, a square root sign -- √ -- can still be entered by 611 | typing "Control-q, Option-v". 612 | 613 | Input Managers 614 | -------------- 615 | 616 | NeXT and Apple realized, when they created Cocoa, that many actions could not 617 | be foreseen by their framework developers. The key binding system is great if 618 | we want to stick within the usual sorts of operations on English text, such as 619 | transposing two letters, skipping the end of a paragraph, or upper-casing a 620 | word, and we can combine these simple actions, but sometimes to do what we 621 | want requires more. 622 | 623 | An *input manager* is a piece of code which is loaded into every running Cocoa 624 | application. The purpose of an input manager is to extend the text system in 625 | ways not thought of by the application's original programmers. 626 | 627 | We've all been hearing of late about how input managers can be used for 628 | nefarious purposes, but as long as they stick to modifying the text system, 629 | they mostly stay out of trouble, and they can be incredibly useful. Two input 630 | managers in particular are quite popular: 631 | 632 | * First, Mike Ferris's [TextExtras][textextras] extends the Cocoa 633 | text system in ways that programmers, particularly, will find 634 | useful. I haven't spent too much time playing with TextExtras, 635 | especially since [TextMate][t-m], my editor of choice, 636 | doesn't quite use the same Cocoa controls as other Cocoa-based 637 | editors like [SubEthaEdit][s-e-e] and [Smultron][smultron]. But 638 | TextExtras adds quite a bit to the Cocoa text system, including 639 | indent wrapping, auto-indentation, showing and selecting matching 640 | braces, improved completion, and, perhaps most of all, customized 641 | piping of text through shell commands. This allows all sorts of 642 | snazzy behavior (note that editors like [TextWrangler][t-w] and 643 | [TextMate][t-m] have their own implementations of this feature). 644 | 645 | * Second, one of my favorite text-system extensions is 646 | [Michael McCracken][mike-mcc]'s [Incremental Search Input Manager][isim] 647 | (ISIM). Here's a [link to a zip-file of the universal binary][isim-univ]. 648 | 649 | ISIM is an input manager that provides three new selectors for binding in 650 | our `DefaultKeyBinding.dict` file: `ISIM_incrementalSearch:`, 651 | `ISIM_reverseIncrementalSearch:`, and `abort:` (that last one may 652 | work for other things, I'm not sure). The idea is pretty simple, but 653 | incredibly useful. Basically, when the selector is invoked, a little 654 | window pops up at the bottom of the current text box. When you type 655 | into this little window, ISIM searches through the current document 656 | searching for text that matches, and selects the first occurrence of 657 | such text. Repeatedly invoking the selector flips through any other 658 | occurrences in the document. A picture can say this better than I can: 659 | 660 | ![Incremental Search Input Manager](Images/incremental-search.png) 661 | 662 | The relevant part of my key bindings file looks like this: 663 | 664 | /* Incremental search */ 665 | "^s" = "ISIM_incrementalSearch:"; 666 | "^r" = "ISIM_reverseIncrementalSearch:"; 667 | "^$g" = "abort:"; 668 | 669 | * Finally, for those who can't get enough customization in a straight 670 | NSTextView, using the techniques described already, Gus Mueller made an 671 | input manager, described in two [blog][gus-im-1] [posts][gus-im-2], which 672 | allows the contents of any Cocoa text field to BBEdit. Type the relvant 673 | key, and your text will pop up in a new BBEdit document. Save, and the 674 | text in the original text field is updated. It's awesome. According to the 675 | second post, modifying it to work with any editor which uses the ODBEditor 676 | suite (used mainly by FTP programs to open remote files in a local text 677 | editor) would be easy--it's open source. 678 | 679 | TextMate, my editor of choice, comes with a similar input manager, I 680 | believe inspired by the first one. And the great thing about TextMate's 681 | version is that it works in Mail (I'm not sure, but I think Gus's 682 | doesn't). If there's a text editor you like, it's extremely nice to be 683 | able to edit Safari form fields, emails, and other text using that editor. 684 | 685 | [gus-im-1]: http://www.gusmueller.com/blog/archives/2004/2/5.html 686 | [gus-im-2]: http://www.gusmueller.com/blog/archives/2005/12/17.html 687 | 688 | Even Lower-Level Hacking: Keyboard Layouts 689 | ------------------------------------------ 690 | 691 | First, we haven't seen any way to remap modifier keys so far. This can be 692 | easily accomplished using the Keyboard and Mouse preference pane. Click the 693 | 'modifier keys' button at the bottom of the view, and a nice sheet pops up. 694 | Mine, which I've set to put the keys on a [Model M][wp-modelm] keyboard in the 695 | right places, with 'Control' where it belongs next to the 'A' key, looks like 696 | this: 697 | 698 | ![Keyboard Pref Pane](Images/keyboard-pref-pane.png) 699 | 700 | [wp-modelm]: http://en.wikipedia.org/wiki/Model_M_Keyboard 701 | 702 | For even finer control over the keyboard, it is possible to create 703 | [customized keyboard layouts][tn-keylayouts]. These allow any unicode glyphs 704 | to be mapped to the keys on the keyboard, so alternate language scripts can be 705 | entered, etc. This will work across the OS, not just in Cocoa text editors, 706 | but is also a much lower-level change, which means that messing it up could be 707 | much worse. I haven't actually ever used any layouts other than U.S. on my 708 | PowerBook, so I don't know how easy this is. There is a pretty nice GUI 709 | editor for this from SIL called [Ukelele][ukelele]. It has great 710 | documentation, and should be all that is needed to make custom keyboard 711 | layouts. 712 | 713 | [ukelele]: http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=ukelele 714 | [tn-keylayouts]: http://developer.apple.com/technotes/tn2002/tn2056.html 715 | 716 | Finally, for the truly adventurous, it is apparently possible to go even 717 | lower-level than Ukelele, and patch the [ADB][adb] codes which are registered 718 | by Apple's USB keyboard drivers. I'm not sure exactly which versions of OS 719 | X this works with, and any hacking at this level requires a serious 720 | disclaimer, as a wrong move here could really mess up your system. But here 721 | [are][snark1] [two][snark2] links at snark.de which discuss such arcane 722 | trickery. Good luck to any who try this. This same guy (Heiko Hellweg) also 723 | [made his own][snark3] keyboard layout, and patched Apple's keyboard drivers 724 | to give himself a meta key: 725 | 726 | > "I got myself the Tiger-Version of the ADB Keyboard Driver 727 | > (AppleADBKeyboard-238.3.4) and hacked away in XCode. My current setup uses 728 | > the obnoxious enter key (between the cursor keys and the right command 729 | > key) as the alt modifier (you can do that without a compiler by just 730 | > [fiddling with info.plist][snark1]) and turns the original alt-key on the left 731 | > onto a META key that sends escape in front of every other key as long as 732 | > it is pressed (for this one, i needed to replace 733 | > ``/System/Library/Extensions/AppleADBKeyboard.kext`` with an actual 734 | > modified binary). 735 | > 736 | > "Now i can actually type ahead blindly without thinking twice. Contact me, 737 | > if you are interested in using this too." 738 | 739 | Needless to say, I wouldn't advise trying this, unless you know what you are 740 | doing. 741 | 742 | [adb]: http://developer.apple.com/documentation/mac/Devices/Devices-203.html 743 | [snark1]: http://www.snark.de/index.cgi/0007 744 | [snark2]: http://www.snark.de/mac/usbkbpatch/index_en.html 745 | [snark3]: http://www.snark.de/index.cgi/0006 746 | 747 | Useful Links 748 | ------------ 749 | 750 | *TODO: Much of this list of links is still incomplete* 751 | 752 | ### Text Editors ### 753 | 754 | Free Cocoa text editors for OS X: 755 | 756 | * [TextEdit][textedit] -- Comes on every Mac 757 | * [Smultron][smultron] -- Clean, simple, Open-source text editor. 758 | Named after some sort of Scandinavian strawberry. Can't beat free! 759 | 760 | Commercial Cocoa text editors: 761 | 762 | * [TextMate][t-m] -- most awesome text editor ever. I really can't 763 | recommend this one enough. If you type lots of text, whether it's 764 | C or Python code, [LaTeX][latex], [John Gruber][gruber]'s 765 | [Markdown][mdown], or anything else, TextMate is amazing. It uses a 766 | different text box than the usual Cocoa one, so not all of the 767 | things discussed here will work, for instance, tying multiple commands 768 | to one binding, or using multiple keystroke commands. Still, TextMate 769 | allows far more customization than NSText widgets in general, so 770 | custom system bindings aren't as necessary. 771 | * [SubEthaEdit][s-e-e] -- Nifty collaborative editor, which allows 772 | people halfway around the world from each-other to work on the same 773 | text file at once. This editor kicks all kinds of ass when it comes 774 | to collaborative note taking, or pair programming. It's not too shabby 775 | for solo programming either. 776 | 777 | Non-Cocoa text editors for OS X: 778 | 779 | * [TextWrangler][t-w] -- Excellent (free!) editor from [Bare Bones][b-b]. 780 | Not Cocoa, so the keybindings described in this how-to won't work, 781 | but a great Mac citizen nonetheless, with lots of scriptability, 782 | and excellent documentation. 783 | * [BBEdit][bbedit] -- [Bare Bones][b-b]'s flagship editor. $200, or 784 | $130 as an "upgrade" from the free TextWrangler, or $50 for 785 | educational users. Steep pricing, but does most everything you'd 786 | ever expect a text editor to do, and more. I think I still like 787 | TextMate better, but Mac users have sworn by BBEdit for almost as 788 | long as I've been alive. 789 | 790 | ### Apple Developer Documentation ### 791 | 792 | Apple has some documentation for the key bindings, but all in all it is far 793 | from adequate, especially for regular users, as opposed to competent 794 | Objective-C hackers. 795 | 796 | * [About Key Bindings][appledev-keybindings] -- A brief note. 797 | * [Text System Defaults and Key Bindings][appledev-text-system-defaults] 798 | -- A longer explanation of some of the possibilities with key 799 | bindings, which also shares some cool text system defaults, 800 | editable from the command line. 801 | * [The NSResponder class][appledev-nsres] -- The NSResponder 802 | class is chock full of useful selectors to try to bind keys to. 803 | * [Text Input Management][appledev-text-input] -- This extensive 804 | article is far beyond the scope of this guide, and also only 805 | somewhat relevant. It details the nitty gritty of the Cocoa 806 | Text system, including information on how to create your own 807 | input managers. 808 | * [Introduction to Property Lists][appledev-plist] -- Apple's 809 | documentation of the property list format, covering both old-style 810 | and XML formats. 811 | * [Registry of Apple use of Unicode corporate-zone characters.][apple-ucode] 812 | -- not at Apple.com, but this text document tells the unicode values 813 | of all the control keys we want to put in our bindings. 814 | 815 | ### Third-party documentation ### 816 | 817 | * Llew Mason's pretty good [explanation][lsmason] of key bindings in OS X 818 | * A page at [Cocoa Dev][cocoadev] about them 819 | * A page by 'misaka' at [deepsky.com][deepsky] 820 | * Shane Celis' description at [gnufoo.org][gnufoo] 821 | * [An example key bindings file](http://www.algorithm.com.au/files/mac_os_x/DefaultKeyBinding.dict) 822 | * Michael C Thornburgh has some Vi-ish keybindings at his site, 823 | [armory.com][armory], in xml plist format. 824 | * David Pogue's [comparison][pogue] of keyboard shortcuts on Windows and on 825 | the Mac. 826 | 827 | ### Key Bindings Editors ### 828 | 829 | * Gerd Knops's [Key Bindings Editor][kbe] is a Cocoa application which 830 | allows the viewing and editing of key bindings files. It knows where the 831 | system, XCode, and TextMate key bindings are, and allows html and plain 832 | text export. 833 | * Mikael Langer's [TextMacro][textmacro] does some stuff which is no 834 | longer needed... it's an input manager which allows arbitrary text to be 835 | input with key bindings, and is supposed to provide for multiple sets of 836 | key bindings which can be swapped out. It is implemented as a preference 837 | pane. 838 | 839 | ### Input Managers ### 840 | 841 | * [Incremental Search Input Manager][isim] 842 | * [TextExtras][textextras] 843 | * [XML Tag Input Manager][xml-im] -- Annard Brouwer's free input manager 844 | for selecting XML/HTML tags; it lets your mouse get in on the text system 845 | action. 846 | 847 | ### Tangentially-related MacOSXHints hints ### 848 | 849 | * [*Prewrap Lines in Mail.app*][mxh-prewrap] discusses TextExtras, and 850 | gives an example of an application. 851 | * [*Find and replace special characters in Cocoa apps*][mxh-find-replace] 852 | -- A hint by [Bill Bumgarner][bbum] about `NSQuotedKeystrokeBinding`, 853 | which is Control-q by default. 854 | * [Enabling meta-key Emacs shortcuts in Cocoa apps][mxh-emacs] -- this one 855 | isn't really so tangential: it shows users how to get emacs emulation by 856 | putting installing a custom keybinding file (the emacs emulation is not 857 | nearly as complete as ours above ;-) ). 858 | 859 | [mxh-prewrap]: http://www.macosxhints.com/article.php?story=2002060811285560 860 | [mxh-find-replace]: http://www.macosxhints.com/article.php?story=20021009063151561 861 | [mxh-emacs]: http://www.macosxhints.com/article.php?story=20010729214616497 862 | 863 | [textedit]: http://www.apple.com/support/mac101/work/23/ 864 | [smultron]: http://smultron.sourceforge.net/ 865 | [t-m]: http://macromates.com/ 866 | [t-w]: http://www.barebones.com/products/textwrangler/index.shtml 867 | [b-b]: http://www.barebones.com/ 868 | [bbedit]: http://www.barebones.com/products/bbedit/index.shtml 869 | [s-e-e]: http://www.codingmonkeys.de/subethaedit/ 870 | [emacs]: http://en.wikipedia.org/wiki/Emacs 871 | 872 | [latex]: http://en.wikipedia.org/wiki/LaTeX 873 | 874 | [textextras]: http://www.lorax.com/FreeStuff/TextExtras.html 875 | [isim]: http://leverage.sourceforge.net/wiki/index.php/Main_Page 876 | [isim-univ]: http://michael-mccracken.net/IncrementalSearchInputManager-universal.zip 877 | [xml-im]: http://homepage.mac.com/annard/FileSharing9.html 878 | 879 | 880 | [kbe]: http://www.cocoabits.com/KeyBindingsEditor/ 881 | [textmacro]: http://www.mai.liu.se/~milan/TextMacro/ 882 | 883 | [bbum]: http://www.friday.com/bbum/ 884 | [lsmason]: http://www.lsmason.com/articles/macosxkeybindings.html 885 | [cocoadev]: http://www.cocoadev.com/index.pl?KeyBindings 886 | [deepsky]: http://www.deepsky.com/~misaka/MacOSX/KeyBindings.html 887 | [gnufoo]: http://www.gnufoo.org/macosx/macosx.html#emacs 888 | [armory]: http://aldebaran.armory.com/~zenomt/macosx/KeyBindings.html 889 | [pogue]: http://www.missingmanuals.com/pub/a/oreilly/missingmanuals/2003/keystrokes_0103.html 890 | 891 | [gruber]: http://daringfireball.net 892 | [mdown]: http://daringfireball.net/projects/markdown/ 893 | [mike-mcc]: http://michael-mccracken.net/ 894 | 895 | [appledev-plist]: http://developer.apple.com/documentation/Cocoa/Conceptual/PropertyLists/PropertyLists.html#//apple_ref/doc/uid/10000048 896 | [appledev-keybindings]: http://developer.apple.com/documentation/Cocoa/Conceptual/InputManager/Concepts/KeyBindings.html#//apple_ref/doc/uid/20001037-DontLinkElementID_2050128a 897 | [appledev-text-system-defaults]: http://developer.apple.com/documentation/Cocoa/Conceptual/BasicEventHandling/Tasks/TextDefaultsAndBindings.html 898 | [appledev-nsres]: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSResponder.html 899 | [appledev-nstext]: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSText.html 900 | [appledev-text-input]: http://developer.apple.com/documentation/Cocoa/Conceptual/InputManager/index.html 901 | [apple-ucode]: http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT 902 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | This article about the Cocoa Text System was written in 2006 and hasn’t been much updated since. Its primary web home is [here](http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html) 2 | 3 | I’m putting it here in case someone wants to download the whole shebang in an easier way than traversing the links on the original page. 4 | 5 | Note, content is © 2006 Jacob Rus. -------------------------------------------------------------------------------- /selectors.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Cocoa Text System - Usable Selectors 7 | 80 | 81 |
82 |

Usable Selectors for Cocoa Key Bindings

83 | 84 |

by Jacob Rus
85 | Friday, 17 March 2006

86 | 87 |

We can use a very wide variety of selectors in our key bindings. Note, if you 88 | find more usable selectors, please let me know about them. Thanks.

89 | 90 |

Generally-applicable selectors

91 | 92 | 98 | 99 |

Undo/redo

100 | 101 | 107 | 108 |

Text manipulation

109 | 110 |

These selectors are for inserting, selecting, deleting, and moving text.

111 | 112 |

Inserting text

113 | 114 |

In general, these selectors: “Insert a … at the insertion point or selection, deleting the selection if there is one”

115 | 116 | 137 | 138 |

Deleting text

139 | 140 |

This group of selectors simply wipes text off the face of the planet.

141 | 142 | 153 | 154 |

Killing and yanking text

155 | 156 |

These selectors delete text, but also put it onto the kill ring (which means that it can be “yanked back later”):

157 | 158 | 166 | 167 |

This one brings back text:

168 | 169 | 173 | 174 |

Change the case of the selected text

175 | 176 |

“change the case of a letter or letters in the selection, perhaps by opening a panel with capitalization options or by cycling through possible case combinations.”

177 | 178 | 181 | 182 |

“set the case of the word or words surrounding the insertion point or 183 | selection, expanding the selection if necessary”

184 | 185 | 190 | 191 |

Moving the insertion point

192 | 193 |

“move the selection or insertion point one element or character”

194 | 195 | 203 | 204 |

“move the selection or insertion point one word…”

205 | 206 | 212 | 213 |

“move the selection to… or the insertion point to…”

214 | 215 | 223 | 224 |

“scroll the receiver… one page in its scroll view, also moving the insertion 225 | point to the top of the newly displayed page.”

226 | 227 | 231 | 232 |

Scroll the text view

233 | 234 |

“scroll the receiver… in its scroll view, without changing the selection”

235 | 236 | 242 | 243 |

“scroll the selection, whatever it is, inside its visible area.”

244 | 245 | 248 | 249 |

Move the insertion point and modify the selection

250 | 251 |

“expand or reduce either end of the selection by one element or character”

252 | 253 | 261 | 262 |

“expand or reduce either end of the selection… by one whole word”

263 | 264 | 270 | 271 |

Apparently some of the options are undocumented, but work just fine

272 | 273 | 283 | 284 |

Select text

285 | 286 |

“select…”

287 | 288 | 297 | 298 |

Working with marks

299 | 300 | 311 | 312 |

Other text editing options

313 | 314 | 326 | 327 |

Cut/Copy/Paste

328 | 329 | 360 | 361 |

Text Styles and formatting (mostly applies to rich text)

362 | 363 |

Set the text alignment

364 | 365 |

“applies … alignment to selected paragraphs (or all text if the receiver is 366 | a plain text object)”

367 | 368 | 374 | 375 |

“changes the base writing direction of a paragraph, for languages like Hebrew 376 | and Arabic, for example.”

377 | 378 | 383 | 384 |

Superscript/subscript

385 | 386 | 396 | 397 |

Underline/outline

398 | 399 | 404 | 405 |

Baseline, kerning, ligatures

406 | 407 |

Set the baseline of the text.

408 | 409 | 415 | 416 |

Set the kerning to be used for the text.

417 | 418 | 430 | 431 |

Tell the selection whether to use standard ligatures, or all ligatures.

432 | 433 | 448 | 449 |

Open up useful panels for text formatting

450 | 451 | 462 | 463 |

Spelling and speech

464 | 465 |

Check the spelling of the text view:

466 | 467 | 483 | 484 |

OS X Speech synthesis:

485 | 486 | 491 | 492 |

Window and document options

493 | 494 |

Printing

495 | 496 | 501 | 502 |

Closing, saving, reverting documents

503 | 504 |

These do the same as the menu options of the same name:

505 | 506 | 514 | 515 | 526 | 527 |

Window manipulations

528 | 529 |

These three simulate clicking the little gem buttons in the top left corner of 530 | the window. Note that close:, etc. are also usable selectors, but not 531 | advisable, as they act slightly differently. Most importantly, close: 532 | doesn’t prompt the user to save changes to unsaved documents, so data loss is 533 | possible if it is used:

534 | 535 | 540 | 541 |

These change window ordering or position:

542 | 543 | 550 | 551 |

This one hides the application:

552 | 553 | 557 |
558 |
Anything I can improve? Send me an email: jacobolus AT gmail
-------------------------------------------------------------------------------- /selectors.md: -------------------------------------------------------------------------------- 1 | Usable Selectors for Cocoa Key Bindings 2 | ======================================= 3 | 4 | by Jacob Rus 5 | Friday, 17 March 2006 6 | 7 | 8 | We can use a very wide variety of selectors in our key bindings. Note, if you 9 | find more usable selectors, please let me know about them. Thanks. 10 | 11 | ## Generally-applicable selectors 12 | 13 | * `cancelOperation:` -- "cancel the current operation." 14 | 15 | * `showContextHelp:` -- "invoke the help system, displaying information 16 | relevant to the receiver and its current state. The sender argument is 17 | typically the object that invoked this method." 18 | 19 | ### Undo/redo ### 20 | 21 | * `undo:` 22 | * `redo:` 23 | 24 | * `breakUndoCoalescing` -- this one sets up an undo state. So if some more 25 | text is typed, and then undo is invoked, it will come back to this point. 26 | 27 | 28 | ## Text manipulation 29 | 30 | These selectors are for inserting, selecting, deleting, and moving text. 31 | 32 | 33 | ### Inserting text ### 34 | 35 | In general, these selectors: "Insert a ... at the insertion point or selection, deleting the selection if there is one" 36 | 37 | * These two also "end editing if the receiver is a text field" 38 | 39 | * `insertTab:` 40 | * `insertNewline:` 41 | 42 | * These selectors should be used to avoid tabbing out of, for instance, a 43 | form field 44 | 45 | * `insertTabIgnoringFieldEditor:` 46 | * `insertNewlineIgnoringFieldEditor:` 47 | 48 | * `insertLineBreak:` 49 | * `insertParagraphSeparator:` 50 | * `insertContainerBreak:` 51 | 52 | * `insertBacktab:` -- "handle a 'backward tab'" 53 | 54 | * `insertText:` -- my favorite selector, "insert a string at the insertion 55 | point or selection, deleting the selection if there is one." 56 | 57 | ### Deleting text ### 58 | 59 | This group of selectors simply wipes text off the face of the planet. 60 | 61 | * `delete:` -- "deletes the selected text only" 62 | 63 | * `deleteBackward:` 64 | * `deleteForward:` 65 | * `deleteWordBackward:` 66 | * `deleteWordForward:` 67 | 68 | * `deleteBackwardByDecomposingPreviousCharacter:` -- "If the previous 69 | character is canonically decomposable, try to delete only the last 70 | character in the grapheme cluster (for example, deleting “a”+ “´” results 71 | in “a”)" 72 | 73 | 74 | ### Killing and yanking text ### 75 | 76 | These selectors delete text, but also put it onto the kill ring (which means that it can be "yanked back later"): 77 | 78 | * `deleteToBeginningOfLine:` 79 | * `deleteToEndOfLine:` 80 | 81 | * `deleteToBeginningOfParagraph:` 82 | * `deleteToEndOfParagraph:` 83 | 84 | * `deleteToMark:` -- "Delete all items from the insertion point to a 85 | previously placed mark, including the selection itself if not empty." 86 | 87 | This one brings back text: 88 | 89 | * `yank:` -- "Replaces the insertion point or selection with text from the 90 | kill buffer." 91 | 92 | ### Change the case of the selected text ### 93 | 94 | "change the case of a letter or letters in the selection, perhaps by opening a panel with capitalization options or by cycling through possible case combinations." 95 | 96 | * `changeCaseOfLetter:` 97 | 98 | "set the case of the word or words surrounding the insertion point or 99 | selection, expanding the selection if necessary" 100 | 101 | * `lowercaseWord:` 102 | * `uppercaseWord:` 103 | * `capitalizeWord:` 104 | 105 | 106 | ### Moving the insertion point ### 107 | 108 | "move the selection or insertion point one element or character" 109 | 110 | * `moveBackward:` 111 | * `moveForward:` 112 | * `moveLeft:` 113 | * `moveRight:` 114 | * `moveUp:` 115 | * `moveDown:` 116 | 117 | "move the selection or insertion point one word..." 118 | 119 | * `moveWordBackward:` 120 | * `moveWordForward:` 121 | * `moveWordLeft:` 122 | * `moveWordRight:` 123 | 124 | "move the selection to... or the insertion point to..." 125 | 126 | * `moveToBeginningOfLine:` 127 | * `moveToEndOfLine:` 128 | * `moveToBeginningOfParagraph:` 129 | * `moveToEndOfParagraph:` 130 | * `moveToBeginningOfDocument:` 131 | * `moveToEndOfDocument:` 132 | 133 | "scroll the receiver... one page in its scroll view, also moving the insertion 134 | point to the top of the newly displayed page." 135 | 136 | * `pageUp:` 137 | * `pageDown:` 138 | 139 | 140 | ### Scroll the text view ### 141 | 142 | "scroll the receiver... in its scroll view, without changing the selection" 143 | 144 | * `scrollLineUp:` 145 | * `scrollLineDown:` 146 | * `scrollPageUp:` 147 | * `scrollPageDown:` 148 | 149 | 150 | "scroll the selection, whatever it is, inside its visible area." 151 | 152 | * `centerSelectionInVisibleArea:` 153 | 154 | ### Move the insertion point and modify the selection ### 155 | 156 | "expand or reduce either end of the selection by one element or character" 157 | 158 | * `moveBackwardAndModifySelection:` 159 | * `moveForwardAndModifySelection:` 160 | * `moveLeftAndModifySelection:` 161 | * `moveRightAndModifySelection:` 162 | * `moveUpAndModifySelection:` 163 | * `moveDownAndModifySelection:` 164 | 165 | "expand or reduce either end of the selection... by one whole word" 166 | 167 | * `moveWordBackwardAndModifySelection:` 168 | * `moveWordForwardAndModifySelection:` 169 | * `moveWordLeftAndModifySelection:` 170 | * `moveWordRightAndModifySelection:` 171 | 172 | Apparently some of the options are undocumented, but work just fine 173 | 174 | * `moveToBeginningOfDocumentAndModifySelection:` 175 | * `moveToEndOfDocumentAndModifySelection:` 176 | * `moveToBeginningOfLineAndModifySelection:` 177 | * `moveToEndOfLineAndModifySelection:` 178 | * `moveToBeginningOfParagraphAndModifySelection:` 179 | * `moveToEndOfParagraphAndModifySelection:` 180 | * `pageUpAndModifySelection:` 181 | * `pageDownAndModifySelection:` 182 | 183 | 184 | ### Select text ### 185 | 186 | "select..." 187 | 188 | * `selectAll:` 189 | * `selectLine:` 190 | * `selectParagraph:` 191 | * `selectWord:` -- "extend the selection to the nearest word boundaries 192 | outside it (up to, but not including, word delimiters)." 193 | * `selectToMark:` -- "select all items from the insertion point or selection 194 | to a previously placed mark, including the selection itself if not empty." 195 | 196 | 197 | ### Working with marks ### 198 | 199 | * `setMark:` -- "set a mark at the insertion point or selection, which is 200 | used by deleteToMark: and selectToMark:" 201 | 202 | * `swapWithMark:` -- "swap the mark and the selection or insertion point, so 203 | that what was marked is now the selection or insertion point, and what was 204 | the insertion point or selection is now the mark." 205 | 206 | * `selectToMark:` -- "select all items from the insertion point or selection 207 | to a previously placed mark, including the selection itself if not empty." 208 | 209 | * `deleteToMark:` -- "delete all items from the insertion point to a 210 | previously placed mark, including the selection itself if not empty." 211 | 212 | 213 | 214 | ### Other text editing options ### 215 | 216 | * `complete:` -- "complete an operation in progress or a partially 217 | constructed element." 218 | 219 | * `indent:` -- "indent the selection or the insertion point if there is no 220 | selection." 221 | 222 | * `transpose:` -- "Transposes the characters to either side of the insertion 223 | point and advances the insertion point past both of them. Does nothing to 224 | a selected range of text." 225 | 226 | * `transposeWords:` -- "Transposes the words to either side of the insertion 227 | point and advances the insertion point past both of them. Does nothing to 228 | a selected range of text." 229 | 230 | 231 | 232 | ### Cut/Copy/Paste ### 233 | 234 | * `copy:` -- "copies the selected text onto the general pasteboard, in as 235 | many formats as the receiver supports." 236 | 237 | * `cut:` -- "deletes the selected text and places it onto the general 238 | pasteboard, in as many formats as the receiver supports." 239 | 240 | * `paste:` -- "pastes text from the general pasteboard at the insertion 241 | point or over the selection." 242 | 243 | 244 | * `pasteAsPlainText:` -- "inserts the contents of the pasteboard into the 245 | receiver’s text as plain text, in the manner of insertText:." 246 | 247 | * `pasteAsRichText:` -- "inserts the contents of the pasteboard into the 248 | receiver’s text as rich text, maintaining its attributes." 249 | 250 | * Copy/paste fonts: 251 | 252 | * `copyFont:` -- "copies the font information for the first character of 253 | the selection (or for the insertion point) onto the font pasteboard, 254 | as NSFontPboardType." 255 | 256 | * `pasteFont:` -- "pastes font information from the font pasteboard onto 257 | the selected text or insertion point of a rich text object, or over 258 | all text of a plain text object." 259 | 260 | * Copy/paste ruler: 261 | 262 | * `copyRuler:` -- "copies the paragraph style information for first 263 | selected paragraph onto the ruler pasteboard, as NSRulerPboardType, 264 | and expands the selection to paragraph boundaries." 265 | 266 | * `pasteRuler:` -- "pastes paragraph style information from the ruler 267 | pasteboard onto the selected paragraphs of a rich text object." 268 | 269 | 270 | ## Text Styles and formatting (mostly applies to rich text) ## 271 | 272 | 273 | ### Set the text alignment ### 274 | 275 | "applies ... alignment to selected paragraphs (or all text if the receiver is 276 | a plain text object)" 277 | 278 | * `alignCenter:` 279 | * `alignLeft:` 280 | * `alignRight:` 281 | * `alignJustified:` 282 | 283 | "changes the base writing direction of a paragraph, for languages like Hebrew 284 | and Arabic, for example." 285 | 286 | * `toggleBaseWritingDirection:` 287 | * `changeBaseWritingDirectionToRTL:` 288 | * `changeBaseWritingDirectionToLTR:` 289 | 290 | 291 | ### Superscript/subscript ### 292 | 293 | * `superscript:` -- "applies a superscript attribute to selected text (or 294 | all text if the receiver is a plain text object), raising its baseline 295 | offset by a predefined amount." 296 | 297 | * `subscript:` -- "applies a subscript attribute to selected text (or all 298 | text if the receiver is a plain text object), lowering its baseline offset 299 | by a predefined amount." 300 | 301 | * `unscript:` -- "removes any superscripting or subscripting from selected 302 | text (or all text if the receiver is a plain text object)." 303 | 304 | 305 | ### Underline/outline ### 306 | 307 | * `underline:` -- "underlines selected text for a rich text object, or all 308 | text for a plain text object." 309 | 310 | * `outline:` 311 | 312 | 313 | ### Baseline, kerning, ligatures ### 314 | 315 | Set the baseline of the text. 316 | 317 | * `lowerBaseline:` -- "lowers the baseline offset of selected text by 1 point, 318 | or of all text if the receiver is a plain text view." 319 | 320 | * `raiseBaseline:` -- "raises the baseline offset of selected text by 1 point, 321 | or of all text if the receiver is a plain text view." 322 | 323 | 324 | Set the kerning to be used for the text. 325 | 326 | 327 | * `useStandardKerning:` -- "cause the receiver to use pair kerning data for 328 | the glyphs in its selection, or for all glyphs if the receiver is a plain 329 | text view." 330 | 331 | * `turnOffKerning:` -- "cause the receiver to use nominal glyph spacing for 332 | the glyphs in its selection, or for all glyphs if the receiver is a plain 333 | text view." 334 | 335 | * `loosenKerning:` -- "increase the space between glyphs in the receiver’s 336 | selection, or in all text if the receiver is a plain text view." 337 | 338 | * `tightenKerning:` -- "decrease the space between glyphs in the receiver’s 339 | selection, or for all glyphs if the receiver is a plain text view." 340 | 341 | 342 | Tell the selection whether to use standard ligatures, or all ligatures. 343 | 344 | * `useStandardLigatures:` -- "cause the receiver to use the standard 345 | ligatures available for the fonts and languages used when setting text, 346 | for the glyphs in the selection if the receiver is a rich text view, or 347 | for all glyphs if it’s a plain text view." 348 | 349 | * `turnOffLigatures:` -- "cause the receiver to use only required ligatures 350 | when setting text, for the glyphs in the selection if the receiver is a 351 | rich text view, or for all glyphs if it’s a plain text view." 352 | 353 | * `useAllLigatures:` -- "cause the receiver to use all ligatures available 354 | for the fonts and languages used when setting text, for the glyphs in the 355 | selection if the receiver is a rich text view, or for all glyphs if it’s a 356 | plain text view." 357 | 358 | * `toggleTraditionalCharacterShape:` -- "toggle the 359 | NSCharacterShapeAttibuteName attribute at the current selection." 360 | 361 | 362 | ### Open up useful panels for text formatting ### 363 | 364 | * `orderFrontLinkPanel:` -- "bring forward a panel allowing the user to 365 | manipulate links in the text view." 366 | 367 | * `orderFrontListPanel:` -- "bring forward a panel allowing the user to 368 | manipulate text lists in the text view." 369 | 370 | * `orderFrontSpacingPanel:` -- "bring forward a panel allowing the user to 371 | manipulate text line heights, interline spacing, and paragraph spacing, in 372 | the text view. 373 | 374 | * `orderFrontTablePanel:` -- "bring forward a panel allowing the user to 375 | manipulate text tables in the text view." 376 | 377 | 378 | ## Spelling and speech ## 379 | 380 | 381 | Check the spelling of the text view: 382 | 383 | * `toggleContinuousSpellChecking:` -- "toggle whether continuous spell 384 | checking is enabled for the receiver." 385 | 386 | * Perform spell checking. If I remember, the first one of these simply 387 | selects a misspelled word. The second one opens the spelling panel, and 388 | the third one tells the spelling system to ignore the selected word. I'm 389 | not positive of that however. 390 | 391 | * `checkSpelling:` -- "search for a misspelled word in the receiver’s 392 | text." 393 | 394 | * `showGuessPanel:` -- "open the Spelling panel, allowing the user to 395 | make a correction during spell checking." 396 | 397 | * `ignoreSpelling:` 398 | 399 | OS X Speech synthesis: 400 | 401 | * `startSpeaking:` -- "speak the selected text, or all text if no 402 | selection." 403 | 404 | * `stopSpeaking:` -- "stop the speaking of text." 405 | 406 | 407 | ## Window and document options ## 408 | 409 | 410 | ### Printing ### 411 | 412 | 413 | * `printDocument:` -- "bring up print sheet" 414 | 415 | * `runPageLayout:` -- the same thing happens as when the user chooses the 416 | Page Setup menu command. 417 | 418 | 419 | ### Closing, saving, reverting documents ### 420 | 421 | These do the same as the menu options of the same name: 422 | 423 | * `save:` 424 | 425 | * `saveAs:` 426 | 427 | * `saveTo:` 428 | 429 | * `revert:` 430 | 431 | * `performClose:` -- "simulate the user clicking the close button by 432 | momentarily highlighting the button and then closing the window." 433 | 434 | 445 | 446 | 447 | 448 | ### Window manipulations ### 449 | 450 | These three simulate clicking the little gem buttons in the top left corner of 451 | the window. Note that `close:`, etc. are also usable selectors, but not 452 | advisable, as they act slightly differently. Most importantly, `close:` 453 | doesn't prompt the user to save changes to unsaved documents, so data loss is 454 | possible if it is used: 455 | 456 | * `performClose:` 457 | * `performMiniaturize:` 458 | * `performZoom:` 459 | 460 | These change window ordering or position: 461 | 462 | * `center` -- "set the window’s location to the center of the screen." 463 | 464 | * `orderBack:` -- move the window behind all the other windows, without 465 | changing either the key window or the main window. 466 | 467 | * `orderFront:` -- move the window in front of all the other windows, 468 | without changing either the key window or the main window. 469 | 470 | 471 | This one hides the application: 472 | 473 | * `hide:` -- "Hide all the application’s windows, and the next application 474 | in line is activated." 475 | -------------------------------------------------------------------------------- /system-bindings.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | Cocoa Text System - Default System Key Bindings 9 | 101 | 102 | 103 | 104 | 105 |
106 |

Default Mac OS X System Key Bindings

107 | 108 |

Keyboard viewer--full sized

109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 |
ShortcutEnglishComputerese
new lineinsertNewline:
new line (don't leave form box)1insertNewlineIgnoringFieldEditor:
new lineinsertNewline:
new line (don't leave form box)1insertNewlineIgnoringFieldEditor:
 
tabinsertTab:
tab (don't leave form box)1insertTabIgnoringFieldEditor:
backtabinsertBacktab:
 
spacechange languagescycleToNextInputScript:
⌘⌃spacechange input systemtogglePlatformInputSystem:
⌘⌥spacechange keyboard layoutcycleToNextInputKeyboardLayout:
 
delete backwarddeleteBackward:
delete backward (an accent)deleteBackwardByDecomposingPreviousCharacter:
⌃⌥delete backward one worddeleteWordBackward:
delete backward one worddeleteWordBackward:
delete forwarddeleteForward:
delete forward one worddeleteWordForward:
 
esccancelcancelOperation:
esccomplete current wordcomplete:
 
move upmoveUp:
select upwardmoveUpAndModifySelection:
scroll one page upscrollPageUp:
move to the beginning of the documentmoveToBeginningOfDocument:
⌘⇧select to the beginning of the documentmoveToBeginningOfDocumentAndModifySelection:
move to the beginning of the paragraph(moveBackward:, moveToBeginningOfParagraph:)
⌥⇧select to the beginning of the paragraphmoveParagraphBackwardAndModifySelection:
move downmoveDown:
select downwardmoveDownAndModifySelection:
scroll one page downscrollPageDown:
move to the end of the documentmoveToEndOfDocument:
⌘⇧select to the end of the documentmoveToEndOfDocumentAndModifySelection:
move to the end of the paragraph(moveForward:, moveToEndOfParagraph:)
⌥⇧select to the end of the paragraphmoveParagraphForwardAndModifySelection:
move leftmoveLeft:
select leftwardmoveLeftAndModifySelection:
move to the beginning of the linemoveToBeginningOfLine:
⌃⇧select to the beginning of the linemoveToBeginningOfLineAndModifySelection:
move to the beginning of the linemoveToBeginningOfLine:
⌘⇧select to the beginning of the linemoveToBeginningOfLineAndModifySelection:
⌘⌃switch writing direction to right-to-leftchangeBaseWritingDirectionToRTL:
move one word leftmoveWordLeft:
⌥⇧select one word leftwardmoveWordLeftAndModifySelection:
move rightmoveRight:
select rightwardmoveRightAndModifySelection:
move to the end of the linemoveToEndOfLine:
⌃⇧select to the end of the linemoveToEndOfLineAndModifySelection:
move to the end of the linemoveToEndOfLine:
⌘⇧select to the end of the linemoveToEndOfLineAndModifySelection:
⌘⌃switch writing direction to left-to-right textchangeBaseWritingDirectionToLTR:
move one word rightmoveWordRight:
⌥⇧select one word rightwardmoveWordRightAndModifySelection:
 
scroll to the beginning of the documentscrollToBeginningOfDocument:
select to the beginning of the documentmoveToBeginningOfDocumentAndModifySelection:
scroll to the end of the documentscrollToEndOfDocument:
select to the end of the documentmoveToEndOfDocumentAndModifySelection:
 
scroll one page upscrollPageUp:
select one page uppageUpAndModifySelection:
move one page uppageUp:
scroll one page downscrollPageDown:
select one page downpageDownAndModifySelection:
move one page downpageDown:
 
.cancelcancelOperation:
Amove to the beginning of the paragraphmoveToBeginningOfParagraph:
Bmove backwardmoveBackward:
Ddelete forwarddeleteForward:
Emove to the end of the paragraphmoveToEndOfParagraph:
Fmove forwardmoveForward:
Hdelete backwarddeleteBackward:
Kdelete to the end of the paragraphdeleteToEndOfParagraph:
Lcenter the selection in the text areacenterSelectionInVisibleArea:
Nmove downmoveDown:
Osplit the current line(insertNewlineIgnoringFieldEditor:, moveBackward:)
Pmove upmoveUp:
Ttranspose letterstranspose:
Vmove one page downpageDown:
Yyank back ‘killed’ textyank:
 
F5complete current wordcomplete:
 
** Not on Apple keyboards **
Backspacedelete backwarddeleteBackward:
Backspacedelete backward one worddeleteWordBackward:
Linefeednew lineinsertNewline:
Linefeednew line (don't leave form box)1insertNewlineIgnoringFieldEditor:
217 | 218 |

219 | 220 |
  1. The commands invoked by ‘⌥ ⇥’ and ‘⌥ ↩’ are designed to avoid leaving 221 | the current text box, as happens when pressing ‘⇥’, which usually tabs to the 222 | next form field, or ‘↩’, which usually submits the form.
223 | 224 |

US Keyboard Layout with Modifier Keys

225 |

Keyboard viewer--full sized

226 |

Keyboard viewer--full sized, shift key

227 |

Keyboard viewer--full sized, option key

228 |

Keyboard viewer--full sized, option+shift

229 | 230 |
231 |
Anything I can improve? Send me an email: jacobolus AT gmail
--------------------------------------------------------------------------------