File: .lake/packages/lean4/src/lean/Lean/Parser/Tactic/Doc.lean

full_name: Lean.Parser.Tactic.Doc.isTactic
code: /-- Check whether a name is a tactic syntax kind -/
def isTactic (env : Environment) (kind : Name) : Bool 
goal: Bool

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.253
code: /--
Stores a collection of *tactic alternatives*, to track which new syntax rules represent new forms of
existing tactics.
-/
builtin_initialize tacticAlternativeExt
    : PersistentEnvExtension (Name × Name) (Name × Name) (NameMap Name) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun as (src, tgt) => as.insert src tgt,
    exportEntriesFn := fun es =>
      es.fold (fun a src tgt => a.push (src, tgt)) #[] |>.qsort (Name.quickLt ·.1 ·.1)
  }
goal: IO (Lean.PersistentEnvExtension (Lean.Name × Lean.Name) (Lean.Name × Lean.Name) (Lean.NameMap Lean.Name))

full_name: Lean.Parser.Tactic.Doc.tacticAlternativeExt
code: /--
Stores a collection of *tactic alternatives*, to track which new syntax rules represent new forms of
existing tactics.
-/
builtin_initialize tacticAlternativeExt
    : PersistentEnvExtension (Name × Name) (Name × Name) (NameMap Name) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun as (src, tgt) => as.insert src tgt,
    exportEntriesFn := fun es =>
      es.fold (fun a src tgt => a.push (src, tgt)) #[] |>.qsort (Name.quickLt ·.1 ·.1)
  }
goal: Lean.PersistentEnvExtension (Lean.Name × Lean.Name) (Lean.Name × Lean.Name) (Lean.NameMap Lean.Name)

full_name: Lean.Parser.Tactic.Doc.alternativeOfTactic
code: /--
If `tac` is registered as the alternative form of another tactic, then return the canonical name for
it.
-/
def alternativeOfTactic (env : Environment) (tac : Name) : Option Name 
goal: Option Lean.Name

full_name: Lean.Parser.Tactic.Doc.aliases
code: /--
Find all alternatives for a given canonical tactic name.
-/
def aliases [Monad m] [MonadEnv m] (tac : Name) : m NameSet 
goal: m Lean.NameSet

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.831
code: builtin_initialize
  let name := `tactic_alt
  registerBuiltinAttribute {
    name := name,
    ref := by exact decl_name%,
    add := fun decl stx kind => do
      unless kind == AttributeKind.global do throwError "invalid attribute '{name}', must be global"
      unless ((← getEnv).getModuleIdxFor? decl).isNone do
        throwError "invalid attribute '{name}', declaration is in an imported module"
      let `(«tactic_alt»|tactic_alt $tgt) := stx
        | throwError "invalid syntax for '{name}' attribute"

      let tgtName ← Lean.Elab.realizeGlobalConstNoOverloadWithInfo tgt

      if !(isTactic (← getEnv) tgtName) then throwErrorAt tgt "'{tgtName}' is not a tactic"
      -- If this condition is true, then we're in an `attribute` command and can validate here.
      if (← getEnv).find? decl |>.isSome then
        if !(isTactic (← getEnv) decl) then throwError "'{decl}' is not a tactic"

      if let some tgt' := alternativeOfTactic (← getEnv) tgtName then
        throwError "'{tgtName}' is itself an alternative for '{tgt'}'"
      modifyEnv fun env => tacticAlternativeExt.addEntry env (decl, tgtName)
      if (← findSimpleDocString? (← getEnv) decl).isSome then
        logWarningAt stx m!"Docstring for '{decl}' will be ignored because it is an alternative"

    descr :=
      "Register a tactic parser as an alternative form of an existing tactic, so they " ++
      "can be grouped together in documentation.",
    -- This runs prior to elaboration because it allows a check for whether the decl is present
    -- in the environment to determine whether we can see if it's a tactic name. This is useful
    -- when the attribute is applied after definition, using an `attribute` command (error checking
    -- for the `@[tactic_alt TAC]` syntax is performed by the parser attribute hook). If this
    -- attribute ran later, then the decl would already be present.
    applicationTime := .beforeElaboration
  }
goal: IO Unit

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.1625
code: /--
The known tactic tags that allow tactics to be grouped by purpose.
-/
builtin_initialize knownTacticTagExt
    : PersistentEnvExtension
        (Name × String × Option String)
        (Name × String × Option String)
        (NameMap (String × Option String)) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun as (src, tgt) => as.insert src tgt,
    exportEntriesFn := fun es =>
      es.fold (fun a src tgt => a.push (src, tgt)) #[] |>.qsort (Name.quickLt ·.1 ·.1)
  }
