hiiro 0.1.211 → 0.1.212

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: 93161b29e527a19a17c9e478558ab0d33a925e27ac04851151d4d86fd1f59f49
4
- data.tar.gz: 775639bdc0be84af6ea30e8edf33251c5ed769614e51c59c12ab1c681be33ebc
3
+ metadata.gz: 595b4d37c446a020b8c28e0698d57f918844638f564a13fbb5cc1eaf63ac8ae1
4
+ data.tar.gz: 85dee985c6307a9e9d818d4bec6be82b8f2b6dea4192ad3ac948548070ffecf0
5
5
  SHA512:
6
- metadata.gz: 30c25c505dc5bfcc956a3be84245f3c3a680f6fe326963083a101f41781cb8a4437fa94d5655cb99fe40a9b0a051b9db73c3eeac3bf1fbbe4f42c2011f4dace2
7
- data.tar.gz: e09c57d45a81c8c2334ab779d96da3ce024ad01904213895d874889697cc26ec6773d8f1589d43cc192a15a99d9da97d206215e725494af92ce6cbf4398bfb2b
6
+ metadata.gz: 9cdd2c615aa42d82551f50fc00c97166f90f6c6918e888daf0570897eb036d6a251d20c96f46160744dae06d01035daca31ed65532a516249bdb5af4a263d1e2
7
+ data.tar.gz: c74ad66f0945e8689e6f0d414365d4760c16d6115d67566fece2848f683d88b328bb614101b2b5a704d2a1e591e160c890f82b84cd30e10c7ef7bda2b5d98d54
data/bin/h-pr CHANGED
@@ -9,168 +9,6 @@ require "tempfile"
9
9
 
10
10
  Hiiro.load_env
11
11
 
