mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-25 02:30:27 +01:00
feat(term): implement copy_all()
Implements the copy_all() method which copies all text in the screen including text in the scrollback buffer. Includes a fix to an upstream bug in libtsm that resulted in double the number of '\n' characters being copied for each row.
This commit is contained in:
parent
8255d8b3ce
commit
71df1e71bd
5 changed files with 56 additions and 14 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -6,7 +6,7 @@
|
||||||
url = https://github.com/libuv/libuv
|
url = https://github.com/libuv/libuv
|
||||||
[submodule "addons/godot_xterm/native/thirdparty/libtsm"]
|
[submodule "addons/godot_xterm/native/thirdparty/libtsm"]
|
||||||
path = addons/godot_xterm/native/thirdparty/libtsm
|
path = addons/godot_xterm/native/thirdparty/libtsm
|
||||||
url = https://github.com/Aetf/libtsm
|
url = https://github.com/lihop/libtsm
|
||||||
[submodule "addons/godot_xterm/native/thirdparty/node-pty"]
|
[submodule "addons/godot_xterm/native/thirdparty/node-pty"]
|
||||||
path = addons/godot_xterm/native/thirdparty/node-pty
|
path = addons/godot_xterm/native/thirdparty/node-pty
|
||||||
url = https://github.com/microsoft/node-pty
|
url = https://github.com/microsoft/node-pty
|
||||||
|
|
|
@ -68,7 +68,8 @@ void Terminal::_bind_methods()
|
||||||
ClassDB::bind_method(D_METHOD("set_blink_off_time", "time"), &Terminal::set_blink_off_time);
|
ClassDB::bind_method(D_METHOD("set_blink_off_time", "time"), &Terminal::set_blink_off_time);
|
||||||
ClassDB::add_property("Terminal", PropertyInfo(Variant::FLOAT, "blink_off_time"), "set_blink_off_time", "get_blink_off_time");
|
ClassDB::add_property("Terminal", PropertyInfo(Variant::FLOAT, "blink_off_time"), "set_blink_off_time", "get_blink_off_time");
|
||||||
|
|
||||||
// Selection copying.
|
// Copying.
|
||||||
|
ClassDB::bind_method(D_METHOD("copy_all"), &Terminal::copy_all);
|
||||||
ClassDB::bind_method(D_METHOD("copy_selection"), &Terminal::copy_selection);
|
ClassDB::bind_method(D_METHOD("copy_selection"), &Terminal::copy_selection);
|
||||||
ClassDB::bind_method(D_METHOD("set_copy_on_selection", "enabled"), &Terminal::set_copy_on_selection);
|
ClassDB::bind_method(D_METHOD("set_copy_on_selection", "enabled"), &Terminal::set_copy_on_selection);
|
||||||
ClassDB::bind_method(D_METHOD("get_copy_on_selection"), &Terminal::get_copy_on_selection);
|
ClassDB::bind_method(D_METHOD("get_copy_on_selection"), &Terminal::get_copy_on_selection);
|
||||||
|
@ -641,15 +642,23 @@ double Terminal::get_blink_off_time() const
|
||||||
return blink_off_time;
|
return blink_off_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Terminal::_copy_screen(ScreenCopyFunction func) {
|
||||||
|
char *out;
|
||||||
|
PackedByteArray data;
|
||||||
|
|
||||||
|
data.resize(func(screen, &out));
|
||||||
|
memcpy(data.ptrw(), out, data.size());
|
||||||
|
std::free(out);
|
||||||
|
|
||||||
|
return data.get_string_from_utf8();
|
||||||
|
}
|
||||||
|
|
||||||
|
String Terminal::copy_all() {
|
||||||
|
return _copy_screen(&tsm_screen_copy_all);
|
||||||
|
}
|
||||||
|
|
||||||
String Terminal::copy_selection() {
|
String Terminal::copy_selection() {
|
||||||
char *out;
|
return _copy_screen(&tsm_screen_selection_copy);
|
||||||
PackedByteArray data;
|
|
||||||
|
|
||||||
data.resize(tsm_screen_selection_copy(screen, &out));
|
|
||||||
memcpy(data.ptrw(), out, data.size());
|
|
||||||
std::free(out);
|
|
||||||
|
|
||||||
return data.get_string_from_utf8();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::set_copy_on_selection(const bool p_enabled) {
|
void Terminal::set_copy_on_selection(const bool p_enabled) {
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include<map>
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <godot_cpp/classes/control.hpp>
|
#include <godot_cpp/classes/control.hpp>
|
||||||
#include <godot_cpp/classes/image_texture.hpp>
|
#include <godot_cpp/classes/image_texture.hpp>
|
||||||
|
@ -71,6 +72,7 @@ namespace godot
|
||||||
void set_blink_off_time(const double p_blink_off_time);
|
void set_blink_off_time(const double p_blink_off_time);
|
||||||
double get_blink_off_time() const;
|
double get_blink_off_time() const;
|
||||||
|
|
||||||
|
String copy_all();
|
||||||
String copy_selection();
|
String copy_selection();
|
||||||
void set_copy_on_selection(const bool p_enable);
|
void set_copy_on_selection(const bool p_enable);
|
||||||
bool get_copy_on_selection() const;
|
bool get_copy_on_selection() const;
|
||||||
|
@ -170,6 +172,9 @@ namespace godot
|
||||||
Timer *selection_timer;
|
Timer *selection_timer;
|
||||||
void _handle_selection(Ref<InputEventMouse> event);
|
void _handle_selection(Ref<InputEventMouse> event);
|
||||||
void _on_selection_held();
|
void _on_selection_held();
|
||||||
|
|
||||||
|
typedef std::function<int(struct tsm_screen*, char**)> ScreenCopyFunction;
|
||||||
|
String _copy_screen(ScreenCopyFunction func);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
2
addons/godot_xterm/native/thirdparty/libtsm
vendored
2
addons/godot_xterm/native/thirdparty/libtsm
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 2131b47acdee1088a78ca922ca96361d6182a03f
|
Subproject commit fa5021916aa8f4e292ae6dbbf9fc874ae517c3a3
|
|
@ -48,8 +48,7 @@ class TestInterface:
|
||||||
func xtest_has_method_clear():
|
func xtest_has_method_clear():
|
||||||
assert_has_method_with_return_type("clear", TYPE_NIL)
|
assert_has_method_with_return_type("clear", TYPE_NIL)
|
||||||
|
|
||||||
# TODO: Implement copy_all() method.
|
func test_has_method_copy_all():
|
||||||
func xtest_has_method_copy_all():
|
|
||||||
assert_has_method_with_return_type("copy_all", TYPE_STRING)
|
assert_has_method_with_return_type("copy_all", TYPE_STRING)
|
||||||
|
|
||||||
func test_has_method_copy_selection():
|
func test_has_method_copy_selection():
|
||||||
|
@ -192,3 +191,32 @@ class TestWrite:
|
||||||
func test_data_sent_not_emitted_when_empty_string_written():
|
func test_data_sent_not_emitted_when_empty_string_written():
|
||||||
subject.write("")
|
subject.write("")
|
||||||
assert_signal_emit_count(subject, "data_sent", 0)
|
assert_signal_emit_count(subject, "data_sent", 0)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCopy:
|
||||||
|
extends TerminalTest
|
||||||
|
|
||||||
|
func fill_screen(char: String = "A") -> String:
|
||||||
|
var result = char.repeat(subject.get_cols() * subject.get_rows())
|
||||||
|
subject.write(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
func test_copy_all_copies_the_entire_screen():
|
||||||
|
var text = fill_screen()
|
||||||
|
# The text will be wrapped over multiple lines and copy_all() preserves
|
||||||
|
# these line wraps, therefore we need to strip them.
|
||||||
|
assert_eq(subject.copy_all().replace("\n", ""), text)
|
||||||
|
|
||||||
|
func test_copy_all_empty_screen():
|
||||||
|
assert_eq(subject.copy_all(), "\n".repeat(subject.get_rows()))
|
||||||
|
|
||||||
|
func test_copy_all_copies_the_scrollback_buffer():
|
||||||
|
var text = fill_screen()
|
||||||
|
text += fill_screen("B")
|
||||||
|
text += fill_screen("C")
|
||||||
|
assert_eq(subject.copy_all().replace("\n", ""), text)
|
||||||
|
|
||||||
|
func test_copy_all_copies_unicode_text():
|
||||||
|
var text = "アイウエオカキクケコサシスセソ"
|
||||||
|
subject.write(text)
|
||||||
|
assert_string_contains(subject.copy_all(), text)
|
||||||
|
|
Loading…
Reference in a new issue