From 479c067a4096f440398f531c11e4eae802ffe7c9 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Tue, 29 Apr 2014 21:37:11 +0100 Subject: [PATCH] Add support for running Kakoune with redirected stdin Will read to a *stdin* fifo buffer --- src/buffer_utils.cc | 35 +++++++++++++++++++++++++++++++++++ src/buffer_utils.hh | 2 ++ src/commands.cc | 35 ++++------------------------------- src/main.cc | 17 +++++++++++++++++ 4 files changed, 58 insertions(+), 31 deletions(-) diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc index af61cb19..7e8f3da4 100644 --- a/src/buffer_utils.cc +++ b/src/buffer_utils.cc @@ -1,5 +1,7 @@ #include "buffer_utils.hh" +#include "event_manager.hh" + namespace Kakoune { @@ -20,4 +22,37 @@ CharCount get_column(const Buffer& buffer, return col; } +Buffer* create_fifo_buffer(String name, int fd) +{ + Buffer* buffer = new Buffer(std::move(name), Buffer::Flags::Fifo | Buffer::Flags::NoUndo); + + auto watcher = new FDWatcher(fd, [buffer](FDWatcher& watcher) { + constexpr size_t buffer_size = 1024 * 16; + char data[buffer_size]; + ssize_t count = read(watcher.fd(), data, buffer_size); + buffer->insert(buffer->end()-1, count > 0 ? String(data, data+count) + : "*** kak: fifo closed ***\n"); + if (count <= 0) + { + kak_assert(buffer->flags() & Buffer::Flags::Fifo); + buffer->flags() &= ~Buffer::Flags::Fifo; + buffer->flags() &= ~Buffer::Flags::NoUndo; + close(watcher.fd()); + delete &watcher; + } + }); + + buffer->hooks().add_hook("BufClose", "", + [buffer, watcher](const String&, const Context&) { + // Check if fifo is still alive, else watcher is already dead + if (buffer->flags() & Buffer::Flags::Fifo) + { + close(watcher->fd()); + delete watcher; + } + }); + + return buffer; +} + } diff --git a/src/buffer_utils.hh b/src/buffer_utils.hh index 16e2c764..bd08d9b3 100644 --- a/src/buffer_utils.hh +++ b/src/buffer_utils.hh @@ -41,6 +41,8 @@ inline void avoid_eol(const Buffer& buffer, Selection& sel) CharCount get_column(const Buffer& buffer, CharCount tabstop, BufferCoord coord); +Buffer* create_fifo_buffer(String name, int fd); + } #endif // buffer_utils_hh_INCLUDED diff --git a/src/commands.cc b/src/commands.cc index ae0115a7..d06f75b8 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -2,6 +2,7 @@ #include "buffer.hh" #include "buffer_manager.hh" +#include "buffer_utils.hh" #include "client.hh" #include "client_manager.hh" #include "color_registry.hh" @@ -45,7 +46,7 @@ Buffer* open_or_create(const String& filename, Context& context) return buffer; } -Buffer* open_fifo(const String& name , const String& filename, Context& context) +Buffer* open_fifo(const String& name , const String& filename) { int fd = open(parse_filename(filename).c_str(), O_RDONLY); fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -54,35 +55,7 @@ Buffer* open_fifo(const String& name , const String& filename, Context& context) BufferManager::instance().delete_buffer_if_exists(name); - Buffer* buffer = new Buffer(name, Buffer::Flags::Fifo | Buffer::Flags::NoUndo); - - auto watcher = new FDWatcher(fd, [buffer](FDWatcher& watcher) { - constexpr size_t buffer_size = 1024 * 16; - char data[buffer_size]; - ssize_t count = read(watcher.fd(), data, buffer_size); - buffer->insert(buffer->end()-1, count > 0 ? String(data, data+count) - : "*** kak: fifo closed ***\n"); - if (count <= 0) - { - kak_assert(buffer->flags() & Buffer::Flags::Fifo); - buffer->flags() &= ~Buffer::Flags::Fifo; - buffer->flags() &= ~Buffer::Flags::NoUndo; - close(watcher.fd()); - delete &watcher; - } - }); - - buffer->hooks().add_hook("BufClose", "", - [buffer, watcher](const String&, const Context&) { - // Check if fifo is still alive, else watcher is already dead - if (buffer->flags() & Buffer::Flags::Fifo) - { - close(watcher->fd()); - delete watcher; - } - }); - - return buffer; + return create_fifo_buffer(std::move(name), fd); } const PerArgumentCommandCompleter filename_completer({ @@ -138,7 +111,7 @@ void edit(const ParametersParser& parser, Context& context) buffer = new Buffer(name, Buffer::Flags::None); } else if (parser.has_option("fifo")) - buffer = open_fifo(name, parser.option_value("fifo"), context); + buffer = open_fifo(name, parser.option_value("fifo")); else buffer = open_or_create(name, context); } diff --git a/src/main.cc b/src/main.cc index d23f8091..b240842e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -30,6 +30,10 @@ #include #include +#include +#include +#include + using namespace Kakoune; void run_unit_tests(); @@ -192,6 +196,19 @@ void create_local_client(const String& init_command) } }; + if (not isatty(1)) + throw runtime_error("stdout is not a tty"); + + if (not isatty(0)) + { + // move stdin to another fd, and restore tty as stdin + int fd = dup(0); + int tty = open("/dev/tty", O_RDONLY); + dup2(tty, 0); + close(tty); + create_fifo_buffer("*stdin*", fd); + } + UserInterface* ui = new LocalNCursesUI{}; static Client* client = ClientManager::instance().create_client( std::unique_ptr{ui}, get_env_vars(), init_command);