@@ -4292,6 +4292,73 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
42924292 ch_log (channel , "Calling function %s failed" , func );
42934293}
42944294
4295+ /*
4296+ * URL decoding (also know as Percent-encoding).
4297+ *
4298+ * Note this function currently is only used for decoding shell's
4299+ * OSC 7 escape sequence which we can assume all bytes are valid
4300+ * UTF-8 bytes. Thus we don't need to deal with invalid UTF-8
4301+ * encoding bytes like 0xfe, 0xff.
4302+ */
4303+ static size_t
4304+ url_decode (const char * src , const size_t len , char_u * dst )
4305+ {
4306+ size_t i = 0 , j = 0 ;
4307+
4308+ while (i < len )
4309+ {
4310+ if (src [i ] == '%' && i + 2 < len )
4311+ {
4312+ dst [j ] = hexhex2nr ((char_u * )& src [i + 1 ]);
4313+ j ++ ;
4314+ i += 3 ;
4315+ }
4316+ else
4317+ {
4318+ dst [j ] = src [i ];
4319+ i ++ ;
4320+ j ++ ;
4321+ }
4322+ }
4323+ dst [j ] = '\0' ;
4324+ return j ;
4325+ }
4326+
4327+ /*
4328+ * Sync terminal buffer's cwd with shell's pwd with the help of OSC 7.
4329+ *
4330+ * The OSC 7 sequence has the format of
4331+ * "\033]7;file://HOSTNAME/CURRENT/DIR\033\\"
4332+ * and what VTerm provides via VTermStringFragment is
4333+ * "file://HOSTNAME/CURRENT/DIR"
4334+ */
4335+ static void
4336+ sync_shell_dir (VTermStringFragment * frag )
4337+ {
4338+ int offset = 7 ; // len of "file://" is 7
4339+ char * pos = (char * )frag -> str + offset ;
4340+ char_u * new_dir ;
4341+
4342+ // remove HOSTNAME to get PWD
4343+ while (* pos != '/' && offset < frag -> len )
4344+ {
4345+ offset += 1 ;
4346+ pos += 1 ;
4347+ }
4348+
4349+ if (offset >= frag -> len )
4350+ {
4351+ semsg (_ (e_failed_to_extract_pwd_from_str_check_your_shell_config ),
4352+ frag -> str );
4353+ return ;
4354+ }
4355+
4356+ new_dir = alloc (frag -> len - offset + 1 );
4357+ url_decode (pos , frag -> len - offset , new_dir );
4358+ changedir_func (new_dir , TRUE, CDSCOPE_WINDOW );
4359+ vim_free (new_dir );
4360+ }
4361+
42954362/*
42964363 * Called by libvterm when it cannot recognize an OSC sequence.
42974364 * We recognize a terminal API command.
@@ -4306,7 +4373,13 @@ parse_osc(int command, VTermStringFragment frag, void *user)
43064373 : term -> tl_job -> jv_channel ;
43074374 garray_T * gap = & term -> tl_osc_buf ;
43084375
4309- // We recognize only OSC 5 1 ; {command}
4376+ // We recognize only OSC 5 1 ; {command} and OSC 7 ; {command}
4377+ if (p_asd && command == 7 )
4378+ {
4379+ sync_shell_dir (& frag );
4380+ return 1 ;
4381+ }
4382+
43104383 if (command != 51 )
43114384 return 0 ;
43124385
0 commit comments