fine-grained space merging

This commit is contained in:
Mirek Kratochvil 2025-07-13 10:24:23 +02:00
parent 96a623ac07
commit bc5d7a6915
3 changed files with 30 additions and 7 deletions

20
Main.hs
View file

@ -112,13 +112,31 @@ zeal (Conflict m o y) =
pops ms ys = ((ms, ys), []) pops ms ys = ((ms, ys), [])
zeal x = [x] zeal x = [x]
resolve Config {..} c@(Conflict m o y) resolve cfg@Config {..} c@(Conflict m o y)
| all Toks.space (concat [m, o, y]) && cfgSpaces /= SpacesNormal =
resolveSpace cfg c
| m == o && o == y = Ok o | m == o && o == y = Ok o
| m == o && cfgResolveSeparate = Ok y | m == o && cfgResolveSeparate = Ok y
| o == y && cfgResolveSeparate = Ok m | o == y && cfgResolveSeparate = Ok m
| m == y && cfgResolveOverlaps = Ok m | m == y && cfgResolveOverlaps = Ok m
resolve _ x = x resolve _ x = x
-- TODO: there might be a bit of interplay between the spaces handling and
-- separate/overlapped conflict resolution -- e.g., what if someone wants to
-- merge overlapping edits in text but separate edits in spaces? At this point
-- that might be ignorable.
resolveSpace Config {..} c@(Conflict m o y)
| m == o && o == y = Ok o
| otherwise =
case cfgSpaces of
SpacesConflict -> c
SpacesMy -> Ok m
SpacesOld -> Ok o
SpacesYour -> Ok y
_ -> error "spaces resolution failed"
resolveSpaces _ x = x
merge cfg@Config {..} ms ys = merge cfg@Config {..} ms ys =
regroup regroup
. map (resolve cfg) . map (resolve cfg)

14
Opts.hs
View file

@ -38,13 +38,15 @@ tokenizer =
] ]
data Spaces data Spaces
= SpacesConflict = SpacesNormal
| SpacesConflict
| SpacesMy | SpacesMy
| SpacesOld | SpacesOld
| SpacesYour | SpacesYour
deriving (Show) deriving (Show, Eq)
spaceMode x spaceMode x
| x `isPrefixOf` "normal" = Right SpacesNormal
| x `isPrefixOf` "conflict" = Right SpacesConflict | x `isPrefixOf` "conflict" = Right SpacesConflict
| x `isPrefixOf` "my" = Right SpacesMy | x `isPrefixOf` "my" = Right SpacesMy
| x `isPrefixOf` "old" = Right SpacesOld | x `isPrefixOf` "old" = Right SpacesOld
@ -53,7 +55,7 @@ spaceMode x
Left Left
$ "could not parse value `" $ "could not parse value `"
++ x ++ x
++ "', use one of `conflict', `my', `old', and `your'" ++ "', use one of `normal', `conflict', `my', `old', and `your'"
data Config = Config data Config = Config
{ cfgTokenizer :: Tokenizer { cfgTokenizer :: Tokenizer
@ -75,10 +77,10 @@ config = do
option (eitherReader spaceMode) option (eitherReader spaceMode)
$ long "spaces" $ long "spaces"
<> short 's' <> short 's'
<> metavar "(conflict|my|old|your)" <> metavar "(normal|conflict|my|old|your)"
<> help <> help
"mode of merging the spaces; instead of conflict one may choose to default the space from the source files (default: conflict)" "mode of merging the space-only changes; instead of usual resolution one may choose to always conflict or to default the space from the source files (default: normal)"
<> value SpacesConflict <> value SpacesNormal
cfgContext <- cfgContext <-
option auto option auto
$ long "expand-context" $ long "expand-context"

View file

@ -23,6 +23,9 @@ unmarkSpace ('.':s) = s
unmarkSpace ('|':s) = s unmarkSpace ('|':s) = s
unmarkSpace _ = error "wat" unmarkSpace _ = error "wat"
space ('.':_) = True
space _ = False
split = split =
unlines unlines
. map (concatMap escape . markSpace) . map (concatMap escape . markSpace)