0.3.0 ANSI

This commit is contained in:
Rob Tillaart 2023-11-11 17:11:00 +01:00
parent 82e0c516c3
commit 12208710bf
10 changed files with 253 additions and 29 deletions

View File

@ -6,13 +6,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.0] - 2023-11-09
- fix missing 0 in normal (#19, Kudos to d0m1n1qu3)
- fix basic escape strings write length (normal, bold etc eating one char).
- add **getScreenSize()** (#16, Kudos to chlordk)
- add **readCursorPosition()** (#16, Kudos to chlordk)
- add example, (#16, Kudos to chlordk)
- add **screenWidth()** call getScreenSize() before use
- add **screenHeight()** call getScreenSize() before use
- refactor **deviceType()** size.
- add **blinkFast()**
- update readme.md
- update keywords.txt
----
## [0.2.1] - 2023-10-17
- update readme.md (badges)
- fix version in ansi.cpp
- add a derived VT100 class (wrapper for now).
- minor edits
## [0.2.0] - 2023-02-26
- fix #13 gotoXY(column, row)
- add ansi_gotoXY example.

View File

@ -76,11 +76,14 @@ Stream interface also includes print(), println(), write().
#### Character modi
Most of these are supported (more or less) in terminal apps.
- **void normal()** normal intensity.
- **void bold()** bold or high intensity.
- **void low()** low intensity.
- **void underline()** idem.
- **void blink()** idem.
- **void blinkFast()** idem.
- **void reverse()** idem.
@ -121,7 +124,23 @@ Some are working with Teraterm, others are unclear of fail.
The user can uncomment these and verify if these work with their terminal.
##### Experimental device type
##### Experimental getScreenSize()
Added in 0.2.2 (From PR #16 refactored) use with care.
- **bool readCursorPosition(uint16_t &w, uint16_t &h, uint32_t timeout = 100)**
returns true if width and height are reported.
Be sure to test the return value!
- **bool getScreenSize(uint16_t &w, uint16_t &h, uint32_t timeout = 100)**
returns true if width and height are reported.
Be sure to test the return value!
- **inline uint16_t screenWidth()** used after successful
call of getScreenSize();
- **inline uint16_t screenHeight()** used after successful
call of getScreenSize();
##### Experimental deviceType()
The **int deviceType()** function needs more testing.

View File

@ -1,7 +1,7 @@
//
// FILE: ansi.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.1
// VERSION: 0.3.0
// PURPOSE: Arduino library to send ANSI escape sequences
// DATE: 2020-04-28
// URL: https://github.com/RobTillaart/ANSI
@ -50,32 +50,37 @@ void ANSI::flush()
//
void ANSI::normal()
{
_stream->write("\033[0m", 3);
_stream->write("\033[0m", 4);
}
void ANSI::bold()
{
_stream->write("\033[1m", 3);
_stream->write("\033[1m", 4);
}
void ANSI::low()
{
_stream->write("\033[2m", 3);
_stream->write("\033[2m", 4);
}
void ANSI::underline()
{
_stream->write("\033[4m", 3);
_stream->write("\033[4m", 4);
}
void ANSI::blink()
{
_stream->write("\033[5m", 3);
_stream->write("\033[5m", 4);
}
void ANSI::blinkFast()
{
_stream->write("\033[6m", 4);
}
void ANSI::reverse()
{
_stream->write("\033[7m", 3);
_stream->write("\033[7m", 4);
}
@ -202,24 +207,86 @@ int ANSI::deviceType(uint32_t timeout)
int type = -1; // -1 = unknown
print("\033[0c");
char buffer[4];
int len = 0;
char c;
uint32_t start = millis();
int read_len = 0;
char buffer[8];
while ((read_len != 3) && ((millis() - start) < timeout))
while ((len < 3) && ((millis() - start) < timeout))
{
delay(1);
read_len = Serial.readBytes(buffer, 3);
if ((buffer[0] == '1') && (buffer[1] == ';'))
if (_stream->available())
{
type = buffer[2] - '0';
c = _stream->read();
buffer[len++] = c;
buffer[len] = 0;
}
// Serial.write(buffer, 3);
// Serial.println();
}
if ((buffer[0] == '1') && (buffer[1] == ';'))
{
type = buffer[2] - '0';
}
return type;
}
bool ANSI::readCursorPosition(uint16_t &w, uint16_t &h, uint32_t timeout)
{
print("\033[6n");
char buffer[16];
int len = 0;
char c;
uint32_t start = millis();
while (millis() - start < timeout)
{
if (_stream->available())
{
c = _stream->read();
buffer[len++] = c;
buffer[len] = 0;
if (c == 'R') break;
}
}
// do we have enough chars
// typical (8) = \e[24;80R
// minimal (6) = \e[1;1R
if (len < 6) return false;
// last char must be R to have them all.
if (c != 'R') return false;
// parse the buffer
int number[2] = {0, 0};
int i = 0;
// read digits.
for (int n = 0; n < 2; n++)
{
// skip until digits
while ((i < len) && !isdigit(buffer[i])) i++;
// read number
while ((i < len) && isdigit(buffer[i]))
{
number[n] *= 10;
number[n] += buffer[i] - '0';
i++;
}
}
w = number[1];
h = number[0];
return ((w > 0) && (h > 0));
}
bool ANSI::getScreenSize(uint16_t &w, uint16_t &h, uint32_t timeout)
{
// gotoXY(9999,9999);
print("\033[9999;9999H");
bool rv = readCursorPosition(w, h, timeout);
_width = w;
_height = h;
return rv;
}
//////////////////////////////////////////////////
//
// PROTECTED

View File

@ -2,7 +2,7 @@
//
// FILE: ansi.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.1
// VERSION: 0.3.0
// PURPOSE: Arduino library to send ANSI escape sequences
// DATE: 2020-04-28
// URL: https://github.com/RobTillaart/ANSI
@ -10,7 +10,7 @@
#include "Arduino.h"
#define ANSI_LIB_VERSION (F("0.2.1"))
#define ANSI_LIB_VERSION (F("0.3.0"))
class ANSI : public Stream
@ -31,6 +31,7 @@ public:
void low();
void underline();
void blink();
void blinkFast();
void reverse();
@ -92,17 +93,32 @@ public:
// EXPERIMENTAL SECTION
// use at own risk
// META
// deviceType is discussed
// - https://github.com/RobTillaart/ANSI/issues/9
// use at own risk
// TERMINAL TYPE
// - https://github.com/RobTillaart/ANSI/issues/9
// timeout in milliseconds.
// note this function blocks for timeout or less.
// -1 = unknown;
// 1 = VT52, 2 = VT100, 3 = VT220,
enum {
UNKNOWN = -1,
// known types
VT52 = 1,
VT100 = 2,
VT220 = 3,
// add others if needed.
};
int deviceType(uint32_t timeout = 100);
// SCREENSIZE
// - https://github.com/RobTillaart/ANSI/pull/16
bool readCursorPosition(uint16_t &w, uint16_t &h, uint32_t timeout = 100);
bool getScreenSize(uint16_t &w, uint16_t &h, uint32_t timeout = 100);
// to be used after successful call of getScreenSize();
inline uint16_t screenWidth() { return _width; };
inline uint16_t screenHeight() { return _height; };
// check if it works on your terminal
// TERATERM
void set132columns() { print("\033[?3h"); }; // +
@ -148,6 +164,9 @@ protected:
Stream * _stream;
// screen size parameters
uint16_t _width = 0;
uint16_t _height = 0;
};

View File

@ -15,10 +15,13 @@ void setup()
Serial.begin(115200);
ansi.clearScreen();
ansi.println("Hello world");
ansi.bold();
ansi.println("Hello world");
ansi.blink();
ansi.println("Hello world");
ansi.blinkFast();
ansi.println("Hello world");
ansi.underline();
ansi.println("Hello world");
ansi.low();

View File

@ -0,0 +1,16 @@
IDE: 1.8.19
Board: UNO
ansi_performance.ino
0.3.0
PERFORMANCE TEST ANSI TERMINAL PRINT
ANSITERM: 352
PERFORMANCE TEST ANSI TERMINAL PRINT
SERIAL: 300
(cleaned output of clearScreen(); test)
ANSITERM: 52
SERIAL: 56
done...

View File

@ -0,0 +1,78 @@
//
// FILE: ansi_screenSize.ino
// AUTHOR: Hans Schou
// PURPOSE: demo of screen size detection
// URL: https://github.com/RobTillaart/ANSI
//
// These terminal emulators can report screen size:
// * Linux, minicom
// * Windows, PuTTY
// * Windows, TeraTerm
// * Windows, MobaXterm
//
// UTF-8: To draw boxes with other than ASCII characters
// an extra font has to be added.
#include "ansi.h"
/*
Example output:
+---------------------
|
| Screen size: 80x24
|
*/
ANSI ansi(&Serial);
uint16_t w, h;
void setup() {
Serial.begin(115200);
ansi.print(" "); // some bug, first character written is missing
if (!ansi.getScreenSize(w, h, 100)) {
ansi.println(F("\n\n### ANSI escape codes not detected ###\n"
"\nThis demo requires a terminal (emulator) with ANSI escape code capabilities."
"\nThe terminal you are using can only do TTY."
"\nOn Linux 'minicom' can be used. On Windows try Putty or MobaXterm."
"\nExample:"
"\n minicom --color=on --baudrate=115200 -D /dev/ttyACM0"
"\n\nUTF-8 is also required. Your should see at least one emoji here?: 🐛 🖥 ☎ ❤ ❣ ✂ ✈"
"\n"
"\nSystem halted."));
while (1) {}
}
ansi.clearScreen();
ansi.gotoXY(6, 3);
ansi.print("Screen size: ");
ansi.print(ansi.screenWidth());
ansi.print("x");
ansi.println(ansi.screenHeight());
ansi.gotoXY(6, 4);
ansi.print("\nUTF-8 test. Your should see at least one emoji here?: 🐛 🖥 ☎ ❤ ❣ ✂ ✈");
delay(1000);
// Draw border
ansi.color(ansi.yellow, ansi.blue);
for (uint16_t y = 1; y <= ansi.screenHeight(); y++) {
ansi.gotoXY(1, y);
if (1 == y || ansi.screenHeight() == y) {
ansi.print("+");
for (uint16_t x = 1; x < ansi.screenWidth() - 1; x++)
ansi.print("-");
ansi.print("+");
} else {
ansi.print("|");
ansi.cursorForward(ansi.screenWidth() - 2);
ansi.print("|");
}
}
delay(3000);
}
void loop() {
}
// -- END OF FILE --

View File

@ -12,6 +12,7 @@ bold KEYWORD2
low KEYWORD2
underline KEYWORD2
blink KEYWORD2
blinkFast KEYWORD2
reverse KEYWORD2
clearScreen KEYWORD2
@ -32,10 +33,15 @@ gray2color KEYWORD2
grey2color KEYWORD2
rgb2color KEYWORD2
# EXPERIMENTAL
deviceType KEYWORD2
readCursorPosition KEYWORD2
getScreenSize KEYWORD2
screenWidth KEYWORD2
screenHeight KEYWORD2
# EXPERIMENTAL
set132columns KEYWORD2
set80columns KEYWORD2
@ -46,6 +52,8 @@ reset KEYWORD2
# Constants (LITERAL1)
ANSI_LIB_VERSION LITERAL1
toEnd LITERAL1
toStart LITERAL1
entireLine LITERAL1

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/ANSI.git"
},
"version": "0.2.1",
"version": "0.3.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=ANSI
version=0.2.1
version=0.3.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library to send ANSI escape sequences.