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:
Arya Irani 2024-04-28 21:30:02 -04:00 committed by GitHub
parent 61c5bebf44
commit 2cf96a36ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 314 additions and 355 deletions

View File

@ -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]

View File

@ -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

View File

@ -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]

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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
```

View File

@ -2,7 +2,6 @@
```ucm:hide
.> builtins.merge
.> builtins.mergeio
.> cd builtin
.> load unison-src/transcripts-using-base/base.u
.> add
.> find

View File

@ -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
```

View File

@ -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:

View File

@ -1,7 +1,6 @@
>
```ucm:hide
.> builtins.merge
.> cd builtin
.> load unison-src/transcripts-using-base/base.u
.> add
```

View File

@ -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"

View File

@ -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"

View File

@ -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)]

View File

@ -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)]

View File

@ -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`!

View File

@ -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]
```

View File

@ -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
```

View File

@ -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

View File

@ -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 = "👏 "

View File

@ -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 = "👏 "

View File

@ -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.

View File

@ -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.

View File

@ -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 .

View File

@ -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:

View File

@ -137,8 +137,6 @@ structural ability X a1 a2 where x : ()
Done.
.ns1> cd .
```
Here's what we've done so far:

View File

@ -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
```

View File

@ -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
😶

View File

@ -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 _
```

View File

@ -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

View File

@ -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
```

View File

@ -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
()

View File

@ -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

View File

@ -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

View File

@ -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
```

View File

@ -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

View File

@ -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...

View File

@ -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...

View File

@ -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:

View File

@ -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:

View File

@ -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
```

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
```

View File

@ -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

View File

@ -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

View File

@ -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`

View File

@ -3,7 +3,8 @@ foo = "bar"
```
```ucm
.> cd `()`
.`()`> add
.> find
.> find-in `()`
.> delete.namespace `()`
```

View File

@ -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.