Skip to content

Commit 98435d2

Browse files
committed
Merge pull request #4 from spicydonuts/expose-node-api
Expose more of the node api for createInterface
2 parents 3cd5719 + e40ab26 commit 98435d2

File tree

6 files changed

+146
-140
lines changed

6 files changed

+146
-140
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,4 @@ A low-level PureScript interface to the Node `readline` API.
88
bower install purescript-readline
99
```
1010

11-
## Module documentation
12-
13-
- [Node.ReadLine](docs/Node/ReadLine.md)
11+
Module documentation can be found on [Pursuit](https://pursuit.purescript.org/packages/purescript-node-readline)

bower.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
"package.json"
2222
],
2323
"dependencies": {
24-
"purescript-console": "^0.1.0"
24+
"purescript-console": "^0.1.0",
25+
"purescript-node-streams": "~0.3.0",
26+
"purescript-node-process": "~0.4.1",
27+
"purescript-options": "^0.6.0",
28+
"purescript-foreign": "^0.7.2"
2529
}
2630
}

docs/Node/ReadLine.md

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/Node/ReadLine.js

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
/* global exports */
2-
"use strict";
2+
'use strict';
33

44
// module Node.ReadLine
55

6-
exports.setLineHandler = function(readline) {
7-
return function(callback) {
8-
return function() {
9-
readline.removeAllListeners('line');
10-
readline.on('line', function(line) {
11-
callback(line)();
12-
});
13-
return readline;
14-
};
15-
};
6+
exports.createInterfaceImpl = function(options) {
7+
return function() {
8+
var readline = require('readline');
9+
return readline.createInterface({
10+
input: options.input,
11+
output: options.output,
12+
completer: options.completer && function(line) {
13+
var res = options.completer(line)();
14+
return [res.completions, res.suffix];
15+
},
16+
terminal: options.terminal,
17+
historySize: options.historySize
18+
});
19+
};
20+
};
21+
22+
exports.close = function(readline) {
23+
return function() {
24+
readline.close();
25+
};
1626
};
1727

1828
exports.prompt = function(readline) {
1929
return function() {
2030
readline.prompt();
21-
return readline;
2231
};
2332
};
2433

@@ -27,29 +36,18 @@ exports.setPrompt = function(prompt) {
2736
return function(readline) {
2837
return function() {
2938
readline.setPrompt(prompt, length);
30-
return readline;
3139
};
3240
};
3341
};
3442
};
3543

36-
exports.createInterface = function(completer) {
37-
return function() {
38-
var readline = require('readline');
39-
return readline.createInterface({
40-
input: process.stdin,
41-
output: process.stdout,
42-
completer: function(line) {
43-
var res = completer(line)();
44-
return [res.completions, res.suffix];
45-
}
46-
});
47-
};
48-
};
49-
50-
exports.close = function(readline) {
44+
exports.setLineHandler = function(readline) {
45+
return function(callback) {
5146
return function() {
52-
readline.close();
53-
return readline;
47+
readline.removeAllListeners('line');
48+
readline.on('line', function(line) {
49+
callback(line)();
50+
});
5451
};
52+
};
5553
};

src/Node/ReadLine.purs

Lines changed: 111 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,133 @@
11
-- | This module provides a binding to the Node `readline` API.
22

3-
module Node.ReadLine where
3+
module Node.ReadLine
4+
( Interface
5+
, READLINE
6+
, InterfaceOptions
7+
, Completer
8+
, LineHandler
9+
, createInterface
10+
, createConsoleInterface
11+
, output
12+
, completer
13+
, terminal
14+
, historySize
15+
, noCompletion
16+
, prompt
17+
, setPrompt
18+
, setLineHandler
19+
, close
20+
) where
421

5-
import Prelude (return)
6-
7-
import Control.Monad.Eff
8-
import Control.Monad.Eff.Console
22+
import Prelude (Unit, return, (<>), ($))
23+
import Control.Monad.Eff (Eff)
24+
import Control.Monad.Eff.Console (CONSOLE)
25+
import Control.Monad.Eff.Exception (EXCEPTION)
26+
import Data.Foreign (Foreign)
27+
import Data.Options (Options, Option, (:=), options, opt)
28+
import Node.Process (stdin, stdout)
29+
import Node.Stream (Readable, Writable)
930

1031
-- | A handle to a console interface.
1132
-- |
1233
-- | A handle can be created with the `createInterface` function.
1334
foreign import data Interface :: *
1435

36+
-- | The effect of interacting with a stream via an `Interface`
37+
foreign import data READLINE :: !
38+
39+
foreign import createInterfaceImpl :: forall eff.
40+
Foreign
41+
-> Eff ( readline :: READLINE
42+
| eff
43+
) Interface
44+
45+
-- | Options passed to `readline`'s `createInterface`
46+
data InterfaceOptions
47+
48+
output :: forall w eff. Option InterfaceOptions (Writable w eff)
49+
output = opt "output"
50+
51+
completer :: forall eff. Option InterfaceOptions (Completer eff)
52+
completer = opt "completer"
53+
54+
terminal :: Option InterfaceOptions Boolean
55+
terminal = opt "terminal"
56+
57+
historySize :: Option InterfaceOptions Int
58+
historySize = opt "historySize"
59+
1560
-- | A function which performs tab completion.
1661
-- |
17-
-- | This function takes the partial command as input, and returns a collection of
62+
-- | This function takes the partial command as input, and returns a collection of
1863
-- | completions, as well as the matched portion of the input string.
19-
type Completer eff = String -> Eff (console :: CONSOLE | eff) { completions :: Array String, matched :: String }
64+
type Completer eff = String -> Eff eff { completions :: Array String
65+
, matched :: String }
2066

21-
-- | A function which handles input from the user.
22-
type LineHandler eff a = String -> Eff (console :: CONSOLE | eff) a
67+
-- | Builds an interface with the specified options.
68+
createInterface :: forall r eff.
69+
Readable r ( readline :: READLINE
70+
| eff
71+
)
72+
-> Options InterfaceOptions
73+
-> Eff ( readline :: READLINE
74+
| eff
75+
) Interface
76+
createInterface input opts = createInterfaceImpl
77+
$ options $ opts
78+
<> opt "input" := input
2379

24-
-- | Set the current line handler function.
25-
foreign import setLineHandler :: forall eff a. Interface -> LineHandler eff a -> Eff (console :: CONSOLE | eff) Interface
80+
-- | Create an interface with the specified completion function.
81+
createConsoleInterface :: forall eff.
82+
Completer ( readline :: READLINE
83+
, console :: CONSOLE
84+
, err :: EXCEPTION
85+
| eff
86+
)
87+
-> Eff ( readline :: READLINE
88+
, console :: CONSOLE
89+
, err :: EXCEPTION
90+
| eff
91+
) Interface
92+
createConsoleInterface compl = createInterface stdin $ output := stdout
93+
<> completer := compl
94+
95+
-- | A completion function which offers no completions.
96+
noCompletion :: forall eff. Completer eff
97+
noCompletion s = return { completions: [], matched: s }
2698

2799
-- | Prompt the user for input on the specified `Interface`.
28-
foreign import prompt :: forall eff. Interface -> Eff (console :: CONSOLE | eff) Interface
100+
foreign import prompt :: forall eff.
101+
Interface
102+
-> Eff ( readline :: READLINE
103+
| eff
104+
) Unit
29105

30106
-- | Set the prompt.
31-
foreign import setPrompt :: forall eff. String -> Int -> Interface -> Eff (console :: CONSOLE | eff) Interface
32-
33-
-- | Create an interface with the specified completion function.
34-
foreign import createInterface :: forall eff. Completer eff -> Eff (console :: CONSOLE | eff) Interface
107+
foreign import setPrompt :: forall eff.
108+
String
109+
-> Int
110+
-> Interface
111+
-> Eff ( readline :: READLINE
112+
| eff
113+
) Unit
35114

36115
-- | Close the specified `Interface`.
37-
foreign import close :: forall eff. Interface -> Eff (console :: CONSOLE | eff) Interface
116+
foreign import close :: forall eff.
117+
Interface
118+
-> Eff ( readline :: READLINE
119+
| eff
120+
) Unit
38121

39-
-- | A completion function which offers no completions.
40-
noCompletion :: forall eff. Completer eff
41-
noCompletion s = return { completions: [], matched: s }
122+
-- | A function which handles each line of input.
123+
type LineHandler eff a = String -> Eff eff a
42124

125+
-- | Set the current line handler function.
126+
foreign import setLineHandler :: forall eff a.
127+
Interface
128+
-> LineHandler ( readline :: READLINE
129+
| eff
130+
) a
131+
-> Eff ( readline :: READLINE
132+
| eff
133+
) Unit

test/Main.purs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
module Test.Main where
22

33
import Prelude
4-
5-
import Control.Monad.Eff
64
import Control.Monad.Eff.Console
7-
85
import Node.ReadLine
96

107
main = do
11-
interface <- createInterface noCompletion
8+
interface <- createConsoleInterface noCompletion
129

1310
setPrompt "> " 2 interface
1411
prompt interface

0 commit comments

Comments
 (0)