summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-08-15 13:21:54 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-08-15 13:21:54 +0100
commit8d4531d419a2854970d67658fadfa9302308fb6c (patch)
treeca1a850a3b4e5d4e5d2a4b5330babf690987be56 /src
parenteff32aa1a17e92b09d3a44c06c71230785e94f55 (diff)
Add support for reading from stdin/writing to stdout in filter mode
Note that kakoune still needs to read the whole buffer first, only once stdin is closed can it execute the keys.
Diffstat (limited to 'src')
-rw-r--r--src/buffer_utils.cc55
-rw-r--r--src/buffer_utils.hh4
-rw-r--r--src/file.cc133
-rw-r--r--src/file.hh5
-rw-r--r--src/main.cc13
5 files changed, 124 insertions, 86 deletions
diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc
index 7e9b7316..020f7b83 100644
--- a/src/buffer_utils.cc
+++ b/src/buffer_utils.cc
@@ -1,5 +1,6 @@
#include "buffer_utils.hh"
+#include "buffer_manager.hh"
#include "event_manager.hh"
#include <sys/select.h>
@@ -24,6 +25,60 @@ CharCount get_column(const Buffer& buffer,
return col;
}
+Buffer* create_buffer_from_data(StringView data, StringView name,
+ Buffer::Flags flags, time_t fs_timestamp)
+{
+ bool bom = false, crlf = false;
+
+ const char* pos = data.begin();
+ if (data.length() >= 3 and
+ data[0] == '\xEF' and data[1] == '\xBB' and data[2] == '\xBF')
+ {
+ bom = true;
+ pos = data.begin() + 3;
+ }
+
+ std::vector<String> lines;
+ while (pos < data.end())
+ {
+ const char* line_end = pos;
+ while (line_end < data.end() and *line_end != '\r' and *line_end != '\n')
+ ++line_end;
+
+ // this should happen only when opening a file which has no
+ // end of line as last character.
+ if (line_end == data.end())
+ {
+ lines.emplace_back(pos, line_end);
+ lines.back() += '\n';
+ break;
+ }
+
+ lines.emplace_back(pos, line_end + 1);
+ lines.back().back() = '\n';
+
+ if (line_end+1 != data.end() and *line_end == '\r' and *(line_end+1) == '\n')
+ {
+ crlf = true;
+ pos = line_end + 2;
+ }
+ else
+ pos = line_end + 1;
+ }
+
+ Buffer* buffer = BufferManager::instance().get_buffer_ifp(name);
+ if (buffer)
+ buffer->reload(std::move(lines), fs_timestamp);
+ else
+ buffer = new Buffer{name, flags, std::move(lines), fs_timestamp};
+
+ OptionManager& options = buffer->options();
+ options.get_local_option("eolformat").set<String>(crlf ? "crlf" : "lf");
+ options.get_local_option("BOM").set<String>(bom ? "utf-8" : "no");
+
+ return buffer;
+}
+
Buffer* create_fifo_buffer(String name, int fd, bool scroll)
{
Buffer* buffer = new Buffer(std::move(name), Buffer::Flags::Fifo | Buffer::Flags::NoUndo);
diff --git a/src/buffer_utils.hh b/src/buffer_utils.hh
index c16b359f..0211a926 100644
--- a/src/buffer_utils.hh
+++ b/src/buffer_utils.hh
@@ -29,6 +29,10 @@ CharCount get_column(const Buffer& buffer,
Buffer* create_fifo_buffer(String name, int fd, bool scroll = false);
+Buffer* create_buffer_from_data(StringView data, StringView name,
+ Buffer::Flags flags,
+ time_t fs_timestamp = InvalidTime);
+
}
#endif // buffer_utils_hh_INCLUDED
diff --git a/src/file.cc b/src/file.cc
index 7dab64ec..92cf6bec 100644
--- a/src/file.cc
+++ b/src/file.cc
@@ -3,6 +3,7 @@
#include "assert.hh"
#include "buffer.hh"
#include "buffer_manager.hh"
+#include "buffer_utils.hh"
#include "completion.hh"
#include "debug.hh"
#include "unicode.hh"
@@ -95,18 +96,8 @@ String compact_path(StringView filename)
return filename.str();
}
-String read_file(StringView filename)
+String read_fd(int fd)
{
- int fd = open(parse_filename(filename).c_str(), O_RDONLY);
- if (fd == -1)
- {
- if (errno == ENOENT)
- throw file_not_found(filename);
-
- throw file_access_error(filename, strerror(errno));
- }
- auto close_fd = on_scope_end([fd]{ close(fd); });
-
String content;
char buf[256];
while (true)
@@ -120,6 +111,21 @@ String read_file(StringView filename)
return content;
}
+String read_file(StringView filename)
+{
+ int fd = open(parse_filename(filename).c_str(), O_RDONLY);
+ if (fd == -1)
+ {
+ if (errno == ENOENT)
+ throw file_not_found(filename);
+
+ throw file_access_error(filename, strerror(errno));
+ }
+ auto close_fd = on_scope_end([fd]{ close(fd); });
+
+ return read_fd(fd);
+}
+
Buffer* create_buffer_from_file(String filename)
{
filename = real_path(parse_filename(filename));
@@ -132,69 +138,20 @@ Buffer* create_buffer_from_file(String filename)
throw file_access_error(filename, strerror(errno));
}
+ auto close_fd = on_scope_end([&]{ close(fd); });
+
struct stat st;
fstat(fd, &st);
if (S_ISDIR(st.st_mode))
- {
- close(fd);
throw file_access_error(filename, "is a directory");
- }
- const char* data = (const char*)mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- auto cleanup = on_scope_end([&]{ munmap((void*)data, st.st_size); close(fd); });
-
- const char* pos = data;
- bool crlf = false;
- bool bom = false;
- if (st.st_size >= 3 and
- data[0] == '\xEF' and data[1] == '\xBB' and data[2] == '\xBF')
- {
- bom = true;
- pos = data + 3;
- }
-
- std::vector<String> lines;
- const char* end = data + st.st_size;
- while (pos < end)
- {
- const char* line_end = pos;
- while (line_end < end and *line_end != '\r' and *line_end != '\n')
- ++line_end;
-
- // this should happen only when opening a file which has no
- // end of line as last character.
- if (line_end == end)
- {
- lines.emplace_back(pos, line_end);
- lines.back() += '\n';
- break;
- }
-
- lines.emplace_back(pos, line_end + 1);
- lines.back().back() = '\n';
- if (line_end+1 != end and *line_end == '\r' and *(line_end+1) == '\n')
- {
- crlf = true;
- pos = line_end + 2;
- }
- else
- pos = line_end + 1;
- }
- Buffer* buffer = BufferManager::instance().get_buffer_ifp(filename);
- if (buffer)
- buffer->reload(std::move(lines), st.st_mtime);
- else
- buffer = new Buffer{filename, Buffer::Flags::File,
- std::move(lines), st.st_mtime};
-
- OptionManager& options = buffer->options();
- options.get_local_option("eolformat").set<String>(crlf ? "crlf" : "lf");
- options.get_local_option("BOM").set<String>(bom ? "utf-8" : "no");
+ const char* data = (const char*)mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ auto unmap = on_scope_end([&]{ munmap((void*)data, st.st_size); });
- return buffer;
+ return create_buffer_from_data({data, data + st.st_size}, filename, Buffer::Flags::File, st.st_mtime);
}
-static void write(int fd, StringView data, StringView filename)
+static void write(int fd, StringView data)
{
const char* ptr = data.data();
ssize_t count = (int)data.length();
@@ -206,14 +163,12 @@ static void write(int fd, StringView data, StringView filename)
count -= written;
if (written == -1)
- throw file_access_error(filename, strerror(errno));
+ throw file_access_error("fd: " + to_string(fd), strerror(errno));
}
}
-void write_buffer_to_file(Buffer& buffer, StringView filename)
+void write_buffer_to_fd(Buffer& buffer, int fd)
{
- buffer.run_hook_in_own_context("BufWritePre", buffer.name());
-
const String& eolformat = buffer.options()["eolformat"].get<String>();
StringView eoldata;
if (eolformat == "crlf")
@@ -221,25 +176,31 @@ void write_buffer_to_file(Buffer& buffer, StringView filename)
else
eoldata = "\n";
+ if (buffer.options()["BOM"].get<String>() == "utf-8")
+ ::write(fd, "\xEF\xBB\xBF", 3);
+
+ for (LineCount i = 0; i < buffer.line_count(); ++i)
{
- int fd = open(parse_filename(filename).c_str(),
- O_CREAT | O_WRONLY | O_TRUNC, 0644);
- if (fd == -1)
- throw file_access_error(filename, strerror(errno));
- auto close_fd = on_scope_end([fd]{ close(fd); });
+ // end of lines are written according to eolformat but always
+ // stored as \n
+ StringView linedata = buffer[i];
+ write(fd, linedata.substr(0, linedata.length()-1));
+ write(fd, eoldata);
+ }
+}
- if (buffer.options()["BOM"].get<String>() == "utf-8")
- ::write(fd, "\xEF\xBB\xBF", 3);
+void write_buffer_to_file(Buffer& buffer, StringView filename)
+{
+ buffer.run_hook_in_own_context("BufWritePre", buffer.name());
+
+ int fd = open(parse_filename(filename).c_str(),
+ O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd == -1)
+ throw file_access_error(filename, strerror(errno));
+ auto close_fd = on_scope_end([fd]{ close(fd); });
+
+ write_buffer_to_fd(buffer, fd);
- for (LineCount i = 0; i < buffer.line_count(); ++i)
- {
- // end of lines are written according to eolformat but always
- // stored as \n
- StringView linedata = buffer[i];
- write(fd, linedata.substr(0, linedata.length()-1), filename);
- write(fd, eoldata, filename);
- }
- }
if ((buffer.flags() & Buffer::Flags::File) and
real_path(filename) == real_path(buffer.name()))
buffer.notify_saved();
diff --git a/src/file.hh b/src/file.hh
index d26b160f..e1561ca9 100644
--- a/src/file.hh
+++ b/src/file.hh
@@ -28,9 +28,14 @@ String parse_filename(StringView filename);
String real_path(StringView filename);
String compact_path(StringView filename);
+String read_fd(int fd);
String read_file(StringView filename);
+
Buffer* create_buffer_from_file(String filename);
+
void write_buffer_to_file(Buffer& buffer, StringView filename);
+void write_buffer_to_fd(Buffer& buffer, int fd);
+
String find_file(StringView filename, memoryview<String> paths);
time_t get_fs_timestamp(StringView filename);
diff --git a/src/main.cc b/src/main.cc
index a917848b..3ef17912 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -411,6 +411,19 @@ int run_filter(StringView keystr, memoryview<StringView> files)
buffer_manager.delete_buffer(*buffer);
}
+ if (not isatty(0))
+ {
+ Buffer* buffer = create_buffer_from_data(read_fd(0), "*stdin*", Buffer::Flags::None);
+ InputHandler input_handler{{ *buffer, Selection{} }};
+
+ for (auto& key : keys)
+ input_handler.handle_key(key);
+
+ write_buffer_to_fd(*buffer, 1);
+
+ buffer_manager.delete_buffer(*buffer);
+ }
+
buffer_manager.clear_buffer_trash();
return 0;
}