Skip to content

Commit 2e6dd94

Browse files
authored
Merge pull request #5521 from xmbhasin/cli-cmd-multi
2 parents 14c73f1 + 6072ffa commit 2e6dd94

File tree

16 files changed

+391
-160
lines changed

16 files changed

+391
-160
lines changed

lib/unison-pretty-printer/src/Unison/Util/Pretty.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,8 @@ column2UnzippedM bottomPadding left right =
695695
column3sep ::
696696
(LL.ListLike s Char, IsString s) => Pretty s -> [(Pretty s, Pretty s, Pretty s)] -> Pretty s
697697
column3sep sep rows =
698-
let bc = align [(b, sep <> c) | (_, b, c) <- rows]
699-
abc = group <$> align [(a, sep <> bc) | ((a, _, _), bc) <- rows `zip` bc]
698+
let bc = align $ [(b, indent sep c) | (_, b, c) <- rows]
699+
abc = group <$> align [(a, indent sep bc) | ((a, _, _), bc) <- rows `zip` bc]
700700
in lines abc
701701

702702
-- | Creates an aligned table with an arbitrary number of columns separated by `sep`

unison-cli/src/Unison/Codebase/Editor/HandleInput.hs

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ import Unison.Codebase.Editor.HandleInput.DeleteBranch (handleDeleteBranch)
5959
import Unison.Codebase.Editor.HandleInput.DeleteNamespace (getEndangeredDependents, handleDeleteNamespace)
6060
import Unison.Codebase.Editor.HandleInput.DeleteProject (handleDeleteProject)
6161
import Unison.Codebase.Editor.HandleInput.Dependents (handleDependents)
62-
import Unison.Codebase.Editor.HandleInput.EditNamespace (handleEditNamespace)
6362
import Unison.Codebase.Editor.HandleInput.EditDependents (handleEditDependents)
63+
import Unison.Codebase.Editor.HandleInput.EditNamespace (handleEditNamespace)
6464
import Unison.Codebase.Editor.HandleInput.FindAndReplace (handleStructuredFindI, handleStructuredFindReplaceI, handleTextFindI)
6565
import Unison.Codebase.Editor.HandleInput.FormatFile qualified as Format
6666
import Unison.Codebase.Editor.HandleInput.Global qualified as Global
@@ -73,6 +73,7 @@ import Unison.Codebase.Editor.HandleInput.MoveAll (handleMoveAll)
7373
import Unison.Codebase.Editor.HandleInput.MoveBranch (doMoveBranch)
7474
import Unison.Codebase.Editor.HandleInput.MoveTerm (doMoveTerm)
7575
import Unison.Codebase.Editor.HandleInput.MoveType (doMoveType)
76+
import Unison.Codebase.Editor.HandleInput.Names (handleNames)
7677
import Unison.Codebase.Editor.HandleInput.NamespaceDependencies (handleNamespaceDependencies)
7778
import Unison.Codebase.Editor.HandleInput.NamespaceDiffUtils (diffHelper)
7879
import Unison.Codebase.Editor.HandleInput.ProjectClone (handleClone)
@@ -497,29 +498,8 @@ loop e = do
497498

