20 |
20 |
21 object Server |
21 object Server |
22 { |
22 { |
23 /* Isabelle tool wrapper */ |
23 /* Isabelle tool wrapper */ |
24 |
24 |
25 private val default_text_length = "UTF-16" |
|
26 private lazy val default_logic = Isabelle_System.getenv("ISABELLE_LOGIC") |
25 private lazy val default_logic = Isabelle_System.getenv("ISABELLE_LOGIC") |
27 |
26 |
28 val isabelle_tool = Isabelle_Tool("vscode_server", "VSCode Language Server for PIDE", args => |
27 val isabelle_tool = Isabelle_Tool("vscode_server", "VSCode Language Server for PIDE", args => |
29 { |
28 { |
30 try { |
29 try { |
31 var log_file: Option[Path] = None |
30 var log_file: Option[Path] = None |
32 var text_length = Text.Length.encoding(default_text_length) |
|
33 var dirs: List[Path] = Nil |
31 var dirs: List[Path] = Nil |
34 var logic = default_logic |
32 var logic = default_logic |
35 var modes: List[String] = Nil |
33 var modes: List[String] = Nil |
36 var options = Options.init() |
34 var options = Options.init() |
37 var system_mode = false |
35 var system_mode = false |
38 |
36 |
39 def text_length_choice: String = |
|
40 commas(Text.Length.encodings.map( |
|
41 { case (a, _) => if (a == default_text_length) a + " (default)" else a })) |
|
42 |
|
43 val getopts = Getopts(""" |
37 val getopts = Getopts(""" |
44 Usage: isabelle vscode_server [OPTIONS] |
38 Usage: isabelle vscode_server [OPTIONS] |
45 |
39 |
46 Options are: |
40 Options are: |
47 -L FILE enable logging on FILE |
41 -L FILE enable logging on FILE |
48 -T LENGTH text length encoding: """ + text_length_choice + """ |
|
49 -d DIR include session directory |
42 -d DIR include session directory |
50 -l NAME logic session name (default ISABELLE_LOGIC=""" + quote(default_logic) + """) |
43 -l NAME logic session name (default ISABELLE_LOGIC=""" + quote(default_logic) + """) |
51 -m MODE add print mode for output |
44 -m MODE add print mode for output |
52 -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) |
45 -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) |
53 -s system build mode for session image |
46 -s system build mode for session image |
54 |
47 |
55 Run the VSCode Language Server protocol (JSON RPC) over stdin/stdout. |
48 Run the VSCode Language Server protocol (JSON RPC) over stdin/stdout. |
56 """, |
49 """, |
57 "L:" -> (arg => log_file = Some(Path.explode(File.standard_path(arg)))), |
50 "L:" -> (arg => log_file = Some(Path.explode(File.standard_path(arg)))), |
58 "T:" -> (arg => Text.Length.encoding(arg)), |
|
59 "d:" -> (arg => dirs = dirs ::: List(Path.explode(File.standard_path(arg)))), |
51 "d:" -> (arg => dirs = dirs ::: List(Path.explode(File.standard_path(arg)))), |
60 "l:" -> (arg => logic = arg), |
52 "l:" -> (arg => logic = arg), |
61 "m:" -> (arg => modes = arg :: modes), |
53 "m:" -> (arg => modes = arg :: modes), |
62 "o:" -> (arg => options = options + arg), |
54 "o:" -> (arg => options = options + arg), |
63 "s" -> (_ => system_mode = true)) |
55 "s" -> (_ => system_mode = true)) |
65 val more_args = getopts(args) |
57 val more_args = getopts(args) |
66 if (more_args.nonEmpty) getopts.usage() |
58 if (more_args.nonEmpty) getopts.usage() |
67 |
59 |
68 val log = Logger.make(log_file) |
60 val log = Logger.make(log_file) |
69 val channel = new Channel(System.in, System.out, log) |
61 val channel = new Channel(System.in, System.out, log) |
70 val server = new Server(channel, options, text_length, logic, dirs, modes, system_mode, log) |
62 val server = new Server(channel, options, logic, dirs, modes, system_mode, log) |
71 |
63 |
72 // prevent spurious garbage on the main protocol channel |
64 // prevent spurious garbage on the main protocol channel |
73 val orig_out = System.out |
65 val orig_out = System.out |
74 try { |
66 try { |
75 System.setOut(new PrintStream(new OutputStream { def write(n: Int) {} })) |
67 System.setOut(new PrintStream(new OutputStream { def write(n: Int) {} })) |
87 } |
79 } |
88 |
80 |
89 class Server( |
81 class Server( |
90 val channel: Channel, |
82 val channel: Channel, |
91 options: Options, |
83 options: Options, |
92 text_length: Text.Length = Text.Length.encoding(Server.default_text_length), |
|
93 session_name: String = Server.default_logic, |
84 session_name: String = Server.default_logic, |
94 session_dirs: List[Path] = Nil, |
85 session_dirs: List[Path] = Nil, |
95 modes: List[String] = Nil, |
86 modes: List[String] = Nil, |
96 system_mode: Boolean = false, |
87 system_mode: Boolean = false, |
97 log: Logger = No_Logger) |
88 log: Logger = No_Logger) |
220 progress.echo(fail_msg); error(fail_msg) |
211 progress.echo(fail_msg); error(fail_msg) |
221 } |
212 } |
222 } |
213 } |
223 |
214 |
224 val base = Build.session_base(options, false, session_dirs, session_name) |
215 val base = Build.session_base(options, false, session_dirs, session_name) |
225 val resources = |
216 val resources = new VSCode_Resources(options, base, log) |
226 new VSCode_Resources(options, text_length, base, log) |
|
227 { |
217 { |
228 override def commit(change: Session.Change): Unit = |
218 override def commit(change: Session.Change): Unit = |
229 if (change.deps_changed || undefined_blobs(change.version.nodes).nonEmpty) |
219 if (change.deps_changed || undefined_blobs(change.version.nodes).nonEmpty) |
230 delay_load.invoke() |
220 delay_load.invoke() |
231 } |
221 } |