3333from importlib import import_module
3434from importlib .util import find_spec
3535from pathlib import Path
36+ from pprint import pformat
3637
3738import click
3839from docutils import nodes
4243from rich .console import Console
4344from rich .theme import Theme
4445from sphinx import application
46+ from sphinx .addnodes import pending_xref
4547from sphinx .util import logging
4648from sphinx .util .nodes import make_refnode
4749
5254from typer .models import Context as TyperContext
5355from typer .models import TyperInfo
5456
55- VERSION = (0 , 4 , 0 )
57+ VERSION = (0 , 4 , 1 )
5658
5759__title__ = "SphinxContrib Typer"
5860__version__ = "." .join (str (i ) for i in VERSION )
@@ -458,7 +460,7 @@ def generate_nodes(
458460 self .env .domaindata ["std" ].setdefault ("typer" , {})[section_id ] = (
459461 self .env .docname ,
460462 section_id ,
461- " " . join ( section_id . split ( "-" )) ,
463+ normal_cmd ,
462464 )
463465
464466 # Summary
@@ -584,7 +586,7 @@ def run(self) -> t.Iterable[nodes.section]:
584586
585587 self .make_sections = "make-sections" in self .options
586588 self .nested = "show-nested" in self .options
587- self .prog_name = self .options .get ("prog" , None )
589+ self .prog_name = self .options .get ("prog" , "" )
588590 if "markup-mode" in self .options :
589591 self .markup_mode = self .options ["markup-mode" ]
590592
@@ -600,6 +602,8 @@ def run(self) -> t.Iterable[nodes.section]:
600602 "Unable to determine program name, please specify using " ":prog:"
601603 ) from err
602604
605+ self .prog_name = self .prog_name .strip ()
606+
603607 self .width = self .options .get ("width" , 65 )
604608 self .iframe_height = self .options .get ("iframe-height" , None )
605609
@@ -950,6 +954,33 @@ def typer_convert_png(
950954 im .save (str (png_path )) # Saves the screenshot
951955
952956
957+ def resolve_typer_reference (app , env , node , contnode ):
958+ target_id = node ["reftarget" ]
959+ if target_id in env .domaindata ["std" ].get ("typer" , {}):
960+ docname , labelid , sectionname = env .domaindata ["std" ]["typer" ][target_id ]
961+ refnode = make_refnode (
962+ env .app .builder ,
963+ node ["refdoc" ],
964+ docname ,
965+ labelid ,
966+ nodes .Text (sectionname .strip ()),
967+ target_id ,
968+ )
969+ return refnode
970+ else :
971+ lineno = node .line or getattr (node .parent , "line" , 0 )
972+ error_message = env .get_doctree (node ["refdoc" ]).reporter .error (
973+ f"Unresolved :typer: reference: '{ target_id } ' in document '{ node ['refdoc' ]} '. "
974+ f"Expected one of: { pformat (list (env .domaindata ["std" ]["typer" ].keys ()), indent = 2 )} " ,
975+ line = lineno ,
976+ )
977+ msgid = node .document .set_id (error_message , node .parent )
978+ problematic = nodes .problematic (node .rawsource , node .rawsource , refid = msgid )
979+ prbid = node .document .set_id (problematic )
980+ error_message .add_backref (prbid )
981+ return problematic
982+
983+
953984def typer_ref_role (name , rawtext , text , lineno , inliner , options = {}, content = []):
954985 env = inliner .document .settings .env
955986 target_id = nodes .make_id (text )
@@ -960,19 +991,32 @@ def typer_ref_role(name, rawtext, text, lineno, inliner, options={}, content=[])
960991 env .docname ,
961992 docname ,
962993 labelid ,
963- nodes .Text (sectionname ),
994+ nodes .Text (sectionname . strip () ),
964995 target_id ,
965996 )
966997 return [refnode ], []
967998 else :
968- msg = inliner .reporter .error (f'Unknown typer reference: "{ text } "' , line = lineno )
969- return [inliner .problematic (rawtext , rawtext , msg )], [msg ]
999+ pending = pending_xref (
1000+ rawtext ,
1001+ refdomain = "std" ,
1002+ reftype = "typer" ,
1003+ reftarget = target_id ,
1004+ modname = None ,
1005+ classname = None ,
1006+ refexplicit = True ,
1007+ refwarn = True ,
1008+ reftitle = text ,
1009+ refdoc = env .docname ,
1010+ )
1011+ pending += nodes .Text (text )
1012+ return [pending ], []
9701013
9711014
9721015def setup (app : application .Sphinx ) -> t .Dict [str , t .Any ]:
9731016 # Need autodoc to support mocking modules
9741017 app .add_directive ("typer" , TyperDirective )
9751018 app .add_role ("typer" , typer_ref_role )
1019+ app .connect ("missing-reference" , resolve_typer_reference )
9761020
9771021 app .add_config_value (
9781022 "typer_render_html" , "sphinxcontrib.typer.typer_render_html" , "env"
0 commit comments