New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] add libvterm support #1130
Conversation
@@ -3743,6 +3743,17 @@ fi | |||
AC_SUBST(LIBXML2_LIBS) | |||
AC_SUBST(LIBXML2_CFLAGS) | |||
|
|||
HAVE_LIBVTERM=no | |||
AC_DEFINE(HAVE_LIBVTERM, 1, [do I need this]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you need this... it should says [Define if libvterm is available.]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will update this together with the make stuff.
@@ -0,0 +1,254 @@ | |||
(require 'subr-x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this file comes from the emacs-vterm
project? Should it have copyright info?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's wait how much code still comes from the module when we merge this.
rust_src/src/vterm.rs
Outdated
remacs_sys::{ | ||
allocate_vterm, color_to_rgb_string, get_col_offset, global_term, refresh_lines, | ||
rgb_string_to_color, row_to_linenr, term_process_key, vterm_module_copy_string_contents, | ||
vterm_output_read, vterm_sb_buffer_size, vterm_screen_callbacks, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also vterm items in here...
rust_src/src/vterm.rs
Outdated
let line_start = row_to_linenr(term, (*term).invalid_start); | ||
|
||
call!( | ||
LispObject::from(intern("goto-line")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
goto-line
is interactive and so calling it programmatically is usually frowned on. Do you need all of the extra behavior of goto-line
or is forward-line
sufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked it and it seems goto-line has some extra logic that is needed in one function call. I will try to find a solution without calling lisp functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling lisp is ok. Calling interactive
lisp is frowned on.
rust_src/src/vterm.rs
Outdated
|
||
let cursor_lnum = row_to_linenr(term, pos.row); | ||
call!( | ||
LispObject::from(intern("goto-line")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about goto-line
here.
rust_src/src/vterm.rs
Outdated
|
||
let buf_index = buffer_lnum - height + 1; | ||
call!( | ||
LispObject::from(intern("goto-line")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
rust_src/src/vterm.rs
Outdated
} | ||
|
||
#[lisp_fn] | ||
pub fn vterm_write_input(input: LispObject) -> LispObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn vterm_write_input(input: LispObject) -> LispObject { | |
pub fn vterm_write_input(input: LispStringRef) -> LispObject { |
rust_src/src/vterm.rs
Outdated
vterm_screen_flush_damage((*term).vts); | ||
} | ||
|
||
LispObject::from(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just return int or EmacsInt?
src/vterm.c
Outdated
} | ||
|
||
VTermScreenCallbacks vterm_screen_callbacks = { | ||
.damage = vterm_damage, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious. Is this attempting to make a set of callbacks that reuse the original libvterm
functions in most of the slots, but just adds some scrollback handling? This feels a slightly awkward way to go about it - perhaps we can find a better way around that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just copied the code from emacs-libvterm and modified it so it works in remacs and didn't really take a look at libvterm, so far.
perhaps we can find a better way around that
Sounds good =)
I don't know much, but libvterm seems to work really well. Thanks for your work!
src/vterm.c
Outdated
}; | ||
|
||
void | ||
vterm_sb_buffer_size () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest not making new non-static functions in the vterm_...
namespace; in case libvterm
itself starts adding more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I wanted to avoid confusion regarding term and vterm, but I will change it to something different.
src/vterm.c
Outdated
vterm_keyboard_key(term->vt, VTERM_KEY_END, modifier); | ||
} else if (is_key(key, len, "<prior>")) { | ||
vterm_keyboard_key(term->vt, VTERM_KEY_PAGEUP, modifier); | ||
} else if (is_key(key, len, "<f0>")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could maybe these be done parametrically by looking for prefix <f
and suffix >
then parsing the middle as being a decimal integer? That would extend beyond 12 then if required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.
} | ||
|
||
static size_t | ||
codepoint_to_utf8_c(const uint32_t codepoint, unsigned char buffer[4]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (and the subsequent utf8_to_codepoint
) are very similar to functions that already exist in libvterm
. It might be easier just to expose those publicly then you can use them directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know. I will make a TODO list.
return offset; | ||
} | ||
|
||
static bool compare_cells(VTermScreenCell *a, VTermScreenCell *b) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This too is almost identical to an internal libvterm
function - might be best to expose and use that.
I tried to allocate the struct as a pseudovector similiar to terminal. Term *
allocate_vterm (void) {
global_term = ALLOCATE_ZEROED_PSEUDOVECTOR
(struct Term, next_vterm, PVEC_VTERM);
} I added the field struct Term *next_vterm; to the term struct. It compiles and runs, but after a few insertions remacs segfaults. Any idea ? |
src/lisp.h
Outdated
bool visible; | ||
} VtermCursor; | ||
|
||
typedef struct Term { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you should name this vterminal
or terminal_vterm
. Plain 'Term' can be confusing as long as the other terminal options are present.
Look here @brotzeit https://github.com/Wilfred/remacs/blob/9517583be200869e076dcf4682eea4943d9a8b76/src/alloc.c#L3246 for following how the vectorlike allocations work. Are you using |
I thought the macro is doing the allocation for pseudovectors. |
I meant for the allocation of |
@shaleh I removed struct Term *
allocate_vterm (void) {
return ALLOCATE_ZEROED_PSEUDOVECTOR
(struct Term, vt, PVEC_VTERM);
}
struct Term {
union vectorlike_header header;
Lisp_Object dummy;
VTerm *vt;
VTermScreen *vts;
// buffer used to:
// - convert VTermScreen cell arrays into utf8 strings
// - receive data from libvterm as a result of key presses.
VtermScrollbackLine **sb_buffer; // Scrollback buffer storage for libvterm
VtermCursor cursor;
bool is_invalidated;
size_t sb_current; // number of rows pushed to sb_buffer
size_t sb_size; // sb_buffer size
// "virtual index" that points to the first sb_buffer row that we need to
// push to the terminal buffer when refreshing the scrollback. When negative,
// it actually points to entries that are no longer in sb_buffer (because the
// window height has increased) and must be deleted from the terminal buffer
int sb_pending;
int invalid_start, invalid_end; // invalid rows in libvterm screen
}; I've read the docs a little more and when I understand correctly non LispObjects have to be after the last LispObject and you tell |
ac02ba4
to
d27082c
Compare
f4c90a6
to
72bbb6e
Compare
It seems bindgen has problems handling the libvterm enum
I've never seen this before. Any idea ? |
Thanks to emacs-libvterm vterm seems to work in remacs.
I just pulled in the code from the module and I will now start the cleanup.
Any kind of help is appreciated, but the PR isn't ready for a review. If you want to improve something just push to this branch.
TODO: