hiiro 0.1.234 → 0.1.236

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/h-pr +95 -6
  3. data/lib/hiiro/version.rb +1 -1
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8460afefae6d7bd3f6ba3d2fb8f71a11b6c78afab3056bc103e3ed3c7a20eba1
4
- data.tar.gz: ec62d0166213c073e62040fa456732e1b75cd3060a0d76ee2061bd921fa69047
3
+ metadata.gz: 57a61c731baafeb477c3f8a1acca82b825ec432019744221b87721bce49d0da3
4
+ data.tar.gz: b51a6debe29e2b95b4fd0f489bf905e041637c06ec971ec73d8cf09ae204bc3a
5
5
  SHA512:
6
- metadata.gz: 211bafbcf686e09654a3b983cb99fb8327f43273b89bb0e9a9c1c52971572f17eb8fafc4b95bcb96b3ff182b83e65218a3aa62df05b2ef75e2b3be390c1adfc8
7
- data.tar.gz: feaa58f7885e1b8ecc0fc3f06f4b8e40b4f1f1b319ae37110772544f96abfb6ba1197d18966f6af4540dafadf3122fdcea2abcb0409470e514291ec1c23e49f7
6
+ metadata.gz: a3e55905cbfc8c4f80d28fd3b4cfdfc04c5cf7566e20efb091a9ed945d0aa45907d45b085d3828506f20d43a07eb79e7991af6f9adb47b0ed197a6474ee66934
7
+ data.tar.gz: 3ecc52af4a2d7d822a10df2e78a994929280640cbe76ac7badd1039911cf54784437bbbb2961065972b0ad06e61c950dc092e3cd031c482f831919258e7a4965
data/bin/h-pr CHANGED
@@ -295,7 +295,7 @@ class PinnedPRManager
295
295
  drafts: ->(pr) { pr['is_draft'] == true },
296
296
  pending: ->(pr) { (c = pr['checks']) && c['pending'].to_i > 0 && c['failed'].to_i == 0 },
297
297
  merged: ->(pr) { pr['state'] == 'MERGED' },
298
- open: ->(pr) { pr['state'] != 'MERGED' && pr['state'] != 'CLOSED' },
298
+ active: ->(pr) { pr['state'] != 'MERGED' && pr['state'] != 'CLOSED' },
299
299
  }.freeze
300
300
 
301
301
  def summarize_checks(rollup)
@@ -384,18 +384,30 @@ class PinnedPRManager
384
384
  repo = pr_repo(pr)
385
385
  repo_label = (repo && repo != 'instacart/carrot') ? " [#{repo}]" : ""
386
386
 
387
- "#{num} #{state_icon} #{reviews_str} ##{pr['number']}#{repo_label} #{pr['title']}".strip
387
+ tags = Array(pr['tags'])
388
+ tags_str = tags.any? ? " " + tags.map { |t| "\e[30;104m#{t}\e[0m" }.join(' ') : ""
389
+
390
+ "#{num} #{state_icon} #{reviews_str} ##{pr['number']}#{repo_label}#{tags_str} #{pr['title']}".strip
388
391
  end
389
392
 
390
393
  def filter_active?(opts)
391
- FILTER_PREDICATES.keys.any? { |f| opts.respond_to?(f) && opts.send(f) }
394
+ FILTER_PREDICATES.keys.any? { |f| opts.respond_to?(f) && opts.send(f) } ||
395
+ (opts.respond_to?(:tag) && opts.tag)
392
396
  end
393
397
 
394
398
  def apply_filters(prs, opts, forced: [])
395
399
  active = FILTER_PREDICATES.keys.select { |f| opts.respond_to?(f) && opts.send(f) }
396
400
  active = (active + forced).uniq
397
- return prs if active.empty?
398
- prs.select { |pr| active.any? { |f| FILTER_PREDICATES[f]&.call(pr) } }
401
+
402
+ results = active.empty? ? prs : prs.select { |pr| active.any? { |f| FILTER_PREDICATES[f]&.call(pr) } }
403
+
404
+ # Tag is an AND post-filter — narrows whatever the flag filters returned
405
+ if opts.respond_to?(:tag) && opts.tag
406
+ tag = opts.tag.to_s
407
+ results = results.select { |pr| Array(pr['tags']).include?(tag) }
408
+ end
409
+
410
+ results
399
411
  end
400
412
 
401
413
  def display_detailed(pr, idx = nil)
