comparison src/terminal.c @ 11670:3b2afa2b77b3 v8.0.0718

patch 8.0.0718: output of job in terminal is not displayed commit https://github.com/vim/vim/commit/cb8bbe9bf3214d07580d6b43d6539416884153bd Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jul 16 13:48:22 2017 +0200 patch 8.0.0718: output of job in terminal is not displayed Problem: Output of job in terminal is not displayed. Solution: Connect the job output to the terminal.
author Christian Brabandt <cb@256bit.org>
date Sun, 16 Jul 2017 14:00:03 +0200
parents 26265ac3b7ed
children 1ce1376fbbf8
comparison
equal deleted inserted replaced
11669:20bedd70c837 11670:3b2afa2b77b3
26 * TODO: 26 * TODO:
27 * - free b_term when closing terminal. 27 * - free b_term when closing terminal.
28 * - remove term from first_term list when closing terminal. 28 * - remove term from first_term list when closing terminal.
29 * - set buffer options to be scratch, hidden, nomodifiable, etc. 29 * - set buffer options to be scratch, hidden, nomodifiable, etc.
30 * - set buffer name to command, add (1) to avoid duplicates. 30 * - set buffer name to command, add (1) to avoid duplicates.
31 * - if buffer is wiped, cleanup terminal, may stop job.
32 * - if the job ends, write "-- JOB ENDED --" in the terminal
31 * - command line completion (command name) 33 * - command line completion (command name)
32 * - support fixed size when 'termsize' is "rowsXcols". 34 * - support fixed size when 'termsize' is "rowsXcols".
33 * - support minimal size when 'termsize' is "rows*cols". 35 * - support minimal size when 'termsize' is "rows*cols".
34 * - support minimal size when 'termsize' is empty. 36 * - support minimal size when 'termsize' is empty.
35 * - implement ":buf {term-buf-name}" 37 * - implement ":buf {term-buf-name}"
38 * - implement term_sendkeys() send keystrokes to a terminal 40 * - implement term_sendkeys() send keystrokes to a terminal
39 * - implement term_wait() wait for screen to be updated 41 * - implement term_wait() wait for screen to be updated
40 * - implement term_scrape() inspect terminal screen 42 * - implement term_scrape() inspect terminal screen
41 * - implement term_open() open terminal window 43 * - implement term_open() open terminal window
42 * - implement term_getjob() 44 * - implement term_getjob()
45 * - implement 'termkey'
43 */ 46 */
44 47
45 #include "vim.h" 48 #include "vim.h"
46 49
47 #ifdef FEAT_TERMINAL 50 #ifdef FEAT_TERMINAL
52 struct terminal_S { 55 struct terminal_S {
53 term_T *tl_next; 56 term_T *tl_next;
54 57
55 VTerm *tl_vterm; 58 VTerm *tl_vterm;
56 job_T *tl_job; 59 job_T *tl_job;
60 buf_T *tl_buffer;
57 61
58 /* Range of screen rows to update. Zero based. */ 62 /* Range of screen rows to update. Zero based. */
59 int tl_dirty_row_start; /* -1 if nothing dirty */ 63 int tl_dirty_row_start; /* -1 if nothing dirty */
60 int tl_dirty_row_end; /* row below last one to update */ 64 int tl_dirty_row_end; /* row below last one to update */
61 65
97 win_T *old_curwin = curwin; 101 win_T *old_curwin = curwin;
98 typval_T argvars[2]; 102 typval_T argvars[2];
99 term_T *term; 103 term_T *term;
100 VTerm *vterm; 104 VTerm *vterm;
101 VTermScreen *screen; 105 VTermScreen *screen;
106 jobopt_T opt;
102 107
103 if (check_restricted() || check_secure()) 108 if (check_restricted() || check_secure())
104 return; 109 return;
105 110
106 term = (term_T *)alloc_clear(sizeof(term_T)); 111 term = (term_T *)alloc_clear(sizeof(term_T));
118 { 123 {
119 /* split failed */ 124 /* split failed */
120 vim_free(term); 125 vim_free(term);
121 return; 126 return;
122 } 127 }
128 term->tl_buffer = curbuf;
123 129
124 curbuf->b_term = term; 130 curbuf->b_term = term;
125 term->tl_next = first_term; 131 term->tl_next = first_term;
126 first_term = term; 132 first_term = term;
127 133
143 149
144 vterm = vterm_new(rows, cols); 150 vterm = vterm_new(rows, cols);
145 term->tl_vterm = vterm; 151 term->tl_vterm = vterm;
146 screen = vterm_obtain_screen(vterm); 152 screen = vterm_obtain_screen(vterm);
147 vterm_screen_set_callbacks(screen, &screen_callbacks, term); 153 vterm_screen_set_callbacks(screen, &screen_callbacks, term);
154 /* TODO: depends on 'encoding'. */
155 vterm_set_utf8(vterm, 1);
156 /* Required to initialize most things. */
157 vterm_screen_reset(screen, 1 /* hard */);
158
159 /* By default NL means CR-NL. */
160 vterm_input_write(vterm, "\x1b[20h", 5);
148 161
149 argvars[0].v_type = VAR_STRING; 162 argvars[0].v_type = VAR_STRING;
150 argvars[0].vval.v_string = eap->arg; 163 argvars[0].vval.v_string = eap->arg;
151 argvars[1].v_type = VAR_UNKNOWN; 164
152 term->tl_job = job_start(argvars); 165 clear_job_options(&opt);
153 166 opt.jo_mode = MODE_RAW;
154 /* TODO: setup channels to/from job */ 167 opt.jo_out_mode = MODE_RAW;
168 opt.jo_err_mode = MODE_RAW;
169 opt.jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE;
170 opt.jo_io[PART_OUT] = JIO_BUFFER;
171 opt.jo_io[PART_ERR] = JIO_BUFFER;
172 opt.jo_set |= JO_OUT_IO + (JO_OUT_IO << (PART_ERR - PART_OUT));
173 opt.jo_io_buf[PART_OUT] = curbuf->b_fnum;
174 opt.jo_io_buf[PART_ERR] = curbuf->b_fnum;
175 opt.jo_set |= JO_OUT_BUF + (JO_OUT_BUF << (PART_ERR - PART_OUT));
176
177 term->tl_job = job_start(argvars, &opt);
178
179 /* TODO: setup channel to job */
155 /* Setup pty, see mch_call_shell(). */ 180 /* Setup pty, see mch_call_shell(). */
181 }
182
183 /*
184 * Invoked when "msg" output from a job was received. Write it to the terminal
185 * of "buffer".
186 */
187 void
188 write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
189 {
190 size_t len = STRLEN(msg);
191 VTerm *vterm = buffer->b_term->tl_vterm;
192
193 ch_logn(channel, "writing %d bytes to terminal", (int)len);
194 vterm_input_write(vterm, (char *)msg, len);
195 vterm_screen_flush_damage(vterm_obtain_screen(vterm));
196
197 /* TODO: only update once in a while. */
198 update_screen(0);
199 setcursor();
200 out_flush();
201 }
202
203 /*
204 * Called to update the window that contains the terminal.
205 */
206 void
207 term_update_window(win_T *wp)
208 {
209 int vterm_rows;
210 int vterm_cols;
211 VTerm *vterm = wp->w_buffer->b_term->tl_vterm;
212 VTermScreen *screen = vterm_obtain_screen(vterm);
213 VTermPos pos;
214
215 vterm_get_size(vterm, &vterm_rows, &vterm_cols);
216
217 /* TODO: Only redraw what changed. */
218 for (pos.row = 0; pos.row < wp->w_height; ++pos.row)
219 {
220 int off = screen_get_current_line_off();
221
222 if (pos.row < vterm_rows)
223 for (pos.col = 0; pos.col < wp->w_width && pos.col < vterm_cols;
224 ++pos.col)
225 {
226 VTermScreenCell cell;
227 int c;
228
229 vterm_screen_get_cell(screen, pos, &cell);
230 /* TODO: use cell.attrs and colors */
231 /* TODO: use cell.width */
232 /* TODO: multi-byte chars */
233 c = cell.chars[0];
234 ScreenLines[off] = c == NUL ? ' ' : c;
235 ScreenAttrs[off] = 0;
236 ++off;
237 }
238
239 screen_line(wp->w_winrow + pos.row, wp->w_wincol, pos.col, wp->w_width,
240 FALSE);
241 }
156 } 242 }
157 243
158 static int 244 static int
159 handle_damage(VTermRect rect, void *user) 245 handle_damage(VTermRect rect, void *user)
160 { 246 {
161 term_T *term = (term_T *)user; 247 term_T *term = (term_T *)user;
162 248
163 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row); 249 term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row);
164 term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row); 250 term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row);
251 redraw_buf_later(term->tl_buffer, NOT_VALID);
165 return 1; 252 return 1;
166 } 253 }
167 254
168 static int 255 static int
169 handle_moverect(VTermRect dest, VTermRect src, void *user) 256 handle_moverect(VTermRect dest, VTermRect src, void *user)
170 { 257 {
258 term_T *term = (term_T *)user;
259
171 /* TODO */ 260 /* TODO */
261 redraw_buf_later(term->tl_buffer, NOT_VALID);
172 return 1; 262 return 1;
173 } 263 }
174 264
175 static int 265 static int
176 handle_movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user) 266 handle_movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
177 { 267 {
178 /* TODO: handle moving the cursor. */ 268 term_T *term = (term_T *)user;
269 win_T *wp;
270 int is_current = FALSE;
271
272 FOR_ALL_WINDOWS(wp)
273 {
274 if (wp->w_buffer == term->tl_buffer)
275 {
276 /* TODO: limit to window size? */
277 wp->w_wrow = pos.row;
278 wp->w_wcol = pos.col;
279 if (wp == curwin)
280 is_current = TRUE;
281 }
282 }
283
284 if (is_current)
285 {
286 setcursor();
287 out_flush();
288 }
289
179 return 1; 290 return 1;
180 } 291 }
181 292
182 static int 293 static int
183 handle_resize(int rows, int cols, void *user) 294 handle_resize(int rows, int cols, void *user)
184 { 295 {
296 term_T *term = (term_T *)user;
297
185 /* TODO: handle terminal resize. */ 298 /* TODO: handle terminal resize. */
299 redraw_buf_later(term->tl_buffer, NOT_VALID);
186 return 1; 300 return 1;
187 } 301 }
188 302
189 /* TODO: Use win_del_lines() to make scroll up efficient. */ 303 /* TODO: Use win_del_lines() to make scroll up efficient. */
190 304
199 * - Write keys to vterm: vterm_keyboard_key() 313 * - Write keys to vterm: vterm_keyboard_key()
200 * - read the output (xterm escape sequences): vterm_output_read() 314 * - read the output (xterm escape sequences): vterm_output_read()
201 * - Write output to channel. 315 * - Write output to channel.
202 */ 316 */
203 317
204 /* TODO: function to read job output from the channel.
205 * write to vterm: vterm_input_write()
206 * This will invoke screen callbacks.
207 * call vterm_screen_flush_damage()
208 */
209
210 #endif /* FEAT_TERMINAL */ 318 #endif /* FEAT_TERMINAL */