12
- class PRManager
13
- attr_reader :hiiro
14
-
15
- def initialize(hiiro)
16
- @hiiro = hiiro
17
- end
18
-
19
- def save(pr_number = nil)
20
- pr_info = fetch_pr_info(pr_number)
21
- unless pr_info
22
- puts "ERROR: Could not find PR"
23
- puts "Make sure you have the gh CLI installed and authenticated."
24
- return false
25
- end
26
-
27
- entry = build_entry(pr_info)
28
- unless entry[:task]
29
- puts "WARNING: Not in a task session, saving without task info"
30
- end
31
-
32
- data = load_data
33
- data['prs'] ||= []
34
-
35
- # Check if this PR is already recorded for this task
36
- existing = data['prs'].find do |p|
37
- p['number'] == pr_info['number'] && p['task'] == entry[:task]
38
- end
39
-
40
- if existing
41
- # Update existing entry
42
- existing.merge!(entry.transform_keys(&:to_s))
43
- existing['updated_at'] = Time.now.iso8601
44
- puts "Updated PR ##{pr_info['number']} for task '#{entry[:task]}'"
45
- else
46
- # Add new entry
47
- data['prs'] << entry.transform_keys(&:to_s).merge('created_at' => Time.now.iso8601)
48
- puts "Saved PR ##{pr_info['number']} for task '#{entry[:task]}'"
49
- end
50
-
51
- save_data(data)
52
- show_entry(entry)
53
- true
54
- end
55
-
56
- def current
57
- pr_info = fetch_pr_info
58
- unless pr_info
59
- puts "No PR found for current branch."
60
- puts "Create one with 'gh pr create' or specify a PR number."
61
- return false
62
- end
63
-
64
- entry = build_entry(pr_info)
65
- puts "Current PR info:"
66
- puts
67
- show_entry(entry)
68
- end
69
-
70
- def open(pr_number = nil)
71
- if pr_number
72
- system('gh', 'pr', 'view', pr_number.to_s, '--web')
73
- else
74
- system('gh', 'pr', 'view', '--web')
75
- end
76
- end
77
-
78
- def view(pr_number = nil)
79
- if pr_number
80
- system('gh', 'pr', 'view', pr_number.to_s)
81
- else
82
- system('gh', 'pr', 'view')
83
- end
84
- end
85
-
86
- private
87
-
88
- def fetch_pr_info(pr_number = nil)
89
- cmd = if pr_number
90
- ['gh', 'pr', 'view', pr_number.to_s, '--json', 'number,title,url,headRefName,state']
91
- else
92
- ['gh', 'pr', 'view', '--json', 'number,title,url,headRefName,state']
93
- end
94
-
95
- output = `#{cmd.join(' ')} 2>/dev/null`
96
- return nil if output.empty?
97
-
98
- JSON.parse(output)
99
- rescue JSON::ParserError
100
- nil
101
- end
102
-
103
- def build_entry(pr_info)
104
- current_task = Environment.current.task
105
- tmux_info = capture_tmux_info
106
-
107
- {
108
- number: pr_info['number'],
109
- title: pr_info['title'],
110
- url: pr_info['url'],
111
- branch: pr_info['headRefName'],
112
- state: pr_info['state'],
113
- worktree: current_task&.tree_name,
114
- task: current_task&.name,
115
- tmux: tmux_info
116
- }
117
- end
118
-
119
- def capture_tmux_info
120
- return nil unless ENV['TMUX']
121
-
122
- {
123
- 'session' => `tmux display-message -p '#S'`.strip,
124
- 'window' => `tmux display-message -p '#W'`.strip,
125
- 'pane' => ENV['TMUX_PANE']
126
- }
127
- end
128
-
129
- def format_entry(entry, num)
130
- lines = []
131
- lines << "#{num}. PR ##{entry['number']}: #{entry['title']}"
132
- lines << " Branch: #{entry['branch']}"
133
- lines << " State: #{entry['state']}"
134
- lines << " Task: #{entry['task'] || '(none)'}"
135
- lines << " Worktree: #{entry['worktree'] || '(none)'}"
136
- if entry['tmux']
137
- lines << " Tmux: #{entry['tmux']['session']}/#{entry['tmux']['window']}"
138
- end
139
- lines << " Created: #{entry['created_at']}"
140
- lines << " URL: #{entry['url']}"
141
- lines.join("\n")
142
- end
143
-
144
- def show_entry(entry)
145
- puts " PR: ##{entry[:number]}"
146
- puts " Title: #{entry[:title]}"
147
- puts " Branch: #{entry[:branch]}"
148
- puts " State: #{entry[:state]}"
149
- puts " URL: #{entry[:url]}"
150
- puts " Task: #{entry[:task] || '(none)'}"
151
- puts " Worktree: #{entry[:worktree] || '(none)'}"
152
- if entry[:tmux]
153
- puts " Tmux session: #{entry[:tmux]['session']}"
154
- puts " Tmux window: #{entry[:tmux]['window']}"
155
- puts " Tmux pane: #{entry[:tmux]['pane']}"
156
- end
157
- end
158
-
159
- def data_file
160
- File.join(Dir.home, '.config', 'hiiro', 'prs.yml')
161
- end
162
-
163
- def load_data
164
- return {} unless File.exist?(data_file)
165
- YAML.safe_load_file(data_file) || {}
166
- end
167
-
168
- def save_data(data)
169
- FileUtils.mkdir_p(File.dirname(data_file))
170
- File.write(data_file, YAML.dump(data))
171
- end
172
- end
173
-
174
12
  class PinnedPRManager
175
13
  PINNED_FILE = File.join(Dir.home, '.config/hiiro/pinned_prs.yml')
176
14
 
@@ -618,14 +456,13 @@ class PinnedPRManager
618
456
  end
619
457
 
620
458
  Hiiro.run(*ARGV, plugins: [Pins]) do
621
- manager = PRManager.new(self)
622
459
  pinned_manager = PinnedPRManager.new
623
460
 
