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