@@ -269,7 +269,7 @@ def base(self, base: str):
269269 def has_missing_info (self ) -> bool :
270270 return None in (self ._pr , self ._head , self ._base )
271271
272- def pprint (self ):
272+ def pprint (self , links : bool ):
273273 s = b (self .commit .commit_id ()[:8 ])
274274 pr_string = None
275275 if self .has_pr ():
@@ -290,10 +290,14 @@ def pprint(self):
290290 if pr_string or branch_string :
291291 s += ")"
292292 s += ": " + self .commit .title ()
293+
294+ if links and self .has_pr ():
295+ s = link (self .pr , s )
296+
293297 return s
294298
295299 def __repr__ (self ):
296- return self .pprint ()
300+ return self .pprint (False )
297301
298302 def read_metadata (self ):
299303 self .commit .commit_msg ()
@@ -341,6 +345,16 @@ def red(s: str):
341345 return bcolors .FAIL + s + bcolors .ENDC
342346
343347
348+ # https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
349+ def link (location : str , text : str ):
350+ """
351+ Emits a link to the terminal using the terminal hyperlink specification.
352+
353+ Does not properly implement file URIs. Only use with web URIs.
354+ """
355+ return f"\033 ]8;;{ location } \033 \\ { text } \033 ]8;;\033 \\ "
356+
357+
344358def error (msg ):
345359 print (red ("\n ERROR: " ) + msg )
346360
@@ -470,10 +484,10 @@ def verify(st: List[StackEntry], check_base: bool = False):
470484 raise RuntimeError
471485
472486
473- def print_stack (st : List [StackEntry ], level = 1 ):
487+ def print_stack (st : List [StackEntry ], links : bool , level = 1 ):
474488 log (b ("Stack:" ), level = level )
475489 for e in reversed (st ):
476- log (" * " + e .pprint (), level = level )
490+ log (" * " + e .pprint (links ), level = level )
477491
478492
479493def draft_bitmask_type (value : str ) -> List [bool ]:
@@ -722,10 +736,11 @@ class CommonArgs(NamedTuple):
722736 head : str
723737 remote : str
724738 target : str
739+ hyperlinks : bool
725740
726741 @classmethod
727742 def from_args (cls , args : argparse .Namespace ) -> "CommonArgs" :
728- return cls (args .base , args .head , args .remote , args .target )
743+ return cls (args .base , args .head , args .remote , args .target , args . hyperlinks )
729744
730745
731746# If the base isn't explicitly specified, find the merge base between
@@ -745,7 +760,7 @@ def deduce_base(args: CommonArgs) -> CommonArgs:
745760 deduced_base = get_command_output (
746761 ["git" , "merge-base" , args .head , f"{ args .remote } /{ args .target } " ]
747762 )
748- return CommonArgs (deduced_base , args .head , args .remote , args .target )
763+ return CommonArgs (deduced_base , args .head , args .remote , args .target , args . hyperlinks )
749764
750765
751766def print_tips_after_export (st : List [StackEntry ], args : CommonArgs ):
@@ -797,7 +812,7 @@ def command_submit(
797812 # elements
798813 init_local_branches (st , args .remote )
799814 set_base_branches (st , args .target )
800- print_stack (st )
815+ print_stack (st , args . hyperlinks )
801816
802817 # If the current branch contains commits from the stack, we will need to
803818 # rebase it in the end since the commits will be modified.
@@ -857,7 +872,7 @@ def command_submit(
857872# LAND
858873# ===----------------------------------------------------------------------=== #
859874def rebase_pr (e : StackEntry , remote : str , target : str ):
860- log (b ("Rebasing " ) + e .pprint (), level = 2 )
875+ log (b ("Rebasing " ) + e .pprint (False ), level = 2 )
861876 # Rebase the head branch to the most recent 'origin/main'
862877 run_shell_command (["git" , "fetch" , "--prune" , remote ])
863878 cmd = ["git" , "checkout" , f"{ remote } /{ e .head } " , "-B" , e .head ]
@@ -883,7 +898,7 @@ def rebase_pr(e: StackEntry, remote: str, target: str):
883898
884899
885900def land_pr (e : StackEntry , remote : str , target : str ):
886- log (b ("Landing " ) + e .pprint (), level = 2 )
901+ log (b ("Landing " ) + e .pprint (False ), level = 2 )
887902 # Rebase the head branch to the most recent 'origin/main'
888903 run_shell_command (["git" , "fetch" , "--prune" , remote ])
889904 cmd = ["git" , "checkout" , f"{ remote } /{ e .head } " , "-B" , e .head ]
@@ -965,7 +980,7 @@ def command_land(args: CommonArgs):
965980 # already be there from the metadata that commits need to have by that
966981 # point.
967982 set_base_branches (st , args .target )
968- print_stack (st )
983+ print_stack (st , args . hyperlinks )
969984
970985 # Verify that the stack is correct before trying to land it.
971986 verify (st , check_base = True )
@@ -977,7 +992,7 @@ def command_land(args: CommonArgs):
977992 if len (st ) > 1 :
978993 log (h ("Rebasing the rest of the stack" ), level = 1 )
979994 prs_to_rebase = st [1 :]
980- print_stack (prs_to_rebase )
995+ print_stack (prs_to_rebase , args . hyperlinks )
981996 for e in prs_to_rebase :
982997 rebase_pr (e , args .remote , args .target )
983998 # Change the target of the new bottom-most PR in the stack to 'target'
@@ -1028,7 +1043,7 @@ def command_abandon(args: CommonArgs):
10281043
10291044 init_local_branches (st , args .remote )
10301045 set_base_branches (st , args .target )
1031- print_stack (st )
1046+ print_stack (st , args . hyperlinks )
10321047
10331048 log (h ("Stripping stack metadata from commit messages" ), level = 1 )
10341049
@@ -1106,7 +1121,7 @@ def command_view(args: CommonArgs):
11061121
11071122 set_head_branches (st , args .remote )
11081123 set_base_branches (st , args .target )
1109- print_stack (st )
1124+ print_stack (st , args . hyperlinks )
11101125 print_tips_after_view (st , args )
11111126 log (h (blue ("SUCCESS!" )), level = 1 )
11121127
@@ -1128,6 +1143,9 @@ def create_argparser() -> argparse.ArgumentParser:
11281143 common_parser .add_argument (
11291144 "-T" , "--target" , default = "main" , help = "Remote target branch"
11301145 )
1146+ common_parser .add_argument (
1147+ "--hyperlinks" , action = argparse .BooleanOptionalAction , default = True , help = "Enable or disable hyperlink support."
1148+ )
11311149
11321150 parser_submit = subparsers .add_parser (
11331151 "submit" ,
0 commit comments