mirror of
https://github.com/kowainik/hit-on.git
synced 2024-11-03 23:06:10 +03:00
* [#104] Support renames in 'hit status' * Improve documentation for parsing 'git diff' * Remove unnecessary qualified use of words
This commit is contained in:
parent
ba0e52d3c5
commit
14b0e3df62
@ -191,7 +191,8 @@ runCurrent = do
|
||||
{- | Show stats from the given commit. If commit is not specified, uses HEAD.
|
||||
-}
|
||||
runStatus :: Maybe Text -> IO ()
|
||||
runStatus (fromMaybe "HEAD" -> commit) = withUntrackedFiles $ showPrettyDiff commit
|
||||
runStatus (fromMaybe "HEAD" -> commit)
|
||||
= withDeletedFiles $ withUntrackedFiles $ showPrettyDiff commit
|
||||
|
||||
{- | Show diff from the given commit. If commit is not specified, uses HEAD.
|
||||
This commands checks whether @diff-hightligh@ is on path and if not, just calls
|
||||
@ -260,22 +261,41 @@ issueFromBranch =
|
||||
. T.drop 1
|
||||
. T.dropWhile (/= '/')
|
||||
|
||||
{- | Perform the given action by first staging the given files and
|
||||
later removing them again after the action
|
||||
-}
|
||||
withFiles :: IO [Text] -> IO a -> IO a
|
||||
withFiles whichFiles action = bracket
|
||||
addFiles
|
||||
removeFiles
|
||||
(const action)
|
||||
where
|
||||
addFiles :: IO [Text]
|
||||
addFiles = do
|
||||
files <- whichFiles
|
||||
for_ files $ \file -> void $ "git" $| ["add", file]
|
||||
pure files
|
||||
|
||||
-- Return files back to not spoil git state and have unexpected behavior
|
||||
removeFiles :: [Text] -> IO ()
|
||||
removeFiles = mapM_ $ \file -> void $ "git" $| ["reset", "--", file]
|
||||
|
||||
{- | Perform given action by adding all deleted files to index and returning
|
||||
them back after action.
|
||||
-}
|
||||
withDeletedFiles :: IO a -> IO a
|
||||
withDeletedFiles = withFiles deletedFiles
|
||||
where
|
||||
-- Find the deleted file to index so they will appear in diff
|
||||
deletedFiles :: IO [Text]
|
||||
deletedFiles = lines <$> "git" $| ["ls-files", "--deleted", "--exclude-standard"]
|
||||
|
||||
{- | Perform given action by adding all untracked files to index and returning
|
||||
them back after action.
|
||||
-}
|
||||
withUntrackedFiles :: IO a -> IO a
|
||||
withUntrackedFiles action = bracket
|
||||
addUntrackedFiles
|
||||
removeUntrackedFiles
|
||||
(const action)
|
||||
withUntrackedFiles = withFiles untrackedFiles
|
||||
where
|
||||
-- Add all untracked file to index so they will appear in diff
|
||||
addUntrackedFiles :: IO [Text]
|
||||
addUntrackedFiles = do
|
||||
untrackedFiles <- lines <$> "git" $| ["ls-files", "--others", "--exclude-standard"]
|
||||
for_ untrackedFiles $ \file -> void $ "git" $| ["add", file]
|
||||
pure untrackedFiles
|
||||
|
||||
-- Return untracked files back to not spoil git state and have unexpected behavior
|
||||
removeUntrackedFiles :: [Text] -> IO ()
|
||||
removeUntrackedFiles = mapM_ $ \file -> void $ "git" $| ["reset", file]
|
||||
-- Find the untracked file to index so they will appear in diff
|
||||
untrackedFiles :: IO [Text]
|
||||
untrackedFiles = lines <$> "git" $| ["ls-files", "--others", "--exclude-standard"]
|
||||
|
@ -27,19 +27,29 @@ data PatchType
|
||||
| Unknown
|
||||
| BrokenPairing
|
||||
|
||||
-- | Map conventional characters to 'PatchType'
|
||||
{- | Parses the different change types.
|
||||
Renames and copies contain an additional similarity percentage between the two files.
|
||||
|
||||
Potential values include:
|
||||
'A' for newly added files
|
||||
'M' for modified files
|
||||
'R100' for renamed files, where 100 denotes a similarity percentage
|
||||
'C75' for copied files, where 75 denotes a similarity percentage
|
||||
-}
|
||||
parsePatchType :: Text -> Maybe PatchType
|
||||
parsePatchType = \case
|
||||
"A" -> Just Added
|
||||
"C" -> Just Copied
|
||||
"D" -> Just Deleted
|
||||
"M" -> Just Modified
|
||||
"R" -> Just Renamed
|
||||
"T" -> Just TypeChanged
|
||||
"U" -> Just Unmerged
|
||||
"X" -> Just Unknown
|
||||
"B" -> Just BrokenPairing
|
||||
_ -> Nothing
|
||||
parsePatchType t = do
|
||||
(c, _) <- T.uncons t
|
||||
case c of
|
||||
'A' -> Just Added
|
||||
'C' -> Just Copied
|
||||
'D' -> Just Deleted
|
||||
'M' -> Just Modified
|
||||
'R' -> Just Renamed
|
||||
'T' -> Just TypeChanged
|
||||
'U' -> Just Unmerged
|
||||
'X' -> Just Unknown
|
||||
'B' -> Just BrokenPairing
|
||||
_ -> Nothing
|
||||
|
||||
-- | Display 'PatchType' in colorful and expanded text.
|
||||
displayPatchType :: PatchType -> Text
|
||||
@ -66,8 +76,25 @@ data DiffName = DiffName
|
||||
, diffNameType :: !PatchType -- ^ type of the changed file
|
||||
}
|
||||
|
||||
{- | Parses a diff list of file names.
|
||||
When a file was renamed, both the previous and the new filename are given.
|
||||
These could be in the following formats:
|
||||
|
||||
@
|
||||
<patch-type> <filename>
|
||||
<patch-type> <old-filename> <new-filename>
|
||||
@
|
||||
|
||||
Typical raw text returned by @git@ can look like this:
|
||||
|
||||
@
|
||||
M README.md
|
||||
A foo
|
||||
R100 bar baz
|
||||
@
|
||||
-}
|
||||
parseDiffName :: [Text] -> Maybe DiffName
|
||||
parseDiffName [t, name] = DiffName name <$> parsePatchType t
|
||||
parseDiffName (t : xs) = DiffName (unwords xs) <$> parsePatchType t
|
||||
parseDiffName _ = Nothing
|
||||
|
||||
-- | Output of the @git diff --stat@ command.
|
||||
@ -87,14 +114,20 @@ It also handles special case of binary files. Typical raw text returned by @git@
|
||||
can look like this:
|
||||
|
||||
@
|
||||
.foo.un~ | Bin 0 -> 523 bytes
|
||||
README.md | 4 ++++
|
||||
foo | 1 +
|
||||
.foo.un~ | Bin 0 -> 523 bytes
|
||||
README.md | 4 ++++
|
||||
foo | 1 +
|
||||
bar => baz | 2 --
|
||||
qux => quux | 0
|
||||
@
|
||||
-}
|
||||
parseDiffStat :: [Text] -> Maybe DiffStat
|
||||
parseDiffStat = \case
|
||||
[diffStatFile, diffStatCount, diffStatSigns] -> Just DiffStat{..}
|
||||
_:"=>":diffStatFile:diffStatCount:rest -> Just DiffStat
|
||||
{ diffStatSigns = unwords rest
|
||||
, ..
|
||||
}
|
||||
diffStatFile:"Bin":rest -> Just DiffStat
|
||||
{ diffStatCount = "Bin"
|
||||
, diffStatSigns = unwords rest
|
||||
@ -122,7 +155,20 @@ showPrettyDiff commit = do
|
||||
|
||||
joinDiffs :: DiffName -> DiffStat -> (Text, Text, Text, Text)
|
||||
joinDiffs DiffName{..} DiffStat{..} =
|
||||
(displayPatchType diffNameType, diffNameFile, diffStatCount, diffStatSigns)
|
||||
( displayPatchType diffNameType
|
||||
, formatName diffNameType diffNameFile
|
||||
, diffStatCount
|
||||
, diffStatSigns
|
||||
)
|
||||
|
||||
formatName :: PatchType -> Text -> Text
|
||||
formatName = \case
|
||||
Renamed -> formatRename
|
||||
Copied -> formatRename
|
||||
_ -> id
|
||||
where
|
||||
formatRename :: Text -> Text
|
||||
formatRename = T.intercalate " -> " . words
|
||||
|
||||
formatTableAligned :: [(Text, Text, Text, Text)] -> Text
|
||||
formatTableAligned rows = unlines $ map formatRow rows
|
||||
|
Loading…
Reference in New Issue
Block a user