-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuffer2vim
executable file
·136 lines (122 loc) · 3.67 KB
/
buffer2vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env perl
# Inspired by https://github.com/jeromebelleman/reactivity vim part
#
# Resources used:
# number of rows to show with vim_last, default 1024:
# urxvt.buffer2vim.lastrows: POSITIVE INT
# If you want to use temp files or a pipe to feed vim, default 'file':
# urxvt.buffer2vim.tmpfiletype: 'file' | 'pipe'
#
# Functions:
# show last rows:
# perl:buffer2vim:vim_last
# show all buffer:
# perl:buffer2vim:vim
sub print_lines {
my ($term, $fh, $max_rows) = @_;
my $empty_lines = 0;
my $row = $term->top_row;
if ($max_rows) {
my $postrow = $term->nrow - $max_rows;
if ($row < $postrow) {
$row = $postrow;
}
}
while ($row < $term->nrow) {
my $line = $term->line($row);
if ($line->l) {
for (; $empty_lines; --$empty_lines) {
print $fh "\n";
}
print $fh eval "\$line->t =~ tr/$urxvt::NOCHAR//dr"; # It's yet faster without this cleanup
print $fh "\n";
} else {
$empty_lines++;
}
$row = $line->end+1;
}
}
sub exec_vim {
my ($term, $filepath, $cwd, $vim_delete_file, $pre_cmd) = @_;
my @vim_cmd = (
'vim',
($vim_delete_file) ? "+\"call delete(expand('%'))\"" : '+"normal gg"', # gg is noop
'+"set buftype=nofile"',
'+"set noreadonly"',
'+"file [urxvt]"',
'+"normal G$"',
'+redraw',
$filepath
);
if ($pre_cmd) {
my $shell = $ENV{'SHELL'} || 'sh';
$term->exec_async(
'urxvt',
'-cd',
$cwd,
'-e',
$shell,
'-c',
$pre_cmd.join(' ', @vim_cmd)
);
} else {
$term->exec_async(
'urxvt',
'-cd',
$cwd,
'-e',
@vim_cmd
);
}
}
sub on_start {
my ($term) = @_;
$term->{last_rows} = $term->x_resource('%.lastrows') || 1024;
$term->{tmp_file_type} = $term->x_resource('%.tmpfiletype') || 'file';
$term->{pre_cmd} = $term->x_resource('%.pre_cmd');
()
}
sub on_child_start {
my ($term, $pid) = @_;
$term->{shell_pid} = $pid;
()
}
sub on_user_command {
my ($term, $cmd) = @_;
my $max_rows;
if ($cmd eq 'buffer2vim:vim_last') {
$max_rows = $term->{last_rows};
} elsif ($cmd eq 'buffer2vim:vim') {
$max_rows = 0;
} else {
return ();
}
if ($term->{tmp_file_type} eq 'pipe') {
my $pipe_path = "/tmp/buffer2vim-urxvt-$term->{shell_pid}.pipe";
if (POSIX::mkfifo($pipe_path, 0600)) {
if (exec_vim($term, $pipe_path, "/proc/$term->{shell_pid}/cwd", 0, $term->{pre_cmd})) {
if (open($fh, ">:utf8", $pipe_path)) {
print_lines($term, $fh, $max_rows);
close $fh;
} else {
urxvt::warn "buffer2vim: Cannot write to $pipe_path\n";
}
} else {
urxvt::warn "buffer2vim: Cannot launch vim to read from $pipe_path\n";
}
unlink $pipe_path;
} else {
urxvt::warn "buffer2vim: Cannot create pipe $pipe_path\n";
}
} elsif ($term->{tmp_file_type} eq 'file') {
use File::Temp qw/ tempfile /;
my ($fh, $filename) = tempfile("buffer2vim-urxvt-$term->{shell_pid}-XXXXXX", DIR => '/tmp');
binmode($fh, ":utf8");
print_lines($term, $fh, $max_rows);
close $fh;
exec_vim($term, $filename, "/proc/$term->{shell_pid}/cwd", 1, $term->{pre_cmd});
} else {
urxvt::warn "buffer2vim: Tmp file type unrecognized: $term->{tmp_file_type}\n";
}
return 1;
}