Class TerminalTextUtils


  • public class TerminalTextUtils
    extends java.lang.Object
    This class contains a number of utility methods for analyzing characters and strings in a terminal context. The main purpose is to make it easier to work with text that may or may not contain double-width text characters, such as CJK (Chinese, Japanese, Korean) and other special symbols. This class assumes those are all double-width and in case the terminal (-emulator) chooses to draw them (somehow) as single-column then all the calculations in this class will be wrong. It seems safe to assume what this class considers double-width really is taking up two columns though.
    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      private TerminalTextUtils()  
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      static java.lang.String fitString​(java.lang.String string, int availableColumnSpace)
      Given a string that may or may not contain CJK characters, returns the substring which will fit inside availableColumnSpace columns.
      static java.lang.String fitString​(java.lang.String string, int fromColumn, int availableColumnSpace)
      Given a string that may or may not contain CJK characters, returns the substring which will fit inside availableColumnSpace columns.
      static java.lang.String getANSIControlSequenceAt​(java.lang.String string, int index)
      Given a string and an index in that string, returns the ANSI control sequence beginning on this index.
      static int getANSIControlSequenceLength​(java.lang.String string, int index)
      Given a string and an index in that string, returns the number of characters starting at index that make up a complete ANSI control sequence.
      static int getColumnIndex​(java.lang.String s, int stringCharacterIndex)
      Given a string and a character index inside that string, find out what the column index of that character would be if printed in a terminal.
      static int getColumnIndex​(java.lang.String s, int stringCharacterIndex, TabBehaviour tabBehaviour, int firstCharacterColumnPosition)
      Given a string and a character index inside that string, find out what the column index of that character would be if printed in a terminal.
      static int getColumnWidth​(java.lang.String s)
      Given a string, returns how many columns this string would need to occupy in a terminal, taking into account that CJK characters takes up two columns.
      static int getStringCharacterIndex​(java.lang.String s, int columnIndex)
      This method does the reverse of getColumnIndex, given a String and imagining it has been printed out to the top-left corner of a terminal, in the column specified by columnIndex, what is the index of that character in the string.
      static java.util.List<java.lang.String> getWordWrappedText​(int maxWidth, java.lang.String... lines)
      This method will calculate word wrappings given a number of lines of text and how wide the text can be printed.
      static boolean isCharCJK​(char c)
      Given a character, is this character considered to be a CJK character? Shamelessly stolen from StackOverflow where it was contributed by user Rakesh N
      static boolean isCharDoubleWidth​(char c)
      Checks if a character is expected to be taking up two columns if printed to a terminal.
      static boolean isCharThai​(char c)
      Given a character, is this character considered to be a Thai character?
      static boolean isControlCharacter​(char c)
      Checks if a particular character is a control character, in Lanterna this currently means it's 0-31 or 127 in the ascii table.
      static boolean isPrintableCharacter​(char c)
      Checks if a particular character is printable.
      private static java.lang.Integer[] mapCodesToIntegerArray​(java.lang.String[] codes)  
      static void updateModifiersFromCSICode​(java.lang.String controlSequence, StyleSet<?> target, StyleSet<?> original)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • TerminalTextUtils

        private TerminalTextUtils()
    • Method Detail

      • getANSIControlSequenceAt

        public static java.lang.String getANSIControlSequenceAt​(java.lang.String string,
                                                                int index)
        Given a string and an index in that string, returns the ANSI control sequence beginning on this index. If there is no control sequence starting there, the method will return null. The returned value is the complete escape sequence including the ESC prefix.
        Parameters:
        string - String to scan for control sequences
        index - Index in the string where the control sequence begins
        Returns:
        null if there was no control sequence starting at the specified index, otherwise the entire control sequence
      • getANSIControlSequenceLength

        public static int getANSIControlSequenceLength​(java.lang.String string,
                                                       int index)
        Given a string and an index in that string, returns the number of characters starting at index that make up a complete ANSI control sequence. If there is no control sequence starting there, the method will return 0.
        Parameters:
        string - String to scan for control sequences
        index - Index in the string where the control sequence begins
        Returns:
        0 if there was no control sequence starting at the specified index, otherwise the length of the entire control sequence
      • isCharCJK

        public static boolean isCharCJK​(char c)
        Given a character, is this character considered to be a CJK character? Shamelessly stolen from StackOverflow where it was contributed by user Rakesh N
        Parameters:
        c - Character to test
        Returns:
        true if the character is a CJK character
      • isCharThai

        public static boolean isCharThai​(char c)
        Given a character, is this character considered to be a Thai character?
        Parameters:
        c - Character to test
        Returns:
        true if the character is a Thai character
      • isCharDoubleWidth

        public static boolean isCharDoubleWidth​(char c)
        Checks if a character is expected to be taking up two columns if printed to a terminal. This will generally be true for CJK (Chinese, Japanese and Korean) characters. Notice that emoji generally takes up more than a single char and can't be tested properly with this method.
        Parameters:
        c - Character to test if it's double-width when printed to a terminal
        Returns:
        true if this character is expected to be taking up two columns when printed to the terminal, otherwise false
      • isControlCharacter

        public static boolean isControlCharacter​(char c)
        Checks if a particular character is a control character, in Lanterna this currently means it's 0-31 or 127 in the ascii table.
        Parameters:
        c - character to test
        Returns:
        true if the character is a control character, false otherwise
      • isPrintableCharacter

        public static boolean isPrintableCharacter​(char c)
        Checks if a particular character is printable. This generally means that the code is not a control character that isn't able to be printed to the terminal properly. For example, NULL, ENQ, BELL and ESC and all control codes that has no proper character associated with it so the behaviour is undefined and depends completely on the terminal what happens if you try to print them. However, certain control characters have a particular meaning to the terminal and are as such considered printable. In Lanterna, we consider these control characters printable:
        • Backspace
        • Horizontal Tab
        • Line feed
        Parameters:
        c - character to test
        Returns:
        true if the character is considered printable, false otherwise
      • getColumnWidth

        public static int getColumnWidth​(java.lang.String s)
        Given a string, returns how many columns this string would need to occupy in a terminal, taking into account that CJK characters takes up two columns.
        Parameters:
        s - String to check length
        Returns:
        Number of actual terminal columns the string would occupy
      • getColumnIndex

        public static int getColumnIndex​(java.lang.String s,
                                         int stringCharacterIndex)
                                  throws java.lang.StringIndexOutOfBoundsException
        Given a string and a character index inside that string, find out what the column index of that character would be if printed in a terminal. If the string only contains non-CJK characters then the returned value will be same as stringCharacterIndex, but if there are CJK characters the value will be different due to CJK characters taking up two columns in width. If the character at the index in the string is a CJK character itself, the returned value will be the index of the left-side of character. The tab character is counted as four spaces.
        Parameters:
        s - String to translate the index from
        stringCharacterIndex - Index within the string to get the terminal column index of
        Returns:
        Index of the character inside the String at stringCharacterIndex when it has been writted to a terminal
        Throws:
        java.lang.StringIndexOutOfBoundsException - if the index given is outside the String length or negative
      • getColumnIndex

        public static int getColumnIndex​(java.lang.String s,
                                         int stringCharacterIndex,
                                         TabBehaviour tabBehaviour,
                                         int firstCharacterColumnPosition)
                                  throws java.lang.StringIndexOutOfBoundsException
        Given a string and a character index inside that string, find out what the column index of that character would be if printed in a terminal. If the string only contains non-CJK characters then the returned value will be same as stringCharacterIndex, but if there are CJK characters the value will be different due to CJK characters taking up two columns in width. If the character at the index in the string is a CJK character itself, the returned value will be the index of the left-side of character.
        Parameters:
        s - String to translate the index from
        stringCharacterIndex - Index within the string to get the terminal column index of
        tabBehaviour - The behavior to use when encountering the tab character
        firstCharacterColumnPosition - Where on the screen the first character in the string would be printed, this applies only when you have an alignment-based TabBehaviour
        Returns:
        Index of the character inside the String at stringCharacterIndex when it has been writted to a terminal
        Throws:
        java.lang.StringIndexOutOfBoundsException - if the index given is outside the String length or negative
      • getStringCharacterIndex

        public static int getStringCharacterIndex​(java.lang.String s,
                                                  int columnIndex)
        This method does the reverse of getColumnIndex, given a String and imagining it has been printed out to the top-left corner of a terminal, in the column specified by columnIndex, what is the index of that character in the string. If the string contains no CJK characters, this will always be the same as columnIndex. If the index specified is the right column of a CJK character, the index is the same as if the column was the left column. So calling getStringCharacterIndex("英", 0) and getStringCharacterIndex("英", 1) will both return 0.
        Parameters:
        s - String to translate the index to
        columnIndex - Column index of the string written to a terminal
        Returns:
        The index in the string of the character in terminal column columnIndex
      • fitString

        public static java.lang.String fitString​(java.lang.String string,
                                                 int availableColumnSpace)
        Given a string that may or may not contain CJK characters, returns the substring which will fit inside availableColumnSpace columns. This method does not handle special cases like tab or new-line.

        Calling this method is the same as calling fitString(string, 0, availableColumnSpace).

        Parameters:
        string - The string to fit inside the availableColumnSpace
        availableColumnSpace - Number of columns to fit the string inside
        Returns:
        The whole or part of the input string which will fit inside the supplied availableColumnSpace
      • fitString

        public static java.lang.String fitString​(java.lang.String string,
                                                 int fromColumn,
                                                 int availableColumnSpace)
        Given a string that may or may not contain CJK characters, returns the substring which will fit inside availableColumnSpace columns. This method does not handle special cases like tab or new-line.

        This overload has a fromColumn parameter that specified where inside the string to start fitting. Please notice that fromColumn is not a character index inside the string, but a column index as if the string has been printed from the left-most side of the terminal. So if the string is "日本語", fromColumn set to 1 will not starting counting from the second character ("本") in the string but from the CJK filler character belonging to "日". If you want to count from a particular character index inside the string, please pass in a substring and use fromColumn set to 0.

        Parameters:
        string - The string to fit inside the availableColumnSpace
        fromColumn - From what column of the input string to start fitting (see description above!)
        availableColumnSpace - Number of columns to fit the string inside
        Returns:
        The whole or part of the input string which will fit inside the supplied availableColumnSpace
      • getWordWrappedText

        public static java.util.List<java.lang.String> getWordWrappedText​(int maxWidth,
                                                                          java.lang.String... lines)
        This method will calculate word wrappings given a number of lines of text and how wide the text can be printed. The result is a list of new rows where word-wrapping was applied.
        Parameters:
        maxWidth - Maximum number of columns that can be used before word-wrapping is applied, if <= 0 then the lines will be returned unchanged
        lines - Input text
        Returns:
        The input text word-wrapped at maxWidth; this may contain more rows than the input text
      • mapCodesToIntegerArray

        private static java.lang.Integer[] mapCodesToIntegerArray​(java.lang.String[] codes)
      • updateModifiersFromCSICode

        public static void updateModifiersFromCSICode​(java.lang.String controlSequence,
                                                      StyleSet<?> target,
                                                      StyleSet<?> original)