hiiro 0.1.132 → 0.1.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/bin/h-claude +97 -0
- data/bin/h-jumplist +183 -0
- data/bin/h-notify +148 -0
- data/bin/h-pr +29 -137
- data/bin/h-project +1 -1
- data/demo.sh +116 -0
- data/demo.typescript +0 -0
- data/h-tmux-plugins.tmux +30 -0
- data/lib/hiiro/tmux.rb +26 -10
- data/lib/hiiro/version.rb +1 -1
- data/lib/hiiro.rb +18 -7
- data/record-demo.sh +176 -0
- data/slides.md +211 -0
- metadata +9 -3
- data/bin/testlink +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5c49242912889d365b5eabdfdc3adeb72ea6d55dd7311280dcc9b3f6ac40013
|
|
4
|
+
data.tar.gz: 219b6710d528233190c7bfb30465d4f3b293cea21f24c8a01561768566ce83ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ae90dc0c81c21b6d580ccfa3b2ba3475633f7686efdc5de97147cc3030538632e01c436a244e682d6ee7cc361cd3ed9945652c2fd1c4792da8ad98d6a160913
|
|
7
|
+
data.tar.gz: ebca695230cc51d34b926726c5514af9b6c535eb368920fca89a0dd3dbec0e37d16748612612032485819ac01419b6c1f7b87ca44fc4d5281885610dec8e3900
|
data/README.md
CHANGED
|
@@ -82,6 +82,7 @@ h ping
|
|
|
82
82
|
| `h plugin` | Manage hiiro plugins (list, edit, search) |
|
|
83
83
|
| `h pr` | GitHub PR management via gh CLI |
|
|
84
84
|
| `h project` | Project navigation with tmux session management |
|
|
85
|
+
| `h queue` | Claude prompt queue with tmux-based task execution |
|
|
85
86
|
| `h session` | Tmux session management |
|
|
86
87
|
| `h sha` | Extract short SHA from git log |
|
|
87
88
|
| `h todo` | Todo list management with tags and task association |
|
|
@@ -212,6 +213,7 @@ All configuration lives in `~/.config/hiiro/`:
|
|
|
212
213
|
~/.config/hiiro/
|
|
213
214
|
plugins/ # Plugin files (auto-loaded)
|
|
214
215
|
pins/ # Pin storage (per command)
|
|
216
|
+
queue/ # Prompt queue (wip, pending, running, done, failed)
|
|
215
217
|
tasks/ # Task metadata
|
|
216
218
|
projects.yml # Project aliases
|
|
217
219
|
apps.yml # App directory mappings
|
data/bin/h-claude
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'hiiro'
|
|
4
4
|
require 'shellwords'
|
|
5
|
+
require 'tempfile'
|
|
5
6
|
|
|
6
7
|
opts = Hiiro::Options.setup {
|
|
7
8
|
flag(:danger, short: :d, default: false)
|
|
@@ -55,4 +56,100 @@ Hiiro.run(*ARGV, plugins: [Pins]) {
|
|
|
55
56
|
|
|
56
57
|
system('tmux', 'split-window', '-v', '-l', size, start_command(opts))
|
|
57
58
|
}
|
|
59
|
+
|
|
60
|
+
add_subcmd(:env) { |*args|
|
|
61
|
+
ap ENV
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
add_subcmd(:inline) { |*args|
|
|
65
|
+
if args.empty? && !$stdin.tty?
|
|
66
|
+
prompt = $stdin.read.strip
|
|
67
|
+
elsif args.any?
|
|
68
|
+
prompt = args.join(' ')
|
|
69
|
+
else
|
|
70
|
+
tmpfile = Tempfile.new(['claude-inline-', '.md'])
|
|
71
|
+
tmpfile.close
|
|
72
|
+
editor = ENV['EDITOR'] || 'vim'
|
|
73
|
+
system(editor, tmpfile.path)
|
|
74
|
+
prompt = File.read(tmpfile.path).strip
|
|
75
|
+
tmpfile.unlink
|
|
76
|
+
if prompt.empty?
|
|
77
|
+
puts "Aborted (empty file)"
|
|
78
|
+
next
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
IO.popen(['claude', '-p'], 'w') { |io| io.write(prompt) }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
add_subcmd(:loop) { |*args|
|
|
86
|
+
editor = ENV['EDITOR'] || 'vim'
|
|
87
|
+
separator = "-" * 72
|
|
88
|
+
history = []
|
|
89
|
+
|
|
90
|
+
loop do
|
|
91
|
+
tmpfile = Tempfile.new(['claude-loop-', '.md'])
|
|
92
|
+
|
|
93
|
+
if history.any?
|
|
94
|
+
lines = []
|
|
95
|
+
history.each_with_index do |(prev_prompt, response), i|
|
|
96
|
+
lines << "# Prompt #{i + 1} (old - do not edit)"
|
|
97
|
+
prev_prompt.lines.each { |l| lines << "> #{l.chomp}" }
|
|
98
|
+
lines << ""
|
|
99
|
+
lines << "## Response #{i + 1}"
|
|
100
|
+
lines << response
|
|
101
|
+
lines << ""
|
|
102
|
+
end
|
|
103
|
+
lines << separator
|
|
104
|
+
lines << "# Put your new prompt below this line"
|
|
105
|
+
lines << ""
|
|
106
|
+
tmpfile.write(lines.join("\n"))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
tmpfile.close
|
|
110
|
+
system(editor, tmpfile.path)
|
|
111
|
+
content = File.read(tmpfile.path).strip
|
|
112
|
+
tmpfile.unlink
|
|
113
|
+
|
|
114
|
+
if content.empty?
|
|
115
|
+
puts "Done."
|
|
116
|
+
break
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Extract only the new prompt (below the separator)
|
|
120
|
+
if content.include?(separator)
|
|
121
|
+
new_prompt = content.split(separator, 2).last.strip
|
|
122
|
+
# Strip the instruction line if present
|
|
123
|
+
new_prompt = new_prompt.sub(/\A# Put your new prompt below this line\n*/, '').strip
|
|
124
|
+
else
|
|
125
|
+
new_prompt = content.strip
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if new_prompt.empty?
|
|
129
|
+
puts "Done."
|
|
130
|
+
break
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Build the full prompt with context for claude
|
|
134
|
+
full_prompt = ""
|
|
135
|
+
if history.any?
|
|
136
|
+
history.each_with_index do |(prev_prompt, response), i|
|
|
137
|
+
full_prompt << "--- Previous prompt #{i + 1} ---\n#{prev_prompt}\n\n"
|
|
138
|
+
full_prompt << "--- Response #{i + 1} ---\n#{response}\n\n"
|
|
139
|
+
end
|
|
140
|
+
full_prompt << "--- New prompt ---\n"
|
|
141
|
+
end
|
|
142
|
+
full_prompt << new_prompt
|
|
143
|
+
|
|
144
|
+
puts "\nSending to claude...\n\n"
|
|
145
|
+
response = IO.popen(['claude', '-p'], 'r+') { |io|
|
|
146
|
+
io.write(full_prompt)
|
|
147
|
+
io.close_write
|
|
148
|
+
io.read
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
puts response
|
|
152
|
+
history << [new_prompt, response]
|
|
153
|
+
end
|
|
154
|
+
}
|
|
58
155
|
}
|
data/bin/h-jumplist
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "hiiro"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
JUMPLIST_DIR = File.join(Dir.home, '.config', 'hiiro', 'jumplist')
|
|
7
|
+
JUMPLIST_FILE = File.join(JUMPLIST_DIR, 'entries')
|
|
8
|
+
POS_FILE = File.join(JUMPLIST_DIR, 'position')
|
|
9
|
+
MAX_SIZE = 50
|
|
10
|
+
|
|
11
|
+
FileUtils.mkdir_p(JUMPLIST_DIR)
|
|
12
|
+
|
|
13
|
+
def read_entries
|
|
14
|
+
return [] unless File.exist?(JUMPLIST_FILE)
|
|
15
|
+
File.readlines(JUMPLIST_FILE, chomp: true).reject(&:empty?)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def write_entries(entries)
|
|
19
|
+
File.write(JUMPLIST_FILE, entries.join("\n") + "\n")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def get_pos
|
|
23
|
+
return 0 unless File.exist?(POS_FILE)
|
|
24
|
+
File.read(POS_FILE).strip.to_i
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def set_pos(n)
|
|
28
|
+
File.write(POS_FILE, n.to_s)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def pane_exists?(pane_id)
|
|
32
|
+
panes = `tmux list-panes -a -F '\#{pane_id}' 2>/dev/null`.strip.split("\n")
|
|
33
|
+
panes.include?(pane_id)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def tmux_display(fmt)
|
|
37
|
+
`tmux display-message -p '#{fmt}'`.strip
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Hiiro.run(*ARGV) do
|
|
41
|
+
add_subcmd(:setup) do
|
|
42
|
+
puts <<~SETUP
|
|
43
|
+
# Add the following to your tmux.conf:
|
|
44
|
+
|
|
45
|
+
# --- Jumplist hooks (record pane/window navigation) ---
|
|
46
|
+
set-hook -g after-select-pane "run-shell -b 'h jumplist record'"
|
|
47
|
+
set-hook -g after-select-window "run-shell -b 'h jumplist record'"
|
|
48
|
+
|
|
49
|
+
# --- Jumplist keybindings ---
|
|
50
|
+
bind-key -r C-b run-shell "h jumplist back"
|
|
51
|
+
bind-key -r C-f run-shell "h jumplist forward"
|
|
52
|
+
SETUP
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
add_subcmd(:record) do
|
|
56
|
+
# Check suppression flag
|
|
57
|
+
suppress = `tmux show-environment TMUX_JUMPLIST_SUPPRESS 2>/dev/null`.strip
|
|
58
|
+
if suppress == "TMUX_JUMPLIST_SUPPRESS=1"
|
|
59
|
+
system('tmux', 'set-environment', '-u', 'TMUX_JUMPLIST_SUPPRESS')
|
|
60
|
+
next
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
pane_id = tmux_display('#\{pane_id\}')
|
|
64
|
+
window_id = tmux_display('#\{window_id\}')
|
|
65
|
+
session_name = tmux_display('#\{session_name\}')
|
|
66
|
+
pane_cmd = tmux_display('#\{pane_current_command\}')
|
|
67
|
+
timestamp = Time.now.to_i.to_s
|
|
68
|
+
|
|
69
|
+
entries = read_entries
|
|
70
|
+
pos = get_pos
|
|
71
|
+
|
|
72
|
+
# If position is not at head, truncate forward history
|
|
73
|
+
if pos > 0 && entries.any?
|
|
74
|
+
entries = entries[pos..]
|
|
75
|
+
set_pos(0)
|
|
76
|
+
elsif pos > 0
|
|
77
|
+
set_pos(0)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Deduplicate: skip if most recent entry is same pane
|
|
81
|
+
if entries.any?
|
|
82
|
+
last_pane = entries[0].split('|', 2).first
|
|
83
|
+
next if last_pane == pane_id
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Prepend new entry (newest first)
|
|
87
|
+
new_entry = [pane_id, window_id, session_name, timestamp, pane_cmd].join('|')
|
|
88
|
+
entries.unshift(new_entry)
|
|
89
|
+
entries = entries.first(MAX_SIZE)
|
|
90
|
+
write_entries(entries)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
add_subcmd(:back) do
|
|
94
|
+
entries = read_entries
|
|
95
|
+
pos = get_pos
|
|
96
|
+
|
|
97
|
+
if entries.empty?
|
|
98
|
+
system('tmux', 'display-message', 'Jumplist: empty')
|
|
99
|
+
next
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# If at position 0, record current pane first so forward works
|
|
103
|
+
if pos == 0
|
|
104
|
+
pane_id = tmux_display('#\{pane_id\}')
|
|
105
|
+
window_id = tmux_display('#\{window_id\}')
|
|
106
|
+
session_name = tmux_display('#\{session_name\}')
|
|
107
|
+
pane_cmd = tmux_display('#\{pane_current_command\}')
|
|
108
|
+
timestamp = Time.now.to_i.to_s
|
|
109
|
+
|
|
110
|
+
new_entry = [pane_id, window_id, session_name, timestamp, pane_cmd].join('|')
|
|
111
|
+
|
|
112
|
+
# Only prepend if different from current head
|
|
113
|
+
if entries.empty? || entries[0].split('|', 2).first != pane_id
|
|
114
|
+
entries.unshift(new_entry)
|
|
115
|
+
entries = entries.first(MAX_SIZE)
|
|
116
|
+
write_entries(entries)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Find next valid entry going backward
|
|
121
|
+
new_pos = pos + 1
|
|
122
|
+
while new_pos < entries.length
|
|
123
|
+
entry = entries[new_pos]
|
|
124
|
+
parts = entry.split('|')
|
|
125
|
+
target_pane = parts[0]
|
|
126
|
+
target_window = parts[1]
|
|
127
|
+
target_session = parts[2]
|
|
128
|
+
|
|
129
|
+
if pane_exists?(target_pane)
|
|
130
|
+
system('tmux', 'set-environment', 'TMUX_JUMPLIST_SUPPRESS', '1')
|
|
131
|
+
system('tmux', 'switch-client', '-t', target_session)
|
|
132
|
+
system('tmux', 'select-window', '-t', target_window)
|
|
133
|
+
system('tmux', 'select-pane', '-t', target_pane)
|
|
134
|
+
set_pos(new_pos)
|
|
135
|
+
next # exit the subcmd block
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
new_pos += 1
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
system('tmux', 'display-message', 'Jumplist: at oldest entry')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
add_subcmd(:forward) do
|
|
145
|
+
pos = get_pos
|
|
146
|
+
|
|
147
|
+
if pos <= 0
|
|
148
|
+
system('tmux', 'display-message', 'Jumplist: at newest entry')
|
|
149
|
+
next
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
entries = read_entries
|
|
153
|
+
|
|
154
|
+
if entries.empty?
|
|
155
|
+
system('tmux', 'display-message', 'Jumplist: empty')
|
|
156
|
+
next
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Find next valid entry going forward (toward index 0)
|
|
160
|
+
new_pos = pos - 1
|
|
161
|
+
while new_pos >= 0
|
|
162
|
+
entry = entries[new_pos]
|
|
163
|
+
parts = entry.split('|')
|
|
164
|
+
target_pane = parts[0]
|
|
165
|
+
target_window = parts[1]
|
|
166
|
+
target_session = parts[2]
|
|
167
|
+
|
|
168
|
+
if pane_exists?(target_pane)
|
|
169
|
+
system('tmux', 'set-environment', 'TMUX_JUMPLIST_SUPPRESS', '1')
|
|
170
|
+
system('tmux', 'switch-client', '-t', target_session)
|
|
171
|
+
system('tmux', 'select-window', '-t', target_window)
|
|
172
|
+
system('tmux', 'select-pane', '-t', target_pane)
|
|
173
|
+
set_pos(new_pos)
|
|
174
|
+
next # exit the subcmd block
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
new_pos -= 1
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
system('tmux', 'display-message', 'Jumplist: at newest entry')
|
|
181
|
+
set_pos(0)
|
|
182
|
+
end
|
|
183
|
+
end
|
data/bin/h-notify
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "hiiro"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
TYPE_PRESETS = {
|
|
7
|
+
'success' => { prefix: '[OK]', sound: 'Glass', title: 'Success' },
|
|
8
|
+
'error' => { prefix: '[ERR]', sound: 'Basso', title: 'Error' },
|
|
9
|
+
'info' => { prefix: '[INFO]', sound: 'Pop', title: 'Info' },
|
|
10
|
+
'warning' => { prefix: '[WARN]', sound: 'Purr', title: 'Warning' },
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def session_name
|
|
14
|
+
`tmux display-message -p '\#{session_name}'`.strip
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def notify_file(session = nil)
|
|
18
|
+
session ||= session_name
|
|
19
|
+
"/tmp/tmux-notifications-#{session}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def read_notifications(session = nil)
|
|
23
|
+
file = notify_file(session)
|
|
24
|
+
return [] unless File.exist?(file)
|
|
25
|
+
File.readlines(file, chomp: true).reject(&:empty?)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def write_notifications(entries, session = nil)
|
|
29
|
+
file = notify_file(session)
|
|
30
|
+
if entries.empty?
|
|
31
|
+
File.delete(file) if File.exist?(file)
|
|
32
|
+
else
|
|
33
|
+
File.write(file, entries.join("\n") + "\n")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def pane_exists?(pane_id)
|
|
38
|
+
panes = `tmux list-panes -a -F '\#{pane_id}' 2>/dev/null`.strip.split("\n")
|
|
39
|
+
panes.include?(pane_id)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Hiiro.run(*ARGV) do
|
|
43
|
+
opts = Hiiro::Options.parse(args) do
|
|
44
|
+
option(:type, short: 't', desc: 'Notification type (success, error, info, warning)', default: 'info')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
preset = TYPE_PRESETS[opts.type] || TYPE_PRESETS['info']
|
|
48
|
+
|
|
49
|
+
add_subcmd(:push) do |*push_args|
|
|
50
|
+
message = push_args.join(' ')
|
|
51
|
+
if message.empty?
|
|
52
|
+
puts "Usage: h notify push [-t TYPE] \"message\""
|
|
53
|
+
next
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
pane_id = `tmux display-message -p '\#{pane_id}'`.strip
|
|
57
|
+
window_id = `tmux display-message -p '\#{window_id}'`.strip
|
|
58
|
+
session = session_name
|
|
59
|
+
pane_cmd = `tmux display-message -p '\#{pane_current_command}'`.strip
|
|
60
|
+
timestamp = Time.now.to_i.to_s
|
|
61
|
+
|
|
62
|
+
entry = [pane_id, window_id, session, timestamp, pane_cmd, message].join('|')
|
|
63
|
+
|
|
64
|
+
entries = read_notifications(session)
|
|
65
|
+
entries.unshift(entry)
|
|
66
|
+
write_notifications(entries, session)
|
|
67
|
+
|
|
68
|
+
# Show tmux display-message with type prefix
|
|
69
|
+
system('tmux', 'display-message', "#{preset[:prefix]} #{message}")
|
|
70
|
+
|
|
71
|
+
# Also send terminal-notifier
|
|
72
|
+
system('terminal-notifier',
|
|
73
|
+
'-title', preset[:title],
|
|
74
|
+
'-message', message,
|
|
75
|
+
'-sound', preset[:sound])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
add_subcmd(:menu) do
|
|
79
|
+
session = session_name
|
|
80
|
+
entries = read_notifications(session)
|
|
81
|
+
|
|
82
|
+
if entries.empty?
|
|
83
|
+
system('tmux', 'display-message', 'No notifications')
|
|
84
|
+
next
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Build display-menu arguments
|
|
88
|
+
menu_args = ['-T', 'Notifications']
|
|
89
|
+
|
|
90
|
+
entries.first(10).each_with_index do |line, idx|
|
|
91
|
+
parts = line.split('|')
|
|
92
|
+
pane_id = parts[0]
|
|
93
|
+
cmd = parts[4]
|
|
94
|
+
msg = parts[5..].join('|')
|
|
95
|
+
msg = msg[0..46] + '...' if msg.length > 50
|
|
96
|
+
|
|
97
|
+
label = "#{idx}: [#{pane_id}] #{cmd}: #{msg}"
|
|
98
|
+
menu_args.push(label, idx.to_s, "run-shell 'h notify jump #{idx}'")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Separator and clear option
|
|
102
|
+
menu_args.push('', '', 'Clear all', 'c', "run-shell 'h notify clear'")
|
|
103
|
+
|
|
104
|
+
system('tmux', 'display-menu', *menu_args)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
add_subcmd(:jump) do |index_str = nil|
|
|
108
|
+
if index_str.nil?
|
|
109
|
+
puts "Usage: h notify jump INDEX"
|
|
110
|
+
next
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
index = index_str.to_i
|
|
114
|
+
session = session_name
|
|
115
|
+
entries = read_notifications(session)
|
|
116
|
+
|
|
117
|
+
if index >= entries.length
|
|
118
|
+
system('tmux', 'display-message', 'Notification not found')
|
|
119
|
+
next
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
entry = entries[index]
|
|
123
|
+
parts = entry.split('|')
|
|
124
|
+
target_pane = parts[0]
|
|
125
|
+
target_window = parts[1]
|
|
126
|
+
|
|
127
|
+
unless pane_exists?(target_pane)
|
|
128
|
+
system('tmux', 'display-message', "Pane #{target_pane} no longer exists")
|
|
129
|
+
entries.delete_at(index)
|
|
130
|
+
write_notifications(entries, session)
|
|
131
|
+
next
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
system('tmux', 'select-window', '-t', target_window)
|
|
135
|
+
system('tmux', 'select-pane', '-t', target_pane)
|
|
136
|
+
|
|
137
|
+
# Remove the notification
|
|
138
|
+
entries.delete_at(index)
|
|
139
|
+
write_notifications(entries, session)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
add_subcmd(:clear) do
|
|
143
|
+
session = session_name
|
|
144
|
+
file = notify_file(session)
|
|
145
|
+
File.delete(file) if File.exist?(file)
|
|
146
|
+
system('tmux', 'display-message', 'Notifications cleared')
|
|
147
|
+
end
|
|
148
|
+
end
|