Merge remote-tracking branch 'origin/master' into fix/view-suffixified

# Conflicts:
#	parser-typechecker/src/Unison/Codebase/Editor/HandleInput.hs
#	parser-typechecker/src/Unison/CommandLine/InputPatterns.hs
This commit is contained in:
Paul Chiusano 2020-03-20 18:16:25 -04:00
commit 6c0dc0d188
13 changed files with 472 additions and 114 deletions

View File

@ -212,21 +212,14 @@ loop = do
getHQ'TermsIncludingHistorical p =
getTermsIncludingHistorical (resolveSplit' p) root0
getHQ'TermReferences :: Path.HQSplit' -> Set Reference
getHQ'TermReferences p =
Set.fromList [ r | Referent.Ref r <- toList (getHQ'Terms p) ]
getHQ'Terms :: Path.HQSplit' -> Set Referent
getHQ'Terms p = BranchUtil.getTerm (resolveSplit' p) root0
getHQ'Types :: Path.HQSplit' -> Set Reference
getHQ'Types p = BranchUtil.getType (resolveSplit' p) root0
resolveHHQS'Types :: HashOrHQSplit' -> Action' m v (Set Reference)
resolveHHQS'Types = either
resolveHHQS'Types = either
(eval . TypeReferencesByShortHash)
(pure . getHQ'Types)
-- Term Refs only
resolveHHQS'Terms = either
(eval . TermReferencesByShortHash)
(pure . getHQ'TermReferences)
-- Term Refs and Cons
resolveHHQS'Referents = either
(eval . TermReferentsByShortHash)
@ -309,6 +302,53 @@ loop = do
typeConflicted src = nameConflicted src Set.empty
termConflicted src tms = nameConflicted src tms Set.empty
hashConflicted src = respond . HashAmbiguous src
hqNameQuery' doSuffixify hqs = do
parseNames0 <- makeHistoricalParsingNames $ Set.fromList hqs
let parseNames = (if doSuffixify then Names3.suffixify else id) parseNames0
let resultss = searchBranchExact hqLength parseNames hqs
(misses, hits) =
partition (\(_, results) -> null results) (zip hqs resultss)
results = List.sort . uniqueBy SR.toReferent $ hits >>= snd
pure (misses, results)
hqNameQuery = hqNameQuery' False
hqNameQuerySuffixify = hqNameQuery' True
typeReferences :: [SearchResult] -> [Reference]
typeReferences rs
= [ r | SR.Tp (SR.TypeResult _ r _) <- rs ]
termReferences :: [SearchResult] -> [Reference]
termReferences rs =
[ r | SR.Tm (SR.TermResult _ (Referent.Ref r) _) <- rs ]
termResults rs = [ r | SR.Tm r <- rs ]
typeResults rs = [ r | SR.Tp r <- rs ]
doRemoveReplacement from patchPath isTerm = do
let patchPath' = fromMaybe defaultPatchPath patchPath
patch <- getPatchAt patchPath'
(misses', hits) <- hqNameQuery [from]
let tpRefs = Set.fromList $ typeReferences hits
tmRefs = Set.fromList $ termReferences hits
tmMisses = (fst <$> misses')
<> (HQ'.toHQ . SR.termName <$> termResults hits)
tpMisses = (fst <$> misses')
<> (HQ'.toHQ . SR.typeName <$> typeResults hits)
misses = if isTerm then tpMisses else tmMisses
go :: Reference -> Action m (Either Event Input) v ()
go fr = do
let termPatch =
over Patch.termEdits (R.deleteDom fr) patch
typePatch =
over Patch.typeEdits (R.deleteDom fr) patch
(patchPath'', patchName) = resolveSplit' patchPath'
-- Save the modified patch
stepAtM inputDescription
(patchPath'',
Branch.modifyPatches
patchName
(const (if isTerm then termPatch else typePatch)))
-- Say something
success
when (not $ null misses) $
respond $ SearchTermsNotFound misses
traverse_ go (if isTerm then tmRefs else tpRefs)
branchExists dest _x = respond $ BranchAlreadyExists dest
branchExistsSplit = branchExists . Path.unsplit'
typeExists dest = respond . TypeAlreadyExists dest
@ -333,13 +373,13 @@ loop = do
DeleteTypeI def -> "delete.type " <> hqs' def
DeleteBranchI opath -> "delete.namespace " <> ops' opath
DeletePatchI path -> "delete.patch " <> ps' path
ReplaceTermI srcH targetH p ->
"replace.term " <> hhqs' srcH <> " "
<> hhqs' targetH <> " "
ReplaceTermI src target p ->
"replace.term " <> HQ.toText src <> " "
<> HQ.toText target <> " "
<> opatch p
ReplaceTypeI srcH targetH p ->
"replace.type " <> hhqs' srcH <> " "
<> hhqs' targetH <> " "
ReplaceTypeI src target p ->
"replace.type " <> HQ.toText src <> " "
<> HQ.toText target <> " "
<> opatch p
ResolveTermNameI path -> "resolve.termName " <> hqs' path
ResolveTypeNameI path -> "resolve.typeName " <> hqs' path
@ -395,10 +435,10 @@ loop = do
QuitI{} -> wat
DeprecateTermI{} -> undefined
DeprecateTypeI{} -> undefined
AddTermReplacementI{} -> undefined
AddTypeReplacementI{} -> undefined
RemoveTermReplacementI{} -> undefined
RemoveTypeReplacementI{} -> undefined
RemoveTermReplacementI src p ->
"delete.term-replacement" <> HQ.toText src <> " " <> opatch p
RemoveTypeReplacementI src p ->
"delete.type-replacement" <> HQ.toText src <> " " <> opatch p
where
hp' = either (Text.pack . show) p'
p' = Text.pack . show . resolveToAbsolute
@ -944,10 +984,10 @@ loop = do
DeleteTypeI hq -> delete (const Set.empty) getHQ'Types hq
DeleteTermI hq -> delete getHQ'Terms (const Set.empty) hq
DisplayI outputLoc (HQ.unsafeFromString -> hq) -> do
DisplayI outputLoc hq -> do
parseNames0 <- (`Names3.Names` mempty) <$> basicPrettyPrintNames0
let parseNames = Names3.suffixify parseNames0
-- use suffixed names for resolving the argument to display
let parseNames = Names3.suffixify parseNames0
let results = Names3.lookupHQTerm hq parseNames
if Set.null results then
respond $ SearchTermsNotFound [hq]
@ -956,12 +996,8 @@ loop = do
-- ... but use the unsuffixed names for display
else doDisplay outputLoc parseNames0 (Set.findMin results)
ShowDefinitionI outputLoc (fmap HQ.unsafeFromString -> hqs) -> do
parseNames0 <- makeHistoricalParsingNames $ Set.fromList hqs
let parseNames = Names3.suffixify parseNames0
let resultss = searchBranchExact hqLength parseNames hqs
(misses, hits) = partition (\(_, results) -> null results) (zip hqs resultss)
results = List.sort . uniqueBy SR.toReferent $ hits >>= snd
ShowDefinitionI outputLoc query -> do
(misses, results) <- hqNameQuerySuffixify query
results' <- loadSearchResults results
let termTypes :: Map.Map Reference (Type v Ann)
termTypes =
@ -1147,9 +1183,16 @@ loop = do
ReplaceTermI from to patchPath -> do
let patchPath' = fromMaybe defaultPatchPath patchPath
patch <- getPatchAt patchPath'
fromRefs <- resolveHHQS'Terms from
toRefs <- resolveHHQS'Terms to
let go :: Reference
(fromMisses', fromHits) <- hqNameQuery [from]
(toMisses', toHits) <- hqNameQuery [to]
let fromRefs = termReferences fromHits
toRefs = termReferences toHits
-- Type hits are term misses
fromMisses = (fst <$> fromMisses')
<> (HQ'.toHQ . SR.typeName <$> typeResults fromHits)
toMisses = (fst <$> toMisses')
<> (HQ'.toHQ . SR.typeName <$> typeResults fromHits)
go :: Reference
-> Reference
-> Action m (Either Event Input) v ()
go fr tr = do
@ -1179,29 +1222,34 @@ loop = do
void $ propagatePatch inputDescription patch' currentPath'
-- Say something
success
sayNotFound = respond
. SearchTermsNotFound
. pure
. either
HQ.HashOnly
(fmap Path.toName' . HQ'.toHQ . Path.unsplitHQ')
sayHashConflicted t = hashConflicted t . Set.map Referent.Ref
sayTermConflicted t = termConflicted t . Set.map Referent.Ref
zeroOneOrMore
fromRefs
(sayNotFound from)
(\r -> zeroOneOrMore toRefs
(sayNotFound to)
(go r)
(either sayHashConflicted sayTermConflicted to))
(either sayHashConflicted sayTermConflicted from)
misses = fromMisses <> toMisses
ambiguous t rs =
let rs' = Set.map Referent.Ref $ Set.fromList rs
in case t of
HQ.HashOnly h ->
hashConflicted h rs'
(Path.parseHQSplit' . HQ.toString -> Right n) ->
termConflicted n rs'
_ -> respond . BadName $ HQ.toString t
when (not $ null misses) $
respond $ SearchTermsNotFound misses
case (fromRefs, toRefs) of
([fr], [tr]) -> go fr tr
([_], tos) -> ambiguous to tos
(frs, _) -> ambiguous from frs
ReplaceTypeI from to patchPath -> do
let patchPath' = fromMaybe defaultPatchPath patchPath
(fromMisses', fromHits) <- hqNameQuery [from]
(toMisses', toHits) <- hqNameQuery [to]
patch <- getPatchAt patchPath'
fromRefs <- resolveHHQS'Types from
toRefs <- resolveHHQS'Types to
let go :: Reference
let fromRefs = typeReferences fromHits
toRefs = typeReferences toHits
-- Term hits are type misses
fromMisses = (fst <$> fromMisses')
<> (HQ'.toHQ . SR.termName <$> termResults fromHits)
toMisses = (fst <$> toMisses')
<> (HQ'.toHQ . SR.termName <$> termResults fromHits)
go :: Reference
-> Reference
-> Action m (Either Event Input) v ()
go fr tr = do
@ -1218,22 +1266,24 @@ loop = do
void $ propagatePatch inputDescription patch' currentPath'
-- Say something
success
sayNotFound = respond
. SearchTermsNotFound
. pure
. either
HQ.HashOnly
(fmap Path.toName' . HQ'.toHQ . Path.unsplitHQ')
sayHashConflicted t = hashConflicted t . Set.map Referent.Ref
zeroOneOrMore
fromRefs
(sayNotFound from)
(\r -> zeroOneOrMore toRefs
(sayNotFound to)
(go r)
(either sayHashConflicted typeConflicted to))
(either sayHashConflicted typeConflicted from)
misses = fromMisses <> toMisses
ambiguous t rs =
let rs' = Set.map Referent.Ref $ Set.fromList rs
in case t of
HQ.HashOnly h ->
hashConflicted h rs'
(Path.parseHQSplit' . HQ.toString -> Right n) ->
typeConflicted n $ Set.fromList rs
-- This is unlikely to happen, as t has to be a parsed
-- hash-qualified name already.
-- Still, the types say we need to handle this case.
_ -> respond . BadName $ HQ.toString t
when (not $ null misses) $
respond $ SearchTermsNotFound misses
case (fromRefs, toRefs) of
([fr], [tr]) -> go fr tr
([_], tos) -> ambiguous to tos
(frs, _) -> ambiguous from frs
LoadI maybePath ->
case maybePath <|> (fst <$> latestFile') of
Nothing -> respond NoUnisonFile
@ -1512,10 +1562,10 @@ loop = do
DeprecateTermI {} -> notImplemented
DeprecateTypeI {} -> notImplemented
AddTermReplacementI {} -> notImplemented
AddTypeReplacementI {} -> notImplemented
RemoveTermReplacementI {} -> notImplemented
RemoveTypeReplacementI {} -> notImplemented
RemoveTermReplacementI from patchPath ->
doRemoveReplacement from patchPath True
RemoveTypeReplacementI from patchPath ->
doRemoveReplacement from patchPath False
ShowDefinitionByPrefixI {} -> notImplemented
UpdateBuiltinsI -> notImplemented
QuitI -> MaybeT $ pure Nothing

View File

@ -15,7 +15,6 @@ import qualified Unison.HashQualified' as HQ'
import Unison.Codebase.Path ( Path' )
import qualified Unison.Codebase.Path as Path
import Unison.Codebase.Editor.RemoteRepo
import Unison.Reference (Reference)
import Unison.ShortHash (ShortHash)
import Unison.Codebase.ShortBranchHash (ShortBranchHash)
import qualified Unison.Codebase.ShortBranchHash as SBH
@ -95,12 +94,10 @@ data Input
-- -- create and remove update directives
| DeprecateTermI PatchPath Path.HQSplit'
| DeprecateTypeI PatchPath Path.HQSplit'
| AddTermReplacementI PatchPath Reference Reference
| AddTypeReplacementI PatchPath Reference Reference
| RemoveTermReplacementI PatchPath Reference Reference
| RemoveTypeReplacementI PatchPath Reference Reference
| ReplaceTermI HashOrHQSplit' HashOrHQSplit' (Maybe PatchPath)
| ReplaceTypeI HashOrHQSplit' HashOrHQSplit' (Maybe PatchPath)
| ReplaceTermI HQ.HashQualified HQ.HashQualified (Maybe PatchPath)
| ReplaceTypeI HQ.HashQualified HQ.HashQualified (Maybe PatchPath)
| RemoveTermReplacementI HQ.HashQualified (Maybe PatchPath)
| RemoveTypeReplacementI HQ.HashQualified (Maybe PatchPath)
| UndoI
-- First `Maybe Int` is cap on number of results, if any
-- Second `Maybe Int` is cap on diff elements shown, if any
@ -115,14 +112,14 @@ data Input
| UnlinkI [Path.HQSplit'] Path.HQSplit'
-- links from <type>
| LinksI Path.HQSplit' (Maybe String)
| DisplayI OutputLocation String
| DisplayI OutputLocation HQ.HashQualified
| DocsI Path.HQSplit'
-- other
| SearchByNameI Bool Bool [String] -- SearchByName isVerbose showAll query
| FindShallowI Path'
| FindPatchI
| ShowDefinitionI OutputLocation [String]
| ShowDefinitionByPrefixI OutputLocation [String]
| ShowDefinitionI OutputLocation [HQ.HashQualified]
| ShowDefinitionByPrefixI OutputLocation [HQ.HashQualified]
| ShowReflogI
| UpdateBuiltinsI
| MergeBuiltinsI

View File

@ -192,6 +192,7 @@ data Output v
| NoBranchWithHash ShortBranchHash
| DumpNumberedArgs NumberedArgs
| DumpBitBooster Branch.Hash (Map Branch.Hash [Branch.Hash])
| BadName String
deriving (Show)
data ReflogEntry =
@ -263,6 +264,7 @@ isFailure o = case o of
TermAmbiguous{} -> True
BranchHashAmbiguous{} -> True
BadDestinationBranch{} -> True
BadName{} -> True
BranchNotFound{} -> True
NameNotFound{} -> True
PatchNotFound{} -> True

View File

@ -258,28 +258,45 @@ patch = InputPattern
)
view :: InputPattern
view = InputPattern "view" [] [(OnePlus, definitionQueryArg)]
"`view foo` prints the definition of `foo`."
(pure . Input.ShowDefinitionI Input.ConsoleLocation)
view = InputPattern
"view"
[]
[(OnePlus, definitionQueryArg)]
"`view foo` prints the definition of `foo`."
( fmap (Input.ShowDefinitionI Input.ConsoleLocation)
. traverse parseHashQualifiedName
)
display :: InputPattern
display = InputPattern "display" [] [(Required, definitionQueryArg)]
"`display foo` prints a rendered version of the term `foo`."
(\case
[s] -> pure (Input.DisplayI Input.ConsoleLocation s)
_ -> Left (I.help display))
display = InputPattern
"display"
[]
[(Required, definitionQueryArg)]
"`display foo` prints a rendered version of the term `foo`."
(\case
[s] -> Input.DisplayI Input.ConsoleLocation <$> parseHashQualifiedName s
_ -> Left (I.help display)
)
displayTo :: InputPattern
displayTo = InputPattern "display.to" [] [(Required, noCompletions), (Required, definitionQueryArg)]
(P.wrap $ makeExample displayTo ["<filename>", "foo"]
<> "prints a rendered version of the term `foo` to the given file.")
(\case
[file,s] -> pure (Input.DisplayI (Input.FileLocation file) s)
_ -> Left (I.help displayTo))
displayTo = InputPattern
"display.to"
[]
[(Required, noCompletions), (Required, definitionQueryArg)]
( P.wrap
$ makeExample displayTo ["<filename>", "foo"]
<> "prints a rendered version of the term `foo` to the given file."
)
(\case
[file, s] ->
Input.DisplayI (Input.FileLocation file) <$> parseHashQualifiedName s
_ -> Left (I.help displayTo)
)
docs :: InputPattern
docs = InputPattern "docs" [] [(Required, definitionQueryArg)]
("`docs foo` shows documentation for the definition `foo`.")
"`docs foo` shows documentation for the definition `foo`."
(\case
[s] -> first fromString $ Input.DocsI <$> Path.parseHQSplit' s
_ -> Left (I.help docs))
@ -290,10 +307,14 @@ undo = InputPattern "undo" [] []
(const $ pure Input.UndoI)
viewByPrefix :: InputPattern
viewByPrefix
= InputPattern "view.recursive" [] [(OnePlus, definitionQueryArg)]
"`view.recursive Foo` prints the definitions of `Foo` and `Foo.blah`."
(pure . Input.ShowDefinitionByPrefixI Input.ConsoleLocation)
viewByPrefix = InputPattern
"view.recursive"
[]
[(OnePlus, definitionQueryArg)]
"`view.recursive Foo` prints the definitions of `Foo` and `Foo.blah`."
( fmap (Input.ShowDefinitionByPrefixI Input.ConsoleLocation)
. traverse parseHashQualifiedName
)
find :: InputPattern
find = InputPattern
@ -415,6 +436,70 @@ deleteType = InputPattern "delete.type" []
"`delete.type` takes an argument, like `delete.type name`."
)
deleteTermReplacementCommand :: String
deleteTermReplacementCommand = "delete.term-replacement"
deleteTypeReplacementCommand :: String
deleteTypeReplacementCommand = "delete.type-replacement"
deleteReplacement :: Bool -> InputPattern
deleteReplacement isTerm = InputPattern
commandName
[]
[(Required, if isTerm then exactDefinitionTermQueryArg else exactDefinitionTypeQueryArg), (Optional, patchArg)]
( P.string
$ commandName
<> " <patch>` removes any edit of the "
<> str
<> " `foo` "
<> "from the patch `patch`, or the default patch if none is specified."
)
(\case
query : patch -> do
patch <-
first fromString
. traverse (Path.parseSplit' Path.wordyNameSegment)
$ listToMaybe patch
q <- parseHashQualifiedName query
pure $ input q patch
_ ->
Left
. P.warnCallout
. P.wrapString
$ commandName
<> " needs arguments. See `help "
<> commandName
<> "`."
)
where
input = if isTerm
then Input.RemoveTermReplacementI
else Input.RemoveTypeReplacementI
str = if isTerm then "term" else "type"
commandName = if isTerm
then deleteTermReplacementCommand
else deleteTypeReplacementCommand
deleteTermReplacement :: InputPattern
deleteTermReplacement = deleteReplacement True
deleteTypeReplacement :: InputPattern
deleteTypeReplacement = deleteReplacement False
parseHashQualifiedName
:: String -> Either (P.Pretty CT.ColorText) HQ.HashQualified
parseHashQualifiedName s =
maybe
( Left
. P.warnCallout
. P.wrap
$ P.string s
<> " is not a well-formed name, hash, or hash-qualified name. "
<> "I expected something like `foo`, `#abc123`, or `foo#abc123`."
)
Right
$ HQ.fromString s
aliasTerm :: InputPattern
aliasTerm = InputPattern "alias.term" []
[(Required, exactDefinitionTermQueryArg), (Required, newNameArg)]
@ -689,8 +774,8 @@ createPullRequest = InputPattern "pull-request.create" ["pr.create"]
<> "will generate a request to merge the remote repo `head`"
<> "into the remote repo `base`."
, ""
, "example: " <>
makeExampleNoBackticks createPullRequest ["https://github.com/unisonweb/base",
, "example: " <>
makeExampleNoBackticks createPullRequest ["https://github.com/unisonweb/base",
"https://github.com/me/unison:.libs.pr.base" ]
])
(\case
@ -793,10 +878,7 @@ previewMergeLocal = InputPattern
)
replaceEdit
:: (Input.HashOrHQSplit'
-> Input.HashOrHQSplit'
-> Maybe Input.PatchPath
-> Input)
:: (HQ.HashQualified -> HQ.HashQualified -> Maybe Input.PatchPath -> Input)
-> String
-> InputPattern
replaceEdit f s = self
@ -825,12 +907,14 @@ replaceEdit f s = self
]
)
(\case
source : target : patch -> first fromString $ do
src <- Path.parseShortHashOrHQSplit' source
dest <- Path.parseShortHashOrHQSplit' target
patch <- traverse (Path.parseSplit' Path.wordyNameSegment)
$ listToMaybe patch
pure $ f src dest patch
source : target : patch -> do
patch <-
first fromString
<$> traverse (Path.parseSplit' Path.wordyNameSegment)
$ listToMaybe patch
sourcehq <- parseHashQualifiedName source
targethq <- parseHashQualifiedName target
pure $ f sourcehq targethq patch
_ -> Left $ I.help self
)
@ -859,7 +943,9 @@ edit = InputPattern
( "`edit foo` prepends the definition of `foo` to the top of the most "
<> "recently saved file."
)
(pure . Input.ShowDefinitionI Input.LatestFileLocation)
( fmap (Input.ShowDefinitionI Input.LatestFileLocation)
. traverse parseHashQualifiedName
)
topicNameArg :: ArgumentType
topicNameArg =
@ -1174,6 +1260,8 @@ validInputs =
, links
, replaceTerm
, replaceType
, deleteTermReplacement
, deleteTypeReplacement
, test
, execute
, viewReflog

View File

@ -670,7 +670,9 @@ notifyUser dir o = case o of
else "Edited Terms:" `P.hang`
P.column2 (prettyTermEdit <$> R.toList terms),
if R.null types && R.null terms then "This patch is empty."
else mempty
else tip . P.string $ "To remove entries from a patch, use "
<> IP.deleteTermReplacementCommand <> " or "
<> IP.deleteTypeReplacementCommand <> ", as appropriate."
]
BustedBuiltins (Set.toList -> new) (Set.toList -> old) ->
-- todo: this could be prettier! Have a nice list like `find` gives, but
@ -799,6 +801,8 @@ notifyUser dir o = case o of
P.wrap "Try again with a few more hash characters to disambiguate."
]
BadDestinationBranch _ -> pure "That destination namespace is bad."
BadName n ->
pure . P.wrap $ P.string n <> " is not a kind of name I understand."
TermNotFound' sh ->
pure $ "I could't find a term with hash "
<> (prettyShortHash sh)

View File

@ -1,6 +1,5 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE BangPatterns #-}
module Unison.Typechecker.TypeError where

View File

@ -159,7 +159,7 @@ requalify hq r = case hq of
HashQualified n _ -> fromNamedReferent n r
HashOnly _ -> fromReferent r
-- this implementation shows HashOnly before the others, because None < Some.
-- this implementation shows HashOnly before the others, because None < Some.
-- Flip it around carefully if HashOnly should come last.
instance Ord n => Ord (HashQualified' n) where
compare a b = case compare (toName a) (toName b) of

View File

@ -0,0 +1,46 @@
# Deleting term and type replacements from patches
```unison
x = 1
```
```ucm
.> add
```
```unison
x = 2
```
```ucm
.> update
.> view.patch
```
```ucm
.> delete.term-replacement #jk19
.> view.patch
```
```unison
type Foo = Foo
```
```ucm
.> add
```
```unison
type Foo = Foo | Bar
```
```ucm
.> update
.> view.patch
```
```ucm
.> delete.type-replacement #568rsi7o3g
.> view.patch
```

View File

@ -0,0 +1,144 @@
# Deleting term and type replacements from patches
```unison
x = 1
```
```ucm
I found and typechecked these definitions in scratch.u. If you
do an `add` or `update`, here's how your codebase would
change:
⍟ These new definitions are ok to `add`:
x : ##Nat
Now evaluating any watch expressions (lines starting with
`>`)... Ctrl+C cancels.
```
```ucm
.> add
⍟ I've added these definitions:
x : ##Nat
```
```unison
x = 2
```
```ucm
I found and typechecked these definitions in scratch.u. If you
do an `add` or `update`, here's how your codebase would
change:
⍟ These names already exist. You can `update` them to your
new definition:
x : ##Nat
Now evaluating any watch expressions (lines starting with
`>`)... Ctrl+C cancels.
```
```ucm
.> update
⍟ I've updated these names to your new definition:
x : ##Nat
.> view.patch
Edited Terms: x#jk19sm5bf8 -> x
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
```
```ucm
.> delete.term-replacement #jk19
Done.
.> view.patch
This patch is empty.
```
```unison
type Foo = Foo
```
```ucm
I found and typechecked these definitions in scratch.u. If you
do an `add` or `update`, here's how your codebase would
change:
⍟ These new definitions are ok to `add`:
type Foo
Now evaluating any watch expressions (lines starting with
`>`)... Ctrl+C cancels.
```
```ucm
.> add
⍟ I've added these definitions:
type Foo
```
```unison
type Foo = Foo | Bar
```
```ucm
I found and typechecked these definitions in scratch.u. If you
do an `add` or `update`, here's how your codebase would
change:
⍟ These names already exist. You can `update` them to your
new definition:
type Foo
Now evaluating any watch expressions (lines starting with
`>`)... Ctrl+C cancels.
```
```ucm
.> update
⍟ I've updated these names to your new definition:
type Foo
.> view.patch
Edited Types: Foo#568rsi7o3g -> Foo
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
```
```ucm
.> delete.type-replacement #568rsi7o3g
Done.
.> view.patch
This patch is empty.
```

View File

@ -424,6 +424,10 @@ unique type Y a b = Y a b
Edited Terms:
ns1.b -> ns2.b
ns1.fromJust' -> ns2.fromJust
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
.> fork ns2 ns3

View File

@ -71,9 +71,17 @@ Update
.> view.patch patch
Edited Terms: hey#8e79ctircj -> hey
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
.> view.patch 1
Edited Terms: hey#8e79ctircj -> hey
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
```

View File

@ -82,6 +82,10 @@ We used to have to know the full hash for a definition to be able to use the `re
.> view.patch
Edited Terms: f#msp7bv40rv -> f
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
```
The value of `h` should have been updated too:

View File

@ -128,10 +128,18 @@ The `a` and `b` namespaces now each contain a patch named `patch`. We can view t
.example.resolve> view.patch a.patch
Edited Terms: c.foo -> a.foo
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
.example.resolve> view.patch b.patch
Edited Terms: c.foo -> b.foo
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
```
Let's now merge these namespaces into `c`:
@ -215,6 +223,10 @@ This changes the merged `c.patch` so that only the edit from #44954ulpdf to #8e
.example.resolve.c> view.patch
Edited Terms: foo#44954ulpdf -> foo#8e68dvpr0a
Tip: To remove entries from a patch, use
delete.term-replacement or delete.type-replacement, as
appropriate.
```
We still have a remaining _name conflict_ since it just so happened that both of the definitions in the edits were named `foo`.