-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
repl_reader.cr
131 lines (113 loc) · 3.87 KB
/
repl_reader.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
require "reply"
class Crystal::ReplReader < Reply::Reader
KEYWORDS = %w(
abstract alias annotation asm begin break case class
def do else elsif end ensure enum extend for fun
if in include instance_sizeof lib macro module
next of offsetof out pointerof private protected require
rescue return select sizeof struct super
then type typeof union uninitialized unless until
verbatim when while with yield
)
METHOD_KEYWORDS = %w(as as? is_a? nil? responds_to?)
CONTINUE_ERROR = [
"expecting identifier 'end', not 'EOF'",
"expecting token 'CONST', not 'EOF'",
"expecting any of these tokens: IDENT, CONST, `, <<, <, <=, ==, ===, !=, =~, !~, >>, >, >=, +, -, *, /, //, !, ~, %, &, |, ^, **, [], []?, []=, <=>, &+, &-, &*, &** (not 'EOF')",
"expecting any of these tokens: ;, NEWLINE (not 'EOF')",
"expecting token ')', not 'EOF'",
"expecting token ']', not 'EOF'",
"expecting token '}', not 'EOF'",
"expecting token '%}', not 'EOF'",
"expecting token '}', not ','",
"expected '}' or named tuple name, not EOF",
"unexpected token: NEWLINE",
"unexpected token: EOF",
"unexpected token: EOF (expecting when, else or end)",
"unexpected token: EOF (expecting ',', ';' or '\n')",
"Unexpected EOF on heredoc identifier",
"unterminated parenthesized expression",
"unterminated call",
"Unterminated string literal",
"unterminated hash literal",
"Unterminated command literal",
"unterminated array literal",
"unterminated tuple literal",
"unterminated macro",
"Unterminated string interpolation",
"invalid trailing comma in call",
"unknown token: '\\u{0}'",
]
@incomplete = false
@repl : Repl?
def initialize(@repl = nil)
super()
# `"`, `:`, `'`, are not a delimiter because symbols and strings are treated as one word.
# '=', !', '?' are not a delimiter because they could make part of method name.
self.word_delimiters = {{" \n\t+-*/,;@&%<>^\\[](){}|.~".chars}}
end
def prompt(io : IO, line_number : Int32, color? : Bool) : Nil
io << "icr:"
io << line_number
io.print(@incomplete ? '*' : '>')
io << ' '
end
def highlight(expression : String) : String
SyntaxHighlighter::Colorize.highlight!(expression)
end
def continue?(expression : String) : Bool
new_parser(expression).parse
@incomplete = false
false
rescue e : CodeError
@incomplete = e.message.in?(CONTINUE_ERROR)
if (message = e.message) && message.matches? /Unterminated heredoc: can't find ".*" anywhere before the end of file/
@incomplete = true
end
@incomplete
end
def format(expression : String) : String?
Crystal.format(expression).chomp rescue nil
end
def indentation_level(expression_before_cursor : String) : Int32?
parser = new_parser(expression_before_cursor)
parser.parse rescue nil
parser.type_nest + parser.def_nest + parser.fun_nest
end
def reindent_line(line)
case line.strip
when "end", ")", "]", "}"
0
when "else", "elsif", "rescue", "ensure", "in", "when"
-1
else
nil
end
end
def save_in_history?(expression : String) : Bool
!expression.blank?
end
def auto_complete(name_filter : String, expression : String) : {String, Array(String)}
if expression.ends_with? '.'
return "Keywords:", METHOD_KEYWORDS.dup
else
return "Keywords:", KEYWORDS.dup
end
end
def auto_completion_display_title(io : IO, title : String)
io << title
end
def auto_completion_display_selected_entry(io : IO, entry : String)
io << entry.colorize.red.bright
end
def auto_completion_display_entry(io : IO, entry_matched : String, entry_remaining : String)
io << entry_matched.colorize.red.bright << entry_remaining
end
private def new_parser(source)
if repl = @repl
repl.new_parser(source)
else
Parser.new(source)
end
end
end