-
Notifications
You must be signed in to change notification settings - Fork 0
/
hx_ide
executable file
·150 lines (130 loc) · 3.57 KB
/
hx_ide
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env ruby
# frozen_string_literal: true
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
require 'json'
require 'open3'
def test_command_map
{
rb: 'bin/rspec',
js: 'yarn test',
jsx: 'yarn test',
ts: 'yarn test',
tsx: 'yarn test'
}
end
def pane_prefix
"hx_ide_pane_#{executing_pane_id}"
end
def executing_pane_id
ENV['KITTY_WINDOW_ID']
end
def open_panes
result = JSON.parse `kitty @ ls --match-tab="state:active"`
result.first['tabs'].first['windows']
end
def open_pane_id(location = 'hsplit')
title = "#{pane_prefix}:#{location}"
open_pane = open_panes.find { |pane| pane['title'] == title }
open_pane['id'] if open_pane
end
def pane_command(k_command:, command:, pane_id:)
`kitty @ #{k_command} --match="id:#{pane_id}" "#{command}"`
end
def send_keys(keys:, pane_id:)
keys.each do |key_strokes|
pane_command(k_command: 'send-key', command: key_strokes, pane_id:)
end
end
def launch_pane(command: '', hold: false, location: 'before', keep_focus: false)
`kitty @ launch \
--allow-remote-control \
--location=#{location} \
--cwd=current \
--bias=30 \
#{keep_focus ? '--keep-focus' : ''} \
--title="#{pane_prefix}:#{location}" #{hold ? '--hold' : ''} #{command}\
`
end
def split_pane(launch_command: '', command: '', hold: false, location: 'before', keep_focus: false)
if (pane_id = open_pane_id(location))
send_keys(keys: ['ctrl+u', 'ctrl+l'], pane_id:)
else
pane_id = launch_pane(
command: launch_command,
hold:,
location:,
keep_focus:
)
return pane_id unless launch_command.strip.empty?
end
if block_given?
yield(pane_id)
else
unless command.strip.empty?
pane_command(
k_command: 'send-text',
command:,
pane_id:
)
end
end
pane_id
end
def file_attributes(id)
file_text = `kitty @ get-text -m "id:#{id}"`
status_line = file_text.match(/(?:NOR|INS|SEL)\s+[\u{2800}-\u{28FF}]*\s+(\S*)\s[^│]* (\d+):*.*/)
file_name = status_line[1].strip
{
status_line:,
file_name:,
line_number: status_line[2],
basedir: `dirname "#{file_name}"`.strip,
basename: `basename "#{file_name}"`.strip,
extension: file_name.split('.').last.strip
}
end
def handle_input(input)
main_id = ENV['KITTY_WINDOW_ID']
file_attrs = file_attributes(main_id)
case input
when 'blame'
split_pane(
location: 'hsplit',
command: "tig blame #{file_attrs[:file_name]} +#{file_attrs[:line_number]} \r"
)
when 'test'
extension = file_attrs[:extension]
command = test_command_map[extension.to_sym]
if command.nil?
puts "Invalid file extension: #{extension}"
else
split_pane(hold: true, location: 'hsplit', command: "#{command} #{file_attrs[:file_name]} \r")
end
when 'explorer'
split_pane(command: "broot #{file_attrs[:basedir]} ; kitty @ close-window \r")
when 'search'
split_pane(hold: true, location: 'hsplit') do |id|
pane_command(
k_command: 'send-text',
command: "hx_fzf #{main_id} #{id} \r",
pane_id: id
)
end
when 'pane'
split_pane(hold: true, location: 'hsplit')
when 'lint'
split_pane(
command: "eslint_d #{file_attrs[:file_name]} --fix \r",
hold: true,
location: 'hsplit',
keep_focus: true
)
when 'cfp'
`echo #{file_attrs[:file_name]} | pbcopy`
else
# for easily testing method output
puts send(input)
end
end
handle_input ARGV[0]
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity