11
11
use glsp:: prelude:: * ;
12
12
13
13
use gong:: { ItemClass , Item } ;
14
- use linefeed:: { Interface , ReadResult } ;
14
+ use linefeed:: { Interface , ReadResult , terminal :: DefaultTerminal } ;
15
15
16
16
static OPTS : gong:: options:: OptionSet = gong:: gong_option_set_fixed!(
17
17
[
@@ -49,7 +49,6 @@ fn usage() {
49
49
fn main ( ) {
50
50
debug_assert ! ( OPTS . is_valid( ) ) ;
51
51
52
- let cwd = std:: env:: current_dir ( ) . unwrap ( ) ;
53
52
let args: Vec < String > = std:: env:: args ( ) . skip ( 1 ) . collect ( ) ;
54
53
let mut files = Vec :: new ( ) ;
55
54
let mut run_repl = true ;
@@ -117,24 +116,41 @@ fn main() {
117
116
;; for “name” in a web browser.
118
117
;; E.g.: rust, lisp, std, special-forms, abbreviations, if, ', @, #n, #t, #f
119
118
;; Without argument, shows the reference manual.
120
- ;;; (www "url") loads “url” in a web browser, unless using --sandboxed.
121
- ;;; CTRL+D to exit, command input history stored in "./{history}"."# ,
119
+ ;;; (www "url") loads “url” in a web browser, unless using --sandboxed."# ,
122
120
name = env!( "CARGO_PKG_NAME" ) ,
123
121
version = env!( "CARGO_PKG_VERSION" ) ,
124
122
homepage = env!( "CARGO_PKG_HOMEPAGE" ) ,
123
+ ) ;
124
+
125
+ match Interface :: new ( env ! ( "CARGO_PKG_NAME" ) ) {
126
+ Ok ( cli) => {
127
+ repl ( runtime, sandboxed, cli) ;
128
+ } ,
129
+ Err ( err) => {
130
+ eprintln ! ( ";;; Terminal is not fully functional: {}" , err) ;
131
+ degraded_repl ( runtime, sandboxed) ;
132
+ }
133
+ } ;
134
+ }
135
+
136
+ fn repl ( runtime : Runtime , sandboxed : bool , cli : Interface < DefaultTerminal > ) {
137
+ let cwd = std:: env:: current_dir ( ) . unwrap ( ) ;
138
+
139
+ eprintln ! (
140
+ r#";;; CTRL+D to exit, command input history stored in "./{history}"."# ,
125
141
history = HISTORY_FILE ,
126
142
) ;
127
- let cli = Interface :: new ( env ! ( "CARGO_PKG_NAME" ) ) . unwrap ( ) ;
143
+
128
144
if let Err ( e) = cli. load_history ( HISTORY_FILE ) {
129
145
if e. kind ( ) != std:: io:: ErrorKind :: NotFound {
130
146
eprintln ! ( "ERROR: failed to load REPL history from {} at {}, {:?}" ,
131
147
HISTORY_FILE , cwd. display( ) , e) ;
132
148
}
133
149
}
134
150
135
- {
136
- let mut reader = cli . lock_reader ( ) ;
137
- reader . set_blink_matching_paren ( true ) ;
151
+ if std :: env :: var ( "TERM" ) . map_or ( false , |s| { s != "dumb" } ) {
152
+ // These options need features not available in dumb terminals.
153
+ cli . lock_reader ( ) . set_blink_matching_paren ( true ) ;
138
154
}
139
155
140
156
loop {
@@ -143,24 +159,11 @@ fn main() {
143
159
match cli. read_line ( ) {
144
160
Ok ( line) => {
145
161
match line {
146
- ReadResult :: Input ( mut line) => {
147
- line = line. trim_end ( ) . to_string ( ) ;
162
+ ReadResult :: Input ( line) => {
148
163
runtime. run ( || {
149
- if line == "help" || line. starts_with ( "help " ) {
150
- let url = help ( Some ( line[ 4 ..] . trim_start ( ) ) ) ;
151
- if sandboxed {
152
- prn ! ( "{}" , url) ;
153
- } else {
154
- match www ( Some ( & url) ) {
155
- Ok ( _url) => { prn ! ( "{}" , url) ; } ,
156
- Err ( err) => { return Err ( err) ; }
157
- }
158
- }
159
- } else {
160
- match eval_line ( & line) {
161
- Ok ( result) => { prn ! ( "{}" , result) ; } ,
162
- Err ( err) => { eprn ! ( "{}" , err. val( ) ) ; }
163
- }
164
+ match eval_line ( & line, sandboxed) {
165
+ Ok ( result) => { prn ! ( "{}" , result) ; } ,
166
+ Err ( err) => { eprn ! ( "{}" , err. val( ) ) ; }
164
167
}
165
168
Ok ( ( ) )
166
169
} ) ;
@@ -175,6 +178,8 @@ fn main() {
175
178
} ,
176
179
Err ( err) => {
177
180
eprintln ! ( "Error: failed to read command line: {:?}" , err) ;
181
+ eprintln ! ( "Switching to degraded mode." ) ;
182
+ degraded_repl ( runtime, sandboxed) ;
178
183
break ;
179
184
}
180
185
}
@@ -186,16 +191,53 @@ fn main() {
186
191
}
187
192
}
188
193
189
- fn eval_line ( line : & str ) -> GResult < Val > {
190
- match glsp:: parse_all ( & line, None ) {
191
- Ok ( values) => {
192
- match glsp:: eval_multi ( & values, Some ( EnvMode :: Copied ) ) {
193
- Ok ( result) => Ok ( result) ,
194
- Err ( err) => Err ( error ! ( "Evaluation error: {}" , err. val( ) ) )
194
+ use std:: io:: { BufRead } ;
195
+ fn degraded_repl ( runtime : Runtime , sandboxed : bool ) {
196
+ eprint ! ( "> " ) ;
197
+ for line in std:: io:: stdin ( ) . lock ( ) . lines ( ) {
198
+ match line {
199
+ Ok ( line) => {
200
+ runtime. run ( || {
201
+ match eval_line ( & line, sandboxed) {
202
+ Ok ( result) => { prn ! ( "{}" , result) ; } ,
203
+ Err ( err) => { eprn ! ( "{}" , err. val( ) ) ; }
204
+ }
205
+ Ok ( ( ) )
206
+ } ) ;
207
+ } ,
208
+ Err ( err) => {
209
+ eprintln ! ( "Error: failed to read command line: {:?}" , err) ;
210
+ break ;
211
+ }
212
+ }
213
+ eprint ! ( "> " ) ;
214
+ }
215
+ }
216
+
217
+ fn eval_line ( mut line : & str , sandboxed : bool ) -> GResult < Val > {
218
+ line = line. trim_start ( ) . trim_end ( ) ;
219
+ if line == "help" || line. starts_with ( "help " ) {
220
+ let url = help ( Some ( line[ 4 ..] . trim_start ( ) ) ) ;
221
+ if sandboxed {
222
+ prn ! ( "{}" , url) ;
223
+ url. to_string ( ) . to_val ( )
224
+ } else {
225
+ match www ( Some ( & url) ) {
226
+ Ok ( url) => url. to_string ( ) . to_val ( ) ,
227
+ Err ( err) => Err ( err)
228
+ }
229
+ }
230
+ } else {
231
+ match glsp:: parse_all ( line, None ) {
232
+ Ok ( values) => {
233
+ match glsp:: eval_multi ( & values, Some ( EnvMode :: Copied ) ) {
234
+ Ok ( result) => Ok ( result) ,
235
+ Err ( err) => Err ( error ! ( "Evaluation error: {}" , err. val( ) ) )
236
+ }
237
+ } ,
238
+ Err ( err) => {
239
+ Err ( error ! ( "Syntax error: {}" , err. val( ) ) )
195
240
}
196
- } ,
197
- Err ( err) => {
198
- Err ( error ! ( "Syntax error: {}" , err. val( ) ) )
199
241
}
200
242
}
201
243
}
0 commit comments