624
461
  resolve_pr = ->(ref) {
625
462
  if ref.nil?
626
463
  pinned = pinned_manager.load_pinned
627
464
  if pinned.empty?
628
- STDERR.puts "No pinned PRs. Use a PR number or 'h pr pin' to track PRs."
465
+ STDERR.puts "No tracked PRs. Use a PR number or 'h pr track' to track PRs."
629
466
  return nil
630
467
  end
631
468
  lines = pinned.each_with_index.each_with_object({}) do |(pr, idx), h|
@@ -724,15 +561,13 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
724
561
  }
725
562
 
726
563
  add_subcmd(:edit) { edit_files(__FILE__) }
727
- add_subcmd(:save) { |pr_number=nil| manager.save(pr_number) }
728
- add_subcmd(:current) { manager.current }
729
564
  add_subcmd(:open) { |pr_number=nil|
730
565
  pr_number = resolve_pr.call(pr_number)
731
- manager.open(pr_number) if pr_number
566
+ system('gh', 'pr', 'view', pr_number.to_s, '--web') if pr_number
732
567
  }
733
568
  add_subcmd(:view) { |pr_number=nil|
734
569
  pr_number = resolve_pr.call(pr_number)
735
- manager.view(pr_number) if pr_number
570
+ system('gh', 'pr', 'view', pr_number.to_s) if pr_number
736
571
  }
737
572
 
738
573
  add_subcmd(:select) do |*args|
@@ -789,107 +624,68 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
789
624
  end
790
625
  end
791
626
 
792
- # === PR Pinning ===
627
+ # === PR Tracking ===
793
628
 
794
- add_subcmd(:pin) do |ref = nil, *pin_args|
629
+ add_subcmd(:track) do |ref = nil|
795
630
  pr_info = nil
796
631
 
797
632
  case ref
798
- when '-', nil
799
- if ref == '-'
800
- # Pin current branch's PR
801
- pr_info = pinned_manager.fetch_current_branch_pr
802
- unless pr_info
803
- puts "No PR found for current branch"
804
- next
805
- end
806
- else
807
- # Select from my PRs
808
- my_prs = pinned_manager.fetch_my_prs
809
- if my_prs.empty?
810
- puts "No open PRs found"
811
- next
812
- end
633
+ when nil
634
+ # Select from my open PRs
635
+ my_prs = pinned_manager.fetch_my_prs
636
+ if my_prs.empty?
637
+ puts "No open PRs found"
638
+ next
639
+ end
813
640
 
814
- lines = my_prs.each_with_object({}) do |pr, h|
815
- display = "##{pr['number']} [#{pr['headRefName']}] #{pr['title']}"
816
- h[display] = pr
817
- end
641
+ lines = my_prs.each_with_object({}) do |pr, h|
642
+ display = "##{pr['number']} [#{pr['headRefName']}] #{pr['title']}"
643
+ h[display] = pr
644
+ end
818
645
 
819
- pr_info = fuzzyfind_from_map(lines)
820
- unless pr_info
821
- puts "No PR selected"
822
- next
823
- end
646
+ pr_info = fuzzyfind_from_map(lines)
647
+ unless pr_info
648
+ puts "No PR selected"
649
+ next
650
+ end
651
+ when '-'
652
+ # Track current branch's PR
653
+ pr_info = pinned_manager.fetch_current_branch_pr
654
+ unless pr_info
655
+ puts "No PR found for current branch"
656
+ next
824
657
  end
825
658
  when /^\d+$/
826
- # Pin by PR number
659
+ # Track by PR number
827
660
  pr_info = pinned_manager.fetch_pr_info(ref)
828
661
  unless pr_info
829
662
  puts "PR ##{ref} not found"
830
663
  next
831
664
  end
832
665
  else
