Terminal mock for unit-testing python curses programs? - unit-testing

I am writing an interactive terminal program using Python curses. I'd like to write unit tests for its functionalities such as drawing custom pads, controlling font colors, scrolling, and resizing responses. But after some tries and searches, I couldn't find a way to write such unit tests without actually invoking the terminal; I couldn't find a function in curses to read the content of the screen, either.
Is there a mock terminal for Python curses that serves these unit testing needs?

You can ask curses what it thinks is on the screen:
inch, winch, mvinch, mvwinch - get a character and
attributes from a curses window
inchstr, inchnstr, winchstr, winchnstr, mvinchstr,
mvinchnstr, mvwinchstr, mvwinchnstr - get a string of
characters (and attributes) from a curses window
instr, innstr, winstr, winnstr, mvinstr, mvinnstr, mvwin-
str, mvwinnstr - get a string of characters from a curses
window
The Python binding provides a way to use those functions (not complete, but sufficient):
window.inch([y, x])
Return the character at the given position in the window. The bottom 8 bits are the character proper, and upper bits are the attributes.
window.instr([n]) window.instr(y, x[, n])
Return a string of characters, extracted from the window starting at the current cursor position, or at y, x if specified. Attributes are stripped from the characters. If n is specified, instr() returns a string at most n characters long (exclusive of the trailing NUL).

Related

How to move cursor position when printing data in Linux Terminal using C++? [duplicate]