goal: IO
  (Lean.PersistentEnvExtension (Lean.Name × String × Option String) (Lean.Name × String × Option String)
    (Lean.NameMap (String × Option String)))

full_name: Lean.Parser.Tactic.Doc.knownTacticTagExt
code: /--
The known tactic tags that allow tactics to be grouped by purpose.
-/
builtin_initialize knownTacticTagExt
    : PersistentEnvExtension
        (Name × String × Option String)
        (Name × String × Option String)
        (NameMap (String × Option String)) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun as (src, tgt) => as.insert src tgt,
    exportEntriesFn := fun es =>
      es.fold (fun a src tgt => a.push (src, tgt)) #[] |>.qsort (Name.quickLt ·.1 ·.1)
  }
goal: Lean.PersistentEnvExtension (Lean.Name × String × Option String) (Lean.Name × String × Option String)
  (Lean.NameMap (String × Option String))

full_name: Lean.Parser.Tactic.Doc.tagInfo
code: /--
Get the user-facing name and docstring for a tactic tag.
-/
def tagInfo [Monad m] [MonadEnv m] (tag : Name) : m (Option (String × Option String)) 
goal: m (Option (String × Option String))

full_name: Lean.Parser.Tactic.Doc.allTags
code: /-- Enumerate the tactic tags that are available -/
def allTags [Monad m] [MonadEnv m] : m (List Name) 
goal: m (List Lean.Name)

full_name: Lean.Parser.Tactic.Doc.allTagsWithInfo
code: /-- Enumerate the tactic tags that are available, with their user-facing name and docstring -/
def allTagsWithInfo [Monad m] [MonadEnv m] : m (List (Name × String × Option String)) 
goal: m (List (Lean.Name × String × Option String))

full_name: Lean.Parser.Tactic.Doc.tacticTagExt
code: /--
The mapping between tags and tactics. Tags may be applied in any module, not just the defining
module for the tactic.

Because this is expected to be augmented regularly, but queried rarely (only when generating
documentation indices), it is just stored as flat unsorted arrays of pairs. Before it is used for
some other purpose, consider a new representation.

The first projection in each pair is the tactic name, and the second is the tag name.
-/
builtin_initialize tacticTagExt
    : PersistentEnvExtension (Name × Name) (Name × Name) (NameMap NameSet) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun tags (decl, newTag) => tags.insert decl (tags.findD decl {} |>.insert newTag)
    exportEntriesFn := fun tags => Id.run do
      let mut exported := #[]
      for (decl, dTags) in tags do
        for t in dTags do
          exported := exported.push (decl, t)
      exported
  }
goal: Lean.PersistentEnvExtension (Lean.Name × Lean.Name) (Lean.Name × Lean.Name) (Lean.NameMap Lean.NameSet)

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.2587
code: /--
The mapping between tags and tactics. Tags may be applied in any module, not just the defining
module for the tactic.

Because this is expected to be augmented regularly, but queried rarely (only when generating
documentation indices), it is just stored as flat unsorted arrays of pairs. Before it is used for
some other purpose, consider a new representation.

The first projection in each pair is the tactic name, and the second is the tag name.
-/
builtin_initialize tacticTagExt
    : PersistentEnvExtension (Name × Name) (Name × Name) (NameMap NameSet) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun tags (decl, newTag) => tags.insert decl (tags.findD decl {} |>.insert newTag)
    exportEntriesFn := fun tags => Id.run do
      let mut exported := #[]
      for (decl, dTags) in tags do
        for t in dTags do
          exported := exported.push (decl, t)
      exported
  }
