Skip to content

Commit

Permalink
[#226] Change output formatting
Browse files Browse the repository at this point in the history
Problem: multiple issues with the CLI output

1. In the --help output, metavars GLOB_PATTERN and REPOSITORY_TYPE
   used spaces instead of underscores. Variables typically don't
   contain spaces in their names, so it looked confusing.
2. Incorrect or unintuitive coloring of the output. For example,
   filenames were dim even though they're important and should
   stand out, the report of success wasn't green, error messages
   weren't red, etc.
3. Excessive indentation and empty lines that made it difficult to
   visually parse the error report. Also the use of the exotic '➥'
   character that looks bad in many font configurations.
4. Filenames and line numbers were far apart, making it impossible
   to Ctrl+Click to jump to the source of the error.
5. In case of connection failure, the output was too verbose and
   platform-dependent.

Solution:

1. Include the filename in positions returned by the scanner.
2. Adjust the pretty-printing functions and update test output.
3. Extend VerifyError with a constructor for connection failures.
  • Loading branch information
int-index committed Dec 22, 2024
1 parent 671f527 commit 0934d6e
Show file tree
Hide file tree
Showing 43 changed files with 689 additions and 1,079 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Unreleased
+ Now Xrefcheck is able to follow relative redirects.
* [#262](https://github.com/serokell/xrefcheck/pull/262)
+ Now Xrefcheck includes a scanner that verifies the repository symlinks.
* [#307](https://github.com/serokell/xrefcheck/pull/307)
+ The output of Xrefcheck is now more legible.

0.2.2
==========
Expand Down
Binary file added docs/output-sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/output-sample/output-sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ library:
- filepath
- fmt
- ftp-client
- crypton-connection
- Glob
- http-client
- http-types
Expand Down
4 changes: 2 additions & 2 deletions src/Xrefcheck/CLI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ exclusionOptionsParser :: Parser ExclusionOptions
exclusionOptionsParser = do
eoIgnore <- many . globOption $
long "ignore" <>
metavar "GLOB PATTERN" <>
metavar "GLOB_PATTERN" <>
help "Ignore these files. References to them will fail verification,\
\ and references from them will not be verified.\
\ Glob patterns that contain wildcards MUST be enclosed\
Expand Down Expand Up @@ -237,7 +237,7 @@ dumpConfigOptions = hsubparser $
option repoTypeReadM $
short 't' <>
long "type" <>
metavar "REPOSITORY TYPE" <>
metavar "REPOSITORY_TYPE" <>
help [int||
Git repository type. \
Can be (#{intercalate " | " $ map show allFlavors}). \
Expand Down
3 changes: 2 additions & 1 deletion src/Xrefcheck/Command.hs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ defaultAction Options{..} = do
verifyRepo rw fullConfig oMode repoInfo

case verifyErrors verifyRes of
Nothing | null scanErrs -> fmtLn "All repository links are valid."
Nothing | null scanErrs ->
fmtLn $ colorIfNeeded Green "All repository links are valid."
Nothing -> exitFailure
Just verifyErrs -> do
unless (null scanErrs) $ fmt "\n"
Expand Down
27 changes: 10 additions & 17 deletions src/Xrefcheck/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,11 @@ instance FromJSON Flavor where
-- | Description of element position in source file.
-- We keep this in text because scanners for different formats use different
-- representation of this thing, and it actually appears in reports only.
newtype Position = Position (Maybe Text)
newtype Position = Position Text
deriving stock (Show, Eq, Generic)

instance Given ColorMode => Buildable Position where
build (Position pos) = case pos of
Nothing -> ""
Just p -> styleIfNeeded Faint $ "at src:" <> build p
instance Buildable Position where
build (Position pos) = build pos

-- | Full info about a reference.
data Reference = Reference
Expand Down Expand Up @@ -235,46 +233,41 @@ instance Given ColorMode => Buildable Reference where
case rifLink of
FLLocal ->
[int||
reference #{paren $ colorIfNeeded Green "file-local"}#{posSep}#{rPos}:
reference #{paren $ colorIfNeeded Green "file-local"} at #{rPos}:
- text: #s{rName}
- anchor: #{rifAnchor ?: styleIfNeeded Faint "-"}
|]
FLRelative link ->
[int||
reference #{paren $ colorIfNeeded Yellow "relative"}#{posSep}#{rPos}:
reference #{paren $ colorIfNeeded Yellow "relative"} at #{rPos}:
- text: #s{rName}
- link: #{link}
- anchor: #{rifAnchor ?: styleIfNeeded Faint "-"}
|]
FLAbsolute link ->
[int||
reference #{paren $ colorIfNeeded Yellow "absolute"}#{posSep}#{rPos}:
reference #{paren $ colorIfNeeded Yellow "absolute"} at #{rPos}:
- text: #s{rName}
- link: /#{link}
- anchor: #{rifAnchor ?: styleIfNeeded Faint "-"}
|]
RIExternal (ELUrl url) ->
[int||
reference #{paren $ colorIfNeeded Red "external"}#{posSep}#{rPos}:
reference #{paren $ colorIfNeeded Red "external"} at #{rPos}:
- text: #s{rName}
- link: #{url}
|]
RIExternal (ELOther url) ->
[int||
reference (other)#{posSep}#{rPos}:
reference (other) at #{rPos}:
- text: #s{rName}
- link: #{url}
|]
where
posSep :: Text
posSep = case rPos of
Position Nothing -> ""
_ -> " "

instance Given ColorMode => Buildable AnchorType where
build = styleIfNeeded Faint . \case
HeaderAnchor l -> colorIfNeeded Green ("header " <> headerLevelToRoman l)
HandAnchor -> colorIfNeeded Yellow "hand made"
HandAnchor -> colorIfNeeded Yellow "handmade"
BiblioAnchor -> colorIfNeeded Cyan "biblio"
where
headerLevelToRoman = \case
Expand All @@ -289,7 +282,7 @@ instance Given ColorMode => Buildable AnchorType where
instance Given ColorMode => Buildable Anchor where
build Anchor{..} =
[int||
#{aName} (#{aType}) #{aPos}
#{aName} (#{aType}) at #{aPos}
|]

instance Given ColorMode => Buildable FileInfo where
Expand Down
33 changes: 15 additions & 18 deletions src/Xrefcheck/Scan.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import Control.Lens (_1, makeLensesWith, (%~))
import Data.Aeson (FromJSON (..), genericParseJSON, withText)
import Data.Map qualified as M
import Data.Reflection (Given)
import Fmt (Buildable (..), fmt)
import Fmt (Buildable (..), Builder, fmtLn)
import System.Directory (doesDirectoryExist, pathIsSymbolicLink)
import System.Process (cwd, readCreateProcess, shell)
import Text.Interpolation.Nyan
Expand Down Expand Up @@ -120,23 +120,20 @@ mkGatherScanError seFile ScanError{sePosition, seDescription} = ScanError
, seDescription
}

instance Given ColorMode => Buildable (ScanError 'Gather) where
build ScanError{..} = [int||
In file #{styleIfNeeded Faint (styleIfNeeded Bold seFile)}
scan error #{sePosition}:

#{seDescription}

|]
pprScanErr :: Given ColorMode => ScanError 'Gather -> Builder
pprScanErr ScanError{..} = hdr <> "\n" <> interpolateIndentF 2 msg <> "\n"
where
hdr, msg :: Builder
hdr =
styleIfNeeded Bold (build sePosition <> ": ") <>
colorIfNeeded Red "scan error:"
msg = build seDescription

reportScanErrs :: Given ColorMode => NonEmpty (ScanError 'Gather) -> IO ()
reportScanErrs errs = fmt
[int||
=== Scan errors found ===

#{interpolateIndentF 2 (interpolateBlockListF' "➥ " build errs)}
Scan errors dumped, #{length errs} in total.
|]
reportScanErrs errs = do
traverse_ (fmtLn . pprScanErr) errs
fmtLn $ colorIfNeeded Red $
"Scan errors dumped, " <> build (length errs) <> " in total."

data ScanErrorDescription
= LinkErr
Expand All @@ -152,8 +149,8 @@ instance Buildable ScanErrorDescription where
markdown or right after comments at the top|]
ParagraphErr txt -> [int||Expected a PARAGRAPH after \
"ignore paragraph" annotation, but found #{txt}|]
UnrecognisedErr txt -> [int||Unrecognised option "#{txt}" perhaps you meant \
<"ignore link"|"ignore paragraph"|"ignore all">|]
UnrecognisedErr txt -> [int||Unrecognised option "#{txt}"
Perhaps you meant <"ignore link"|"ignore paragraph"|"ignore all">|]

firstFileSupport :: [FileSupport] -> FileSupport
firstFileSupport fs isSymlink =
Expand Down
Loading

0 comments on commit 0934d6e

Please sign in to comment.