@@ -2,7 +2,6 @@ package replpkg
2
2
3
3
import (
4
4
"bytes"
5
- "flag"
6
5
"fmt"
7
6
"io/ioutil"
8
7
"os"
@@ -23,36 +22,12 @@ import (
23
22
// Importing this package installs Import as go/types.DefaultImport.
24
23
"golang.org/x/tools/imports"
25
24
26
- "github.com/mitchellh/go-homedir"
27
25
"github.com/motemen/go-quickfix"
28
26
)
29
27
30
- const version = "0.2.5"
31
- const printerName = "__gore_p"
28
+ const printerName = "__gophernotes"
32
29
33
- var (
34
- flagAutoImport = flag .Bool ("autoimport" , false , "formats and adjusts imports automatically" )
35
- flagExtFiles = flag .String ("context" , "" ,
36
- "import packages, functions, variables and constants from external golang source files" )
37
- flagPkg = flag .String ("pkg" , "" , "specify a package where the session will be run inside" )
38
- )
39
-
40
- func homeDir () (home string , err error ) {
41
- home = os .Getenv ("GORE_HOME" )
42
- if home != "" {
43
- return
44
- }
45
-
46
- home , err = homedir .Dir ()
47
- if err != nil {
48
- return
49
- }
50
-
51
- home = filepath .Join (home , ".gore" )
52
- return
53
- }
54
-
55
- // Session encodes info about the current REPL session
30
+ // Session encodes info about the current REPL session.
56
31
type Session struct {
57
32
FilePath string
58
33
File * ast.File
@@ -82,7 +57,7 @@ func main() {
82
57
`
83
58
84
59
// printerPkgs is a list of packages that provides
85
- // pretty printing function. Preceding first.
60
+ // pretty printing function.
86
61
var printerPkgs = []struct {
87
62
path string
88
63
code string
@@ -94,7 +69,6 @@ var printerPkgs = []struct {
94
69
95
70
// NewSession initiates a new REPL
96
71
func NewSession () (* Session , error ) {
97
- var err error
98
72
99
73
s := & Session {
100
74
Fset : token .NewFileSet (),
@@ -103,6 +77,7 @@ func NewSession() (*Session, error) {
103
77
},
104
78
}
105
79
80
+ var err error
106
81
s .FilePath , err = tempFile ()
107
82
if err != nil {
108
83
return nil , err
@@ -117,12 +92,11 @@ func NewSession() (*Session, error) {
117
92
}
118
93
debugf ("could not import %q: %s" , pp .path , err )
119
94
}
120
-
121
95
if initialSource == "" {
122
- return nil , fmt .Errorf (` Could not load pretty printing package (even "fmt"; something is wrong)` )
96
+ return nil , fmt .Errorf (" Could not load pretty printing package" )
123
97
}
124
98
125
- s .File , err = parser .ParseFile (s .Fset , "gore_session .go" , initialSource , parser .Mode (0 ))
99
+ s .File , err = parser .ParseFile (s .Fset , "gophernotes_session .go" , initialSource , parser .Mode (0 ))
126
100
if err != nil {
127
101
return nil , err
128
102
}
@@ -136,22 +110,22 @@ func (s *Session) mainFunc() *ast.FuncDecl {
136
110
return s .File .Scope .Lookup ("main" ).Decl .(* ast.FuncDecl )
137
111
}
138
112
139
- // Run calls "go run" with appropriate files appended
140
- func (s * Session ) Run () ([]byte , error , bytes.Buffer ) {
113
+ // Run calls "go run" with appropriate files appended.
114
+ func (s * Session ) Run () ([]byte , bytes.Buffer , error ) {
141
115
f , err := os .Create (s .FilePath )
142
116
if err != nil {
143
- return [] byte {}, err , bytes.Buffer {}
117
+ return nil , bytes.Buffer {}, err
144
118
}
145
119
146
120
err = printer .Fprint (f , s .Fset , s .File )
147
121
if err != nil {
148
- return [] byte {}, err , bytes.Buffer {}
122
+ return nil , bytes.Buffer {}, err
149
123
}
150
124
151
125
return goRun (append (s .ExtraFilePaths , s .FilePath ))
152
126
}
153
127
154
- // tempFile prepares the temporary session file for the REPL
128
+ // tempFile prepares the temporary session file for the REPL.
155
129
func tempFile () (string , error ) {
156
130
dir , err := ioutil .TempDir ("" , "" )
157
131
if err != nil {
@@ -163,22 +137,20 @@ func tempFile() (string, error) {
163
137
return "" , err
164
138
}
165
139
166
- return filepath .Join (dir , "gore_session .go" ), nil
140
+ return filepath .Join (dir , "gophernotes_session .go" ), nil
167
141
}
168
142
169
- func goRun (files []string ) ([]byte , error , bytes.Buffer ) {
143
+ func goRun (files []string ) ([]byte , bytes.Buffer , error ) {
170
144
171
145
var stderr bytes.Buffer
172
146
173
147
args := append ([]string {"run" }, files ... )
174
148
debugf ("go %s" , strings .Join (args , " " ))
175
149
cmd := exec .Command ("go" , args ... )
176
150
cmd .Stdin = os .Stdin
177
- //cmd.Stdout = os.Stdout
178
- //cmd.Stderr = os.Stderr
179
151
cmd .Stderr = & stderr
180
152
out , err := cmd .Output ()
181
- return out , err , stderr
153
+ return out , stderr , err
182
154
}
183
155
184
156
func (s * Session ) evalExpr (in string ) (ast.Expr , error ) {
@@ -246,10 +218,10 @@ func (s *Session) appendStatements(stmts ...ast.Stmt) {
246
218
s .mainBody .List = append (s .mainBody .List , stmts ... )
247
219
}
248
220
249
- // Error is an exported type error
221
+ // Error is an exported error.
250
222
type Error string
251
223
252
- // ErrContinue and ErrQuit are specific exported errors
224
+ // ErrContinue and ErrQuit are specific exported error types.
253
225
const (
254
226
ErrContinue Error = "<continue input>"
255
227
ErrQuit Error = "<quit session>"
@@ -285,7 +257,7 @@ func (s *Session) reset() error {
285
257
return err
286
258
}
287
259
288
- file , err := parser .ParseFile (s .Fset , "gore_session .go" , source , parser .Mode (0 ))
260
+ file , err := parser .ParseFile (s .Fset , "gophernotes_session .go" , source , parser .Mode (0 ))
289
261
if err != nil {
290
262
return err
291
263
}
@@ -297,34 +269,56 @@ func (s *Session) reset() error {
297
269
}
298
270
299
271
// Eval handles the evaluation of code parsed from received messages
300
- func (s * Session ) Eval (in string ) (string , error , bytes.Buffer ) {
272
+ func (s * Session ) Eval (in string ) (string , bytes.Buffer , error ) {
301
273
debugf ("eval >>> %q" , in )
302
274
303
275
s .clearQuickFix ()
304
276
s .storeMainBody ()
305
277
306
- for _ , command := range commands {
307
- arg := strings .TrimPrefix (in , ":" + command .name )
308
- if arg == in {
278
+ // Split the lines of the input to check for special commands.
279
+ inLines := strings .Split (in , "\n " )
280
+ var nonImportLines []string
281
+ for _ , line := range inLines {
282
+
283
+ // Extract non-special lines.
284
+ if ! strings .HasPrefix (line , "import" ) && ! strings .HasPrefix (line , ":" ) {
285
+ nonImportLines = append (nonImportLines , line )
309
286
continue
310
287
}
311
288
312
- if arg == "" || strings . HasPrefix ( arg , " " ) {
313
- arg = strings . TrimSpace ( arg )
289
+ // Process special commands.
290
+ for _ , command := range commands {
314
291
315
- result , err := command .action (s , arg )
316
- if err != nil {
317
- if err == ErrQuit {
318
- return "" , err , bytes.Buffer {}
319
- }
320
- errorf ("%s: %s" , command .name , err )
292
+ // Extract any argument provided with the special command.
293
+ arg := strings .TrimPrefix (line , ":" + command .name )
294
+ if command .name == "import" {
295
+ arg = strings .TrimPrefix (arg , "import" )
296
+ }
297
+ if arg == line {
298
+ continue
321
299
}
322
300
323
- s .doQuickFix ()
324
- return result , nil , bytes.Buffer {}
301
+ // Apply the action associated with the special command.
302
+ if arg == "" || strings .HasPrefix (arg , " " ) {
303
+ arg = strings .TrimSpace (arg )
304
+ _ , err := command .action (s , arg )
305
+ if err != nil {
306
+ if err == ErrQuit {
307
+ return "" , bytes.Buffer {}, err
308
+ }
309
+ errorf ("%s: %s" , command .name , err )
310
+ }
311
+ }
325
312
}
326
313
}
327
314
315
+ // Join the non-special lines back together for evaluation.
316
+ in = strings .Join (nonImportLines , "\n " )
317
+ if len (in ) == 0 {
318
+ s .doQuickFix ()
319
+ return "" , bytes.Buffer {}, nil
320
+ }
321
+
328
322
if _ , err := s .evalExpr (in ); err != nil {
329
323
debugf ("expr :: err = %s" , err )
330
324
@@ -363,18 +357,15 @@ func (s *Session) Eval(in string) (string, error, bytes.Buffer) {
363
357
if err = s .importFile (functproxy ); err != nil {
364
358
errorf ("%s" , err )
365
359
if _ , ok := err .(scanner.ErrorList ); ok {
366
- return "" , ErrContinue , bytes.Buffer {}
360
+ return "" , bytes.Buffer {}, ErrContinue
367
361
}
368
362
}
369
363
}
370
364
}
371
365
372
- if * flagAutoImport {
373
- s .fixImports ()
374
- }
375
366
s .doQuickFix ()
376
367
377
- output , err , strerr := s .Run ()
368
+ output , strerr , err := s .Run ()
378
369
if err != nil {
379
370
if exitErr , ok := err .(* exec.ExitError ); ok {
380
371
// if failed with status 2, remove the last statement
@@ -388,7 +379,7 @@ func (s *Session) Eval(in string) (string, error, bytes.Buffer) {
388
379
errorf ("%s" , err )
389
380
}
390
381
391
- return string (output ), err , strerr
382
+ return string (output ), strerr , err
392
383
}
393
384
394
385
// storeMainBody stores current state of code so that it can be restored
0 commit comments