833
- puts "Usage: h pr pin [-|PR_NUMBER]"
834
- puts " - Pin current branch's PR"
835
- puts " <num> Pin PR by number"
666
+ puts "Usage: h pr track [-|PR_NUMBER]"
667
+ puts " - Track current branch's PR"
668
+ puts " <num> Track PR by number"
836
669
  puts " (none) Select from your open PRs"
837
670
  next
838
671
  end
839
672
 
840
- pinned_manager.pin(pr_info)
841
- puts "Pinned PR ##{pr_info['number']}: #{pr_info['title']}"
842
- end
843
-
844
- add_subcmd(:unpin) do |ref = nil, *unpin_args|
845
- pinned = pinned_manager.load_pinned
846
-
847
- if pinned.empty?
848
- puts "No pinned PRs"
849
- next
850
- end
851
-
852
- pr_number = nil
853
-
854
- if ref.nil?
855
- # Select from pinned PRs
856
- lines = pinned.each_with_index.each_with_object({}) do |(pr, idx), h|
857
- h[pinned_manager.display_pinned(pr, idx)] = pr['number'].to_s
858
- end
859
-
860
- pr_number = fuzzyfind_from_map(lines)
861
- unless pr_number
862
- puts "No PR selected"
863
- next
864
- end
865
- elsif ref =~ /^\d+$/
866
- pr_number = ref
867
- else
868
- puts "Usage: h pr unpin [PR_NUMBER]"
673
+ if pinned_manager.pinned?(pr_info['number'])
674
+ puts "Already tracking ##{pr_info['number']}"
869
675
  next
870
676
  end
871
677
 
872
- if pinned_manager.unpin(pr_number)
873
- puts "Unpinned PR ##{pr_number}"
874
- else
875
- puts "PR ##{pr_number} was not pinned"
678
+ context = {}
679
+ env = Environment.current rescue nil
680
+ if env
681
+ task = env.task
682
+ context['task'] = task.name if task
683
+ context['worktree'] = task.tree_name if task&.tree_name
684
+ context['tmux_session'] = env.session&.name
876
685
  end
877
- end
878
686
 
879
- add_subcmd(:pinned) do |*args|
880
- pinned = pinned_manager.load_pinned
881
-
882
- if pinned.empty?
883
- puts "No pinned PRs"
884
- next
885
- end
886
-
887
- puts "Pinned PRs:"
888
- puts
889
-
890
- pinned.each_with_index do |pr, idx|
891
- puts pinned_manager.display_pinned(pr, idx)
892
- end
687
+ pinned_manager.pin(pr_info.merge(context))
688
+ puts "Now tracking ##{pr_info['number']}: #{pr_info['title']}"
893
689
  end
894
690
 
895
691
  add_subcmd(:ls) do |*ls_args|
@@ -898,7 +694,7 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
898
694
  pinned = pinned_manager.load_pinned
899
695
 
900
696
  if pinned.empty?
901
- puts "No pinned PRs"
697
+ puts "No tracked PRs"
902
698
  next
903
699
  end
904
700
 
@@ -922,19 +718,13 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
922
718
  pinned = pinned_manager.load_pinned
923
719
 
924
720
  if pinned.empty?
925
- puts "No pinned PRs"
721
+ puts "No tracked PRs"
926
722
  next
927
723
  end
928
724
 
929
- compact = status_args.include?('-c') || status_args.include?('--compact')
930
-
931
725
  pinned.each_with_index do |pr, idx|
932
- if compact
933
- puts pinned_manager.display_pinned(pr, idx)
934
- else
935
- puts pinned_manager.display_detailed(pr, idx)
936
- puts
937
- end
726
+ puts pinned_manager.display_detailed(pr, idx)
727
+ puts
938
728
  end
939
729
 
940
730
  last_checked = pinned.filter_map { |pr| pr['last_checked'] }.max
@@ -946,7 +736,7 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
946
736
  pinned = pinned_manager.load_pinned
947
737
 
948
738
  if pinned.empty?
