├── 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 |Version 0.8
89 | by Jacob Rus
90 | Monday, 20 March 2006
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 |Before delving too deeply into the intricacies of the Cocoa text system, it 133 | helps to understand some programmer jargon.
134 | 135 |The Insertion Point (sometimes called the caret) 137 | is the blinking vertical line that shows where text typed into a text box 138 | will show up.
A Buffer is the text field currently being edited. This might be a 140 | text box in an online form in Safari, or the main window in TextEdit.
Key Bindings, often called ‘keyboard shortcuts’,
142 | define what happens when any key is typed in an application. For instance,
143 | in a Mac text editor, the ‘a’ key inserts an a
, ‘Opt-e, e’ inserts an
144 | é
, and ‘Ctrl-a’ moves the insertion point to the beginning of the
145 | current line.
A String is a chunk of text, literally a ‘string’ of 147 | letters.
A Method is a function that an object (which includes 149 | just about everything in Cocoa) can perform.
A Selector is the name of a method. It is a string. Something like
151 | "insertTab:"
, or "save:"
The Mark is an invisible point somewhere in the document, which can 153 | be set, and then returned to. Marking is the way regions of text were 154 | selected in UNIX text editors back in the days before they could be 155 | highlighted in blue with a mouse drag.
To Kill some text is basically the same as using the ‘Cut’ command, 157 | but in OS X uses a separate mechanism, that is localized to the current 158 | buffer. By default ‘Ctrl-k’ kills everything after the insertion point on 159 | the current line.
Yank is the analog of the ‘Paste’ command. By default, ‘Ctrl-y’ 161 | yanks back whatever was most recently killed.
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 |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 |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 |
187 |
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 |
195 |
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 |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 |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.
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.
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.
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 |A string is simply a sequence of letters, numbers, and symbols, 261 | such as:
262 | 263 |"this is a string with some $#@! symbols"
264 |
A list is, like it sounds, a list of other objects, such as 266 | lists or strings:
267 | 268 |("a", "list", "can", "contain", "many", "strings")
269 |
A dictionary contains pairs of “keys” and “values”. Basically, 271 | dictionaries provide a way to name a bunch of objects, and refer 272 | to them by name. Note that while dictionary keys must be strings, 273 | the values can be any type of object.
274 | 275 |{"key1" = "value1"; "key2" = "value2"; "key3" = ("a", "list");}
276 |
In addition, comments can be added to old-style property lists
278 | by enclosing some text in /*
and */
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 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
:
{
316 | /* This will make all a's turn to tabs. Beware. */
317 | "a" = "insertTab:";
318 | }
319 |
320 |
321 | 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:
334 |340 | 341 |339 |
"@t"
= Command-t
335 |"^t"
= Control-t
336 |"~t"
= Option-t
337 |"@^T"
= Command-Control-Shift-t
338 |"~ "
= Option-space
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 #
:
347 |350 | 351 |349 |
"@$#5"
= Command-Shift-Numpad 5
348 |"^6"
= Control-6
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’.
362 |364 | 365 |363 |
"~\\$"
= Option-$
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 |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 |
Notes:
408 | 409 |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 |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:
{
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:
{
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”).
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 |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 |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:
Beyond that, it’s possible make key bindings as pranks. That’s always fun:
634 | 635 |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
.
NSTextKillRingSize
This default sets the size of the kill ring. It can be set as follows:
656 | 657 |defaults write -g NSTextKillRingSize -string 4
658 |
659 |
660 | This changes the size of the “kill ring” which large deleted blocks of
661 | text get copied to. In this case, I have set it to keep track of the 4
662 | most recent such blocks. This means that this text can be cycled through,
663 | and won’t be lost as soon as more text is killed. An extra binding is
664 | useful in dealing with a kill ring: yankAndSelect:
, which cycles through
665 | the kill ring.
NSRepeatCountBinding
This one is one of the coolest features of the text system. In emacs, 669 | pressing “Control-u”, and then a number, 94 say, and then any other 670 | command, will repeat that command 94 times. It is possible to set OS X to 671 | do the same thing with “Control-u” as follows:
672 | 673 |defaults write -g NSRepeatCountBinding -string "^u"
674 |
675 |
676 | Of course, any other binding could be set instead of “Control-u”.
NSQuotedKeystrokeBinding
This default is normally linked to Control-q. It causes the next 680 | keystroke typed to be passed through the system, without activating any 681 | bindings. For example, if the “Option-v” is bound to scroll up in the 682 | key bindings file, a square root sign — √ — can still be entered by 683 | typing “Control-q, Option-v”.
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 |First, Mike Ferris’s TextExtras extends the Cocoa 706 | text system in ways that programmers, particularly, will find 707 | useful. I haven’t spent too much time playing with TextExtras, 708 | especially since TextMate, my editor of choice, 709 | doesn’t quite use the same Cocoa controls as other Cocoa-based 710 | editors like SubEthaEdit and Smultron. But 711 | TextExtras adds quite a bit to the Cocoa text system, including 712 | indent wrapping, auto-indentation, showing and selecting matching 713 | braces, improved completion, and, perhaps most of all, customized 714 | piping of text through shell commands. This allows all sorts of 715 | snazzy behavior (note that editors like TextWrangler and 716 | TextMate have their own implementations of this feature).
Second, one of my favorite text-system extensions is 718 | Michael McCracken’s Incremental Search Input Manager 719 | (ISIM). Here’s a link to a zip-file of the universal binary.
720 | 721 |ISIM is an input manager that provides three new selectors for binding in
722 | our DefaultKeyBinding.dict
file: ISIM_incrementalSearch:
,
723 | ISIM_reverseIncrementalSearch:
, and abort:
(that last one may
724 | work for other things, I’m not sure). The idea is pretty simple, but
725 | incredibly useful. Basically, when the selector is invoked, a little
726 | window pops up at the bottom of the current text box. When you type
727 | into this little window, ISIM searches through the current document
728 | searching for text that matches, and selects the first occurrence of
729 | such text. Repeatedly invoking the selector flips through any other
730 | occurrences in the document. A picture can say this better than I can:
The relevant part of my key bindings file looks like this:
735 | 736 |/* Incremental search */
737 | "^s" = "ISIM_incrementalSearch:";
738 | "^r" = "ISIM_reverseIncrementalSearch:";
739 | "^$g" = "abort:";
740 |
Finally, for those who can’t get enough customization in a straight 742 | NSTextView, using the techniques described already, Gus Mueller made an 743 | input manager, described in two blog posts, which 744 | allows the contents of any Cocoa text field to BBEdit. Type the relvant 745 | key, and your text will pop up in a new BBEdit document. Save, and the 746 | text in the original text field is updated. It’s awesome. According to the 747 | second post, modifying it to work with any editor which uses the ODBEditor 748 | suite (used mainly by FTP programs to open remote files in a local text 749 | editor) would be easy—it’s open source.
750 | 751 |TextMate, my editor of choice, comes with a similar input manager, I 752 | believe inspired by the first one. And the great thing about TextMate’s 753 | version is that it works in Mail (I’m not sure, but I think Gus’s 754 | doesn’t). If there’s a text editor you like, it’s extremely nice to be 755 | able to edit Safari form fields, emails, and other text using that editor.
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 |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 |804 | 805 |“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 |
800 | 801 |/System/Library/Extensions/AppleADBKeyboard.kext
with an actual 799 | modified binary).“Now i can actually type ahead blindly without thinking twice. Contact me, 802 | if you are interested in using this too.”
803 |
Needless to say, I wouldn’t advise trying this, unless you know what you are 806 | doing.
807 | 808 |TODO: Much of this list of links is still incomplete
811 | 812 |Free Cocoa text editors for OS X:
815 | 816 |Commercial Cocoa text editors:
823 | 824 |Non-Cocoa text editors for OS X:
842 | 843 |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 |NSQuotedKeystrokeBinding
,
928 | which is Control-q by default.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 |
by Jacob Rus
85 | Friday, 17 March 2006
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 |cancelOperation:
— “cancel the current operation.”
showContextHelp:
— “invoke the help system, displaying information
95 | relevant to the receiver and its current state. The sender argument is
96 | typically the object that invoked this method.”
undo:
redo:
breakUndoCoalescing
— this one sets up an undo state. So if some more
105 | text is typed, and then undo is invoked, it will come back to this point.
These selectors are for inserting, selecting, deleting, and moving text.
111 | 112 |In general, these selectors: “Insert a … at the insertion point or selection, deleting the selection if there is one”
115 | 116 |These two also “end editing if the receiver is a text field”
118 | 119 |insertTab:
insertNewline:
These selectors should be used to avoid tabbing out of, for instance, a 124 | form field
125 | 126 |insertTabIgnoringFieldEditor:
insertNewlineIgnoringFieldEditor:
insertLineBreak:
insertParagraphSeparator:
insertContainerBreak:
insertBacktab:
— “handle a ‘backward tab’”
insertText:
— my favorite selector, “insert a string at the insertion
135 | point or selection, deleting the selection if there is one.”
This group of selectors simply wipes text off the face of the planet.
141 | 142 |delete:
— “deletes the selected text only”
deleteBackward:
deleteForward:
deleteWordBackward:
deleteWordForward:
deleteBackwardByDecomposingPreviousCharacter:
— “If the previous
149 | character is canonically decomposable, try to delete only the last
150 | character in the grapheme cluster (for example, deleting “a”+ “´” results
151 | in “a”)”
These selectors delete text, but also put it onto the kill ring (which means that it can be “yanked back later”):
157 | 158 |deleteToBeginningOfLine:
deleteToEndOfLine:
deleteToBeginningOfParagraph:
deleteToEndOfParagraph:
deleteToMark:
— “Delete all items from the insertion point to a
164 | previously placed mark, including the selection itself if not empty.”
This one brings back text:
168 | 169 |yank:
— “Replaces the insertion point or selection with text from the
171 | kill buffer.”“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 |changeCaseOfLetter:
“set the case of the word or words surrounding the insertion point or 183 | selection, expanding the selection if necessary”
184 | 185 |lowercaseWord:
uppercaseWord:
capitalizeWord:
“move the selection or insertion point one element or character”
194 | 195 |moveBackward:
moveForward:
moveLeft:
moveRight:
moveUp:
moveDown:
“move the selection or insertion point one word…”
205 | 206 |moveWordBackward:
moveWordForward:
moveWordLeft:
moveWordRight:
“move the selection to… or the insertion point to…”
214 | 215 |moveToBeginningOfLine:
moveToEndOfLine:
moveToBeginningOfParagraph:
moveToEndOfParagraph:
moveToBeginningOfDocument:
moveToEndOfDocument:
“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 |pageUp:
pageDown:
“scroll the receiver… in its scroll view, without changing the selection”
235 | 236 |scrollLineUp:
scrollLineDown:
scrollPageUp:
scrollPageDown:
“scroll the selection, whatever it is, inside its visible area.”
244 | 245 |centerSelectionInVisibleArea:
“expand or reduce either end of the selection by one element or character”
252 | 253 |moveBackwardAndModifySelection:
moveForwardAndModifySelection:
moveLeftAndModifySelection:
moveRightAndModifySelection:
moveUpAndModifySelection:
moveDownAndModifySelection:
“expand or reduce either end of the selection… by one whole word”
263 | 264 |moveWordBackwardAndModifySelection:
moveWordForwardAndModifySelection:
moveWordLeftAndModifySelection:
moveWordRightAndModifySelection:
Apparently some of the options are undocumented, but work just fine
272 | 273 |moveToBeginningOfDocumentAndModifySelection:
moveToEndOfDocumentAndModifySelection:
moveToBeginningOfLineAndModifySelection:
moveToEndOfLineAndModifySelection:
moveToBeginningOfParagraphAndModifySelection:
moveToEndOfParagraphAndModifySelection:
pageUpAndModifySelection:
pageDownAndModifySelection:
“select…”
287 | 288 |selectAll:
selectLine:
selectParagraph:
selectWord:
— “extend the selection to the nearest word boundaries
293 | outside it (up to, but not including, word delimiters).”selectToMark:
— “select all items from the insertion point or selection
295 | to a previously placed mark, including the selection itself if not empty.”setMark:
— “set a mark at the insertion point or selection, which is
302 | used by deleteToMark: and selectToMark:”
swapWithMark:
— “swap the mark and the selection or insertion point, so
304 | that what was marked is now the selection or insertion point, and what was
305 | the insertion point or selection is now the mark.”
selectToMark:
— “select all items from the insertion point or selection
307 | to a previously placed mark, including the selection itself if not empty.”
deleteToMark:
— “delete all items from the insertion point to a
309 | previously placed mark, including the selection itself if not empty.”
complete:
— “complete an operation in progress or a partially
316 | constructed element.”
indent:
— “indent the selection or the insertion point if there is no
318 | selection.”
transpose:
— “Transposes the characters to either side of the insertion
320 | point and advances the insertion point past both of them. Does nothing to
321 | a selected range of text.”
transposeWords:
— “Transposes the words to either side of the insertion
323 | point and advances the insertion point past both of them. Does nothing to
324 | a selected range of text.”
copy:
— “copies the selected text onto the general pasteboard, in as
331 | many formats as the receiver supports.”
cut:
— “deletes the selected text and places it onto the general
333 | pasteboard, in as many formats as the receiver supports.”
paste:
— “pastes text from the general pasteboard at the insertion
335 | point or over the selection.”
pasteAsPlainText:
— “inserts the contents of the pasteboard into the
337 | receiver’s text as plain text, in the manner of insertText:.”
pasteAsRichText:
— “inserts the contents of the pasteboard into the
339 | receiver’s text as rich text, maintaining its attributes.”
Copy/paste fonts:
341 | 342 |copyFont:
— “copies the font information for the first character of
344 | the selection (or for the insertion point) onto the font pasteboard,
345 | as NSFontPboardType.”
pasteFont:
— “pastes font information from the font pasteboard onto
347 | the selected text or insertion point of a rich text object, or over
348 | all text of a plain text object.”
Copy/paste ruler:
351 | 352 |copyRuler:
— “copies the paragraph style information for first
354 | selected paragraph onto the ruler pasteboard, as NSRulerPboardType,
355 | and expands the selection to paragraph boundaries.”
pasteRuler:
— “pastes paragraph style information from the ruler
357 | pasteboard onto the selected paragraphs of a rich text object.”
“applies … alignment to selected paragraphs (or all text if the receiver is 366 | a plain text object)”
367 | 368 |alignCenter:
alignLeft:
alignRight:
alignJustified:
“changes the base writing direction of a paragraph, for languages like Hebrew 376 | and Arabic, for example.”
377 | 378 |toggleBaseWritingDirection:
changeBaseWritingDirectionToRTL:
changeBaseWritingDirectionToLTR:
superscript:
— “applies a superscript attribute to selected text (or
388 | all text if the receiver is a plain text object), raising its baseline
389 | offset by a predefined amount.”
subscript:
— “applies a subscript attribute to selected text (or all
391 | text if the receiver is a plain text object), lowering its baseline offset
392 | by a predefined amount.”
unscript:
— “removes any superscripting or subscripting from selected
394 | text (or all text if the receiver is a plain text object).”
underline:
— “underlines selected text for a rich text object, or all
401 | text for a plain text object.”
outline:
Set the baseline of the text.
408 | 409 |lowerBaseline:
— “lowers the baseline offset of selected text by 1 point,
411 | or of all text if the receiver is a plain text view.”
raiseBaseline:
— “raises the baseline offset of selected text by 1 point,
413 | or of all text if the receiver is a plain text view.”
Set the kerning to be used for the text.
417 | 418 |useStandardKerning:
— “cause the receiver to use pair kerning data for
420 | the glyphs in its selection, or for all glyphs if the receiver is a plain
421 | text view.”
turnOffKerning:
— “cause the receiver to use nominal glyph spacing for
423 | the glyphs in its selection, or for all glyphs if the receiver is a plain
424 | text view.”
loosenKerning:
— “increase the space between glyphs in the receiver’s
426 | selection, or in all text if the receiver is a plain text view.”
tightenKerning:
— “decrease the space between glyphs in the receiver’s
428 | selection, or for all glyphs if the receiver is a plain text view.”
Tell the selection whether to use standard ligatures, or all ligatures.
432 | 433 |useStandardLigatures:
— “cause the receiver to use the standard
435 | ligatures available for the fonts and languages used when setting text,
436 | for the glyphs in the selection if the receiver is a rich text view, or
437 | for all glyphs if it’s a plain text view.”
turnOffLigatures:
— “cause the receiver to use only required ligatures
439 | when setting text, for the glyphs in the selection if the receiver is a
440 | rich text view, or for all glyphs if it’s a plain text view.”
useAllLigatures:
— “cause the receiver to use all ligatures available
442 | for the fonts and languages used when setting text, for the glyphs in the
443 | selection if the receiver is a rich text view, or for all glyphs if it’s a
444 | plain text view.”
toggleTraditionalCharacterShape:
— “toggle the
446 | NSCharacterShapeAttibuteName attribute at the current selection.”
orderFrontLinkPanel:
— “bring forward a panel allowing the user to
453 | manipulate links in the text view.”
orderFrontListPanel:
— “bring forward a panel allowing the user to
455 | manipulate text lists in the text view.”
orderFrontSpacingPanel:
— “bring forward a panel allowing the user to
457 | manipulate text line heights, interline spacing, and paragraph spacing, in
458 | the text view.
orderFrontTablePanel:
— “bring forward a panel allowing the user to
460 | manipulate text tables in the text view.”
Check the spelling of the text view:
466 | 467 |toggleContinuousSpellChecking:
— “toggle whether continuous spell
469 | checking is enabled for the receiver.”
Perform spell checking. If I remember, the first one of these simply 471 | selects a misspelled word. The second one opens the spelling panel, and 472 | the third one tells the spelling system to ignore the selected word. I’m 473 | not positive of that however.
474 | 475 |checkSpelling:
— “search for a misspelled word in the receiver’s
477 | text.”
showGuessPanel:
— “open the Spelling panel, allowing the user to
479 | make a correction during spell checking.”
ignoreSpelling:
OS X Speech synthesis:
485 | 486 |startSpeaking:
— “speak the selected text, or all text if no
488 | selection.”
stopSpeaking:
— “stop the speaking of text.”
printDocument:
— “bring up print sheet”
runPageLayout:
— the same thing happens as when the user chooses the
499 | Page Setup menu command.
These do the same as the menu options of the same name:
505 | 506 |save:
saveAs:
saveTo:
revert:
performClose:
— “simulate the user clicking the close button by
512 | momentarily highlighting the button and then closing the window.”
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:
performClose:
performMiniaturize:
performZoom:
These change window ordering or position:
542 | 543 |center
— “set the window’s location to the center of the screen.”
orderBack:
— move the window behind all the other windows, without
546 | changing either the key window or the main window.
orderFront:
— move the window in front of all the other windows,
548 | without changing either the key window or the main window.
This one hides the application:
552 | 553 |hide:
— “Hide all the application’s windows, and the next application
555 | in line is activated.”Shortcut | English | Computerese | |
---|---|---|---|
↩ | new line | insertNewline: | |
⌥ | ↩ | new line (don't leave form box)1 | insertNewlineIgnoringFieldEditor: |
⌅ | new line | insertNewline: | |
⌥ | ⌅ | new line (don't leave form box)1 | insertNewlineIgnoringFieldEditor: |
⇥ | tab | insertTab: | |
⌥ | ⇥ | tab (don't leave form box)1 | insertTabIgnoringFieldEditor: |
⇤ | backtab | insertBacktab: | |
⌘ | space | change languages | cycleToNextInputScript: |
⌘⌃ | space | change input system | togglePlatformInputSystem: |
⌘⌥ | space | change keyboard layout | cycleToNextInputKeyboardLayout: |
⌫ | delete backward | deleteBackward: | |
⌃ | ⌫ | delete backward (an accent) | deleteBackwardByDecomposingPreviousCharacter: |
⌃⌥ | ⌫ | delete backward one word | deleteWordBackward: |
⌥ | ⌫ | delete backward one word | deleteWordBackward: |
⌦ | delete forward | deleteForward: | |
⌥ | ⌦ | delete forward one word | deleteWordForward: |
esc | cancel | cancelOperation: | |
⌥ | esc | complete current word | complete: |
⇡ | move up | moveUp: | |
⇧ | ⇡ | select upward | moveUpAndModifySelection: |
⌃ | ⇡ | scroll one page up | scrollPageUp: |
⌘ | ⇡ | move to the beginning of the document | moveToBeginningOfDocument: |
⌘⇧ | ⇡ | select to the beginning of the document | moveToBeginningOfDocumentAndModifySelection: |
⌥ | ⇡ | move to the beginning of the paragraph | (moveBackward:, moveToBeginningOfParagraph:) |
⌥⇧ | ⇡ | select to the beginning of the paragraph | moveParagraphBackwardAndModifySelection: |
⇣ | move down | moveDown: | |
⇧ | ⇣ | select downward | moveDownAndModifySelection: |
⌃ | ⇣ | scroll one page down | scrollPageDown: |
⌘ | ⇣ | move to the end of the document | moveToEndOfDocument: |
⌘⇧ | ⇣ | select to the end of the document | moveToEndOfDocumentAndModifySelection: |
⌥ | ⇣ | move to the end of the paragraph | (moveForward:, moveToEndOfParagraph:) |
⌥⇧ | ⇣ | select to the end of the paragraph | moveParagraphForwardAndModifySelection: |
⇠ | move left | moveLeft: | |
⇧ | ⇠ | select leftward | moveLeftAndModifySelection: |
⌃ | ⇠ | move to the beginning of the line | moveToBeginningOfLine: |
⌃⇧ | ⇠ | select to the beginning of the line | moveToBeginningOfLineAndModifySelection: |
⌘ | ⇠ | move to the beginning of the line | moveToBeginningOfLine: |
⌘⇧ | ⇠ | select to the beginning of the line | moveToBeginningOfLineAndModifySelection: |
⌘⌃ | ⇠ | switch writing direction to right-to-left | changeBaseWritingDirectionToRTL: |
⌥ | ⇠ | move one word left | moveWordLeft: |
⌥⇧ | ⇠ | select one word leftward | moveWordLeftAndModifySelection: |
⇢ | move right | moveRight: | |
⇧ | ⇢ | select rightward | moveRightAndModifySelection: |
⌃ | ⇢ | move to the end of the line | moveToEndOfLine: |
⌃⇧ | ⇢ | select to the end of the line | moveToEndOfLineAndModifySelection: |
⌘ | ⇢ | move to the end of the line | moveToEndOfLine: |
⌘⇧ | ⇢ | select to the end of the line | moveToEndOfLineAndModifySelection: |
⌘⌃ | ⇢ | switch writing direction to left-to-right text | changeBaseWritingDirectionToLTR: |
⌥ | ⇢ | move one word right | moveWordRight: |
⌥⇧ | ⇢ | select one word rightward | moveWordRightAndModifySelection: |
↖ | scroll to the beginning of the document | scrollToBeginningOfDocument: | |
⇧ | ↖ | select to the beginning of the document | moveToBeginningOfDocumentAndModifySelection: |
↘ | scroll to the end of the document | scrollToEndOfDocument: | |
⇧ | ↘ | select to the end of the document | moveToEndOfDocumentAndModifySelection: |
⇞ | scroll one page up | scrollPageUp: | |
⇧ | ⇞ | select one page up | pageUpAndModifySelection: |
⌥ | ⇞ | move one page up | pageUp: |
⇟ | scroll one page down | scrollPageDown: | |
⇧ | ⇟ | select one page down | pageDownAndModifySelection: |
⌥ | ⇟ | move one page down | pageDown: |
⌘ | . | cancel | cancelOperation: |
⌃ | A | move to the beginning of the paragraph | moveToBeginningOfParagraph: |
⌃ | B | move backward | moveBackward: |
⌃ | D | delete forward | deleteForward: |
⌃ | E | move to the end of the paragraph | moveToEndOfParagraph: |
⌃ | F | move forward | moveForward: |
⌃ | H | delete backward | deleteBackward: |
⌃ | K | delete to the end of the paragraph | deleteToEndOfParagraph: |
⌃ | L | center the selection in the text area | centerSelectionInVisibleArea: |
⌃ | N | move down | moveDown: |
⌃ | O | split the current line | (insertNewlineIgnoringFieldEditor:, moveBackward:) |
⌃ | P | move up | moveUp: |
⌃ | T | transpose letters | transpose: |
⌃ | V | move one page down | pageDown: |
⌃ | Y | yank back ‘killed’ text | yank: |
F5 | complete current word | complete: | |
** Not on Apple keyboards ** | |||
Backspace | delete backward | deleteBackward: | |
⌥ | Backspace | delete backward one word | deleteWordBackward: |
Linefeed | new line | insertNewline: | |
⌥ | Linefeed | new line (don't leave form box)1 | insertNewlineIgnoringFieldEditor: |