3838 * in tl_scrollback are no longer used.
3939 *
4040 * TODO:
41- * - What to store in a session file? Shell at the prompt would be OK to
42- * restore, but others may not. Open the window and let the user start the
43- * command? Also see #2650.
44- * - Adding WinBar to terminal window doesn't display, text isn't shifted down.
41+ * - Add a flag to kill the job when Vim is exiting. Useful when it's showing
42+ * a logfile. Or send keys there to make it quit: "exit\r" for a shell.
4543 * - When using 'termguicolors' still use the 16 ANSI colors as-is. Helps for
44+ * - Adding WinBar to terminal window doesn't display, text isn't shifted down.
4645 * a job that uses 16 colors while Vim is using > 256.
4746 * - in GUI vertical split causes problems. Cursor is flickering. (Hirohito
4847 * Higashi, 2017 Sep 19)
@@ -135,6 +134,9 @@ struct terminal_S {
135134 void * tl_winpty_config ;
136135 void * tl_winpty ;
137136#endif
137+ #if defined(FEAT_SESSION )
138+ char_u * tl_command ;
139+ #endif
138140
139141 /* last known vterm size */
140142 int tl_rows ;
@@ -487,6 +489,52 @@ term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
487489 if (without_job )
488490 return curbuf ;
489491
492+ #if defined(FEAT_SESSION )
493+ /* Remember the command for the session file. */
494+ if (opt -> jo_term_norestore )
495+ {
496+ term -> tl_command = vim_strsave ((char_u * )"NONE" );
497+ }
498+ else if (argvar -> v_type == VAR_STRING )
499+ {
500+ char_u * cmd = argvar -> vval .v_string ;
501+
502+ if (cmd != NULL && STRCMP (cmd , p_sh ) != 0 )
503+ term -> tl_command = vim_strsave (cmd );
504+ }
505+ else if (argvar -> v_type == VAR_LIST
506+ && argvar -> vval .v_list != NULL
507+ && argvar -> vval .v_list -> lv_len > 0 )
508+ {
509+ garray_T ga ;
510+ listitem_T * item ;
511+
512+ ga_init2 (& ga , 1 , 100 );
513+ for (item = argvar -> vval .v_list -> lv_first ;
514+ item != NULL ; item = item -> li_next )
515+ {
516+ char_u * s = get_tv_string_chk (& item -> li_tv );
517+ char_u * p ;
518+
519+ if (s == NULL )
520+ break ;
521+ p = vim_strsave_fnameescape (s , FALSE);
522+ if (p == NULL )
523+ break ;
524+ ga_concat (& ga , p );
525+ vim_free (p );
526+ ga_append (& ga , ' ' );
527+ }
528+ if (item == NULL )
529+ {
530+ ga_append (& ga , NUL );
531+ term -> tl_command = ga .ga_data ;
532+ }
533+ else
534+ ga_clear (& ga );
535+ }
536+ #endif
537+
490538 /* System dependent: setup the vterm and maybe start the job in it. */
491539 if (argvar -> v_type == VAR_STRING
492540 && argvar -> vval .v_string != NULL
@@ -561,6 +609,8 @@ ex_terminal(exarg_T *eap)
561609 opt .jo_curwin = 1 ;
562610 else if ((int )(p - cmd ) == 6 && STRNICMP (cmd , "hidden" , 6 ) == 0 )
563611 opt .jo_hidden = 1 ;
612+ else if ((int )(p - cmd ) == 9 && STRNICMP (cmd , "norestore" , 9 ) == 0 )
613+ opt .jo_term_norestore = 1 ;
564614 else if ((int )(p - cmd ) == 4 && STRNICMP (cmd , "rows" , 4 ) == 0
565615 && ep != NULL && isdigit (ep [1 ]))
566616 {
@@ -620,6 +670,42 @@ ex_terminal(exarg_T *eap)
620670 vim_free (opt .jo_eof_chars );
621671}
622672
673+ #if defined(FEAT_SESSION ) || defined(PROTO )
674+ /*
675+ * Write a :terminal command to the session file to restore the terminal in
676+ * window "wp".
677+ * Return FAIL if writing fails.
678+ */
679+ int
680+ term_write_session (FILE * fd , win_T * wp )
681+ {
682+ term_T * term = wp -> w_buffer -> b_term ;
683+
684+ /* Create the terminal and run the command. This is not without
685+ * risk, but let's assume the user only creates a session when this
686+ * will be OK. */
687+ if (fprintf (fd , "terminal ++curwin ++cols=%d ++rows=%d " ,
688+ term -> tl_cols , term -> tl_rows ) < 0 )
689+ return FAIL ;
690+ if (term -> tl_command != NULL && fputs ((char * )term -> tl_command , fd ) < 0 )
691+ return FAIL ;
692+
693+ return put_eol (fd );
694+ }
695+
696+ /*
697+ * Return TRUE if "buf" has a terminal that should be restored.
698+ */
699+ int
700+ term_should_restore (buf_T * buf )
701+ {
702+ term_T * term = buf -> b_term ;
703+
704+ return term != NULL && (term -> tl_command == NULL
705+ || STRCMP (term -> tl_command , "NONE" ) != 0 );
706+ }
707+ #endif
708+
623709/*
624710 * Free the scrollback buffer for "term".
625711 */
@@ -669,6 +755,9 @@ free_terminal(buf_T *buf)
669755
670756 term_free_vterm (term );
671757 vim_free (term -> tl_title );
758+ #ifdef FEAT_SESSION
759+ vim_free (term -> tl_command );
760+ #endif
672761 vim_free (term -> tl_status_text );
673762 vim_free (term -> tl_opencmd );
674763 vim_free (term -> tl_eof_chars );
@@ -4047,6 +4136,29 @@ f_term_sendkeys(typval_T *argvars, typval_T *rettv)
40474136 }
40484137}
40494138
4139+ /*
4140+ * "term_setrestore(buf, command)" function
4141+ */
4142+ void
4143+ f_term_setrestore (typval_T * argvars UNUSED , typval_T * rettv UNUSED )
4144+ {
4145+ #if defined(FEAT_SESSION )
4146+ buf_T * buf = term_get_buf (argvars );
4147+ term_T * term ;
4148+ char_u * cmd ;
4149+
4150+ if (buf == NULL )
4151+ return ;
4152+ term = buf -> b_term ;
4153+ vim_free (term -> tl_command );
4154+ cmd = get_tv_string_chk (& argvars [1 ]);
4155+ if (cmd != NULL )
4156+ term -> tl_command = vim_strsave (cmd );
4157+ else
4158+ term -> tl_command = NULL ;
4159+ #endif
4160+ }
4161+
40504162/*
40514163 * "term_start(command, options)" function
40524164 */
@@ -4064,7 +4176,8 @@ f_term_start(typval_T *argvars, typval_T *rettv)
40644176 + JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO ,
40654177 JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD
40664178 + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
4067- + JO2_CWD + JO2_ENV + JO2_EOF_CHARS ) == FAIL )
4179+ + JO2_CWD + JO2_ENV + JO2_EOF_CHARS
4180+ + JO2_NORESTORE ) == FAIL )
40684181 return ;
40694182
40704183 if (opt .jo_vertical )
@@ -4566,6 +4679,7 @@ term_and_job_init(
45664679{
45674680 create_vterm (term , term -> tl_rows , term -> tl_cols );
45684681
4682+ /* This will change a string in "argvar". */
45694683 term -> tl_job = job_start (argvar , opt );
45704684 if (term -> tl_job != NULL )
45714685 ++ term -> tl_job -> jv_refcount ;
0 commit comments