package com.termux.terminal; import android.view.KeyEvent; import junit.framework.TestCase; public class KeyHandlerTest extends TestCase { private static String stringToHex(String s) { if (s == null) return null; StringBuilder buffer = new StringBuilder(); for (int i = 0; i < s.length(); i++) { if (buffer.length() > 0) { buffer.append(" "); } buffer.append("0x"); buffer.append(Integer.toHexString(s.charAt(i))); } return buffer.toString(); } private static void assertKeysEquals(String expected, String actual) { if (!expected.equals(actual)) { assertEquals(stringToHex(expected), stringToHex(actual)); } } /** See http://pubs.opengroup.org/onlinepubs/7990989799/xcurses/terminfo.html */ public void testTermCaps() { // Backspace. assertKeysEquals("\u007f", KeyHandler.getCodeFromTermcap("kb", false, false)); // Back tab. assertKeysEquals("\033[Z", KeyHandler.getCodeFromTermcap("kB", false, false)); // Arrow keys (up/down/right/left): assertKeysEquals("\033[A", KeyHandler.getCodeFromTermcap("ku", false, false)); assertKeysEquals("\033[B", KeyHandler.getCodeFromTermcap("kd", false, false)); assertKeysEquals("\033[C", KeyHandler.getCodeFromTermcap("kr", false, false)); assertKeysEquals("\033[D", KeyHandler.getCodeFromTermcap("kl", false, false)); // .. shifted: assertKeysEquals("\033[1;2A", KeyHandler.getCodeFromTermcap("kUP", false, false)); assertKeysEquals("\033[1;2B", KeyHandler.getCodeFromTermcap("kDN", false, false)); assertKeysEquals("\033[1;2C", KeyHandler.getCodeFromTermcap("%i", false, false)); assertKeysEquals("\033[1;2D", KeyHandler.getCodeFromTermcap("#4", false, false)); // Home/end keys: assertKeysEquals("\033[H", KeyHandler.getCodeFromTermcap("kh", false, false)); assertKeysEquals("\033[F", KeyHandler.getCodeFromTermcap("@7", false, false)); // ... shifted: assertKeysEquals("\033[1;2H", KeyHandler.getCodeFromTermcap("#2", false, false)); assertKeysEquals("\033[1;2F", KeyHandler.getCodeFromTermcap("*7", false, false)); // The traditional keyboard keypad: // [Insert] [Home] [Page Up ] // [Delete] [End] [Page Down] // // Termcap names (with xterm response in parenthesis): // K1=Upper left of keypad (xterm sends same "<ESC>[H" = Home). // K2=Center of keypad (xterm sends invalid response). // K3=Upper right of keypad (xterm sends "<ESC>[5~" = Page Up). // K4=Lower left of keypad (xterm sends "<ESC>[F" = End key). // K5=Lower right of keypad (xterm sends "<ESC>[6~" = Page Down). // // vim/neovim (runtime/doc/term.txt): // t_K1 <kHome> keypad home key // t_K3 <kPageUp> keypad page-up key // t_K4 <kEnd> keypad end key // t_K5 <kPageDown> keypad page-down key // assertKeysEquals("\033[H", KeyHandler.getCodeFromTermcap("K1", false, false)); assertKeysEquals("\033OH", KeyHandler.getCodeFromTermcap("K1", true, false)); assertKeysEquals("\033[5~", KeyHandler.getCodeFromTermcap("K3", false, false)); assertKeysEquals("\033[F", KeyHandler.getCodeFromTermcap("K4", false, false)); assertKeysEquals("\033OF", KeyHandler.getCodeFromTermcap("K4", true, false)); assertKeysEquals("\033[6~", KeyHandler.getCodeFromTermcap("K5", false, false)); // Function keys F1-F12: assertKeysEquals("\033OP", KeyHandler.getCodeFromTermcap("k1", false, false)); assertKeysEquals("\033OQ", KeyHandler.getCodeFromTermcap("k2", false, false)); assertKeysEquals("\033OR", KeyHandler.getCodeFromTermcap("k3", false, false)); assertKeysEquals("\033OS", KeyHandler.getCodeFromTermcap("k4", false, false)); assertKeysEquals("\033[15~", KeyHandler.getCodeFromTermcap("k5", false, false)); assertKeysEquals("\033[17~", KeyHandler.getCodeFromTermcap("k6", false, false)); assertKeysEquals("\033[18~", KeyHandler.getCodeFromTermcap("k7", false, false)); assertKeysEquals("\033[19~", KeyHandler.getCodeFromTermcap("k8", false, false)); assertKeysEquals("\033[20~", KeyHandler.getCodeFromTermcap("k9", false, false)); assertKeysEquals("\033[21~", KeyHandler.getCodeFromTermcap("k;", false, false)); assertKeysEquals("\033[23~", KeyHandler.getCodeFromTermcap("F1", false, false)); assertKeysEquals("\033[24~", KeyHandler.getCodeFromTermcap("F2", false, false)); // Function keys F13-F24 (same as shifted F1-F12): assertKeysEquals("\033[1;2P", KeyHandler.getCodeFromTermcap("F3", false, false)); assertKeysEquals("\033[1;2Q", KeyHandler.getCodeFromTermcap("F4", false, false)); assertKeysEquals("\033[1;2R", KeyHandler.getCodeFromTermcap("F5", false, false)); assertKeysEquals("\033[1;2S", KeyHandler.getCodeFromTermcap("F6", false, false)); assertKeysEquals("\033[15;2~", KeyHandler.getCodeFromTermcap("F7", false, false)); assertKeysEquals("\033[17;2~", KeyHandler.getCodeFromTermcap("F8", false, false)); assertKeysEquals("\033[18;2~", KeyHandler.getCodeFromTermcap("F9", false, false)); assertKeysEquals("\033[19;2~", KeyHandler.getCodeFromTermcap("FA", false, false)); assertKeysEquals("\033[20;2~", KeyHandler.getCodeFromTermcap("FB", false, false)); assertKeysEquals("\033[21;2~", KeyHandler.getCodeFromTermcap("FC", false, false)); assertKeysEquals("\033[23;2~", KeyHandler.getCodeFromTermcap("FD", false, false)); assertKeysEquals("\033[24;2~", KeyHandler.getCodeFromTermcap("FE", false, false)); } public void testKeyCodes() { // Return sends carriage return (\r), which normally gets translated by the device driver to newline (\n) unless the ICRNL termios // flag has been set. assertKeysEquals("\r", KeyHandler.getCode(KeyEvent.KEYCODE_ENTER, 0, false, false)); // Backspace. assertKeysEquals("\u007f", KeyHandler.getCode(KeyEvent.KEYCODE_DEL, 0, false, false)); // Space. assertNull(KeyHandler.getCode(KeyEvent.KEYCODE_SPACE, 0, false, false)); assertKeysEquals("\u0000", KeyHandler.getCode(KeyEvent.KEYCODE_SPACE, KeyHandler.KEYMOD_CTRL, false, false)); // Back tab. assertKeysEquals("\033[Z", KeyHandler.getCode(KeyEvent.KEYCODE_TAB, KeyHandler.KEYMOD_SHIFT, false, false)); // Arrow keys (up/down/right/left): assertKeysEquals("\033[A", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_UP, 0, false, false)); assertKeysEquals("\033[B", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_DOWN, 0, false, false)); assertKeysEquals("\033[C", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_RIGHT, 0, false, false)); assertKeysEquals("\033[D", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_LEFT, 0, false, false)); // .. shifted: assertKeysEquals("\033[1;2A", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_UP, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2B", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_DOWN, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2C", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_RIGHT, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2D", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_LEFT, KeyHandler.KEYMOD_SHIFT, false, false)); // .. ctrl:ed: assertKeysEquals("\033[1;5A", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_UP, KeyHandler.KEYMOD_CTRL, false, false)); assertKeysEquals("\033[1;5B", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_DOWN, KeyHandler.KEYMOD_CTRL, false, false)); assertKeysEquals("\033[1;5C", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_RIGHT, KeyHandler.KEYMOD_CTRL, false, false)); assertKeysEquals("\033[1;5D", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_LEFT, KeyHandler.KEYMOD_CTRL, false, false)); // .. ctrl:ed and shifted: int mod = KeyHandler.KEYMOD_CTRL | KeyHandler.KEYMOD_SHIFT; assertKeysEquals("\033[1;6A", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_UP, mod, false, false)); assertKeysEquals("\033[1;6B", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_DOWN, mod, false, false)); assertKeysEquals("\033[1;6C", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_RIGHT, mod, false, false)); assertKeysEquals("\033[1;6D", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_LEFT, mod, false, false)); // Home/end keys: assertKeysEquals("\033[H", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_HOME, 0, false, false)); assertKeysEquals("\033[F", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_END, 0, false, false)); // ... shifted: assertKeysEquals("\033[1;2H", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_HOME, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2F", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_END, KeyHandler.KEYMOD_SHIFT, false, false)); // Function keys F1-F12: assertKeysEquals("\033OP", KeyHandler.getCode(KeyEvent.KEYCODE_F1, 0, false, false)); assertKeysEquals("\033OQ", KeyHandler.getCode(KeyEvent.KEYCODE_F2, 0, false, false)); assertKeysEquals("\033OR", KeyHandler.getCode(KeyEvent.KEYCODE_F3, 0, false, false)); assertKeysEquals("\033OS", KeyHandler.getCode(KeyEvent.KEYCODE_F4, 0, false, false)); assertKeysEquals("\033[15~", KeyHandler.getCode(KeyEvent.KEYCODE_F5, 0, false, false)); assertKeysEquals("\033[17~", KeyHandler.getCode(KeyEvent.KEYCODE_F6, 0, false, false)); assertKeysEquals("\033[18~", KeyHandler.getCode(KeyEvent.KEYCODE_F7, 0, false, false)); assertKeysEquals("\033[19~", KeyHandler.getCode(KeyEvent.KEYCODE_F8, 0, false, false)); assertKeysEquals("\033[20~", KeyHandler.getCode(KeyEvent.KEYCODE_F9, 0, false, false)); assertKeysEquals("\033[21~", KeyHandler.getCode(KeyEvent.KEYCODE_F10, 0, false, false)); assertKeysEquals("\033[23~", KeyHandler.getCode(KeyEvent.KEYCODE_F11, 0, false, false)); assertKeysEquals("\033[24~", KeyHandler.getCode(KeyEvent.KEYCODE_F12, 0, false, false)); // Function keys F13-F24 (same as shifted F1-F12): assertKeysEquals("\033[1;2P", KeyHandler.getCode(KeyEvent.KEYCODE_F1, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2Q", KeyHandler.getCode(KeyEvent.KEYCODE_F2, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2R", KeyHandler.getCode(KeyEvent.KEYCODE_F3, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[1;2S", KeyHandler.getCode(KeyEvent.KEYCODE_F4, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[15;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F5, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[17;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F6, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[18;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F7, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[19;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F8, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[20;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F9, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[21;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F10, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[23;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F11, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("\033[24;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F12, KeyHandler.KEYMOD_SHIFT, false, false)); assertKeysEquals("0", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_0, 0, false, false)); assertKeysEquals("1", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_1, 0, false, false)); assertKeysEquals("2", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_2, 0, false, false)); assertKeysEquals("3", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_3, 0, false, false)); assertKeysEquals("4", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_4, 0, false, false)); assertKeysEquals("5", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_5, 0, false, false)); assertKeysEquals("6", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_6, 0, false, false)); assertKeysEquals("7", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_7, 0, false, false)); assertKeysEquals("8", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_8, 0, false, false)); assertKeysEquals("9", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_9, 0, false, false)); assertKeysEquals(",", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_COMMA, 0, false, false)); assertKeysEquals(".", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_DOT, 0, false, false)); } }