Skip to content

Commit e5e42ee

Browse files
committed
Implement completions for cabal files
Includes: * completions for keywords, sensitive to stanzas * value completions for constant values, files, directories and exposed modules * completion of snippets for different stanzas and the required basic fields
1 parent 6111a10 commit e5e42ee

File tree

30 files changed

+2314
-295
lines changed

30 files changed

+2314
-295
lines changed

ghcide/src/Development/IDE/Plugin/Completions.hs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ import qualified Language.LSP.Protocol.Lens as L
4949
import Language.LSP.Protocol.Message
5050
import Language.LSP.Protocol.Types
5151
import qualified Language.LSP.Server as LSP
52-
import qualified Language.LSP.VFS as VFS
5352
import Numeric.Natural
5453
import Text.Fuzzy.Parallel (Scored (..))
5554

ghcide/src/Text/Fuzzy/Parallel.hs

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
-- | Parallel versions of 'filter' and 'simpleFilter'
22

33
module Text.Fuzzy.Parallel
4-
( filter,
5-
simpleFilter,
6-
match,
4+
( filter, filter',
5+
simpleFilter, simpleFilter',
6+
match, defChunkSize, defMaxResults,
77
Scored(..)
88
) where
99

@@ -29,7 +29,6 @@ data Scored a = Scored {score :: !Int, original:: !a}
2929
-- Just 5
3030
--
3131
{-# INLINABLE match #-}
32-
3332
match :: T.Text -- ^ Pattern in lowercase except for first character
3433
-> T.Text -- ^ The text to search in.
3534
-> Maybe Int -- ^ The score
@@ -70,22 +69,13 @@ match (T.Text pArr pOff pLen) (T.Text sArr sOff sLen) = go 0 1 pOff sOff
7069

7170
toLowerAscii w = if (w - 65) < 26 then w .|. 0x20 else w
7271

73-
-- | The function to filter a list of values by fuzzy search on the text extracted from them.
74-
filter :: Int -- ^ Chunk size. 1000 works well.
75-
-> Int -- ^ Max. number of results wanted
76-
-> T.Text -- ^ Pattern.
77-
-> [t] -- ^ The list of values containing the text to search in.
78-
-> (t -> T.Text) -- ^ The function to extract the text from the container.
79-
-> [Scored t] -- ^ The list of results, sorted, highest score first.
80-
filter chunkSize maxRes pattern ts extract = partialSortByAscScore maxRes perfectScore (concat vss)
81-
where
82-
-- Preserve case for the first character, make all others lowercase
83-
pattern' = case T.uncons pattern of
84-
Just (c, rest) -> T.cons c (T.toLower rest)
85-
_ -> pattern
86-
vss = map (mapMaybe (\t -> flip Scored t <$> match pattern' (extract t))) (chunkList chunkSize ts)
87-
`using` parList (evalList rseq)
88-
perfectScore = fromMaybe (error $ T.unpack pattern) $ match pattern' pattern'
72+
-- | Sensible default value for chunk size to use when calling simple filter.
73+
defChunkSize :: Int
74+
defChunkSize = 1000
75+
76+
-- | Sensible default value for the number of max results to use when calling simple filter.
77+
defMaxResults :: Int
78+
defMaxResults = 10
8979

9080
-- | Return all elements of the list that have a fuzzy
9181
-- match against the pattern. Runs with default settings where
@@ -102,6 +92,52 @@ simpleFilter :: Int -- ^ Chunk size. 1000 works well.
10292
simpleFilter chunk maxRes pattern xs =
10393
filter chunk maxRes pattern xs id
10494

95+
96+
-- | The function to filter a list of values by fuzzy search on the text extracted from them,
97+
-- using a custom matching function which determines how close words are.
98+
filter' :: Int -- ^ Chunk size. 1000 works well.
99+
-> Int -- ^ Max. number of results wanted
100+
-> T.Text -- ^ Pattern.
101+
-> [t] -- ^ The list of values containing the text to search in.
102+
-> (t -> T.Text) -- ^ The function to extract the text from the container.
103+
-> (T.Text -> T.Text -> Maybe Int)
104+
-- ^ Custom scoring function to use for calculating how close words are
105+
-- When the function returns Nothing, this means the values are incomparable.
106+
-> [Scored t] -- ^ The list of results, sorted, highest score first.
107+
filter' chunkSize maxRes pattern ts extract match' = partialSortByAscScore maxRes perfectScore (concat vss)
108+
where
109+
-- Preserve case for the first character, make all others lowercase
110+
pattern' = case T.uncons pattern of
111+
Just (c, rest) -> T.cons c (T.toLower rest)
112+
_ -> pattern
113+
vss = map (mapMaybe (\t -> flip Scored t <$> match' pattern' (extract t))) (chunkList chunkSize ts)
114+
`using` parList (evalList rseq)
115+
perfectScore = fromMaybe (error $ T.unpack pattern) $ match' pattern' pattern'
116+
117+
-- | The function to filter a list of values by fuzzy search on the text extracted from them,
118+
-- using a custom matching function which determines how close words are.
119+
filter :: Int -- ^ Chunk size. 1000 works well.
120+
-> Int -- ^ Max. number of results wanted
121+
-> T.Text -- ^ Pattern.
122+
-> [t] -- ^ The list of values containing the text to search in.
123+
-> (t -> T.Text) -- ^ The function to extract the text from the container.
124+
-> [Scored t] -- ^ The list of results, sorted, highest score first.
125+
filter chunkSize maxRes pattern ts extract =
126+
filter' chunkSize maxRes pattern ts extract match
127+
128+
-- | Return all elements of the list that have a fuzzy match against the pattern,
129+
-- the closeness of the match is determined using the custom scoring match function that is passed.
130+
-- Runs with default settings where nothing is added around the matches, as case insensitive.
131+
{-# INLINABLE simpleFilter' #-}
132+
simpleFilter' :: Int -- ^ Chunk size. 1000 works well.
133+
-> Int -- ^ Max. number of results wanted
134+
-> T.Text -- ^ Pattern to look for.
135+
-> [T.Text] -- ^ List of texts to check.
136+
-> (T.Text -> T.Text -> Maybe Int)
137+
-- ^ Custom scoring function to use for calculating how close words are
138+
-> [Scored T.Text] -- ^ The ones that match.
139+
simpleFilter' chunk maxRes pattern xs match' =
140+
filter' chunk maxRes pattern xs id match'
105141
--------------------------------------------------------------------------------
106142

107143
chunkList :: Int -> [a] -> [[a]]

plugins/hls-cabal-plugin/hls-cabal-plugin.cabal

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,39 @@ library
2727
exposed-modules:
2828
Ide.Plugin.Cabal
2929
Ide.Plugin.Cabal.Diagnostics
30+
Ide.Plugin.Cabal.Completion.Completer.FilePath
31+
Ide.Plugin.Cabal.Completion.Completer.Module
32+
Ide.Plugin.Cabal.Completion.Completer.Simple
33+
Ide.Plugin.Cabal.Completion.Completer.Snippet
34+
Ide.Plugin.Cabal.Completion.Completer.Types
35+
Ide.Plugin.Cabal.Completion.Completions
36+
Ide.Plugin.Cabal.Completion.Data
37+
Ide.Plugin.Cabal.Completion.Types
3038
Ide.Plugin.Cabal.LicenseSuggest
3139
Ide.Plugin.Cabal.Parse
3240

41+
3342
build-depends:
3443
, base >=4.12 && <5
3544
, bytestring
36-
-- Ideally, we only want to support a single Cabal version, supporting
37-
-- older versions is completely pointless since Cabal is backwards compatible,
38-
-- the latest Cabal version can parse all versions of the Cabal file format.
39-
--
40-
-- However, stack is making this difficult, if we change the version of Cabal,
41-
-- we essentially need to make sure all other packages in the snapshot have their
42-
-- Cabal dependency version relaxed.
43-
-- Most packages have a Hackage revision, but stack won't pick these up (for sensible reasons)
44-
-- automatically, forcing us to manually update the packages revision id.
45-
-- This is a lot of work for almost zero benefit, so we just allow more versions here
46-
-- and we eventually completely drop support for building HLS with stack.
47-
, Cabal ^>=3.2 || ^>=3.4 || ^>=3.6 || ^>= 3.8 || ^>= 3.10
45+
, Cabal-syntax >= 3.7
46+
, containers
4847
, deepseq
4948
, directory
49+
, filepath
5050
, extra >=1.7.4
5151
, ghcide == 2.1.0.0
5252
, hashable
5353
, hls-plugin-api == 2.1.0.0
5454
, hls-graph == 2.1.0.0
55+
, lens
5556
, lsp ^>=2.0.0.0
5657
, lsp-types ^>=2.0.0.1
5758
, regex-tdfa ^>=1.3.1
5859
, stm
5960
, text
61+
, text-rope
62+
, transformers
6063
, unordered-containers >=0.2.10.0
6164
, containers
6265
hs-source-dirs: src
@@ -68,15 +71,24 @@ test-suite tests
6871
type: exitcode-stdio-1.0
6972
hs-source-dirs: test
7073
main-is: Main.hs
74+
other-modules:
75+
Completer
76+
Context
77+
Utils
7178
build-depends:
7279
, base
7380
, bytestring
81+
, Cabal-syntax >= 3.7
82+
, directory
7483
, filepath
7584
, ghcide
7685
, hls-cabal-plugin
7786
, hls-test-utils == 2.1.0.0
7887
, lens
88+
, lsp
7989
, lsp-types
8090
, tasty-hunit
8191
, text
92+
, text-rope
93+
, transformers
8294
, row-types

0 commit comments

Comments
 (0)