A Quick Introduction to psc-ide

Let’s explore the psc-ide client tool. In the latest version of PureScript, psc-ide is accessible in the purs ide command.

Before we start let’s install jq, which is a tool for working with JSON. We can use jq to pretty print JSON from the server. Then let’s create a new PureScript project.

dom@system: pulp init
dom@system: pulp build

You should now have a PureScript project that contains an ‘output’ folder. When we query psc-ide it will look in the output folder for the answers we’re looking for. Let’s start psc-ide server by running the following command in the project’s root directory.

dom@system: psc ide server

Then open a new terminal and tell psc-client to send a command to the server. Let’s load all of the project’s modules, so we can know more about the project.

dom@system: echo '{"command":"load"}' | purs ide client | jq '.'
{
  "result":"Loaded 34 modules and 0 source files.",
  "resultType":"success"
}

Notice how we pipe JSON to the client via standard input, and the client returns the response from the server. Now let’s find out the exact modules that are available.

dom@system: echo '{"command": "list", "params": { "type": "availableModules" }}' | purs ide client | jq '.'
{
  "resultType": "success",
  "result": [
    "Data.HeytingAlgebra",
    "Control.Semigroupoid",
    "Control.Bind",
    "Data.Semigroup",
    "Data.Ord.Unsafe",
    "Data.Ordering",
    "Data.EuclideanRing",
    "Data.Ring",
    "Data.Unit",
    "Data.Show",
    "Data.Void",
    "Data.NaturalTransformation",
    "Data.Bounded",
    "Data.Ord",
    "Data.Field",
    "Control.Monad.Eff.Unsafe",
    "Control.Applicative",
    "Control.Monad.Eff.Console",
    "PSCI.Support",
    "Data.Eq",
    "Control.Monad",
    "Control.Monad.Eff.Uncurried",
    "Control.Category",
    "Control.Monad.Eff",
    "Main",
    "Data.Functor",
    "Data.Semiring",
    "Data.BooleanAlgebra",
    "Prelude",
    "Control.Apply",
    "Control.Monad.Eff.Class",
    "Data.CommutativeRing",
    "Data.Function",
    "Data.Boolean"
  ]
}

Nice. That list of modules can be helpful when we can’t remember the name of a particular module. When we’re managing imports we can display this list and take advantage of our brain’s recognition capabilities when our remembering fails.

But what if we’re looking for a particular function but don’t know which module it’s in? What if all we know is that it starts with “mai?” Let’s use the “complete” command with a prefix filter to find the function we’re looking for.

dom@system: echo '{"command":"complete","params":{"filters":[{"filter": "prefix","params":{"search": "mai"}}]}}' | purs ide client | jq '.'
{
  "resultType": "success",
  "result": [
    {
      "type": "∀ e. Eff ( console ∷ CONSOLE | e ) Unit",
      "documentation": null,
      "module": "Main",
      "expandedType": "∀ e. Eff ( console ∷ CONSOLE | e ) Unit",
      "definedAt": null,
      "identifier": "main"
    }
  ]
}

Notice that the server response includes the module name, type signature, and other info about the identifiers.

So this is good for inspecting a static project, but what if we’re editing code? If we change a file in /src how do we let psc-ide know that the ‘output’ directory needs updating? Enter the “rebuild” command. After we change a file we can tell the server to rebuild that file. Let’s add a new function to Main.purs and tell the server to rebuild.

main :: forall e. Eff (console :: CONSOLE | e) Unit
main = do
  log "Hello sailor!"

doubleLog :: String -> Eff (console :: CONSOLE | e) Unit
doubleLog s = do
  log s
  log s
dom@system: echo '{"command": "rebuild","params": {"file": "src/Main.purs"}}' | purs ide client | jq '.'
{
  "resultType": "success",
  "result": []
}

Now if we search for doubleLog the server will be able to give us more info about it.

That’s it for now. You can find all the available commands on the psc-ide Protocol page.