mirror of
https://github.com/unisonweb/unison.git
synced 2024-09-11 02:25:39 +03:00
deprecate cd
, up
; add find-in
(#4883)
* deprecate `cd`, `up`, hide `reset-root`, add `find-in`, hides unimplemented `update.builtins` Co-authored-by: Chris Penner <christopher.penner@gmail.com>
This commit is contained in:
parent
61c5bebf44
commit
2cf96a36ae
@ -24,6 +24,7 @@ module Unison.Codebase.Path
|
||||
prefix,
|
||||
unprefix,
|
||||
prefixName,
|
||||
prefixName2,
|
||||
unprefixName,
|
||||
HQSplit,
|
||||
Split,
|
||||
@ -192,6 +193,11 @@ prefix (Absolute (Path prefix)) = \case
|
||||
AbsolutePath' abs -> unabsolute abs
|
||||
RelativePath' rel -> Path $ prefix <> toSeq (unrelative rel)
|
||||
|
||||
prefix2 :: Path -> Path' -> Path
|
||||
prefix2 (Path prefix) = \case
|
||||
AbsolutePath' abs -> unabsolute abs
|
||||
RelativePath' rel -> Path $ prefix <> toSeq (unrelative rel)
|
||||
|
||||
-- | Finds the longest shared path prefix of two paths.
|
||||
-- Returns (shared prefix, path to first location from shared prefix, path to second location from shared prefix)
|
||||
--
|
||||
@ -273,6 +279,9 @@ unprefixName prefix = toName . unprefix prefix . fromName'
|
||||
prefixName :: Absolute -> Name -> Name
|
||||
prefixName p n = fromMaybe n . toName . prefix p . fromName' $ n
|
||||
|
||||
prefixName2 :: Path -> Name -> Name
|
||||
prefixName2 p n = fromMaybe n . toName . prefix2 p . fromName' $ n
|
||||
|
||||
singleton :: NameSegment -> Path
|
||||
singleton n = fromList [n]
|
||||
|
||||
|
@ -6,4 +6,4 @@ true \
|
||||
&& stack exec transcripts \
|
||||
&& stack exec unison transcript unison-src/transcripts-round-trip/main.md \
|
||||
&& stack exec unison transcript unison-src/transcripts-manual/rewrites.md \
|
||||
&& stack exec integration-tests
|
||||
&& stack exec cli-integration-tests
|
||||
|
@ -1429,24 +1429,28 @@ handleFindI ::
|
||||
Cli ()
|
||||
handleFindI isVerbose fscope ws input = do
|
||||
Cli.Env {codebase} <- ask
|
||||
currentBranch0 <- Cli.getCurrentBranch0
|
||||
(pped, names) <- case fscope of
|
||||
FindLocal -> do
|
||||
let names = Branch.toNames (Branch.withoutLib currentBranch0)
|
||||
(pped, names, searchRoot, branch0) <- case fscope of
|
||||
FindLocal p -> do
|
||||
searchRoot <- Cli.resolvePath p
|
||||
branch0 <- Cli.getBranch0At searchRoot
|
||||
let names = Branch.toNames (Branch.withoutLib branch0)
|
||||
-- Don't exclude anything from the pretty printer, since the type signatures we print for
|
||||
-- results may contain things in lib.
|
||||
pped <- Cli.currentPrettyPrintEnvDecl
|
||||
pure (pped, names)
|
||||
FindLocalAndDeps -> do
|
||||
let names = Branch.toNames (Branch.withoutTransitiveLibs currentBranch0)
|
||||
pure (pped, names, Just p, branch0)
|
||||
FindLocalAndDeps p -> do
|
||||
searchRoot <- Cli.resolvePath p
|
||||
branch0 <- Cli.getBranch0At searchRoot
|
||||
let names = Branch.toNames (Branch.withoutTransitiveLibs branch0)
|
||||
-- Don't exclude anything from the pretty printer, since the type signatures we print for
|
||||
-- results may contain things in lib.
|
||||
pped <- Cli.currentPrettyPrintEnvDecl
|
||||
pure (pped, names)
|
||||
pure (pped, names, Just p, branch0)
|
||||
FindGlobal -> do
|
||||
globalNames <- Names.makeAbsolute . Branch.toNames <$> Cli.getRootBranch0
|
||||
pped <- Cli.prettyPrintEnvDeclFromNames globalNames
|
||||
pure (pped, globalNames)
|
||||
currentBranch0 <- Cli.getCurrentBranch0
|
||||
pure (pped, globalNames, Nothing, currentBranch0)
|
||||
let suffixifiedPPE = PPED.suffixifiedPPE pped
|
||||
let getResults :: Names -> Cli [SearchResult]
|
||||
getResults names =
|
||||
@ -1455,7 +1459,7 @@ handleFindI isVerbose fscope ws input = do
|
||||
-- type query
|
||||
":" : ws -> do
|
||||
typ <- parseSearchType (show input) (unwords ws)
|
||||
let keepNamed = Set.intersection (Branch.deepReferents currentBranch0)
|
||||
let keepNamed = Set.intersection (Branch.deepReferents branch0)
|
||||
(noExactTypeMatches, matches) <- do
|
||||
Cli.runTransaction do
|
||||
matches <- keepNamed <$> Codebase.termsOfType codebase typ
|
||||
@ -1481,16 +1485,16 @@ handleFindI isVerbose fscope ws input = do
|
||||
(mapMaybe (HQ.parseTextWith anythingBeforeHash . Text.pack) qs)
|
||||
pure $ uniqueBy SR.toReferent srs
|
||||
let respondResults results = do
|
||||
Cli.setNumberedArgs $ fmap searchResultToHQString results
|
||||
Cli.setNumberedArgs $ fmap (searchResultToHQString searchRoot) results
|
||||
results' <- Cli.runTransaction (Backend.loadSearchResults codebase results)
|
||||
Cli.respond $ ListOfDefinitions fscope suffixifiedPPE isVerbose results'
|
||||
results <- getResults names
|
||||
case (results, fscope) of
|
||||
([], FindLocal) -> do
|
||||
([], FindLocal {}) -> do
|
||||
Cli.respond FindNoLocalMatches
|
||||
-- We've already searched everything else, so now we search JUST the
|
||||
-- names in lib.
|
||||
let mayOnlyLibBranch = currentBranch0 & Branch.children %%~ \cs -> Map.singleton NameSegment.libSegment <$> Map.lookup NameSegment.libSegment cs
|
||||
let mayOnlyLibBranch = branch0 & Branch.children %%~ \cs -> Map.singleton NameSegment.libSegment <$> Map.lookup NameSegment.libSegment cs
|
||||
case mayOnlyLibBranch of
|
||||
Nothing -> respondResults []
|
||||
Just onlyLibBranch -> do
|
||||
@ -1804,11 +1808,14 @@ confirmedCommand i = do
|
||||
pure $ Just i == (loopState ^. #lastInput)
|
||||
|
||||
-- | restores the full hash to these search results, for _numberedArgs purposes
|
||||
searchResultToHQString :: SearchResult -> String
|
||||
searchResultToHQString = \case
|
||||
SR.Tm' n r _ -> Text.unpack $ HQ.toText $ HQ.requalify n r
|
||||
SR.Tp' n r _ -> Text.unpack $ HQ.toText $ HQ.requalify n (Referent.Ref r)
|
||||
searchResultToHQString :: Maybe Path -> SearchResult -> String
|
||||
searchResultToHQString oprefix = \case
|
||||
SR.Tm' n r _ -> Text.unpack $ HQ.toText $ HQ.requalify (addPrefix <$> n) r
|
||||
SR.Tp' n r _ -> Text.unpack $ HQ.toText $ HQ.requalify (addPrefix <$> n) (Referent.Ref r)
|
||||
_ -> error "impossible match failure"
|
||||
where
|
||||
addPrefix :: Name -> Name
|
||||
addPrefix = maybe id Path.prefixName2 oprefix
|
||||
|
||||
-- return `name` and `name.<everything>...`
|
||||
_searchBranchPrefix :: Branch m -> Name -> [SearchResult]
|
||||
|
@ -35,7 +35,7 @@ import Data.These (These)
|
||||
import U.Codebase.HashTags (CausalHash)
|
||||
import Unison.Codebase.Branch.Merge qualified as Branch
|
||||
import Unison.Codebase.Editor.RemoteRepo (ReadRemoteNamespace, WriteGitRepo, WriteRemoteNamespace)
|
||||
import Unison.Codebase.Path (Path')
|
||||
import Unison.Codebase.Path (Path, Path')
|
||||
import Unison.Codebase.Path qualified as Path
|
||||
import Unison.Codebase.Path.Parse qualified as Path
|
||||
import Unison.Codebase.PushBehavior (PushBehavior)
|
||||
@ -313,8 +313,8 @@ data OutputLocation
|
||||
deriving (Eq, Show)
|
||||
|
||||
data FindScope
|
||||
= FindLocal
|
||||
| FindLocalAndDeps
|
||||
= FindLocal Path
|
||||
| FindLocalAndDeps Path
|
||||
| FindGlobal
|
||||
deriving stock (Eq, Show)
|
||||
|
||||
|
@ -124,7 +124,7 @@ updateBuiltins =
|
||||
InputPattern
|
||||
"builtins.update"
|
||||
[]
|
||||
I.Visible
|
||||
I.Hidden
|
||||
[]
|
||||
( "Adds all the builtins that are missing from this namespace, "
|
||||
<> "and deprecate the ones that don't exist in this version of Unison."
|
||||
@ -531,7 +531,7 @@ sfind :: InputPattern
|
||||
sfind =
|
||||
InputPattern "rewrite.find" ["sfind"] I.Visible [("rewrite-rule definition", Required, definitionQueryArg)] msg parse
|
||||
where
|
||||
parse [q] = Input.StructuredFindI Input.FindLocal <$> parseHashQualifiedName q
|
||||
parse [q] = Input.StructuredFindI (Input.FindLocal Path.empty) <$> parseHashQualifiedName q
|
||||
parse _ = Left "expected exactly one argument"
|
||||
msg =
|
||||
P.lines
|
||||
@ -589,14 +589,68 @@ sfindReplace =
|
||||
]
|
||||
|
||||
find :: InputPattern
|
||||
find = find' "find" Input.FindLocal
|
||||
find = find' "find" (Input.FindLocal Path.empty)
|
||||
|
||||
findAll :: InputPattern
|
||||
findAll = find' "find.all" Input.FindLocalAndDeps
|
||||
findAll = find' "find.all" (Input.FindLocalAndDeps Path.empty)
|
||||
|
||||
findGlobal :: InputPattern
|
||||
findGlobal = find' "find.global" Input.FindGlobal
|
||||
|
||||
findIn, findInAll :: InputPattern
|
||||
findIn = findIn' "find-in" Input.FindLocal
|
||||
findInAll = findIn' "find-in.all" Input.FindLocalAndDeps
|
||||
|
||||
findIn' :: String -> (Path.Path -> Input.FindScope) -> InputPattern
|
||||
findIn' cmd mkfscope =
|
||||
InputPattern
|
||||
cmd
|
||||
[]
|
||||
I.Visible
|
||||
[("namespace", Required, namespaceArg), ("query", ZeroPlus, exactDefinitionArg)]
|
||||
findHelp
|
||||
\case
|
||||
p : args -> first P.text do
|
||||
p <- Path.parsePath p
|
||||
pure (Input.FindI False (mkfscope p) args)
|
||||
_ -> Left findHelp
|
||||
|
||||
findHelp :: P.Pretty CT.ColorText
|
||||
findHelp =
|
||||
( P.wrapColumn2
|
||||
[ ("`find`", "lists all definitions in the current namespace."),
|
||||
( "`find foo`",
|
||||
"lists all definitions with a name similar to 'foo' in the current "
|
||||
<> "namespace (excluding those under 'lib')."
|
||||
),
|
||||
( "`find foo bar`",
|
||||
"lists all definitions with a name similar to 'foo' or 'bar' in the "
|
||||
<> "current namespace (excluding those under 'lib')."
|
||||
),
|
||||
( "`find-in namespace`",
|
||||
"lists all definitions in the specified subnamespace."
|
||||
),
|
||||
( "`find-in namespace foo bar`",
|
||||
"lists all definitions with a name similar to 'foo' or 'bar' in the "
|
||||
<> "specified subnamespace."
|
||||
),
|
||||
( "find.all foo",
|
||||
"lists all definitions with a name similar to 'foo' in the current "
|
||||
<> "namespace (including one level of 'lib')."
|
||||
),
|
||||
( "`find-in.all namespace`",
|
||||
"lists all definitions in the specified subnamespace (including one level of its 'lib')."
|
||||
),
|
||||
( "`find-in.all namespace foo bar`",
|
||||
"lists all definitions with a name similar to 'foo' or 'bar' in the "
|
||||
<> "specified subnamespace (including one level of its 'lib')."
|
||||
),
|
||||
( "find.global foo",
|
||||
"lists all definitions with a name similar to 'foo' in any namespace"
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
find' :: String -> Input.FindScope -> InputPattern
|
||||
find' cmd fscope =
|
||||
InputPattern
|
||||
@ -604,25 +658,7 @@ find' cmd fscope =
|
||||
[]
|
||||
I.Visible
|
||||
[("query", ZeroPlus, exactDefinitionArg)]
|
||||
( P.wrapColumn2
|
||||
[ ("`find`", "lists all definitions in the current namespace."),
|
||||
( "`find foo`",
|
||||
"lists all definitions with a name similar to 'foo' in the current "
|
||||
<> "namespace (excluding those under 'lib')."
|
||||
),
|
||||
( "`find foo bar`",
|
||||
"lists all definitions with a name similar to 'foo' or 'bar' in the "
|
||||
<> "current namespace (excluding those under 'lib')."
|
||||
),
|
||||
( "find.all foo",
|
||||
"lists all definitions with a name similar to 'foo' in the current "
|
||||
<> "namespace (including one level of 'lib')."
|
||||
),
|
||||
( "find.global foo",
|
||||
"lists all definitions with a name similar to 'foo' in any namespace"
|
||||
)
|
||||
]
|
||||
)
|
||||
findHelp
|
||||
(pure . Input.FindI False fscope)
|
||||
|
||||
findShallow :: InputPattern
|
||||
@ -656,7 +692,7 @@ findVerbose =
|
||||
( "`find.verbose` searches for definitions like `find`, but includes hashes "
|
||||
<> "and aliases in the results."
|
||||
)
|
||||
(pure . Input.FindI True Input.FindLocal)
|
||||
(pure . Input.FindI True (Input.FindLocal Path.empty))
|
||||
|
||||
findVerboseAll :: InputPattern
|
||||
findVerboseAll =
|
||||
@ -668,7 +704,7 @@ findVerboseAll =
|
||||
( "`find.all.verbose` searches for definitions like `find.all`, but includes hashes "
|
||||
<> "and aliases in the results."
|
||||
)
|
||||
(pure . Input.FindI True Input.FindLocalAndDeps)
|
||||
(pure . Input.FindI True (Input.FindLocalAndDeps Path.empty))
|
||||
|
||||
findPatch :: InputPattern
|
||||
findPatch =
|
||||
@ -968,11 +1004,11 @@ aliasMany =
|
||||
up :: InputPattern
|
||||
up =
|
||||
InputPattern
|
||||
"up"
|
||||
"deprecated.up"
|
||||
[]
|
||||
I.Visible
|
||||
I.Hidden
|
||||
[]
|
||||
(P.wrapColumn2 [(makeExample up [], "move current path up one level")])
|
||||
(P.wrapColumn2 [(makeExample up [], "move current path up one level (deprecated)")])
|
||||
( \case
|
||||
[] -> Right Input.UpI
|
||||
_ -> Left (I.help up)
|
||||
@ -981,12 +1017,12 @@ up =
|
||||
cd :: InputPattern
|
||||
cd =
|
||||
InputPattern
|
||||
"namespace"
|
||||
["cd", "j"]
|
||||
"deprecated.cd"
|
||||
["deprecated.namespace"]
|
||||
I.Visible
|
||||
[("namespace", Required, namespaceArg)]
|
||||
( P.lines
|
||||
[ "Moves your perspective to a different namespace.",
|
||||
[ "Moves your perspective to a different namespace. Deprecated for now because too many important things depend on your perspective selection.",
|
||||
"",
|
||||
P.wrapColumn2
|
||||
[ ( makeExample cd ["foo.bar"],
|
||||
@ -1020,7 +1056,7 @@ back =
|
||||
[]
|
||||
( P.wrapColumn2
|
||||
[ ( makeExample back [],
|
||||
"undoes the last" <> makeExample' cd <> "command."
|
||||
"undoes the last" <> makeExample' projectSwitch <> "command."
|
||||
)
|
||||
]
|
||||
)
|
||||
@ -1233,15 +1269,18 @@ resetRoot =
|
||||
InputPattern
|
||||
"reset-root"
|
||||
[]
|
||||
I.Visible
|
||||
I.Hidden
|
||||
[("namespace or hash to reset to", Required, namespaceArg)]
|
||||
( P.wrapColumn2
|
||||
[ ( makeExample resetRoot [".foo"],
|
||||
"Reset the root namespace (along with its history) to that of the `.foo` namespace."
|
||||
),
|
||||
( makeExample resetRoot ["#9dndk3kbsk13nbpeu"],
|
||||
"Reset the root namespace (along with its history) to that of the namespace with hash `#9dndk3kbsk13nbpeu`."
|
||||
)
|
||||
( P.lines
|
||||
[ "Deprecated because it's incompatible with projects. ⚠️ Warning, this command can cause codebase corruption.",
|
||||
P.wrapColumn2
|
||||
[ ( makeExample resetRoot [".foo"],
|
||||
"Reset the root namespace (along with its history) to that of the `.foo` namespace. Deprecated"
|
||||
),
|
||||
( makeExample resetRoot ["#9dndk3kbsk13nbpeu"],
|
||||
"Reset the root namespace (along with its history) to that of the namespace with hash `#9dndk3kbsk13nbpeu`."
|
||||
)
|
||||
]
|
||||
]
|
||||
)
|
||||
\case
|
||||
@ -2982,7 +3021,9 @@ validInputs =
|
||||
editNamespace,
|
||||
execute,
|
||||
find,
|
||||
findIn,
|
||||
findAll,
|
||||
findInAll,
|
||||
findGlobal,
|
||||
findPatch,
|
||||
findShallow,
|
||||
|
@ -971,8 +971,8 @@ notifyUser dir = \case
|
||||
pure . P.warnCallout . P.lines $
|
||||
[ "Are you sure you want to clear away everything?",
|
||||
"You could use "
|
||||
<> IP.makeExample' IP.cd
|
||||
<> " to switch to a new namespace instead."
|
||||
<> IP.makeExample' IP.projectCreate
|
||||
<> " to switch to a new project instead."
|
||||
]
|
||||
DeleteBranchConfirmation _uniqueDeletions -> error "todo"
|
||||
-- let
|
||||
|
@ -12,7 +12,6 @@ transcripts which contain less boilerplate.
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> builtins.mergeio
|
||||
.> cd builtin
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
```
|
||||
@ -55,4 +54,3 @@ testAutoClean _ =
|
||||
.> add
|
||||
.> io.test testAutoClean
|
||||
```
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> builtins.mergeio
|
||||
.> cd builtin
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
.> find
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> cd builtin
|
||||
```
|
||||
|
||||
Unison has cryptographic builtins for hashing and computing [HMACs](https://en.wikipedia.org/wiki/HMAC) (hash-based message authentication codes). This transcript shows their usage and has some test cases.
|
||||
@ -48,8 +47,7 @@ ex5 = crypto.hmac Sha2_256 mysecret f |> hex
|
||||
And here's the full API:
|
||||
|
||||
```ucm
|
||||
.builtin.crypto> find
|
||||
.> cd .
|
||||
.> find-in builtin.crypto
|
||||
```
|
||||
|
||||
Note that the universal versions of `hash` and `hmac` are currently unimplemented and will bomb at runtime:
|
||||
@ -263,4 +261,3 @@ test> md5.tests.ex3 =
|
||||
```ucm
|
||||
.> test
|
||||
```
|
||||
|
||||
|
@ -120,18 +120,18 @@ ex5 = crypto.hmac Sha2_256 mysecret f |> hex
|
||||
And here's the full API:
|
||||
|
||||
```ucm
|
||||
.builtin.crypto> find
|
||||
.> find-in builtin.crypto
|
||||
|
||||
1. type CryptoFailure
|
||||
2. Ed25519.sign.impl : ##Bytes
|
||||
-> ##Bytes
|
||||
-> ##Bytes
|
||||
-> #0o7mf021fo #r29dja8j9d ##Bytes
|
||||
3. Ed25519.verify.impl : ##Bytes
|
||||
-> ##Bytes
|
||||
-> ##Bytes
|
||||
-> #0o7mf021fo #r29dja8j9d ##Boolean
|
||||
4. hash : HashAlgorithm -> a -> ##Bytes
|
||||
2. Ed25519.sign.impl : Bytes
|
||||
-> Bytes
|
||||
-> Bytes
|
||||
-> Either Failure Bytes
|
||||
3. Ed25519.verify.impl : Bytes
|
||||
-> Bytes
|
||||
-> Bytes
|
||||
-> Either Failure Boolean
|
||||
4. hash : HashAlgorithm -> a -> Bytes
|
||||
5. builtin type HashAlgorithm
|
||||
6. HashAlgorithm.Blake2b_256 : HashAlgorithm
|
||||
7. HashAlgorithm.Blake2b_512 : HashAlgorithm
|
||||
@ -142,13 +142,11 @@ And here's the full API:
|
||||
12. HashAlgorithm.Sha2_512 : HashAlgorithm
|
||||
13. HashAlgorithm.Sha3_256 : HashAlgorithm
|
||||
14. HashAlgorithm.Sha3_512 : HashAlgorithm
|
||||
15. hashBytes : HashAlgorithm -> ##Bytes -> ##Bytes
|
||||
16. hmac : HashAlgorithm -> ##Bytes -> a -> ##Bytes
|
||||
17. hmacBytes : HashAlgorithm -> ##Bytes -> ##Bytes -> ##Bytes
|
||||
15. hashBytes : HashAlgorithm -> Bytes -> Bytes
|
||||
16. hmac : HashAlgorithm -> Bytes -> a -> Bytes
|
||||
17. hmacBytes : HashAlgorithm -> Bytes -> Bytes -> Bytes
|
||||
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
Note that the universal versions of `hash` and `hmac` are currently unimplemented and will bomb at runtime:
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
>
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> cd builtin
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
```
|
||||
|
@ -3,7 +3,6 @@
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> builtins.mergeio
|
||||
.> cd builtin
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
```
|
||||
@ -61,7 +60,7 @@ serverThread portVar toSend = 'let
|
||||
cert = decodeCert (toUtf8 self_signed_cert_pem2)
|
||||
|
||||
-- assume there is exactly one key decoded from our Bytes
|
||||
key = match (decodePrivateKey (toUtf8 self_signed_key_pem)) with
|
||||
key = match (decodePrivateKey (toUtf8 self_signed_key_pem)) with
|
||||
k +: _ -> k
|
||||
[] -> bug "oh no"
|
||||
|
||||
|
@ -80,7 +80,7 @@ serverThread portVar toSend = 'let
|
||||
cert = decodeCert (toUtf8 self_signed_cert_pem2)
|
||||
|
||||
-- assume there is exactly one key decoded from our Bytes
|
||||
key = match (decodePrivateKey (toUtf8 self_signed_key_pem)) with
|
||||
key = match (decodePrivateKey (toUtf8 self_signed_key_pem)) with
|
||||
k +: _ -> k
|
||||
[] -> bug "oh no"
|
||||
|
||||
|
@ -3,7 +3,6 @@ Test for new Text -> Bytes conversions explicitly using UTF-8 as the encoding
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> builtins.mergeio
|
||||
.> cd builtin
|
||||
```
|
||||
|
||||
Unison has function for converting between `Text` and a UTF-8 `Bytes` encoding of the Text.
|
||||
@ -31,13 +30,13 @@ greek = "ΑΒΓΔΕ"
|
||||
> toUtf8 greek
|
||||
```
|
||||
|
||||
We can check that encoding and then decoding should give us back the same `Text` we started with
|
||||
We can check that encoding and then decoding should give us back the same `Text` we started with
|
||||
|
||||
```unison
|
||||
checkRoundTrip: Text -> [Result]
|
||||
checkRoundTrip t =
|
||||
checkRoundTrip t =
|
||||
bytes = toUtf8 t
|
||||
match fromUtf8.impl bytes with
|
||||
match fromUtf8.impl bytes with
|
||||
Left e -> [Result.Fail "could not decode"]
|
||||
Right t' -> if t == t' then [Result.Ok "Passed"] else [Result.Fail ("Got: " ++ t' ++ " Expected: " ++ t)]
|
||||
|
||||
|
@ -71,13 +71,13 @@ greek = "ΑΒΓΔΕ"
|
||||
0xsce91ce92ce93ce94ce95
|
||||
|
||||
```
|
||||
We can check that encoding and then decoding should give us back the same `Text` we started with
|
||||
We can check that encoding and then decoding should give us back the same `Text` we started with
|
||||
|
||||
```unison
|
||||
checkRoundTrip: Text -> [Result]
|
||||
checkRoundTrip t =
|
||||
checkRoundTrip t =
|
||||
bytes = toUtf8 t
|
||||
match fromUtf8.impl bytes with
|
||||
match fromUtf8.impl bytes with
|
||||
Left e -> [Result.Fail "could not decode"]
|
||||
Right t' -> if t == t' then [Result.Ok "Passed"] else [Result.Fail ("Got: " ++ t' ++ " Expected: " ++ t)]
|
||||
|
||||
|
@ -114,8 +114,7 @@ Let's try it!
|
||||
|
||||
```ucm
|
||||
.> alias.many stuff.List.adjacentPairs stuff.List.all stuff.List.any stuff.List.chunk stuff.List.chunksOf stuff.List.dropWhile stuff.List.first stuff.List.init stuff.List.intersperse stuff.List.isEmpty stuff.List.last stuff.List.replicate stuff.List.splitAt stuff.List.tail stuff.List.takeWhile .mylib
|
||||
.> cd .mylib
|
||||
.mylib> find
|
||||
.> find-in mylib
|
||||
```
|
||||
|
||||
Thanks, `alias.many`!
|
||||
|
@ -46,33 +46,23 @@ Let's try it!
|
||||
|
||||
Tip: You can use `undo` or `reflog` to undo this change.
|
||||
|
||||
.> cd .mylib
|
||||
|
||||
.mylib> find
|
||||
.> find-in mylib
|
||||
|
||||
1. stuff.List.adjacentPairs : [a] -> [(a, a)]
|
||||
2. stuff.List.all : (a ->{g} ##Boolean)
|
||||
-> [a]
|
||||
->{g} ##Boolean
|
||||
3. stuff.List.any : (a ->{g} ##Boolean)
|
||||
-> [a]
|
||||
->{g} ##Boolean
|
||||
4. stuff.List.chunk : ##Nat -> [a] -> [[a]]
|
||||
5. stuff.List.chunksOf : ##Nat -> [a] -> [[a]]
|
||||
6. stuff.List.dropWhile : (a ->{g} ##Boolean)
|
||||
-> [a]
|
||||
->{g} [a]
|
||||
7. stuff.List.first : [a] -> #nirp5os0q6 a
|
||||
8. stuff.List.init : [a] -> #nirp5os0q6 [a]
|
||||
2. stuff.List.all : (a ->{g} Boolean) -> [a] ->{g} Boolean
|
||||
3. stuff.List.any : (a ->{g} Boolean) -> [a] ->{g} Boolean
|
||||
4. stuff.List.chunk : Nat -> [a] -> [[a]]
|
||||
5. stuff.List.chunksOf : Nat -> [a] -> [[a]]
|
||||
6. stuff.List.dropWhile : (a ->{g} Boolean) -> [a] ->{g} [a]
|
||||
7. stuff.List.first : [a] -> Optional a
|
||||
8. stuff.List.init : [a] -> Optional [a]
|
||||
9. stuff.List.intersperse : a -> [a] -> [a]
|
||||
10. stuff.List.isEmpty : [a] -> ##Boolean
|
||||
11. stuff.List.last : [a] -> #nirp5os0q6 a
|
||||
12. stuff.List.replicate : ##Nat -> a -> [a]
|
||||
13. stuff.List.splitAt : ##Nat -> [a] -> ([a], [a])
|
||||
14. stuff.List.tail : [a] -> #nirp5os0q6 [a]
|
||||
15. stuff.List.takeWhile : (a ->{𝕖} ##Boolean)
|
||||
-> [a]
|
||||
->{𝕖} [a]
|
||||
10. stuff.List.isEmpty : [a] -> Boolean
|
||||
11. stuff.List.last : [a] -> Optional a
|
||||
12. stuff.List.replicate : Nat -> a -> [a]
|
||||
13. stuff.List.splitAt : Nat -> [a] -> ([a], [a])
|
||||
14. stuff.List.tail : [a] -> Optional [a]
|
||||
15. stuff.List.takeWhile : (a ->{𝕖} Boolean) -> [a] ->{𝕖} [a]
|
||||
|
||||
|
||||
```
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
```ucm:hide
|
||||
.> builtins.mergeio
|
||||
.> cd builtin
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
```
|
||||
@ -11,9 +10,9 @@ Any.unsafeExtract is a way to extract the value contained in an Any. This is uns
|
||||
|
||||
```unison
|
||||
|
||||
test> Any.unsafeExtract.works =
|
||||
test> Any.unsafeExtract.works =
|
||||
use Nat !=
|
||||
checks [1 == Any.unsafeExtract (Any 1),
|
||||
checks [1 == Any.unsafeExtract (Any 1),
|
||||
not (1 == Any.unsafeExtract (Any 2)),
|
||||
(Some 1) == Any.unsafeExtract (Any (Some 1))
|
||||
]
|
||||
@ -22,4 +21,3 @@ test> Any.unsafeExtract.works =
|
||||
```ucm
|
||||
.> add
|
||||
```
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
Any.unsafeExtract is a way to extract the value contained in an Any. This is unsafe because it allows the programmer to coerce a value into any type, which would cause undefined behaviour if used to coerce a value to the wrong type.
|
||||
|
||||
```unison
|
||||
test> Any.unsafeExtract.works =
|
||||
test> Any.unsafeExtract.works =
|
||||
use Nat !=
|
||||
checks [1 == Any.unsafeExtract (Any 1),
|
||||
checks [1 == Any.unsafeExtract (Any 1),
|
||||
not (1 == Any.unsafeExtract (Any 2)),
|
||||
(Some 1) == Any.unsafeExtract (Any (Some 1))
|
||||
]
|
||||
@ -26,7 +26,7 @@ test> Any.unsafeExtract.works =
|
||||
Now evaluating any watch expressions (lines starting with
|
||||
`>`)... Ctrl+C cancels.
|
||||
|
||||
3 | checks [1 == Any.unsafeExtract (Any 1),
|
||||
3 | checks [1 == Any.unsafeExtract (Any 1),
|
||||
|
||||
✅ Passed Passed
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
```ucm:hide
|
||||
.> builtins.mergeio
|
||||
.> cd builtin
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
```
|
||||
@ -276,8 +275,8 @@ test> Text.tests.indexOf =
|
||||
Text.indexOf needle8 haystack == None,
|
||||
Text.indexOf needle9 haystack == Some 0,
|
||||
]
|
||||
|
||||
test> Text.tests.indexOfEmoji =
|
||||
|
||||
test> Text.tests.indexOfEmoji =
|
||||
haystack = "clap 👏 your 👏 hands 👏 if 👏 you 👏 love 👏 unison"
|
||||
needle1 = "👏"
|
||||
needle2 = "👏 "
|
||||
|
@ -257,8 +257,8 @@ test> Text.tests.indexOf =
|
||||
Text.indexOf needle8 haystack == None,
|
||||
Text.indexOf needle9 haystack == Some 0,
|
||||
]
|
||||
|
||||
test> Text.tests.indexOfEmoji =
|
||||
|
||||
test> Text.tests.indexOfEmoji =
|
||||
haystack = "clap 👏 your 👏 hands 👏 if 👏 you 👏 love 👏 unison"
|
||||
needle1 = "👏"
|
||||
needle2 = "👏 "
|
||||
|
@ -1,46 +0,0 @@
|
||||
## Switching between namespaces / projects / branches / modules
|
||||
|
||||
Unison uses the same organizational element to represent directories, projects, sub-projects, forks, modules, etc.; currently called a "namespace".
|
||||
|
||||
Namespaces are trees that contain definitions of "types" and "terms", "patches", and other child namespaces.
|
||||
|
||||
We're still working out what a nice codebase layout might be (feel free to write up a blog post if you find one that works well for you), but in this example, we have these, along with their children (not shown):
|
||||
|
||||
> .libs.base
|
||||
> .libs.megaparser.master
|
||||
> .libs.megaparser.v1
|
||||
> .libs.megaparser.v2
|
||||
> .arya.base
|
||||
> .arya.myproject
|
||||
> .pullrequests.runarorama.base_3.base
|
||||
> .pullrequests.runarorama.base_3.head
|
||||
> .pullrequests.runarorama.base_3.merged
|
||||
> .temp
|
||||
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> move.namespace builtin .arya.base
|
||||
```
|
||||
|
||||
```ucm
|
||||
.> cd arya.base
|
||||
.arya.base> find Boolean
|
||||
```
|
||||
```ucm:hide
|
||||
.arya.base> cd .arya.myproject
|
||||
```
|
||||
|
||||
blah blah blah more stuff about project management and patches and the value of working from the appropriate namespace, and what that is in any given case
|
||||
|
||||
We can pop back to the previous namespace with the `back` command.
|
||||
|
||||
```ucm:hide
|
||||
.arya.myproject> back
|
||||
```
|
||||
```ucm:hide
|
||||
.arya.base> back
|
||||
```
|
||||
```ucm:error
|
||||
.> back
|
||||
```
|
||||
😬 Right, ok.
|
@ -1,40 +0,0 @@
|
||||
## Switching between namespaces / projects / branches / modules
|
||||
|
||||
Unison uses the same organizational element to represent directories, projects, sub-projects, forks, modules, etc.; currently called a "namespace".
|
||||
|
||||
Namespaces are trees that contain definitions of "types" and "terms", "patches", and other child namespaces.
|
||||
|
||||
We're still working out what a nice codebase layout might be (feel free to write up a blog post if you find one that works well for you), but in this example, we have these, along with their children (not shown):
|
||||
|
||||
> .libs.base
|
||||
> .libs.megaparser.master
|
||||
> .libs.megaparser.v1
|
||||
> .libs.megaparser.v2
|
||||
> .arya.base
|
||||
> .arya.myproject
|
||||
> .pullrequests.runarorama.base_3.base
|
||||
> .pullrequests.runarorama.base_3.head
|
||||
> .pullrequests.runarorama.base_3.merged
|
||||
> .temp
|
||||
|
||||
```ucm
|
||||
.> cd arya.base
|
||||
|
||||
.arya.base> find Boolean
|
||||
|
||||
1. builtin type Boolean
|
||||
2. Boolean.not : Boolean -> Boolean
|
||||
|
||||
|
||||
```
|
||||
blah blah blah more stuff about project management and patches and the value of working from the appropriate namespace, and what that is in any given case
|
||||
|
||||
We can pop back to the previous namespace with the `back` command.
|
||||
|
||||
```ucm
|
||||
.> back
|
||||
|
||||
You're already at the very beginning! 🙂
|
||||
|
||||
```
|
||||
😬 Right, ok.
|
@ -78,7 +78,7 @@ Deleting the root namespace should require confirmation if not forced.
|
||||
⚠️
|
||||
|
||||
Are you sure you want to clear away everything?
|
||||
You could use `namespace` to switch to a new namespace instead.
|
||||
You could use `project.create` to switch to a new project instead.
|
||||
|
||||
.> delete.namespace .
|
||||
|
||||
|
@ -48,7 +48,6 @@ structural ability X a1 a2 where x : ()
|
||||
.ns1> alias.term fromJust fromJust'
|
||||
.ns1> alias.term helloWorld helloWorld2
|
||||
.ns1> fork .ns1 .ns2
|
||||
.ns1> cd .
|
||||
```
|
||||
|
||||
Here's what we've done so far:
|
||||
|
@ -137,8 +137,6 @@ structural ability X a1 a2 where x : ()
|
||||
|
||||
Done.
|
||||
|
||||
.ns1> cd .
|
||||
|
||||
```
|
||||
Here's what we've done so far:
|
||||
|
||||
|
@ -1,23 +1,44 @@
|
||||
```unison
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.> move builtin lib.builtin
|
||||
```
|
||||
|
||||
```unison:hide
|
||||
foo = 1
|
||||
lib.foo = 2
|
||||
lib.bar = 3
|
||||
cat.foo = 4
|
||||
cat.lib.foo = 5
|
||||
cat.lib.bar = 6
|
||||
somewhere.bar = 7
|
||||
```
|
||||
|
||||
```ucm
|
||||
```ucm:hide
|
||||
.> add
|
||||
```
|
||||
|
||||
```ucm
|
||||
.> find foo
|
||||
.> view 1
|
||||
.> find.all foo
|
||||
.> view 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
.somewhere> find.global foo
|
||||
.> find-in cat foo
|
||||
.> view 1
|
||||
.> find-in.all cat foo
|
||||
.> view 1
|
||||
```
|
||||
|
||||
```ucm
|
||||
.somewhere> find bar
|
||||
.somewhere> find.global bar
|
||||
```
|
||||
|
||||
```ucm
|
||||
.> find bar
|
||||
.> find-in somewhere bar
|
||||
```
|
||||
|
||||
```ucm:error
|
||||
@ -25,5 +46,5 @@ lib.bar = 3
|
||||
```
|
||||
|
||||
```ucm:error
|
||||
.> find.global nothere
|
||||
.> find.global notHere
|
||||
```
|
||||
|
@ -2,59 +2,84 @@
|
||||
foo = 1
|
||||
lib.foo = 2
|
||||
lib.bar = 3
|
||||
cat.foo = 4
|
||||
cat.lib.foo = 5
|
||||
cat.lib.bar = 6
|
||||
somewhere.bar = 7
|
||||
```
|
||||
|
||||
```ucm
|
||||
|
||||
Loading changes detected in scratch.u.
|
||||
|
||||
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`:
|
||||
|
||||
foo : ##Nat
|
||||
lib.bar : ##Nat
|
||||
lib.foo : ##Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
|
||||
foo : ##Nat
|
||||
lib.bar : ##Nat
|
||||
lib.foo : ##Nat
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> find foo
|
||||
|
||||
1. foo : ##Nat
|
||||
1. cat.foo : Nat
|
||||
2. foo : Nat
|
||||
|
||||
|
||||
.> view 1
|
||||
|
||||
cat.foo : Nat
|
||||
cat.foo = 4
|
||||
|
||||
.> find.all foo
|
||||
|
||||
1. cat.foo : Nat
|
||||
2. cat.lib.foo : Nat
|
||||
3. lib.foo : Nat
|
||||
4. foo : Nat
|
||||
|
||||
|
||||
.> view 1
|
||||
|
||||
cat.foo : Nat
|
||||
cat.foo = 4
|
||||
|
||||
```
|
||||
```ucm
|
||||
☝️ The namespace .somewhere is empty.
|
||||
.> find-in cat foo
|
||||
|
||||
.somewhere> find.global foo
|
||||
1. foo : Nat
|
||||
|
||||
|
||||
1. .foo : ##Nat
|
||||
2. .lib.foo : ##Nat
|
||||
.> view 1
|
||||
|
||||
cat.foo : Nat
|
||||
cat.foo = 4
|
||||
|
||||
.> find-in.all cat foo
|
||||
|
||||
1. lib.foo : Nat
|
||||
2. foo : Nat
|
||||
|
||||
|
||||
.> view 1
|
||||
|
||||
cat.lib.foo : Nat
|
||||
cat.lib.foo = 5
|
||||
|
||||
```
|
||||
```ucm
|
||||
.somewhere> find bar
|
||||
|
||||
1. bar : ##Nat
|
||||
|
||||
|
||||
.somewhere> find.global bar
|
||||
|
||||
1. .cat.lib.bar : Nat
|
||||
2. .lib.bar : Nat
|
||||
3. .somewhere.bar : Nat
|
||||
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> find bar
|
||||
|
||||
☝️
|
||||
1. somewhere.bar : Nat
|
||||
|
||||
I couldn't find matches in this namespace, searching in
|
||||
'lib'...
|
||||
|
||||
1. lib.bar : ##Nat
|
||||
.> find-in somewhere bar
|
||||
|
||||
1. bar : Nat
|
||||
|
||||
|
||||
```
|
||||
@ -76,7 +101,7 @@ lib.bar = 3
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> find.global nothere
|
||||
.> find.global notHere
|
||||
|
||||
😶
|
||||
|
||||
|
@ -34,7 +34,7 @@ Namespace args
|
||||
|
||||
```ucm
|
||||
.> add
|
||||
.> debug.fuzzy-options cd _
|
||||
.> debug.fuzzy-options find-in _
|
||||
```
|
||||
|
||||
Project Branch args
|
||||
@ -44,4 +44,3 @@ Project Branch args
|
||||
myproject/main> branch mybranch
|
||||
.> debug.fuzzy-options switch _
|
||||
```
|
||||
|
||||
|
@ -56,7 +56,7 @@ Namespace args
|
||||
⊡ Ignored previously added definitions: nested.optionTwo
|
||||
optionOne
|
||||
|
||||
.> debug.fuzzy-options cd _
|
||||
.> debug.fuzzy-options find-in _
|
||||
|
||||
Select a namespace:
|
||||
* nested
|
||||
|
@ -5,7 +5,6 @@
|
||||
.> builtins.mergeio
|
||||
.> load unison-src/transcripts-using-base/base.u
|
||||
.> add
|
||||
.> cd builtin
|
||||
```
|
||||
|
||||
Tests for IO builtins which wired to foreign haskell calls.
|
||||
@ -323,7 +322,7 @@ testGetEnv _ =
|
||||
test = 'let
|
||||
path = reraise (getEnv.impl "PATH") -- PATH exists on windows, mac and linux.
|
||||
check "PATH environent variable should be set" (size path > 0)
|
||||
match getEnv.impl "DOESNTEXIST" with
|
||||
match getEnv.impl "DOESNTEXIST" with
|
||||
Right _ -> emit (Fail "env var shouldn't exist")
|
||||
Left _ -> emit (Ok "DOESNTEXIST didn't exist")
|
||||
runTest test
|
||||
@ -335,7 +334,7 @@ testGetEnv _ =
|
||||
|
||||
### Read command line args
|
||||
|
||||
`runMeWithNoArgs`, `runMeWithOneArg`, and `runMeWithTwoArgs` raise exceptions
|
||||
`runMeWithNoArgs`, `runMeWithOneArg`, and `runMeWithTwoArgs` raise exceptions
|
||||
unless they called with the right number of arguments.
|
||||
|
||||
```unison:hide
|
||||
@ -370,7 +369,6 @@ testGetArgs.runMeWithTwoArgs = 'let
|
||||
Test that they can be run with the right number of args.
|
||||
```ucm
|
||||
.> add
|
||||
.> cd testGetArgs
|
||||
.> run runMeWithNoArgs
|
||||
.> run runMeWithOneArg foo
|
||||
.> run runMeWithTwoArgs foo bar
|
||||
@ -422,4 +420,3 @@ testRandom = do
|
||||
.> add
|
||||
.> io.test testGetEnv
|
||||
```
|
||||
|
||||
|
@ -520,7 +520,7 @@ testGetEnv _ =
|
||||
test = 'let
|
||||
path = reraise (getEnv.impl "PATH") -- PATH exists on windows, mac and linux.
|
||||
check "PATH environent variable should be set" (size path > 0)
|
||||
match getEnv.impl "DOESNTEXIST" with
|
||||
match getEnv.impl "DOESNTEXIST" with
|
||||
Right _ -> emit (Fail "env var shouldn't exist")
|
||||
Left _ -> emit (Ok "DOESNTEXIST didn't exist")
|
||||
runTest test
|
||||
@ -547,7 +547,7 @@ testGetEnv _ =
|
||||
```
|
||||
### Read command line args
|
||||
|
||||
`runMeWithNoArgs`, `runMeWithOneArg`, and `runMeWithTwoArgs` raise exceptions
|
||||
`runMeWithNoArgs`, `runMeWithOneArg`, and `runMeWithTwoArgs` raise exceptions
|
||||
unless they called with the right number of arguments.
|
||||
|
||||
```unison
|
||||
@ -590,8 +590,6 @@ Test that they can be run with the right number of args.
|
||||
testGetArgs.runMeWithOneArg : '{IO, Exception} ()
|
||||
testGetArgs.runMeWithTwoArgs : '{IO, Exception} ()
|
||||
|
||||
.> cd testGetArgs
|
||||
|
||||
.> run runMeWithNoArgs
|
||||
|
||||
()
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
```ucm:hide
|
||||
.master> builtins.merge
|
||||
.> cd .
|
||||
```
|
||||
|
||||
The Unison namespace is a versioned tree of names that map to Unison definitions. You can change this namespace and fork and merge subtrees of it. Let's start by introducing a few definitions into a new namespace, `foo`:
|
||||
@ -49,7 +48,7 @@ y = "hello"
|
||||
|
||||
Notice that `master` now has the definition of `y` we wrote.
|
||||
|
||||
We can also delete the fork if we're done with it. (Don't worry, even though the history at that path is now empty,
|
||||
We can also delete the fork if we're done with it. (Don't worry, even though the history at that path is now empty,
|
||||
it's still in the `history` of the parent namespace and can be resurrected at any time.)
|
||||
|
||||
```ucm
|
||||
|
@ -102,7 +102,7 @@ y = "hello"
|
||||
|
||||
Notice that `master` now has the definition of `y` we wrote.
|
||||
|
||||
We can also delete the fork if we're done with it. (Don't worry, even though the history at that path is now empty,
|
||||
We can also delete the fork if we're done with it. (Don't worry, even though the history at that path is now empty,
|
||||
it's still in the `history` of the parent namespace and can be resurrected at any time.)
|
||||
|
||||
```ucm
|
||||
|
@ -22,7 +22,6 @@ Will add `a` and `b` to the codebase and give `b` a longer (in terms of segment
|
||||
.a> add
|
||||
.a> alias.term b aaa.but.more.segments
|
||||
.a> view a
|
||||
.> cd .
|
||||
```
|
||||
|
||||
Next let's introduce a conflicting symbol and show that its hash qualified name isn't used when it has an unconflicted name:
|
||||
@ -55,8 +54,8 @@ d = c + 10
|
||||
.a3> merge .a2 .a3
|
||||
```
|
||||
|
||||
At this point, `a3` is conflicted for symbols `c` and `d`, so those are deprioritized.
|
||||
The original `a2` namespace has an unconflicted definition for `c` and `d`, but since there are multiple 'c's in scope,
|
||||
At this point, `a3` is conflicted for symbols `c` and `d`, so those are deprioritized.
|
||||
The original `a2` namespace has an unconflicted definition for `c` and `d`, but since there are multiple 'c's in scope,
|
||||
`a2.c` is chosen because although the suffixified version has fewer segments, its fully-qualified name has the fewest segments.
|
||||
|
||||
```ucm
|
||||
@ -66,7 +65,7 @@ The original `a2` namespace has an unconflicted definition for `c` and `d`, but
|
||||
## Name biasing
|
||||
|
||||
```unison
|
||||
deeply.nested.term =
|
||||
deeply.nested.term =
|
||||
a + 1
|
||||
|
||||
deeply.nested.num = 10
|
||||
@ -76,7 +75,7 @@ a = 10
|
||||
|
||||
```ucm
|
||||
.biasing> add
|
||||
-- Despite being saved with name `a`,
|
||||
-- Despite being saved with name `a`,
|
||||
-- the pretty printer should prefer the suffixified 'deeply.nested.num name' over the shallow 'a'.
|
||||
-- It's closer to the term being printed.
|
||||
.biasing> view deeply.nested.term
|
||||
@ -94,4 +93,3 @@ other.num = 20
|
||||
-- because `deeply.nested.num` is nearby to the term being viewed.
|
||||
.biasing> view deeply.nested.term
|
||||
```
|
||||
|
||||
|
@ -30,8 +30,6 @@ Will add `a` and `b` to the codebase and give `b` a longer (in terms of segment
|
||||
use Nat +
|
||||
b + 1
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
Next let's introduce a conflicting symbol and show that its hash qualified name isn't used when it has an unconflicted name:
|
||||
|
||||
@ -101,8 +99,8 @@ d = c + 10
|
||||
Applying changes from patch...
|
||||
|
||||
```
|
||||
At this point, `a3` is conflicted for symbols `c` and `d`, so those are deprioritized.
|
||||
The original `a2` namespace has an unconflicted definition for `c` and `d`, but since there are multiple 'c's in scope,
|
||||
At this point, `a3` is conflicted for symbols `c` and `d`, so those are deprioritized.
|
||||
The original `a2` namespace has an unconflicted definition for `c` and `d`, but since there are multiple 'c's in scope,
|
||||
`a2.c` is chosen because although the suffixified version has fewer segments, its fully-qualified name has the fewest segments.
|
||||
|
||||
```ucm
|
||||
@ -138,7 +136,7 @@ The original `a2` namespace has an unconflicted definition for `c` and `d`, but
|
||||
## Name biasing
|
||||
|
||||
```unison
|
||||
deeply.nested.term =
|
||||
deeply.nested.term =
|
||||
a + 1
|
||||
|
||||
deeply.nested.num = 10
|
||||
@ -170,7 +168,7 @@ a = 10
|
||||
deeply.nested.num : Nat
|
||||
deeply.nested.term : Nat
|
||||
|
||||
-- Despite being saved with name `a`,
|
||||
-- Despite being saved with name `a`,
|
||||
-- the pretty printer should prefer the suffixified 'deeply.nested.num name' over the shallow 'a'.
|
||||
-- It's closer to the term being printed.
|
||||
.biasing> view deeply.nested.term
|
||||
|
@ -37,7 +37,6 @@ and update the codebase to use the new type `Foo`...
|
||||
|
||||
```ucm
|
||||
.subpath> view fooToInt
|
||||
.> cd .
|
||||
```
|
||||
|
||||
### Preserving user type variables
|
||||
@ -57,7 +56,6 @@ Add that to the codebase:
|
||||
|
||||
```ucm
|
||||
.subpath> add
|
||||
.> cd .
|
||||
```
|
||||
|
||||
Let's now edit the dependency:
|
||||
@ -71,7 +69,6 @@ Update...
|
||||
|
||||
```ucm
|
||||
.subpath> update.old
|
||||
.> cd .
|
||||
```
|
||||
|
||||
Now the type of `someTerm` should be `Optional x -> Optional x` and the
|
||||
@ -106,7 +103,6 @@ We'll make two copies of this namespace.
|
||||
```ucm
|
||||
.subpath> add
|
||||
.subpath> fork one two
|
||||
.> cd .
|
||||
```
|
||||
|
||||
Now let's edit one of the terms...
|
||||
|
@ -90,8 +90,6 @@ and update the codebase to use the new type `Foo`...
|
||||
fooToInt : Foo -> Int
|
||||
fooToInt _ = +42
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
### Preserving user type variables
|
||||
|
||||
@ -130,8 +128,6 @@ Add that to the codebase:
|
||||
preserve.otherTerm : Optional baz -> Optional baz
|
||||
preserve.someTerm : Optional foo -> Optional foo
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
Let's now edit the dependency:
|
||||
|
||||
@ -148,7 +144,8 @@ preserve.someTerm _ = None
|
||||
do an `add` or `update`, here's how your codebase would
|
||||
change:
|
||||
|
||||
⍟ These new definitions are ok to `add`:
|
||||
⍟ These names already exist. You can `update` them to your
|
||||
new definition:
|
||||
|
||||
preserve.someTerm : Optional x -> Optional x
|
||||
|
||||
@ -162,8 +159,6 @@ Update...
|
||||
|
||||
preserve.someTerm : Optional x -> Optional x
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
Now the type of `someTerm` should be `Optional x -> Optional x` and the
|
||||
type of `otherTerm` should remain the same.
|
||||
@ -234,8 +229,6 @@ We'll make two copies of this namespace.
|
||||
|
||||
Done.
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
Now let's edit one of the terms...
|
||||
|
||||
|
@ -6,12 +6,6 @@ This transcript tests the errors printed to the user when a name cannot be resol
|
||||
|
||||
First we define differing types with the same name in different namespaces:
|
||||
|
||||
```ucm
|
||||
.> cd example.resolution_failures
|
||||
```
|
||||
|
||||
Now let's add a term named `a.foo`:
|
||||
|
||||
```unison
|
||||
unique type one.AmbiguousType = one.AmbiguousType
|
||||
unique type two.AmbiguousType = two.AmbiguousType
|
||||
@ -26,7 +20,7 @@ two.ambiguousTerm = "term two"
|
||||
|
||||
## Tests
|
||||
|
||||
Now we introduce code which isn't sufficiently qualified.
|
||||
Now we introduce code which isn't sufficiently qualified.
|
||||
It is ambiguous which type from which namespace we mean.
|
||||
|
||||
We expect the output to:
|
||||
|
@ -6,14 +6,6 @@ This transcript tests the errors printed to the user when a name cannot be resol
|
||||
|
||||
First we define differing types with the same name in different namespaces:
|
||||
|
||||
```ucm
|
||||
.> cd example.resolution_failures
|
||||
|
||||
☝️ The namespace .example.resolution_failures is empty.
|
||||
|
||||
```
|
||||
Now let's add a term named `a.foo`:
|
||||
|
||||
```unison
|
||||
unique type one.AmbiguousType = one.AmbiguousType
|
||||
unique type two.AmbiguousType = two.AmbiguousType
|
||||
@ -39,6 +31,8 @@ two.ambiguousTerm = "term two"
|
||||
|
||||
```
|
||||
```ucm
|
||||
☝️ The namespace .example.resolution_failures is empty.
|
||||
|
||||
.example.resolution_failures> add
|
||||
|
||||
⍟ I've added these definitions:
|
||||
@ -51,7 +45,7 @@ two.ambiguousTerm = "term two"
|
||||
```
|
||||
## Tests
|
||||
|
||||
Now we introduce code which isn't sufficiently qualified.
|
||||
Now we introduce code which isn't sufficiently qualified.
|
||||
It is ambiguous which type from which namespace we mean.
|
||||
|
||||
We expect the output to:
|
||||
|
@ -37,7 +37,7 @@ We'll also make a second fork `c` which we'll use as the target for our patch la
|
||||
Now let's make a change to `foo` in the `a` namespace:
|
||||
|
||||
```ucm
|
||||
.example.resolve> cd a
|
||||
.example.resolve> deprecated.cd a
|
||||
```
|
||||
|
||||
```unison
|
||||
@ -51,7 +51,7 @@ foo = 43
|
||||
And make a different change in the `b` namespace:
|
||||
|
||||
```ucm
|
||||
.example.resolve> cd .example.resolve.b
|
||||
.example.resolve> deprecated.cd .example.resolve.b
|
||||
```
|
||||
|
||||
```unison
|
||||
@ -65,7 +65,7 @@ foo = 44
|
||||
The `a` and `b` namespaces now each contain a patch named `patch`. We can view these:
|
||||
|
||||
```ucm
|
||||
.example.resolve.b> cd .example.resolve
|
||||
.example.resolve.b> deprecated.cd .example.resolve
|
||||
.example.resolve> view.patch a.patch
|
||||
.example.resolve> view.patch b.patch
|
||||
```
|
||||
@ -82,7 +82,7 @@ Let's now merge these namespaces into `c`:
|
||||
The namespace `c` now has an edit conflict, since the term `foo` was edited in two different ways.
|
||||
|
||||
```ucm:error
|
||||
.example.resolve> cd c
|
||||
.example.resolve> deprecated.cd c
|
||||
.example.resolve.c> todo
|
||||
```
|
||||
|
||||
|
@ -50,7 +50,7 @@ We'll also make a second fork `c` which we'll use as the target for our patch la
|
||||
Now let's make a change to `foo` in the `a` namespace:
|
||||
|
||||
```ucm
|
||||
.example.resolve> cd a
|
||||
.example.resolve> deprecated.cd a
|
||||
|
||||
```
|
||||
```unison
|
||||
@ -82,7 +82,7 @@ foo = 43
|
||||
And make a different change in the `b` namespace:
|
||||
|
||||
```ucm
|
||||
.example.resolve> cd .example.resolve.b
|
||||
.example.resolve> deprecated.cd .example.resolve.b
|
||||
|
||||
```
|
||||
```unison
|
||||
@ -114,7 +114,7 @@ foo = 44
|
||||
The `a` and `b` namespaces now each contain a patch named `patch`. We can view these:
|
||||
|
||||
```ucm
|
||||
.example.resolve.b> cd .example.resolve
|
||||
.example.resolve.b> deprecated.cd .example.resolve
|
||||
|
||||
.example.resolve> view.patch a.patch
|
||||
|
||||
@ -188,7 +188,7 @@ Let's now merge these namespaces into `c`:
|
||||
The namespace `c` now has an edit conflict, since the term `foo` was edited in two different ways.
|
||||
|
||||
```ucm
|
||||
.example.resolve> cd c
|
||||
.example.resolve> deprecated.cd c
|
||||
|
||||
.example.resolve.c> todo
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
https://github.com/unisonweb/unison/issues/2786
|
||||
|
||||
```ucm:hide
|
||||
.> builtins.merge
|
||||
.ns> builtins.merge
|
||||
```
|
||||
|
||||
@ -15,7 +14,6 @@ structural type X = x
|
||||
|
||||
```ucm
|
||||
.ns> add
|
||||
.> cd .
|
||||
```
|
||||
|
||||
Now we update the type, changing the name of the constructors, _but_, we simultaneously
|
||||
|
@ -30,8 +30,6 @@ structural type X = x
|
||||
structural type X
|
||||
(also named builtin.Unit)
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
Now we update the type, changing the name of the constructors, _but_, we simultaneously
|
||||
add a new top-level term with the same name as the old constructor.
|
||||
@ -55,9 +53,14 @@ dependsOnX = Text.size X.x
|
||||
|
||||
⍟ These new definitions are ok to `add`:
|
||||
|
||||
structural type X
|
||||
X.x : Text
|
||||
dependsOnX : Nat
|
||||
|
||||
⍟ These names already exist. You can `update` them to your
|
||||
new definition:
|
||||
|
||||
structural type X
|
||||
(The old definition is also named builtin.Unit.)
|
||||
|
||||
```
|
||||
This update should succeed since the conflicted constructor
|
||||
|
@ -44,9 +44,9 @@ unique type subnamespace.AType = A | B
|
||||
|
||||
```ucm
|
||||
-- Should tab complete namespaces
|
||||
.> debug.tab-complete cd sub
|
||||
.> debug.tab-complete cd subnamespace
|
||||
.> debug.tab-complete cd subnamespace.
|
||||
.> debug.tab-complete find-in sub
|
||||
.> debug.tab-complete find-in subnamespace
|
||||
.> debug.tab-complete find-in subnamespace.
|
||||
.> debug.tab-complete io.test sub
|
||||
.> debug.tab-complete io.test subnamespace
|
||||
.> debug.tab-complete io.test subnamespace.
|
||||
@ -86,4 +86,3 @@ mybranchsubnamespace.term = 1
|
||||
myproject/main> add
|
||||
myproject/main> debug.tab-complete merge mybr
|
||||
```
|
||||
|
||||
|
@ -103,17 +103,17 @@ unique type subnamespace.AType = A | B
|
||||
|
||||
```ucm
|
||||
-- Should tab complete namespaces
|
||||
.> debug.tab-complete cd sub
|
||||
.> debug.tab-complete find-in sub
|
||||
|
||||
subnamespace
|
||||
subnamespace2
|
||||
|
||||
.> debug.tab-complete cd subnamespace
|
||||
.> debug.tab-complete find-in subnamespace
|
||||
|
||||
subnamespace
|
||||
subnamespace2
|
||||
|
||||
.> debug.tab-complete cd subnamespace.
|
||||
.> debug.tab-complete find-in subnamespace.
|
||||
|
||||
subnamespace.AType
|
||||
|
||||
|
@ -17,7 +17,6 @@ useMyType = match MyType 1 with
|
||||
|
||||
```ucm:hide
|
||||
.simple> add
|
||||
.> cd .
|
||||
```
|
||||
|
||||
Perform a type-changing update so dependents are added to our update frontier.
|
||||
@ -31,7 +30,6 @@ type MyType = MyType Text
|
||||
```ucm:error
|
||||
.simple> update.old
|
||||
.simple> todo
|
||||
.> cd .
|
||||
```
|
||||
|
||||
## A merge with conflicting updates.
|
||||
@ -61,7 +59,6 @@ type MyType = MyType Nat
|
||||
|
||||
```ucm:hide
|
||||
.mergeA> update.old
|
||||
.> cd .
|
||||
```
|
||||
|
||||
```unison:hide
|
||||
|
@ -44,8 +44,6 @@ type MyType = MyType Text
|
||||
|
||||
|
||||
|
||||
.> cd .
|
||||
|
||||
```
|
||||
## A merge with conflicting updates.
|
||||
|
||||
@ -78,13 +76,13 @@ type MyType = MyType Int
|
||||
|
||||
1. type MyType#ig1g2ka7lv
|
||||
↓
|
||||
2. ┌ type MyType#ig1g2ka7lv
|
||||
3. └ type MyType#m6mdqhqcr1
|
||||
2. ┌ type MyType#8c6f40i3tj
|
||||
3. └ type MyType#ig1g2ka7lv
|
||||
|
||||
4. MyType.MyType#ig1g2ka7lv#0 : Nat -> MyType#ig1g2ka7lv
|
||||
↓
|
||||
5. ┌ MyType.MyType#ig1g2ka7lv#0 : Nat -> MyType#ig1g2ka7lv
|
||||
6. └ MyType.MyType#m6mdqhqcr1#0 : Int -> MyType#m6mdqhqcr1
|
||||
5. ┌ MyType.MyType#8c6f40i3tj#0 : Int -> MyType#8c6f40i3tj
|
||||
6. └ MyType.MyType#ig1g2ka7lv#0 : Nat -> MyType#ig1g2ka7lv
|
||||
|
||||
7. x#dcgdua2lj6 : Nat
|
||||
↓
|
||||
@ -114,16 +112,16 @@ type MyType = MyType Int
|
||||
use as the new definition:
|
||||
|
||||
The type 1. #8h7qq3ougl was replaced with
|
||||
2. MyType#ig1g2ka7lv
|
||||
3. MyType#m6mdqhqcr1
|
||||
2. MyType#8c6f40i3tj
|
||||
3. MyType#ig1g2ka7lv
|
||||
The term 4. #gjmq673r1v was replaced with
|
||||
5. x#dcgdua2lj6
|
||||
6. x#f3lgjvjqoo
|
||||
❓
|
||||
|
||||
The term MyType.MyType has conflicting definitions:
|
||||
7. MyType.MyType#ig1g2ka7lv#0
|
||||
8. MyType.MyType#m6mdqhqcr1#0
|
||||
7. MyType.MyType#8c6f40i3tj#0
|
||||
8. MyType.MyType#ig1g2ka7lv#0
|
||||
|
||||
Tip: This occurs when merging branches that both independently
|
||||
introduce the same name. Use `move.term` or `delete.term`
|
||||
|
@ -3,7 +3,8 @@ foo = "bar"
|
||||
```
|
||||
|
||||
```ucm
|
||||
.> cd `()`
|
||||
.`()`> add
|
||||
.> find
|
||||
.> find-in `()`
|
||||
.> delete.namespace `()`
|
||||
```
|
||||
|
@ -16,8 +16,6 @@ foo = "bar"
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> cd `()`
|
||||
|
||||
☝️ The namespace .`()` is empty.
|
||||
|
||||
.`()`> add
|
||||
@ -26,6 +24,16 @@ foo = "bar"
|
||||
|
||||
foo : ##Text
|
||||
|
||||
.> find
|
||||
|
||||
1. `()`.foo : ##Text
|
||||
|
||||
|
||||
.> find-in `()`
|
||||
|
||||
1. foo : ##Text
|
||||
|
||||
|
||||
.> delete.namespace `()`
|
||||
|
||||
Done.
|
||||
|
Loading…
Reference in New Issue
Block a user