Recent

Author Topic: TermUtils - Creating Pretty Terminal Applications without CRT  (Read 3673 times)

Warfley

  • Hero Member
  • *****
  • Posts: 1499
TermUtils - Creating Pretty Terminal Applications without CRT
« on: August 02, 2020, 04:18:05 am »
Hey ho,

I really like terminal applications. I like using them and I like writing them, but I don't like the CRT unit.

When you wanted to have a cross plattform console application there was no real way around the CRT, but for a while now the Windows 10 terminal supports ANSI escape sequences, which means a lot of the cross platform compatibility hassle can be avoided by simply resorting to using the escape sequences rather than the low level system APIs.

To be honest, juggling with escape sequences is not much fun either, so I wrote a small library that can handle all that escape sequence stuff and provide a nice API, which also solves the little remaining cross compatibility issues that are left.

The goal of this is not to support every plattform and every terminal. The goal is to support the most common plattforms (Windows 10 terminal, Linux xTerm, Konsole and Gnome Terminal, macOS Terminal and iTerm) but therefore support them well.

Link: https://github.com/Warfley/LazTermUtils

Features:
  • Allows to create a Terminal that either uses STDIN, STDOUT and STDERR, or can read and write from files (or tty pseudo files in Linux). This allows even accessing other terminals, e.g. when you want to send a message to all open sessions on a server.
  • Supports most widespread Textmodifications like bold, italic, underlined, striked, etc.
  • Allows to specify colors as 24 bit values, compatibly with non system LCL colors (like $FF0000 for red)
  • Can read keys including their modifications directly, e.g. it can detect ctrl + key or alt + key, as well as support for most special keys
  • Allows for both line buffered echoed input and direct invisible input (i.e. where the key is recognized on press and not printed to the terminal)
  • Functionality for moving the cursor, clearing the screen and clearing the current line
  • Can buffer output to a given size to allow for a better performance (rather than writing each char at a time)
  • Provides a cross plattform IsATTY function to check if the handle used is connected to a terminal or a file
  • Non blocking read to allow to check if a keypress was made without waiting for it
  • UTF-8 support for keystroke reading


Notes:
This is limited due to the limitations of the escape sequences. This means some things are simply not possible Ctrl + I for example is treated as a Tab, there is no way the library can distinquish between these two and therefore always says it recieved a tab when Ctrl + I is used.

When being in direct read mode (i.e. reading without linebuffering and echoing by the terminal) all special key combinations like ctrl + c are disabled and you will recieve the key strokes for those rather than the event (like SIGINT)

Some terminals like the macOS terminal do not support 24 bit (true) color. In that case simply define Col8 (either in the package options or in the TerminalColor.pas) to use 8-bit colors. Don't worry the API does not change so no code has do be adopted, the color resolution will simply be downscaled from 24 to 8 bit during runtime.

I tried to keep the normal FPC functions like WriteLn and ReadLn still working, but of course modifications (like changing the color) can also effect these functions. Also when direct read mode is enabled, a lot of the behaviour changes. Newlines will be #13 (enter key code) and newlines under Unix will not reset the cursor (so #13 needs to be printed to return the cursor). One is best advised to only use the provided Stream classes for this interface.

Examples can be found in the example folder. See Github readme for more information.

The Colortest example measures the fps it can archive when printing every single cell of the terminal in an infinite loop. On my 1080p display with Konsole I get 45 fps when running in fullscreen, I would like to know what performance you archive with this



This is still a work in progress, I just thought it is now in such a state that I might share it with others (so the basic functionality seems to work quite well). If you find bugs report them, the best way to do it is by opening a Github issue.
« Last Edit: August 02, 2020, 06:04:05 pm by Warfley »

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #1 on: August 02, 2020, 05:39:55 am »
Cool, will play around with this 👍

MarkMLl

  • Hero Member
  • *****
  • Posts: 6646
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #2 on: August 02, 2020, 10:42:07 am »
One of the "all-time great" programs was Visual BASIC for DOS, which as I understand it was released as a fallback in case VB (v1) for Windows bombed. Much as I dislike traditional BASIC, I've always felt that it was unfortunate that there wasn't a character-mode IDE for Linux/unix, I've tried to tinker with such things in the past but have usually got hung up on things like WINCH handling (mainstream work obviously took precedence over "interesting R&D").

There was a Pascal dialog(ue) editor for FreeVision. I've used it for one engineering test program but it was... /quirky/ and it goes without saying that there is absolutely no integration between it and the fp IDE.

https://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg45646.html
https://forum.lazarus.freepascal.org/index.php?topic=18998.0

It's now 15 years too late, but if the fp IDE had had a form/dialogue editor based on FreeVision/curses etc. it would have changed history.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #3 on: August 02, 2020, 06:08:00 pm »
Small update: now has UTF-8 support, as well as the ability to read keys non-blocking to check if keys have been pressed without waiting for one

