This is a new feature for purs ide which is suitable as a first contribution. In this issue I've written down why we'd want to add a namespace filter and how you could go about implementing it. A good point to get started is to read the CONTRIBUTING.md file in the root of this repository. If you want to pick this as your first contribution to purs ide I'd be happy to answer any questions or help you if you run into problems. Just ask here in the issue or on IRC at #purescript where I'm usually available during the European day.
Motivation
The idea is that we'd like to be able to specify to which namespaces purs ide should limit the results of a query. Here are some future features this would enable in editors:
- Split the type of command into type of or kind of, to let the user decide which of the two he wanted, in cases where type and constructor name overlap. With the new filter in place, type of would only allow declarations in the value namespace and the kind of command would limit its query results to the type namespace.
- An editor could determine that the user is editing a specific syntax construct and limit the completions to the correct namespace. For example, if we determined (eg. with a regex) that the user is editing an instance head we know that we only need to allow completions from the type or kind namespace.
- Allowing the editors to specify that they only want to import a type constructor, if it was determined that the to-be-imported identifier was at the type level. Right now, for example for newtypes which expose their constructor, it's impossible to only import the type.
Implementation
purs ide provides completions and type information through a set of commands. Through a JSON protocol editors can query the server. These queries are built up from a list of filters and an optional matcher. As the issue title already says, implementing this feature requires that we add a new filter. To do so we'll need to take two main steps:
- Implementing the filtering logic
- Parsing the new filter as JSON
Implementing the filtering logic
We'll need to implement a new function namespaceFilter :: NonEmpty IdeNamespace -> Filter, where the NonEmpty type is from Data.List.NonEmpty. It should be located in the Language.PureScript.Ide.Filter module, where all the other purs ide filters live. Inside this filter we'll need to only keep the declarations that live in the correct namespace.
For example, if we were filtering with IdeNSValue :| [IdeNSType] as the argument to namespaceFilter we'd need to remove all the IdeKindDecl declarations from the filtered modules. One thing to note here, is that the filters are also supposed to remove modules that contain no more declarations after the filter has been applied.
We'll want to add a couple of tests to tests/Language/PureScript/Ide/FilterSpec.hs to make sure our implementation does what we expect it to (I encourage you to write the tests first, but that's not for everyone and totally up to you).
After we have implemented the functionality we want our filter to have, it's time to wire everything up with the rest of purs ide.
Parsing the new filter
If you take a look at the psc-ide/PROTOCOL.md file, which documents the protocol purs ide speaks up to this point, and check out the Filter section you'll see that all the filters share some commonalities. They all have a top-level filter field, which contains the filter's name and a params field which contains the filters parameters. I'd suggest using a non-empty Array of Strings for the parameters to this filter. An example JSON encoded filter could look like:
{
"filter": "namespace",
"params":
{
"namespaces": ["value", "type", "kind"]
}
}
We'll then need to add another case to the FromJSON instance for Filter inside Language.PureScript.Ide.Filter. Once that instance is implemented and works correctly, we should be able to write queries that filter declarations by namespace!
Playing with it
Trying it out should look a little something like this:
mkdir test-project
cd test-project
pulp init
pulp build
purs ide server --log-level debug
# In a second terminal:
echo '{"command": "load"}' | purs ide client
echo '{"command": "complete", "params": {"filters": [{"filter": "namespace", "params": {"namespaces": ["kind"]}}]}}' | purs ide client
Which should return the Effect kind from Control.Monad.Eff.
This is a new feature for
purs idewhich is suitable as a first contribution. In this issue I've written down why we'd want to add a namespace filter and how you could go about implementing it. A good point to get started is to read theCONTRIBUTING.mdfile in the root of this repository. If you want to pick this as your first contribution topurs ideI'd be happy to answer any questions or help you if you run into problems. Just ask here in the issue or on IRC at #purescript where I'm usually available during the European day.Motivation
The idea is that we'd like to be able to specify to which namespaces
purs ideshould limit the results of a query. Here are some future features this would enable in editors:Implementation
purs ideprovides completions and type information through a set of commands. Through a JSON protocol editors can query the server. These queries are built up from a list of filters and an optional matcher. As the issue title already says, implementing this feature requires that we add a new filter. To do so we'll need to take two main steps:Implementing the filtering logic
We'll need to implement a new function
namespaceFilter :: NonEmpty IdeNamespace -> Filter, where theNonEmptytype is fromData.List.NonEmpty. It should be located in theLanguage.PureScript.Ide.Filtermodule, where all the otherpurs idefilters live. Inside this filter we'll need to only keep the declarations that live in the correct namespace.For example, if we were filtering with
IdeNSValue :| [IdeNSType]as the argument tonamespaceFilterwe'd need to remove all theIdeKindDecldeclarations from the filtered modules. One thing to note here, is that the filters are also supposed to remove modules that contain no more declarations after the filter has been applied.We'll want to add a couple of tests to
tests/Language/PureScript/Ide/FilterSpec.hsto make sure our implementation does what we expect it to (I encourage you to write the tests first, but that's not for everyone and totally up to you).After we have implemented the functionality we want our filter to have, it's time to wire everything up with the rest of
purs ide.Parsing the new filter
If you take a look at the psc-ide/PROTOCOL.md file, which documents the protocol
purs idespeaks up to this point, and check out the Filter section you'll see that all the filters share some commonalities. They all have a top-levelfilterfield, which contains the filter's name and aparamsfield which contains the filters parameters. I'd suggest using a non-empty Array of Strings for the parameters to this filter. An example JSON encoded filter could look like:{ "filter": "namespace", "params": { "namespaces": ["value", "type", "kind"] } }We'll then need to add another case to the
FromJSONinstance forFilterinsideLanguage.PureScript.Ide.Filter. Once that instance is implemented and works correctly, we should be able to write queries that filter declarations by namespace!Playing with it
Trying it out should look a little something like this:
Which should return the
Effectkind fromControl.Monad.Eff.