Skip to content

Commit 5e7d92c

Browse files
committed
Expose more of the node api for createInterface
1 parent 3cd5719 commit 5e7d92c

File tree

5 files changed

+200
-71
lines changed

5 files changed

+200
-71
lines changed

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: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,71 +12,119 @@ A handle to a console interface.
1212

1313
A handle can be created with the `createInterface` function.
1414

15+
#### `READLINE`
16+
17+
``` purescript
18+
data READLINE :: !
19+
```
20+
21+
The effect of interacting with a stream via an `Interface`
22+
23+
#### `InterfaceOptions`
24+
25+
``` purescript
26+
data InterfaceOptions
27+
```
28+
29+
Options passed to `readline`'s `createInterface`
30+
31+
#### `output`
32+
33+
``` purescript
34+
output :: forall w eff. Option InterfaceOptions (Writable w eff)
35+
```
36+
37+
#### `completer`
38+
39+
``` purescript
40+
completer :: forall eff. Option InterfaceOptions (Completer eff)
41+
```
42+
43+
#### `terminal`
44+
45+
``` purescript
46+
terminal :: Option InterfaceOptions Boolean
47+
```
48+
49+
#### `historySize`
50+
51+
``` purescript
52+
historySize :: Option InterfaceOptions Int
53+
```
54+
1555
#### `Completer`
1656

1757
``` purescript
18-
type Completer eff = String -> Eff (console :: CONSOLE | eff) { completions :: Array String, matched :: String }
58+
type Completer eff = String -> Eff eff { completions :: Array String, matched :: String }
1959
```
2060

2161
A function which performs tab completion.
2262

23-
This function takes the partial command as input, and returns a collection of
63+
This function takes the partial command as input, and returns a collection of
2464
completions, as well as the matched portion of the input string.
2565

26-
#### `LineHandler`
66+
#### `createInterface`
2767

2868
``` purescript
29-
type LineHandler eff a = String -> Eff (console :: CONSOLE | eff) a
69+
createInterface :: forall r eff. Readable r eff -> Options InterfaceOptions -> Eff (readline :: READLINE | eff) Interface
3070
```
3171

32-
A function which handles input from the user.
72+
Builds an interface with the specified options.
3373

34-
#### `setLineHandler`
74+
#### `createConsoleInterface`
3575

3676
``` purescript
37-
setLineHandler :: forall eff a. Interface -> LineHandler eff a -> Eff (console :: CONSOLE | eff) Interface
77+
createConsoleInterface :: forall eff. Completer (readline :: READLINE, console :: CONSOLE, err :: EXCEPTION | eff) -> Eff (readline :: READLINE, console :: CONSOLE, err :: EXCEPTION | eff) Interface
3878
```
3979

40-
Set the current line handler function.
80+
Create an interface with the specified completion function.
81+
82+
#### `noCompletion`
83+
84+
``` purescript
85+
noCompletion :: forall eff. Completer eff
86+
```
87+
88+
A completion function which offers no completions.
4189

4290
#### `prompt`
4391

4492
``` purescript
45-
prompt :: forall eff. Interface -> Eff (console :: CONSOLE | eff) Interface
93+
prompt :: forall eff. Interface -> Eff (readline :: READLINE | eff) Interface
4694
```
4795

4896
Prompt the user for input on the specified `Interface`.
4997

5098
#### `setPrompt`
5199

52100
``` purescript
53-
setPrompt :: forall eff. String -> Int -> Interface -> Eff (console :: CONSOLE | eff) Interface
101+
setPrompt :: forall eff. String -> Int -> Interface -> Eff (readline :: READLINE | eff) Interface
54102
```
55103

56104
Set the prompt.
57105

58-
#### `createInterface`
106+
#### `close`
59107

60108
``` purescript
61-
createInterface :: forall eff. Completer eff -> Eff (console :: CONSOLE | eff) Interface
109+
close :: forall eff. Interface -> Eff (readline :: READLINE | eff) Interface
62110
```
63111

64-
Create an interface with the specified completion function.
112+
Close the specified `Interface`.
65113

66-
#### `close`
114+
#### `LineHandler`
67115

68116
``` purescript
69-
close :: forall eff. Interface -> Eff (console :: CONSOLE | eff) Interface
117+
type LineHandler eff a = String -> Eff eff a
70118
```
71119

72-
Close the specified `Interface`.
120+
A function which handles each line of input.
73121

74-
#### `noCompletion`
122+
#### `setLineHandler`
75123

76124
``` purescript
77-
noCompletion :: forall eff. Completer eff
125+
setLineHandler :: forall eff a. Interface -> LineHandler (readline :: READLINE | eff) a -> Eff (readline :: READLINE | eff) Interface
78126
```
79127

80-
A completion function which offers no completions.
128+
Set the current line handler function.
81129

82130

src/Node/ReadLine.js

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,27 @@
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+
return readline;
26+
};
1627
};
1728

1829
exports.prompt = function(readline) {
@@ -33,23 +44,14 @@ exports.setPrompt = function(prompt) {
3344
};
3445
};
3546

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) {
47+
exports.setLineHandler = function(readline) {
48+
return function(callback) {
5149
return function() {
52-
readline.close();
53-
return readline;
50+
readline.removeAllListeners('line');
51+
readline.on('line', function(line) {
52+
callback(line)();
53+
});
54+
return readline;
5455
};
56+
};
5557
};

src/Node/ReadLine.purs

Lines changed: 98 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,120 @@
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 (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.Maybe (Maybe(Just))
28+
import Data.Options (Options, Option, (:=), options, opt)
29+
import Node.Process (stdin, stdout)
30+
import Node.Stream (Readable, Writable)
931

1032
-- | A handle to a console interface.
1133
-- |
1234
-- | A handle can be created with the `createInterface` function.
1335
foreign import data Interface :: *
1436

37+
-- | The effect of interacting with a stream via an `Interface`
38+
foreign import data READLINE :: !
39+
40+
foreign import createInterfaceImpl :: forall eff.
41+
Foreign
42+
-> Eff ( readline :: READLINE | 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 eff
70+
-> Options InterfaceOptions
71+
-> Eff ( readline :: READLINE
72+
| eff )
73+
Interface
74+
createInterface input opts = createInterfaceImpl
75+
$ options $ opts
76+
<> opt "input" := input
2377

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

2796
-- | Prompt the user for input on the specified `Interface`.
28-
foreign import prompt :: forall eff. Interface -> Eff (console :: CONSOLE | eff) Interface
97+
foreign import prompt :: forall eff.
98+
Interface
99+
-> Eff ( readline :: READLINE | eff ) Interface
29100

30101
-- | 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
102+
foreign import setPrompt :: forall eff.
103+
String
104+
-> Int
105+
-> Interface
106+
-> Eff ( readline :: READLINE | eff ) Interface
35107

36108
-- | Close the specified `Interface`.
37-
foreign import close :: forall eff. Interface -> Eff (console :: CONSOLE | eff) Interface
109+
foreign import close :: forall eff.
110+
Interface
111+
-> Eff ( readline :: READLINE | eff ) Interface
38112

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

116+
-- | Set the current line handler function.
117+
foreign import setLineHandler :: forall eff a.
118+
Interface
119+
-> LineHandler ( readline :: READLINE | eff ) a
120+
-> Eff ( readline :: READLINE | eff ) Interface

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)