mirror of
https://github.com/atom/atom.git
synced 2026-01-26 15:28:27 -05:00
Merge pull request #18235 from atom/migrate-go-to-line-package
➡ Migrate core package 'go-to-line' into ./packages
This commit is contained in:
3
package-lock.json
generated
3
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
4
packages/go-to-line/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
node_modules
|
||||
npm-debug.log
|
||||
20
packages/go-to-line/LICENSE.md
Normal file
20
packages/go-to-line/LICENSE.md
Normal 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.
|
||||
5
packages/go-to-line/README.md
Normal file
5
packages/go-to-line/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Go To Line package
|
||||
|
||||
Move the cursor to a specific line in the editor using <kbd>ctrl-g</kbd>.
|
||||
|
||||

|
||||
15
packages/go-to-line/keymaps/go-to-line.cson
Normal file
15
packages/go-to-line/keymaps/go-to-line.cson
Normal 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'
|
||||
105
packages/go-to-line/lib/go-to-line-view.js
Normal file
105
packages/go-to-line/lib/go-to-line-view.js
Normal 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()
|
||||
}
|
||||
}
|
||||
7
packages/go-to-line/menus/go-to-line.cson
Normal file
7
packages/go-to-line/menus/go-to-line.cson
Normal file
@@ -0,0 +1,7 @@
|
||||
'menu': [
|
||||
'label': 'Edit'
|
||||
'submenu': [
|
||||
'label': 'Go to Line'
|
||||
'command': 'go-to-line:toggle'
|
||||
]
|
||||
]
|
||||
31
packages/go-to-line/package.json
Normal file
31
packages/go-to-line/package.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
70
packages/go-to-line/spec/fixtures/sample.js
vendored
Normal file
70
packages/go-to-line/spec/fixtures/sample.js
vendored
Normal 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;
|
||||
};
|
||||
165
packages/go-to-line/spec/go-to-line-spec.js
Normal file
165
packages/go-to-line/spec/go-to-line-spec.js
Normal 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])
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user