All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aesh.readline.terminal.Key Maven / Gradle / Ivy

There is a newer version: 1.17
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.aesh.readline.terminal;

import org.aesh.readline.action.KeyAction;
import org.aesh.utils.InfoCmpHelper;
import org.aesh.utils.Config;
import org.aesh.readline.util.Parser;

import java.nio.IntBuffer;

/**
 * ANSCII enum key chart
 *
 * @author Ståle W. Pedersen
 */
public enum Key implements KeyAction {
    CTRL_AT(new int[]{0}),
    CTRL_A(new int[]{1}),
    CTRL_B(new int[]{2}),
    CTRL_C(new int[]{3}),
    CTRL_D(new int[]{4}),
    CTRL_E(new int[]{5}),
    CTRL_F(new int[]{6}),
    CTRL_G(new int[]{7}),
    CTRL_H(new int[]{8}),
    CTRL_I(new int[]{9}),
    CTRL_J(new int[]{10}),
    CTRL_K(new int[]{11}),
    CTRL_L(new int[]{12}),
    CTRL_M(new int[]{13}),
    CTRL_N(new int[]{14}),
    CTRL_O(new int[]{15}),
    CTRL_P(new int[]{16}),
    CTRL_Q(new int[]{17}),
    CTRL_R(new int[]{18}),
    CTRL_S(new int[]{19}),
    CTRL_T(new int[]{20}),
    CTRL_U(new int[]{21}),
    CTRL_V(new int[]{22}),
    CTRL_W(new int[]{23}),
    CTRL_X(new int[]{24}),
    CTRL_Y(new int[]{25}),
    CTRL_Z(new int[]{26}),
    ESC(new int[]{27}), //ctrl-[ and esc
    FILE_SEPARATOR(new int[]{28}), //ctrl-\
    GROUP_SEPARATOR(new int[]{29}), //ctrl-]
    RECORD_SEPARATOR(new int[]{30}), //ctrl-ctrl
    UNIT_SEPARATOR(new int[]{31}), //ctrl-_

    SPACE(new int[]{32}),
    EXCLAMATION(new int[]{33}), // !
    QUOTE(new int[]{34}), // "
    HASH(new int[]{35}), // #
    DOLLAR(new int[]{36}), // $
    PERCENT(new int[]{37}), // %
    AMPERSAND(new int[]{38}), // &
    APOSTROPHE(new int[]{39}), // '
    LEFT_PARANTHESIS(new int[]{40}), // (
    RIGHT_PARANTHESIS(new int[]{41}), // )
    STAR(new int[]{42}), // *
    PLUS(new int[]{43}), // +
    COMMA(new int[]{44}), // ,
    MINUS(new int[]{45}), // -
    PERIOD(new int[]{46}), // .
    SLASH(new int[]{47}), // /
    ZERO(new int[]{48}), // 0
    ONE(new int[]{49}), // 1
    TWO(new int[]{50}), // 2
    THREE(new int[]{51}), // 3
    FOUR(new int[]{52}), // 4
    FIVE(new int[]{53}), // 5
    SIX(new int[]{54}), // 6
    SEVEN(new int[]{55}), // 7
    EIGHT(new int[]{56}), // 8
    NINE(new int[]{57}), // 9
    COLON(new int[]{58}), // :
    SEMI_COLON(new int[]{59}), // ;
    LESS_THAN(new int[]{60}), // <
    EQUALS(new int[]{61}), // =
    GREATER_THAN(new int[]{62}), // >
    QUESTION_MARK(new int[]{63}), // ?
    AT(new int[]{64}), // @
    A(new int[]{65}),
    B(new int[]{66}),
    C(new int[]{67}),
    D(new int[]{68}),
    E(new int[]{69}),
    F(new int[]{70}),
    G(new int[]{71}),
    H(new int[]{72}),
    I(new int[]{73}),
    J(new int[]{74}),
    K(new int[]{75}),
    L(new int[]{76}),
    M(new int[]{77}),
    N(new int[]{78}),
    O(new int[]{79}),
    P(new int[]{80}),
    Q(new int[]{81}),
    R(new int[]{82}),
    S(new int[]{83}),
    T(new int[]{84}),
    U(new int[]{85}),
    V(new int[]{86}),
    W(new int[]{87}),
    X(new int[]{88}),
    Y(new int[]{89}),
    Z(new int[]{90}),
    LEFT_SQUARE_BRACKET(new int[]{91}), // [
    BACKSLASH(new int[]{92}), // \
    RIGHT_SQUARE_BRACKET(new int[]{93}), // ]
    HAT(new int[]{94}), // ^
    UNDERSCORE(new int[]{95}), // _
    GRAVE(new int[]{96}), // `
    a(new int[]{97}),
    b(new int[]{98}),
    c(new int[]{99}),
    d(new int[]{100}),
    e(new int[]{101}),
    f(new int[]{102}),
    g(new int[]{103}),
    h(new int[]{104}),
    i(new int[]{105}),
    j(new int[]{106}),
    k(new int[]{107}),
    l(new int[]{108}),
    m(new int[]{109}),
    n(new int[]{110}),
    o(new int[]{111}),
    p(new int[]{112}),
    q(new int[]{113}),
    r(new int[]{114}),
    s(new int[]{115}),
    t(new int[]{116}),
    u(new int[]{117}),
    v(new int[]{118}),
    w(new int[]{119}),
    x(new int[]{120}),
    y(new int[]{121}),
    z(new int[]{122}),
    LEFT_CURLY_BRACKET(new int[]{123}), // {
    VERTICAL_BAR(new int[]{124}), // |
    RIGHT_CURLY_BRACKET(new int[]{125}), // }
    TILDE(new int[]{126}), // ~