498499
fixupOutput :: Path.HQSplit -> HQ.HashQualified Name
499500
fixupOutput = HQ'.toHQ . Path.nameFromHQSplit
500-
NamesI global query -> do
501-
hqLength <- Cli.runTransaction Codebase.hashLength
502-
let searchNames names = do
503-
let pped = PPED.makePPED (PPE.hqNamer 10 names) (PPE.suffixifyByHash names)
504-
unsuffixifiedPPE = PPED.unsuffixifiedPPE pped
505-
terms = Names.lookupHQTerm Names.IncludeSuffixes query names
506-
types = Names.lookupHQType Names.IncludeSuffixes query names
507-
terms' :: [(Referent, [HQ'.HashQualified Name])]
508-
terms' = map (\r -> (r, PPE.allTermNames unsuffixifiedPPE r)) (Set.toList terms)
509-
types' :: [(Reference, [HQ'.HashQualified Name])]
510-
types' = map (\r -> (r, PPE.allTypeNames unsuffixifiedPPE r)) (Set.toList types)
511-
pure (terms', types')
512-
if global
513-
then do
514-
Global.forAllProjectBranches \(projBranchNames, _ids) branch -> do
515-
let names = Branch.toNames . Branch.head $ branch
516-
(terms, types) <- searchNames names
517-
when (not (null terms) || not (null types)) do
518-
Cli.respond $ GlobalListNames projBranchNames hqLength types terms
519-
else do
520-
names <- Cli.currentNames
521-
(terms, types) <- searchNames names
522-
Cli.respond $ ListNames hqLength types terms
501+
NamesI global queries -> do
502+
mapM_ (handleNames global) queries
523503
DocsI srcs -> do
524504
for_ srcs docsI
525505
CreateAuthorI authorNameSegment authorFullName -> do
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
module Unison.Codebase.Editor.HandleInput.Names (handleNames) where
2+
3+
import Control.Monad (when)
4+
import Data.Set qualified as Set
5+
import Unison.Cli.Monad (Cli)
6+
import Unison.Cli.Monad qualified as Cli
7+
import Unison.Cli.NamesUtils qualified as Cli
8+
import Unison.Codebase qualified as Codebase
9+
import Unison.Codebase.Branch qualified as Branch
10+
import Unison.Codebase.Branch.Names qualified as Branch
11+
import Unison.Codebase.Editor.HandleInput.Global qualified as Global
12+
import Unison.Codebase.Editor.Input (ErrorMessageOrName, RawQuery)
13+
import Unison.Codebase.Editor.Output (Output (..))
14+
import Unison.HashQualifiedPrime qualified as HQ'
15+
import Unison.Name (Name)
16+
import Unison.NamesWithHistory qualified as Names
17+
import Unison.PrettyPrintEnv qualified as PPE
18+
import Unison.PrettyPrintEnv.Names qualified as PPE
19+
import Unison.PrettyPrintEnvDecl qualified as PPED
20+
import Unison.PrettyPrintEnvDecl.Names qualified as PPED
21+
import Unison.Reference (Reference)
22+
import Unison.Referent (Referent)
23+
import Unison.Util.Pretty qualified as P
24+
25+
-- | Handles a single @NamesI@ input query returning terms that match a given name.
26+
--
27+
-- Parameters:
28+
--
29+
-- * @global :: Bool@
30+
-- ** If @True@, search all projects and branches.
31+
-- ** If @False@, search only the current branch.
32+
--
33+
-- * @query :: (RawQuery, ErrorMessageOrName)@
34+
-- ** The first member is the raw @nameQuery@ being handled.
35+
-- ** The second member is the parsed @nameQuery@ that is either an error message
36+
-- to be printed or a name that can be looked up in the codebase.
37+
handleNames ::
38+
Bool ->
39+
(RawQuery, ErrorMessageOrName) ->
40+
Cli ()
41+
handleNames _ (nameQuery, Left errMsg) = do
42+
Cli.respond $
43+
PrintMessage $
44+
P.lines [prettyNameQuery, errMsg]
45+
where
46+
prettyNameQuery =
47+
P.red (P.bold $ P.string nameQuery) <> ":"
48+
handleNames global (nameQuery, Right query) = do
49+
hqLength <- Cli.runTransaction Codebase.hashLength
50+
let searchNames names = do
51+
let pped = PPED.makePPED (PPE.hqNamer 10 names) (PPE.suffixifyByHash names)
52+
unsuffixifiedPPE = PPED.unsuffixifiedPPE pped
53+
terms = Names.lookupHQTerm Names.IncludeSuffixes query names
54+
types = Names.lookupHQType Names.IncludeSuffixes query names
55+
terms' :: [(Referent, [HQ'.HashQualified Name])]
56+
terms' = map (\r -> (r, PPE.allTermNames unsuffixifiedPPE r)) (Set.toList terms)
57+
types' :: [(Reference, [HQ'.HashQualified Name])]
58+
types' = map (\r -> (r, PPE.allTypeNames unsuffixifiedPPE r)) (Set.toList types)
59+
pure (terms', types')
60+
if global
61+
then do
62+
Global.forAllProjectBranches \(projBranchNames, _ids) branch -> do
63+
let names = Branch.toNames . Branch.head $ branch
64+
(terms, types) <- searchNames names
65+
when (not (null terms) || not (null types)) do
66+
Cli.respond $ GlobalListNames nameQuery projBranchNames hqLength types terms
67+
else do
68+
names <- Cli.currentNames
69+
(terms, types) <- searchNames names
70+
Cli.respond $ ListNames nameQuery hqLength types terms

unison-cli/src/Unison/Codebase/Editor/Input.hs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ module Unison.Codebase.Editor.Input
2727
IsGlobal,
2828
DeleteOutput (..),
2929
DeleteTarget (..),
30+
31+
-- * Type aliases
32+
ErrorMessageOrName,
33+
RawQuery,
3034
)
3135
where
3236

@@ -61,6 +65,12 @@ type SourceName = Text -- "foo.u" or "buffer 7"
6165

6266
type PatchPath = Path.Split'
6367

68+
type ErrorMessageOrValue a = Either (P.Pretty P.ColorText) a
69+
70+
type ErrorMessageOrName = ErrorMessageOrValue (HQ.HashQualified Name)
71+
72+
type RawQuery = String
73+
6474
data OptionalPatch = NoPatch | DefaultPatch | UsePatch PatchPath
6575
deriving (Eq, Ord, Show)
6676

@@ -141,7 +151,8 @@ data Input
141151
-- > names .foo.bar
142152
-- > names .foo.bar#asdflkjsdf
143153
-- > names #sdflkjsdfhsdf
144-
NamesI IsGlobal (HQ.HashQualified Name)
154+
-- > names foo.bar foo.baz #sdflkjsdfhsdf
155+
NamesI IsGlobal [(RawQuery, ErrorMessageOrName)]
145156
| AliasTermI !Bool HashOrHQSplit' Path.Split' -- bool = force?
146157
| AliasTypeI !Bool HashOrHQSplit' Path.Split' -- bool = force?
147158
| AliasManyI [Path.HQSplit] Path'

unison-cli/src/Unison/Codebase/Editor/Output.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,12 @@ data Output
264264
| MovedOverExistingBranch Path'
265265
| DeletedEverything
266266
| ListNames
267+
String -- input namesQuery for which this output is being produced
267268
Int -- hq length to print References
268269
[(Reference, [HQ'.HashQualified Name])] -- type match, type names
269270
[(Referent, [HQ'.HashQualified Name])] -- term match, term names
270271
| GlobalListNames
272+
String -- input namesQuery for which this output is being produced
271273
(ProjectAndBranch ProjectName ProjectBranchName)
272274
Int -- hq length to print References
273275
[(Reference, [HQ'.HashQualified Name])] -- type match, type names
@@ -547,7 +549,7 @@ isFailure o = case o of
547549
MoveRootBranchConfirmation -> False
548550
MovedOverExistingBranch {} -> False
549551
DeletedEverything -> False
550-
ListNames _ tys tms -> null tms && null tys
552+
ListNames _ _ tys tms -> null tms && null tys
551553
GlobalListNames {} -> False
552554
ListOfDefinitions _ _ _ ds -> null ds
553555
GlobalFindBranchResults _ _ _ _ -> False

unison-cli/src/Unison/CommandLine/InputPatterns.hs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,13 @@ formatStructuredArgument schLength = \case
281281
else "." <> s
282282
pathArgStr = Text.pack $ show pathArg
283283

284-
-- | Converts an arbitrary argument to a `String`. This is for cases where the
284+
-- | Converts an arbitrary argument to a `String`.
285+
--
286+
-- This is for cases where the
285287
-- command /should/ accept a structured argument of some type, but currently
286288
-- wants a `String`.
289+
--
290+
-- This can also be used where the input argument needs to be included in the output.
287291
unifyArgument :: I.Argument -> String
288292
unifyArgument = either id (Text.unpack . formatStructuredArgument Nothing)
289293

@@ -2687,16 +2691,30 @@ names isGlobal =
26872691
cmdName
26882692
[]
26892693
I.Visible
2690-
[("name or hash", Required, definitionQueryArg)]
2691-
(P.wrap $ makeExample (names isGlobal) ["foo"] <> description)
2694+
[("name or hash", OnePlus, definitionQueryArg)]
2695+
description
26922696
$ \case
2693-
[thing] -> Input.NamesI isGlobal <$> handleHashQualifiedNameArg thing
2694-
args -> wrongArgsLength "exactly one argument" args
2697+
[] -> wrongArgsLength "at least one argument" []
2698+
[rawArg] -> do
2699+
let arg = handleArg rawArg
2700+
case arg of
2701+
(_, Left errMsg) -> Left errMsg
2702+
(argString, Right name) -> pure $ Input.NamesI isGlobal [(argString, Right name)]
2703+
rawArgs -> do
2704+
let args = handleArg <$> rawArgs
2705+
pure $ Input.NamesI isGlobal args
26952706
where
2696-
description
2697-
| isGlobal = "Iteratively search across all projects and branches for names matching `foo`. Note that this is expected to be quite slow and is primarily for debugging issues with your codebase."
2698-
| otherwise = "List all known names for `foo` in the current branch."
2707+
isGlobalPreamble = "Iteratively search names or hashes across all projects and branches."
2708+
isNotGlobalPreamble = "Search names or hashes in the current branch."
26992709
cmdName = if isGlobal then "debug.names.global" else "names"
2710+
description =
2711+
P.lines
2712+
[ if isGlobal then isGlobalPreamble else isNotGlobalPreamble,
2713+
P.wrap $ makeExample (names isGlobal) ["foo"] <> "List all known names for `foo`.",
2714+
P.wrap $ makeExample (names isGlobal) ["foo", "#bar"] <> "List all known names for the name `foo` and for the hash `#bar`.",
2715+
P.wrap $ makeExample (names isGlobal) [] <> "without arguments invokes a search to select names/hashes to list, which requires that `fzf` can be found within your PATH."
2716+
]
2717+
handleArg arg = (unifyArgument arg, handleHashQualifiedNameArg arg)
27002718

27012719
dependents, dependencies :: InputPattern
27022720
dependents =

unison-cli/src/Unison/CommandLine/OutputMessages.hs

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Data.List qualified as List
1414
import Data.List.Extra (notNull, nubOrd, nubOrdOn)
1515
import Data.List.NonEmpty qualified as NEList
1616
import Data.Map qualified as Map
17+
import Data.Ord (comparing)
1718
import Data.Sequence qualified as Seq
1819
import Data.Set qualified as Set
1920
import Data.Set.NonEmpty (NESet)
@@ -138,7 +139,6 @@ import Unison.Term (Term)
138139
import Unison.Term qualified as Term
139140
import Unison.Type (Type)
140141
import Unison.UnisonFile qualified as UF
141-
import Unison.Util.ColorText qualified
142142
import Unison.Util.Conflicted (Conflicted (..))
143143
import Unison.Util.Defn (Defn (..))
144144
import Unison.Util.Defns (Defns (..))
@@ -863,23 +863,16 @@ notifyUser dir = \case
863863
"",
864864
output
865865
]
866-
ListNames len types terms ->
867-
listOfNames len types terms
868-
GlobalListNames projectBranchName len types terms -> do
869-
output <- listOfNames len types terms
866+
ListNames namesQuery len types terms ->
867+
listOfNames namesQuery len types terms
868+
GlobalListNames namesQuery projectBranchName len types terms -> do
869+
output <- listOfNames namesQuery len types terms
870870
pure $
871871
P.lines
872872
[ P.wrap $ "Found results in " <> P.text (into @Text projectBranchName),
873873
"",
874874
output
875875
]
876-
-- > names foo
877-
-- Terms:
878-
-- Hash: #asdflkjasdflkjasdf
879-
-- Names: .util.frobnicate foo blarg.mcgee
880-
--
881-
-- Term (with hash #asldfkjsdlfkjsdf): .util.frobnicate, foo, blarg.mcgee
882-
-- Types (with hash #hsdflkjsdfsldkfj): Optional, Maybe, foo
883876
ListShallow buildPPE entries -> do
884877
let needPPE =
885878
entries
@@ -2364,7 +2357,7 @@ prettyTransportError = \case
23642357
Share.UnexpectedResponse resp ->
23652358
unexpectedServerResponse resp
23662359

2367-
unexpectedServerResponse :: Servant.ResponseF LazyByteString.ByteString -> P.Pretty Unison.Util.ColorText.ColorText
2360+
unexpectedServerResponse :: Servant.ResponseF LazyByteString.ByteString -> Pretty
23682361
unexpectedServerResponse resp =
23692362
(P.lines . catMaybes)
23702363
[ Just
@@ -2916,44 +2909,63 @@ listOfDefinitions ::
29162909
listOfDefinitions fscope ppe detailed results =
29172910
pure $ listOfDefinitions' fscope ppe detailed results
29182911

2919-
listOfNames :: Int -> [(Reference, [HQ'.HashQualified Name])] -> [(Referent, [HQ'.HashQualified Name])] -> IO Pretty
2920-
listOfNames len types terms = do
2912+
listOfNames :: String -> Int -> [(Reference, [HQ'.HashQualified Name])] -> [(Referent, [HQ'.HashQualified Name])] -> IO Pretty
2913+
listOfNames namesQuery len types terms = do
29212914
if null types && null terms
29222915
then
2923-
pure . P.callout "😶" $
2924-
P.sepNonEmpty "\n\n" $
2925-
[ P.wrap "I couldn't find anything by that name."
2916+
pure
2917+
. P.sepNonEmpty "\n"
2918+
$ [ P.red prettyQuery,
2919+
P.string "😶",
2920+
P.wrap "I couldn't find anything by that name."
29262921
]
29272922
else
2928-
pure . P.sepNonEmpty "\n\n" $
2929-
[ formatTypes types,
2930-
formatTerms terms
2923+
pure . P.sepNonEmpty "\n" $
2924+
[ P.green prettyQuery,
2925+
makeTable prettyRows
29312926
]
29322927
where
2933-
formatTerms tms =
2934-
P.lines . P.nonEmpty $ P.plural tms (P.blue "Term") : List.intersperse "" (go <$> tms)
2928+
prettyQuery = P.singleQuoted' (P.string namesQuery) ":"
2929+
2930+
makeTable =
2931+
P.column3Header "Hash" "Kind" "Names"
2932+
2933+
prettyRows = makePrettyRows $ List.sortBy compareRows rows
2934+
makePrettyRows =
2935+
fmap
2936+
( \(ref, kind, hqs) ->
2937+
( P.syntaxToColor ref,
2938+
P.blue kind,
2939+
P.group $
2940+
P.commas $
2941+
P.bold . P.syntaxToColor . prettyHashQualified'
2942+
<$> hqs
2943+
)
2944+
)
2945+
2946+
-- Compare rows by their list of names, first by comparing each name in the list
2947+
-- then by the length of the list of they share the same prefix
2948+
compareRows :: (a, b, [HQ'.HashQualified Name]) -> (a, b, [HQ'.HashQualified Name]) -> Ordering
2949+
compareRows (_, _, hqs1) (_, _, hqs2) =
2950+
Name.compareAlphabetical hqs1 hqs2 <> comparing length hqs1 hqs2
2951+
2952+
rows = termRows terms ++ typeRows types
2953+
2954+
termRows terms =
2955+
makeSortedRow "Term" <$> prettyTerms
29352956
where
2936-
go (ref, hqs) =
2937-
P.column2
2938-
[ ("Hash:", P.syntaxToColor (prettyReferent len ref)),
2939-
( "Names: ",
2940-
P.group $
2941-
P.spaced $
2942-
P.bold . P.syntaxToColor . prettyHashQualified' <$> List.sortBy Name.compareAlphabetical hqs
2943-
)
2944-
]
2945-
formatTypes types =
2946-
P.lines . P.nonEmpty $ P.plural types (P.blue "Type") : List.intersperse "" (go <$> types)
2957+
prettyTerms = terms & over (mapped . _1) (prettyReferent len)
2958+
2959+
typeRows types =
2960+
makeSortedRow "Type" <$> prettyTypes
29472961
where
2948-
go (ref, hqs) =
2949-
P.column2
2950-
[ ("Hash:", P.syntaxToColor (prettyReference len ref)),
2951-
( "Names:",
2952-
P.group $
2953-
P.spaced $
2954-
P.bold . P.syntaxToColor . prettyHashQualified' <$> List.sortBy Name.compareAlphabetical hqs
2955-
)
2956-
]
2962+
prettyTypes = types & over (mapped . _1) (prettyReference len)
2963+
2964+
makeSortedRow kind (ref, hqs) =
2965+
( ref,
2966+
kind,
2967+
List.sortBy Name.compareAlphabetical hqs
2968+
)
29572969

29582970
data ShowNumbers = ShowNumbers | HideNumbers
29592971

unison-cli/unison-cli.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ library
7474
Unison.Codebase.Editor.HandleInput.MoveBranch
7575
Unison.Codebase.Editor.HandleInput.MoveTerm
7676
Unison.Codebase.Editor.HandleInput.MoveType
77+
Unison.Codebase.Editor.HandleInput.Names
7778
Unison.Codebase.Editor.HandleInput.NamespaceDependencies
7879
Unison.Codebase.Editor.HandleInput.NamespaceDiffUtils
7980
Unison.Codebase.Editor.HandleInput.ProjectClone

0 commit comments

Comments
 (0)