949
- puts "No pinned PRs to update"
739
+ puts "No tracked PRs to update"
950
740
  next
951
741
  end
952
742
 
@@ -1014,11 +804,10 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
1014
804
  end
1015
805
 
1016
806
  add_subcmd(:prune) do |*args|
1017
- # Alias to auto-unpin
1018
807
  pinned = pinned_manager.load_pinned
1019
808
 
1020
809
  if pinned.empty?
1021
- puts "No pinned PRs"
810
+ puts "No tracked PRs"
1022
811
  next
1023
812
  end
1024
813
 
@@ -1212,25 +1001,7 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
1212
1001
  system('tmux', 'switch-client', '-t', target_session)
1213
1002
  end
1214
1003
 
1215
- add_subcmd(:track) do
1216
- pr_info = pinned_manager.fetch_current_branch_pr
1217
- unless pr_info
1218
- puts "No PR for current branch"
1219
- next
1220
- end
1221
-
1222
- if pinned_manager.pinned?(pr_info['number'])
1223
- puts "Already tracking ##{pr_info['number']}"
1224
- next
1225
- end
1226
-
1227
- full_info = pinned_manager.fetch_pr_info(pr_info['number'])
1228
- pinned_manager.pin(full_info)
1229
- puts "Now tracking ##{pr_info['number']}: #{pr_info['title']}"
1230
- end
1231
-
1232
- add_subcmd(:ignore) do |ref = nil|
1233
- # Alias to unpin
1004
+ add_subcmd(:rm) do |ref = nil|
1234
1005
  pinned = pinned_manager.load_pinned
1235
1006
 
1236
1007
  if pinned.empty?
@@ -1253,103 +1024,165 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
1253
1024
  elsif ref =~ /^\d+$/
1254
1025
  pr_number = ref
1255
1026
  else
1256
- puts "Usage: h pr ignore [PR_NUMBER]"
1027
+ puts "Usage: h pr rm [PR_NUMBER]"
1257
1028
  next
1258
1029
  end
1259
1030
 
1260
1031
  if pinned_manager.unpin(pr_number)
1261
- puts "Stopped tracking PR ##{pr_number}"
1032
+ puts "Removed PR ##{pr_number} from tracking"
1262
1033
  else
1263
1034
  puts "PR ##{pr_number} was not tracked"
1264
1035
  end
1265
1036
  end
1266
1037
 
1267
- add_subcmd(:rm) do |ref = nil|
1268
- # Alias to ignore/unpin
1269
- pinned = pinned_manager.load_pinned
1038
+ # === PR State ===
1270
1039
 
1271
- if pinned.empty?
1272
- puts "No tracked PRs"
1040
+ add_subcmd(:ready) do |ref = nil|
1041
+ pr_number = resolve_pr.call(ref)
1042
+ next unless pr_number
1043
+ system('gh', 'pr', 'ready', pr_number.to_s)
1044
+ end
1045
+
1046
+ add_subcmd(:'to-draft') do |ref = nil|
1047
+ pr_number = resolve_pr.call(ref)
1048
+ next unless pr_number
1049
+ system('gh', 'pr', 'ready', '--draft', pr_number.to_s)
1050
+ end
1051
+
1052
+ # === PR Actions ===
1053
+
1054
+ add_subcmd(:diff) do |ref = nil|
1055
+ pr_number = resolve_pr.call(ref)
1056
+ next unless pr_number
1057
+ system('gh', 'pr', 'diff', pr_number.to_s)
1058
+ end
1059
+
1060
+ add_subcmd(:checkout) do |ref = nil|
1061
+ pr_number = resolve_pr.call(ref)
1062
+ next unless pr_number
1063
+ system('gh', 'pr', 'checkout', pr_number.to_s)
1064
+ end
1065
+
1066
+ add_subcmd(:merge) do |ref = nil, *merge_args|
1067
+ pr_number = resolve_pr.call(ref)
1068
+ next unless pr_number
1069
+ system('gh', 'pr', 'merge', pr_number.to_s, *merge_args)
1070
+ end
1071
+
1072
+ add_subcmd(:comment) do |ref = nil|
1073
+ pr_number = resolve_pr.call(ref)
1074
+ next unless pr_number
1075
+
1076
+ tmpfile = Tempfile.new(['pr-comment-', '.md'])
1077
+ tmpfile.close
1078
+ edit_files(tmpfile.path)
1079
+
1080
+ body = File.read(tmpfile.path).strip
1081
+ tmpfile.unlink
1082
+
1083
+ if body.empty?
1084
+ puts "Aborted: empty comment"
1273
1085
  next
