proper hyperlink_command, notably for locate_query;
authorwenzelm
Thu, 29 Jun 2017 14:39:24 +0200
changeset 66215 9a8b6b86350c
parent 66214 eec1c99e1bdc
child 66216 d4949bae0bad
proper hyperlink_command, notably for locate_query; support bidirectional caret update;
src/Tools/VSCode/extension/src/extension.ts
src/Tools/VSCode/extension/src/library.ts
src/Tools/VSCode/src/protocol.scala
src/Tools/VSCode/src/server.scala
--- a/src/Tools/VSCode/extension/src/extension.ts	Thu Jun 29 13:28:08 2017 +0200
+++ b/src/Tools/VSCode/extension/src/extension.ts	Thu Jun 29 14:39:24 2017 +0200
@@ -9,9 +9,10 @@
 import * as state_panel from './state_panel';
 import * as symbol from './symbol';
 import * as completion from './completion';
-import { ExtensionContext, workspace, window, commands, languages } from 'vscode';
-import { LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, TransportKind, NotificationType }
-  from 'vscode-languageclient';
+import { Uri, Selection, Position, ExtensionContext, workspace, window, commands, languages }
+  from 'vscode';
+import { LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, TransportKind,
+  NotificationType } from 'vscode-languageclient';
 
 
 let last_caret_update: protocol.Caret_Update = {}
@@ -79,12 +80,28 @@
       }
     }
 
+    function goto_file(caret_update: protocol.Caret_Update)
+    {
+      if (caret_update.uri) {
+        workspace.openTextDocument(Uri.parse(caret_update.uri)).then(document =>
+        {
+          const editor = library.find_file_editor(document.uri)
+          if (editor) {
+            const pos = new Position(caret_update.line || 0, caret_update.character || 0)
+            editor.selections = [new Selection(pos, pos)]
+          }
+        })
+      }
+    }
+
     language_client.onReady().then(() =>
     {
       context.subscriptions.push(
         window.onDidChangeActiveTextEditor(_ => update_caret()),
         window.onDidChangeTextEditorSelection(_ => update_caret()))
       update_caret()
+
+      language_client.onNotification(protocol.caret_update_type, goto_file)
     })
 
 
--- a/src/Tools/VSCode/extension/src/library.ts	Thu Jun 29 13:28:08 2017 +0200
+++ b/src/Tools/VSCode/extension/src/library.ts	Thu Jun 29 14:39:24 2017 +0200
@@ -29,15 +29,17 @@
 
 export function find_file_editor(uri: Uri): TextEditor | undefined
 {
+  function check(editor: TextEditor): boolean
+  { return editor && is_file(editor.document.uri) && editor.document.uri.fsPath === uri.fsPath }
+
   if (is_file(uri)) {
-    return window.visibleTextEditors.find(editor =>
-      is_file(editor.document.uri) && editor.document.uri.fsPath === uri.fsPath)
+    if (check(window.activeTextEditor)) return window.activeTextEditor
+    else return window.visibleTextEditors.find(check)
   }
   else return undefined
 }
 
 
-
 /* Isabelle configuration */
 
 export function get_configuration<T>(name: string): T
--- a/src/Tools/VSCode/src/protocol.scala	Thu Jun 29 13:28:08 2017 +0200
+++ b/src/Tools/VSCode/src/protocol.scala	Thu Jun 29 14:39:24 2017 +0200
@@ -478,10 +478,19 @@
   }
 
 
-  /* caret handling */
+  /* caret update: bidirectional */
 
   object Caret_Update
   {
+    def apply(node_pos: Line.Node_Position): JSON.T =
+      Notification("PIDE/caret_update",
+        Map("uri" -> Url.print_file_name(node_pos.name),
+          "line" -> node_pos.pos.line,
+          "character" -> node_pos.pos.column))
+
+    def apply(file: JFile, pos: Line.Position): JSON.T =
+      apply(Line.Node_Position(file.getPath, pos))
+
     def unapply(json: JSON.T): Option[Option[(JFile, Line.Position)]] =
       json match {
         case Notification("PIDE/caret_update", Some(params)) =>
--- a/src/Tools/VSCode/src/server.scala	Thu Jun 29 13:28:08 2017 +0200
+++ b/src/Tools/VSCode/src/server.scala	Thu Jun 29 14:39:24 2017 +0200
@@ -527,8 +527,13 @@
     /* hyperlinks */
 
     override def hyperlink_command(
-      focus: Boolean, snapshot: Document.Snapshot, id: Document_ID.Generic, offset: Symbol.Offset = 0)
-        : Option[Hyperlink] = None
+      focus: Boolean, snapshot: Document.Snapshot, id: Document_ID.Generic,
+      offset: Symbol.Offset = 0): Option[Hyperlink] =
+    {
+      if (snapshot.is_outdated) None
+      else snapshot.find_command_position(id, offset).map(node_pos =>
+        new Hyperlink { def follow(unit: Unit) { channel.write(Protocol.Caret_Update(node_pos)) } })
+    }
 
 
     /* dispatcher thread */