From f1519ad50574be6b86480d53bd49ec0868791b5b Mon Sep 17 00:00:00 2001
From: mihailik <mihailik@gmail.com>
Date: Fri, 4 Dec 2015 08:09:59 +0000
Subject: [PATCH] [jump-to-line addon] Add

---
 addon/search/jumpToLine.js | 72 ++++++++++++++++++++++++++++++++++++++
 demo/search.html           |  8 +++--
 doc/manual.html            |  7 ++++
 3 files changed, 85 insertions(+), 2 deletions(-)
 create mode 100644 addon/search/jumpToLine.js

diff --git a/addon/search/jumpToLine.js b/addon/search/jumpToLine.js
new file mode 100644
index 000000000..58c5b6707
--- /dev/null
+++ b/addon/search/jumpToLine.js
@@ -0,0 +1,72 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
+// Define search commands. Depends on dialog.js or another
+// implementation of the openDialog method.
+
+// Replace works a little oddly -- it will do the replace on the next
+// Ctrl-G (or whatever is bound to findNext) press. You prevent a
+// replace by making sure the match is no longer selected when hitting
+// Ctrl-G.
+
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
+
+  function dialog(cm, text, shortText, deflt, f) {
+    if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
+    else f(prompt(shortText, deflt));
+  }
+
+  var jumpDialog =
+    'Jump to line: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use line:column or scroll% syntax)</span>';
+
+  function jumpToLine(cm) {
+    var cur = cm.getCursor();
+     dialog(cm, jumpDialog, 'Jump to line:', (cur.line+1)+':'+(cur.ch+1), function(posStr) {
+      if (!posStr) return;
+
+      var clnMatch = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr);
+      var prcMatch = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr);
+      var lnMatch = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr);
+      if (clnMatch) {
+        try {
+          var line = parseInt(clnMatch[1]);
+          var ch = parseInt(clnMatch[2]);
+          if ('+-'.indexOf(clnMatch[1].charAt(0))>=0)
+            line = cur.line+line+1;
+        }
+        catch (error) { return; }
+        cm.setCursor(line-1, ch-1);
+      }
+      else if (prcMatch) {
+        try {
+          var prc = parseFloat(prcMatch[1]);
+          var line = Math.round(cm.lineCount()*prc/100);
+          if ('+-'.indexOf(prcMatch[1].charAt(0))>=0)
+            line = cur.line+line+1;
+        }
+        catch (error) { return; }
+        cm.setCursor(line-1, cur.ch);
+      }
+      else if (lnMatch) {
+        try {
+          var line = parseInt(lnMatch[1]);
+          if ('+-'.indexOf(lnMatch[1].charAt(0))>=0)
+            line = cur.line+line+1;
+        }
+        catch (error) { return; }
+        cm.setCursor(line-1, cur.ch);
+      }
+     })
+  }
+
+  CodeMirror.commands.jumpToLine = jumpToLine;
+  CodeMirror.keyMap.default["Alt-G"] = "jumpToLine";
+});
diff --git a/demo/search.html b/demo/search.html
index 21c34251e..fd445db29 100644
--- a/demo/search.html
+++ b/demo/search.html
@@ -14,6 +14,7 @@
 <script src="../addon/search/search.js"></script>
 <script src="../addon/scroll/annotatescrollbar.js"></script>
 <script src="../addon/search/matchesonscrollbar.js"></script>
+<script src="../addon/search/jumpToLine.js"></script>
 <style type="text/css">
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
       dt {font-family: monospace; color: #666;}
@@ -84,12 +85,15 @@ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
       <dt>Shift-Ctrl-G / Shift-Cmd-G</dt><dd>Find previous</dd>
       <dt>Shift-Ctrl-F / Cmd-Option-F</dt><dd>Replace</dd>
       <dt>Shift-Ctrl-R / Shift-Cmd-Option-F</dt><dd>Replace all</dd>
-      <dt>Alt-F</dt><dd>Persistent search (dialog doesn't autoclose, enter to find next, shift-enter to find previous)</dd>
+      <dt>Alt-F</dt><dd>Persistent search (dialog doesn't autoclose,
+      enter to find next, shift-enter to find previous)</dd>
+      <dt>Alt-G</dt><dd>Jump to line</dd>
     </dl>
     <p>Searching is enabled by
     including <a href="../addon/search/search.js">addon/search/search.js</a>
     and <a href="../addon/search/searchcursor.js">addon/search/searchcursor.js</a>.
-    For good-looking input dialogs, you also want to include
+    Jump to line - including <a href="../addon/search/jumpToLine.js">addon/search/jumpToLine.js</a>.</p>
+    <p>For good-looking input dialogs, you also want to include
     <a href="../addon/dialog/dialog.js">addon/dialog/dialog.js</a>
     and <a href="../addon/dialog/dialog.css">addon/dialog/dialog.css</a>.</p>
   </article>
diff --git a/doc/manual.html b/doc/manual.html
index 4d3326eb5..6fed80226 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -2234,6 +2234,13 @@ editor.setOption("extraKeys", {
       of <a href="#addon_dialog"><code>openDialog</code></a> when
       available to make prompting for search queries less ugly.</dd>
 
+      <dt id="addon_jumptoline"><a href="../addon/search/jumpToLine.js"><code>search/jumpToLine.js</code></a></dt>
+      <dd>Implements jumpToLine command and binding <code>Alt-G</code> to it.
+      Accepts <code>linenumber</code>, <code>+/-linenumber</code>, <code>line:char</code>,
+      <code>scroll%</code> and <code>:linenumber</code> formats.
+      This will make use of <a href="#addon_dialog"><code>openDialog</code></a>
+      when available to make prompting for line number neater.</dd>
+
       <dt id="addon_matchesonscrollbar"><a href="../addon/search/matchesonscrollbar.js"><code>search/matchesonscrollbar.js</code></a></dt>
       <dd>Adds a <code>showMatchesOnScrollbar</code> method to editor
       instances, which should be given a query (string or regular
-- 
GitLab