comparison src/terminal.c @ 13535:e9ffb5b35266 v8.0.1641

patch 8.0.1641: job in terminal can't communicate with Vim commit https://github.com/vim/vim/commit/8fbaeb195d9298c3a2a80300b5f96f1adddd2f59 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Mar 25 18:20:17 2018 +0200 patch 8.0.1641: job in terminal can't communicate with Vim Problem: Job in terminal can't communicate with Vim. Solution: Add the terminal API.
author Christian Brabandt <cb@256bit.org>
date Sun, 25 Mar 2018 18:30:07 +0200
parents d0d66898e98b
children 87a9c1be0ae3
comparison
equal deleted inserted replaced
13534:e74cff16bab6 13535:e9ffb5b35266
36 * that buffer, attributes come from the scrollback buffer tl_scrollback. 36 * that buffer, attributes come from the scrollback buffer tl_scrollback.
37 * When the buffer is changed it is turned into a normal buffer, the attributes 37 * When the buffer is changed it is turned into a normal buffer, the attributes
38 * in tl_scrollback are no longer used. 38 * in tl_scrollback are no longer used.
39 * 39 *
40 * TODO: 40 * TODO:
41 * - Win32: In the GUI use a terminal emulator for :!cmd. 41 * - For the "drop" command accept another argument for options.
42 * - Add a way to set the 16 ANSI colors, to be used for 'termguicolors' and in 42 * - Add a way to set the 16 ANSI colors, to be used for 'termguicolors' and in
43 * the GUI. 43 * the GUI.
44 * - Some way for the job running in the terminal to send a :drop command back 44 * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for
45 * to the Vim running the terminal. Should be usable by a simple shell or 45 * redirection.
46 * python script.
47 * - implement term_setsize() 46 * - implement term_setsize()
48 * - Copy text in the vterm to the Vim buffer once in a while, so that 47 * - Copy text in the vterm to the Vim buffer once in a while, so that
49 * completion works. 48 * completion works.
50 * - Adding WinBar to terminal window doesn't display, text isn't shifted down. 49 * - Adding WinBar to terminal window doesn't display, text isn't shifted down.
51 * a job that uses 16 colors while Vim is using > 256. 50 * a job that uses 16 colors while Vim is using > 256.
3144 # endif 3143 # endif
3145 } 3144 }
3146 } 3145 }
3147 3146
3148 /* 3147 /*
3148 * Handles a "drop" command from the job in the terminal.
3149 * "item" is the file name, "item->li_next" may have options.
3150 */
3151 static void
3152 handle_drop_command(listitem_T *item)
3153 {
3154 char_u *fname = get_tv_string(&item->li_tv);
3155 int bufnr;
3156 win_T *wp;
3157 tabpage_T *tp;
3158 exarg_T ea;
3159
3160 bufnr = buflist_add(fname, BLN_LISTED | BLN_NOOPT);
3161 FOR_ALL_TAB_WINDOWS(tp, wp)
3162 {
3163 if (wp->w_buffer->b_fnum == bufnr)
3164 {
3165 /* buffer is in a window already, go there */
3166 goto_tabpage_win(tp, wp);
3167 return;
3168 }
3169 }
3170
3171 /* open in new window, like ":sbuffer N" */
3172 vim_memset(&ea, 0, sizeof(ea));
3173 ea.cmd = (char_u *)"sbuffer";
3174 goto_buffer(&ea, DOBUF_FIRST, FORWARD, bufnr);
3175 }
3176
3177 /*
3178 * Handles a function call from the job running in a terminal.
3179 * "item" is the function name, "item->li_next" has the arguments.
3180 */
3181 static void
3182 handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
3183 {
3184 char_u *func;
3185 typval_T argvars[2];
3186 typval_T rettv;
3187 int doesrange;
3188
3189 if (item->li_next == NULL)
3190 {
3191 ch_log(channel, "Missing function arguments for call");
3192 return;
3193 }
3194 func = get_tv_string(&item->li_tv);
3195
3196 if (!ASCII_ISUPPER(*func))
3197 {
3198 ch_log(channel, "Invalid function name: %s", func);
3199 return;
3200 }
3201
3202 argvars[0].v_type = VAR_NUMBER;
3203 argvars[0].vval.v_number = term->tl_buffer->b_fnum;
3204 argvars[1] = item->li_next->li_tv;
3205 if (call_func(func, STRLEN(func), &rettv,
3206 2, argvars, /* argv_func */ NULL,
3207 /* firstline */ 1, /* lastline */ 1,
3208 &doesrange, /* evaluate */ TRUE,
3209 /* partial */ NULL, /* selfdict */ NULL) == OK)
3210 {
3211 clear_tv(&rettv);
3212 ch_log(channel, "Function %s called", func);
3213 }
3214 else
3215 ch_log(channel, "Calling function %s failed", func);
3216 }
3217
3218 /*
3219 * Called by libvterm when it cannot recognize an OSC sequence.
3220 * We recognize a terminal API command.
3221 */
3222 static int
3223 parse_osc(const char *command, size_t cmdlen, void *user)
3224 {
3225 term_T *term = (term_T *)user;
3226 js_read_T reader;
3227 typval_T tv;
3228 channel_T *channel = term->tl_job == NULL ? NULL
3229 : term->tl_job->jv_channel;
3230
3231 /* We recognize only OSC 5 1 ; {command} */
3232 if (cmdlen < 3 || STRNCMP(command, "51;", 3) != 0)
3233 return 0; /* not handled */
3234
3235 reader.js_buf = vim_strnsave((char_u *)command + 3, cmdlen - 3);
3236 if (reader.js_buf == NULL)
3237 return 1;
3238 reader.js_fill = NULL;
3239 reader.js_used = 0;
3240 if (json_decode(&reader, &tv, 0) == OK
3241 && tv.v_type == VAR_LIST
3242 && tv.vval.v_list != NULL)
3243 {
3244 listitem_T *item = tv.vval.v_list->lv_first;
3245
3246 if (item == NULL)
3247 ch_log(channel, "Missing command");
3248 else
3249 {
3250 char_u *cmd = get_tv_string(&item->li_tv);
3251
3252 item = item->li_next;
3253 if (item == NULL)
3254 ch_log(channel, "Missing argument for %s", cmd);
3255 else if (STRCMP(cmd, "drop") == 0)
3256 handle_drop_command(item);
3257 else if (STRCMP(cmd, "call") == 0)
3258 handle_call_command(term, channel, item);
3259 else
3260 ch_log(channel, "Invalid command received: %s", cmd);
3261 }
3262 }
3263 else
3264 ch_log(channel, "Invalid JSON received");
3265
3266 vim_free(reader.js_buf);
3267 clear_tv(&tv);
3268 return 1;
3269 }
3270
3271 static VTermParserCallbacks parser_fallbacks = {
3272 NULL, /* text */
3273 NULL, /* control */
3274 NULL, /* escape */
3275 NULL, /* csi */
3276 parse_osc, /* osc */
3277 NULL, /* dcs */
3278 NULL /* resize */
3279 };
3280
3281 /*
3149 * Create a new vterm and initialize it. 3282 * Create a new vterm and initialize it.
3150 */ 3283 */
3151 static void 3284 static void
3152 create_vterm(term_T *term, int rows, int cols) 3285 create_vterm(term_T *term, int rows, int cols)
3153 { 3286 {
3154 VTerm *vterm; 3287 VTerm *vterm;
3155 VTermScreen *screen; 3288 VTermScreen *screen;
3289 VTermState *state;
3156 VTermValue value; 3290 VTermValue value;
3157 3291
3158 vterm = vterm_new(rows, cols); 3292 vterm = vterm_new(rows, cols);
3159 term->tl_vterm = vterm; 3293 term->tl_vterm = vterm;
3160 screen = vterm_obtain_screen(vterm); 3294 screen = vterm_obtain_screen(vterm);
3184 else 3318 else
3185 value.boolean = 1; 3319 value.boolean = 1;
3186 #else 3320 #else
3187 value.boolean = 0; 3321 value.boolean = 0;
3188 #endif 3322 #endif
3189 vterm_state_set_termprop(vterm_obtain_state(vterm), 3323 state = vterm_obtain_state(vterm);
3190 VTERM_PROP_CURSORBLINK, &value); 3324 vterm_state_set_termprop(state, VTERM_PROP_CURSORBLINK, &value);
3325 vterm_state_set_unrecognised_fallbacks(state, &parser_fallbacks, term);
3191 } 3326 }
3192 3327
3193 /* 3328 /*
3194 * Return the text to show for the buffer name and status. 3329 * Return the text to show for the buffer name and status.
3195 */ 3330 */