hiiro 0.1.338 → 0.1.340

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92203914806a439748cb5f3020d0784c253e3a1ac91bebf786a2115c9aa3b0d4
4
- data.tar.gz: 665b26d833fd387edf53814df50d6289e8dea59b56abc97ba485ed0ab169ad71
3
+ metadata.gz: 413a819364e3fce84109acbe813f653663567f5c2cb7025a2f2af4ab940051a5
4
+ data.tar.gz: 3b2082944a38035fcb96635c376b738e2aff83ad6d63e211e12d4693c738058a
5
5
  SHA512:
6
- metadata.gz: ceb994131ac83201c806910f87099df9e1cfbea8ffd91d5fcf15221c64ee153af859a40eb7dc36553cd5f4fd1c690f2123415b933676656fb5d70af54359f608
7
- data.tar.gz: 5c3f66a48df5269d6d383030c8e46a88a87b451bcca5fdbf1c53fd0aebc7d437810815f616cdd70d9df0e20132c5482425555292b932694825f4972118f677ee
6
+ metadata.gz: 8e0dc534669ec4d03fc1549167a7bae54229398d253f843025a10fb99ee1b727eebb80c9287cb5c17d15e46186257049edad67f55de5126e900590b9e05a4ea8
7
+ data.tar.gz: 1451f79da21cbe8be1c98b46425e66f405fe2a2e87be9039b99ad753c7901dff025676fa73cea0e801a9f82c7234d1de554a1e0ceff282ba3b589a673d115f03
data/CHANGELOG.md CHANGED
@@ -1,8 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.340] - 2026-04-07
4
+
5
+ ### Fixed
6
+ - `h notify jump` now runs `switch-client` before `select-window`/`select-pane` so jumping to a pane in a different session actually works
7
+ - `h notify ls` and `h notify menu` now auto-prune stale entries for panes that no longer exist
8
+
9
+ ### Added
10
+ - `h notify prune` — explicitly remove all notifications for dead panes
11
+
12
+ ## [0.1.339] - 2026-04-07
13
+
14
+ ### Added
15
+ - `h ps byport <port> [port2 ...]` — find processes listening on specified port(s)
16
+ - `PsProcess.by_port(*ports)` — query processes by listening port numbers
17
+ - `h task switch` now matches ~/proj/* directories by prefix as fallback when task name doesn't match
18
+
3
19
  ## [0.1.338] - 2026-04-07
4
20
 
5
21
  ### Changed
22
+ - `h pr watch`, `h pr fwatch`, `h pr check` now default to current branch's PR (use `-s` to select via fuzzyfinder)
6
23
  - Renamed `registry_entries` table to `registry` (auto-migrates existing data)
7
24
 
8
25
  ## [0.1.337] - 2026-04-06
@@ -316,4 +333,4 @@
316
333
  - `bin/h-link` — reads/writes links via `Hiiro::Link` SQLite model with YAML dual-write fallback; adds `q`/`query` subcommands
317
334
  - `bin/h-pane` — load/save pane homes via `Hiiro::PaneHome` model with YAML dual-write
318
335
  - `bin/h-pr` — adds `q`/`query` subcommands for inspecting PR records via raw SQL
319
- - `plugins/pins.rb` — `Pin` class reads/writes via `Hiiro::PinRecord` SQLite model with YAML dual-write fallback
336
+ - `plugins/pins.rb` — `Pin` class reads/writes via `Hiiro::PinRecord` SQLite model with YAML dual-write fallback
data/bin/h-notify CHANGED
@@ -121,16 +121,37 @@ Hiiro.run(*ARGV, tasks: true) do
121
121
  if data.empty?
122
122
  puts "No notifications."
123
123
  else
124
- data.each_with_index do |e, i|
125
- time_str = Time.at(e['timestamp']).strftime('%H:%M:%S')
126
- prefix = TYPE_PRESETS[e['type']]&.dig(:prefix) || '[INFO]'
127
- puts "%3d) %s [%s/%s] %s: %s (%s)" % [i, prefix, e['session'], e['pane_id'], e['pane_cmd'], e['message'], time_str]
124
+ live_ids = Hiiro::Tmux::Panes.fetch(all: true).ids.to_set
125
+ pruned = data.reject { |e| live_ids.include?(e['pane_id']) }
126
+ data = data.select { |e| live_ids.include?(e['pane_id']) }
127
+ write_log(data) if pruned.any?
128
+
129
+ if data.empty?
130
+ puts "No notifications (#{pruned.size} stale entries removed)."
131
+ else
132
+ puts "(#{pruned.size} stale entries removed.)" if pruned.any?
133
+ data.each_with_index do |e, i|
134
+ time_str = Time.at(e['timestamp']).strftime('%H:%M:%S')
135
+ prefix = TYPE_PRESETS[e['type']]&.dig(:prefix) || '[INFO]'
136
+ puts "%3d) %s [%s/%s] %s: %s (%s)" % [i, prefix, e['session'], e['pane_id'], e['pane_cmd'], e['message'], time_str]
137
+ end
128
138
  end
129
139
  end
130
140
  end
131
141
 
142
+ add_subcmd(:prune) do
143
+ data = read_log
144
+ live_ids = Hiiro::Tmux::Panes.fetch(all: true).ids.to_set
145
+ pruned = data.reject { |e| live_ids.include?(e['pane_id']) }
146
+ write_log(data.select { |e| live_ids.include?(e['pane_id']) })
147
+ puts "Removed #{pruned.size} stale notification(s). #{data.size - pruned.size} remaining."
148
+ end
149
+
132
150
  add_subcmd(:menu) do
133
- entries = read_log
151
+ data = read_log
152
+ live_ids = Hiiro::Tmux::Panes.fetch(all: true).ids.to_set
153
+ entries = data.select { |e| live_ids.include?(e['pane_id']) }
154
+ write_log(entries) if entries.size != data.size
134
155
 
135
156
  if entries.empty?
136
157
  next
@@ -169,8 +190,9 @@ Hiiro.run(*ARGV, tasks: true) do
169
190
  next
170
191
  end
171
192
 
172
- tmux_client.select_window(entry['window_id'])
173
- tmux_client.select_pane(entry['pane_id'])
193
+ system('tmux', 'switch-client', '-t', entry['session'])
194
+ system('tmux', 'select-window', '-t', entry['window_id'])
195
+ system('tmux', 'select-pane', '-t', entry['pane_id'])
174
196
 
175
197
  data.delete_at(index)
176
198
  write_log(data)
data/bin/h-pr CHANGED
@@ -11,11 +11,30 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
11
11
  pm = pinned_manager = Hiiro::PinnedPRManager.new
12
12
  Hiiro::PinnedPRManager.add_resolvers(self)
13
13
 
14
- watch_block = ->(original_pr_number=nil, *watch_args) {
14
+ watch_block = ->(*all_args) {
15
+ opts = Hiiro::Options.setup {
16
+ option(:select, short: :s, type: :flag, desc: 'Select PR via fuzzyfinder')
17
+ }.parse(all_args)
18
+
19
+ original_pr_number = opts.args.first
20
+ watch_args = opts.args[1..] || []
15
21
  watch = get_value(:watch)
16
22
  fail_fast = get_value(:fail_fast)
17
23
 
18
- pr_number = resolve(:pr, original_pr_number)
24
+ pr_number = if opts.select
25
+ resolve(:pr, nil) # triggers fuzzyfinder
26
+ elsif original_pr_number
27
+ resolve(:pr, original_pr_number)
28
+ else
29
+ # Default to current branch's PR
30
+ current_pr = pm.fetch_current_branch_pr
31
+ if current_pr
32
+ current_pr.number.to_s
33
+ else
34
+ STDERR.puts "No PR for current branch. Use -s to select or provide a PR number."
35
+ nil
36
+ end
37
+ end
19
38
  return unless pr_number
20
39
 
21
40
  base_cmd = %w[gh pr checks]
data/bin/h-ps CHANGED
@@ -20,6 +20,21 @@ Hiiro.run(*ARGV) do
20
20
  end
21
21
  end
22
22
 
23
+ add_subcmd(:byport) { |*ports|
24
+ if ports.empty?
25
+ puts "Usage: h ps byport <port> [port2 ...]"
26
+ next
27
+ end
28
+
29
+ processes = Hiiro::PsProcess.by_port(*ports)
30
+
31
+ if processes.empty?
32
+ puts "No processes found on port(s): #{ports.join(', ')}"
33
+ else
34
+ processes.each { |p| puts "#{p.pid}\t#{p.dir || '(unknown)'}" }
35
+ end
36
+ }
37
+
23
38
  add_subcmd(:search) { |pattern = nil|
24
39
  if pattern.nil?
25
40
  puts "Usage: h ps search <pattern>"
@@ -54,6 +54,22 @@ class Hiiro::PsProcess
54
54
  all.find { |p| p.pid == pid.to_s }
55
55
  end
56
56
 
57
+ # Find processes listening on given port numbers
58
+ def self.by_port(*ports)
59
+ pids = Set.new
60
+ ports.each do |port|
61
+ lsof_output = `lsof -i :#{port.to_i} 2>/dev/null`.lines[1..]
62
+ next unless lsof_output
63
+
64
+ lsof_output.each do |line|
65
+ fields = line.split
66
+ pids << fields[1] if fields[1]
67
+ end
68
+ end
69
+
70
+ all.select { |p| pids.include?(p.pid) }
71
+ end
72
+
57
73
  # Find processes with files open in given directories
58
74
  def self.in_dirs(*paths)
59
75
  pids = Set.new
data/lib/hiiro/tasks.rb CHANGED
@@ -964,6 +964,22 @@ class Hiiro
964
964
  end
965
965
  end
966
966
 
967
+ # If still no task/session found, check ~/proj/* directories by prefix
968
+ unless task
969
+ proj_dirs = Dir.glob(File.expand_path('~/proj/*/'))
970
+ dir_names = proj_dirs.map { |d| File.basename(d) }
971
+ result = Hiiro::Matcher.by_prefix(dir_names, task_name)
972
+ if result.one?
973
+ dir_name = result.first.item
974
+ h.start_tmux_session(dir_name, start_directory: File.expand_path("~/proj/#{dir_name}"))
975
+ puts "Switched to ~/proj/#{dir_name}"
976
+ next
977
+ elsif result.ambiguous?
978
+ puts "Ambiguous match for '#{task_name}': #{result.matches.map(&:item).join(', ')}"
979
+ exit 1
980
+ end
981
+ end
982
+
967
983
  tm.switch_to_task(task, app_name: app_name, force: opts.force)
968
984
  end
969
985
 
data/lib/hiiro/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Hiiro
2
- VERSION = "0.1.338"
2
+ VERSION = "0.1.340"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiiro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.338
4
+ version: 0.1.340
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Toyota