libcruft-util/cruft/util/term.cpp

126 lines
3.3 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2016-2017 Danny Robson <danny@nerdcruft.net>
*/
#include "term.hpp"
#include "string.hpp"
#include <filesystem>
#include <cstdlib>
#include <stdexcept>
using cruft::term::csi::graphics;
const graphics graphics::RESET (0);
///////////////////////////////////////////////////////////////////////////////
// find the terminfo path within a directory, for a key
//
// throws an exception if not found
static
std::filesystem::path
find_terminfo_path (const std::filesystem::path &dir,
const std::string &key)
{
const char letter[2] = { key[0], '\0' };
auto candidate = dir / letter / key;
if (!std::filesystem::is_directory (candidate))
throw std::runtime_error ("path not found");
return candidate;
}
//-----------------------------------------------------------------------------
// find the terminfo path for a given key.
//
// throws an exception if not found
static
std::filesystem::path
find_terminfo_path [[gnu::unused]] (const std::string &key)
{
static const std::filesystem::path DEFAULT_SEARCH_DIR = "/usr/share/terminfo";
// check if the path is explicitly listed. must not fall through.
if (const char *dir = getenv ("TERMINFO")) {
return find_terminfo_path (dir, key);
}
// check if we have a path at $HOME. falls through.
if (const char *home = getenv ("HOME")) {
std::filesystem::path HOME (home);
try {
return find_terminfo_path (HOME / ".terminfo", key);
} catch (...) { }
}
// check colon seperated list in TERMINFO_DIRS
if (const char *dirs = getenv ("TERMINFO_DIRS")) {
auto tok = cruft::tokeniser (dirs, ':');
for (auto i: tok) {
try {
return find_terminfo_path (
i.empty () ?
DEFAULT_SEARCH_DIR :
std::filesystem::path (i.cbegin (), i.cend ()), key
);
} catch (...) { }
}
}
return find_terminfo_path ("/usr/share/terminfo", key);
}
///////////////////////////////////////////////////////////////////////////////
bool
cruft::term::has_csi_support (void)
{
// HACK: this will do until we get a terminfo/termcap reader
return getenv ("TERM") == std::string ("XTERM");
}
///////////////////////////////////////////////////////////////////////////////
graphics::graphics (layer _layer, hue _hue):
m_value (_layer + int (_hue))
{ ; }
//-----------------------------------------------------------------------------
graphics::graphics (char _value):
m_value (_value)
{ ; }
///////////////////////////////////////////////////////////////////////////////
char
graphics::value (void) const
{
return m_value;
}
//-----------------------------------------------------------------------------
char
graphics::value (char _value)
{
return m_value = _value;
}
///////////////////////////////////////////////////////////////////////////////
std::ostream&
cruft::term::csi::operator<< (std::ostream &os, graphics g)
{
return os << code::CSI << '[' << +g.value () << decltype(g)::terminator;
}