AlexTP

  • Hero Member
  • *****
  • Posts: 2365
    • UVviewsoft
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #4 on: August 04, 2020, 10:13:21 am »
Can I make the LCL component on it which shows terminal like panel, run Bash in background, and shows Bash output in that panel?
And put some user input into Bash, e.g. "ls"[enter] ?
And Bash output is colored (ansi codes)?

MarkMLl

  • Hero Member
  • *****
  • Posts: 6646
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #5 on: August 04, 2020, 10:24:45 am »
Can I make the LCL component on it which shows terminal like panel, run Bash in background, and shows Bash output in that panel?
And put some user input into Bash, e.g. "ls"[enter] ?
And Bash output is colored (ansi codes)?

I've definitely had Bash (and other programs) running in my own terminal component in the past. However it will need to be told the appropriate terminal type, and the terminal component will need to handle the appropriate escape sequences... see termcap/terminfo.

Code: [Select]
...
    process.Environment.Add('TERM=dumb');
    for i := 1 to GetEnvironmentVariableCount do begin
      if Pos('COLORTERM=', GetEnvironmentString(i)) = 1 then (* Ignore this     *)
        continue;
      if Pos('TERM=', GetEnvironmentString(i)) = 1 then (* Already specified dumb *)
        continue;
      process.Environment.Add(GetEnvironmentString(i))
    end;
    process.Options := [poUsePipes];
    process.Execute;
    Sleep(100);
    while process.Running or not ((process.Output.NumBytesAvailable = 0) and
                                        (process.StdErr.NumBytesAvailable = 0)) do
...

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

AlexTP

  • Hero Member
  • *****
  • Posts: 2365
    • UVviewsoft
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #6 on: August 04, 2020, 10:30:24 am »
It is blurry answer, I cannot get - can I run Bash and see its output (colored) or not.
I want to see  the demo app in your repo!

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #7 on: August 04, 2020, 02:23:13 pm »
Can I make the LCL component on it which shows terminal like panel, run Bash in background, and shows Bash output in that panel?
And put some user input into Bash, e.g. "ls"[enter] ?
And Bash output is colored (ansi codes)?
What you are talking about is a Terminal Emulator, this is not a TE, it is a library to iteract with an existing TE (or TTY). It's like the CRT unit but supports only a few plattforms but therefore has more features (and removes some of the annoyances of CRT)
« Last Edit: August 04, 2020, 02:29:07 pm by Warfley »

AlexTP

  • Hero Member
  • *****
  • Posts: 2365
    • UVviewsoft
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #8 on: August 04, 2020, 05:38:16 pm »
OK
I posted all info to https://wiki.freepascal.org/LazTermUtils
feel free to edit.

Roland57

  • Sr. Member
  • ****
  • Posts: 416
    • msegui.net
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #9 on: February 02, 2021, 07:23:46 am »
Hello!

I try to compile LazTermUtils, with Lazarus 2.0.8 r62955, on Linux 64.

I get an error on this line:

Code: Pascal  [Select][+][-]
  1. function ColorText(const AString: string; const Foreground: TTextColor): string;
  2. begin
  3.   Result := ModifyString([TTerminalModifier.ForegroundModifier(Foreground)], AString);
  4. end;

Quote
terminalmodifier.pas(501,76) Error: Incompatible type for arg no. 1: Got "{Array Of Const/Constant Open} Array of TTerminalModifier", expected "TModifiers"

My projects are on Gitlab and on Codeberg.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #10 on: February 14, 2021, 02:57:07 am »
I try to compile LazTermUtils, with Lazarus 2.0.8 r62955, on Linux 64.
Sorry for answering so late, the problem is that the FPC version that you use (and probably is shipped with that lazarus version) is too old. In modern FPC versions (>=3.2) you can create dynamic arrays with the [elements] syntax.

I don't intend on backporting the library for older FPC versions, but AFAIK this is the only line that needs to be changed to work with an older FPC version, so you could just fix this line yourself:
Code: Pascal  [Select][+][-]
  1. function ColorText(const AString: string; const Foreground: TTextColor): string;
  2. var
  3.   mods: TModifiers;
  4. begin
  5.   SetLength(mods, 1);
  6.   mods[0] := TTerminalModifier.ForegroundModifier(Foreground)
  7.   Result := ModifyString(mods, AString);
  8. end;

Roland57

  • Sr. Member
  • ****
  • Posts: 416
    • msegui.net
Re: TermUtils - Creating Pretty Terminal Applications without CRT
« Reply #11 on: February 14, 2021, 04:32:16 am »
Thank you for your answer. There were other small modifications to do here and there, but after I understood the principle (with help of your example) it was easy.

Now that I can compile the units, I will take a closer look to the examples.

Regards.

Roland
My projects are on Gitlab and on Codeberg.

 

TinyPortal © 2005-2018