Skip to content
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

Closed
wants to merge 7 commits into from
Closed

[WIP] add libvterm support #1130

wants to merge 7 commits into from

Conversation

brotzeit
Copy link
Member

@brotzeit brotzeit commented Dec 8, 2018

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:

  • use pseudovector instead of Lisp_Misc_Save_Value
  • use libvterm functions where possible
  • update make stuff

@@ -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])
Copy link
Collaborator

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.]

Copy link
Member Author

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)
Copy link
Collaborator

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?

Copy link
Member Author

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.

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,
Copy link
Collaborator

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...

let line_start = row_to_linenr(term, (*term).invalid_start);

call!(
LispObject::from(intern("goto-line")),
Copy link
Collaborator

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?

Copy link
Member Author

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.

Copy link
Collaborator

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.


let cursor_lnum = row_to_linenr(term, pos.row);
call!(
LispObject::from(intern("goto-line")),
Copy link
Collaborator

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.


let buf_index = buffer_lnum - height + 1;
call!(
LispObject::from(intern("goto-line")),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

}

#[lisp_fn]
pub fn vterm_write_input(input: LispObject) -> LispObject {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn vterm_write_input(input: LispObject) -> LispObject {
pub fn vterm_write_input(input: LispStringRef) -> LispObject {

vterm_screen_flush_damage((*term).vts);
}

LispObject::from(0)
Copy link
Collaborator

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,
Copy link

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?

Copy link
Member Author

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 () {
Copy link

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.

Copy link
Member Author

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>")) {
Copy link

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.

Copy link
Member Author

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]) {
Copy link

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.

Copy link
Member Author

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) {
Copy link

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.

@brotzeit
Copy link
Member Author

brotzeit commented Dec 9, 2018

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 {
Copy link
Collaborator

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.

@shaleh
Copy link
Collaborator

shaleh commented Dec 9, 2018

Look here @brotzeit https://github.com/Wilfred/remacs/blob/9517583be200869e076dcf4682eea4943d9a8b76/src/alloc.c#L3246 for following how the vectorlike allocations work.

Are you using malloc directly or are you using lisp_malloc?

@brotzeit
Copy link
Member Author

brotzeit commented Dec 9, 2018

Are you using malloc directly or are you using lisp_malloc?

I thought the macro is doing the allocation for pseudovectors.

@shaleh
Copy link
Collaborator

shaleh commented Dec 10, 2018

I meant for the allocation of next.

@brotzeit
Copy link
Member Author

brotzeit commented Dec 12, 2018

@shaleh I removed next for now, but it still doesn't work.

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 ALLOCATE_ZEROED_PSEUDOVECTOR with the second argument where it has to start allocating different types.

@brotzeit
Copy link
Member Author

@db48x @Wilfred any idea ?

@brotzeit
Copy link
Member Author

It seems bindgen has problems handling the libvterm enum VTermProp.

error[E0573]: expected type, found module `VTermProp`
   --> src/vterm.rs:537:11
    |
537 |     prop: VTermProp,
    |           ^^^^^^^^^ did you mean `VTermPos`?

I've never seen this before. Any idea ?

@brotzeit
Copy link
Member Author

brotzeit commented Jan 5, 2019

#1212

@brotzeit brotzeit closed this Jan 5, 2019
@brotzeit brotzeit mentioned this pull request Jan 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants