1 #pragma once 2 3 4 #include <utility> 5 #include <memory> 6 #include <uv.h> 7 #include "stream.hpp" 8 #include "util.hpp" 9 10 11 namespace uvw { 12 13 14 namespace details { 15 16 17 struct ResetModeMemo { ~ResetModeMemouvw::details::ResetModeMemo18 ~ResetModeMemo() { 19 uv_tty_reset_mode(); 20 } 21 }; 22 23 24 enum class UVTTYModeT: std::underlying_type_t<uv_tty_mode_t> { 25 NORMAL = UV_TTY_MODE_NORMAL, 26 RAW = UV_TTY_MODE_RAW, 27 IO = UV_TTY_MODE_IO 28 }; 29 30 31 } 32 33 34 /** 35 * @brief The TTYHandle handle. 36 * 37 * TTY handles represent a stream for the console. 38 * 39 * To create a `TTYHandle` through a `Loop`, arguments follow: 40 * 41 * * A valid FileHandle. Usually the file descriptor will be: 42 * * `uvw::StdIN` or `0` for `stdin` 43 * * `uvw::StdOUT` or `1` for `stdout` 44 * * `uvw::StdERR` or `2` for `stderr` 45 * * A boolean value that specifies the plan on calling `read()` with this 46 * stream. Remember that `stdin` is readable, `stdout` is not. 47 * 48 * See the official 49 * [documentation](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_init) 50 * for further details. 51 */ 52 class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> { resetModeMemo()53 static auto resetModeMemo() { 54 static std::weak_ptr<details::ResetModeMemo> weak; 55 auto shared = weak.lock(); 56 if(!shared) { weak = shared = std::make_shared<details::ResetModeMemo>(); } 57 return shared; 58 } 59 60 public: 61 using Mode = details::UVTTYModeT; 62 TTYHandle(ConstructorAccess ca,std::shared_ptr<Loop> ref,FileHandle desc,bool readable)63 explicit TTYHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, FileHandle desc, bool readable) 64 : StreamHandle{ca, std::move(ref)}, 65 memo{resetModeMemo()}, 66 fd{desc}, 67 rw{readable} 68 {} 69 70 /** 71 * @brief Initializes the handle. 72 * @return True in case of success, false otherwise. 73 */ init()74 bool init() { 75 return initialize(&uv_tty_init, fd, rw); 76 } 77 78 /** 79 * @brief Sets the TTY using the specified terminal mode. 80 * 81 * Available modes are: 82 * 83 * * `TTY::Mode::NORMAL` 84 * * `TTY::Mode::RAW` 85 * * `TTY::Mode::IO` 86 * 87 * See the official 88 * [documentation](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_mode_t) 89 * for further details. 90 * 91 * @param m The mode to be set. 92 * @return True in case of success, false otherwise. 93 */ mode(Mode m)94 bool mode(Mode m) { 95 return (0 == uv_tty_set_mode(get(), static_cast<std::underlying_type_t<Mode>>(m))); 96 } 97 98 /** 99 * @brief Resets TTY settings to default values. 100 * @return True in case of success, false otherwise. 101 */ reset()102 bool reset() noexcept { 103 return (0 == uv_tty_reset_mode()); 104 } 105 106 /** 107 * @brief Gets the current Window size. 108 * @return The current Window size or `{-1, -1}` in case of errors. 109 */ getWinSize()110 WinSize getWinSize() { 111 WinSize size; 112 113 if(0 != uv_tty_get_winsize(get(), &size.width, &size.height)) { 114 size.width = -1; 115 size.height = -1; 116 } 117 118 return size; 119 } 120 121 private: 122 std::shared_ptr<details::ResetModeMemo> memo; 123 FileHandle::Type fd; 124 int rw; 125 }; 126 127 128 } 129