/ANSITerminal

A Swift library to access features of ANSI terminal.

Primary LanguageSwiftMIT LicenseMIT

ANSITerminal

ANSITerminal is an open source Swift library to access ANSI Terminal and (almost) all of its features. It's including text coloring, text styling, cursor and screen handling, and direct keyboard input. ANSITerminal is based on standard ANSI features which is commonly supported on Unix terminals especially such as xterm and VT-100 compatible.

UPDATE:
Latest version is v.0.0.3 at May, 26th 2019. There are a simple demo and also a simple game made using this library. Have fun! :)

Usage

Using ANSITerminal library is as easy as putting import ANSITerminal in your Swift program then you will be able to use any functions or extensions provided by this library. The main advantage of using this library instead of something like ncurses is it doesn't take over the whole screen. You may use this library to complement your common console program.

Using Swift Package Manager

ANSITerminal only supports library distribution through Swift Package Manager. To use ANSITerminal, simply add a dependency into your project's package.swift file. Here's package.swift example from ansiDemo project.

// swift-tools-version:5.0

import PackageDescription

let package = Package(
    name: "ansiDemo",
    dependencies: [
        .package(url: "https://github.com/pakLebah/ANSITerminal", from: "0.0.3"),
    ],
    targets: [
        .target(
            name: "ansiDemo",
            dependencies: ["ANSITerminal"],
            path: "Sources"),
    ]
)

You just need to add a package dependency pointed to ANSITerminal's GitHub repo and "ANSITerminal" item into target dependency. Then you should be able to put import ANSITerminal in your Swift program and enjoy ANSI terminal features. That's all.

If you find a missing ANSI feature that you need, you could simply call swift package edit ANSITerminal. SPM will create a local copy of ANSITerminal for you, so you could add any missing features by yourself. Everytime you build the project, Swift will refers to the local copy instead of the original source. Once you done with it, don't forget to send a pull request to me. I'll be happy to accept any useful contributions to ANSITerminal from anyone.

Features

Text Coloring

ANSI color is available as property to String type through extension. To color a text, simply follow the text with the color's name. For example, 'text'.blue will produce text (blue text)* on the screen. To set text background color, simply follow the text with the color's name but with on prefix. For example, 'text'.onCyan will produce text (black text over cyan background) on the screen. As coloring is available as property to String, you may combine them. For example, 'text'.blue.onCyan will produce text (blue text over cyan background) on the screen. In case you prefer more expressive property name, you may want to use as prefix for text color. So, instead of 'text'.blue you could use 'text'.asBlue. It's so easy!

But the color name property is only available for the 16 system colors. Most ANSI terminals also support 256 colors. To use 256 colors palette, use foreColor(_:) type extension method to set text color and backColor(_:) to set text background color. You may also want to use colors(_: _:) that combines text color and background color respectively. Those type methods work just like the type properties mentioned before. Since 256 is too many to define correct and consistent name for each of them, you have to use the color index for 256 color palette. For example, 'text'.foreColor(196) will produce text (red text) on the screen. As in 16 colors properties, there are also more expressive method names for 256 colors methods, using with prefix. So, instead of 'text'.foreColor(196) you could also use 'text'.withForeColor(196).

The String extension mechanism sets color only for the text. After the text, the color is set back to the default, both for text and background color. If you want more control over the mechanism, you could use setColor(fore: back:) function for 16 colors system and setColors(_: _:) function for 256 colors palette. Those functions do not revert color back to the default, so you must not forget to call setDefault(color: style:) to turn ANSI attributes (either color or style) back to the default. Otherwise, your terminal color will stay with the last color and style settings.

Below are the default color palettes for ANSI terminal. You may need to look it up if you want to get the color number of 256 colors palette.

ANSI Color Palette

16 Colors (System)

216 Colors (by block)


Grayscale Colors

Text Styling

Similar to text coloring, text styling is also available as property to String type. To style a text, simply follow the text with a style name. For example, 'text'.bold will produce text on the screen, 'text'.italic will produce text on the screen, etc. There are 10 styles available on ANSI terminal, but not all of them are supported by every kind of ANSI terminal. Fortunately, normal, bold, italic, and inverse are mostly supported. So, if you want to use the other styles, make sure your users' terminal supports them.

Since color and style are both ANSI attributes, you may also combine them in a text. For example, 'text'.blue.bold will text (bold blue text) on the screen. Also similar to text coloring, there is also setStyle(_:) function to fix a text style until you call setDefault(color: style:) function to turn ANSI attributes (color and style) back to the default.

Here are the available text styles on ANSI terminal:

Cursor and Screen Handling

Cursor Related Functions

  1. storeCursorPosition() to store current cursor position.
  2. restoreCursorPosition() to restore last saved cursor position. Please note that this function sometimes has a side effect to also reset color and style to default on some terminals.
  3. cursorOn() to make cursor visible.
  4. cursorOff() to make cursor invisible (hidden).
  5. moveTo(_: _:) to position cursor to given row and col[umn] respectively.
  6. readCursorPosition() → (row: col:) to get current cursor position.

Screen Related Functions

  1. clearScreen() to clear the entire screen and put cursor at home position.
  2. clearLine() to clear the entire line of current cursor position.
  3. clearToEndOfLine() to clear the line of current cursor position to the end of line.
  4. scrollRegion(top: bottom:) to set scrolling region of the screen.
  5. readScreenSize() → (row: col:) to get current screen size in row and col[umn]. Please note that this function is not supported on emulated terminal such as VS Code's integrated terminal or repl.it's web terminal.**

Keyboard Input Handling

  1. keyPressed() → Bool to check whether any keys on the keyboard is pressed.
  2. readCode() → Int to read keyboard input one by one directly from standard input as ASCII code.
  3. readChar() → Character to read keyboard input one by one directly from standard input as Character.
  4. readKey() → (code: meta: []) to read keyboard input in advance manner, returns ASCII code and meta keys (shift, control, alt), if available. This function is important for complex keyboard input such as arrow keys, function keys (F1..F12), and any other possible combinations, which are common in games.

Miscellaneous Functions

  1. delay(_:) to suspend program execution in milliseconds.
  2. clearBuffer(isOut: isIn:) to clear standard input/output buffer.
  3. write(_:... suspend:) to directly write a (bunch of) text into standard output with optional suspend delay, it also has writeln(_:... suspend:) if you need a newline after the (bunch of) text.
  4. stripAttributes(from:) → String to strip all colors and styles from a text to get the actual text, which could be useful to get the actual text's length after adding colors/styles.
  5. ask(_:) → String is a shortcut to ask for a question from user.

I consider those as the most useful and used functions in common console applications. You should look into the source code files to see the rest of available functions. I will update the documentation to be more complete. A simple demo program is available here. There is also a simple console game that I made using this library, it's a slide game.

If you have any issues using this library, feel free to submit an issue. Thank you.

________
* GitHub's Markdown doesn't support custom text color via CSS.
** XCode's integrated console doesn't support ANSI at all.