1274
1086
  end
1275
1087
 
1276
- pr_number = nil
1088
+ system('gh', 'pr', 'comment', pr_number.to_s, '--body', body)
1089
+ end
1277
1090
 
1278
- if ref.nil?
1279
- lines = pinned.each_with_index.each_with_object({}) do |(pr, idx), h|
1280
- h[pinned_manager.display_pinned(pr, idx)] = pr['number'].to_s
1281
- end
1091
+ # === Comment Templates ===
1282
1092
 
1283
- pr_number = fuzzyfind_from_map(lines)
1284
- unless pr_number
1285
- puts "No PR selected"
1286
- next
1287
- end
1288
- elsif ref =~ /^\d+$/
1289
- pr_number = ref
1290
- else
1291
- puts "Usage: h pr rm [PR_NUMBER]"
1093
+ TEMPLATES_DIR = File.join(Dir.home, '.config', 'hiiro', 'pr_templates')
1094
+
1095
+ add_subcmd(:templates) do
1096
+ FileUtils.mkdir_p(TEMPLATES_DIR)
1097
+ files = Dir.glob(File.join(TEMPLATES_DIR, '*.md')).sort
1098
+
1099
+ if files.empty?
1100
+ puts "No templates found. Use 'h pr new-template <name>' to create one."
1292
1101
  next
1293
1102
  end
1294
1103
 
1295
- if pinned_manager.unpin(pr_number)
1296
- puts "Removed PR ##{pr_number} from tracking"
1297
- else
1298
- puts "PR ##{pr_number} was not tracked"
1104
+ puts "Comment templates:"
1105
+ puts
1106
+ files.each do |f|
1107
+ name = File.basename(f, '.md')
1108
+ first_line = File.readlines(f).first&.strip || ''
1109
+ puts " #{name.ljust(20)} #{first_line}"
1299
1110
  end
1300
1111
  end
1301
1112
 
1302
- add_subcmd(:'suggest-unpin') do |*args|
1303
- pinned = pinned_manager.load_pinned
1113
+ add_subcmd(:'new-template') do |name = nil|
1114
+ FileUtils.mkdir_p(TEMPLATES_DIR)
1304
1115
 
1305
- if pinned.empty?
1306
- puts "No pinned PRs"
1116
+ unless name
1117
+ STDERR.puts "Usage: h pr new-template <name>"
1307
1118
  next
1308
1119
  end
1309
1120
 
1310
- merged = pinned.select { |pr| pr['state'] == 'MERGED' }
1311
- closed = pinned.select { |pr| pr['state'] == 'CLOSED' }
1121
+ path = File.join(TEMPLATES_DIR, "#{name}.md")
1312
1122
 
1313
- if merged.empty? && closed.empty?
1314
- puts "No merged or closed PRs to unpin"
1315
- next
1123
+ if File.exist?(path)
1124
+ puts "Template '#{name}' already exists, opening for edit..."
1316
1125
  end
1317
1126
 
1318
- puts "PRs that can be unpinned:"
1319
- puts
1127
+ edit_files(path)
1128
+ puts "Template saved: #{path}"
1129
+ end
1320
1130
 
