➡️ Migrate core package 'go-to-line' into ./packages

This commit is contained in:
David Wilson 2018-10-15 17:04:26 -07:00
parent d1fd0d251e
commit a5305f4ca3
12 changed files with 426 additions and 6 deletions

3
package-lock.json generated
View File

@ -2544,8 +2544,7 @@
"integrity": "sha1-hJgDKzttHMge68X3lpDY/in6v08="
},
"go-to-line": {
"version": "https://www.atom.io/api/packages/go-to-line/versions/0.33.0/tarball",
"integrity": "sha512-YD5zEkGQRTl6jrgAIOQ0Zr0rB/f/yPifxhz4od2kN+JfGVeb76xD9FG5OkR9dr0vEtPfJeDbG2WWTJ1JGMShqQ=="
"version": "file:packages/go-to-line"
},
"graceful-fs": {
"version": "4.1.11",

View File

@ -69,7 +69,7 @@
"git-utils": "5.2.1",
"github": "https://www.atom.io/api/packages/github/versions/0.20.1/tarball",
"glob": "^7.1.1",
"go-to-line": "https://www.atom.io/api/packages/go-to-line/versions/0.33.0/tarball",
"go-to-line": "file:packages/go-to-line",
"grammar-selector": "https://www.atom.io/api/packages/grammar-selector/versions/0.50.1/tarball",
"grim": "1.5.0",
"image-view": "https://www.atom.io/api/packages/image-view/versions/0.63.1/tarball",
@ -204,7 +204,7 @@
"fuzzy-finder": "1.8.2",
"github": "0.20.1",
"git-diff": "file:./packages/git-diff",
"go-to-line": "0.33.0",
"go-to-line": "file:./packages/go-to-line",
"grammar-selector": "0.50.1",
"image-view": "0.63.1",
"incompatible-packages": "file:./packages/incompatible-packages",

View File

@ -35,7 +35,7 @@ See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate
| **fuzzy-finder** | [`atom/fuzzy-finder`][fuzzy-finder] | |
| **github** | [`atom/github`][github] | |
| **git-diff** | [`./git-diff`](./git-diff) | [#17843](https://github.com/atom/atom/issues/17843) |
| **go-to-line** | [`atom/go-to-line`][go-to-line] | [#17844](https://github.com/atom/atom/issues/17844) |
| **go-to-line** | [`./go-to-line`](./go-to-line) | [#17844](https://github.com/atom/atom/issues/17844) |
| **grammar-selector** | [`atom/grammar-selector`][grammar-selector] | [#17845](https://github.com/atom/atom/issues/17845) |
| **image-view** | [`atom/image-view`][image-view] | |
| **incompatible-packages** | [`./incompatible-packages`](./incompatible-packages) | [#17846](https://github.com/atom/atom/issues/17846) |
@ -115,7 +115,6 @@ See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate
[find-and-replace]: https://github.com/atom/find-and-replace
[fuzzy-finder]: https://github.com/atom/fuzzy-finder
[github]: https://github.com/atom/github
[go-to-line]: https://github.com/atom/go-to-line
[grammar-selector]: https://github.com/atom/grammar-selector
[image-view]: https://github.com/atom/image-view
[keybinding-resolver]: https://github.com/atom/keybinding-resolver

4
packages/go-to-line/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.DS_Store
Thumbs.db
node_modules
npm-debug.log

View File

@ -0,0 +1,20 @@
Copyright (c) 2014 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,5 @@
# Go To Line package
Move the cursor to a specific line in the editor using <kbd>ctrl-g</kbd>.
![](https://f.cloud.github.com/assets/671378/2241602/fdd88c4c-9cd8-11e3-9d14-74844ec7da01.png)

View File

@ -0,0 +1,15 @@
'.platform-darwin, .platform-win32, .platform-linux':
'ctrl-g': 'go-to-line:toggle'
'.go-to-line atom-text-editor[mini]':
'enter': 'core:confirm',
'escape': 'core:cancel'
'.platform-darwin .go-to-line atom-text-editor[mini]':
'cmd-w': 'core:cancel'
'.platform-win32 .go-to-line atom-text-editor[mini]':
'ctrl-w': 'core:cancel'
'.platform-linux .go-to-line atom-text-editor[mini]':
'ctrl-w': 'core:cancel'

View File

@ -0,0 +1,105 @@
'use babel'
import { Point, TextEditor } from 'atom'
class GoToLineView {
constructor () {
this.miniEditor = new TextEditor({ mini: true })
this.miniEditor.element.addEventListener('blur', this.close.bind(this))
this.message = document.createElement('div')
this.message.classList.add('message')
this.element = document.createElement('div')
this.element.classList.add('go-to-line')
this.element.appendChild(this.miniEditor.element)
this.element.appendChild(this.message)
this.panel = atom.workspace.addModalPanel({
item: this,
visible: false
})
atom.commands.add('atom-text-editor', 'go-to-line:toggle', () => {
this.toggle()
return false
})
atom.commands.add(this.miniEditor.element, 'core:confirm', () => {
this.navigate()
})
atom.commands.add(this.miniEditor.element, 'core:cancel', () => {
this.close()
})
this.miniEditor.onWillInsertText((arg) => {
if (arg.text.match(/[^0-9:]/)) {
arg.cancel()
}
})
this.miniEditor.onDidChange(() => {
this.navigate({keepOpen: true})
})
}
toggle () {
this.panel.isVisible() ? this.close() : this.open()
}
close () {
if (!this.panel.isVisible()) return
this.miniEditor.setText('')
this.panel.hide()
if (this.miniEditor.element.hasFocus()) {
this.restoreFocus()
}
}
navigate (options = {}) {
const lineNumber = this.miniEditor.getText()
const editor = atom.workspace.getActiveTextEditor()
if (!options.keepOpen) {
this.close()
}
if (!editor || !lineNumber.length) return
const currentRow = editor.getCursorBufferPosition().row
const rowLineNumber = lineNumber.split(/:+/)[0] || ''
const row = rowLineNumber.length > 0 ? parseInt(rowLineNumber) - 1 : currentRow
const columnLineNumber = lineNumber.split(/:+/)[1] || ''
const column = columnLineNumber.length > 0 ? parseInt(columnLineNumber) - 1 : -1
const position = new Point(row, column)
editor.setCursorBufferPosition(position)
editor.unfoldBufferRow(row)
if (column < 0) {
editor.moveToFirstCharacterOfLine()
}
editor.scrollToBufferPosition(position, {
center: true
})
}
storeFocusedElement () {
this.previouslyFocusedElement = document.activeElement
return this.previouslyFocusedElement
}
restoreFocus () {
if (this.previouslyFocusedElement && this.previouslyFocusedElement.parentElement) {
return this.previouslyFocusedElement.focus()
}
atom.views.getView(atom.workspace).focus()
}
open () {
if (this.panel.isVisible() || !atom.workspace.getActiveTextEditor()) return
this.storeFocusedElement()
this.panel.show()
this.message.textContent = 'Enter a <row> or <row>:<column> to go there. Examples: "3" for row 3 or "2:7" for row 2 and column 7'
this.miniEditor.element.focus()
}
}
export default {
activate () {
return new GoToLineView()
}
}

View File

@ -0,0 +1,7 @@
'menu': [
'label': 'Edit'
'submenu': [
'label': 'Go to Line'
'command': 'go-to-line:toggle'
]
]

View File

@ -0,0 +1,31 @@
{
"name": "go-to-line",
"version": "0.33.0",
"main": "./lib/go-to-line-view",
"description": "Jump to a specific editor line number with `ctrl-g`.",
"license": "MIT",
"scripts": {
"lint": "standard"
},
"activationCommands": {
"atom-text-editor": [
"go-to-line:toggle"
]
},
"repository": "https://github.com/atom/atom",
"engines": {
"atom": "*"
},
"devDependencies": {
"standard": "^8.6.0"
},
"standard": {
"globals": [
"atom",
"waitsForPromise"
],
"ignore": [
"spec/fixtures"
]
}
}

View File

@ -0,0 +1,70 @@
var quicksort = function () {
var sort = function(items) {
if (items.length <= 1) return items;
var pivot = items.shift(), current, left = [], right = [];
while(items.length > 0) {
current = items.shift();
current < pivot ? left.push(current) : right.push(current);
}
return sort(left).concat(pivot).concat(sort(right));
};
return sort(Array.apply(this, arguments));
};
// adapted from:
// https://github.com/nzakas/computer-science-in-javascript/tree/master/algorithms/sorting/merge-sort-recursive
var mergeSort function (items){
var merge = function (left, right){
var result = [];
var il = 0;
var ir = 0;
while (il < left.length && ir < right.length){
if (left[il] < right[ir]){
result.push(left[il++]);
} else {
result.push(right[ir++]);
}
}
return result.concat(left.slice(il)).concat(right.slice(ir));
};
if (items.length < 2) {
return items;
}
var middle = Math.floor(items.length / 2),
left = items.slice(0, middle),
right = items.slice(middle),
params = merge(mergeSort(left), mergeSort(right));
// Add the arguments to replace everything between 0 and last item in the array
params.unshift(0, items.length);
items.splice.apply(items, params);
return items;
};
// adapted from:
// https://github.com/nzakas/computer-science-in-javascript/blob/master/algorithms/sorting/bubble-sort/bubble-sort.js
var bubbleSort = function (items){
var swap = function (items, firstIndex, secondIndex){
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
};
var len = items.length,
i, j, stop;
for (i=0; i < len; i++){
for (j=0, stop=len-i; j < stop; j++){
if (items[j] > items[j+1]){
swap(items, j, j+1);
}
}
}
return items;
};

View File

@ -0,0 +1,165 @@
'use babel'
/* eslint-env jasmine */
import GoToLineView from '../lib/go-to-line-view'
describe('GoToLine', () => {
let editor = null
let editorView = null
let goToLine = null
beforeEach(() => {
waitsForPromise(() => {
return atom.workspace.open('sample.js')
})
runs(() => {
const workspaceElement = atom.views.getView(atom.workspace)
workspaceElement.style.height = '200px'
workspaceElement.style.width = '1000px'
jasmine.attachToDOM(workspaceElement)
editor = atom.workspace.getActiveTextEditor()
editorView = atom.views.getView(editor)
goToLine = GoToLineView.activate()
editor.setCursorBufferPosition([1, 0])
})
})
describe('when go-to-line:toggle is triggered', () => {
it('adds a modal panel', () => {
expect(goToLine.panel.isVisible()).toBeFalsy()
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
})
})
describe('when entering a line number', () => {
it('only allows 0-9 and the colon character to be entered in the mini editor', () => {
expect(goToLine.miniEditor.getText()).toBe('')
goToLine.miniEditor.insertText('a')
expect(goToLine.miniEditor.getText()).toBe('')
goToLine.miniEditor.insertText('path/file.txt:56')
expect(goToLine.miniEditor.getText()).toBe('')
goToLine.miniEditor.insertText(':')
expect(goToLine.miniEditor.getText()).toBe(':')
goToLine.miniEditor.setText('')
goToLine.miniEditor.insertText('4')
expect(goToLine.miniEditor.getText()).toBe('4')
})
})
describe('when typing line numbers (auto-navigation)', () => {
it('automatically scrolls to the desired line', () => {
goToLine.miniEditor.insertText('13')
expect(editor.getCursorBufferPosition()).toEqual([12, 0])
})
})
describe('when typing line and column numbers (auto-navigation)', () => {
it('automatically scrolls to the desired line and column', () => {
goToLine.miniEditor.insertText('3:8')
expect(editor.getCursorBufferPosition()).toEqual([2, 7])
})
})
describe('when entering a line number and column number', () => {
it('moves the cursor to the column number of the line specified', () => {
expect(goToLine.miniEditor.getText()).toBe('')
goToLine.miniEditor.insertText('3:14')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(editor.getCursorBufferPosition()).toEqual([2, 13])
})
it('centers the selected line', () => {
goToLine.miniEditor.insertText('45:4')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
const rowsPerPage = editor.getRowsPerPage()
const currentRow = editor.getCursorBufferPosition().row - 1
expect(editor.getFirstVisibleScreenRow()).toBe(currentRow - Math.ceil(rowsPerPage / 2))
expect(editor.getLastVisibleScreenRow()).toBe(currentRow + Math.floor(rowsPerPage / 2))
})
})
describe('when entering a line number greater than the number of rows in the buffer', () => {
it('moves the cursor position to the first character of the last line', () => {
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
expect(goToLine.miniEditor.getText()).toBe('')
goToLine.miniEditor.insertText('71')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(goToLine.panel.isVisible()).toBeFalsy()
expect(editor.getCursorBufferPosition()).toEqual([70, 0])
})
})
describe('when entering a column number greater than the number in the specified line', () => {
it('moves the cursor position to the last character of the specified line', () => {
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
expect(goToLine.miniEditor.getText()).toBe('')
goToLine.miniEditor.insertText('3:43')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(goToLine.panel.isVisible()).toBeFalsy()
expect(editor.getCursorBufferPosition()).toEqual([2, 40])
})
})
describe('when core:confirm is triggered', () => {
describe('when a line number has been entered', () => {
it('moves the cursor to the first character of the line', () => {
goToLine.miniEditor.insertText('3')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(editor.getCursorBufferPosition()).toEqual([2, 4])
})
})
describe('when the line number entered is nested within foldes', () => {
it('unfolds all folds containing the given row', () => {
expect(editor.indentationForBufferRow(6)).toEqual(3)
editor.foldAll()
expect(editor.screenRowForBufferRow(6)).toEqual(0)
goToLine.miniEditor.insertText('7')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(editor.getCursorBufferPosition()).toEqual([6, 6])
})
})
})
describe('when no line number has been entered', () => {
it('closes the view and does not update the cursor position', () => {
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(goToLine.panel.isVisible()).toBeFalsy()
expect(editor.getCursorBufferPosition()).toEqual([1, 0])
})
})
describe('when no line number has been entered, but a column number has been entered', () => {
it('navigates to the column of the current line', () => {
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
goToLine.miniEditor.insertText('4:1')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(goToLine.panel.isVisible()).toBeFalsy()
expect(editor.getCursorBufferPosition()).toEqual([3, 0])
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
goToLine.miniEditor.insertText(':19')
atom.commands.dispatch(goToLine.miniEditor.element, 'core:confirm')
expect(goToLine.panel.isVisible()).toBeFalsy()
expect(editor.getCursorBufferPosition()).toEqual([3, 18])
})
})
describe('when core:cancel is triggered', () => {
it('closes the view and does not update the cursor position', () => {
atom.commands.dispatch(editorView, 'go-to-line:toggle')
expect(goToLine.panel.isVisible()).toBeTruthy()
atom.commands.dispatch(goToLine.miniEditor.element, 'core:cancel')
expect(goToLine.panel.isVisible()).toBeFalsy()
expect(editor.getCursorBufferPosition()).toEqual([1, 0])
})
})
})