Hi, I’m studying with the Ada Craft (95) manual, but I have a big issue, in that I am autistic. I have an idea of how I want to do it, what seems the most intuitive to me, regardless of the language’s capabilities or how much of it I learnt.
Here’s an exemple:
Change the way that appointments are listed so that they are displayed a screenful at a time (or just under a screenful to allow room for prompts etc.) on the system that you’re using. Provide the ability to go either forwards or backwards a screen or half a screen at a time.
In my head, I need to know how to :
Clear the screen
define the type and object “page” made of (Page_Length) lines of (Line_Length) characters.
Reformat the output to fit “page”, populate “page” and outputs it
But I’m pretty sure I shouldnt do that, but I can’t figure out, and waiting is not gonna help, because I’m autistic. I can not think “simply”. I would like a tutorial for dealing with terminals in Ada…
Also, I have debian, and I can only clear the screen and change the line with ANSI codes. New_Page and Set_Line have no effect, beside adding two new lines for the former. The line number is reset alright, but with no change to the terminal. Checked on bash, fish, urxvt and foot. Seems like Ada.Text_IO can’t controll the standard input, and can’t request line length either.
So I don’t understand how to do the exo, since I’m pretty sure I’m not expected to use a binding to ncurse…
However, nothing in your requirements indicates that you need to do this. You can simply output a screen-full of information, scrolling the existing information off the screen, and wait for user input.
If your screen/terminal emulator has N lines, then a screenful is usually N - 1 lines, with the Nth line reserved for prompts/input. N is often 24. Consider
with Ada.Text_IO;
procedure Screens_Full is
Screen_Lines : constant := 23; -- Presume 24-line terminal, with last line for prompts/input
procedure Display (Start : in Positive);
-- Display a screenful of lines, starting with line Start
procedure Display (Start : in Positive) is
-- Empty
begin -- Display
All_Lines : for L in Start .. Start + Screen_Lines - 1 loop
Ada.Text_IO.Put_Line (Item => "Line" & L'Image);
end loop All_Lines;
end Display;
Next : Positive := 1;
Command : Character;
begin -- Screens_Full
All_Screens : loop
Display (Start => Next);
Get_Command : loop
Ada.Text_IO.Get_Immediate (Item => Command);
case Command is
when 'n' => -- Next screen
Next := Next + Screen_Lines;
exit Get_Command;
when 'p' => -- Previous screen
Next := Integer'Max (1, Next - Screen_Lines);
exit Get_Command;
when 'q' => -- Quit
return;
when others =>
null;
end case;
end loop Get_Command;
end loop All_Screens;
end Screens_Full;
“Often” 24. I suppose I can’t request the real number. And What happens if “Line” becomes a long string, that spans more than one one line ?
I wish I could just take in all the output and refactor it in pages of appropriate width and height. But I’m not supposed to think so hard, ok.
The answer to those questions may be implementation dependent and may also change based on terminal settings. I know for BASH shells I can do “echo $LINES” to get the number of lines in the terminal, but that number can change if the person stretches the window. In my case stuff that is longer than the terminal line just extends out into space and I can use the scroll bar to see it.
But it may very with different terminals and different OS versions.
Possibly yeah. Unfortunately the practical implications of how systems exist can make general solutions tough or even in some cases impossible. In those cases you either have to bite your lip and just do a suboptimal solution (relative to your preferences) or abandon the process all together.
If you know the appropriate width and height then you know the number of lines. If you don’t know them, and have to deal with the possibility of them being different from run to run, then displaying a “screenful” becomes pretty much impossible. I don’t know a portable way to obtain those values. Possibly some combination of the ANSI position-cursor and report-cursor codes could do it.
But as this is a pedagogical exercise, I suspect you’re over-thinking things. No doubt the intention is that you assume the default size of the console/terminal emulator you are using, and ignore the possibility that it might be different.
I would look at libcurses (don’t know whether there are Ada bindings, but the API is not that extensive in practice). It will let you query terminal size, write characters are specific positions on the screen, and so on. For inspiration, take a look at the curses package in python possibly, or the doc of libcurses itself
I’m a little late, but Ncurses is overkill for this. All of this can very easily be done without a library and, while I used the DEVICE STATUS REPORT control function which makes the terminal send an ACTIVE POSITION REPORT control function I then parsed to get the current position of the cursor and from that the dimensions, an Ada program would be better suited to binding the C language bullshit that returns this value more easily. Unlike Common Lisp, Ada makes it very easy to bind to such routines.
I almost wrote a shitty Ada library like this, but the lack of metaprogramming swayed me. Only a handful of these control functions are needed for most programs, so a library is superfluous. I may as well continue to use mine, however.