1321
- (merged + closed).each_with_index do |pr, idx|
1322
- puts pinned_manager.display_pinned(pr, idx)
1131
+ add_subcmd(:'from-template') do |ref = nil|
1132
+ FileUtils.mkdir_p(TEMPLATES_DIR)
1133
+ files = Dir.glob(File.join(TEMPLATES_DIR, '*.md')).sort
1134
+
1135
+ if files.empty?
1136
+ STDERR.puts "No templates found. Use 'h pr new-template <name>' to create one."
1137
+ next
1323
1138
  end
1324
1139
 
1325
- puts
1326
- puts "Run 'h pr auto-unpin' to unpin all merged/closed PRs"
1140
+ template_map = files.each_with_object({}) do |f, h|
1141
+ name = File.basename(f, '.md')
1142
+ first_line = File.readlines(f).first&.strip || ''
1143
+ h["#{name.ljust(20)} #{first_line}"] = f
1144
+ end
1145
+
1146
+ template_path = fuzzyfind_from_map(template_map)
1147
+ next unless template_path
1148
+
1149
+ pr_number = resolve_pr.call(ref)
1150
+ next unless pr_number
1151
+
1152
+ body = File.read(template_path).strip
1153
+ system('gh', 'pr', 'comment', pr_number.to_s, '--body', body)
1327
1154
  end
1328
1155
 
1329
- add_subcmd(:'auto-unpin') do |*args|
1330
- pinned = pinned_manager.load_pinned
1156
+ # === PR List by Context ===
1331
1157
 
1332
- if pinned.empty?
1333
- puts "No pinned PRs"
1158
+ add_subcmd(:'for-task') do |task_name = nil|
1159
+ tracked = pinned_manager.load_pinned
1160
+
1161
+ if tracked.empty?
1162
+ puts "No tracked PRs"
1334
1163
  next
1335
1164
  end
1336
1165
 
1337
- merged_or_closed = pinned.select { |pr| pr['state'] == 'MERGED' || pr['state'] == 'CLOSED' }
1166
+ task_name ||= begin
1167
+ env = Environment.current rescue nil
1168
+ env&.task&.name
1169
+ end
1338
1170
 
1339
- if merged_or_closed.empty?
1340
- puts "No merged or closed PRs to unpin"
1171
+ unless task_name
1172
+ STDERR.puts "Not in a task context. Pass a task name: h pr for-task <name>"
1341
1173
  next
1342
1174
  end
1343
1175
 
1344
- puts "Unpinning #{merged_or_closed.length} merged/closed PR(s):"
1345
- puts
1176
+ matches = tracked.select { |pr| pr['task'] == task_name }
1346
1177
 
1347
- merged_or_closed.each do |pr|
1348
- puts " ##{pr['number']}: #{pr['title']} [#{pr['state']}]"
1349
- pinned_manager.unpin(pr['number'])
1178
+ if matches.empty?
1179
+ puts "No tracked PRs for task '#{task_name}'"
1180
+ next
1350
1181
  end
1351
1182
 
1183
+ puts "PRs for task '#{task_name}':"
1352
1184
  puts
1353
- puts "Done. #{pinned_manager.load_pinned.length} PR(s) still pinned."
1185
+ matches.each_with_index { |pr, i| puts pinned_manager.display_pinned(pr, i) }
1354
1186
  end
1187
+
1355
1188
  end
data/lib/hiiro/queue.rb CHANGED
@@ -238,7 +238,7 @@ class Hiiro
238
238
 
239
239
  mapping = tasks.each_with_object({}) do |task, h|
240
240
  line = format("%-25s tree: %-20s", task.name, task.tree_name || '(none)')
241
- h[line] = task.name
241
+ h[line] = task
242
242
  end
243
243
 
244
244
  hiiro.fuzzyfind_from_map(mapping)
@@ -246,7 +246,7 @@ class Hiiro
246
246
 
247
247
  def resolve_task_info(opts, hiiro, default_task_info)