@@ -474,8 +486,9 @@ FILTER_OPTS = Proc.new {
474
486
  flag(:drafts, short: 'd', desc: 'filter: draft PRs')
475
487
  flag(:pending, short: 'p', desc: 'filter: pending checks')
476
488
  flag(:merged, short: 'm', desc: 'filter: merged PRs')
477
- flag(:open, short: 'o', desc: 'filter: open (non-merged) PRs')
489
+ flag(:active, short: 'o', desc: 'filter: open (non-merged) PRs')
478
490
  flag(:numbers, short: 'n', desc: 'output PR numbers only (no #)')
491
+ option(:tag, short: 't', desc: 'filter by tag (AND with other filters)')
479
492
  }
480
493
 
481
494
  Hiiro.run(*ARGV, plugins: [Pins]) do
@@ -729,6 +742,11 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
729
742
  instance_eval(&FILTER_OPTS)
730
743
  }
731
744
 
745
+ if opts.help
746
+ puts opts.help_text
747
+ exit 1
748
+ end
749
+
732
750
  pinned = pinned_manager.load_pinned
733
751
  next puts "No tracked PRs" if pinned.empty?
734
752
 
@@ -1312,6 +1330,77 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
1312
1330
  matches.each_with_index { |pr, i| puts pinned_manager.display_pinned(pr, i) }
1313
1331
  end
1314
1332
 
1333
+ # === Tags ===
1334
+
1335
+ add_subcmd(:tag) do |ref = nil, *tag_names|
1336
+ if ref.nil? || tag_names.empty?
1337
+ puts "Usage: h pr tag <ref> <tag> [tag2 ...]"
1338
+ next
1339
+ end
1340
+
1341
+ pr_number = resolve_pr.call(ref)
1342
+ next unless pr_number
1343
+
1344
+ pinned = pinned_manager.load_pinned
1345
+ pr = pinned.find { |p| p['number'].to_s == pr_number.to_s }
1346
+ unless pr
1347
+ puts "PR ##{pr_number} not in tracked list"
1348
+ next
1349
+ end
1350
+
1351
+ pr['tags'] = (Array(pr['tags']) + tag_names).uniq
1352
+ pinned_manager.save_pinned(pinned)
1353
+ puts "Tagged ##{pr_number} with: #{tag_names.join(', ')}"
1354
+ puts " Tags now: #{pr['tags'].join(', ')}"
1355
+ end
1356
+
1357
+ add_subcmd(:untag) do |ref = nil, *tag_names|
1358
+ if ref.nil?
1359
+ puts "Usage: h pr untag <ref> [tag ...] (omit tags to clear all)"
1360
+ next
1361
+ end
1362
+
1363
+ pr_number = resolve_pr.call(ref)
1364
+ next unless pr_number
1365
+
1366
+ pinned = pinned_manager.load_pinned
1367
+ pr = pinned.find { |p| p['number'].to_s == pr_number.to_s }
1368
+ unless pr
1369
+ puts "PR ##{pr_number} not in tracked list"
1370
+ next
1371
+ end
1372
+
1373
+ if tag_names.empty?
1374
+ pr.delete('tags')
1375
+ puts "Cleared all tags from ##{pr_number}"
1376
+ else
1377
+ pr['tags'] = Array(pr['tags']) - tag_names
1378
+ pr.delete('tags') if pr['tags'].empty?
1379
+ puts "Removed tag(s) #{tag_names.join(', ')} from ##{pr_number}"
1380
+ end
1381
+
1382
+ pinned_manager.save_pinned(pinned)
1383
+ end
1384
+
1385
+ add_subcmd(:tags) do
1386
+ pinned = pinned_manager.load_pinned
1387
+ by_tag = Hash.new { |h, k| h[k] = [] }
1388
+
1389
+ pinned.each do |pr|
1390
+ Array(pr['tags']).each { |t| by_tag[t] << pr }
1391
+ end
1392
+
1393
+ if by_tag.empty?
1394
+ puts "No tagged PRs."
1395
+ next
1396
+ end
1397
+
1398
+ by_tag.sort.each do |tag, prs|
1399
+ puts "\e[30;104m#{tag}\e[0m (#{prs.length})"
1400
+ prs.each { |pr| puts " ##{pr['number']} #{pr['title']}" }
1401
+ end
1402
+ end
1403
+
1315
1404
  # === Multi-PR action commands (mCMD) ===
1316
1405
  # Each accepts composable filter flags and applies the action to all matching PRs.
1317
1406
  # Without filters, falls back to fuzzy-select.
data/lib/hiiro/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Hiiro
2
- VERSION = "0.1.234"
2
+ VERSION = "0.1.236"
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.234
4
+ version: 0.1.236
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Toyota