I'm currently designing a CLI interface for linux, and for various reasons I am not able to use ncurses. I am using exclusively C++ and the Qt framework.
Therefore, in order to have a user-friendly interface, I have to run this getch loop in a separate thread:
https://stackoverflow.com/a/912796/3605689
Which basically means I have to implement all basic functionalities (such as backspace) by myself. I have already implemented command completion and command history(like when you press tab or uparrow/downarrow in linux), but I can't figure out how to implement leftarrow/rightarrow (aka seeking through the typeahead).
Normally, I implement it like this: upon every gech which is not equal to -1, I check whether the user has pressed a special key (one that modifies the typeahead somehow). I then clear the stdout using the following function:
void inputobject::clear_line(int nletters)
{
QTextStream(stdout) << "\033[2K";
for(int i = 0; i < nletters;i++){
QTextStream(stdout) << "\b";
}
rewind(stdout);
}
And replace it with something else, effectively simulating the typeahead. For example, in the case of backspace, I would save the command call clear_line, and print the command out again, just with one less letter, behaving exactly as a normal console application would.
My real problem is with the cursor, in the case of left/rightarrow, I need to move the cursor visual in order to be able to indicate where in the text is the user seeking:
Because of the nature of how I rewrite the given stdout line to simulate the typeahead, it does not really matter where the cursor REALLY is, as long as it stays on the same line - it is just the visual that matters. How can I achieve moving the cursor visual on linux?
The answer was provided in the comment by Evilruff:
Cursor Movement
ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:
Position the Cursor:
\033[;H
Or
\033[L;Cf
puts the cursor at line L and column C.
Move the cursor up N lines:
\033[NA
Move the cursor down N lines:
\033[NB
Move the cursor forward N columns:
\033[NC
Move the cursor backward N columns:
\033[ND
Clear the screen, move to (0,0):
\033[2J
Erase to end of line:
\033[K
Save cursor position:
\033[s
Restore cursor position:
\033[u
Not using ncurses and co is a serious limitation.
It is hell to make correct input/output on shell for displaying anything.
The only others real solutions (I can't think as a solution to reimplement a ncurse-like library) I think of are:
making call to dialog (for some example www.linuxjournal.com/article/2807 and for the doc: http://linux.die.net/man/1/dialog)
using the framebuffer mecanism with Qt4 (here)

Strikethrough text in ncurses

I am developing a terminal TUI application for myself using the ncurses library. (Running on Linux)
I cannot seem to find much info regarding the use of a "strikethrough/strikeout" text attribute when adding a string to a ncurses window using addstr and friends.
The only information I've found online was on this site:
https://midnight-commander.org/ticket/3264
Ncurses will not add [strikethrough text] because the bitfield is already fully packed.
I was wondering if there are any workarounds to this, or any official way to do this.
Any help would be appreciated.
Thanks.
ncurses has 16 bits allocated for video-attributes. SVr4 curses used 8; XOpen Curses added 7. Those 15 are defined for X/Open Curses compatibility.
Referring to the X/Open Curses documentation, there are two sets of definitions:
A_ALTCHARSET Alternate character set
A_BLINK Blinking
A_BOLD Extra bright or bold
A_DIM Half bright
A_INVIS Invisible
A_PROTECT Protected
A_REVERSE Reverse video
A_STANDOUT Best highlighting mode of the terminal
A_UNDERLINE Underlining
and
WA_ALTCHARSET Alternate character set
WA_BLINK Blinking
WA_BOLD Extra bright or bold
WA_DIM Half bright
WA_HORIZONTAL Horizontal highlight
WA_INVIS Invisible
WA_LEFT Left highlight
WA_LOW Low highlight
WA_PROTECT Protected
WA_REVERSE Reverse video
WA_RIGHT Right highlight
WA_STANDOUT Best highlighting mode of the terminal
WA_TOP Top highlight
WA_UNDERLINE Underlining
WA_VERTICAL Vertical highlight
depending on whether the bits are stored in a attr_t or a chtype (X/Open and SVr4 respectively). In ncurses, those are the same (see the manual page), so that it does not matter if one refers to A_BOLD or WA_BOLD (Solaris xpg4 curses does store those differently).
Discounting the A_ vs WA_, the two lists are different. The newer ones from X/Open Curses are rarely used. Since ncurses doesn't know what it looks like on the screen, someone could add the corresponding terminfo capability to a terminal description and ncurses would handle it.
The terminfo manual page mentions these:
The XSI Curses standard added these hardcopy capabilities. They were
used in some post-4.1 versions of System V curses, e.g., Solaris 2.5
and IRIX 6.x. Except for YI, the ncurses termcap names for them are
invented. According to the XSI Curses standard, they have no termcap
names. If your compiled terminfo entries use these, they may not be
binary-compatible with System V terminfo entries after SVr4.1; beware!
(Explaining how to modify a terminal description can be found in thousands of webpages, and is off-topic for this forum).
Possible attributes in ncurses are:
A_NORMAL Normal display (no highlight)
A_STANDOUT Best highlighting mode of the terminal.
A_UNDERLINE Underlining
A_REVERSE Reverse video
A_BLINK Blinking
A_DIM Half bright
A_BOLD Extra bright or bold
A_PROTECT Protected mode
A_INVIS Invisible or blank mode
A_ALTCHARSET Alternate character set
A_CHARTEXT Bit−mask to extract a character
COLOR_PAIR(n) Color−pair number n
Functions like attron(), attroff(), attrset() may be used to work with attributes,
Strikethrough is not and will not be available.
If you know your terminal and want your software to be able to to work just on such an terminal type AND the terminal supports strikethrough, then you can use control characters or escape sequences to activate such a funcionality.
You can use Unicode for that:
(I know it's an old question, but I had a similar issue, and this is the top result for "curses strikethrough" on Google, so this answer might be helpful to someone.)
I made it work using Python, but the strategy should work in any language:
import curses
def strike(text: str) -> str:
# See <https://stackoverflow.com/a/25244576/4039050>
return "\u0336".join(text) + "\u0336"
def main(stdscr):
message = "The quick brown fox jumps over the lazy dog."
stdscr.addstr(strike(message))
stdscr.refresh()
stdscr.getch()
if __name__ == "__main__":
curses.wrapper(main)

Borland c++ console functions

I'm studing now and I got this homework / tasks to do:
1) If you press the CTRL + L key, all numeric symbols should change the color.
2) If you press the CTRL + S key, you will get the length of the word, left from the cursor.
I found this function int bioskey(int cmd);
So now I can check if the key is pressed, but how to change the color only of numeric symbols, or read words from console to get their length ?
Some of us still remember the MS-DOS (let it rest in peace or pieces...)
if you are really in MS-DOS then you can not expect that the content of the console would be changed in colors for only specific areas. You need to do that your self. The problem is we do not know anything about your project background so we do not know what and how yours stuff is represented,rendered/outputed/inputed etc...
I assume EGA/VGA BIOS text mode is used so you can exploit direct access to the VRAM. So you need to set pointer to the address B800:0000 and handle it as array where each character on screen has 2 BYTEs. one is color attribute and the other is ASCII code (not sure in which order anymore)...
So for already rendered stuff you just:
loop through whole screen
usually 80x25x2 Bytes
test each ASCII for alpha numeric value
so ASCII code >= '0' and code<='9' for numbers or add all the stuff you are considering as alphanumeric like code>' ' and code<='9'.
change colors for selected characters
just by changing the attribute byte.
When you put it together for numbers it will look like this:
char far *scr=(char far*)0x0B0000000;
int x,y,a;
for (a=0,y=0;y<25;y++)
for (x=0;x<80;x++,a+=2)
if ((scr[a+0]>='0')&&((scr[a+0]<='9'))
{
scr[a+1]=7; //attribute with the different color here
}
if it does not work than try swap scr[a+0] and scr[a+1]. If an exception occur then you are not in MS-DOS and you do not have access to VRAM. In that case use DOS-BOX or driver that allows access to memory like dllportio ...
For more info see some more or less related QA's:
Display an array of color in C
What is the best way to move an object on the screen?
If you got problem with the CTRL+Key detection not sure if in-build function in TC++ allows CTRL (was too long ago) then you can exploit BIOS or even hook up the keyboard ISR. See the second link where ISR for keyboard handler is there present... You can port it to C++ or google there must be a lot of examples out there especially TP7.0 (which is pascal but easily portable to TC++)

Linux - moving the console cursor visual

I'm currently designing a CLI interface for linux, and for various reasons I am not able to use ncurses. I am using exclusively C++ and the Qt framework.
Therefore, in order to have a user-friendly interface, I have to run this getch loop in a separate thread:
https://stackoverflow.com/a/912796/3605689
Which basically means I have to implement all basic functionalities (such as backspace) by myself. I have already implemented command completion and command history(like when you press tab or uparrow/downarrow in linux), but I can't figure out how to implement leftarrow/rightarrow (aka seeking through the typeahead).
Normally, I implement it like this: upon every gech which is not equal to -1, I check whether the user has pressed a special key (one that modifies the typeahead somehow). I then clear the stdout using the following function:
void inputobject::clear_line(int nletters)
{
QTextStream(stdout) << "\033[2K";
for(int i = 0; i < nletters;i++){
QTextStream(stdout) << "\b";
}
rewind(stdout);
}
And replace it with something else, effectively simulating the typeahead. For example, in the case of backspace, I would save the command call clear_line, and print the command out again, just with one less letter, behaving exactly as a normal console application would.
My real problem is with the cursor, in the case of left/rightarrow, I need to move the cursor visual in order to be able to indicate where in the text is the user seeking:
Because of the nature of how I rewrite the given stdout line to simulate the typeahead, it does not really matter where the cursor REALLY is, as long as it stays on the same line - it is just the visual that matters. How can I achieve moving the cursor visual on linux?
The answer was provided in the comment by Evilruff:
Cursor Movement
ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:
Position the Cursor:
\033[;H
Or
\033[L;Cf
puts the cursor at line L and column C.
Move the cursor up N lines:
\033[NA
Move the cursor down N lines:
\033[NB
Move the cursor forward N columns:
\033[NC
Move the cursor backward N columns:
\033[ND
Clear the screen, move to (0,0):
\033[2J
Erase to end of line:
\033[K
Save cursor position:
\033[s
Restore cursor position:
\033[u
Not using ncurses and co is a serious limitation.
It is hell to make correct input/output on shell for displaying anything.
The only others real solutions (I can't think as a solution to reimplement a ncurse-like library) I think of are:
making call to dialog (for some example www.linuxjournal.com/article/2807 and for the doc: http://linux.die.net/man/1/dialog)
using the framebuffer mecanism with Qt4 (here)

Getting cursor position and terminal size in linux terminal

In my console based Linux C++ application I want to get the size of the terminal (lines+columns) and the current cursor position. For the latter I think I could use the ANSI codes for that, but I am not sure how to parse it correctly. Also I don't see how to get the size of the window?
For other reasons switching to ncurses is not an option at this time.
Old method of getting the size was termcap with the libtermcap. New is terminfo (+lib).
I would recommend to use a library that abstracts this (and all other terminal related stuff) away and use a terminal output library like (n)curses.
This will in addition also work on other Unix systems.
To fetch the size, the correct way is to call the TIOCGWINSZ ioctl(). An example from my code:
struct winsize ws = { 0, 0, 0, 0 };
if(ioctl(tt->outfd, TIOCGWINSZ, &ws) == -1)
return;
/* ws.ws_row and ws.ws_col now give the size */
You'll want to do that initially, and then again after receipt of a SIGWINCH signal, which informs of a WINdow CHange.
As for obtaining the cursor position, that's a little harder. Some terminals allow querying it by DSR 6 (Device Status Report)
$ echo -ne "\e[6n"; cat -v
^[[62;1R
The reply from DSR comes in CSI R, here telling me the (1-based) 62nd row, 1st column.
However, since not all terminals support DSR 6, it may be easiest not to rely on being able to query the cursor position, and instead performing your initial terminal addressing in an absolute manner, placing the cursor exactly where you want it.