99from gh_llm .pager import DEFAULT_PAGE_SIZE , TimelinePager
1010from gh_llm .render import (
1111 render_checks_section ,
12+ render_description ,
1213 render_event_detail ,
1314 render_event_detail_blocks ,
1415 render_expand_hints ,
16+ render_frontmatter ,
1517 render_header ,
1618 render_hidden_gap ,
1719 render_page ,
@@ -31,6 +33,15 @@ class _ExpandOptions:
3133 details : bool = False
3234
3335
36+ @dataclass (frozen = True )
37+ class _ShowOptions :
38+ meta : bool = True
39+ description : bool = True
40+ timeline : bool = True
41+ checks : bool = True
42+ actions : bool = True
43+
44+
3445def register_pr_parser (subparsers : Any ) -> None :
3546 pr_parser = subparsers .add_parser ("pr" , help = "PR-related commands" )
3647 pr_subparsers = pr_parser .add_subparsers (dest = "pr_command" )
@@ -42,6 +53,12 @@ def register_pr_parser(subparsers: Any) -> None:
4253 view_parser .add_argument ("pr" , nargs = "?" , help = "PR number/url/branch" )
4354 view_parser .add_argument ("--repo" , help = "repository in OWNER/REPO format" )
4455 view_parser .add_argument ("--page-size" , type = int , default = DEFAULT_PAGE_SIZE , help = "timeline entries per page" )
56+ view_parser .add_argument (
57+ "--show" ,
58+ action = "append" ,
59+ default = [],
60+ help = "show regions: meta, description, timeline, checks, actions, all (comma-separated or repeatable)" ,
61+ )
4562 view_parser .add_argument (
4663 "--expand" ,
4764 action = "append" ,
@@ -213,6 +230,7 @@ def cmd_pr_view(args: Any) -> int:
213230 page_size = int (args .page_size )
214231 diff_hunk_lines = _resolve_diff_hunk_lines (args = args , default = DEFAULT_DIFF_HUNK_LINES )
215232 expand = _parse_expand_options (raw_values = list (getattr (args , "expand" , [])))
233+ show = _parse_show_options (raw_values = list (getattr (args , "show" , [])))
216234 client = GitHubClient ()
217235 pager = TimelinePager (client )
218236
@@ -227,12 +245,26 @@ def cmd_pr_view(args: Any) -> int:
227245 )
228246 shown_pages : set [int ] = {1 }
229247
230- for line in render_header (context ):
231- print (line )
232- for line in render_page (1 , context , first_page ):
233- print (line )
248+ wrote_output = False
234249
235- if last_page is not None :
250+ def print_block (lines : list [str ]) -> None :
251+ nonlocal wrote_output
252+ if not lines :
253+ return
254+ if wrote_output :
255+ print ()
256+ for line in lines :
257+ print (line )
258+ wrote_output = True
259+
260+ if show .meta :
261+ print_block (render_frontmatter (context ))
262+ if show .description :
263+ print_block (render_description (context ))
264+ if show .timeline :
265+ print_block (render_page (1 , context , first_page ))
266+
267+ if show .timeline and last_page is not None :
236268 trailing_pages : list [tuple [int , TimelinePage ]] = []
237269 include_previous = context .total_pages > 2 and context .total_count % context .page_size != 0
238270 if include_previous :
@@ -256,9 +288,7 @@ def cmd_pr_view(args: Any) -> int:
256288 hidden_start = 2
257289 hidden_end = first_trailing_page - 1
258290 hidden_pages = list (range (hidden_start , hidden_end + 1 )) if hidden_start <= hidden_end else []
259- print ()
260- for line in render_hidden_gap (context , hidden_pages ):
261- print (line )
291+ print_block (render_hidden_gap (context , hidden_pages ))
262292 if hidden_pages :
263293 print ()
264294 for index , (page_number , page_data ) in enumerate (trailing_pages ):
@@ -267,19 +297,26 @@ def cmd_pr_view(args: Any) -> int:
267297 for line in render_page (page_number , context , page_data ):
268298 print (line )
269299
270- print ()
271- for line in render_expand_hints (context , shown_pages ):
272- print (line )
273- checks = client .fetch_checks (meta .ref ) if meta .state == "OPEN" else []
274- for line in render_checks_section (
275- context = context ,
276- checks = checks ,
277- show_all = False ,
278- is_open = (meta .state == "OPEN" ),
279- ):
280- print (line )
281- for line in render_pr_actions (context ):
282- print (line )
300+ if show .timeline :
301+ print_block (render_expand_hints (context , shown_pages ))
302+ if show .checks :
303+ checks = client .fetch_checks (meta .ref ) if meta .state == "OPEN" else []
304+ print_block (
305+ render_checks_section (
306+ context = context ,
307+ checks = checks ,
308+ show_all = False ,
309+ is_open = (meta .state == "OPEN" ),
310+ )
311+ )
312+ if show .actions :
313+ print_block (
314+ render_pr_actions (
315+ context ,
316+ include_diff = True ,
317+ include_manage = show .actions ,
318+ )
319+ )
283320
284321 return 0
285322
@@ -664,6 +701,42 @@ def _parse_expand_options(*, raw_values: list[str]) -> _ExpandOptions:
664701 return _ExpandOptions (resolved = resolved , hidden = hidden , details = details )
665702
666703
704+ def _parse_show_options (* , raw_values : list [str ]) -> _ShowOptions :
705+ if not raw_values :
706+ return _ShowOptions ()
707+
708+ selected : set [str ] = set ()
709+ aliases : dict [str , set [str ]] = {
710+ "meta" : {"meta" },
711+ "description" : {"description" },
712+ "desc" : {"description" },
713+ "timeline" : {"timeline" },
714+ "checks" : {"checks" },
715+ "actions" : {"actions" },
716+ "summary" : {"meta" , "description" },
717+ "all" : {"meta" , "description" , "timeline" , "checks" , "actions" },
718+ "*" : {"meta" , "description" , "timeline" , "checks" , "actions" },
719+ }
720+
721+ for raw in raw_values :
722+ for part in raw .split ("," ):
723+ token = part .strip ().lower ()
724+ if not token :
725+ continue
726+ mapped = aliases .get (token )
727+ if mapped is None :
728+ raise RuntimeError (f"unknown show option: { token } " )
729+ selected .update (mapped )
730+
731+ return _ShowOptions (
732+ meta = ("meta" in selected ),
733+ description = ("description" in selected ),
734+ timeline = ("timeline" in selected ),
735+ checks = ("checks" in selected ),
736+ actions = ("actions" in selected ),
737+ )
738+
739+
667740def _resolve_pr_meta (* , client : GitHubClient , args : Any ) -> PullRequestMeta :
668741 selector = getattr (args , "pr" , None )
669742 repo = getattr (args , "repo" , None )
0 commit comments