    BACKSPACE(Config.isOSPOSIXCompatible() ?
            new int[]{127} : new int[]{8}),

    WINDOWS_ESC(new int[]{224}), // just used to identify win special chars
    WINDOWS_ESC_2(new int[]{341}), // just used to identify win special chars
    //movement
    UP( new int[]{ESC.getFirstValue(),91,65}),
    DOWN( new int[]{ESC.getFirstValue(),91,66}),
    RIGHT( new int[]{ESC.getFirstValue(),91,67}),
    LEFT( new int[]{ESC.getFirstValue(),91,68}),

    UP_2(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kcuu1", new int[]{27,79,65})),
    DOWN_2( InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kcud1", new int[]{27,79,66})),
    RIGHT_2( InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("cuf1", new int[]{27,79,67})),
    LEFT_2( InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kcub1", new int[]{27,79,68})),

    //meta
    META_a(new int[]{ESC.getFirstValue(),a.getFirstValue()}),
    META_b(new int[]{ESC.getFirstValue(),b.getFirstValue()}),
    META_c(new int[]{ESC.getFirstValue(),c.getFirstValue()}),
    META_d(new int[]{ESC.getFirstValue(),d.getFirstValue()}),
    META_e(new int[]{ESC.getFirstValue(),e.getFirstValue()}),
    META_f(new int[]{ESC.getFirstValue(),f.getFirstValue()}),
    META_l(new int[]{ESC.getFirstValue(),l.getFirstValue()}),
    META_u(new int[]{ESC.getFirstValue(),u.getFirstValue()}),

    META_BACKSPACE(new int[]{ESC.getFirstValue(),BACKSPACE.getFirstValue()}),

    //div
    DELETE( InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kdch1", new int[]{27,91,51,126})),

    INSERT(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kich1", new int[]{27,91,50,126})),
    PGUP(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kpp", new int[]{27, 91, 53, 126})),
    // Seen on Solaris, kpp returning different encoding than actual key
    PGUP_2(new int[]{27, 91, 53, 126}),
    PGDOWN(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("knp", new int[]{27, 91, 54, 126})),
    // Seen on Solaris, knp returning different encoding than actual key
    PGDOWN_2(new int[]{27, 91, 54, 126}),
    HOME(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("khome", new int[]{27,79,72})),
    HOME_2(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("home", new int[]{27,91,72})),
    END(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("kend", new int[]{27,79,70})),
    END_2(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("end", new int[]{27,91,70})),
    END_3(InfoCmpHelper.getCurrentTranslatedCapabilityAsInts("end", new int[]{27,91,52,126})),

    META_CTRL_J( new int[]{ESC.getFirstValue(),10}),
    META_CTRL_D(new int[]{ESC.getFirstValue(),4}),
    CTRL_X_CTRL_U(new int[]{CTRL_X.getFirstValue(),CTRL_U.getFirstValue()}),

    CTRL_LEFT(new int[] {ESC.getFirstValue(),91,49,59,53,68}),
    CTRL_RIGHT(new int[] {ESC.getFirstValue(),91,49,59,53,67}),
    CTRL_UP(new int[] {ESC.getFirstValue(),91,49,59,53,65}),
    CTRL_DOWN(new int[] {ESC.getFirstValue(),91,49,59,53,66}),

    ENTER(Config.isOSPOSIXCompatible() ?
            new int[]{10} : new int[]{13}),
    //needed to support stupid \r\n on windows...
    ENTER_2(Config.isOSPOSIXCompatible() ?
            new int[]{10} : new int[]{13,10});

    private final IntBuffer keyValues;

    Key(int[] keyValues) {
        this.keyValues = IntBuffer.allocate(keyValues.length);
        this.keyValues.put(keyValues);

    }

    /**
     * is of type a-z or A-Z
     */
    public boolean isCharacter() {
        return (keyValues.limit() == 1 &&
                ((keyValues.get(0) > 63 && keyValues.get(0) < 91) || (keyValues.get(0) > 96 && keyValues.get(0) < 123)));
    }

    /**
     * @return true if input is 0-9
     */
    public boolean isNumber() {
        return (keyValues.limit() == 1 && ((keyValues.get(0) > 47) && (keyValues.get(0) < 58)));
    }

    /**
     * @return true if input is a valid char
     */
    public boolean isPrintable() {
        return isPrintable(getKeyValues());
    }

    public static boolean isPrintable(int value) {
        if(Config.isOSPOSIXCompatible())
            return (((value > 31 && value < 127) || value > 127));
        else
            return (((value > 31 && value < 127) ||
                    (value > 127 &&
                            value != WINDOWS_ESC.getFirstValue() &&
                            value != WINDOWS_ESC_2.getFirstValue())));

    }

    public static boolean isPrintable(int[] keyValues) {
        return (keyValues.length == 1 && isPrintable(keyValues[0]));
    }

    public static boolean isPrintable(IntBuffer keyValues) {
        if(Config.isOSPOSIXCompatible())
            return (keyValues.limit() == 1 && ((keyValues.get(0) > 31 && keyValues.get(0) < 127) || keyValues.get(0) > 127));
        else
            return (keyValues.limit() == 1 && ((keyValues.get(0) > 31 && keyValues.get(0) < 127) ||
                    (keyValues.get(0) > 127 &&
                            keyValues.get(0) != WINDOWS_ESC.getFirstValue() &&
                            keyValues.get(0) != WINDOWS_ESC_2.getFirstValue())));
    }

    public char getAsChar() {
        return (char) keyValues.get(0);
    }

    public int[] getKeyValues() {
        return keyValues.array();
    }

    public String getKeyValuesAsString() {
        return Parser.fromCodePoints(keyValues.array());
    }

    public int getFirstValue() {
        return keyValues.get(0);
    }

    public static boolean startsWithEscape(int[] input) {
        return ((Config.isOSPOSIXCompatible() && input[0] == Key.ESC.getFirstValue()) ||
                (!Config.isOSPOSIXCompatible() && input[0] == Key.WINDOWS_ESC.getFirstValue()));
    }

    public static Key getKey(int[] otherValues) {
        for(Key key : Key.values()) {
            if(key.equalTo(otherValues))
                return key;
        }
        return null;
    }

    public static Key findStartKey(int[] input) {
        for(Key key : values()) {
            if(key != Key.ESC && key != Key.WINDOWS_ESC &&
                    key.inputStartsWithKey(input)) {
                if(Config.isOSPOSIXCompatible() && key == Key.CTRL_J) {
                   return ENTER;
                }
                else if(!Config.isOSPOSIXCompatible() && key == Key.CTRL_M) {
                    if(input.length > 1 && input[1] == Key.CTRL_J.getFirstValue())
                        return ENTER_2;
                    else
                        return ENTER;
                }
                else
                    return key;
            }
        }
        //need to do this in two steps since esc/windows_esc would be returned always
        if(Key.ESC.inputStartsWithKey(input))
            return Key.ESC;
        else if(Key.WINDOWS_ESC.inputStartsWithKey(input))
            return Key.WINDOWS_ESC;

        return null;
    }

    public static Key findStartKey(int[] input, int position) {
        for(Key key : values()) {
            if(key != Key.ESC && key != Key.WINDOWS_ESC &&
                    key.inputStartsWithKey(input, position)) {
                if(Config.isOSPOSIXCompatible() && key == Key.CTRL_J) {
                   return ENTER;
                }
                else if(!Config.isOSPOSIXCompatible() && key == Key.CTRL_M) {
                    if(input.length > position + 1 && input[position+1] == Key.CTRL_J.getFirstValue())
                        return ENTER_2;
                    else
                        return ENTER;
                }
                else
                    return key;
            }
        }
        //need to do this in two steps since esc/windows_esc would be returned always
        if(Key.ESC.inputStartsWithKey(input, position))
            return Key.ESC;
        else if(Key.WINDOWS_ESC.inputStartsWithKey(input, position))
            return Key.WINDOWS_ESC;

        return null;
    }

    public boolean inputStartsWithKey(int[] input) {
        if(keyValues.limit() > input.length)
            return false;
        for(int i=0; i < keyValues.limit(); i++) {
            if(keyValues.get(i) != input[i])
                return false;
        }
        return true;
    }

    public boolean inputStartsWithKey(int[] input, int position) {
        if(keyValues.limit()+position > input.length)
            return false;
        for(int i=0; i < keyValues.limit(); i++) {
            if(keyValues.get(i) != input[i+position])
                return false;
        }
        return true;
    }

    public boolean containKey(int[] input) {
        for(int i=0; i < input.length; i++) {
            if(input[i] == keyValues.get(0)) {
                if(keyValues.limit() == 1)
                    return true;
                else if((i + keyValues.limit()) < input.length) {
                    int j = i;
                    for(int k : keyValues.array()) {
                        if(input[j] != k) {
                            return false;
                        }
                        j++;
                    }
                    return true;
                }
            }
        }
        return false;
    }

    public boolean equalTo(int[] otherValues) {
        if(keyValues.limit() == otherValues.length) {
            for(int i=0; i < keyValues.limit(); i++) {
                if(keyValues.get(i) != otherValues[i])
                    return false;
            }
            return true;
        }
        return false;
    }

    public boolean equalTo(KeyAction key) {
        if(keyValues.limit() == key.length()) {
            for(int i = 0; i < keyValues.limit();i++)
                if(keyValues.get(i) != key.getCodePointAt(i))
                    return false;
            return true;
        }
        return false;
    }

    @Override
    public int getCodePointAt(int index) {
        return keyValues.get(index);
    }

    @Override
    public int length() {
        return keyValues.limit();
    }

    @Override
    public IntBuffer buffer() {
        return keyValues;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy