Mercurial > vim
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 */ |