peaclock

A responsive and customizable clock, timer, and stopwatch for the terminal.


peaclock

/

src

/

ob

/

readline.hh

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#ifndef OB_READLINE_HH
#define OB_READLINE_HH

#include "ob/text.hh"

#include <cstddef>

#include <deque>
#include <string>
#include <limits>
#include <fstream>

#include <filesystem>
namespace fs = std::filesystem;

namespace OB
{

class Readline
{
public:

  Readline() = default;

  Readline& style(std::string const& style = {});
  Readline& prompt(std::string const& str, std::string const& style = {});

  std::string operator()(bool& is_running);

  void hist_push(std::string const& str);
  void hist_load(fs::path const& path);

private:

  void refresh();

  void curs_begin();
  void curs_end();
  void curs_left();
  void curs_right();

  void edit_insert(std::string const& str);
  void edit_clear();
  bool edit_delete();
  bool edit_backspace();

  void hist_prev();
  void hist_next();
  void hist_reset();
  void hist_search(std::string const& str);
  void hist_open(fs::path const& path);
  void hist_save(std::string const& str);

  std::string normalize(std::string const& str) const;

  // width and height of the terminal
  std::size_t _width {0};
  std::size_t _height {0};

  struct Style
  {
    std::string prompt;
    std::string input;
  } _style;

  struct Prompt
  {
    std::string lhs;
    std::string rhs;
    std::string fmt;
    std::string str {":"};
  } _prompt;

  struct Input
  {
    std::size_t off {0};
    std::size_t idx {0};
    std::size_t cur {0};
    std::string buf;
    OB::Text::String str;
    OB::Text::String fmt;
  } _input;

  struct History
  {
    static std::size_t constexpr npos {std::numeric_limits<std::size_t>::max()};

    struct Search
    {
      struct Result
      {
        Result(std::size_t s, std::size_t i):
          score {s},
          idx {i}
        {
        }

        std::size_t score {0};
        std::size_t idx {0};
      };

      using value_type = std::deque<Result>;

      value_type& operator()()
      {
        return val;
      }

      bool empty()
      {
        return val.empty();
      }

      void clear()
      {
        idx = History::npos;
        val.clear();
      }

      std::size_t idx {0};
      value_type val;
    } search;

    using value_type = std::deque<std::string>;

    value_type& operator()()
    {
      return val;
    }

    value_type val;
    std::size_t idx {npos};

    std::ofstream file;
  } _history;
};

} // namespace OB

#endif // OB_READLINE_HH
Back to Top