mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge branch 'master' into jlks-missing-services-fix
This commit is contained in:
@@ -48,7 +48,7 @@ For more information on how to work with Atom's official packages, see
|
||||
[JavaScript](https://github.com/styleguide/javascript),
|
||||
and [CSS](https://github.com/styleguide/css) styleguides.
|
||||
* Include thoughtfully-worded, well-structured
|
||||
[Jasmine](http://jasmine.github.io/) specs.
|
||||
[Jasmine](http://jasmine.github.io/) specs in the `./spec` folder. Run them using `apm test`.
|
||||
* Document new code based on the
|
||||
[Documentation Styleguide](#documentation-styleguide)
|
||||
* End files with a newline.
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.143.0"
|
||||
"atom-package-manager": "0.145.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ _ = require 'underscore-plus'
|
||||
temp = require 'temp'
|
||||
|
||||
directoryToOpen = temp.mkdirSync('browser-process-startup-')
|
||||
socketPath = path.join(os.tmpdir(), 'atom.sock')
|
||||
socketPath = path.join(os.tmpdir(), "atom-#{process.env.USER}.sock")
|
||||
numberOfRuns = 10
|
||||
|
||||
deleteSocketFile = ->
|
||||
|
||||
@@ -65,7 +65,7 @@ module.exports =
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
"""
|
||||
|
||||
'jschardet@1.1.0':
|
||||
'jschardet@1.1.1':
|
||||
license: 'LGPL'
|
||||
source: 'README.md in the repository'
|
||||
sourceText: """
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
'fontSize': 16
|
||||
'core':
|
||||
'themes': [
|
||||
'atom-dark-ui'
|
||||
'atom-dark-syntax'
|
||||
'one-dark-ui'
|
||||
'one-dark-syntax'
|
||||
]
|
||||
|
||||
@@ -217,6 +217,7 @@
|
||||
{label: 'Split Down', command: 'pane:split-down'}
|
||||
{label: 'Split Left', command: 'pane:split-left'}
|
||||
{label: 'Split Right', command: 'pane:split-right'}
|
||||
{label: 'Close Pane', command: 'pane:close'}
|
||||
{type: 'separator'}
|
||||
]
|
||||
'atom-pane': [
|
||||
@@ -225,5 +226,6 @@
|
||||
{label: 'Split Down', command: 'pane:split-down'}
|
||||
{label: 'Split Left', command: 'pane:split-left'}
|
||||
{label: 'Split Right', command: 'pane:split-right'}
|
||||
{label: 'Close Pane', command: 'pane:close'}
|
||||
{type: 'separator'}
|
||||
]
|
||||
|
||||
@@ -174,6 +174,7 @@
|
||||
{label: 'Split Down', command: 'pane:split-down'}
|
||||
{label: 'Split Left', command: 'pane:split-left'}
|
||||
{label: 'Split Right', command: 'pane:split-right'}
|
||||
{label: 'Close Pane', command: 'pane:close'}
|
||||
{type: 'separator'}
|
||||
]
|
||||
'atom-pane': [
|
||||
@@ -182,5 +183,6 @@
|
||||
{label: 'Split Down', command: 'pane:split-down'}
|
||||
{label: 'Split Left', command: 'pane:split-left'}
|
||||
{label: 'Split Right', command: 'pane:split-right'}
|
||||
{label: 'Close Pane', command: 'pane:close'}
|
||||
{type: 'separator'}
|
||||
]
|
||||
|
||||
@@ -196,6 +196,7 @@
|
||||
{label: 'Split Down', command: 'pane:split-down'}
|
||||
{label: 'Split Left', command: 'pane:split-left'}
|
||||
{label: 'Split Right', command: 'pane:split-right'}
|
||||
{label: 'Close Pane', command: 'pane:close'}
|
||||
{type: 'separator'}
|
||||
]
|
||||
'atom-pane': [
|
||||
@@ -204,5 +205,6 @@
|
||||
{label: 'Split Down', command: 'pane:split-down'}
|
||||
{label: 'Split Left', command: 'pane:split-left'}
|
||||
{label: 'Split Right', command: 'pane:split-right'}
|
||||
{label: 'Close Pane', command: 'pane:close'}
|
||||
{type: 'separator'}
|
||||
]
|
||||
|
||||
34
package.json
34
package.json
@@ -20,7 +20,7 @@
|
||||
"atomShellVersion": "0.21.3",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^3.1.5",
|
||||
"atom-keymap": "^4",
|
||||
"atom-space-pen-views": "^2.0.4",
|
||||
"babel-core": "^4.0.2",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
@@ -47,7 +47,7 @@
|
||||
"nslog": "^2.0.0",
|
||||
"oniguruma": "^4.0.0",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^3.3.3",
|
||||
"pathwatcher": "^4.3.1",
|
||||
"property-accessors": "^1.1.3",
|
||||
"q": "^1.1.2",
|
||||
"random-words": "0.0.1",
|
||||
@@ -64,13 +64,13 @@
|
||||
"space-pen": "3.8.2",
|
||||
"stacktrace-parser": "0.1.1",
|
||||
"temp": "0.8.1",
|
||||
"text-buffer": "^4.1.5",
|
||||
"text-buffer": "^5",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.6"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.26.0",
|
||||
"atom-dark-ui": "0.47.0",
|
||||
"atom-dark-ui": "0.49.0",
|
||||
"atom-light-syntax": "0.26.0",
|
||||
"atom-light-ui": "0.41.0",
|
||||
"base16-tomorrow-dark-theme": "0.25.0",
|
||||
@@ -81,16 +81,16 @@
|
||||
"one-light-ui": "0.4.0",
|
||||
"solarized-dark-syntax": "0.32.0",
|
||||
"solarized-light-syntax": "0.19.0",
|
||||
"archive-view": "0.52.0",
|
||||
"archive-view": "0.53.0",
|
||||
"autocomplete": "0.44.0",
|
||||
"autoflow": "0.22.0",
|
||||
"autosave": "0.20.0",
|
||||
"background-tips": "0.23.0",
|
||||
"bookmarks": "0.35.0",
|
||||
"bracket-matcher": "0.71.0",
|
||||
"bracket-matcher": "0.73.0",
|
||||
"command-palette": "0.34.0",
|
||||
"deprecation-cop": "0.37.0",
|
||||
"dev-live-reload": "0.44.0",
|
||||
"dev-live-reload": "0.45.0",
|
||||
"encoding-selector": "0.19.0",
|
||||
"exception-reporting": "0.24.0",
|
||||
"feedback": "0.34.0",
|
||||
@@ -99,25 +99,25 @@
|
||||
"git-diff": "0.54.0",
|
||||
"go-to-line": "0.30.0",
|
||||
"grammar-selector": "0.46.0",
|
||||
"image-view": "0.51.0",
|
||||
"image-view": "0.52.0",
|
||||
"incompatible-packages": "0.24.0",
|
||||
"keybinding-resolver": "0.29.0",
|
||||
"link": "0.30.0",
|
||||
"markdown-preview": "0.141.0",
|
||||
"markdown-preview": "0.143.0",
|
||||
"metrics": "0.45.0",
|
||||
"notifications": "0.32.0",
|
||||
"notifications": "0.33.0",
|
||||
"open-on-github": "0.34.0",
|
||||
"package-generator": "0.38.0",
|
||||
"release-notes": "0.52.0",
|
||||
"settings-view": "0.184.0",
|
||||
"snippets": "0.82.0",
|
||||
"settings-view": "0.185.0",
|
||||
"snippets": "0.84.0",
|
||||
"spell-check": "0.55.0",
|
||||
"status-bar": "0.63.0",
|
||||
"styleguide": "0.44.0",
|
||||
"symbols-view": "0.90.0",
|
||||
"symbols-view": "0.91.0",
|
||||
"tabs": "0.67.0",
|
||||
"timecop": "0.31.0",
|
||||
"tree-view": "0.167.0",
|
||||
"tree-view": "0.168.0",
|
||||
"update-package-dependencies": "0.9.0",
|
||||
"welcome": "0.25.0",
|
||||
"whitespace": "0.29.0",
|
||||
@@ -129,7 +129,7 @@
|
||||
"language-css": "0.28.0",
|
||||
"language-gfm": "0.67.0",
|
||||
"language-git": "0.10.0",
|
||||
"language-go": "0.21.0",
|
||||
"language-go": "0.22.0",
|
||||
"language-html": "0.29.0",
|
||||
"language-hyperlink": "0.12.2",
|
||||
"language-java": "0.14.0",
|
||||
@@ -139,12 +139,12 @@
|
||||
"language-make": "0.14.0",
|
||||
"language-mustache": "0.11.0",
|
||||
"language-objective-c": "0.15.0",
|
||||
"language-perl": "0.16.0",
|
||||
"language-perl": "0.19.0",
|
||||
"language-php": "0.21.0",
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.32.0",
|
||||
"language-ruby": "0.49.0",
|
||||
"language-ruby-on-rails": "0.20.0",
|
||||
"language-ruby-on-rails": "0.21.0",
|
||||
"language-sass": "0.36.0",
|
||||
"language-shellscript": "0.13.0",
|
||||
"language-source": "0.9.0",
|
||||
|
||||
@@ -115,6 +115,24 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(3).text).toBe ' var pivot = items.shift(), current, left = [], '
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(4).text).toBe ' right = [];'
|
||||
|
||||
describe "when the only whitespace characters are at the beginning of the line", ->
|
||||
beforeEach ->
|
||||
displayBuffer.setEditorWidthInChars(10)
|
||||
|
||||
it "wraps the line at the max length when indented with tabs", ->
|
||||
buffer.setTextInRange([[0, 0], [1, 0]], '\t\tabcdefghijklmnopqrstuvwxyz')
|
||||
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe ' abcdef'
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe ' ghijkl'
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe ' mnopqr'
|
||||
|
||||
it "wraps the line at the max length when indented with spaces", ->
|
||||
buffer.setTextInRange([[0, 0], [1, 0]], ' abcdefghijklmnopqrstuvwxyz')
|
||||
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe ' abcdef'
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe ' ghijkl'
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe ' mnopqr'
|
||||
|
||||
describe "when there are hard tabs", ->
|
||||
beforeEach ->
|
||||
buffer.setText(buffer.getText().replace(new RegExp(' ', 'g'), '\t'))
|
||||
@@ -124,9 +142,42 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(3).tokens[1].isHardTab).toBeTruthy()
|
||||
|
||||
describe "when a line is wrapped", ->
|
||||
it "correctly tokenizes soft wrap indentation tokens", ->
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[0].isSoftWrapIndentation).toBeTruthy()
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(4).tokens[1].isSoftWrapIndentation).toBeTruthy()
|
||||
it "breaks soft-wrap indentation into a token for each indentation level to support indent guides", ->
|
||||
tokenizedLine = displayBuffer.tokenizedLineForScreenRow(4)
|
||||
|
||||
expect(tokenizedLine.tokens[0].value).toBe(" ")
|
||||
expect(tokenizedLine.tokens[0].isSoftWrapIndentation).toBeTruthy()
|
||||
|
||||
expect(tokenizedLine.tokens[1].value).toBe(" ")
|
||||
expect(tokenizedLine.tokens[1].isSoftWrapIndentation).toBeTruthy()
|
||||
|
||||
expect(tokenizedLine.tokens[2].isSoftWrapIndentation).toBeFalsy()
|
||||
|
||||
describe "when editor.softWrapHangingIndent is set", ->
|
||||
beforeEach ->
|
||||
atom.config.set('editor.softWrapHangingIndent', 3)
|
||||
|
||||
it "further indents wrapped lines", ->
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe " return "
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(11).text).toBe " sort(left).concat(pivot).concat(sort(right)"
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(12).text).toBe " );"
|
||||
|
||||
it "includes hanging indent when breaking soft-wrap indentation into tokens", ->
|
||||
tokenizedLine = displayBuffer.tokenizedLineForScreenRow(4)
|
||||
|
||||
expect(tokenizedLine.tokens[0].value).toBe(" ")
|
||||
expect(tokenizedLine.tokens[0].isSoftWrapIndentation).toBeTruthy()
|
||||
|
||||
expect(tokenizedLine.tokens[1].value).toBe(" ")
|
||||
expect(tokenizedLine.tokens[1].isSoftWrapIndentation).toBeTruthy()
|
||||
|
||||
expect(tokenizedLine.tokens[2].value).toBe(" ") # hanging indent
|
||||
expect(tokenizedLine.tokens[2].isSoftWrapIndentation).toBeTruthy()
|
||||
|
||||
expect(tokenizedLine.tokens[3].value).toBe(" ") # odd space
|
||||
expect(tokenizedLine.tokens[3].isSoftWrapIndentation).toBeTruthy()
|
||||
|
||||
expect(tokenizedLine.tokens[4].isSoftWrapIndentation).toBeFalsy()
|
||||
|
||||
describe "when the buffer changes", ->
|
||||
describe "when buffer lines are updated", ->
|
||||
|
||||
@@ -9,7 +9,7 @@ webdriverio = require "../../../build/node_modules/webdriverio"
|
||||
AtomPath = remote.process.argv[0]
|
||||
AtomLauncherPath = path.join(__dirname, "..", "helpers", "atom-launcher.sh")
|
||||
ChromedriverPath = path.resolve(__dirname, '..', '..', '..', 'atom-shell', 'chromedriver', 'chromedriver')
|
||||
SocketPath = path.join(temp.mkdirSync("socket-dir"), "atom.sock")
|
||||
SocketPath = path.join(temp.mkdirSync("socket-dir"), "atom-#{process.env.USER}.sock")
|
||||
ChromedriverPort = 9515
|
||||
|
||||
buildAtomClient = (args, env) ->
|
||||
|
||||
@@ -1937,14 +1937,14 @@ describe "TextEditorComponent", ->
|
||||
gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(11), metaKey: true))
|
||||
nextAnimationFrame()
|
||||
gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(11), metaKey: true))
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[10, 0], [20, 0]]]
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [[[7, 4], [7, 6]], [[10, 0], [19, 0]]]
|
||||
|
||||
it "merges overlapping selections", ->
|
||||
gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(17), metaKey: true))
|
||||
gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(9), metaKey: true))
|
||||
nextAnimationFrame()
|
||||
gutterNode.dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenRowInGutter(9), metaKey: true))
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [[[5, 0], [20, 0]]]
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [[[5, 0], [19, 0]]]
|
||||
|
||||
describe "when the gutter is shift-clicked and dragged", ->
|
||||
describe "when the shift-click is below the existing selection's tail", ->
|
||||
|
||||
@@ -1626,7 +1626,54 @@ describe "TextEditor", ->
|
||||
[[6, 22], [6, 28]]
|
||||
]
|
||||
|
||||
it "can add selections to soft-wrapped line segments", ->
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(40)
|
||||
|
||||
editor.setSelectedScreenRange([[3, 10], [3, 15]])
|
||||
editor.addSelectionBelow()
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [
|
||||
[[3, 10], [3, 15]]
|
||||
[[4, 10], [4, 15]]
|
||||
]
|
||||
|
||||
it "takes atomic tokens into account", ->
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample-with-tabs-and-leading-comment.coffee', autoIndent: false).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.setSelectedBufferRange([[2, 1], [2, 3]])
|
||||
editor.addSelectionBelow()
|
||||
|
||||
expect(editor.getSelectedBufferRanges()).toEqual [
|
||||
[[2, 1], [2, 3]]
|
||||
[[3, 1], [3, 2]]
|
||||
]
|
||||
|
||||
describe "when the selection is empty", ->
|
||||
describe "when lines are soft-wrapped", ->
|
||||
beforeEach ->
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(40)
|
||||
|
||||
it "skips soft-wrap indentation tokens", ->
|
||||
editor.setCursorScreenPosition([3, 0])
|
||||
editor.addSelectionBelow()
|
||||
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [
|
||||
[[3, 0], [3, 0]]
|
||||
[[4, 4], [4, 4]]
|
||||
]
|
||||
|
||||
it "does not skip them if they're shorter than the current column", ->
|
||||
editor.setCursorScreenPosition([3, 37])
|
||||
editor.addSelectionBelow()
|
||||
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [
|
||||
[[3, 37], [3, 37]]
|
||||
[[4, 26], [4, 26]]
|
||||
]
|
||||
|
||||
it "does not skip lines that are shorter than the current column", ->
|
||||
editor.setCursorBufferPosition([3, 36])
|
||||
editor.addSelectionBelow()
|
||||
@@ -1690,7 +1737,54 @@ describe "TextEditor", ->
|
||||
[[3, 22], [3, 38]]
|
||||
]
|
||||
|
||||
it "can add selections to soft-wrapped line segments", ->
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(40)
|
||||
|
||||
editor.setSelectedScreenRange([[4, 10], [4, 15]])
|
||||
editor.addSelectionAbove()
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [
|
||||
[[4, 10], [4, 15]]
|
||||
[[3, 10], [3, 15]]
|
||||
]
|
||||
|
||||
it "takes atomic tokens into account", ->
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample-with-tabs-and-leading-comment.coffee', autoIndent: false).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.setSelectedBufferRange([[3, 1], [3, 2]])
|
||||
editor.addSelectionAbove()
|
||||
|
||||
expect(editor.getSelectedBufferRanges()).toEqual [
|
||||
[[3, 1], [3, 2]]
|
||||
[[2, 1], [2, 3]]
|
||||
]
|
||||
|
||||
describe "when the selection is empty", ->
|
||||
describe "when lines are soft-wrapped", ->
|
||||
beforeEach ->
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(40)
|
||||
|
||||
it "skips soft-wrap indentation tokens", ->
|
||||
editor.setCursorScreenPosition([5, 0])
|
||||
editor.addSelectionAbove()
|
||||
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [
|
||||
[[5, 0], [5, 0]]
|
||||
[[4, 4], [4, 4]]
|
||||
]
|
||||
|
||||
it "does not skip them if they're shorter than the current column", ->
|
||||
editor.setCursorScreenPosition([5, 29])
|
||||
editor.addSelectionAbove()
|
||||
|
||||
expect(editor.getSelectedScreenRanges()).toEqual [
|
||||
[[5, 29], [5, 29]]
|
||||
[[4, 26], [4, 26]]
|
||||
]
|
||||
|
||||
it "does not skip lines that are shorter than the current column", ->
|
||||
editor.setCursorBufferPosition([6, 36])
|
||||
editor.addSelectionAbove()
|
||||
|
||||
@@ -129,6 +129,7 @@ describe "ThemeManager", ->
|
||||
expect(importPaths[0]).toContain 'atom-dark-ui'
|
||||
|
||||
it 'adds theme-* classes to the workspace for each active theme', ->
|
||||
atom.config.set('core.themes', ['atom-dark-ui', 'atom-dark-syntax'])
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
themeManager.onDidChangeActiveThemes didChangeActiveThemesHandler = jasmine.createSpy()
|
||||
|
||||
|
||||
@@ -878,3 +878,25 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).foldable).toBe true
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).foldable).toBe false
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).foldable).toBe false
|
||||
|
||||
describe "when the buffer is configured with the null grammar", ->
|
||||
it "uses the placeholder tokens and does not actually tokenize using the grammar", ->
|
||||
spyOn(atom.grammars.nullGrammar, 'tokenizeLine').andCallThrough()
|
||||
buffer = atom.project.bufferForPathSync('sample.will-use-the-null-grammar')
|
||||
buffer.setText('a\nb\nc')
|
||||
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
tokenizeCallback = jasmine.createSpy('onDidTokenize')
|
||||
tokenizedBuffer.onDidTokenize(tokenizeCallback)
|
||||
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
expect(tokenizeCallback.callCount).toBe 1
|
||||
expect(atom.grammars.nullGrammar.tokenizeLine.callCount).toBe 0
|
||||
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens.length).toBe 1
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0].value).toBe 'a'
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens.length).toBe 1
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].value).toBe 'b'
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens.length).toBe 1
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].value).toBe 'c'
|
||||
|
||||
@@ -18,7 +18,7 @@ DefaultSocketPath =
|
||||
if process.platform is 'win32'
|
||||
'\\\\.\\pipe\\atom-sock'
|
||||
else
|
||||
path.join(os.tmpdir(), 'atom.sock')
|
||||
path.join(os.tmpdir(), "atom-#{process.env.USER}.sock")
|
||||
|
||||
# The application's singleton class.
|
||||
#
|
||||
|
||||
@@ -28,7 +28,7 @@ module.exports =
|
||||
type: 'string'
|
||||
themes:
|
||||
type: 'array'
|
||||
default: ['atom-dark-ui', 'atom-dark-syntax']
|
||||
default: ['one-dark-ui', 'one-dark-syntax']
|
||||
items:
|
||||
type: 'string'
|
||||
projectHome:
|
||||
@@ -149,6 +149,10 @@ module.exports =
|
||||
softWrapAtPreferredLineLength:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
softWrapHangingIndent:
|
||||
type: 'integer'
|
||||
default: 0
|
||||
minimum: 0
|
||||
scrollSensitivity:
|
||||
type: 'integer'
|
||||
default: 40
|
||||
|
||||
@@ -69,12 +69,17 @@ class DisplayBuffer extends Model
|
||||
scrollPastEnd: atom.config.get('editor.scrollPastEnd', scope: scopeDescriptor)
|
||||
softWrap: atom.config.get('editor.softWrap', scope: scopeDescriptor)
|
||||
softWrapAtPreferredLineLength: atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor)
|
||||
softWrapHangingIndent: atom.config.get('editor.softWrapHangingIndent', scope: scopeDescriptor)
|
||||
preferredLineLength: atom.config.get('editor.preferredLineLength', scope: scopeDescriptor)
|
||||
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrap', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrap = newValue
|
||||
@updateWrappedScreenLines()
|
||||
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrapHangingIndent', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrapHangingIndent = newValue
|
||||
@updateWrappedScreenLines()
|
||||
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrapAtPreferredLineLength', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrapAtPreferredLineLength = newValue
|
||||
@updateWrappedScreenLines() if @isSoftWrapped()
|
||||
@@ -859,6 +864,18 @@ class DisplayBuffer extends Model
|
||||
column = screenLine.clipScreenColumn(column, options)
|
||||
new Point(row, column)
|
||||
|
||||
# Clip the start and end of the given range to valid positions on screen.
|
||||
# See {::clipScreenPosition} for more information.
|
||||
#
|
||||
# * `range` The {Range} to clip.
|
||||
# * `options` (optional) See {::clipScreenPosition} `options`.
|
||||
# Returns a {Range}.
|
||||
clipScreenRange: (range, options) ->
|
||||
start = @clipScreenPosition(range.start, options)
|
||||
end = @clipScreenPosition(range.end, options)
|
||||
|
||||
new Range(start, end)
|
||||
|
||||
# Calculates a {Range} representing the start of the {TextBuffer} until the end.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
@@ -1145,7 +1162,10 @@ class DisplayBuffer extends Model
|
||||
softWraps = 0
|
||||
if @isSoftWrapped()
|
||||
while wrapScreenColumn = tokenizedLine.findWrapColumn(@getSoftWrapColumn())
|
||||
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(wrapScreenColumn)
|
||||
[wrappedLine, tokenizedLine] = tokenizedLine.softWrapAt(
|
||||
wrapScreenColumn,
|
||||
@configSettings.softWrapHangingIndent
|
||||
)
|
||||
break if wrappedLine.hasOnlySoftWrapIndentation()
|
||||
screenLines.push(wrappedLine)
|
||||
softWraps++
|
||||
|
||||
@@ -96,7 +96,8 @@ class GitRepository
|
||||
@subscriptions.add new Disposable(-> window.removeEventListener 'focus', onWindowFocus)
|
||||
|
||||
if @project?
|
||||
@subscriptions.add @project.eachBuffer (buffer) => @subscribeToBuffer(buffer)
|
||||
@project.getBuffers().forEach (buffer) => @subscribeToBuffer(buffer)
|
||||
@subscriptions.add @project.onDidAddBuffer (buffer) => @subscribeToBuffer(buffer)
|
||||
|
||||
# Public: Destroy this {GitRepository} object.
|
||||
#
|
||||
|
||||
@@ -124,6 +124,8 @@ class Marker
|
||||
Grim.deprecate("Use Marker::onDidChange instead")
|
||||
when 'destroyed'
|
||||
Grim.deprecate("Use Marker::onDidDestroy instead")
|
||||
else
|
||||
Grim.deprecate("Marker::on is deprecated. Use documented event subscription methods instead.")
|
||||
|
||||
EmitterMixin::on.apply(this, arguments)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ class Pane extends Model
|
||||
super
|
||||
|
||||
@emitter = new Emitter
|
||||
@itemSubscriptions = new WeakMap
|
||||
@items = []
|
||||
|
||||
@addItems(compact(params?.items ? []))
|
||||
@@ -249,6 +250,10 @@ class Pane extends Model
|
||||
|
||||
getPanes: -> [this]
|
||||
|
||||
unsubscribeFromItem: (item) ->
|
||||
@itemSubscriptions.get(item)?.dispose()
|
||||
@itemSubscriptions.delete(item)
|
||||
|
||||
###
|
||||
Section: Items
|
||||
###
|
||||
@@ -340,7 +345,9 @@ class Pane extends Model
|
||||
addItem: (item, index=@getActiveItemIndex() + 1) ->
|
||||
return if item in @items
|
||||
|
||||
if typeof item.on is 'function'
|
||||
if typeof item.onDidDestroy is 'function'
|
||||
@itemSubscriptions.set item, item.onDidDestroy => @removeItem(item, true)
|
||||
else if typeof item.on is 'function'
|
||||
@subscribe item, 'destroyed', => @removeItem(item, true)
|
||||
|
||||
@items.splice(index, 0, item)
|
||||
@@ -369,6 +376,7 @@ class Pane extends Model
|
||||
|
||||
if typeof item.on is 'function'
|
||||
@unsubscribe item
|
||||
@unsubscribeFromItem(item)
|
||||
|
||||
if item is @activeItem
|
||||
if @items.length is 1
|
||||
|
||||
@@ -118,9 +118,14 @@ class Project extends Model
|
||||
onDidChangePaths: (callback) ->
|
||||
@emitter.on 'did-change-paths', callback
|
||||
|
||||
onDidAddBuffer: (callback) ->
|
||||
@emitter.on 'did-add-buffer', callback
|
||||
|
||||
on: (eventName) ->
|
||||
if eventName is 'path-changed'
|
||||
Grim.deprecate("Use Project::onDidChangePaths instead")
|
||||
else
|
||||
Grim.deprecate("Project::on is deprecated. Use documented event subscription methods instead.")
|
||||
super
|
||||
|
||||
###
|
||||
@@ -434,6 +439,7 @@ class Project extends Model
|
||||
@buffers.splice(index, 0, buffer)
|
||||
@subscribeToBuffer(buffer)
|
||||
@emit 'buffer-created', buffer
|
||||
@emitter.emit 'did-add-buffer', buffer
|
||||
buffer
|
||||
|
||||
# Removes a {TextBuffer} association from the project.
|
||||
|
||||
@@ -67,6 +67,8 @@ class Selection extends Model
|
||||
Grim.deprecate("Use Selection::onDidChangeRange instead. Call ::getScreenRange() yourself in your callback if you need the range.")
|
||||
when 'destroyed'
|
||||
Grim.deprecate("Use Selection::onDidDestroy instead.")
|
||||
else
|
||||
Grim.deprecate("Selection::on is deprecated. Use documented event subscription methods instead.")
|
||||
|
||||
super
|
||||
|
||||
@@ -183,7 +185,7 @@ class Selection extends Model
|
||||
|
||||
# Public: Clears the selection, moving the marker to the head.
|
||||
clear: ->
|
||||
@marker.setProperties(goalBufferRange: null)
|
||||
@marker.setProperties(goalScreenRange: null)
|
||||
@marker.clearTail() unless @retainSelection
|
||||
@finalize()
|
||||
|
||||
@@ -656,38 +658,38 @@ class Selection extends Model
|
||||
|
||||
# Public: Moves the selection down one row.
|
||||
addSelectionBelow: ->
|
||||
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
|
||||
range = (@getGoalScreenRange() ? @getScreenRange()).copy()
|
||||
nextRow = range.end.row + 1
|
||||
|
||||
for row in [nextRow..@editor.getLastBufferRow()]
|
||||
for row in [nextRow..@editor.getLastScreenRow()]
|
||||
range.start.row = row
|
||||
range.end.row = row
|
||||
clippedRange = @editor.clipBufferRange(range)
|
||||
clippedRange = @editor.clipScreenRange(range, skipSoftWrapIndentation: true)
|
||||
|
||||
if range.isEmpty()
|
||||
continue if range.end.column > 0 and clippedRange.end.column is 0
|
||||
else
|
||||
continue if clippedRange.isEmpty()
|
||||
|
||||
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
|
||||
@editor.addSelectionForScreenRange(clippedRange, goalScreenRange: range)
|
||||
break
|
||||
|
||||
# Public: Moves the selection up one row.
|
||||
addSelectionAbove: ->
|
||||
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
|
||||
range = (@getGoalScreenRange() ? @getScreenRange()).copy()
|
||||
previousRow = range.end.row - 1
|
||||
|
||||
for row in [previousRow..0]
|
||||
range.start.row = row
|
||||
range.end.row = row
|
||||
clippedRange = @editor.clipBufferRange(range)
|
||||
clippedRange = @editor.clipScreenRange(range, skipSoftWrapIndentation: true)
|
||||
|
||||
if range.isEmpty()
|
||||
continue if range.end.column > 0 and clippedRange.end.column is 0
|
||||
else
|
||||
continue if clippedRange.isEmpty()
|
||||
|
||||
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
|
||||
@editor.addSelectionForScreenRange(clippedRange, goalScreenRange: range)
|
||||
break
|
||||
|
||||
# Public: Combines the given selection into this selection and then destroys
|
||||
@@ -696,12 +698,14 @@ class Selection extends Model
|
||||
# * `otherSelection` A {Selection} to merge with.
|
||||
# * `options` (optional) {Object} options matching those found in {::setBufferRange}.
|
||||
merge: (otherSelection, options) ->
|
||||
myGoalBufferRange = @getGoalBufferRange()
|
||||
otherGoalBufferRange = otherSelection.getGoalBufferRange()
|
||||
if myGoalBufferRange? and otherGoalBufferRange?
|
||||
options.goalBufferRange = myGoalBufferRange.union(otherGoalBufferRange)
|
||||
myGoalScreenRange = @getGoalScreenRange()
|
||||
otherGoalScreenRange = otherSelection.getGoalScreenRange()
|
||||
|
||||
if myGoalScreenRange? and otherGoalScreenRange?
|
||||
options.goalScreenRange = myGoalScreenRange.union(otherGoalScreenRange)
|
||||
else
|
||||
options.goalBufferRange = myGoalBufferRange ? otherGoalBufferRange
|
||||
options.goalScreenRange = myGoalScreenRange ? otherGoalScreenRange
|
||||
|
||||
@setBufferRange(@getBufferRange().union(otherSelection.getBufferRange()), options)
|
||||
otherSelection.destroy()
|
||||
|
||||
@@ -763,6 +767,6 @@ class Selection extends Model
|
||||
plantTail: ->
|
||||
@marker.plantTail()
|
||||
|
||||
getGoalBufferRange: ->
|
||||
if goalBufferRange = @marker.getProperties().goalBufferRange
|
||||
Range.fromObject(goalBufferRange)
|
||||
getGoalScreenRange: ->
|
||||
if goalScreenRange = @marker.getProperties().goalScreenRange
|
||||
Range.fromObject(goalScreenRange)
|
||||
|
||||
@@ -457,6 +457,10 @@ class TextEditor extends Model
|
||||
onDidChangeScrollLeft: (callback) ->
|
||||
@emitter.on 'did-change-scroll-left', callback
|
||||
|
||||
# TODO Remove once the tabs package no longer uses .on subscriptions
|
||||
onDidChangeIcon: (callback) ->
|
||||
@emitter.on 'did-change-icon', callback
|
||||
|
||||
on: (eventName) ->
|
||||
switch eventName
|
||||
when 'title-changed'
|
||||
@@ -512,6 +516,9 @@ class TextEditor extends Model
|
||||
when 'scroll-left-changed'
|
||||
deprecate("Use TextEditor::onDidChangeScrollLeft instead")
|
||||
|
||||
else
|
||||
deprecate("TextEditor::on is deprecated. Use documented event subscription methods instead.")
|
||||
|
||||
EmitterMixin::on.apply(this, arguments)
|
||||
|
||||
# Retrieves the current {TextBuffer}.
|
||||
@@ -1275,6 +1282,14 @@ class TextEditor extends Model
|
||||
# Returns a {Point}.
|
||||
clipScreenPosition: (screenPosition, options) -> @displayBuffer.clipScreenPosition(screenPosition, options)
|
||||
|
||||
# Extended: Clip the start and end of the given range to valid positions on screen.
|
||||
# See {::clipScreenPosition} for more information.
|
||||
#
|
||||
# * `range` The {Range} to clip.
|
||||
# * `options` (optional) See {::clipScreenPosition} `options`.
|
||||
# Returns a {Range}.
|
||||
clipScreenRange: (range, options) -> @displayBuffer.clipScreenRange(range, options)
|
||||
|
||||
###
|
||||
Section: Decorations
|
||||
###
|
||||
|
||||
@@ -138,12 +138,19 @@ class TokenizedBuffer extends Model
|
||||
|
||||
tokenizeInBackground: ->
|
||||
return if not @visible or @pendingChunk or not @isAlive()
|
||||
|
||||
@pendingChunk = true
|
||||
_.defer =>
|
||||
@pendingChunk = false
|
||||
@tokenizeNextChunk() if @isAlive() and @buffer.isAlive()
|
||||
|
||||
tokenizeNextChunk: ->
|
||||
# Short circuit null grammar which can just use the placeholder tokens
|
||||
if @grammar is atom.grammars.nullGrammar and @firstInvalidRow()?
|
||||
@invalidRows = []
|
||||
@markTokenizationComplete()
|
||||
return
|
||||
|
||||
rowsRemaining = @chunkSize
|
||||
|
||||
while @firstInvalidRow()? and rowsRemaining > 0
|
||||
@@ -177,10 +184,13 @@ class TokenizedBuffer extends Model
|
||||
if @firstInvalidRow()?
|
||||
@tokenizeInBackground()
|
||||
else
|
||||
unless @fullyTokenized
|
||||
@emit 'tokenized'
|
||||
@emitter.emit 'did-tokenize'
|
||||
@fullyTokenized = true
|
||||
@markTokenizationComplete()
|
||||
|
||||
markTokenizationComplete: ->
|
||||
unless @fullyTokenized
|
||||
@emit 'tokenized'
|
||||
@emitter.emit 'did-tokenize'
|
||||
@fullyTokenized = true
|
||||
|
||||
firstInvalidRow: ->
|
||||
@invalidRows[0]
|
||||
|
||||
@@ -11,6 +11,7 @@ module.exports =
|
||||
class TokenizedLine
|
||||
endOfLineInvisibles: null
|
||||
lineIsWhitespaceOnly: false
|
||||
firstNonWhitespaceIndex: 0
|
||||
foldable: false
|
||||
|
||||
constructor: ({tokens, @lineEnding, @ruleStack, @startBufferColumn, @fold, @tabLength, @indentLevel, @invisibles}) ->
|
||||
@@ -96,6 +97,7 @@ class TokenizedLine
|
||||
# Returns a {Number} representing the `line` position where the wrap would take place.
|
||||
# Returns `null` if a wrap wouldn't occur.
|
||||
findWrapColumn: (maxColumn) ->
|
||||
return unless maxColumn?
|
||||
return unless @text.length > maxColumn
|
||||
|
||||
if /\s/.test(@text[maxColumn])
|
||||
@@ -106,43 +108,37 @@ class TokenizedLine
|
||||
return @text.length
|
||||
else
|
||||
# search backward for the start of the word on the boundary
|
||||
for column in [maxColumn..0] when @isColumnOutsideSoftWrapIndentation(column)
|
||||
for column in [maxColumn..@firstNonWhitespaceIndex]
|
||||
return column + 1 if /\s/.test(@text[column])
|
||||
|
||||
return maxColumn
|
||||
|
||||
# Calculates how many trailing spaces in this line's indentation cannot fit in a single tab.
|
||||
#
|
||||
# Returns a {Number} representing the odd indentation spaces in this line.
|
||||
getOddIndentationSpaces: ->
|
||||
oddIndentLevel = @indentLevel - Math.floor(@indentLevel)
|
||||
Math.round(@tabLength * oddIndentLevel)
|
||||
buildSoftWrapIndentationTokens: (token, hangingIndent) ->
|
||||
totalIndentSpaces = (@indentLevel * @tabLength) + hangingIndent
|
||||
indentTokens = []
|
||||
while totalIndentSpaces > 0
|
||||
tokenLength = Math.min(@tabLength, totalIndentSpaces)
|
||||
indentToken = token.buildSoftWrapIndentationToken(tokenLength)
|
||||
indentTokens.push(indentToken)
|
||||
totalIndentSpaces -= tokenLength
|
||||
|
||||
buildSoftWrapIndentationTokens: (token) ->
|
||||
indentTokens = [0...Math.floor(@indentLevel)].map =>
|
||||
token.buildSoftWrapIndentationToken(@tabLength)
|
||||
indentTokens
|
||||
|
||||
if @getOddIndentationSpaces()
|
||||
indentTokens.concat(
|
||||
token.buildSoftWrapIndentationToken @getOddIndentationSpaces()
|
||||
)
|
||||
else
|
||||
indentTokens
|
||||
|
||||
softWrapAt: (column) ->
|
||||
softWrapAt: (column, hangingIndent) ->
|
||||
return [new TokenizedLine([], '', [0, 0], [0, 0]), this] if column == 0
|
||||
|
||||
rightTokens = new Array(@tokens...)
|
||||
leftTokens = []
|
||||
leftTextLength = 0
|
||||
while leftTextLength < column
|
||||
if leftTextLength + rightTokens[0].value.length > column
|
||||
rightTokens[0..0] = rightTokens[0].splitAt(column - leftTextLength)
|
||||
leftScreenColumn = 0
|
||||
|
||||
while leftScreenColumn < column
|
||||
if leftScreenColumn + rightTokens[0].screenDelta > column
|
||||
rightTokens[0..0] = rightTokens[0].splitAt(column - leftScreenColumn)
|
||||
nextToken = rightTokens.shift()
|
||||
leftTextLength += nextToken.value.length
|
||||
leftScreenColumn += nextToken.screenDelta
|
||||
leftTokens.push nextToken
|
||||
|
||||
indentationTokens = @buildSoftWrapIndentationTokens(leftTokens[0])
|
||||
indentationTokens = @buildSoftWrapIndentationTokens(leftTokens[0], hangingIndent)
|
||||
|
||||
leftFragment = new TokenizedLine(
|
||||
tokens: leftTokens
|
||||
@@ -167,11 +163,6 @@ class TokenizedLine
|
||||
isSoftWrapped: ->
|
||||
@lineEnding is null
|
||||
|
||||
isColumnOutsideSoftWrapIndentation: (column) ->
|
||||
return true if @softWrapIndentationTokens.length == 0
|
||||
|
||||
column > @softWrapIndentationDelta
|
||||
|
||||
isColumnInsideSoftWrapIndentation: (column) ->
|
||||
return false if @softWrapIndentationTokens.length == 0
|
||||
|
||||
@@ -216,15 +207,15 @@ class TokenizedLine
|
||||
outputTokens
|
||||
|
||||
markLeadingAndTrailingWhitespaceTokens: ->
|
||||
firstNonWhitespaceIndex = @text.search(NonWhitespaceRegex)
|
||||
if firstNonWhitespaceIndex > 0 and isPairedCharacter(@text, firstNonWhitespaceIndex - 1)
|
||||
firstNonWhitespaceIndex--
|
||||
@firstNonWhitespaceIndex = @text.search(NonWhitespaceRegex)
|
||||
if @firstNonWhitespaceIndex > 0 and isPairedCharacter(@text, @firstNonWhitespaceIndex - 1)
|
||||
@firstNonWhitespaceIndex--
|
||||
firstTrailingWhitespaceIndex = @text.search(TrailingWhitespaceRegex)
|
||||
@lineIsWhitespaceOnly = firstTrailingWhitespaceIndex is 0
|
||||
index = 0
|
||||
for token in @tokens
|
||||
if index < firstNonWhitespaceIndex
|
||||
token.firstNonWhitespaceIndex = Math.min(index + token.value.length, firstNonWhitespaceIndex - index)
|
||||
if index < @firstNonWhitespaceIndex
|
||||
token.firstNonWhitespaceIndex = Math.min(index + token.value.length, @firstNonWhitespaceIndex - index)
|
||||
# Only the *last* segment of a soft-wrapped line can have trailing whitespace
|
||||
if @lineEnding? and (index + token.value.length > firstTrailingWhitespaceIndex)
|
||||
token.firstTrailingWhitespaceIndex = Math.max(0, firstTrailingWhitespaceIndex - index)
|
||||
|
||||
Reference in New Issue
Block a user