248
248
  task_name = if opts.choose
249
- select_task(hiiro)
249
+ select_task(hiiro)&.name
250
250
  elsif opts.task
251
251
  opts.task
252
252
  else
@@ -322,7 +322,7 @@ class Hiiro
322
322
  parent_hiiro.make_child do |h|
323
323
  h.add_subcmd(:watch) {
324
324
  q.queue_dirs
325
- current_version = Gem.loaded_specs['hiiro']&.version&.to_s
325
+ current_version = `gem which hiiro`.sub(/.*hiiro-/, '').sub(/\/.*/, '')
326
326
  puts current_version:;
327
327
  puts "Watching #{File.join(DIR, 'pending')} ..."
328
328
  puts "Press Ctrl-C to stop"
@@ -330,8 +330,8 @@ class Hiiro
330
330
  loop do
331
331
  loops += 1
332
332
  if current_version
333
- latest = Gem::Specification.find_by_name('hiiro')&.version&.to_s rescue nil
334
- if loops % 50 == 0
333
+ latest = `gem which hiiro`.sub(/.*hiiro-/, '').sub(/\/.*/, '') rescue nil
334
+ if loops % 20 == 0
335
335
  puts current_version:, latest:;
336
336
  end
337
337
 
data/lib/hiiro/tasks.rb CHANGED
@@ -401,10 +401,9 @@ class Hiiro
401
401
  branch_col = all_data.map { |_, d| d[:branch].length }.max || 0
402
402
 
403
403
  all_data.each do |task, d|
404
- display_name = scope == :subtask ? task.short_name : task.name
405
404
  line = format("%-#{name_col}s %-#{tree_col}s %-#{branch_col}s %s",
406
405
  d[:name], d[:tree], d[:branch], d[:session])
407
- mapping[line] = { type: :task, name: display_name }
406
+ mapping[line] = task
408
407
  end
409
408
 
410
409
  # Add non-task tmux sessions (exclude sessions that belong to tasks)
@@ -413,7 +412,7 @@ class Hiiro
413
412
  extra_sessions = environment.all_sessions.reject { |s| task_session_names.include?(s.name) }
414
413
  extra_sessions.sort_by(&:name).each do |session|
415
414
  line = format("%-25s (tmux session)", session.name)
416
- mapping[line] = { type: :session, name: session.name }
415
+ mapping[line] = session
417
416
  end
418
417
  end
419
418
 
@@ -623,16 +622,14 @@ class Hiiro
623
622
  selected = tm.select_task_interactive
624
623
  next unless selected
625
624
 
626
- if selected.is_a?(Hash)
627
- if selected[:type] == :session
628
- h.start_tmux_session(selected[:name])
629
- puts "Switched to session '#{selected[:name]}'"
630
- next
631
- else
632
- task_name = selected[:name]
633
- end
634
- else
635
- task_name = selected
625
+ case selected
626
+ when Hiiro::Tmux::Session
627
+ h.start_tmux_session(selected.name)
628
+ puts "Switched to session '#{selected.name}'"
629
+ next
630
+ when Hiiro::Task
631
+ tm.switch_to_task(selected, app_name: app_name)
632
+ next
636
633
  end
637
634
  end
638
635
 
@@ -713,9 +710,9 @@ class Hiiro
713
710
 
714
711
  h.add_subcmd(:stop) do |task_name=nil|
715
712
  if task_name.nil?
716
- task_name = tm.select_task_interactive
717
- next unless task_name
718
- task_name = task_name[:name]
713
+ selected = tm.select_task_interactive
714
+ next unless selected
715
+ task_name = selected.name
719
716
  end
720
717
  task = tm.task_by_name(task_name)
721
718
  tm.stop_task(task)
data/lib/hiiro/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Hiiro
2
- VERSION = "0.1.211"
2
+ VERSION = "0.1.212"
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.211
4
+ version: 0.1.212
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Toyota