Skip to content

Commit 12f6adf

Browse files
committed
Add OSC 7 support
Fixes #552.
1 parent decd9b7 commit 12f6adf

6 files changed

Lines changed: 74 additions & 6 deletions

File tree

src/terminal/terminaldisplay.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ std::string Display::new_frame( bool initialized, const Framebuffer& last, const
102102
}
103103
}
104104

105+
/* has cwd changed? OSC 7 current directory support */
106+
if ( f.is_current_directory_initialized()
107+
&& ( !initialized || f.get_current_directory() != frame.last_frame.get_current_directory() ) ) {
108+
frame.append( "\033]7;" );
109+
for ( const auto c : f.get_current_directory() ) {
110+
frame.append( c );
111+
}
112+
frame.append( '\007' );
113+
/* ST is more correct, but BEL more widely supported */
114+
}
115+
105116
/* has clipboard changed? */
106117
if ( f.get_clipboard() != frame.last_frame.get_clipboard() ) {
107118
frame.append( "\033]52;c;" );

src/terminal/terminalframebuffer.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ DrawState::DrawState( int s_width, int s_height )
7373
}
7474

7575
Framebuffer::Framebuffer( int s_width, int s_height )
76-
: rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), title_initialized( false ),
77-
ds( s_width, s_height )
76+
: rows(), icon_name(), window_title(), current_directory(), clipboard(), bell_count( 0 ),
77+
title_initialized( false ), cwd_initialized( false ), ds( s_width, s_height )
7878
{
7979
assert( s_height > 0 );
8080
assert( s_width > 0 );
@@ -85,8 +85,8 @@ Framebuffer::Framebuffer( int s_width, int s_height )
8585

8686
Framebuffer::Framebuffer( const Framebuffer& other )
8787
: rows( other.rows ), icon_name( other.icon_name ), window_title( other.window_title ),
88-
clipboard( other.clipboard ), bell_count( other.bell_count ), title_initialized( other.title_initialized ),
89-
ds( other.ds )
88+
current_directory( other.current_directory ), clipboard( other.clipboard ), bell_count( other.bell_count ),
89+
title_initialized( other.title_initialized ), cwd_initialized( other.cwd_initialized ), ds( other.ds )
9090
{}
9191

9292
Framebuffer& Framebuffer::operator=( const Framebuffer& other )
@@ -95,9 +95,11 @@ Framebuffer& Framebuffer::operator=( const Framebuffer& other )
9595
rows = other.rows;
9696
icon_name = other.icon_name;
9797
window_title = other.window_title;
98+
current_directory = other.current_directory;
9899
clipboard = other.clipboard;
99100
bell_count = other.bell_count;
100101
title_initialized = other.title_initialized;
102+
cwd_initialized = other.cwd_initialized;
101103
ds = other.ds;
102104
}
103105
return *this;
@@ -387,6 +389,7 @@ void Framebuffer::reset( void )
387389
ds = DrawState( width, height );
388390
rows = rows_type( height, newrow() );
389391
window_title.clear();
392+
current_directory.clear();
390393
clipboard.clear();
391394
/* do not reset bell_count */
392395
}

src/terminal/terminalframebuffer.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,11 @@ class Framebuffer
416416
rows_type rows;
417417
title_type icon_name;
418418
title_type window_title;
419+
title_type current_directory;
419420
title_type clipboard;
420421
unsigned int bell_count;
421422
bool title_initialized; /* true if the window title has been set via an OSC */
423+
bool cwd_initialized; /* true if the cwd has been set via an OSC */
422424

423425
row_pointer newrow( void )
424426
{
@@ -495,11 +497,15 @@ class Framebuffer
495497

496498
void set_title_initialized( void ) { title_initialized = true; }
497499
bool is_title_initialized( void ) const { return title_initialized; }
500+
void set_current_directory_initialized( void ) { cwd_initialized = true; }
501+
bool is_current_directory_initialized( void ) const { return cwd_initialized; }
498502
void set_icon_name( const title_type& s ) { icon_name = s; }
499503
void set_window_title( const title_type& s ) { window_title = s; }
504+
void set_current_directory( const title_type& s ) { current_directory = s; }
500505
void set_clipboard( const title_type& s ) { clipboard = s; }
501506
const title_type& get_icon_name( void ) const { return icon_name; }
502507
const title_type& get_window_title( void ) const { return window_title; }
508+
const title_type& get_current_directory( void ) const { return current_directory; }
503509
const title_type& get_clipboard( void ) const { return clipboard; }
504510

505511
void prefix_window_title( const title_type& s );
@@ -514,8 +520,8 @@ class Framebuffer
514520

515521
bool operator==( const Framebuffer& x ) const
516522
{
517-
return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard )
518-
&& ( bell_count == x.bell_count ) && ( ds == x.ds );
523+
return ( rows == x.rows ) && ( window_title == x.window_title ) && ( current_directory == x.current_directory )
524+
&& ( clipboard == x.clipboard ) && ( bell_count == x.bell_count ) && ( ds == x.ds );
519525
}
520526
};
521527
}

src/terminal/terminalfunctions.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,13 @@ void Dispatcher::OSC_dispatch( const Parser::OSC_End* act __attribute( ( unused
657657
OSC_8( osc_8_str, fb );
658658
return;
659659
}
660+
if ( cmd_num == 7 ) {
661+
fb->set_current_directory_initialized();
662+
int cwd_length = std::min( OSC_string.size(), (size_t)1024 );
663+
Terminal::Framebuffer::title_type new_cwd( OSC_string.begin() + offset, OSC_string.begin() + cwd_length );
664+
fb->set_current_directory( new_cwd );
665+
return;
666+
}
660667
bool set_icon = cmd_num == 0 || cmd_num == 1;
661668
bool set_title = cmd_num == 0 || cmd_num == 2;
662669
if ( set_icon || set_title ) {

src/tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ displaytests = \
2525
emulation-back-tab.test \
2626
emulation-cursor-motion.test \
2727
emulation-multiline-scroll.test \
28+
emulation-osc7.test \
2829
emulation-scroll.test \
2930
emulation-wrap-across-frames.test \
3031
network-no-diff.test \

src/tests/emulation-osc7.test

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/sh
2+
3+
#
4+
# This test is for issue 539 on github.
5+
#
6+
7+
# shellcheck source=e2e-test-subrs
8+
. "$(dirname "$0")/e2e-test-subrs"
9+
PATH=$PATH:.:$srcdir
10+
# Top-level wrapper.
11+
if [ $# -eq 0 ]; then
12+
e2e-test "$0" baseline post
13+
exit
14+
fi
15+
16+
# OK, we have arguments, we're one of the test hooks.
17+
if [ $# -ne 1 ]; then
18+
fail "bad arguments %s\n" "$@"
19+
fi
20+
21+
if ! tmux_check 3 3; then
22+
printf "tmux does not support OSC7\n" >&2
23+
exit 77
24+
fi
25+
26+
baseline()
27+
{
28+
printf '\033]7;file://hostname/directory/\007'
29+
echo 0
30+
printf '\033]7;\007'
31+
}
32+
33+
case $1 in
34+
baseline)
35+
baseline;;
36+
post)
37+
;;
38+
*)
39+
fail "unknown test argument %s\n" "$1";;
40+
esac

0 commit comments

Comments
 (0)