goal: IO (Lean.PersistentEnvExtension (Lean.Name × Lean.Name) (Lean.Name × Lean.Name) (Lean.NameMap Lean.NameSet))

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.2867
code: builtin_initialize
  let name := `tactic_tag
  registerBuiltinAttribute {
    name := name,
    ref := by exact decl_name%,
    add := fun decl stx kind => do
      unless kind == AttributeKind.global do throwError "invalid attribute '{name}', must be global"
      let `(«tactic_tag»|tactic_tag $tags*) := stx
        | throwError "invalid '{name}' attribute"
      if (← getEnv).find? decl |>.isSome then
        if !(isTactic (← getEnv) decl) then
          throwErrorAt stx "'{decl}' is not a tactic"

      if let some tgt' := alternativeOfTactic (← getEnv) decl then
        throwErrorAt stx "'{decl}' is an alternative form of '{tgt'}'"

      for t in tags do
        let tagName := t.getId
        if let some _ ← tagInfo tagName then
          modifyEnv (tacticTagExt.addEntry · (decl, tagName))
        else
          let all ← allTags
          let extra : MessageData :=
              let count := all.length
              let name := (m!"'{·}'")
              let suggestions :=
                if count == 0 then m!"(no tags defined)"
                else if count == 1 then
                  MessageData.joinSep (all.map name) ", "
                else if count < 10 then
                  m!"one of " ++ MessageData.joinSep (all.map name) ", "
                else
                  m!"one of " ++
                  MessageData.joinSep (all.take 10 |>.map name) ", " ++ ", ..."
              m!"(expected {suggestions})"

          throwErrorAt t (m!"unknown tag '{tagName}' " ++ extra)
    descr := "Register a tactic parser as an alternative of an existing tactic, so they can be " ++
      "grouped together in documentation.",
    -- This runs prior to elaboration because it allows a check for whether the decl is present
    -- in the environment to determine whether we can see if it's a tactic name. This is useful
    -- when the attribute is applied after definition, using an `attribute` command (error checking
    -- for the `@[tactic_tag ...]` syntax is performed by the parser attribute hook). If this
    -- attribute ran later, then the decl would already be present.
    applicationTime := .beforeElaboration
  }
goal: IO Unit

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.3682
code: /--
Extensions to tactic documentation.

This provides a structured way to indicate that an extensible tactic has been extended (for
instance, new cases tried by `trivial`).
-/
builtin_initialize tacticDocExtExt
    : PersistentEnvExtension (Name × Array String) (Name × String) (NameMap (Array String)) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun es (x, ext) => es.insert x (es.findD x #[] |>.push ext),
    exportEntriesFn := fun es =>
      es.fold (fun a src tgt => a.push (src, tgt)) #[] |>.qsort (Name.quickLt ·.1 ·.1)
  }
goal: IO (Lean.PersistentEnvExtension (Lean.Name × Array String) (Lean.Name × String) (Lean.NameMap (Array String)))

full_name: Lean.Parser.Tactic.Doc.tacticDocExtExt
code: /--
Extensions to tactic documentation.

This provides a structured way to indicate that an extensible tactic has been extended (for
instance, new cases tried by `trivial`).
-/
builtin_initialize tacticDocExtExt
    : PersistentEnvExtension (Name × Array String) (Name × String) (NameMap (Array String)) ←
  registerPersistentEnvExtension {
    mkInitial := pure {},
    addImportedFn := fun _ => pure {},
    addEntryFn := fun es (x, ext) => es.insert x (es.findD x #[] |>.push ext),
    exportEntriesFn := fun es =>
      es.fold (fun a src tgt => a.push (src, tgt)) #[] |>.qsort (Name.quickLt ·.1 ·.1)
  }
goal: Lean.PersistentEnvExtension (Lean.Name × Array String) (Lean.Name × String) (Lean.NameMap (Array String))

full_name: Lean.Parser.Tactic.Doc.getTacticExtensions
code: /-- Gets the extensions declared for the documentation for the given canonical tactic name -/
def getTacticExtensions (env : Environment) (tactic : Name) : Array String 
goal: Array String

full_name: Lean.Parser.Tactic.Doc.getTacticExtensionString.indentLine
code: /-- Gets the rendered extensions for the given canonical tactic name -/
def getTacticExtensionString (env : Environment) (tactic : Name) : String 
goal: String

full_name: Lean.Parser.Tactic.Doc.getTacticExtensionString
code: /-- Gets the rendered extensions for the given canonical tactic name -/
def getTacticExtensionString (env : Environment) (tactic : Name) : String 
goal: String

full_name: Lean.Parser.Tactic.Doc.getTacticExtensionString.bullet
code: /-- Gets the rendered extensions for the given canonical tactic name -/
def getTacticExtensionString (env : Environment) (tactic : Name) : String 
goal: String

full_name: Lean.Parser.Tactic.Doc.tacticDocsOnTactics
code: /--
Validates that a tactic alternative is actually a tactic and that syntax tagged as tactics are
tactics.
-/
def tacticDocsOnTactics : ParserAttributeHook 
goal: Lean.Parser.ParserAttributeHook

full_name: Lean.Parser.Tactic.Doc.initFn._@..lake.packages.lean4.src.lean.Lean.Parser.Tactic.Doc._hyg.4468
code: builtin_initialize
  registerParserAttributeHook tacticDocsOnTactics
goal: IO Unit