|
20 | 20 |
|
21 | 21 | #include <crispy/App.h>
|
22 | 22 | #include <crispy/StackTrace.h>
|
| 23 | +#include <crispy/base64.h> |
23 | 24 | #include <crispy/utils.h>
|
24 | 25 |
|
25 | 26 | #include <fmt/chrono.h>
|
@@ -54,6 +55,7 @@ using std::string_view;
|
54 | 55 | using std::unique_ptr;
|
55 | 56 |
|
56 | 57 | using namespace std::string_literals;
|
| 58 | +using namespace std::string_view_literals; |
57 | 59 |
|
58 | 60 | namespace CLI = crispy::cli;
|
59 | 61 |
|
@@ -239,6 +241,106 @@ int ContourApp::captureAction()
|
239 | 241 | return EXIT_FAILURE;
|
240 | 242 | }
|
241 | 243 |
|
| 244 | +#if defined(GOOD_IMAGE_PROTOCOL) |
| 245 | +namespace |
| 246 | +{ |
| 247 | + crispy::Size parseSize(string_view _text) |
| 248 | + { |
| 249 | + (void) _text; |
| 250 | + return crispy::Size {}; // TODO |
| 251 | + } |
| 252 | + |
| 253 | + terminal::ImageAlignment parseImageAlignment(string_view _text) |
| 254 | + { |
| 255 | + (void) _text; |
| 256 | + return terminal::ImageAlignment::TopStart; // TODO |
| 257 | + } |
| 258 | + |
| 259 | + terminal::ImageResize parseImageResize(string_view _text) |
| 260 | + { |
| 261 | + (void) _text; |
| 262 | + return terminal::ImageResize::NoResize; // TODO |
| 263 | + } |
| 264 | + |
| 265 | + // terminal::CellLocation parsePosition(string_view _text) |
| 266 | + // { |
| 267 | + // (void) _text; |
| 268 | + // return {}; // TODO |
| 269 | + // } |
| 270 | + |
| 271 | + // TODO: chunkedFileReader(path) to return iterator over spans of data chunks. |
| 272 | + std::vector<uint8_t> readFile(FileSystem::path const& _path) |
| 273 | + { |
| 274 | + auto ifs = std::ifstream(_path.string()); |
| 275 | + if (!ifs.good()) |
| 276 | + return {}; |
| 277 | + |
| 278 | + auto const size = FileSystem::file_size(_path); |
| 279 | + auto text = std::vector<uint8_t>(); |
| 280 | + text.resize(size); |
| 281 | + ifs.read((char*) &text[0], static_cast<std::streamsize>(size)); |
| 282 | + return text; |
| 283 | + } |
| 284 | + |
| 285 | + void displayImage(terminal::ImageResize _resizePolicy, |
| 286 | + terminal::ImageAlignment _alignmentPolicy, |
| 287 | + crispy::Size _screenSize, |
| 288 | + string_view _fileName) |
| 289 | + { |
| 290 | + auto constexpr ST = "\033\\"sv; |
| 291 | + |
| 292 | + cout << fmt::format("{}f={},c={},l={},a={},z={};", |
| 293 | + "\033Ps"sv, // GIONESHOT |
| 294 | + '0', // image format: 0 = auto detect |
| 295 | + _screenSize.width, |
| 296 | + _screenSize.height, |
| 297 | + int(_alignmentPolicy), |
| 298 | + int(_resizePolicy)); |
| 299 | + |
| 300 | + #if 1 |
| 301 | + auto const data = readFile(FileSystem::path(string(_fileName))); // TODO: incremental buffered read |
| 302 | + auto encoderState = crispy::base64::EncoderState {}; |
| 303 | + |
| 304 | + std::vector<char> buf; |
| 305 | + auto const writer = [&](char a, char b, char c, char d) { |
| 306 | + buf.push_back(a); |
| 307 | + buf.push_back(b); |
| 308 | + buf.push_back(c); |
| 309 | + buf.push_back(d); |
| 310 | + }; |
| 311 | + auto const flush = [&]() { |
| 312 | + cout.write(buf.data(), static_cast<std::streamsize>(buf.size())); |
| 313 | + buf.clear(); |
| 314 | + }; |
| 315 | + |
| 316 | + for (uint8_t const byte: data) |
| 317 | + { |
| 318 | + crispy::base64::encode(byte, encoderState, writer); |
| 319 | + if (buf.size() >= 4096) |
| 320 | + flush(); |
| 321 | + } |
| 322 | + flush(); |
| 323 | + #endif |
| 324 | + |
| 325 | + cout << ST; |
| 326 | + } |
| 327 | +} // namespace |
| 328 | + |
| 329 | +int ContourApp::imageAction() |
| 330 | +{ |
| 331 | + auto const resizePolicy = parseImageResize(parameters().get<string>("contour.image.resize")); |
| 332 | + auto const alignmentPolicy = parseImageAlignment(parameters().get<string>("contour.image.align")); |
| 333 | + auto const size = parseSize(parameters().get<string>("contour.image.size")); |
| 334 | + auto const fileName = parameters().verbatim.front(); |
| 335 | + // TODO: how do we wanna handle more than one verbatim arg (image)? |
| 336 | + // => report error and EXIT_FAILURE as only one verbatim arg is allowed. |
| 337 | + // FIXME: What if parameter `size` is given as `_size` instead, it should cause an |
| 338 | + // invalid-argument error above already! |
| 339 | + displayImage(resizePolicy, alignmentPolicy, size, fileName); |
| 340 | + return EXIT_SUCCESS; |
| 341 | +} |
| 342 | +#endif |
| 343 | + |
242 | 344 | int ContourApp::parserTableAction()
|
243 | 345 | {
|
244 | 346 | terminal::parser::dot(std::cout, terminal::parser::ParserTable::get());
|
@@ -318,6 +420,35 @@ crispy::cli::Command ContourApp::parameterDefinition() const
|
318 | 420 | "FILE",
|
319 | 421 | CLI::Presence::Required },
|
320 | 422 | } } } },
|
| 423 | +#if defined(GOOD_IMAGE_PROTOCOL) |
| 424 | + CLI::Command { |
| 425 | + "image", |
| 426 | + "Sends an image to the terminal emulator for display.", |
| 427 | + CLI::OptionList { |
| 428 | + CLI::Option { "resize", |
| 429 | + CLI::Value { "fit"s }, |
| 430 | + "Sets the image resize policy.\n" |
| 431 | + "Policies available are:\n" |
| 432 | + " - no (no resize),\n" |
| 433 | + " - fit (resize to fit),\n" |
| 434 | + " - fill (resize to fill),\n" |
| 435 | + " - stretch (stretch to fill)." }, |
| 436 | + CLI::Option { "align", |
| 437 | + CLI::Value { "center"s }, |
| 438 | + "Sets the image alignment policy.\n" |
| 439 | + "Possible policies are: TopLeft, TopCenter, TopRight, MiddleLeft, " |
| 440 | + "MiddleCenter, MiddleRight, BottomLeft, BottomCenter, BottomRight." }, |
| 441 | + CLI::Option { "size", |
| 442 | + CLI::Value { ""s }, |
| 443 | + "Sets the amount of columns and rows to place the image onto. " |
| 444 | + "The top-left of the this area is the current cursor position, " |
| 445 | + "and it will be scrolled automatically if not enough rows are present." } }, |
| 446 | + CLI::CommandList {}, |
| 447 | + CLI::CommandSelect::Explicit, |
| 448 | + CLI::Verbatim { |
| 449 | + "IMAGE_FILE", |
| 450 | + "Path to image to be displayed. Image formats supported are at least PNG, JPG." } }, |
| 451 | +#endif |
321 | 452 | CLI::Command {
|
322 | 453 | "capture",
|
323 | 454 | "Captures the screen buffer of the currently running terminal.",
|
|
0 commit comments