#include
#include
#include
#include
#include
// OS-specific libraries.
#include
#include
#include "ansi_code.hpp"
#include "common.hpp"
#include "input_output.hpp"
#include "terminal_pager.hpp"
terminal_pager::terminal_pager()
: m_rows(0)
, m_columns(0)
, m_start_row_index(0)
{
maybe_grab_cout();
}
terminal_pager::~terminal_pager()
{
release_cout();
}
std::string terminal_pager::get_input() const
{
// Blocks until input received.
std::string str;
char ch;
std::cin.get(ch);
str += ch;
if (ansi_code::is_escape_char(ch)) // Start of ANSI escape sequence.
{
do
{
std::cin.get(ch);
str += ch;
} while (!std::isalpha(ch)); // ANSI escape sequence ends with a letter.
}
return str;
}
void terminal_pager::maybe_grab_cout()
{
// Unfortunately need to access _internal namespace of termcolor to check if a tty.
if (termcolor::_internal::is_atty(std::cout))
{
// Should we do anything with cerr?
m_cout_rdbuf = std::cout.rdbuf(&m_stringbuf);
}
else
{
m_cout_rdbuf = std::cout.rdbuf();
}
}
bool terminal_pager::process_input(std::string input)
{
if (input.size() == 0)
{
return true;
}
switch (input[0])
{
case 'q':
case 'Q':
return true; // Exit pager.
case 'u':
case 'U':
scroll(true, true); // Up a page.
return false;
case 'd':
case 'D':
case ' ':
scroll(false, true); // Down a page.
return false;
case '\n':
scroll(false, false); // Down a line.
return false;
case '\e': // ANSI escape sequence.
// Cannot switch on a std::string.
if (ansi_code::is_up_arrow(input))
{
scroll(true, false); // Up a line.
return false;
}
else if (ansi_code::is_down_arrow(input))
{
scroll(false, false); // Down a line.
return false;
}
}
std::cout