Comparar commits
355 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 79c6badce8 | |||
| a48ef934eb | |||
| 85d5968318 | |||
| 9b4dd602be | |||
| 62d84e5d4b | |||
| 61ed5da1dc | |||
| 32e25d4bb2 | |||
| aae9614839 | |||
| 7fa4121227 | |||
| 1d783826a2 | |||
| bdb6e193de | |||
| 3f75512de2 | |||
| 5910b05344 | |||
| 7f039b3383 | |||
| ca35ced587 | |||
| 734ef19f48 | |||
| ef9ce1bf70 | |||
| c754b73b71 | |||
| 21565332a4 | |||
| 8871d9cd2d | |||
| 64f0fcc839 | |||
| 581d12b04f | |||
| 05a9ace3e6 | |||
| 03eac362f6 | |||
| 8a05b0f51d | |||
| 4069d23d86 | |||
| 78b48345ac | |||
| 139e2f6de0 | |||
| ed86b4a478 | |||
| f2352131cc | |||
| 56df435fb8 | |||
| 595ff19b5b | |||
| 33eb0bae8f | |||
| fde1560377 | |||
| a640d07599 | |||
| 45b65cd3aa | |||
| f217278001 | |||
| 3320176a0a | |||
| 754b5a6004 | |||
| 79b84b2433 | |||
| 17be036ff8 | |||
| 23deec833f | |||
| 6a8d0bef4a | |||
| d5ce1a0312 | |||
| 74decbd18a | |||
| 085806f97f | |||
| ca8be83903 | |||
| da713da311 | |||
| 7a6c75a83e | |||
| 3e7a517c25 | |||
| e623ef4232 | |||
| 18399aa264 | |||
| 2a5f393712 | |||
| 27f779ec03 | |||
| 5d717eb7bd | |||
| 0b457fd80a | |||
| dd9aa2d02f | |||
| 87b530140b | |||
| 2f46fee1ca | |||
| fbb48e7807 | |||
| 01c141eec6 | |||
| 7d9d0c715c | |||
| a9887b5007 | |||
| c4dec72dcd | |||
| d093d5cc06 | |||
| 27c9e54538 | |||
| 3bbe6ee98c | |||
| 524d8e8e21 | |||
| c31211dc21 | |||
| 6c1b63d352 | |||
| 6fa7da79eb | |||
| c2371f3054 | |||
| 2349627e3c | |||
| 90d92a4c92 | |||
| 66171e0301 | |||
| cdc7f70b22 | |||
| e225dbe93d | |||
| 7dc18765ad | |||
| c1d379fd6c | |||
| a754ac4da0 | |||
| 21560df2f0 | |||
| f0aa408b70 | |||
| 161c9a62b5 | |||
| 2c5bbcbc22 | |||
| eee72f7664 | |||
| 073d398e6f | |||
| 2310e263a7 | |||
| de7b212d99 | |||
| 75873ef6b3 | |||
| 73855a49fc | |||
| cae055fd3f | |||
| 2aad31c4dc | |||
| 93052ad611 | |||
| 67733b8b05 | |||
| 21543569ef | |||
| 7371ebbf20 | |||
| 73470cc294 | |||
| 1e60b5fa3b | |||
| 172ecbd897 | |||
| 289cc24b56 | |||
| a20483ccdb | |||
| b2ceaf3b8b | |||
| 1c3c508985 | |||
| 645f4ad907 | |||
| 05dd6f8f17 | |||
| b19390b519 | |||
| a3f339e0c3 | |||
| 42040e14b3 | |||
| 91640f0886 | |||
| 0377d64788 | |||
| cd37caae96 | |||
| aab63c26e7 | |||
| 6da6101a52 | |||
| 87b33648dc | |||
| d0b380e535 | |||
| 99480901e2 | |||
| 6852720408 | |||
| f9498732a5 | |||
| e4aa82fda1 | |||
| bc1a743b2f | |||
| 3fe22aa5c8 | |||
| fe035d4d7c | |||
| e8bfb7ca09 | |||
| 4bfd48b983 | |||
| 5a1fadf7ce | |||
| 819ac9ea68 | |||
| 6384841134 | |||
| a0fbec29c3 | |||
| 238fca2004 | |||
| 014beda455 | |||
| 777df644ce | |||
| f3ea3a3395 | |||
| b82fdace61 | |||
| 7195102a04 | |||
| 5ec6a4a189 | |||
| e330b1a2e8 | |||
| 5334433bc2 | |||
| 366a12903a | |||
| 063cb04fb5 | |||
| d9c2f07fbe | |||
| 5c1fa8e53d | |||
| a1f3540cb4 | |||
| 2eeb399cf1 | |||
| 71e8e865f2 | |||
| 9f080be6e1 | |||
| 56f66f8578 | |||
| 0b1dc704ea | |||
| 578d823118 | |||
| 0196f2a2eb | |||
| 1e68a7266f | |||
| 093143f7a9 | |||
| 4eeef9cfbd | |||
| ce3ec75c55 | |||
| bb09de9703 | |||
| e64ba18fe3 | |||
| 3908f81fc6 | |||
| fac46a295c | |||
| b01470a738 | |||
| f3be613662 | |||
| ede29d99c1 | |||
| d2369e94c8 | |||
| dbe3399016 | |||
| 3952423d99 | |||
| ffdcecc0f2 | |||
| 0069eb4d0d | |||
| 5fa55026d5 | |||
| 6d04d57e74 | |||
| 3f0dca5a40 | |||
| 8b14a66e2c | |||
| 1607411df1 | |||
| dade9f6309 | |||
| 568aa1d396 | |||
| 9febe179fa | |||
| c9e68ab044 | |||
| 285186567a | |||
| 1c136f16e3 | |||
| 534a2d4565 | |||
| 9e814de969 | |||
| 7202ba274a | |||
| 46e85fac87 | |||
| d1f1b494cf | |||
| f11803df60 | |||
| f094a86ae7 | |||
| a6c791ce39 | |||
| dfa870f514 | |||
| a98377b899 | |||
| c3de3d8eea | |||
| 2d15f5e49a | |||
| 56386cb06a | |||
| 986a7ad5c3 | |||
| 9a01b5a6bf | |||
| ccafda6f7f | |||
| 33538a5ed7 | |||
| aae85cd7c1 | |||
| ce098e587f | |||
| 233d819e04 | |||
| fbbf3d177a | |||
| c33bd34996 | |||
| 34cdb23d71 | |||
| fcedcd117d | |||
| 3d7de21d6c | |||
| 2278ee742a | |||
| 55e90f8ae1 | |||
| 2ca738453b | |||
| 31a9bb83cf | |||
| 1e4504e7f3 | |||
| bf05ddb958 | |||
| 756c2be64a | |||
| 6fdd4f775b | |||
| 625fcaffc8 | |||
| 955d379e0e | |||
| 0d71f20073 | |||
| 42c40e8c7a | |||
| 89212e599f | |||
| 95e4ac903c | |||
| 311155ac0d | |||
| aaa82e23da | |||
| 8e46bc5241 | |||
| 37a5a6f501 | |||
| 83f14c137c | |||
| b0b458b1f6 | |||
| f4de124aa6 | |||
| 4b0eaf05a5 | |||
| 03e8bc6f19 | |||
| 13186fcf7a | |||
| fea0f1f90a | |||
| b449bb4444 | |||
| fe6b40fc5d | |||
| 82e3935ae3 | |||
| 32a3b6302c | |||
| 6157fcaf73 | |||
| ab74d8be38 | |||
| 886a2aa867 | |||
| aeaa76a9e1 | |||
| 6a7bcb6f52 | |||
| ee1ec4670d | |||
| 7e0af4c575 | |||
| f55a200591 | |||
| 89d8eac091 | |||
| 5011b6e78f | |||
| d6e67c5b32 | |||
| de547e20c2 | |||
| 2b79b19330 | |||
| 2b234545b5 | |||
| a66543048b | |||
| ca96aa2804 | |||
| 316571308a | |||
| b323d9ce18 | |||
| 0e1c757cd0 | |||
| 084bbb1578 | |||
| 7c348ee478 | |||
| a0c6a94409 | |||
| 80cdf61fa4 | |||
| 29c3fadb6f | |||
| 1ae3806c69 | |||
| 98b509441c | |||
| 02f40688e2 | |||
| cb8e378af6 | |||
| babc4732b8 | |||
| dcccde8f3f | |||
| 8ed4923e58 | |||
| 529c829438 | |||
| 809a02ca10 | |||
| b9902cb6f2 | |||
| de4d3dbbe9 | |||
| 3fe88c4df1 | |||
| 20811a9f52 | |||
| b137f1a3e3 | |||
| 0b12f01206 | |||
| 1d7b4c5f9a | |||
| e2d4b58d5f | |||
| 1c8df2c0b5 | |||
| 9067c65a41 | |||
| 1d4f2fba8b | |||
| 12dd412439 | |||
| 19d680544b | |||
| a45dd3fe37 | |||
| f6c8a435ae | |||
| 93bfe0edf6 | |||
| d3fed57cb3 | |||
| 8372adb38a | |||
| e4b3d3a83c | |||
| 11f1ef9d8b | |||
| 7d87ae00ff | |||
| 3ec2378242 | |||
| 28943a35da | |||
| 7b43c8a860 | |||
| 8b17b7eca9 | |||
| 6432cda691 | |||
| cf0bdb9c94 | |||
| 34f1472653 | |||
| a475e27cd4 | |||
| abc1f23516 | |||
| dc7e7f9ed0 | |||
| 5fdec4dc7b | |||
| 618d281d6c | |||
| 055ec8cb9c | |||
| df3fe90c89 | |||
| 21e0e95a7a | |||
| 6caed6e918 | |||
| 7dd84636ba | |||
| b12954760d | |||
| 4bb21fd9ec | |||
| 11787e5a5d | |||
| 276e63611a | |||
| 957374eb40 | |||
| fe9f1373c1 | |||
| 6290c19264 | |||
| 913bb82d6e | |||
| ffc936ca4d | |||
| 1808e5f991 | |||
| 62feefd28d | |||
| ada992be4d | |||
| f8933cfeab | |||
| 0878d7ab6a | |||
| bd8e19bce7 | |||
| 4852ba6d95 | |||
| caffcafe2e | |||
| c7a1205ca6 | |||
| 2c4f94c319 | |||
| 941fc97e79 | |||
| 8788b2a51c | |||
| ca8ae9ad61 | |||
| 2fb00af255 | |||
| 94a8d16664 | |||
| fc0a46d6b2 | |||
| fd443a8b68 | |||
| c43f277c5b | |||
| dd0938dca6 | |||
| e90f19da97 | |||
| c3aea1d149 | |||
| 569c3116a8 | |||
| 8bdc1d2418 | |||
| 6a1e83205f | |||
| 33891b51f2 | |||
| 1ef821f4e7 | |||
| ed030a54c3 | |||
| 6bb3a69410 | |||
| 53f5e9fbc6 | |||
| 1dac1f375c | |||
| cfab5c619d | |||
| b6afc415f8 | |||
| 5454e93168 | |||
| 389b2bd8d6 | |||
| 8ea011597c | |||
| 21060ae85a | |||
| f67e9b6e03 | |||
| 64f2cdb795 | |||
| a996597d49 | |||
| 52680bd63f | |||
| 8f9f5ed0ed | |||
| d71e58ec33 | |||
| 8c8f1bc048 | |||
| 94bc4ce737 | |||
| 9914085ead |
@@ -8,6 +8,10 @@ _ = require 'underscore-plus'
|
||||
packageJson = require './package.json'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
if not grunt.option('verbose')
|
||||
grunt.log.writeln = (args...) -> grunt.log
|
||||
grunt.log.write = (args...) -> grunt.log
|
||||
|
||||
[major, minor, patch] = packageJson.version.split('.')
|
||||
if process.platform is 'win32'
|
||||
appName = 'Atom'
|
||||
|
||||
@@ -73,8 +73,8 @@ window.clickEvent = (properties={}) ->
|
||||
|
||||
window.mouseEvent = (type, properties) ->
|
||||
if properties.point
|
||||
{point, editor} = properties
|
||||
{top, left} = @pagePixelPositionForPoint(editor, point)
|
||||
{point, editorView} = properties
|
||||
{top, left} = @pagePixelPositionForPoint(editorView, point)
|
||||
properties.pageX = left + 1
|
||||
properties.pageY = top + 1
|
||||
properties.originalEvent ?= {detail: 1}
|
||||
@@ -86,14 +86,14 @@ window.mousedownEvent = (properties={}) ->
|
||||
window.mousemoveEvent = (properties={}) ->
|
||||
window.mouseEvent('mousemove', properties)
|
||||
|
||||
window.pagePixelPositionForPoint = (editor, point) ->
|
||||
window.pagePixelPositionForPoint = (editorView, point) ->
|
||||
point = Point.fromObject point
|
||||
top = editor.lines.offset().top + point.row * editor.lineHeight
|
||||
left = editor.lines.offset().left + point.column * editor.charWidth - editor.lines.scrollLeft()
|
||||
top = editorView.lines.offset().top + point.row * editorView.lineHeight
|
||||
left = editorView.lines.offset().left + point.column * editorView.charWidth - editorView.lines.scrollLeft()
|
||||
{ top, left }
|
||||
|
||||
window.setEditorWidthInChars = (editor, widthInChars, charWidth=editor.charWidth) ->
|
||||
editor.width(charWidth * widthInChars + editor.lines.position().left)
|
||||
window.seteditorViewWidthInChars = (editorView, widthInChars, charWidth=editorView.charWidth) ->
|
||||
editorView.width(charWidth * widthInChars + editorView.lines.position().left)
|
||||
|
||||
$.fn.resultOfTrigger = (type) ->
|
||||
event = $.Event(type)
|
||||
|
||||
@@ -2,8 +2,8 @@ require './benchmark-helper'
|
||||
{$, _, RootView} = require 'atom'
|
||||
TokenizedBuffer = require '../src/tokenized-buffer'
|
||||
|
||||
describe "editor.", ->
|
||||
editor = null
|
||||
describe "editorView.", ->
|
||||
editorView = null
|
||||
|
||||
beforeEach ->
|
||||
window.rootViewParentSelector = '#jasmine-content'
|
||||
@@ -12,19 +12,19 @@ describe "editor.", ->
|
||||
|
||||
rootView.width(1024)
|
||||
rootView.height(768)
|
||||
rootView.openSync() # open blank editor
|
||||
editor = rootView.getActiveView()
|
||||
rootView.openSync()
|
||||
editorView = rootView.getActiveView()
|
||||
|
||||
afterEach ->
|
||||
if editor.pendingDisplayUpdate
|
||||
if editorView.pendingDisplayUpdate
|
||||
waitsFor "editor to finish rendering", (done) ->
|
||||
editor.on 'editor:display-updated', done
|
||||
editorView.on 'editor:display-updated', done
|
||||
|
||||
describe "keymap.", ->
|
||||
event = null
|
||||
|
||||
beforeEach ->
|
||||
event = keydownEvent('x', target: editor.hiddenInput[0])
|
||||
event = keydownEvent('x', target: editorView.hiddenInput[0])
|
||||
|
||||
benchmark "keydown-event-with-no-binding", 10, ->
|
||||
keymap.handleKeyEvent(event)
|
||||
@@ -35,8 +35,8 @@ describe "editor.", ->
|
||||
|
||||
describe "empty-file.", ->
|
||||
benchmark "insert-delete", ->
|
||||
editor.insertText('x')
|
||||
editor.backspace()
|
||||
editorView.insertText('x')
|
||||
editorView.backspace()
|
||||
|
||||
describe "300-line-file.", ->
|
||||
beforeEach ->
|
||||
@@ -44,81 +44,81 @@ describe "editor.", ->
|
||||
|
||||
describe "at-begining.", ->
|
||||
benchmark "insert-delete", ->
|
||||
editor.insertText('x')
|
||||
editor.backspace()
|
||||
editorView.insertText('x')
|
||||
editorView.backspace()
|
||||
|
||||
benchmark "insert-delete-rehighlight", ->
|
||||
editor.insertText('"')
|
||||
editor.backspace()
|
||||
editorView.insertText('"')
|
||||
editorView.backspace()
|
||||
|
||||
describe "at-end.", ->
|
||||
beforeEach ->
|
||||
editor.moveCursorToBottom()
|
||||
editorView.moveCursorToBottom()
|
||||
|
||||
benchmark "insert-delete", ->
|
||||
editor.insertText('"')
|
||||
editor.backspace()
|
||||
editorView.insertText('"')
|
||||
editorView.backspace()
|
||||
|
||||
describe "empty-vs-set-innerHTML.", ->
|
||||
[firstRow, lastRow] = []
|
||||
beforeEach ->
|
||||
firstRow = editor.getFirstVisibleScreenRow()
|
||||
lastRow = editor.getLastVisibleScreenRow()
|
||||
firstRow = editorView.getFirstVisibleScreenRow()
|
||||
lastRow = editorView.getLastVisibleScreenRow()
|
||||
|
||||
benchmark "build-gutter-html.", 1000, ->
|
||||
editor.gutter.renderLineNumbers(null, firstRow, lastRow)
|
||||
editorView.gutter.renderLineNumbers(null, firstRow, lastRow)
|
||||
|
||||
benchmark "set-innerHTML.", 1000, ->
|
||||
editor.gutter.renderLineNumbers(null, firstRow, lastRow)
|
||||
editor.gutter.lineNumbers[0].innerHtml = ''
|
||||
editorView.gutter.renderLineNumbers(null, firstRow, lastRow)
|
||||
editorView.gutter.lineNumbers[0].innerHtml = ''
|
||||
|
||||
benchmark "empty.", 1000, ->
|
||||
editor.gutter.renderLineNumbers(null, firstRow, lastRow)
|
||||
editor.gutter.lineNumbers.empty()
|
||||
editorView.gutter.renderLineNumbers(null, firstRow, lastRow)
|
||||
editorView.gutter.lineNumbers.empty()
|
||||
|
||||
describe "positionLeftForLineAndColumn.", ->
|
||||
line = null
|
||||
beforeEach ->
|
||||
editor.scrollTop(2000)
|
||||
editor.resetDisplay()
|
||||
line = editor.lineElementForScreenRow(106)[0]
|
||||
editorView.scrollTop(2000)
|
||||
editorView.resetDisplay()
|
||||
line = editorView.lineElementForScreenRow(106)[0]
|
||||
|
||||
describe "one-line.", ->
|
||||
beforeEach ->
|
||||
editor.clearCharacterWidthCache()
|
||||
editorView.clearCharacterWidthCache()
|
||||
|
||||
benchmark "uncached", 5000, ->
|
||||
editor.positionLeftForLineAndColumn(line, 106, 82)
|
||||
editor.clearCharacterWidthCache()
|
||||
editorView.positionLeftForLineAndColumn(line, 106, 82)
|
||||
editorView.clearCharacterWidthCache()
|
||||
|
||||
benchmark "cached", 5000, ->
|
||||
editor.positionLeftForLineAndColumn(line, 106, 82)
|
||||
editorView.positionLeftForLineAndColumn(line, 106, 82)
|
||||
|
||||
describe "multiple-lines.", ->
|
||||
[firstRow, lastRow] = []
|
||||
beforeEach ->
|
||||
firstRow = editor.getFirstVisibleScreenRow()
|
||||
lastRow = editor.getLastVisibleScreenRow()
|
||||
firstRow = editorView.getFirstVisibleScreenRow()
|
||||
lastRow = editorView.getLastVisibleScreenRow()
|
||||
|
||||
benchmark "cache-entire-visible-area", 100, ->
|
||||
for i in [firstRow..lastRow]
|
||||
line = editor.lineElementForScreenRow(i)[0]
|
||||
editor.positionLeftForLineAndColumn(line, i, Math.max(0, editor.lineLengthForBufferRow(i)))
|
||||
line = editorView.lineElementForScreenRow(i)[0]
|
||||
editorView.positionLeftForLineAndColumn(line, i, Math.max(0, editorView.lineLengthForBufferRow(i)))
|
||||
|
||||
describe "text-rendering.", ->
|
||||
beforeEach ->
|
||||
editor.scrollTop(2000)
|
||||
editorView.scrollTop(2000)
|
||||
|
||||
benchmark "resetDisplay", 50, ->
|
||||
editor.resetDisplay()
|
||||
editorView.resetDisplay()
|
||||
|
||||
benchmark "htmlForScreenRows", 1000, ->
|
||||
lastRow = editor.getLastScreenRow()
|
||||
editor.htmlForScreenRows(0, lastRow)
|
||||
lastRow = editorView.getLastScreenRow()
|
||||
editorView.htmlForScreenRows(0, lastRow)
|
||||
|
||||
benchmark "htmlForScreenRows.htmlParsing", 50, ->
|
||||
lastRow = editor.getLastScreenRow()
|
||||
html = editor.htmlForScreenRows(0, lastRow)
|
||||
lastRow = editorView.getLastScreenRow()
|
||||
html = editorView.htmlForScreenRows(0, lastRow)
|
||||
|
||||
div = document.createElement('div')
|
||||
div.innerHTML = html
|
||||
@@ -126,44 +126,44 @@ describe "editor.", ->
|
||||
describe "gutter-api.", ->
|
||||
describe "getLineNumberElementsForClass.", ->
|
||||
beforeEach ->
|
||||
editor.gutter.addClassToLine(20, 'omgwow')
|
||||
editor.gutter.addClassToLine(40, 'omgwow')
|
||||
editorView.gutter.addClassToLine(20, 'omgwow')
|
||||
editorView.gutter.addClassToLine(40, 'omgwow')
|
||||
|
||||
benchmark "DOM", 20000, ->
|
||||
editor.gutter.getLineNumberElementsForClass('omgwow')
|
||||
editorView.gutter.getLineNumberElementsForClass('omgwow')
|
||||
|
||||
benchmark "getLineNumberElement.DOM", 20000, ->
|
||||
editor.gutter.getLineNumberElement(12)
|
||||
editorView.gutter.getLineNumberElement(12)
|
||||
|
||||
benchmark "toggle-class", 2000, ->
|
||||
editor.gutter.addClassToLine(40, 'omgwow')
|
||||
editor.gutter.removeClassFromLine(40, 'omgwow')
|
||||
editorView.gutter.addClassToLine(40, 'omgwow')
|
||||
editorView.gutter.removeClassFromLine(40, 'omgwow')
|
||||
|
||||
describe "find-then-unset.", ->
|
||||
classes = ['one', 'two', 'three', 'four']
|
||||
|
||||
benchmark "single-class", 200, ->
|
||||
editor.gutter.addClassToLine(30, 'omgwow')
|
||||
editor.gutter.addClassToLine(40, 'omgwow')
|
||||
editor.gutter.removeClassFromAllLines('omgwow')
|
||||
editorView.gutter.addClassToLine(30, 'omgwow')
|
||||
editorView.gutter.addClassToLine(40, 'omgwow')
|
||||
editorView.gutter.removeClassFromAllLines('omgwow')
|
||||
|
||||
benchmark "multiple-class", 200, ->
|
||||
editor.gutter.addClassToLine(30, 'one')
|
||||
editor.gutter.addClassToLine(30, 'two')
|
||||
editorView.gutter.addClassToLine(30, 'one')
|
||||
editorView.gutter.addClassToLine(30, 'two')
|
||||
|
||||
editor.gutter.addClassToLine(40, 'two')
|
||||
editor.gutter.addClassToLine(40, 'three')
|
||||
editor.gutter.addClassToLine(40, 'four')
|
||||
editorView.gutter.addClassToLine(40, 'two')
|
||||
editorView.gutter.addClassToLine(40, 'three')
|
||||
editorView.gutter.addClassToLine(40, 'four')
|
||||
|
||||
for klass in classes
|
||||
editor.gutter.removeClassFromAllLines(klass)
|
||||
editorView.gutter.removeClassFromAllLines(klass)
|
||||
|
||||
describe "line-htmlification.", ->
|
||||
div = null
|
||||
html = null
|
||||
beforeEach ->
|
||||
lastRow = editor.getLastScreenRow()
|
||||
html = editor.htmlForScreenRows(0, lastRow)
|
||||
lastRow = editorView.getLastScreenRow()
|
||||
html = editorView.htmlForScreenRows(0, lastRow)
|
||||
div = document.createElement('div')
|
||||
|
||||
benchmark "setInnerHTML", 1, ->
|
||||
@@ -178,40 +178,40 @@ describe "editor.", ->
|
||||
rootView.openSync('huge.js')
|
||||
|
||||
benchmark "moving-to-eof.", 1, ->
|
||||
editor.moveCursorToBottom()
|
||||
editorView.moveCursorToBottom()
|
||||
|
||||
describe "on-first-line.", ->
|
||||
benchmark "inserting-newline", 5, ->
|
||||
editor.insertNewline()
|
||||
editorView.insertNewline()
|
||||
|
||||
describe "on-last-visible-line.", ->
|
||||
beforeEach ->
|
||||
editor.setCursorScreenPosition([editor.getLastVisibleScreenRow(), 0])
|
||||
editorView.setCursorScreenPosition([editorView.getLastVisibleScreenRow(), 0])
|
||||
|
||||
benchmark "move-down-and-scroll", 300, ->
|
||||
editor.trigger 'move-down'
|
||||
editorView.trigger 'move-down'
|
||||
|
||||
describe "at-eof.", ->
|
||||
endPosition = null
|
||||
|
||||
beforeEach ->
|
||||
editor.moveCursorToBottom()
|
||||
endPosition = editor.getCursorScreenPosition()
|
||||
editorView.moveCursorToBottom()
|
||||
endPosition = editorView.getCursorScreenPosition()
|
||||
|
||||
benchmark "move-to-beginning-of-word", ->
|
||||
editor.moveCursorToBeginningOfWord()
|
||||
editor.setCursorScreenPosition(endPosition)
|
||||
editorView.moveCursorToBeginningOfWord()
|
||||
editorView.setCursorScreenPosition(endPosition)
|
||||
|
||||
benchmark "insert", ->
|
||||
editor.insertText('x')
|
||||
editorView.insertText('x')
|
||||
|
||||
describe "TokenizedBuffer.", ->
|
||||
describe "coffee-script-grammar.", ->
|
||||
[languageMode, buffer] = []
|
||||
|
||||
beforeEach ->
|
||||
editSession = benchmarkFixturesProject.openSync('medium.coffee')
|
||||
{ languageMode, buffer } = editSession
|
||||
editor = benchmarkFixturesProject.openSync('medium.coffee')
|
||||
{ languageMode, buffer } = editor
|
||||
|
||||
benchmark "construction", 20, ->
|
||||
new TokenizedBuffer(buffer, { languageMode, tabLength: 2})
|
||||
|
||||
@@ -245,7 +245,7 @@ $('ol.entries li.file.status-modified span.name').each (i, el) ->
|
||||
parents.each (i, el) ->
|
||||
filePath.unshift($(el).find('div.header span.name').eq(0).text())
|
||||
|
||||
modifiedFilePath = path.join(project.rootDirectory.path, filePath.join(path.sep))
|
||||
modifiedFilePath = path.join(atom.project.rootDirectory.path, filePath.join(path.sep))
|
||||
modifiedFiles.push modifiedFilePath
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{Document, Point, Range, Site} = require 'telepath'
|
||||
{Document, Point, Range} = require 'telepath'
|
||||
|
||||
module.exports =
|
||||
_: require 'underscore-plus'
|
||||
@@ -11,7 +11,6 @@ module.exports =
|
||||
Git: require '../src/git'
|
||||
Point: Point
|
||||
Range: Range
|
||||
Site: Site
|
||||
|
||||
# The following classes can't be used from a Task handler and should therefore
|
||||
# only be exported when not running as a child node process
|
||||
@@ -21,8 +20,7 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
module.exports.$ = $
|
||||
module.exports.$$ = $$
|
||||
module.exports.$$$ = $$$
|
||||
module.exports.Editor = require '../src/editor'
|
||||
module.exports.pathForRepositoryUrl = require('../src/project').pathForRepositoryUrl
|
||||
module.exports.Editor = require '../src/editor-view'
|
||||
module.exports.RootView = require '../src/root-view'
|
||||
module.exports.SelectList = require '../src/select-list'
|
||||
module.exports.ScrollView = require '../src/scroll-view'
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
'.editor':
|
||||
# Platform Bindings
|
||||
'alt-left': 'editor:move-to-previous-word-boundary'
|
||||
'alt-right': 'editor:move-to-next-word-boundary'
|
||||
'alt-shift-left': 'editor:select-to-previous-word-boundary'
|
||||
'alt-shift-right': 'editor:select-to-next-word-boundary'
|
||||
'home': 'editor:move-to-first-character-of-line'
|
||||
'end': 'editor:move-to-end-of-line'
|
||||
'shift-home': 'editor:select-to-first-character-of-line'
|
||||
'shift-end': 'editor:select-to-end-of-line'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-t': 'editor:transpose'
|
||||
|
||||
'.editor:not(.mini)':
|
||||
# Atom Specific
|
||||
'ctrl-C': 'editor:copy-path'
|
||||
|
||||
# Sublime Parity
|
||||
'tab': 'editor:indent'
|
||||
'enter': 'editor:newline'
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'ctrl-K': 'editor:delete-line'
|
||||
'ctrl-shift-up': 'editor:add-selection-above'
|
||||
'ctrl-shift-down': 'editor:add-selection-below'
|
||||
|
||||
'.tool-panel':
|
||||
'escape': 'core:close'
|
||||
|
||||
'.tool-panel.panel-left, .tool-panel.panel-right':
|
||||
'escape': 'tool-panel:unfocus'
|
||||
|
||||
'.editor !important, .editor.mini !important':
|
||||
'escape': 'editor:consolidate-selections'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'input:not(.hidden-input), .native-key-bindings':
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
'left': 'native!'
|
||||
'right': 'native!'
|
||||
'shift-left': 'native!'
|
||||
'shift-right': 'native!'
|
||||
'backspace': 'native!'
|
||||
'shift-backspace': 'native!'
|
||||
'delete': 'native!'
|
||||
'ctrl-b': 'native!'
|
||||
'ctrl-f': 'native!'
|
||||
'ctrl-F': 'native!'
|
||||
'ctrl-B': 'native!'
|
||||
'ctrl-h': 'native!'
|
||||
'ctrl-d': 'native!'
|
||||
@@ -0,0 +1,154 @@
|
||||
'.platform-darwin':
|
||||
# Apple specific
|
||||
'cmd-q': 'application:quit'
|
||||
'cmd-h': 'application:hide'
|
||||
'cmd-H': 'application:hide-other-applications'
|
||||
'cmd-m': 'application:minimize'
|
||||
'alt-cmd-ctrl-m': 'application:zoom'
|
||||
|
||||
'ctrl-p': 'core:move-up'
|
||||
'ctrl-n': 'core:move-down'
|
||||
'ctrl-b': 'core:move-left'
|
||||
'ctrl-f': 'core:move-right'
|
||||
'ctrl-P': 'core:select-up'
|
||||
'ctrl-N': 'core:select-down'
|
||||
'ctrl-F': 'core:select-right'
|
||||
'ctrl-B': 'core:select-left'
|
||||
'ctrl-h': 'core:backspace'
|
||||
'ctrl-d': 'core:delete'
|
||||
|
||||
# Atom Specific
|
||||
'cmd-O': 'application:open-dev'
|
||||
'cmd-alt-ctrl-s': 'application:run-all-specs'
|
||||
'enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
'left': 'core:move-left'
|
||||
'right': 'core:move-right'
|
||||
'ctrl-alt-cmd-r': 'window:reload'
|
||||
'alt-cmd-i': 'window:toggle-dev-tools'
|
||||
'cmd-alt-ctrl-p': 'window:run-package-specs'
|
||||
|
||||
# Sublime Parity
|
||||
'cmd-,': 'application:show-settings'
|
||||
'cmd-N': 'application:new-window'
|
||||
'cmd-W': 'window:close'
|
||||
'cmd-o': 'application:open'
|
||||
'cmd-T': 'pane:reopen-closed-item'
|
||||
'cmd-n': 'application:new-file'
|
||||
'cmd-s': 'core:save'
|
||||
'cmd-S': 'core:save-as'
|
||||
'cmd-alt-s': 'window:save-all'
|
||||
'cmd-w': 'core:close'
|
||||
'cmd-ctrl-f': 'window:toggle-full-screen'
|
||||
'cmd-z': 'core:undo'
|
||||
'cmd-Z': 'core:redo'
|
||||
'cmd-y': 'core:redo'
|
||||
'cmd-x': 'core:cut'
|
||||
'cmd-c': 'core:copy'
|
||||
'cmd-v': 'core:paste'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'cmd-up': 'core:move-to-top'
|
||||
'cmd-down': 'core:move-to-bottom'
|
||||
'cmd-shift-up': 'core:select-to-top'
|
||||
'cmd-shift-down': 'core:select-to-bottom'
|
||||
'cmd-{': 'pane:show-previous-item'
|
||||
'cmd-}': 'pane:show-next-item'
|
||||
'cmd-alt-left': 'pane:show-previous-item'
|
||||
'cmd-alt-right': 'pane:show-next-item'
|
||||
'cmd-=': 'window:increase-font-size'
|
||||
'cmd-+': 'window:increase-font-size'
|
||||
'cmd--': 'window:decrease-font-size'
|
||||
|
||||
'cmd-k up': 'pane:split-up' # Atom Specific
|
||||
'cmd-k down': 'pane:split-down' # Atom Specific
|
||||
'cmd-k left': 'pane:split-left' # Atom Specific
|
||||
'cmd-k right': 'pane:split-right' # Atom Specific
|
||||
'cmd-k cmd-w': 'pane:close' # Atom Specific
|
||||
'cmd-k alt-cmd-w': 'pane:close-other-items' # Atom Specific
|
||||
'cmd-k cmd-left': 'window:focus-previous-pane'
|
||||
'cmd-k cmd-right': 'window:focus-next-pane'
|
||||
'cmd-1': 'pane:show-item-1'
|
||||
'cmd-2': 'pane:show-item-2'
|
||||
'cmd-3': 'pane:show-item-3'
|
||||
'cmd-4': 'pane:show-item-4'
|
||||
'cmd-5': 'pane:show-item-5'
|
||||
'cmd-6': 'pane:show-item-6'
|
||||
'cmd-7': 'pane:show-item-7'
|
||||
'cmd-8': 'pane:show-item-8'
|
||||
'cmd-9': 'pane:show-item-9'
|
||||
|
||||
'.platform-darwin .editor':
|
||||
# Apple Specific
|
||||
'cmd-backspace': 'editor:backspace-to-beginning-of-line'
|
||||
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
||||
'ctrl-A': 'editor:select-to-first-character-of-line'
|
||||
'ctrl-E': 'editor:select-to-end-of-line'
|
||||
'cmd-left': 'editor:move-to-first-character-of-line'
|
||||
'cmd-right': 'editor:move-to-end-of-line'
|
||||
'cmd-shift-left': 'editor:select-to-first-character-of-line'
|
||||
'cmd-shift-right': 'editor:select-to-end-of-line'
|
||||
'alt-backspace': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-delete': 'editor:delete-to-end-of-word'
|
||||
'ctrl-a': 'editor:move-to-first-character-of-line'
|
||||
'ctrl-e': 'editor:move-to-end-of-line'
|
||||
'ctrl-k': 'editor:cut-to-end-of-line'
|
||||
|
||||
# Atom Specific
|
||||
'ctrl-W': 'editor:select-word'
|
||||
|
||||
# Sublime Parity
|
||||
'cmd-a': 'core:select-all'
|
||||
'cmd-alt-p': 'editor:log-cursor-scope'
|
||||
'cmd-k cmd-u': 'editor:upper-case'
|
||||
'cmd-k cmd-l': 'editor:lower-case'
|
||||
|
||||
'body.platform-darwin .editor:not(.mini)':
|
||||
# Atom specific
|
||||
'alt-cmd-z': 'editor:checkout-head-revision'
|
||||
'cmd-<': 'editor:scroll-to-cursor'
|
||||
'alt-cmd-ctrl-f': 'editor:fold-selection'
|
||||
'cmd-=': 'editor:auto-indent'
|
||||
|
||||
# Sublime Parity
|
||||
'cmd-enter': 'editor:newline-below'
|
||||
'cmd-shift-enter': 'editor:newline-above'
|
||||
'cmd-]': 'editor:indent-selected-rows'
|
||||
'cmd-[': 'editor:outdent-selected-rows'
|
||||
'ctrl-cmd-up': 'editor:move-line-up'
|
||||
'ctrl-cmd-down': 'editor:move-line-down'
|
||||
'cmd-/': 'editor:toggle-line-comments'
|
||||
'cmd-j': 'editor:join-line'
|
||||
'cmd-D': 'editor:duplicate-line'
|
||||
|
||||
'cmd-alt-[': 'editor:fold-current-row'
|
||||
'cmd-alt-]': 'editor:unfold-current-row'
|
||||
'cmd-alt-{': 'editor:fold-all' # Atom Specific
|
||||
'cmd-alt-}': 'editor:unfold-all' # Atom Specific
|
||||
'cmd-k cmd-0': 'editor:unfold-all'
|
||||
'cmd-k cmd-1': 'editor:fold-at-indent-level-1'
|
||||
'cmd-k cmd-2': 'editor:fold-at-indent-level-2'
|
||||
'cmd-k cmd-3': 'editor:fold-at-indent-level-3'
|
||||
'cmd-k cmd-4': 'editor:fold-at-indent-level-4'
|
||||
'cmd-k cmd-5': 'editor:fold-at-indent-level-5'
|
||||
'cmd-k cmd-6': 'editor:fold-at-indent-level-6'
|
||||
'cmd-k cmd-7': 'editor:fold-at-indent-level-7'
|
||||
'cmd-k cmd-8': 'editor:fold-at-indent-level-8'
|
||||
'cmd-k cmd-9': 'editor:fold-at-indent-level-9'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'body.platform-darwin input:not(.hidden-input), body.platform-darwin .native-key-bindings':
|
||||
'cmd-z': 'native!'
|
||||
'cmd-Z': 'native!'
|
||||
'cmd-x': 'native!'
|
||||
'cmd-c': 'native!'
|
||||
'cmd-v': 'native!'
|
||||
@@ -1,194 +0,0 @@
|
||||
'body':
|
||||
# Apple specific
|
||||
'meta-q': 'application:quit'
|
||||
'meta-h': 'application:hide'
|
||||
'meta-H': 'application:hide-other-applications'
|
||||
'meta-m': 'application:minimize'
|
||||
'alt-meta-ctrl-m': 'application:zoom'
|
||||
|
||||
'ctrl-p': 'core:move-up'
|
||||
'ctrl-n': 'core:move-down'
|
||||
'ctrl-b': 'core:move-left'
|
||||
'ctrl-f': 'core:move-right'
|
||||
'ctrl-P': 'core:select-up'
|
||||
'ctrl-N': 'core:select-down'
|
||||
'ctrl-F': 'core:select-right'
|
||||
'ctrl-B': 'core:select-left'
|
||||
'ctrl-h': 'core:backspace'
|
||||
'ctrl-d': 'core:delete'
|
||||
|
||||
# Atom Specific
|
||||
'meta-O': 'application:open-dev'
|
||||
'meta-alt-ctrl-s': 'application:run-all-specs'
|
||||
'enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
'left': 'core:move-left'
|
||||
'right': 'core:move-right'
|
||||
'ctrl-alt-meta-r': 'window:reload'
|
||||
'alt-meta-i': 'window:toggle-dev-tools'
|
||||
'meta-alt-ctrl-p': 'window:run-package-specs'
|
||||
|
||||
# Sublime Parity
|
||||
'meta-,': 'application:show-settings'
|
||||
'meta-N': 'application:new-window'
|
||||
'meta-W': 'window:close'
|
||||
'meta-o': 'application:open'
|
||||
'meta-T': 'pane:reopen-closed-item'
|
||||
'meta-n': 'application:new-file'
|
||||
'meta-s': 'core:save'
|
||||
'meta-S': 'core:save-as'
|
||||
'meta-alt-s': 'window:save-all'
|
||||
'meta-w': 'core:close'
|
||||
'meta-ctrl-f': 'window:toggle-full-screen'
|
||||
'meta-z': 'core:undo'
|
||||
'meta-Z': 'core:redo'
|
||||
'meta-y': 'core:redo'
|
||||
'meta-x': 'core:cut'
|
||||
'meta-c': 'core:copy'
|
||||
'meta-v': 'core:paste'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'meta-up': 'core:move-to-top'
|
||||
'meta-down': 'core:move-to-bottom'
|
||||
'meta-shift-up': 'core:select-to-top'
|
||||
'meta-shift-down': 'core:select-to-bottom'
|
||||
'meta-{': 'pane:show-previous-item'
|
||||
'meta-}': 'pane:show-next-item'
|
||||
'meta-alt-left': 'pane:show-previous-item'
|
||||
'meta-alt-right': 'pane:show-next-item'
|
||||
'meta-=': 'window:increase-font-size'
|
||||
'meta-+': 'window:increase-font-size'
|
||||
'meta--': 'window:decrease-font-size'
|
||||
|
||||
'meta-k up': 'pane:split-up' # Atom Specific
|
||||
'meta-k down': 'pane:split-down' # Atom Specific
|
||||
'meta-k left': 'pane:split-left' # Atom Specific
|
||||
'meta-k right': 'pane:split-right' # Atom Specific
|
||||
'meta-k meta-w': 'pane:close' # Atom Specific
|
||||
'meta-k alt-meta-w': 'pane:close-other-items' # Atom Specific
|
||||
'meta-k meta-left': 'window:focus-previous-pane'
|
||||
'meta-k meta-right': 'window:focus-next-pane'
|
||||
'meta-1': 'pane:show-item-1'
|
||||
'meta-2': 'pane:show-item-2'
|
||||
'meta-3': 'pane:show-item-3'
|
||||
'meta-4': 'pane:show-item-4'
|
||||
'meta-5': 'pane:show-item-5'
|
||||
'meta-6': 'pane:show-item-6'
|
||||
'meta-7': 'pane:show-item-7'
|
||||
'meta-8': 'pane:show-item-8'
|
||||
'meta-9': 'pane:show-item-9'
|
||||
|
||||
'.editor':
|
||||
# Apple Specific
|
||||
'alt-left': 'editor:move-to-previous-word-boundary'
|
||||
'alt-right': 'editor:move-to-next-word-boundary'
|
||||
'alt-shift-left': 'editor:select-to-previous-word-boundary'
|
||||
'alt-shift-right': 'editor:select-to-next-word-boundary'
|
||||
'meta-backspace': 'editor:backspace-to-beginning-of-line'
|
||||
'meta-delete': 'editor:backspace-to-beginning-of-line'
|
||||
'ctrl-A': 'editor:select-to-first-character-of-line'
|
||||
'ctrl-E': 'editor:select-to-end-of-line'
|
||||
'meta-left': 'editor:move-to-first-character-of-line'
|
||||
'meta-right': 'editor:move-to-end-of-line'
|
||||
'meta-shift-left': 'editor:select-to-first-character-of-line'
|
||||
'meta-shift-right': 'editor:select-to-end-of-line'
|
||||
'home': 'editor:move-to-first-character-of-line'
|
||||
'end': 'editor:move-to-end-of-line'
|
||||
'shift-home': 'editor:select-to-first-character-of-line'
|
||||
'shift-end': 'editor:select-to-end-of-line'
|
||||
'alt-backspace': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-delete': 'editor:delete-to-end-of-word'
|
||||
'ctrl-a': 'editor:move-to-first-character-of-line'
|
||||
'ctrl-e': 'editor:move-to-end-of-line'
|
||||
'ctrl-k': 'editor:cut-to-end-of-line'
|
||||
|
||||
# Atom Specific
|
||||
'ctrl-W': 'editor:select-word'
|
||||
|
||||
# Sublime Parity
|
||||
'meta-a': 'core:select-all'
|
||||
'meta-alt-p': 'editor:log-cursor-scope'
|
||||
'ctrl-t': 'editor:transpose'
|
||||
'meta-k meta-u': 'editor:upper-case'
|
||||
'meta-k meta-l': 'editor:lower-case'
|
||||
|
||||
'.editor:not(.mini)':
|
||||
# Atom Specific
|
||||
'alt-meta-z': 'editor:checkout-head-revision'
|
||||
'meta-<': 'editor:scroll-to-cursor'
|
||||
'ctrl-C': 'editor:copy-path'
|
||||
'alt-meta-ctrl-f': 'editor:fold-selection'
|
||||
'meta-=': 'editor:auto-indent'
|
||||
|
||||
# Sublime Parity
|
||||
'tab': 'editor:indent'
|
||||
'enter': 'editor:newline'
|
||||
'meta-enter': 'editor:newline-below'
|
||||
'meta-shift-enter': 'editor:newline-above'
|
||||
'meta-]': 'editor:indent-selected-rows'
|
||||
'meta-[': 'editor:outdent-selected-rows'
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'ctrl-meta-up': 'editor:move-line-up'
|
||||
'ctrl-meta-down': 'editor:move-line-down'
|
||||
'meta-/': 'editor:toggle-line-comments'
|
||||
'meta-j': 'editor:join-line'
|
||||
'meta-D': 'editor:duplicate-line'
|
||||
'ctrl-K': 'editor:delete-line'
|
||||
'ctrl-shift-up': 'editor:add-selection-above'
|
||||
'ctrl-shift-down': 'editor:add-selection-below'
|
||||
|
||||
'meta-alt-[': 'editor:fold-current-row'
|
||||
'meta-alt-]': 'editor:unfold-current-row'
|
||||
'meta-alt-{': 'editor:fold-all' # Atom Specific
|
||||
'meta-alt-}': 'editor:unfold-all' # Atom Specific
|
||||
'meta-k meta-0': 'editor:unfold-all'
|
||||
'meta-k meta-1': 'editor:fold-at-indent-level-1'
|
||||
'meta-k meta-2': 'editor:fold-at-indent-level-2'
|
||||
'meta-k meta-3': 'editor:fold-at-indent-level-3'
|
||||
'meta-k meta-4': 'editor:fold-at-indent-level-4'
|
||||
'meta-k meta-5': 'editor:fold-at-indent-level-5'
|
||||
'meta-k meta-6': 'editor:fold-at-indent-level-6'
|
||||
'meta-k meta-7': 'editor:fold-at-indent-level-7'
|
||||
'meta-k meta-8': 'editor:fold-at-indent-level-8'
|
||||
'meta-k meta-9': 'editor:fold-at-indent-level-9'
|
||||
|
||||
'.tool-panel':
|
||||
'escape': 'core:close'
|
||||
|
||||
'.tool-panel.panel-left, .tool-panel.panel-right':
|
||||
'escape': 'tool-panel:unfocus'
|
||||
|
||||
'.editor !important, .editor.mini !important':
|
||||
'escape': 'editor:consolidate-selections'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'input:not(.hidden-input), .native-key-bindings':
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
'left': 'native!'
|
||||
'right': 'native!'
|
||||
'shift-left': 'native!'
|
||||
'shift-right': 'native!'
|
||||
'backspace': 'native!'
|
||||
'shift-backspace': 'native!'
|
||||
'delete': 'native!'
|
||||
'meta-z': 'native!'
|
||||
'meta-Z': 'native!'
|
||||
'meta-x': 'native!'
|
||||
'meta-c': 'native!'
|
||||
'meta-v': 'native!'
|
||||
'ctrl-b': 'native!'
|
||||
'ctrl-f': 'native!'
|
||||
'ctrl-F': 'native!'
|
||||
'ctrl-B': 'native!'
|
||||
'ctrl-h': 'native!'
|
||||
'ctrl-d': 'native!'
|
||||
@@ -0,0 +1,102 @@
|
||||
'.platform-win32':
|
||||
# Atom Specific
|
||||
'enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
'left': 'core:move-left'
|
||||
'right': 'core:move-right'
|
||||
'ctrl-alt-r': 'window:reload'
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-N': 'application:new-window'
|
||||
'ctrl-W': 'window:close'
|
||||
'ctrl-o': 'application:open'
|
||||
'ctrl-T': 'pane:reopen-closed-item'
|
||||
'ctrl-n': 'application:new-file'
|
||||
'ctrl-s': 'core:save'
|
||||
'ctrl-S': 'core:save-as'
|
||||
'ctrl-w': 'core:close'
|
||||
'ctrl-z': 'core:undo'
|
||||
'ctrl-y': 'core:redo'
|
||||
'ctrl-x': 'core:cut'
|
||||
'ctrl-c': 'core:copy'
|
||||
'ctrl-v': 'core:paste'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
'ctrl-shift-down': 'core:move-down'
|
||||
'ctrl-=': 'window:increase-font-size'
|
||||
'ctrl-+': 'window:increase-font-size'
|
||||
'ctrl--': 'window:decrease-font-size'
|
||||
|
||||
'ctrl-k up': 'pane:split-up' # Atom Specific
|
||||
'ctrl-k down': 'pane:split-down' # Atom Specific
|
||||
'ctrl-k left': 'pane:split-left' # Atom Specific
|
||||
'ctrl-k right': 'pane:split-right' # Atom Specific
|
||||
'ctrl-k ctrl-w': 'pane:close' # Atom Specific
|
||||
'ctrl-k alt-ctrl-w': 'pane:close-other-items' # Atom Specific
|
||||
'ctrl-k ctrl-left': 'window:focus-previous-pane'
|
||||
'ctrl-k ctrl-right': 'window:focus-next-pane'
|
||||
|
||||
'.platform-win32 .editor':
|
||||
# Windows specific
|
||||
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-a': 'core:select-all'
|
||||
'ctrl-alt-p': 'editor:log-cursor-scope'
|
||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||
|
||||
'.platform-win32 .editor:not(.mini)':
|
||||
# Atom specific
|
||||
'alt-ctrl-z': 'editor:checkout-head-revision'
|
||||
'ctrl-<': 'editor:scroll-to-cursor'
|
||||
'alt-ctrl-f': 'editor:fold-selection'
|
||||
'ctrl-=': 'editor:auto-indent'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-enter': 'editor:newline-below'
|
||||
'ctrl-shift-enter': 'editor:newline-above'
|
||||
'ctrl-]': 'editor:indent-selected-rows'
|
||||
'ctrl-[': 'editor:outdent-selected-rows'
|
||||
'ctrl-up': 'editor:move-line-up'
|
||||
'ctrl-down': 'editor:move-line-down'
|
||||
'ctrl-/': 'editor:toggle-line-comments'
|
||||
'ctrl-j': 'editor:join-line'
|
||||
'ctrl-D': 'editor:duplicate-line'
|
||||
|
||||
'ctrl-alt-[': 'editor:fold-current-row'
|
||||
'ctrl-alt-]': 'editor:unfold-current-row'
|
||||
'ctrl-alt-{': 'editor:fold-all' # Atom Specific
|
||||
'ctrl-alt-}': 'editor:unfold-all' # Atom Specific
|
||||
'ctrl-k ctrl-0': 'editor:unfold-all'
|
||||
'ctrl-k ctrl-1': 'editor:fold-at-indent-level-1'
|
||||
'ctrl-k ctrl-2': 'editor:fold-at-indent-level-2'
|
||||
'ctrl-k ctrl-3': 'editor:fold-at-indent-level-3'
|
||||
'ctrl-k ctrl-4': 'editor:fold-at-indent-level-4'
|
||||
'ctrl-k ctrl-5': 'editor:fold-at-indent-level-5'
|
||||
'ctrl-k ctrl-6': 'editor:fold-at-indent-level-6'
|
||||
'ctrl-k ctrl-7': 'editor:fold-at-indent-level-7'
|
||||
'ctrl-k ctrl-8': 'editor:fold-at-indent-level-8'
|
||||
'ctrl-k ctrl-9': 'editor:fold-at-indent-level-9'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'.platform-win32 input:not(.hidden-input), .platform-win32 .native-key-bindings':
|
||||
'ctrl-z': 'native!'
|
||||
'ctrl-Z': 'native!'
|
||||
'ctrl-x': 'native!'
|
||||
'ctrl-c': 'native!'
|
||||
'ctrl-v': 'native!'
|
||||
@@ -0,0 +1,172 @@
|
||||
'menu': [
|
||||
{
|
||||
label: '&File'
|
||||
submenu: [
|
||||
{ label: 'New &Window', command: 'application:new-window' }
|
||||
{ label: '&New File', command: 'application:new-file' }
|
||||
{ label: '&Open...', command: 'application:open' }
|
||||
{ label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Preferences...', command: 'application:show-settings' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Save', command: 'core:save' }
|
||||
{ label: 'Save &As...', command: 'core:save-as' }
|
||||
{ label: 'Save A&ll', command: 'window:save-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Close Buffer', command: 'core:close' }
|
||||
{ label: 'Close All &Buffers', command: 'pane:close' }
|
||||
{ label: 'Clos&e Window', command: 'window:close' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'E&xit', command: 'application:quit' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Edit'
|
||||
submenu: [
|
||||
{ label: '&Undo', command: 'core:undo' }
|
||||
{ label: '&Redo', command: 'core:redo' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Cut', command: 'core:cut' }
|
||||
{ label: 'C&opy', command: 'core:copy' }
|
||||
{ label: 'Copy Pat&h', command: 'editor:copy-path' }
|
||||
{ label: '&Paste', command: 'core:paste' }
|
||||
{ label: 'Select &All', command: 'core:select-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Toggle Comments', command: 'editor:toggle-line-comments' }
|
||||
{
|
||||
label: 'Lines',
|
||||
submenu: [
|
||||
{ label: '&Indent', command: 'editor:indent-selected-rows' }
|
||||
{ label: '&Outdent', command: 'editor:outdent-selected-rows' }
|
||||
{ label: '&Auto Indent', command: 'editor:auto-indent' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Move Line &Up', command: 'editor:move-line-up' }
|
||||
{ label: 'Move Line &Down', command: 'editor:move-line-down' }
|
||||
{ label: 'Du&plicate Line', command: 'editor:duplicate-line' }
|
||||
{ label: 'D&elete Line', command: 'editor:delete-line' }
|
||||
{ label: '&Join Lines', command: 'editor:join-line' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Text',
|
||||
submenu: [
|
||||
{ label: '&Upper Case', command: 'editor:upper-case' }
|
||||
{ label: '&Lower Case', command: 'editor:lower-case' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Delete to End of &Word', command: 'editor:delete-to-end-of-word' }
|
||||
{ label: '&Delete Line', command: 'editor:delete-line' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Transpose', command: 'editor:transpose' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Folding',
|
||||
submenu: [
|
||||
{ label: '&Fold', command: 'editor:fold-current-row' }
|
||||
{ label: '&Unfold', command: 'editor:unfold-current-row' }
|
||||
{ label: 'Unfold &All', command: 'editor:unfold-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Fol&d All', command: 'editor:fold-all' }
|
||||
{ label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' }
|
||||
{ label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' }
|
||||
{ label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' }
|
||||
{ label: 'Fold Level 4', command: 'editor:fold-at-indent-level-4' }
|
||||
{ label: 'Fold Level 5', command: 'editor:fold-at-indent-level-5' }
|
||||
{ label: 'Fold Level 6', command: 'editor:fold-at-indent-level-6' }
|
||||
{ label: 'Fold Level 7', command: 'editor:fold-at-indent-level-7' }
|
||||
{ label: 'Fold Level 8', command: 'editor:fold-at-indent-level-8' }
|
||||
{ label: 'Fold Level 9', command: 'editor:fold-at-indent-level-9' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&View'
|
||||
submenu: [
|
||||
{ label: '&Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' }
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ label: 'Open In &Dev Mode...', command: 'application:open-dev' }
|
||||
{ label: 'Run &Atom Specs', command: 'application:run-all-specs' }
|
||||
{ label: 'Run Package &Specs', command: 'window:run-package-specs' }
|
||||
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Selection'
|
||||
submenu: [
|
||||
{ label: 'Add Selection &Above', command: 'editor:add-selection-above' }
|
||||
{ label: 'Add Selection &Below', command: 'editor:add-selection-below' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select to &Top', command: 'core:select-to-top' }
|
||||
{ label: 'Select to Botto&m', command: 'core:select-to-bottom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select &Line', command: 'editor:select-line' }
|
||||
{ label: 'Select &Word', command: 'editor:select-word' }
|
||||
{ label: 'Select to Beginning of W&ord', command: 'editor:select-to-beginning-of-word' }
|
||||
{ label: 'Select to Beginning of L&ine', command: 'editor:select-to-beginning-of-line' }
|
||||
{ label: 'Select to First &Character of Line', command: 'editor:select-to-first-character-of-line' }
|
||||
{ label: 'Select to End of Wor&d', command: 'editor:select-to-end-of-word' }
|
||||
{ label: 'Select to End of Lin&e', command: 'editor:select-to-end-of-line' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Movement'
|
||||
submenu: [
|
||||
{ label: 'Move to &Top', command: 'core:move-to-top' }
|
||||
{ label: 'Move to &Bottom', command: 'core:move-to-bottom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Move to Beginning of &Line', command: 'editor:move-to-beginning-of-line' }
|
||||
{ label: 'Move to &First Character of Line', command: 'editor:move-to-first-character-of-line' }
|
||||
{ label: 'Move to &End of Line', command: 'editor:move-to-end-of-line' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Move to Beginning of &Word', command: 'editor:move-to-beginning-of-word' }
|
||||
{ label: 'Move to End of Wor&d', command: 'editor:move-to-end-of-word' }
|
||||
{ label: 'Move to &Next Word', command: 'editor:move-to-next-word-boundary' }
|
||||
{ label: 'Move to &Previous Word', command: 'editor:move-to-previous-word-boundary' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'F&ind'
|
||||
submenu: []
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Packages'
|
||||
submenu: []
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Window'
|
||||
submenu: [
|
||||
{ label: 'Mi&nimize', command: 'application:minimize' }
|
||||
{ label: 'Ma&ximize', command: 'application:zoom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Bring &All to Front', command: 'application:bring-all-windows-to-front' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
{ label: '&About Atom...', command: 'application:about' }
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ label: "Install &update", command: 'application:install-update', visible: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Report an &Issue', command: 'application:report-issue' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
]
|
||||
+50
-50
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"version": "36.0.0",
|
||||
"version": "39.0.0",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -9,14 +9,14 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"atomShellVersion": "0.6.10",
|
||||
"atomShellVersion": "0.6.11",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"bootstrap": "git://github.com/twbs/bootstrap.git#v3.0.0",
|
||||
"clear-cut": "0.1.0",
|
||||
"bootstrap": "git://github.com/benogle/bootstrap.git",
|
||||
"clear-cut": "0.2.0",
|
||||
"coffee-script": "1.6.3",
|
||||
"coffeestack": "0.6.0",
|
||||
"emissary": "0.9.0",
|
||||
"emissary": "0.19.0",
|
||||
"first-mate": "0.5.0",
|
||||
"fs-plus": "0.9.0",
|
||||
"fuzzaldrin": "0.1.0",
|
||||
@@ -28,14 +28,14 @@
|
||||
"nslog": "0.1.0",
|
||||
"oniguruma": "0.24.0",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "0.9.0",
|
||||
"pathwatcher": "0.10.0",
|
||||
"pegjs": "0.7.0",
|
||||
"q": "0.9.7",
|
||||
"scandal": "0.8.0",
|
||||
"season": "0.14.0",
|
||||
"semver": "1.1.4",
|
||||
"space-pen": "2.0.0",
|
||||
"telepath": "0.23.0",
|
||||
"telepath": "0.45.0",
|
||||
"temp": "0.5.0",
|
||||
"underscore-plus": "0.3.0"
|
||||
},
|
||||
@@ -52,7 +52,6 @@
|
||||
"grunt-contrib-coffee": "~0.7.0",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"walkdir": "0.0.7",
|
||||
"ws": "0.4.27",
|
||||
"js-yaml": "~2.1.0",
|
||||
"grunt-markdown": "~0.4.0",
|
||||
"json-front-matter": "~0.1.3",
|
||||
@@ -65,55 +64,56 @@
|
||||
"rimraf": "~2.2.2"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-light-ui": "0.6.0",
|
||||
"atom-light-ui": "0.8.0",
|
||||
"atom-light-syntax": "0.6.0",
|
||||
"atom-dark-ui": "0.6.0",
|
||||
"atom-dark-ui": "0.8.0",
|
||||
"atom-dark-syntax": "0.6.0",
|
||||
"base16-tomorrow-dark-theme": "0.6.0",
|
||||
"solarized-dark-syntax": "0.4.0",
|
||||
"archive-view": "0.11.0",
|
||||
"autocomplete": "0.12.0",
|
||||
"autoflow": "0.5.0",
|
||||
"autosave": "0.6.0",
|
||||
"bookmarks": "0.10.0",
|
||||
"bracket-matcher": "0.11.0",
|
||||
"command-logger": "0.6.0",
|
||||
"command-palette": "0.7.0",
|
||||
"dev-live-reload": "0.15.0",
|
||||
"editor-stats": "0.5.0",
|
||||
"exception-reporting": "0.7.0",
|
||||
"find-and-replace": "0.40.0",
|
||||
"fuzzy-finder": "0.20.0",
|
||||
"gists": "0.6.0",
|
||||
"git-diff": "0.13.0",
|
||||
"github-sign-in": "0.9.0",
|
||||
"go-to-line": "0.8.0",
|
||||
"grammar-selector": "0.8.0",
|
||||
"image-view": "0.7.0",
|
||||
"link": "0.7.0",
|
||||
"markdown-preview": "0.15.0",
|
||||
"metrics": "0.11.0",
|
||||
"package-generator": "0.19.0",
|
||||
"release-notes": "0.11.0",
|
||||
"settings-view": "0.39.0",
|
||||
"snippets": "0.13.0",
|
||||
"spell-check": "0.13.0",
|
||||
"status-bar": "0.16.0",
|
||||
"styleguide": "0.9.0",
|
||||
"symbols-view": "0.19.0",
|
||||
"tabs": "0.8.0",
|
||||
"terminal": "0.16.0",
|
||||
"timecop": "0.9.0",
|
||||
"to-the-hubs": "0.9.0",
|
||||
"tree-view": "0.30.0",
|
||||
"visual-bell": "0.3.0",
|
||||
"whitespace": "0.8.0",
|
||||
"wrap-guide": "0.5.0",
|
||||
"archive-view": "0.14.0",
|
||||
"autocomplete": "0.15.0",
|
||||
"autoflow": "0.9.0",
|
||||
"autosave": "0.7.0",
|
||||
"bookmarks": "0.13.0",
|
||||
"bracket-matcher": "0.12.0",
|
||||
"command-logger": "0.7.0",
|
||||
"command-palette": "0.10.0",
|
||||
"dev-live-reload": "0.17.0",
|
||||
"editor-stats": "0.7.0",
|
||||
"exception-reporting": "0.8.0",
|
||||
"find-and-replace": "0.49.0",
|
||||
"fuzzy-finder": "0.25.0",
|
||||
"gists": "0.11.0",
|
||||
"git-diff": "0.16.0",
|
||||
"github-sign-in": "0.11.0",
|
||||
"go-to-line": "0.10.0",
|
||||
"grammar-selector": "0.11.0",
|
||||
"image-view": "0.9.0",
|
||||
"keybinding-resolver": "0.5.0",
|
||||
"link": "0.9.0",
|
||||
"markdown-preview": "0.19.0",
|
||||
"metrics": "0.12.0",
|
||||
"package-generator": "0.21.0",
|
||||
"release-notes": "0.12.0",
|
||||
"settings-view": "0.47.0",
|
||||
"snippets": "0.15.0",
|
||||
"spell-check": "0.15.0",
|
||||
"status-bar": "0.22.0",
|
||||
"styleguide": "0.15.0",
|
||||
"symbols-view": "0.24.0",
|
||||
"tabs": "0.12.0",
|
||||
"terminal": "0.22.0",
|
||||
"timecop": "0.10.0",
|
||||
"to-the-hubs": "0.13.0",
|
||||
"tree-view": "0.39.0",
|
||||
"visual-bell": "0.4.0",
|
||||
"whitespace": "0.9.0",
|
||||
"wrap-guide": "0.6.0",
|
||||
"language-c": "0.2.0",
|
||||
"language-clojure": "0.1.0",
|
||||
"language-coffee-script": "0.3.0",
|
||||
"language-css": "0.2.0",
|
||||
"language-gfm": "0.8.0",
|
||||
"language-gfm": "0.9.0",
|
||||
"language-git": "0.3.0",
|
||||
"language-go": "0.2.0",
|
||||
"language-html": "0.2.0",
|
||||
@@ -139,7 +139,7 @@
|
||||
"language-sql": "0.2.0",
|
||||
"language-text": "0.2.0",
|
||||
"language-todo": "0.2.0",
|
||||
"language-toml": "0.6.0",
|
||||
"language-toml": "0.7.0",
|
||||
"language-xml": "0.2.0",
|
||||
"language-yaml": "0.1.0"
|
||||
},
|
||||
|
||||
+11
-5
@@ -5,9 +5,15 @@ var path = require('path');
|
||||
// Executes an array of commands one by one.
|
||||
function executeCommands(commands, done, index) {
|
||||
index = (index == undefined ? 0 : index);
|
||||
if (index < commands.length)
|
||||
safeExec(commands[index], executeCommands.bind(this, commands, done, index + 1));
|
||||
else
|
||||
if (index < commands.length) {
|
||||
var command = commands[index];
|
||||
var options = null;
|
||||
if (typeof command !== 'string') {
|
||||
options = command.options;
|
||||
command = command.command;
|
||||
}
|
||||
safeExec(command, options, executeCommands.bind(this, commands, done, index + 1));
|
||||
} else
|
||||
done(null);
|
||||
}
|
||||
|
||||
@@ -21,8 +27,8 @@ var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo';
|
||||
var commands = [
|
||||
'git submodule --quiet sync',
|
||||
'git submodule --quiet update --recursive --init',
|
||||
joinCommands('cd vendor/apm', 'npm install --silent .'),
|
||||
'npm install --silent vendor/apm',
|
||||
{command: joinCommands('cd vendor/apm', 'npm install --silent .'), options: {ignoreStdout: true}},
|
||||
{command: 'npm install --silent vendor/apm', options: {ignoreStdout: true}},
|
||||
echoNewLine,
|
||||
'node node_modules/atom-package-manager/bin/apm clean',
|
||||
'node node_modules/atom-package-manager/bin/apm install --silent',
|
||||
|
||||
@@ -10,7 +10,7 @@ exports.safeExec = function(command, options, callback) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
// This needed to be increase for `apm test` runs that generate tons of failures
|
||||
// This needed to be increased for `apm test` runs that generate many failures
|
||||
// The default is 200KB.
|
||||
options.maxBuffer = 1024 * 1024;
|
||||
|
||||
@@ -21,7 +21,8 @@ exports.safeExec = function(command, options, callback) {
|
||||
callback(null);
|
||||
});
|
||||
child.stderr.pipe(process.stderr);
|
||||
child.stdout.pipe(process.stdout);
|
||||
if (!options.ignoreStdout)
|
||||
child.stdout.pipe(process.stdout);
|
||||
}
|
||||
|
||||
// Same with safeExec but call child_process.spawn instead.
|
||||
|
||||
@@ -15,14 +15,14 @@ describe "AtomPackage", ->
|
||||
describe "when the theme contains a single style file", ->
|
||||
it "loads and applies css", ->
|
||||
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
|
||||
themePath = project.resolve('packages/theme-with-index-css')
|
||||
themePath = atom.project.resolve('packages/theme-with-index-css')
|
||||
theme = Package.load(themePath)
|
||||
theme.activate()
|
||||
expect($(".editor").css("padding-top")).toBe "1234px"
|
||||
|
||||
it "parses, loads and applies less", ->
|
||||
expect($(".editor").css("padding-bottom")).not.toBe "1234px"
|
||||
themePath = project.resolve('packages/theme-with-index-less')
|
||||
themePath = atom.project.resolve('packages/theme-with-index-less')
|
||||
theme = Package.load(themePath)
|
||||
theme.activate()
|
||||
expect($(".editor").css("padding-top")).toBe "4321px"
|
||||
@@ -33,7 +33,7 @@ describe "AtomPackage", ->
|
||||
expect($(".editor").css("padding-right")).not.toBe("102px")
|
||||
expect($(".editor").css("padding-bottom")).not.toBe("103px")
|
||||
|
||||
themePath = project.resolve('packages/theme-with-package-file')
|
||||
themePath = atom.project.resolve('packages/theme-with-package-file')
|
||||
theme = Package.load(themePath)
|
||||
theme.activate()
|
||||
expect($(".editor").css("padding-top")).toBe("101px")
|
||||
@@ -46,7 +46,7 @@ describe "AtomPackage", ->
|
||||
expect($(".editor").css("padding-right")).not.toBe "20px"
|
||||
expect($(".editor").css("padding-bottom")).not.toBe "30px"
|
||||
|
||||
themePath = project.resolve('packages/theme-without-package-file')
|
||||
themePath = atom.project.resolve('packages/theme-without-package-file')
|
||||
theme = Package.load(themePath)
|
||||
theme.activate()
|
||||
expect($(".editor").css("padding-top")).toBe "10px"
|
||||
@@ -55,7 +55,7 @@ describe "AtomPackage", ->
|
||||
|
||||
describe "reloading a theme", ->
|
||||
beforeEach ->
|
||||
themePath = project.resolve('packages/theme-with-package-file')
|
||||
themePath = atom.project.resolve('packages/theme-with-package-file')
|
||||
theme = Package.load(themePath)
|
||||
theme.activate()
|
||||
|
||||
@@ -66,7 +66,7 @@ describe "AtomPackage", ->
|
||||
|
||||
describe "events", ->
|
||||
beforeEach ->
|
||||
themePath = project.resolve('packages/theme-with-package-file')
|
||||
themePath = atom.project.resolve('packages/theme-with-package-file')
|
||||
theme = Package.load(themePath)
|
||||
theme.activate()
|
||||
|
||||
|
||||
+83
-82
@@ -5,16 +5,16 @@ ThemeManager = require '../src/theme-manager'
|
||||
|
||||
describe "the `atom` global", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
atom.rootView = new RootView
|
||||
|
||||
describe "package lifecycle methods", ->
|
||||
describe ".loadPackage(name)", ->
|
||||
describe "when the package has deferred deserializers", ->
|
||||
it "requires the package's main module if one of its deferred deserializers is referenced", ->
|
||||
pack = atom.loadPackage('package-with-activation-events')
|
||||
pack = atom.packages.loadPackage('package-with-activation-events')
|
||||
spyOn(pack, 'activateStylesheets').andCallThrough()
|
||||
expect(pack.mainModule).toBeNull()
|
||||
object = deserialize({deserializer: 'Foo', data: 5})
|
||||
object = atom.deserializers.deserialize({deserializer: 'Foo', data: 5})
|
||||
expect(pack.mainModule).toBeDefined()
|
||||
expect(object.constructor.name).toBe 'Foo'
|
||||
expect(object.data).toBe 5
|
||||
@@ -23,34 +23,34 @@ describe "the `atom` global", ->
|
||||
it "continues if the package has an invalid package.json", ->
|
||||
spyOn(console, 'warn')
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
expect(-> atom.loadPackage("package-with-broken-package-json")).not.toThrow()
|
||||
expect(-> atom.packages.loadPackage("package-with-broken-package-json")).not.toThrow()
|
||||
|
||||
it "continues if the package has an invalid keymap", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
expect(-> atom.loadPackage("package-with-broken-keymap")).not.toThrow()
|
||||
expect(-> atom.packages.loadPackage("package-with-broken-keymap")).not.toThrow()
|
||||
|
||||
describe ".unloadPackage(name)", ->
|
||||
describe "when the package is active", ->
|
||||
it "throws an error", ->
|
||||
pack = atom.activatePackage('package-with-main')
|
||||
expect(atom.isPackageLoaded(pack.name)).toBeTruthy()
|
||||
expect(atom.isPackageActive(pack.name)).toBeTruthy()
|
||||
expect( -> atom.unloadPackage(pack.name)).toThrow()
|
||||
expect(atom.isPackageLoaded(pack.name)).toBeTruthy()
|
||||
expect(atom.isPackageActive(pack.name)).toBeTruthy()
|
||||
pack = atom.packages.activatePackage('package-with-main')
|
||||
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
|
||||
expect(atom.packages.isPackageActive(pack.name)).toBeTruthy()
|
||||
expect( -> atom.packages.unloadPackage(pack.name)).toThrow()
|
||||
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
|
||||
expect(atom.packages.isPackageActive(pack.name)).toBeTruthy()
|
||||
|
||||
describe "when the package is not loaded", ->
|
||||
it "throws an error", ->
|
||||
expect(atom.isPackageLoaded('unloaded')).toBeFalsy()
|
||||
expect( -> atom.unloadPackage('unloaded')).toThrow()
|
||||
expect(atom.isPackageLoaded('unloaded')).toBeFalsy()
|
||||
expect(atom.packages.isPackageLoaded('unloaded')).toBeFalsy()
|
||||
expect( -> atom.packages.unloadPackage('unloaded')).toThrow()
|
||||
expect(atom.packages.isPackageLoaded('unloaded')).toBeFalsy()
|
||||
|
||||
describe "when the package is loaded", ->
|
||||
it "no longers reports it as being loaded", ->
|
||||
pack = atom.loadPackage('package-with-main')
|
||||
expect(atom.isPackageLoaded(pack.name)).toBeTruthy()
|
||||
atom.unloadPackage(pack.name)
|
||||
expect(atom.isPackageLoaded(pack.name)).toBeFalsy()
|
||||
pack = atom.packages.loadPackage('package-with-main')
|
||||
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
|
||||
atom.packages.unloadPackage(pack.name)
|
||||
expect(atom.packages.isPackageLoaded(pack.name)).toBeFalsy()
|
||||
|
||||
describe ".activatePackage(id)", ->
|
||||
describe "atom packages", ->
|
||||
@@ -59,7 +59,7 @@ describe "the `atom` global", ->
|
||||
it "requires the module at the specified path", ->
|
||||
mainModule = require('./fixtures/packages/package-with-main/main-module')
|
||||
spyOn(mainModule, 'activate')
|
||||
pack = atom.activatePackage('package-with-main')
|
||||
pack = atom.packages.activatePackage('package-with-main')
|
||||
expect(mainModule.activate).toHaveBeenCalled()
|
||||
expect(pack.mainModule).toBe mainModule
|
||||
|
||||
@@ -67,13 +67,13 @@ describe "the `atom` global", ->
|
||||
it "requires index.coffee", ->
|
||||
indexModule = require('./fixtures/packages/package-with-index/index')
|
||||
spyOn(indexModule, 'activate')
|
||||
pack = atom.activatePackage('package-with-index')
|
||||
pack = atom.packages.activatePackage('package-with-index')
|
||||
expect(indexModule.activate).toHaveBeenCalled()
|
||||
expect(pack.mainModule).toBe indexModule
|
||||
|
||||
it "assigns config defaults from the module", ->
|
||||
expect(atom.config.get('package-with-config-defaults.numbers.one')).toBeUndefined()
|
||||
atom.activatePackage('package-with-config-defaults')
|
||||
atom.packages.activatePackage('package-with-config-defaults')
|
||||
expect(atom.config.get('package-with-config-defaults.numbers.one')).toBe 1
|
||||
expect(atom.config.get('package-with-config-defaults.numbers.two')).toBe 2
|
||||
|
||||
@@ -85,24 +85,24 @@ describe "the `atom` global", ->
|
||||
spyOn(mainModule, 'activate').andCallThrough()
|
||||
AtomPackage = require '../src/atom-package'
|
||||
spyOn(AtomPackage.prototype, 'requireMainModule').andCallThrough()
|
||||
pack = atom.activatePackage('package-with-activation-events')
|
||||
pack = atom.packages.activatePackage('package-with-activation-events')
|
||||
|
||||
it "defers requiring/activating the main module until an activation event bubbles to the root view", ->
|
||||
expect(pack.requireMainModule).not.toHaveBeenCalled()
|
||||
expect(mainModule.activate).not.toHaveBeenCalled()
|
||||
rootView.trigger 'activation-event'
|
||||
atom.rootView.trigger 'activation-event'
|
||||
expect(mainModule.activate).toHaveBeenCalled()
|
||||
|
||||
it "triggers the activation event on all handlers registered during activation", ->
|
||||
rootView.openSync()
|
||||
editor = rootView.getActiveView()
|
||||
atom.rootView.openSync()
|
||||
editorView = atom.rootView.getActiveView()
|
||||
eventHandler = jasmine.createSpy("activation-event")
|
||||
editor.command 'activation-event', eventHandler
|
||||
editor.trigger 'activation-event'
|
||||
editorView.command 'activation-event', eventHandler
|
||||
editorView.trigger 'activation-event'
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
expect(mainModule.activationEventCallCount).toBe 1
|
||||
expect(eventHandler.callCount).toBe 1
|
||||
editor.trigger 'activation-event'
|
||||
editorView.trigger 'activation-event'
|
||||
expect(mainModule.activationEventCallCount).toBe 2
|
||||
expect(eventHandler.callCount).toBe 2
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
@@ -111,23 +111,23 @@ describe "the `atom` global", ->
|
||||
it "does not throw an exception", ->
|
||||
spyOn(console, "error")
|
||||
spyOn(console, "warn").andCallThrough()
|
||||
expect(-> atom.activatePackage('package-without-module')).not.toThrow()
|
||||
expect(-> atom.packages.activatePackage('package-without-module')).not.toThrow()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
|
||||
it "passes the activate method the package's previously serialized state if it exists", ->
|
||||
pack = atom.activatePackage("package-with-serialization")
|
||||
pack = atom.packages.activatePackage("package-with-serialization")
|
||||
expect(pack.mainModule.someNumber).not.toBe 77
|
||||
pack.mainModule.someNumber = 77
|
||||
atom.deactivatePackage("package-with-serialization")
|
||||
atom.packages.deactivatePackage("package-with-serialization")
|
||||
spyOn(pack.mainModule, 'activate').andCallThrough()
|
||||
atom.activatePackage("package-with-serialization")
|
||||
atom.packages.activatePackage("package-with-serialization")
|
||||
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
|
||||
|
||||
it "logs warning instead of throwing an exception if the package fails to load", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
spyOn(console, "warn")
|
||||
expect(-> atom.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(-> atom.packages.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
|
||||
describe "keymap loading", ->
|
||||
@@ -137,28 +137,28 @@ describe "the `atom` global", ->
|
||||
element2 = $$ -> @div class: 'test-2'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
|
||||
atom.activatePackage("package-with-keymaps")
|
||||
atom.packages.activatePackage("package-with-keymaps")
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1"
|
||||
expect(atom.keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2"
|
||||
expect(atom.keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe "test-1"
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)[0].command).toBe "test-2"
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
|
||||
describe "when the metadata contains a 'keymaps' manifest", ->
|
||||
it "loads only the keymaps specified by the manifest, in the specified order", ->
|
||||
element1 = $$ -> @div class: 'test-1'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
|
||||
atom.activatePackage("package-with-keymaps-manifest")
|
||||
atom.packages.activatePackage("package-with-keymaps-manifest")
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1'
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2'
|
||||
expect(atom.keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe 'keymap-1'
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-n', element1)[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-y', element3)).toHaveLength 0
|
||||
|
||||
describe "menu loading", ->
|
||||
beforeEach ->
|
||||
@@ -171,7 +171,7 @@ describe "the `atom` global", ->
|
||||
|
||||
expect(atom.contextMenu.definitionsForElement(element)).toEqual []
|
||||
|
||||
atom.activatePackage("package-with-menus")
|
||||
atom.packages.activatePackage("package-with-menus")
|
||||
|
||||
expect(atom.menu.template.length).toBe 2
|
||||
expect(atom.menu.template[0].label).toBe "Second to Last"
|
||||
@@ -186,7 +186,7 @@ describe "the `atom` global", ->
|
||||
|
||||
expect(atom.contextMenu.definitionsForElement(element)).toEqual []
|
||||
|
||||
atom.activatePackage("package-with-menus-manifest")
|
||||
atom.packages.activatePackage("package-with-menus-manifest")
|
||||
|
||||
expect(atom.menu.template[0].label).toBe "Second to Last"
|
||||
expect(atom.menu.template[1].label).toBe "Last"
|
||||
@@ -209,7 +209,7 @@ describe "the `atom` global", ->
|
||||
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
|
||||
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
|
||||
|
||||
atom.activatePackage("package-with-stylesheets-manifest")
|
||||
atom.packages.activatePackage("package-with-stylesheets-manifest")
|
||||
|
||||
expect(atom.themes.stylesheetElementForId(one)).toExist()
|
||||
expect(atom.themes.stylesheetElementForId(two)).toExist()
|
||||
@@ -231,7 +231,7 @@ describe "the `atom` global", ->
|
||||
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
|
||||
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
|
||||
|
||||
atom.activatePackage("package-with-stylesheets")
|
||||
atom.packages.activatePackage("package-with-stylesheets")
|
||||
expect(atom.themes.stylesheetElementForId(one)).toExist()
|
||||
expect(atom.themes.stylesheetElementForId(two)).toExist()
|
||||
expect(atom.themes.stylesheetElementForId(three)).toExist()
|
||||
@@ -239,90 +239,91 @@ describe "the `atom` global", ->
|
||||
|
||||
describe "grammar loading", ->
|
||||
it "loads the package's grammars", ->
|
||||
atom.activatePackage('package-with-grammars')
|
||||
atom.packages.activatePackage('package-with-grammars')
|
||||
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Alot'
|
||||
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Alittle'
|
||||
|
||||
describe "scoped-property loading", ->
|
||||
it "loads the scoped properties", ->
|
||||
atom.activatePackage("package-with-scoped-properties")
|
||||
atom.packages.activatePackage("package-with-scoped-properties")
|
||||
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
|
||||
|
||||
describe "textmate packages", ->
|
||||
it "loads the package's grammars", ->
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
|
||||
it "translates the package's scoped properties to Atom terms", ->
|
||||
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBe '# '
|
||||
|
||||
describe "when the package has no grammars but does have preferences", ->
|
||||
it "loads the package's preferences as scoped properties", ->
|
||||
jasmine.unspy(window, 'setTimeout')
|
||||
spyOn(syntax, 'addProperties').andCallThrough()
|
||||
spyOn(atom.syntax, 'addProperties').andCallThrough()
|
||||
|
||||
atom.activatePackage('package-with-preferences-tmbundle')
|
||||
atom.packages.activatePackage('package-with-preferences-tmbundle')
|
||||
|
||||
waitsFor ->
|
||||
atom.syntax.addProperties.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(atom.syntax.getProperty(['.source.pref'], 'editor.increaseIndentPattern')).toBe '^abc$'
|
||||
|
||||
describe ".deactivatePackage(id)", ->
|
||||
describe "atom packages", ->
|
||||
it "calls `deactivate` on the package's main module if activate was successful", ->
|
||||
pack = atom.activatePackage("package-with-deactivate")
|
||||
expect(atom.isPackageActive("package-with-deactivate")).toBeTruthy()
|
||||
pack = atom.packages.activatePackage("package-with-deactivate")
|
||||
expect(atom.packages.isPackageActive("package-with-deactivate")).toBeTruthy()
|
||||
spyOn(pack.mainModule, 'deactivate').andCallThrough()
|
||||
|
||||
atom.deactivatePackage("package-with-deactivate")
|
||||
atom.packages.deactivatePackage("package-with-deactivate")
|
||||
expect(pack.mainModule.deactivate).toHaveBeenCalled()
|
||||
expect(atom.isPackageActive("package-with-module")).toBeFalsy()
|
||||
expect(atom.packages.isPackageActive("package-with-module")).toBeFalsy()
|
||||
|
||||
spyOn(console, 'warn')
|
||||
badPack = atom.activatePackage("package-that-throws-on-activate")
|
||||
expect(atom.isPackageActive("package-that-throws-on-activate")).toBeTruthy()
|
||||
badPack = atom.packages.activatePackage("package-that-throws-on-activate")
|
||||
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeTruthy()
|
||||
spyOn(badPack.mainModule, 'deactivate').andCallThrough()
|
||||
|
||||
atom.deactivatePackage("package-that-throws-on-activate")
|
||||
atom.packages.deactivatePackage("package-that-throws-on-activate")
|
||||
expect(badPack.mainModule.deactivate).not.toHaveBeenCalled()
|
||||
expect(atom.isPackageActive("package-that-throws-on-activate")).toBeFalsy()
|
||||
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeFalsy()
|
||||
|
||||
it "does not serialize packages that have not been activated called on their main module", ->
|
||||
spyOn(console, 'warn')
|
||||
badPack = atom.activatePackage("package-that-throws-on-activate")
|
||||
badPack = atom.packages.activatePackage("package-that-throws-on-activate")
|
||||
spyOn(badPack.mainModule, 'serialize').andCallThrough()
|
||||
|
||||
atom.deactivatePackage("package-that-throws-on-activate")
|
||||
atom.packages.deactivatePackage("package-that-throws-on-activate")
|
||||
expect(badPack.mainModule.serialize).not.toHaveBeenCalled()
|
||||
|
||||
it "absorbs exceptions that are thrown by the package module's serialize methods", ->
|
||||
spyOn(console, 'error')
|
||||
atom.activatePackage('package-with-serialize-error', immediate: true)
|
||||
atom.activatePackage('package-with-serialization', immediate: true)
|
||||
atom.deactivatePackages()
|
||||
atom.packages.activatePackage('package-with-serialize-error', immediate: true)
|
||||
atom.packages.activatePackage('package-with-serialization', immediate: true)
|
||||
atom.packages.deactivatePackages()
|
||||
expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
|
||||
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
|
||||
expect(console.error).toHaveBeenCalled()
|
||||
|
||||
it "removes the package's grammars", ->
|
||||
atom.activatePackage('package-with-grammars')
|
||||
atom.deactivatePackage('package-with-grammars')
|
||||
atom.packages.activatePackage('package-with-grammars')
|
||||
atom.packages.deactivatePackage('package-with-grammars')
|
||||
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Null Grammar'
|
||||
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Null Grammar'
|
||||
|
||||
it "removes the package's keymaps", ->
|
||||
atom.activatePackage('package-with-keymaps')
|
||||
atom.deactivatePackage('package-with-keymaps')
|
||||
expect(atom.keymap.bindingsForElement($$ -> @div class: 'test-1')['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.bindingsForElement($$ -> @div class: 'test-2')['ctrl-z']).toBeUndefined()
|
||||
atom.packages.activatePackage('package-with-keymaps')
|
||||
atom.packages.deactivatePackage('package-with-keymaps')
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
|
||||
|
||||
it "removes the package's stylesheets", ->
|
||||
atom.activatePackage('package-with-stylesheets')
|
||||
atom.deactivatePackage('package-with-stylesheets')
|
||||
atom.packages.activatePackage('package-with-stylesheets')
|
||||
atom.packages.deactivatePackage('package-with-stylesheets')
|
||||
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
|
||||
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
|
||||
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
|
||||
@@ -331,22 +332,22 @@ describe "the `atom` global", ->
|
||||
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
|
||||
|
||||
it "removes the package's scoped-properties", ->
|
||||
atom.activatePackage("package-with-scoped-properties")
|
||||
atom.packages.activatePackage("package-with-scoped-properties")
|
||||
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
|
||||
atom.deactivatePackage("package-with-scoped-properties")
|
||||
atom.packages.deactivatePackage("package-with-scoped-properties")
|
||||
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBeUndefined()
|
||||
|
||||
describe "textmate packages", ->
|
||||
it "removes the package's grammars", ->
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
atom.deactivatePackage('language-ruby')
|
||||
atom.packages.deactivatePackage('language-ruby')
|
||||
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
|
||||
|
||||
it "removes the package's scoped properties", ->
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.deactivatePackage('language-ruby')
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.deactivatePackage('language-ruby')
|
||||
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
|
||||
describe ".activate()", ->
|
||||
|
||||
@@ -112,7 +112,7 @@ describe "Config", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(nodeFs, 'writeFileSync')
|
||||
jasmine.unspy config, 'save'
|
||||
jasmine.unspy atom.config, 'save'
|
||||
|
||||
describe "when ~/.atom/config.json exists", ->
|
||||
it "writes any non-default properties to ~/.atom/config.json", ->
|
||||
@@ -158,12 +158,12 @@ describe "Config", ->
|
||||
expect(atom.config.get("foo.quux.y")).toBe 1
|
||||
|
||||
describe ".observe(keyPath)", ->
|
||||
observeHandler = null
|
||||
[observeHandler, observeSubscription] = []
|
||||
|
||||
beforeEach ->
|
||||
observeHandler = jasmine.createSpy("observeHandler")
|
||||
atom.config.set("foo.bar.baz", "value 1")
|
||||
atom.config.observe "foo.bar.baz", observeHandler
|
||||
observeSubscription = atom.config.observe "foo.bar.baz", observeHandler
|
||||
|
||||
it "fires the given callback with the current value at the keypath", ->
|
||||
expect(observeHandler).toHaveBeenCalledWith("value 1")
|
||||
@@ -192,6 +192,12 @@ describe "Config", ->
|
||||
atom.config.set("foo.bar.baz", "i'm back")
|
||||
expect(observeHandler).toHaveBeenCalledWith("i'm back", {previous: undefined})
|
||||
|
||||
it "does not fire the callback once the observe subscription is off'ed", ->
|
||||
observeHandler.reset() # clear the initial call
|
||||
observeSubscription.off()
|
||||
atom.config.set('foo.bar.baz', "value 2")
|
||||
expect(observeHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe ".initializeConfigDirectory()", ->
|
||||
beforeEach ->
|
||||
atom.config.configDirPath = dotAtomPath
|
||||
|
||||
@@ -5,8 +5,8 @@ describe "DisplayBuffer", ->
|
||||
[displayBuffer, buffer, changeHandler, tabLength] = []
|
||||
beforeEach ->
|
||||
tabLength = 2
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
buffer = project.bufferForPathSync('sample.js')
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
displayBuffer = new DisplayBuffer({buffer, tabLength})
|
||||
changeHandler = jasmine.createSpy 'changeHandler'
|
||||
displayBuffer.on 'changed', changeHandler
|
||||
@@ -20,7 +20,7 @@ describe "DisplayBuffer", ->
|
||||
displayBuffer.setTabLength(4)
|
||||
displayBuffer.setEditorWidthInChars(64)
|
||||
displayBuffer.createFold(2, 4)
|
||||
displayBuffer2 = deserialize(displayBuffer.serialize())
|
||||
displayBuffer2 = atom.deserializers.deserialize(displayBuffer.serialize())
|
||||
expect(displayBuffer2.id).toBe displayBuffer.id
|
||||
expect(displayBuffer2.buffer).toBe displayBuffer.buffer
|
||||
expect(displayBuffer2.tokenizedBuffer.buffer).toBe displayBuffer.tokenizedBuffer.buffer
|
||||
@@ -154,7 +154,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "when a newline is inserted, deleted, and re-inserted at the end of a wrapped line (regression)", ->
|
||||
it "correctly renders the original wrapped line", ->
|
||||
buffer = project.buildBufferSync(null, '')
|
||||
buffer = atom.project.buildBufferSync(null, '')
|
||||
displayBuffer = new DisplayBuffer({buffer, tabLength, editorWidthInChars: 30, softWrap: true})
|
||||
|
||||
buffer.insert([0, 0], "the quick brown fox jumps over the lazy dog.")
|
||||
@@ -206,7 +206,7 @@ describe "DisplayBuffer", ->
|
||||
beforeEach ->
|
||||
displayBuffer.destroy()
|
||||
buffer.release()
|
||||
buffer = project.bufferForPathSync('two-hundred.txt')
|
||||
buffer = atom.project.bufferForPathSync('two-hundred.txt')
|
||||
displayBuffer = new DisplayBuffer({buffer, tabLength})
|
||||
displayBuffer.on 'changed', changeHandler
|
||||
|
||||
@@ -600,7 +600,7 @@ describe "DisplayBuffer", ->
|
||||
it "unsubscribes all display buffer markers from their underlying buffer marker (regression)", ->
|
||||
marker = displayBuffer.markBufferPosition([12, 2])
|
||||
displayBuffer.destroy()
|
||||
expect(marker.bufferMarker.subscriptionCount()).toBe 0
|
||||
expect(marker.bufferMarker.getSubscriptionCount()).toBe 0
|
||||
expect( -> buffer.insert([12, 2], '\n')).not.toThrow()
|
||||
|
||||
describe "markers", ->
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+2613
-2773
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1,5 +1,5 @@
|
||||
class Foo
|
||||
registerDeserializer(this)
|
||||
atom.deserializers.add(this)
|
||||
@deserialize: ({data}) -> new Foo(data)
|
||||
constructor: (@data) ->
|
||||
|
||||
@@ -9,5 +9,5 @@ module.exports =
|
||||
|
||||
activate: ->
|
||||
@activateCallCount++
|
||||
rootView.getActiveView()?.command 'activation-event', =>
|
||||
atom.rootView.getActiveView()?.command 'activation-event', =>
|
||||
@activationEventCallCount++
|
||||
|
||||
+24
-23
@@ -182,10 +182,10 @@ describe "Git", ->
|
||||
|
||||
beforeEach ->
|
||||
repo = new Git(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
|
||||
modifiedPath = project.resolve('git/working-dir/file.txt')
|
||||
modifiedPath = atom.project.resolve('git/working-dir/file.txt')
|
||||
originalModifiedPathText = fs.readFileSync(modifiedPath, 'utf8')
|
||||
newPath = project.resolve('git/working-dir/untracked.txt')
|
||||
cleanPath = project.resolve('git/working-dir/other.txt')
|
||||
newPath = atom.project.resolve('git/working-dir/untracked.txt')
|
||||
cleanPath = atom.project.resolve('git/working-dir/other.txt')
|
||||
fs.writeFileSync(newPath, '')
|
||||
|
||||
afterEach ->
|
||||
@@ -208,44 +208,44 @@ describe "Git", ->
|
||||
expect(repo.isStatusModified(statuses[modifiedPath])).toBeTruthy()
|
||||
|
||||
describe "buffer events", ->
|
||||
[originalContent, editSession] = []
|
||||
[originalContent, editor] = []
|
||||
|
||||
beforeEach ->
|
||||
editSession = project.openSync('sample.js')
|
||||
originalContent = editSession.getText()
|
||||
editor = atom.project.openSync('sample.js')
|
||||
originalContent = editor.getText()
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(editSession.getPath(), originalContent)
|
||||
fs.writeFileSync(editor.getPath(), originalContent)
|
||||
|
||||
it "emits a status-changed event when a buffer is saved", ->
|
||||
editSession.insertNewline()
|
||||
editor.insertNewline()
|
||||
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
project.getRepo().on 'status-changed', statusHandler
|
||||
editSession.save()
|
||||
atom.project.getRepo().on 'status-changed', statusHandler
|
||||
editor.save()
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith editSession.getPath(), 256
|
||||
expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256
|
||||
|
||||
it "emits a status-changed event when a buffer is reloaded", ->
|
||||
fs.writeFileSync(editSession.getPath(), 'changed')
|
||||
fs.writeFileSync(editor.getPath(), 'changed')
|
||||
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
project.getRepo().on 'status-changed', statusHandler
|
||||
editSession.getBuffer().reload()
|
||||
atom.project.getRepo().on 'status-changed', statusHandler
|
||||
editor.getBuffer().reload()
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith editSession.getPath(), 256
|
||||
editSession.getBuffer().reload()
|
||||
expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256
|
||||
editor.getBuffer().reload()
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
it "emits a status-changed event when a buffer's path changes", ->
|
||||
fs.writeFileSync(editSession.getPath(), 'changed')
|
||||
fs.writeFileSync(editor.getPath(), 'changed')
|
||||
|
||||
statusHandler = jasmine.createSpy('statusHandler')
|
||||
project.getRepo().on 'status-changed', statusHandler
|
||||
editSession.getBuffer().trigger 'path-changed'
|
||||
atom.project.getRepo().on 'status-changed', statusHandler
|
||||
editor.getBuffer().emit 'path-changed'
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
expect(statusHandler).toHaveBeenCalledWith editSession.getPath(), 256
|
||||
editSession.getBuffer().trigger 'path-changed'
|
||||
expect(statusHandler).toHaveBeenCalledWith editor.getPath(), 256
|
||||
editor.getBuffer().emit 'path-changed'
|
||||
expect(statusHandler.callCount).toBe 1
|
||||
|
||||
describe "when a project is deserialized", ->
|
||||
@@ -256,8 +256,9 @@ describe "Git", ->
|
||||
project2?.destroy()
|
||||
|
||||
it "subscribes to all the serialized buffers in the project", ->
|
||||
project.openSync('sample.js')
|
||||
project2 = deserialize(project.serialize())
|
||||
atom.project.openSync('sample.js')
|
||||
#TODO Replace with atom.replicate().project when Atom is a telepath model
|
||||
project2 = atom.replicate().get('project')
|
||||
buffer = project2.getBuffers()[0]
|
||||
|
||||
waitsFor ->
|
||||
|
||||
+73
-109
@@ -21,25 +21,19 @@ describe "Keymap", ->
|
||||
describe ".handleKeyEvent(event)", ->
|
||||
deleteCharHandler = null
|
||||
insertCharHandler = null
|
||||
commandZHandler = null
|
||||
|
||||
beforeEach ->
|
||||
keymap.bindKeys '.command-mode', 'x': 'deleteChar'
|
||||
keymap.bindKeys '.insert-mode', 'x': 'insertChar'
|
||||
keymap.bindKeys 'name', '.command-mode', 'x': 'deleteChar'
|
||||
keymap.bindKeys 'name', '.insert-mode', 'x': 'insertChar'
|
||||
keymap.bindKeys 'name', '.command-mode', 'cmd-z': 'commandZPressed'
|
||||
|
||||
deleteCharHandler = jasmine.createSpy('deleteCharHandler')
|
||||
insertCharHandler = jasmine.createSpy('insertCharHandler')
|
||||
commandZHandler = jasmine.createSpy('commandZHandler')
|
||||
fragment.on 'deleteChar', deleteCharHandler
|
||||
fragment.on 'insertChar', insertCharHandler
|
||||
|
||||
it "adds a 'keystrokes' string to the event object", ->
|
||||
event = keydownEvent('x', altKey: true, metaKey: true)
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(event.keystrokes).toBe 'alt-meta-x'
|
||||
|
||||
event = keydownEvent(',', metaKey: true)
|
||||
event.which = 188
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(event.keystrokes).toBe 'meta-,'
|
||||
fragment.on 'commandZPressed', commandZHandler
|
||||
|
||||
describe "when no binding matches the event's keystroke", ->
|
||||
it "does not return false so the event continues to propagate", ->
|
||||
@@ -47,10 +41,11 @@ describe "Keymap", ->
|
||||
|
||||
describe "when a non-English keyboard language is used", ->
|
||||
it "uses the physical character pressed instead of the character it maps to in the current language", ->
|
||||
event = keydownEvent('U+03B6', metaKey: true) # This is the 'z' key using the Greek keyboard layout
|
||||
event.which = 122
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(event.keystrokes).toBe 'meta-z'
|
||||
event = keydownEvent('U+03B6', metaKey: true, which: 122, target: fragment[0]) # This is the 'z' key using the Greek keyboard layout
|
||||
result = keymap.handleKeyEvent(event)
|
||||
|
||||
expect(result).toBe(false)
|
||||
expect(commandZHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when at least one binding fully matches the event's keystroke", ->
|
||||
describe "when the event's target node matches a selector with a matching binding", ->
|
||||
@@ -67,9 +62,6 @@ describe "Keymap", ->
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
expect(insertCharHandler).toHaveBeenCalled()
|
||||
commandEvent = insertCharHandler.argsForCall[0][0]
|
||||
expect(commandEvent.keyEvent).toBe event
|
||||
expect(event.keystrokes).toBe 'x'
|
||||
|
||||
describe "when the event's target node *descends* from a selector with a matching binding", ->
|
||||
it "triggers the command event associated with that binding on the target node and returns false", ->
|
||||
@@ -88,7 +80,7 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event's target node descends from multiple nodes that match selectors with a binding", ->
|
||||
beforeEach ->
|
||||
keymap.bindKeys '.child-node', 'x': 'foo'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'foo'
|
||||
|
||||
it "only triggers bindings on selectors associated with the closest ancestor node", ->
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
@@ -125,10 +117,10 @@ describe "Keymap", ->
|
||||
describe "when the event bubbles to a node that matches multiple selectors", ->
|
||||
describe "when the matching selectors differ in specificity", ->
|
||||
it "triggers the binding for the most specific selector", ->
|
||||
keymap.bindKeys 'div .child-node', 'x': 'foo'
|
||||
keymap.bindKeys '.command-mode .child-node !important', 'x': 'baz'
|
||||
keymap.bindKeys '.command-mode .child-node', 'x': 'quux'
|
||||
keymap.bindKeys '.child-node', 'x': 'bar'
|
||||
keymap.bindKeys 'name', 'div .child-node', 'x': 'foo'
|
||||
keymap.bindKeys 'name', '.command-mode .child-node !important', 'x': 'baz'
|
||||
keymap.bindKeys 'name', '.command-mode .child-node', 'x': 'quux'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'bar'
|
||||
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
barHandler = jasmine.createSpy 'barHandler'
|
||||
@@ -146,8 +138,8 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the matching selectors have the same specificity", ->
|
||||
it "triggers the bindings for the most recently declared selector", ->
|
||||
keymap.bindKeys '.child-node', 'x': 'foo', 'y': 'baz'
|
||||
keymap.bindKeys '.child-node', 'x': 'bar'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'foo', 'y': 'baz'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'bar'
|
||||
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
barHandler = jasmine.createSpy 'barHandler'
|
||||
@@ -167,10 +159,11 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event's target is the document body", ->
|
||||
it "triggers the mapped event on the rootView", ->
|
||||
window.rootView = new RootView
|
||||
keymap.bindKeys 'body', 'x': 'foo'
|
||||
atom.rootView = new RootView
|
||||
atom.rootView.attachToDom()
|
||||
keymap.bindKeys 'name', 'body', 'x': 'foo'
|
||||
fooHandler = jasmine.createSpy("fooHandler")
|
||||
rootView.on 'foo', fooHandler
|
||||
atom.rootView.on 'foo', fooHandler
|
||||
|
||||
result = keymap.handleKeyEvent(keydownEvent('x', target: document.body))
|
||||
expect(result).toBe(false)
|
||||
@@ -180,7 +173,7 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event matches a 'native!' binding", ->
|
||||
it "returns true, allowing the browser's native key handling to process the event", ->
|
||||
keymap.bindKeys '.grandchild-node', 'x': 'native!'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'x': 'native!'
|
||||
nativeHandler = jasmine.createSpy("nativeHandler")
|
||||
fragment.on 'native!', nativeHandler
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment.find('.grandchild-node')[0]))).toBe true
|
||||
@@ -190,7 +183,7 @@ describe "Keymap", ->
|
||||
[quitHandler, closeOtherWindowsHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
keymap.bindKeys "*",
|
||||
keymap.bindKeys 'name', "*",
|
||||
'ctrl-x ctrl-c': 'quit'
|
||||
'ctrl-x 1': 'close-other-windows'
|
||||
|
||||
@@ -220,7 +213,7 @@ describe "Keymap", ->
|
||||
expect(closeOtherWindowsHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a second keystroke added to the first doesn't match any bindings", ->
|
||||
it "clears the queued keystrokes without triggering any events", ->
|
||||
it "clears the queued keystroke without triggering any events", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment[0], ctrlKey: true))).toBe false
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: fragment[0]))).toBe false
|
||||
expect(quitHandler).not.toHaveBeenCalled()
|
||||
@@ -230,7 +223,7 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event's target node descends from multiple nodes that match selectors with a partial binding match", ->
|
||||
it "allows any of the bindings to be triggered upon a second keystroke, favoring the most specific selector", ->
|
||||
keymap.bindKeys ".grandchild-node", 'ctrl-x ctrl-c': 'more-specific-quit'
|
||||
keymap.bindKeys 'name', ".grandchild-node", 'ctrl-x ctrl-c': 'more-specific-quit'
|
||||
grandchildNode = fragment.find('.grandchild-node')[0]
|
||||
moreSpecificQuitHandler = jasmine.createSpy('moreSpecificQuitHandler')
|
||||
fragment.on 'more-specific-quit', moreSpecificQuitHandler
|
||||
@@ -254,39 +247,17 @@ describe "Keymap", ->
|
||||
describe "when there is a complete binding with a more specific selector", ->
|
||||
it "favors the more specific complete match", ->
|
||||
|
||||
describe "when a tab keystroke does not match any bindings", ->
|
||||
it "returns false to prevent the browser from transferring focus", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('U+0009', target: fragment[0]))).toBe false
|
||||
|
||||
describe ".keystrokesByCommandForSelector(selector)", ->
|
||||
it "returns a hash of all commands and their keybindings", ->
|
||||
keymap.bindKeys 'body', 'a': 'letter'
|
||||
keymap.bindKeys '.editor', 'b': 'letter'
|
||||
keymap.bindKeys '.editor', '1': 'number'
|
||||
keymap.bindKeys '.editor', 'meta-alt-1': 'number-with-modifiers'
|
||||
|
||||
expect(keymap.keystrokesByCommandForSelector()).toEqual
|
||||
'letter': ['b', 'a']
|
||||
'number': ['1']
|
||||
'number-with-modifiers': ['alt-meta-1']
|
||||
|
||||
expect(keymap.keystrokesByCommandForSelector('.editor')).toEqual
|
||||
'letter': ['b']
|
||||
'number': ['1']
|
||||
'number-with-modifiers': ['alt-meta-1']
|
||||
|
||||
|
||||
describe ".bindKeys(selector, bindings)", ->
|
||||
describe ".bindKeys(name, selector, bindings)", ->
|
||||
it "normalizes the key patterns in the hash to put the modifiers in alphabetical order", ->
|
||||
fooHandler = jasmine.createSpy('fooHandler')
|
||||
fragment.on 'foo', fooHandler
|
||||
keymap.bindKeys '*', 'ctrl-alt-delete': 'foo'
|
||||
keymap.bindKeys 'name', '*', 'ctrl-alt-delete': 'foo'
|
||||
result = keymap.handleKeyEvent(keydownEvent('delete', ctrlKey: true, altKey: true, target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
|
||||
fooHandler.reset()
|
||||
keymap.bindKeys '*', 'ctrl-alt--': 'foo'
|
||||
keymap.bindKeys 'name', '*', 'ctrl-alt--': 'foo'
|
||||
result = keymap.handleKeyEvent(keydownEvent('-', ctrlKey: true, altKey: true, target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
@@ -299,15 +270,17 @@ describe "Keymap", ->
|
||||
'.brown':
|
||||
'ctrl-h': 'harvest'
|
||||
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual { 'ctrl-c': 'cultivate' }
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual { 'ctrl-h': 'harvest' }
|
||||
keymap.add 'medical',
|
||||
'.green':
|
||||
'ctrl-v': 'vomit'
|
||||
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'green')).toHaveLength 2
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'brown')).toHaveLength 1
|
||||
|
||||
keymap.remove('nature')
|
||||
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual {}
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual {}
|
||||
expect(keymap.bindingSetsByFirstKeystroke['ctrl-c']).toEqual []
|
||||
expect(keymap.bindingSetsByFirstKeystroke['ctrl-h']).toEqual []
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'green')).toHaveLength 1
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'brown')).toEqual []
|
||||
|
||||
describe ".keystrokeStringForEvent(event)", ->
|
||||
describe "when no modifiers are pressed", ->
|
||||
@@ -318,12 +291,12 @@ describe "Keymap", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left'))).toBe 'left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('\b'))).toBe 'backspace'
|
||||
|
||||
describe "when ctrl, alt or meta is pressed with a non-modifier key", ->
|
||||
describe "when ctrl, alt or command is pressed with a non-modifier key", ->
|
||||
it "returns a string that identifies the key pressed", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('a', altKey: true))).toBe 'alt-a'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('[', metaKey: true))).toBe 'meta-['
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('[', metaKey: true))).toBe 'cmd-['
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('*', ctrlKey: true))).toBe 'ctrl-*'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', ctrlKey: true, metaKey: true, altKey: true))).toBe 'alt-ctrl-meta-left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', ctrlKey: true, metaKey: true, altKey: true))).toBe 'alt-cmd-ctrl-left'
|
||||
|
||||
describe "when shift is pressed when a non-modifer key", ->
|
||||
it "returns a string that identifies the key pressed", ->
|
||||
@@ -332,54 +305,45 @@ describe "Keymap", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', shiftKey: true))).toBe 'shift-left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('Left', shiftKey: true))).toBe 'shift-left'
|
||||
|
||||
describe ".bindingsForElement(element)", ->
|
||||
describe ".keyBindingsMatchingElement(element)", ->
|
||||
it "returns the matching bindings for the element", ->
|
||||
keymap.bindKeys '.command-mode', 'c': 'c'
|
||||
keymap.bindKeys '.grandchild-node', 'g': 'g'
|
||||
keymap.bindKeys 'name', '.command-mode', 'c': 'c'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'g': 'g'
|
||||
|
||||
bindings = keymap.bindingsForElement(fragment.find('.grandchild-node'))
|
||||
expect(Object.keys(bindings).length).toBe 2
|
||||
expect(bindings['c']).toEqual "c"
|
||||
expect(bindings['g']).toEqual "g"
|
||||
bindings = keymap.keyBindingsMatchingElement(fragment.find('.grandchild-node'))
|
||||
expect(bindings).toHaveLength 2
|
||||
expect(bindings[0].command).toEqual "g"
|
||||
expect(bindings[1].command).toEqual "c"
|
||||
|
||||
describe "when multiple bindings match a keystroke", ->
|
||||
it "only returns bindings that match the most specific selector", ->
|
||||
keymap.bindKeys '.command-mode', 'g': 'command-mode'
|
||||
keymap.bindKeys '.command-mode .grandchild-node', 'g': 'command-and-grandchild-node'
|
||||
keymap.bindKeys '.grandchild-node', 'g': 'grandchild-node'
|
||||
keymap.bindKeys 'name', '.command-mode', 'g': 'cmd-mode'
|
||||
keymap.bindKeys 'name', '.command-mode .grandchild-node', 'g': 'cmd-and-grandchild-node'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'g': 'grandchild-node'
|
||||
|
||||
bindings = keymap.bindingsForElement(fragment.find('.grandchild-node'))
|
||||
expect(Object.keys(bindings).length).toBe 1
|
||||
expect(bindings['g']).toEqual "command-and-grandchild-node"
|
||||
bindings = keymap.keyBindingsMatchingElement(fragment.find('.grandchild-node'))
|
||||
expect(bindings).toHaveLength 3
|
||||
expect(bindings[0].command).toEqual "cmd-and-grandchild-node"
|
||||
|
||||
describe ".getAllKeyMappings", ->
|
||||
it "returns the all bindings", ->
|
||||
keymap.bindKeys path.join('~', '.atom', 'packages', 'dummy', 'keymaps', 'a.cson'), '.command-mode', 'k': 'c'
|
||||
describe ".keyBindingsForCommandMatchingElement(element)", ->
|
||||
beforeEach ->
|
||||
keymap.add 'nature',
|
||||
'.green':
|
||||
'ctrl-c': 'cultivate'
|
||||
'.green-2':
|
||||
'ctrl-o': 'cultivate'
|
||||
'.brown':
|
||||
'ctrl-h': 'harvest'
|
||||
'.blue':
|
||||
'ctrl-c': 'fly'
|
||||
|
||||
mappings = keymap.getAllKeyMappings()
|
||||
expect(mappings.length).toBe 1
|
||||
expect(mappings[0].source).toEqual 'dummy'
|
||||
expect(mappings[0].keystrokes).toEqual 'k'
|
||||
expect(mappings[0].command).toEqual 'c'
|
||||
expect(mappings[0].selector).toEqual '.command-mode'
|
||||
it "finds a keymap for an element", ->
|
||||
el = $$ -> @div class: 'green'
|
||||
bindings = keymap.keyBindingsForCommandMatchingElement('cultivate', el)
|
||||
expect(bindings).toHaveLength 1
|
||||
expect(bindings[0].keystroke).toEqual "ctrl-c"
|
||||
|
||||
describe ".determineSource", ->
|
||||
describe "for a package", ->
|
||||
it "returns '<package-name>'", ->
|
||||
expect(keymap.determineSource(path.join('~', '.atom', 'packages', 'dummy', 'keymaps', 'a.cson'))).toEqual 'dummy'
|
||||
|
||||
describe "for a linked package", ->
|
||||
it "returns '<package-name>'", ->
|
||||
expect(keymap.determineSource(path.join('Users', 'john', 'github', 'dummy', 'keymaps', 'a.cson'))).toEqual 'dummy'
|
||||
|
||||
describe "for a user defined keymap", ->
|
||||
it "returns 'User'", ->
|
||||
expect(keymap.determineSource(path.join('~', '.atom', 'keymaps', 'a.cson'))).toEqual 'User'
|
||||
|
||||
describe "for a core keymap", ->
|
||||
it "returns 'Core'", ->
|
||||
expect(keymap.determineSource(path.join('Applications', 'Atom.app', '..', 'node_modules', 'dummy', 'keymaps', 'a.cson'))).toEqual 'Core'
|
||||
|
||||
describe "for a linked core keymap", ->
|
||||
it "returns 'Core'", ->
|
||||
expect(keymap.determineSource(path.join('Users', 'john', 'github', 'atom', 'keymaps', 'a.cson'))).toEqual 'Core'
|
||||
it "no keymap an element without that map", ->
|
||||
el = $$ -> @div class: 'brown'
|
||||
bindings = keymap.keyBindingsForCommandMatchingElement('cultivate', el)
|
||||
expect(bindings).toHaveLength 0
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
describe "LanguageMode", ->
|
||||
[editSession, buffer, languageMode] = []
|
||||
[editor, buffer, languageMode] = []
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
editor.destroy()
|
||||
|
||||
describe "javascript", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
editSession = project.openSync('sample.js', autoIndent: false)
|
||||
{buffer, languageMode} = editSession
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
editor = atom.project.openSync('sample.js', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
describe ".minIndentLevelForRowRange(startRow, endRow)", ->
|
||||
it "returns the minimum indent level for the given row range", ->
|
||||
@@ -109,9 +109,9 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "coffeescript", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-coffee-script', sync: true)
|
||||
editSession = project.openSync('coffee.coffee', autoIndent: false)
|
||||
{buffer, languageMode} = editSession
|
||||
atom.packages.activatePackage('language-coffee-script', sync: true)
|
||||
editor = atom.project.openSync('coffee.coffee', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
describe ".toggleLineCommentsForBufferRows(start, end)", ->
|
||||
it "comments/uncomments lines in the given range", ->
|
||||
@@ -156,9 +156,9 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "css", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-css', sync: true)
|
||||
editSession = project.openSync('css.css', autoIndent: false)
|
||||
{buffer, languageMode} = editSession
|
||||
atom.packages.activatePackage('language-css', sync: true)
|
||||
editor = atom.project.openSync('css.css', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
describe ".toggleLineCommentsForBufferRows(start, end)", ->
|
||||
it "comments/uncomments lines in the given range", ->
|
||||
@@ -197,10 +197,10 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "less", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-less', sync: true)
|
||||
atom.activatePackage('language-css', sync: true)
|
||||
editSession = project.openSync('sample.less', autoIndent: false)
|
||||
{buffer, languageMode} = editSession
|
||||
atom.packages.activatePackage('language-less', sync: true)
|
||||
atom.packages.activatePackage('language-css', sync: true)
|
||||
editor = atom.project.openSync('sample.less', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
describe "when commenting lines", ->
|
||||
it "only uses the `commentEnd` pattern if it comes from the same grammar as the `commentStart`", ->
|
||||
@@ -209,68 +209,68 @@ describe "LanguageMode", ->
|
||||
|
||||
describe "folding", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
editSession = project.openSync('sample.js', autoIndent: false)
|
||||
{buffer, languageMode} = editSession
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
editor = atom.project.openSync('sample.js', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
it "maintains cursor buffer position when a folding/unfolding", ->
|
||||
editSession.setCursorBufferPosition([5,5])
|
||||
editor.setCursorBufferPosition([5,5])
|
||||
languageMode.foldAll()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([5,5])
|
||||
expect(editor.getCursorBufferPosition()).toEqual([5,5])
|
||||
|
||||
describe ".unfoldAll()", ->
|
||||
it "unfolds every folded line", ->
|
||||
initialScreenLineCount = editSession.getScreenLineCount()
|
||||
initialScreenLineCount = editor.getScreenLineCount()
|
||||
languageMode.foldBufferRow(0)
|
||||
languageMode.foldBufferRow(1)
|
||||
expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount
|
||||
expect(editor.getScreenLineCount()).toBeLessThan initialScreenLineCount
|
||||
languageMode.unfoldAll()
|
||||
expect(editSession.getScreenLineCount()).toBe initialScreenLineCount
|
||||
expect(editor.getScreenLineCount()).toBe initialScreenLineCount
|
||||
|
||||
describe ".foldAll()", ->
|
||||
it "folds every foldable line", ->
|
||||
languageMode.foldAll()
|
||||
|
||||
fold1 = editSession.lineForScreenRow(0).fold
|
||||
fold1 = editor.lineForScreenRow(0).fold
|
||||
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 12]
|
||||
fold1.destroy()
|
||||
|
||||
fold2 = editSession.lineForScreenRow(1).fold
|
||||
fold2 = editor.lineForScreenRow(1).fold
|
||||
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 9]
|
||||
fold2.destroy()
|
||||
|
||||
fold3 = editSession.lineForScreenRow(4).fold
|
||||
fold3 = editor.lineForScreenRow(4).fold
|
||||
expect([fold3.getStartRow(), fold3.getEndRow()]).toEqual [4, 7]
|
||||
|
||||
describe ".foldBufferRow(bufferRow)", ->
|
||||
describe "when bufferRow can be folded", ->
|
||||
it "creates a fold based on the syntactic region starting at the given row", ->
|
||||
languageMode.foldBufferRow(1)
|
||||
fold = editSession.lineForScreenRow(1).fold
|
||||
fold = editor.lineForScreenRow(1).fold
|
||||
expect(fold.getStartRow()).toBe 1
|
||||
expect(fold.getEndRow()).toBe 9
|
||||
|
||||
describe "when bufferRow can't be folded", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", ->
|
||||
languageMode.foldBufferRow(8)
|
||||
fold = editSession.lineForScreenRow(1).fold
|
||||
fold = editor.lineForScreenRow(1).fold
|
||||
expect(fold.getStartRow()).toBe 1
|
||||
expect(fold.getEndRow()).toBe 9
|
||||
|
||||
describe "when the bufferRow is already folded", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
|
||||
languageMode.foldBufferRow(2)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
|
||||
expect(editSession.lineForScreenRow(0).fold).not.toBeDefined()
|
||||
expect(editor.lineForScreenRow(1).fold).toBeDefined()
|
||||
expect(editor.lineForScreenRow(0).fold).not.toBeDefined()
|
||||
|
||||
languageMode.foldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(0).fold).toBeDefined()
|
||||
expect(editor.lineForScreenRow(0).fold).toBeDefined()
|
||||
|
||||
describe "when the bufferRow is in a multi-line comment", ->
|
||||
it "searches upward and downward for surrounding comment lines and folds them as a single fold", ->
|
||||
buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment")
|
||||
languageMode.foldBufferRow(1)
|
||||
fold = editSession.lineForScreenRow(1).fold
|
||||
fold = editor.lineForScreenRow(1).fold
|
||||
expect(fold.getStartRow()).toBe 1
|
||||
expect(fold.getEndRow()).toBe 3
|
||||
|
||||
@@ -278,7 +278,7 @@ describe "LanguageMode", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
|
||||
buffer.insert([1,0], " //this is a single line comment\n")
|
||||
languageMode.foldBufferRow(1)
|
||||
fold = editSession.lineForScreenRow(0).fold
|
||||
fold = editor.lineForScreenRow(0).fold
|
||||
expect(fold.getStartRow()).toBe 0
|
||||
expect(fold.getEndRow()).toBe 13
|
||||
|
||||
@@ -286,77 +286,77 @@ describe "LanguageMode", ->
|
||||
describe "when bufferRow can be unfolded", ->
|
||||
it "destroys a fold based on the syntactic region starting at the given row", ->
|
||||
languageMode.foldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
|
||||
expect(editor.lineForScreenRow(1).fold).toBeDefined()
|
||||
|
||||
languageMode.unfoldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
|
||||
expect(editor.lineForScreenRow(1).fold).toBeUndefined()
|
||||
|
||||
describe "when bufferRow can't be unfolded", ->
|
||||
it "does not throw an error", ->
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
|
||||
expect(editor.lineForScreenRow(1).fold).toBeUndefined()
|
||||
languageMode.unfoldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
|
||||
expect(editor.lineForScreenRow(1).fold).toBeUndefined()
|
||||
|
||||
describe "folding with comments", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
editSession = project.openSync('sample-with-comments.js', autoIndent: false)
|
||||
{buffer, languageMode} = editSession
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
editor = atom.project.openSync('sample-with-comments.js', autoIndent: false)
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
describe ".unfoldAll()", ->
|
||||
it "unfolds every folded line", ->
|
||||
initialScreenLineCount = editSession.getScreenLineCount()
|
||||
initialScreenLineCount = editor.getScreenLineCount()
|
||||
languageMode.foldBufferRow(0)
|
||||
languageMode.foldBufferRow(5)
|
||||
expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount
|
||||
expect(editor.getScreenLineCount()).toBeLessThan initialScreenLineCount
|
||||
languageMode.unfoldAll()
|
||||
expect(editSession.getScreenLineCount()).toBe initialScreenLineCount
|
||||
expect(editor.getScreenLineCount()).toBe initialScreenLineCount
|
||||
|
||||
describe ".foldAll()", ->
|
||||
it "folds every foldable line", ->
|
||||
languageMode.foldAll()
|
||||
|
||||
fold1 = editSession.lineForScreenRow(0).fold
|
||||
fold1 = editor.lineForScreenRow(0).fold
|
||||
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19]
|
||||
fold1.destroy()
|
||||
|
||||
fold2 = editSession.lineForScreenRow(1).fold
|
||||
fold2 = editor.lineForScreenRow(1).fold
|
||||
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [1, 4]
|
||||
|
||||
fold3 = editSession.lineForScreenRow(2).fold.destroy()
|
||||
fold3 = editor.lineForScreenRow(2).fold.destroy()
|
||||
|
||||
fold4 = editSession.lineForScreenRow(3).fold
|
||||
fold4 = editor.lineForScreenRow(3).fold
|
||||
expect([fold4.getStartRow(), fold4.getEndRow()]).toEqual [6, 8]
|
||||
|
||||
describe ".foldAllAtIndentLevel()", ->
|
||||
it "folds every foldable range at a given indentLevel", ->
|
||||
languageMode.foldAllAtIndentLevel(2)
|
||||
|
||||
fold1 = editSession.lineForScreenRow(6).fold
|
||||
fold1 = editor.lineForScreenRow(6).fold
|
||||
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [6, 8]
|
||||
fold1.destroy()
|
||||
|
||||
fold2 = editSession.lineForScreenRow(11).fold
|
||||
fold2 = editor.lineForScreenRow(11).fold
|
||||
expect([fold2.getStartRow(), fold2.getEndRow()]).toEqual [11, 14]
|
||||
fold2.destroy()
|
||||
|
||||
it "does not fold anything but the indentLevel", ->
|
||||
languageMode.foldAllAtIndentLevel(0)
|
||||
|
||||
fold1 = editSession.lineForScreenRow(0).fold
|
||||
fold1 = editor.lineForScreenRow(0).fold
|
||||
expect([fold1.getStartRow(), fold1.getEndRow()]).toEqual [0, 19]
|
||||
fold1.destroy()
|
||||
|
||||
fold2 = editSession.lineForScreenRow(5).fold
|
||||
fold2 = editor.lineForScreenRow(5).fold
|
||||
expect(fold2).toBeFalsy()
|
||||
|
||||
describe "css", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-source', sync: true)
|
||||
atom.activatePackage('language-css', sync: true)
|
||||
editSession = project.openSync('css.css', autoIndent: true)
|
||||
atom.packages.activatePackage('language-source', sync: true)
|
||||
atom.packages.activatePackage('language-css', sync: true)
|
||||
editor = atom.project.openSync('css.css', autoIndent: true)
|
||||
|
||||
describe "suggestedIndentForBufferRow", ->
|
||||
it "does not return negative values (regression)", ->
|
||||
editSession.setText('.test {\npadding: 0;\n}')
|
||||
expect(editSession.suggestedIndentForBufferRow(2)).toBe 0
|
||||
editor.setText('.test {\npadding: 0;\n}')
|
||||
expect(editor.suggestedIndentForBufferRow(2)).toBe 0
|
||||
|
||||
@@ -9,7 +9,7 @@ describe "PaneContainer", ->
|
||||
|
||||
beforeEach ->
|
||||
class TestView extends View
|
||||
registerDeserializer(this)
|
||||
atom.deserializers.add(this)
|
||||
@deserialize: ({name}) -> new TestView(name)
|
||||
@content: -> @div tabindex: -1
|
||||
initialize: (@name) -> @text(@name)
|
||||
@@ -25,7 +25,7 @@ describe "PaneContainer", ->
|
||||
pane3 = pane2.splitDown(new TestView('3'))
|
||||
|
||||
afterEach ->
|
||||
unregisterDeserializer(TestView)
|
||||
atom.deserializers.remove(TestView)
|
||||
|
||||
describe ".focusNextPane()", ->
|
||||
it "focuses the pane following the focused pane or the first pane if no pane has focus", ->
|
||||
@@ -84,7 +84,7 @@ describe "PaneContainer", ->
|
||||
expect(panes).toEqual [pane4]
|
||||
|
||||
panes = []
|
||||
subscription.cancel()
|
||||
subscription.off()
|
||||
pane4.splitDown()
|
||||
expect(panes).toEqual []
|
||||
|
||||
@@ -111,11 +111,11 @@ describe "PaneContainer", ->
|
||||
|
||||
describe "when the last-closed pane item is an edit session", ->
|
||||
it "reopens the edit session (regression)", ->
|
||||
editSession = project.openSync('sample.js')
|
||||
pane3.showItem(editSession)
|
||||
pane3.destroyItem(editSession)
|
||||
editor = atom.project.openSync('sample.js')
|
||||
pane3.showItem(editor)
|
||||
pane3.destroyItem(editor)
|
||||
expect(container.reopenItem()).toBeTruthy()
|
||||
expect(pane3.activeItem.getPath()).toBe editSession.getPath()
|
||||
expect(pane3.activeItem.getPath()).toBe editor.getPath()
|
||||
expect(container.reopenItem()).toBeFalsy()
|
||||
|
||||
describe "when there is no active pane", ->
|
||||
@@ -169,28 +169,28 @@ describe "PaneContainer", ->
|
||||
it "returns true after modified files are saved", ->
|
||||
pane1.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
pane2.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
spyOn(atom, "confirmSync").andReturn(0)
|
||||
spyOn(atom, "confirm").andReturn(0)
|
||||
|
||||
saved = container.confirmClose()
|
||||
|
||||
runs ->
|
||||
expect(saved).toBeTruthy()
|
||||
expect(atom.confirmSync).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
it "returns false if the user cancels saving", ->
|
||||
pane1.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
pane2.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
spyOn(atom, "confirmSync").andReturn(1)
|
||||
spyOn(atom, "confirm").andReturn(1)
|
||||
|
||||
saved = container.confirmClose()
|
||||
|
||||
runs ->
|
||||
expect(saved).toBeFalsy()
|
||||
expect(atom.confirmSync).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
describe "serialization", ->
|
||||
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
|
||||
newContainer = deserialize(container.serialize())
|
||||
newContainer = atom.deserializers.deserialize(container.serialize())
|
||||
expect(newContainer.find('.row > :contains(1)')).toExist()
|
||||
expect(newContainer.find('.row > .column > :contains(2)')).toExist()
|
||||
expect(newContainer.find('.row > .column > :contains(3)')).toExist()
|
||||
@@ -202,7 +202,7 @@ describe "PaneContainer", ->
|
||||
xit "removes empty panes on deserialization", ->
|
||||
# only deserialize pane 1's view successfully
|
||||
TestView.deserialize = ({name}) -> new TestView(name) if name is '1'
|
||||
newContainer = deserialize(container.serialize())
|
||||
newContainer = atom.deserializers.deserialize(container.serialize())
|
||||
expect(newContainer.find('.row, .column')).not.toExist()
|
||||
expect(newContainer.find('> :contains(1)')).toExist()
|
||||
|
||||
|
||||
+121
-121
@@ -5,7 +5,7 @@ path = require 'path'
|
||||
temp = require 'temp'
|
||||
|
||||
describe "Pane", ->
|
||||
[container, view1, view2, editSession1, editSession2, pane] = []
|
||||
[container, view1, view2, editor1, editor2, pane] = []
|
||||
|
||||
class TestView extends View
|
||||
@deserialize: ({id, text}) -> new TestView({id, text})
|
||||
@@ -16,17 +16,17 @@ describe "Pane", ->
|
||||
isEqual: (other) -> @id == other.id and @text == other.text
|
||||
|
||||
beforeEach ->
|
||||
registerDeserializer(TestView)
|
||||
atom.deserializers.add(TestView)
|
||||
container = new PaneContainer
|
||||
view1 = new TestView(id: 'view-1', text: 'View 1')
|
||||
view2 = new TestView(id: 'view-2', text: 'View 2')
|
||||
editSession1 = project.openSync('sample.js')
|
||||
editSession2 = project.openSync('sample.txt')
|
||||
pane = new Pane(view1, editSession1, view2, editSession2)
|
||||
editor1 = atom.project.openSync('sample.js')
|
||||
editor2 = atom.project.openSync('sample.txt')
|
||||
pane = new Pane(view1, editor1, view2, editor2)
|
||||
container.setRoot(pane)
|
||||
|
||||
afterEach ->
|
||||
unregisterDeserializer(TestView)
|
||||
atom.deserializers.remove(TestView)
|
||||
|
||||
describe ".initialize(items...)", ->
|
||||
it "displays the first item in the pane", ->
|
||||
@@ -52,9 +52,9 @@ describe "Pane", ->
|
||||
expect(itemChangedHandler.argsForCall[0][1]).toBe view2
|
||||
itemChangedHandler.reset()
|
||||
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
expect(itemChangedHandler).toHaveBeenCalled()
|
||||
expect(itemChangedHandler.argsForCall[0][1]).toBe editSession1
|
||||
expect(itemChangedHandler.argsForCall[0][1]).toBe editor1
|
||||
itemChangedHandler.reset()
|
||||
|
||||
describe "if the pane's active view is focused before calling showItem", ->
|
||||
@@ -70,12 +70,12 @@ describe "Pane", ->
|
||||
view3 = null
|
||||
beforeEach ->
|
||||
view3 = new TestView(id: 'view-3', text: "View 3")
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
expect(pane.getActiveItemIndex()).toBe 1
|
||||
|
||||
it "adds it to the items list after the active item", ->
|
||||
pane.showItem(view3)
|
||||
expect(pane.getItems()).toEqual [view1, editSession1, view3, view2, editSession2]
|
||||
expect(pane.getItems()).toEqual [view1, editor1, view3, view2, editor2]
|
||||
expect(pane.activeItem).toBe view3
|
||||
expect(pane.getActiveItemIndex()).toBe 2
|
||||
|
||||
@@ -89,19 +89,19 @@ describe "Pane", ->
|
||||
describe "when showing a model item", ->
|
||||
describe "when no view has yet been appended for that item", ->
|
||||
it "appends and shows a view to display the item based on its `.getViewClass` method", ->
|
||||
pane.showItem(editSession1)
|
||||
editor = pane.activeView
|
||||
expect(editor.css('display')).not.toBe 'none'
|
||||
expect(editor.activeEditSession).toBe editSession1
|
||||
pane.showItem(editor1)
|
||||
editorView = pane.activeView
|
||||
expect(editorView.css('display')).not.toBe 'none'
|
||||
expect(editorView.activeEditSession).toBe editor1
|
||||
|
||||
describe "when a valid view has already been appended for another item", ->
|
||||
it "multiple views are created for multiple items", ->
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editSession2)
|
||||
pane.showItem(editor1)
|
||||
pane.showItem(editor2)
|
||||
expect(pane.itemViews.find('.editor').length).toBe 2
|
||||
editor = pane.activeView
|
||||
expect(editor.css('display')).not.toBe 'none'
|
||||
expect(editor.activeEditSession).toBe editSession2
|
||||
editorView = pane.activeView
|
||||
expect(editorView.css('display')).not.toBe 'none'
|
||||
expect(editorView.activeEditSession).toBe editor2
|
||||
|
||||
it "creates a new view with the item", ->
|
||||
initialViewCount = pane.itemViews.find('.test-view').length
|
||||
@@ -141,77 +141,77 @@ describe "Pane", ->
|
||||
describe ".destroyItem(item)", ->
|
||||
describe "if the item is not modified", ->
|
||||
it "removes the item and tries to call destroy on it", ->
|
||||
pane.destroyItem(editSession2)
|
||||
expect(pane.getItems().indexOf(editSession2)).toBe -1
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
pane.destroyItem(editor2)
|
||||
expect(pane.getItems().indexOf(editor2)).toBe -1
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
|
||||
describe "if the item is modified", ->
|
||||
beforeEach ->
|
||||
spyOn(editSession2, 'save')
|
||||
spyOn(editSession2, 'saveAs')
|
||||
spyOn(editor2, 'save')
|
||||
spyOn(editor2, 'saveAs')
|
||||
|
||||
editSession2.insertText('a')
|
||||
expect(editSession2.isModified()).toBeTruthy()
|
||||
editor2.insertText('a')
|
||||
expect(editor2.isModified()).toBeTruthy()
|
||||
|
||||
describe "if the [Save] option is selected", ->
|
||||
describe "when the item has a uri", ->
|
||||
it "saves the item before removing and destroying it", ->
|
||||
spyOn(atom, 'confirmSync').andReturn(0)
|
||||
pane.destroyItem(editSession2)
|
||||
spyOn(atom, 'confirm').andReturn(0)
|
||||
pane.destroyItem(editor2)
|
||||
|
||||
expect(editSession2.save).toHaveBeenCalled()
|
||||
expect(pane.getItems().indexOf(editSession2)).toBe -1
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
expect(editor2.save).toHaveBeenCalled()
|
||||
expect(pane.getItems().indexOf(editor2)).toBe -1
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
|
||||
describe "when the item has no uri", ->
|
||||
it "presents a save-as dialog, then saves the item with the given uri before removing and destroying it", ->
|
||||
editSession2.buffer.setPath(undefined)
|
||||
editor2.buffer.setPath(undefined)
|
||||
|
||||
spyOn(atom, 'showSaveDialogSync').andReturn("/selected/path")
|
||||
spyOn(atom, 'confirmSync').andReturn(0)
|
||||
pane.destroyItem(editSession2)
|
||||
spyOn(atom, 'confirm').andReturn(0)
|
||||
pane.destroyItem(editor2)
|
||||
|
||||
expect(atom.showSaveDialogSync).toHaveBeenCalled()
|
||||
|
||||
expect(editSession2.saveAs).toHaveBeenCalledWith("/selected/path")
|
||||
expect(pane.getItems().indexOf(editSession2)).toBe -1
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
expect(editor2.saveAs).toHaveBeenCalledWith("/selected/path")
|
||||
expect(pane.getItems().indexOf(editor2)).toBe -1
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
|
||||
describe "if the [Don't Save] option is selected", ->
|
||||
it "removes and destroys the item without saving it", ->
|
||||
spyOn(atom, 'confirmSync').andReturn(2)
|
||||
pane.destroyItem(editSession2)
|
||||
spyOn(atom, 'confirm').andReturn(2)
|
||||
pane.destroyItem(editor2)
|
||||
|
||||
expect(editSession2.save).not.toHaveBeenCalled()
|
||||
expect(pane.getItems().indexOf(editSession2)).toBe -1
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
expect(editor2.save).not.toHaveBeenCalled()
|
||||
expect(pane.getItems().indexOf(editor2)).toBe -1
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
|
||||
describe "if the [Cancel] option is selected", ->
|
||||
it "does not save, remove, or destroy the item", ->
|
||||
spyOn(atom, 'confirmSync').andReturn(1)
|
||||
pane.destroyItem(editSession2)
|
||||
spyOn(atom, 'confirm').andReturn(1)
|
||||
pane.destroyItem(editor2)
|
||||
|
||||
expect(editSession2.save).not.toHaveBeenCalled()
|
||||
expect(pane.getItems().indexOf(editSession2)).not.toBe -1
|
||||
expect(editSession2.destroyed).toBeFalsy()
|
||||
expect(editor2.save).not.toHaveBeenCalled()
|
||||
expect(pane.getItems().indexOf(editor2)).not.toBe -1
|
||||
expect(editor2.destroyed).toBeFalsy()
|
||||
|
||||
describe ".removeItem(item)", ->
|
||||
it "removes the item from the items list and shows the next item if it was showing", ->
|
||||
pane.removeItem(view1)
|
||||
expect(pane.getItems()).toEqual [editSession1, view2, editSession2]
|
||||
expect(pane.activeItem).toBe editSession1
|
||||
expect(pane.getItems()).toEqual [editor1, view2, editor2]
|
||||
expect(pane.activeItem).toBe editor1
|
||||
|
||||
pane.showItem(editSession2)
|
||||
pane.removeItem(editSession2)
|
||||
expect(pane.getItems()).toEqual [editSession1, view2]
|
||||
expect(pane.activeItem).toBe editSession1
|
||||
pane.showItem(editor2)
|
||||
pane.removeItem(editor2)
|
||||
expect(pane.getItems()).toEqual [editor1, view2]
|
||||
expect(pane.activeItem).toBe editor1
|
||||
|
||||
it "triggers 'pane:item-removed' with the item and its former index", ->
|
||||
itemRemovedHandler = jasmine.createSpy("itemRemovedHandler")
|
||||
pane.on 'pane:item-removed', itemRemovedHandler
|
||||
pane.removeItem(editSession1)
|
||||
pane.removeItem(editor1)
|
||||
expect(itemRemovedHandler).toHaveBeenCalled()
|
||||
expect(itemRemovedHandler.argsForCall[0][1..2]).toEqual [editSession1, 1]
|
||||
expect(itemRemovedHandler.argsForCall[0][1..2]).toEqual [editor1, 1]
|
||||
|
||||
describe "when removing the last item", ->
|
||||
it "removes the pane", ->
|
||||
@@ -236,11 +236,11 @@ describe "Pane", ->
|
||||
|
||||
describe "when the item is a model", ->
|
||||
it "removes the associated view only when all items that require it have been removed", ->
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editSession2)
|
||||
pane.removeItem(editSession2)
|
||||
pane.showItem(editor1)
|
||||
pane.showItem(editor2)
|
||||
pane.removeItem(editor2)
|
||||
expect(pane.itemViews.find('.editor')).toExist()
|
||||
pane.removeItem(editSession1)
|
||||
pane.removeItem(editor1)
|
||||
expect(pane.itemViews.find('.editor')).not.toExist()
|
||||
|
||||
describe ".moveItem(item, index)", ->
|
||||
@@ -249,21 +249,21 @@ describe "Pane", ->
|
||||
pane.on 'pane:item-moved', itemMovedHandler
|
||||
|
||||
pane.moveItem(view1, 2)
|
||||
expect(pane.getItems()).toEqual [editSession1, view2, view1, editSession2]
|
||||
expect(pane.getItems()).toEqual [editor1, view2, view1, editor2]
|
||||
expect(itemMovedHandler).toHaveBeenCalled()
|
||||
expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [view1, 2]
|
||||
itemMovedHandler.reset()
|
||||
|
||||
pane.moveItem(editSession1, 3)
|
||||
expect(pane.getItems()).toEqual [view2, view1, editSession2, editSession1]
|
||||
pane.moveItem(editor1, 3)
|
||||
expect(pane.getItems()).toEqual [view2, view1, editor2, editor1]
|
||||
expect(itemMovedHandler).toHaveBeenCalled()
|
||||
expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editSession1, 3]
|
||||
expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editor1, 3]
|
||||
itemMovedHandler.reset()
|
||||
|
||||
pane.moveItem(editSession1, 1)
|
||||
expect(pane.getItems()).toEqual [view2, editSession1, view1, editSession2]
|
||||
pane.moveItem(editor1, 1)
|
||||
expect(pane.getItems()).toEqual [view2, editor1, view1, editor2]
|
||||
expect(itemMovedHandler).toHaveBeenCalled()
|
||||
expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editSession1, 1]
|
||||
expect(itemMovedHandler.argsForCall[0][1..2]).toEqual [editor1, 1]
|
||||
itemMovedHandler.reset()
|
||||
|
||||
describe ".moveItemToPane(item, pane, index)", ->
|
||||
@@ -275,21 +275,21 @@ describe "Pane", ->
|
||||
|
||||
it "moves the item to the given pane at the given index", ->
|
||||
pane.moveItemToPane(view1, pane2, 1)
|
||||
expect(pane.getItems()).toEqual [editSession1, view2, editSession2]
|
||||
expect(pane.getItems()).toEqual [editor1, view2, editor2]
|
||||
expect(pane2.getItems()).toEqual [view3, view1]
|
||||
|
||||
describe "when it is the last item on the source pane", ->
|
||||
it "removes the source pane, but does not destroy the item", ->
|
||||
pane.removeItem(view1)
|
||||
pane.removeItem(view2)
|
||||
pane.removeItem(editSession2)
|
||||
pane.removeItem(editor2)
|
||||
|
||||
expect(pane.getItems()).toEqual [editSession1]
|
||||
pane.moveItemToPane(editSession1, pane2, 1)
|
||||
expect(pane.getItems()).toEqual [editor1]
|
||||
pane.moveItemToPane(editor1, pane2, 1)
|
||||
|
||||
expect(pane.hasParent()).toBeFalsy()
|
||||
expect(pane2.getItems()).toEqual [view3, editSession1]
|
||||
expect(editSession1.destroyed).toBeFalsy()
|
||||
expect(pane2.getItems()).toEqual [view3, editor1]
|
||||
expect(editor1.destroyed).toBeFalsy()
|
||||
|
||||
describe "when the item is a jQuery object", ->
|
||||
it "preserves data by detaching instead of removing", ->
|
||||
@@ -303,37 +303,37 @@ describe "Pane", ->
|
||||
containerCloseHandler = jasmine.createSpy("containerCloseHandler")
|
||||
container.on 'core:close', containerCloseHandler
|
||||
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
initialItemCount = pane.getItems().length
|
||||
pane.trigger 'core:close'
|
||||
expect(pane.getItems().length).toBe initialItemCount - 1
|
||||
expect(editSession1.destroyed).toBeTruthy()
|
||||
expect(editor1.destroyed).toBeTruthy()
|
||||
|
||||
expect(containerCloseHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "pane:close", ->
|
||||
it "destroys all items and removes the pane", ->
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
pane.trigger 'pane:close'
|
||||
expect(pane.hasParent()).toBeFalsy()
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
expect(editSession1.destroyed).toBeTruthy()
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
expect(editor1.destroyed).toBeTruthy()
|
||||
|
||||
describe "pane:close-other-items", ->
|
||||
it "destroys all items except the current", ->
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
pane.trigger 'pane:close-other-items'
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
expect(pane.getItems()).toEqual [editSession1]
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
expect(pane.getItems()).toEqual [editor1]
|
||||
|
||||
describe "core:save", ->
|
||||
describe "when the current item has a uri", ->
|
||||
describe "when the current item has a save method", ->
|
||||
it "saves the current item", ->
|
||||
spyOn(editSession2, 'save')
|
||||
pane.showItem(editSession2)
|
||||
spyOn(editor2, 'save')
|
||||
pane.showItem(editor2)
|
||||
pane.trigger 'core:save'
|
||||
expect(editSession2.save).toHaveBeenCalled()
|
||||
expect(editor2.save).toHaveBeenCalled()
|
||||
|
||||
describe "when the current item has no save method", ->
|
||||
it "does nothing", ->
|
||||
@@ -347,14 +347,14 @@ describe "Pane", ->
|
||||
|
||||
describe "when the current item has a saveAs method", ->
|
||||
it "opens a save dialog and saves the current item as the selected path", ->
|
||||
spyOn(editSession2, 'saveAs')
|
||||
editSession2.buffer.setPath(undefined)
|
||||
pane.showItem(editSession2)
|
||||
spyOn(editor2, 'saveAs')
|
||||
editor2.buffer.setPath(undefined)
|
||||
pane.showItem(editor2)
|
||||
|
||||
pane.trigger 'core:save'
|
||||
|
||||
expect(atom.showSaveDialogSync).toHaveBeenCalled()
|
||||
expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path')
|
||||
expect(editor2.saveAs).toHaveBeenCalledWith('/selected/path')
|
||||
|
||||
describe "when the current item has no saveAs method", ->
|
||||
it "does nothing", ->
|
||||
@@ -368,13 +368,13 @@ describe "Pane", ->
|
||||
|
||||
describe "when the current item has a saveAs method", ->
|
||||
it "opens the save dialog and calls saveAs on the item with the selected path", ->
|
||||
spyOn(editSession2, 'saveAs')
|
||||
pane.showItem(editSession2)
|
||||
spyOn(editor2, 'saveAs')
|
||||
pane.showItem(editor2)
|
||||
|
||||
pane.trigger 'core:save-as'
|
||||
|
||||
expect(atom.showSaveDialogSync).toHaveBeenCalledWith(path.dirname(editSession2.getPath()))
|
||||
expect(editSession2.saveAs).toHaveBeenCalledWith('/selected/path')
|
||||
expect(atom.showSaveDialogSync).toHaveBeenCalledWith(path.dirname(editor2.getPath()))
|
||||
expect(editor2.saveAs).toHaveBeenCalledWith('/selected/path')
|
||||
|
||||
describe "when the current item does not have a saveAs method", ->
|
||||
it "does nothing", ->
|
||||
@@ -386,11 +386,11 @@ describe "Pane", ->
|
||||
it "advances forward/backward through the pane's items, looping around at either end", ->
|
||||
expect(pane.activeItem).toBe view1
|
||||
pane.trigger 'pane:show-previous-item'
|
||||
expect(pane.activeItem).toBe editSession2
|
||||
expect(pane.activeItem).toBe editor2
|
||||
pane.trigger 'pane:show-previous-item'
|
||||
expect(pane.activeItem).toBe view2
|
||||
pane.trigger 'pane:show-next-item'
|
||||
expect(pane.activeItem).toBe editSession2
|
||||
expect(pane.activeItem).toBe editor2
|
||||
pane.trigger 'pane:show-next-item'
|
||||
expect(pane.activeItem).toBe view1
|
||||
|
||||
@@ -424,8 +424,8 @@ describe "Pane", ->
|
||||
describe ".remove()", ->
|
||||
it "destroys all the pane's items", ->
|
||||
pane.remove()
|
||||
expect(editSession1.destroyed).toBeTruthy()
|
||||
expect(editSession2.destroyed).toBeTruthy()
|
||||
expect(editor1.destroyed).toBeTruthy()
|
||||
expect(editor2.destroyed).toBeTruthy()
|
||||
|
||||
it "triggers a 'pane:removed' event with the pane", ->
|
||||
removedHandler = jasmine.createSpy("removedHandler")
|
||||
@@ -438,7 +438,7 @@ describe "Pane", ->
|
||||
[paneToLeft, paneToRight] = []
|
||||
|
||||
beforeEach ->
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
paneToLeft = pane.splitLeft(pane.copyActiveItem())
|
||||
paneToRight = pane.splitRight(pane.copyActiveItem())
|
||||
container.attachToDom()
|
||||
@@ -475,24 +475,24 @@ describe "Pane", ->
|
||||
describe "when it is the last pane", ->
|
||||
beforeEach ->
|
||||
expect(container.getPanes().length).toBe 1
|
||||
window.rootView = focus: jasmine.createSpy("rootView.focus")
|
||||
atom.rootView = focus: jasmine.createSpy("rootView.focus")
|
||||
|
||||
describe "when the removed pane is focused", ->
|
||||
it "calls focus on rootView so we don't lose focus", ->
|
||||
container.attachToDom()
|
||||
pane.focus()
|
||||
pane.remove()
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
expect(atom.rootView.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when the removed pane is not focused", ->
|
||||
it "does not call focus on root view", ->
|
||||
expect(pane).not.toMatchSelector ':has(:focus)'
|
||||
pane.remove()
|
||||
expect(rootView.focus).not.toHaveBeenCalled()
|
||||
expect(atom.rootView.focus).not.toHaveBeenCalled()
|
||||
|
||||
describe ".getNextPane()", ->
|
||||
it "returns the next pane if one exists, wrapping around from the last pane to the first", ->
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
expect(pane.getNextPane()).toBeUndefined
|
||||
pane2 = pane.splitRight(pane.copyActiveItem())
|
||||
expect(pane.getNextPane()).toBe pane2
|
||||
@@ -538,7 +538,7 @@ describe "Pane", ->
|
||||
[pane1, view3, view4] = []
|
||||
beforeEach ->
|
||||
pane1 = pane
|
||||
pane.showItem(editSession1)
|
||||
pane.showItem(editor1)
|
||||
view3 = new TestView(id: 'view-3', text: 'View 3')
|
||||
view4 = new TestView(id: 'view-4', text: 'View 4')
|
||||
|
||||
@@ -547,8 +547,8 @@ describe "Pane", ->
|
||||
# creates the new pane with a copy of the active item if none are given
|
||||
pane2 = pane1.splitRight(pane1.copyActiveItem())
|
||||
expect(container.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(pane2.items).toEqual [editSession1]
|
||||
expect(pane2.activeItem).not.toBe editSession1 # it's a copy
|
||||
expect(pane2.items).toEqual [editor1]
|
||||
expect(pane2.activeItem).not.toBe editor1 # it's a copy
|
||||
|
||||
pane3 = pane2.splitRight(view3, view4)
|
||||
expect(pane3.getItems()).toEqual [view3, view4]
|
||||
@@ -571,8 +571,8 @@ describe "Pane", ->
|
||||
# creates the new pane with a copy of the active item if none are given
|
||||
pane2 = pane.splitLeft(pane1.copyActiveItem())
|
||||
expect(container.find('.row .pane').toArray()).toEqual [pane2[0], pane[0]]
|
||||
expect(pane2.items).toEqual [editSession1]
|
||||
expect(pane2.activeItem).not.toBe editSession1 # it's a copy
|
||||
expect(pane2.items).toEqual [editor1]
|
||||
expect(pane2.activeItem).not.toBe editor1 # it's a copy
|
||||
|
||||
pane3 = pane2.splitLeft(view3, view4)
|
||||
expect(pane3.getItems()).toEqual [view3, view4]
|
||||
@@ -583,8 +583,8 @@ describe "Pane", ->
|
||||
# creates the new pane with a copy of the active item if none are given
|
||||
pane2 = pane.splitDown(pane1.copyActiveItem())
|
||||
expect(container.find('.column .pane').toArray()).toEqual [pane[0], pane2[0]]
|
||||
expect(pane2.items).toEqual [editSession1]
|
||||
expect(pane2.activeItem).not.toBe editSession1 # it's a copy
|
||||
expect(pane2.items).toEqual [editor1]
|
||||
expect(pane2.activeItem).not.toBe editor1 # it's a copy
|
||||
|
||||
pane3 = pane2.splitDown(view3, view4)
|
||||
expect(pane3.getItems()).toEqual [view3, view4]
|
||||
@@ -595,8 +595,8 @@ describe "Pane", ->
|
||||
# creates the new pane with a copy of the active item if none are given
|
||||
pane2 = pane.splitUp(pane1.copyActiveItem())
|
||||
expect(container.find('.column .pane').toArray()).toEqual [pane2[0], pane[0]]
|
||||
expect(pane2.items).toEqual [editSession1]
|
||||
expect(pane2.activeItem).not.toBe editSession1 # it's a copy
|
||||
expect(pane2.items).toEqual [editor1]
|
||||
expect(pane2.activeItem).not.toBe editor1 # it's a copy
|
||||
|
||||
pane3 = pane2.splitUp(view3, view4)
|
||||
expect(pane3.getItems()).toEqual [view3, view4]
|
||||
@@ -673,18 +673,18 @@ describe "Pane", ->
|
||||
|
||||
describe ".itemForUri(uri)", ->
|
||||
it "returns the item for which a call to .getUri() returns the given uri", ->
|
||||
expect(pane.itemForUri(editSession1.getUri())).toBe editSession1
|
||||
expect(pane.itemForUri(editSession2.getUri())).toBe editSession2
|
||||
expect(pane.itemForUri(editor1.getUri())).toBe editor1
|
||||
expect(pane.itemForUri(editor2.getUri())).toBe editor2
|
||||
|
||||
describe "serialization", ->
|
||||
it "can serialize and deserialize the pane and all its items", ->
|
||||
newPane = deserialize(pane.serialize())
|
||||
expect(newPane.getItems()).toEqual [view1, editSession1, view2, editSession2]
|
||||
newPane = atom.deserializers.deserialize(pane.serialize())
|
||||
expect(newPane.getItems()).toEqual [view1, editor1, view2, editor2]
|
||||
|
||||
it "restores the active item on deserialization", ->
|
||||
pane.showItem(editSession2)
|
||||
newPane = deserialize(pane.serialize())
|
||||
expect(newPane.activeItem).toEqual editSession2
|
||||
pane.showItem(editor2)
|
||||
newPane = atom.deserializers.deserialize(pane.serialize())
|
||||
expect(newPane.activeItem).toEqual editor2
|
||||
|
||||
it "does not show items that cannot be deserialized", ->
|
||||
spyOn(console, 'warn')
|
||||
@@ -693,18 +693,18 @@ describe "Pane", ->
|
||||
paneState = pane.serialize()
|
||||
paneState.get('items').set(pane.items.indexOf(view2), {deserializer: 'Bogus'}) # nuke serialized state of active item
|
||||
|
||||
newPane = deserialize(paneState)
|
||||
newPane = atom.deserializers.deserialize(paneState)
|
||||
expect(newPane.activeItem).toEqual pane.items[0]
|
||||
expect(newPane.items.length).toBe pane.items.length - 1
|
||||
|
||||
it "focuses the pane after attach only if had focus when serialized", ->
|
||||
reloadContainer = ->
|
||||
projectState = project.serialize()
|
||||
projectReplica = atom.replicate().get('project')
|
||||
containerState = container.serialize()
|
||||
container.remove()
|
||||
project.destroy()
|
||||
window.project = deserialize(projectState)
|
||||
container = deserialize(containerState)
|
||||
atom.project = projectReplica
|
||||
atom.project.destroy()
|
||||
container = atom.deserializers.deserialize(containerState)
|
||||
pane = container.getRoot()
|
||||
container.attachToDom()
|
||||
|
||||
|
||||
+167
-154
@@ -8,7 +8,7 @@ BufferedProcess = require '../src/buffered-process'
|
||||
|
||||
describe "Project", ->
|
||||
beforeEach ->
|
||||
project.setPath(project.resolve('dir'))
|
||||
atom.project.setPath(atom.project.resolve('dir'))
|
||||
|
||||
describe "serialization", ->
|
||||
deserializedProject = null
|
||||
@@ -17,121 +17,134 @@ describe "Project", ->
|
||||
deserializedProject?.destroy()
|
||||
|
||||
it "destroys unretained buffers and does not include them in the serialized state", ->
|
||||
project.bufferForPathSync('a')
|
||||
expect(project.getBuffers().length).toBe 1
|
||||
deserializedProject = deserialize(project.serialize())
|
||||
atom.project.bufferForPathSync('a')
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
|
||||
atom.project.getState().serializeForPersistence()
|
||||
deserializedProject = atom.replicate().get('project')
|
||||
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
expect(atom.project.getBuffers().length).toBe 0
|
||||
|
||||
it "listens for destroyed events on deserialized buffers and removes them when they are destroyed", ->
|
||||
atom.project.openSync('a')
|
||||
expect(atom.project.getBuffers().length).toBe 1
|
||||
atom.project.getState().serializeForPersistence()
|
||||
deserializedProject = atom.replicate().get('project')
|
||||
|
||||
expect(deserializedProject.getBuffers().length).toBe 1
|
||||
deserializedProject.getBuffers()[0].destroy()
|
||||
expect(deserializedProject.getBuffers().length).toBe 0
|
||||
expect(project.getBuffers().length).toBe 0
|
||||
|
||||
describe "when an edit session is destroyed", ->
|
||||
it "removes edit session and calls destroy on buffer (if buffer is not referenced by other edit sessions)", ->
|
||||
editSession = project.openSync("a")
|
||||
anotherEditSession = project.openSync("a")
|
||||
editor = atom.project.openSync("a")
|
||||
anotherEditSession = atom.project.openSync("a")
|
||||
|
||||
expect(project.editSessions.length).toBe 2
|
||||
expect(editSession.buffer).toBe anotherEditSession.buffer
|
||||
expect(atom.project.editors.length).toBe 2
|
||||
expect(editor.buffer).toBe anotherEditSession.buffer
|
||||
|
||||
editSession.destroy()
|
||||
expect(project.editSessions.length).toBe 1
|
||||
editor.destroy()
|
||||
expect(atom.project.editors.length).toBe 1
|
||||
|
||||
anotherEditSession.destroy()
|
||||
expect(project.editSessions.length).toBe 0
|
||||
expect(atom.project.editors.length).toBe 0
|
||||
|
||||
describe "when an edit session is saved and the project has no path", ->
|
||||
it "sets the project's path to the saved file's parent directory", ->
|
||||
tempFile = temp.openSync().path
|
||||
project.setPath(undefined)
|
||||
expect(project.getPath()).toBeUndefined()
|
||||
editSession = project.openSync()
|
||||
editSession.saveAs(tempFile)
|
||||
expect(project.getPath()).toBe path.dirname(tempFile)
|
||||
atom.project.setPath(undefined)
|
||||
expect(atom.project.getPath()).toBeUndefined()
|
||||
editor = atom.project.openSync()
|
||||
editor.saveAs(tempFile)
|
||||
expect(atom.project.getPath()).toBe path.dirname(tempFile)
|
||||
|
||||
describe "when an edit session is deserialized", ->
|
||||
it "emits an 'edit-session-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editSessionCreatedHandler')
|
||||
project.on 'edit-session-created', handler
|
||||
it "emits an 'editor-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
atom.project.on 'editor-created', handler
|
||||
|
||||
editSession1 = project.openSync("a")
|
||||
editor1 = atom.project.openSync("a")
|
||||
expect(handler.callCount).toBe 1
|
||||
expect(project.getEditSessions().length).toBe 1
|
||||
expect(project.getEditSessions()[0]).toBe editSession1
|
||||
expect(atom.project.getEditSessions().length).toBe 1
|
||||
expect(atom.project.getEditSessions()[0]).toBe editor1
|
||||
|
||||
editSession2 = deserialize(editSession1.serialize())
|
||||
editor2 = atom.deserializers.deserialize(editor1.serialize())
|
||||
expect(handler.callCount).toBe 2
|
||||
expect(project.getEditSessions().length).toBe 2
|
||||
expect(project.getEditSessions()[0]).toBe editSession1
|
||||
expect(project.getEditSessions()[1]).toBe editSession2
|
||||
expect(atom.project.getEditSessions().length).toBe 2
|
||||
expect(atom.project.getEditSessions()[0]).toBe editor1
|
||||
expect(atom.project.getEditSessions()[1]).toBe editor2
|
||||
|
||||
describe "when an edit session is copied", ->
|
||||
it "emits an 'edit-session-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editSessionCreatedHandler')
|
||||
project.on 'edit-session-created', handler
|
||||
it "emits an 'editor-created' event and stores the edit session", ->
|
||||
handler = jasmine.createSpy('editorCreatedHandler')
|
||||
atom.project.on 'editor-created', handler
|
||||
|
||||
editSession1 = project.openSync("a")
|
||||
editor1 = atom.project.openSync("a")
|
||||
expect(handler.callCount).toBe 1
|
||||
expect(project.getEditSessions().length).toBe 1
|
||||
expect(project.getEditSessions()[0]).toBe editSession1
|
||||
expect(atom.project.getEditSessions().length).toBe 1
|
||||
expect(atom.project.getEditSessions()[0]).toBe editor1
|
||||
|
||||
editSession2 = editSession1.copy()
|
||||
editor2 = editor1.copy()
|
||||
expect(handler.callCount).toBe 2
|
||||
expect(project.getEditSessions().length).toBe 2
|
||||
expect(project.getEditSessions()[0]).toBe editSession1
|
||||
expect(project.getEditSessions()[1]).toBe editSession2
|
||||
expect(atom.project.getEditSessions().length).toBe 2
|
||||
expect(atom.project.getEditSessions()[0]).toBe editor1
|
||||
expect(atom.project.getEditSessions()[1]).toBe editor2
|
||||
|
||||
describe ".openSync(path)", ->
|
||||
[fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = []
|
||||
beforeEach ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
newBufferHandler = jasmine.createSpy('newBufferHandler')
|
||||
project.on 'buffer-created', newBufferHandler
|
||||
atom.project.on 'buffer-created', newBufferHandler
|
||||
newEditSessionHandler = jasmine.createSpy('newEditSessionHandler')
|
||||
project.on 'edit-session-created', newEditSessionHandler
|
||||
atom.project.on 'editor-created', newEditSessionHandler
|
||||
|
||||
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
|
||||
barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//)
|
||||
project.registerOpener(fooOpener)
|
||||
project.registerOpener(barOpener)
|
||||
atom.project.registerOpener(fooOpener)
|
||||
atom.project.registerOpener(barOpener)
|
||||
|
||||
afterEach ->
|
||||
project.unregisterOpener(fooOpener)
|
||||
project.unregisterOpener(barOpener)
|
||||
atom.project.unregisterOpener(fooOpener)
|
||||
atom.project.unregisterOpener(barOpener)
|
||||
|
||||
describe "when passed a path that doesn't match a custom opener", ->
|
||||
describe "when given an absolute path that hasn't been opened previously", ->
|
||||
it "returns a new edit session for the given path and emits 'buffer-created' and 'edit-session-created' events", ->
|
||||
editSession = project.openSync(absolutePath)
|
||||
expect(editSession.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
|
||||
editor = atom.project.openSync(absolutePath)
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when given a relative path that hasn't been opened previously", ->
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'edit-session-created' events", ->
|
||||
editSession = project.openSync('a')
|
||||
expect(editSession.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
|
||||
editor = atom.project.openSync('a')
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when passed the path to a buffer that has already been opened", ->
|
||||
it "returns a new edit session containing previously opened buffer and emits a 'edit-session-created' event", ->
|
||||
editSession = project.openSync(absolutePath)
|
||||
it "returns a new edit session containing previously opened buffer and emits a 'editor-created' event", ->
|
||||
editor = atom.project.openSync(absolutePath)
|
||||
newBufferHandler.reset()
|
||||
expect(project.openSync(absolutePath).buffer).toBe editSession.buffer
|
||||
expect(project.openSync('a').buffer).toBe editSession.buffer
|
||||
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
|
||||
expect(atom.project.openSync('a').buffer).toBe editor.buffer
|
||||
expect(newBufferHandler).not.toHaveBeenCalled()
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when not passed a path", ->
|
||||
it "returns a new edit session and emits 'buffer-created' and 'edit-session-created' events", ->
|
||||
editSession = project.openSync()
|
||||
expect(editSession.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer)
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
|
||||
editor = atom.project.openSync()
|
||||
expect(editor.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when passed a path that matches a custom opener", ->
|
||||
it "returns the resource returned by the custom opener", ->
|
||||
pathToOpen = project.resolve('a.foo')
|
||||
expect(project.openSync(pathToOpen, hey: "there")).toEqual { foo: pathToOpen, options: {hey: "there"} }
|
||||
expect(project.openSync("bar://baz")).toEqual { bar: "bar://baz" }
|
||||
pathToOpen = atom.project.resolve('a.foo')
|
||||
expect(atom.project.openSync(pathToOpen, hey: "there")).toEqual { foo: pathToOpen, options: {hey: "there"} }
|
||||
expect(atom.project.openSync("bar://baz")).toEqual { bar: "bar://baz" }
|
||||
|
||||
describe ".open(path)", ->
|
||||
[fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = []
|
||||
@@ -139,81 +152,81 @@ describe "Project", ->
|
||||
beforeEach ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
newBufferHandler = jasmine.createSpy('newBufferHandler')
|
||||
project.on 'buffer-created', newBufferHandler
|
||||
atom.project.on 'buffer-created', newBufferHandler
|
||||
newEditSessionHandler = jasmine.createSpy('newEditSessionHandler')
|
||||
project.on 'edit-session-created', newEditSessionHandler
|
||||
atom.project.on 'editor-created', newEditSessionHandler
|
||||
|
||||
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
|
||||
barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//)
|
||||
project.registerOpener(fooOpener)
|
||||
project.registerOpener(barOpener)
|
||||
atom.project.registerOpener(fooOpener)
|
||||
atom.project.registerOpener(barOpener)
|
||||
|
||||
afterEach ->
|
||||
project.unregisterOpener(fooOpener)
|
||||
project.unregisterOpener(barOpener)
|
||||
atom.project.unregisterOpener(fooOpener)
|
||||
atom.project.unregisterOpener(barOpener)
|
||||
|
||||
describe "when passed a path that doesn't match a custom opener", ->
|
||||
describe "when given an absolute path that isn't currently open", ->
|
||||
it "returns a new edit session for the given path and emits 'buffer-created' and 'edit-session-created' events", ->
|
||||
editSession = null
|
||||
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
project.open(absolutePath).then (o) -> editSession = o
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editSession.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when given a relative path that isn't currently opened", ->
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'edit-session-created' events", ->
|
||||
editSession = null
|
||||
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
project.open(absolutePath).then (o) -> editSession = o
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editSession.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
expect(editor.buffer.getPath()).toBe absolutePath
|
||||
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when passed the path to a buffer that is currently opened", ->
|
||||
it "returns a new edit session containing currently opened buffer and emits a 'edit-session-created' event", ->
|
||||
editSession = null
|
||||
it "returns a new edit session containing currently opened buffer and emits a 'editor-created' event", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
project.open(absolutePath).then (o) -> editSession = o
|
||||
atom.project.open(absolutePath).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
newBufferHandler.reset()
|
||||
expect(project.openSync(absolutePath).buffer).toBe editSession.buffer
|
||||
expect(project.openSync('a').buffer).toBe editSession.buffer
|
||||
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
|
||||
expect(atom.project.openSync('a').buffer).toBe editor.buffer
|
||||
expect(newBufferHandler).not.toHaveBeenCalled()
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when not passed a path", ->
|
||||
it "returns a new edit session and emits 'buffer-created' and 'edit-session-created' events", ->
|
||||
editSession = null
|
||||
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
project.open().then (o) -> editSession = o
|
||||
atom.project.open().then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editSession.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer)
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
|
||||
expect(editor.buffer.getPath()).toBeUndefined()
|
||||
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
|
||||
expect(newEditSessionHandler).toHaveBeenCalledWith editor
|
||||
|
||||
describe "when passed a path that matches a custom opener", ->
|
||||
it "returns the resource returned by the custom opener", ->
|
||||
waitsForPromise ->
|
||||
pathToOpen = project.resolve('a.foo')
|
||||
project.open(pathToOpen, hey: "there").then (item) ->
|
||||
pathToOpen = atom.project.resolve('a.foo')
|
||||
atom.project.open(pathToOpen, hey: "there").then (item) ->
|
||||
expect(item).toEqual { foo: pathToOpen, options: {hey: "there"} }
|
||||
|
||||
waitsForPromise ->
|
||||
project.open("bar://baz").then (item) ->
|
||||
atom.project.open("bar://baz").then (item) ->
|
||||
expect(item).toEqual { bar: "bar://baz" }
|
||||
|
||||
it "returns number of read bytes as progress indicator", ->
|
||||
filePath = project.resolve 'a'
|
||||
filePath = atom.project.resolve 'a'
|
||||
totalBytes = 0
|
||||
promise = project.open(filePath)
|
||||
promise = atom.project.open(filePath)
|
||||
promise.progress (bytesRead) -> totalBytes = bytesRead
|
||||
|
||||
waitsForPromise ->
|
||||
@@ -225,22 +238,22 @@ describe "Project", ->
|
||||
describe ".bufferForPathSync(path)", ->
|
||||
describe "when opening a previously opened path", ->
|
||||
it "does not create a new buffer", ->
|
||||
buffer = project.bufferForPathSync("a").retain()
|
||||
expect(project.bufferForPathSync("a")).toBe buffer
|
||||
buffer = atom.project.bufferForPathSync("a").retain()
|
||||
expect(atom.project.bufferForPathSync("a")).toBe buffer
|
||||
|
||||
alternativeBuffer = project.bufferForPathSync("b").retain().release()
|
||||
alternativeBuffer = atom.project.bufferForPathSync("b").retain().release()
|
||||
expect(alternativeBuffer).not.toBe buffer
|
||||
buffer.release()
|
||||
|
||||
it "creates a new buffer if the previous buffer was destroyed", ->
|
||||
buffer = project.bufferForPathSync("a").retain().release()
|
||||
expect(project.bufferForPathSync("a").retain().release()).not.toBe buffer
|
||||
buffer = atom.project.bufferForPathSync("a").retain().release()
|
||||
expect(atom.project.bufferForPathSync("a").retain().release()).not.toBe buffer
|
||||
|
||||
describe ".bufferForPath(path)", ->
|
||||
[buffer] = []
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
project.bufferForPath("a").then (o) ->
|
||||
atom.project.bufferForPath("a").then (o) ->
|
||||
buffer = o
|
||||
buffer.retain()
|
||||
|
||||
@@ -250,60 +263,60 @@ describe "Project", ->
|
||||
describe "when opening a previously opened path", ->
|
||||
it "does not create a new buffer", ->
|
||||
waitsForPromise ->
|
||||
project.bufferForPath("a").then (anotherBuffer) ->
|
||||
atom.project.bufferForPath("a").then (anotherBuffer) ->
|
||||
expect(anotherBuffer).toBe buffer
|
||||
|
||||
waitsForPromise ->
|
||||
project.bufferForPath("b").then (anotherBuffer) ->
|
||||
atom.project.bufferForPath("b").then (anotherBuffer) ->
|
||||
expect(anotherBuffer).not.toBe buffer
|
||||
|
||||
it "creates a new buffer if the previous buffer was destroyed", ->
|
||||
buffer.release()
|
||||
|
||||
waitsForPromise ->
|
||||
project.bufferForPath("b").then (anotherBuffer) ->
|
||||
atom.project.bufferForPath("b").then (anotherBuffer) ->
|
||||
expect(anotherBuffer).not.toBe buffer
|
||||
|
||||
describe ".resolve(uri)", ->
|
||||
describe "when passed an absolute or relative path", ->
|
||||
it "returns an absolute path based on the project's root", ->
|
||||
it "returns an absolute path based on the atom.project's root", ->
|
||||
absolutePath = require.resolve('./fixtures/dir/a')
|
||||
expect(project.resolve('a')).toBe absolutePath
|
||||
expect(project.resolve(absolutePath + '/../a')).toBe absolutePath
|
||||
expect(project.resolve('a/../a')).toBe absolutePath
|
||||
expect(atom.project.resolve('a')).toBe absolutePath
|
||||
expect(atom.project.resolve(absolutePath + '/../a')).toBe absolutePath
|
||||
expect(atom.project.resolve('a/../a')).toBe absolutePath
|
||||
|
||||
describe "when passed a uri with a scheme", ->
|
||||
it "does not modify uris that begin with a scheme", ->
|
||||
expect(project.resolve('http://zombo.com')).toBe 'http://zombo.com'
|
||||
expect(atom.project.resolve('http://zombo.com')).toBe 'http://zombo.com'
|
||||
|
||||
describe ".setPath(path)", ->
|
||||
describe "when path is a file", ->
|
||||
it "sets its path to the files parent directory and updates the root directory", ->
|
||||
project.setPath(require.resolve('./fixtures/dir/a'))
|
||||
expect(project.getPath()).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
expect(project.getRootDirectory().path).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
atom.project.setPath(require.resolve('./fixtures/dir/a'))
|
||||
expect(atom.project.getPath()).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
expect(atom.project.getRootDirectory().path).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
|
||||
describe "when path is a directory", ->
|
||||
it "sets its path to the directory and updates the root directory", ->
|
||||
directory = fs.absolute(path.join(__dirname, 'fixtures', 'dir', 'a-dir'))
|
||||
project.setPath(directory)
|
||||
expect(project.getPath()).toEqual directory
|
||||
expect(project.getRootDirectory().path).toEqual directory
|
||||
atom.project.setPath(directory)
|
||||
expect(atom.project.getPath()).toEqual directory
|
||||
expect(atom.project.getRootDirectory().path).toEqual directory
|
||||
|
||||
describe "when path is null", ->
|
||||
it "sets its path and root directory to null", ->
|
||||
project.setPath(null)
|
||||
expect(project.getPath()?).toBeFalsy()
|
||||
expect(project.getRootDirectory()?).toBeFalsy()
|
||||
atom.project.setPath(null)
|
||||
expect(atom.project.getPath()?).toBeFalsy()
|
||||
expect(atom.project.getRootDirectory()?).toBeFalsy()
|
||||
|
||||
describe ".replace()", ->
|
||||
[filePath, commentFilePath, sampleContent, sampleCommentContent] = []
|
||||
|
||||
beforeEach ->
|
||||
project.setPath(project.resolve('../'))
|
||||
atom.project.setPath(atom.project.resolve('../'))
|
||||
|
||||
filePath = project.resolve('sample.js')
|
||||
commentFilePath = project.resolve('sample-with-comments.js')
|
||||
filePath = atom.project.resolve('sample.js')
|
||||
commentFilePath = atom.project.resolve('sample-with-comments.js')
|
||||
sampleContent = fs.readFileSync(filePath).toString()
|
||||
sampleCommentContent = fs.readFileSync(commentFilePath).toString()
|
||||
|
||||
@@ -315,7 +328,7 @@ describe "Project", ->
|
||||
it "replaces properly", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
atom.project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
@@ -325,12 +338,12 @@ describe "Project", ->
|
||||
|
||||
describe "when a buffer is already open", ->
|
||||
it "replaces properly and saves when not modified", ->
|
||||
editSession = project.openSync('sample.js')
|
||||
expect(editSession.isModified()).toBeFalsy()
|
||||
editor = atom.project.openSync('sample.js')
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
atom.project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
@@ -338,16 +351,16 @@ describe "Project", ->
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editSession.isModified()).toBeFalsy()
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editSession = project.openSync('sample.js')
|
||||
editSession.buffer.change([[0,0],[0,0]], 'omg')
|
||||
expect(editSession.isModified()).toBeTruthy()
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.buffer.change([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.replace /items/gi, 'okthen', [filePath], (result) ->
|
||||
atom.project.replace /items/gi, 'okthen', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
@@ -355,19 +368,19 @@ describe "Project", ->
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editSession.isModified()).toBeTruthy()
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
describe ".scan(options, callback)", ->
|
||||
describe "when called with a regex", ->
|
||||
it "calls the callback with all regex results in all files in the project", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.scan /(a)+/, (result) ->
|
||||
atom.project.scan /(a)+/, (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results[0].filePath).toBe project.resolve('a')
|
||||
expect(results[0].filePath).toBe atom.project.resolve('a')
|
||||
expect(results[0].matches).toHaveLength(3)
|
||||
expect(results[0].matches[0]).toEqual
|
||||
matchText: 'aaa'
|
||||
@@ -378,13 +391,13 @@ describe "Project", ->
|
||||
it "works with with escaped literals (like $ and ^)", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.scan /\$\w+/, (result) -> results.push(result)
|
||||
atom.project.scan /\$\w+/, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results.length).toBe 1
|
||||
|
||||
{filePath, matches} = results[0]
|
||||
expect(filePath).toBe project.resolve('a')
|
||||
expect(filePath).toBe atom.project.resolve('a')
|
||||
expect(matches).toHaveLength 1
|
||||
expect(matches[0]).toEqual
|
||||
matchText: '$bill'
|
||||
@@ -393,11 +406,11 @@ describe "Project", ->
|
||||
range: [[2, 6], [2, 11]]
|
||||
|
||||
it "works on evil filenames", ->
|
||||
project.setPath(path.join(__dirname, 'fixtures', 'evil-files'))
|
||||
atom.project.setPath(path.join(__dirname, 'fixtures', 'evil-files'))
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
project.scan /evil/, (result) ->
|
||||
atom.project.scan /evil/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
@@ -420,7 +433,7 @@ describe "Project", ->
|
||||
it "ignores case if the regex includes the `i` flag", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.scan /DOLLAR/i, (result) -> results.push(result)
|
||||
atom.project.scan /DOLLAR/i, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
@@ -448,11 +461,11 @@ describe "Project", ->
|
||||
fs.removeSync(projectPath) if fs.existsSync(projectPath)
|
||||
|
||||
it "excludes ignored files", ->
|
||||
project.setPath(projectPath)
|
||||
atom.project.setPath(projectPath)
|
||||
atom.config.set('core.excludeVcsIgnoredPaths', true)
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
project.scan /match/, (results) ->
|
||||
atom.project.scan /match/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
@@ -460,14 +473,14 @@ describe "Project", ->
|
||||
|
||||
it "includes only files when a directory filter is specified", ->
|
||||
projectPath = path.join(path.join(__dirname, 'fixtures', 'dir'))
|
||||
project.setPath(projectPath)
|
||||
atom.project.setPath(projectPath)
|
||||
|
||||
filePath = path.join(projectPath, 'a-dir', 'oh-git')
|
||||
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
project.scan /aaa/, paths: ["a-dir#{path.sep}"], (result) ->
|
||||
atom.project.scan /aaa/, paths: ["a-dir#{path.sep}"], (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
@@ -480,11 +493,11 @@ describe "Project", ->
|
||||
projectPath = temp.mkdirSync()
|
||||
filePath = path.join(projectPath, '.text')
|
||||
fs.writeFileSync(filePath, 'match this')
|
||||
project.setPath(projectPath)
|
||||
atom.project.setPath(projectPath)
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
project.scan /match this/, (result) ->
|
||||
atom.project.scan /match this/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
@@ -501,18 +514,18 @@ describe "Project", ->
|
||||
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
project.scan /dollar/, (results) ->
|
||||
atom.project.scan /dollar/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editSession = project.openSync("a")
|
||||
editSession.setText("Elephant")
|
||||
editor = atom.project.openSync("a")
|
||||
editor.setText("Elephant")
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.scan /a|Elephant/, (result) -> results.push result
|
||||
atom.project.scan /a|Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 3
|
||||
|
||||
+196
-195
@@ -8,67 +8,68 @@ describe "RootView", ->
|
||||
pathToOpen = null
|
||||
|
||||
beforeEach ->
|
||||
project.setPath(project.resolve('dir'))
|
||||
pathToOpen = project.resolve('a')
|
||||
window.rootView = new RootView
|
||||
rootView.enableKeymap()
|
||||
rootView.openSync(pathToOpen)
|
||||
rootView.focus()
|
||||
atom.project.setPath(atom.project.resolve('dir'))
|
||||
pathToOpen = atom.project.resolve('a')
|
||||
atom.rootView = new RootView
|
||||
atom.rootView.enableKeymap()
|
||||
atom.rootView.openSync(pathToOpen)
|
||||
atom.rootView.focus()
|
||||
|
||||
describe "@deserialize()", ->
|
||||
viewState = null
|
||||
|
||||
refreshRootViewAndProject = ->
|
||||
rootViewState = rootView.serialize()
|
||||
projectState = project.serialize()
|
||||
rootView.remove()
|
||||
project.destroy()
|
||||
window.project = deserialize(projectState)
|
||||
window.rootView = deserialize(rootViewState)
|
||||
rootView.attachToDom()
|
||||
rootViewState = atom.rootView.serialize()
|
||||
atom.project.getState().serializeForPersistence()
|
||||
project2 = atom.replicate().get('project')
|
||||
atom.rootView.remove()
|
||||
atom.project.destroy()
|
||||
atom.project = project2
|
||||
atom.rootView = atom.deserializers.deserialize(rootViewState)
|
||||
atom.rootView.attachToDom()
|
||||
|
||||
describe "when the serialized RootView has an unsaved buffer", ->
|
||||
it "constructs the view with the same panes", ->
|
||||
rootView.attachToDom()
|
||||
rootView.openSync()
|
||||
editor1 = rootView.getActiveView()
|
||||
atom.rootView.attachToDom()
|
||||
atom.rootView.openSync()
|
||||
editor1 = atom.rootView.getActiveView()
|
||||
buffer = editor1.getBuffer()
|
||||
editor1.splitRight()
|
||||
expect(rootView.getActiveView()).toBe rootView.getEditors()[2]
|
||||
expect(atom.rootView.getActiveView()).toBe atom.rootView.getEditors()[2]
|
||||
|
||||
refreshRootViewAndProject()
|
||||
|
||||
expect(rootView.getEditors().length).toBe 2
|
||||
expect(rootView.getActiveView()).toBe rootView.getEditors()[1]
|
||||
expect(rootView.title).toBe "untitled - #{project.getPath()}"
|
||||
expect(atom.rootView.getEditors().length).toBe 2
|
||||
expect(atom.rootView.getActiveView()).toBe atom.rootView.getEditors()[1]
|
||||
expect(atom.rootView.title).toBe "untitled - #{atom.project.getPath()}"
|
||||
|
||||
describe "when there are open editors", ->
|
||||
it "constructs the view with the same panes", ->
|
||||
rootView.attachToDom()
|
||||
pane1 = rootView.getActivePane()
|
||||
atom.rootView.attachToDom()
|
||||
pane1 = atom.rootView.getActivePane()
|
||||
pane2 = pane1.splitRight()
|
||||
pane3 = pane2.splitRight()
|
||||
pane4 = pane2.splitDown()
|
||||
pane2.showItem(project.openSync('b'))
|
||||
pane3.showItem(project.openSync('../sample.js'))
|
||||
pane2.showItem(atom.project.openSync('b'))
|
||||
pane3.showItem(atom.project.openSync('../sample.js'))
|
||||
pane3.activeItem.setCursorScreenPosition([2, 4])
|
||||
pane4.showItem(project.openSync('../sample.txt'))
|
||||
pane4.showItem(atom.project.openSync('../sample.txt'))
|
||||
pane4.activeItem.setCursorScreenPosition([0, 2])
|
||||
pane2.focus()
|
||||
|
||||
refreshRootViewAndProject()
|
||||
|
||||
expect(rootView.getEditors().length).toBe 4
|
||||
editor1 = rootView.panes.find('.row > .pane .editor:eq(0)').view()
|
||||
editor3 = rootView.panes.find('.row > .pane .editor:eq(1)').view()
|
||||
editor2 = rootView.panes.find('.row > .column > .pane .editor:eq(0)').view()
|
||||
editor4 = rootView.panes.find('.row > .column > .pane .editor:eq(1)').view()
|
||||
expect(atom.rootView.getEditors().length).toBe 4
|
||||
editor1 = atom.rootView.panes.find('.row > .pane .editor:eq(0)').view()
|
||||
editor3 = atom.rootView.panes.find('.row > .pane .editor:eq(1)').view()
|
||||
editor2 = atom.rootView.panes.find('.row > .column > .pane .editor:eq(0)').view()
|
||||
editor4 = atom.rootView.panes.find('.row > .column > .pane .editor:eq(1)').view()
|
||||
|
||||
expect(editor1.getPath()).toBe project.resolve('a')
|
||||
expect(editor2.getPath()).toBe project.resolve('b')
|
||||
expect(editor3.getPath()).toBe project.resolve('../sample.js')
|
||||
expect(editor1.getPath()).toBe atom.project.resolve('a')
|
||||
expect(editor2.getPath()).toBe atom.project.resolve('b')
|
||||
expect(editor3.getPath()).toBe atom.project.resolve('../sample.js')
|
||||
expect(editor3.getCursorScreenPosition()).toEqual [2, 4]
|
||||
expect(editor4.getPath()).toBe project.resolve('../sample.txt')
|
||||
expect(editor4.getPath()).toBe atom.project.resolve('../sample.txt')
|
||||
expect(editor4.getCursorScreenPosition()).toEqual [0, 2]
|
||||
|
||||
# ensure adjust pane dimensions is called
|
||||
@@ -83,184 +84,184 @@ describe "RootView", ->
|
||||
expect(editor3.isFocused).toBeFalsy()
|
||||
expect(editor4.isFocused).toBeFalsy()
|
||||
|
||||
expect(rootView.title).toBe "#{path.basename(editor2.getPath())} - #{project.getPath()}"
|
||||
expect(atom.rootView.title).toBe "#{path.basename(editor2.getPath())} - #{atom.project.getPath()}"
|
||||
|
||||
describe "where there are no open editors", ->
|
||||
it "constructs the view with no open editors", ->
|
||||
rootView.getActivePane().remove()
|
||||
expect(rootView.getEditors().length).toBe 0
|
||||
atom.rootView.getActivePane().remove()
|
||||
expect(atom.rootView.getEditors().length).toBe 0
|
||||
refreshRootViewAndProject()
|
||||
expect(rootView.getEditors().length).toBe 0
|
||||
expect(atom.rootView.getEditors().length).toBe 0
|
||||
|
||||
describe "focus", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
atom.rootView.attachToDom()
|
||||
|
||||
describe "when there is an active view", ->
|
||||
it "hands off focus to the active view", ->
|
||||
editor = rootView.getActiveView()
|
||||
editor.isFocused = false
|
||||
rootView.focus()
|
||||
expect(editor.isFocused).toBeTruthy()
|
||||
editorView = atom.rootView.getActiveView()
|
||||
editorView.isFocused = false
|
||||
atom.rootView.focus()
|
||||
expect(editorView.isFocused).toBeTruthy()
|
||||
|
||||
describe "when there is no active view", ->
|
||||
beforeEach ->
|
||||
rootView.getActivePane().remove()
|
||||
expect(rootView.getActiveView()).toBeUndefined()
|
||||
rootView.attachToDom()
|
||||
atom.rootView.getActivePane().remove()
|
||||
expect(atom.rootView.getActiveView()).toBeUndefined()
|
||||
atom.rootView.attachToDom()
|
||||
expect(document.activeElement).toBe document.body
|
||||
|
||||
describe "when are visible focusable elements (with a -1 tabindex)", ->
|
||||
it "passes focus to the first focusable element", ->
|
||||
focusable1 = $$ -> @div "One", id: 'one', tabindex: -1
|
||||
focusable2 = $$ -> @div "Two", id: 'two', tabindex: -1
|
||||
rootView.horizontal.append(focusable1, focusable2)
|
||||
atom.rootView.horizontal.append(focusable1, focusable2)
|
||||
expect(document.activeElement).toBe document.body
|
||||
|
||||
rootView.focus()
|
||||
atom.rootView.focus()
|
||||
expect(document.activeElement).toBe focusable1[0]
|
||||
|
||||
describe "when there are no visible focusable elements", ->
|
||||
it "surrenders focus to the body", ->
|
||||
focusable = $$ -> @div "One", id: 'one', tabindex: -1
|
||||
rootView.horizontal.append(focusable)
|
||||
atom.rootView.horizontal.append(focusable)
|
||||
focusable.hide()
|
||||
expect(document.activeElement).toBe document.body
|
||||
|
||||
rootView.focus()
|
||||
atom.rootView.focus()
|
||||
expect(document.activeElement).toBe document.body
|
||||
|
||||
describe "keymap wiring", ->
|
||||
commandHandler = null
|
||||
beforeEach ->
|
||||
commandHandler = jasmine.createSpy('commandHandler')
|
||||
rootView.on('foo-command', commandHandler)
|
||||
atom.rootView.on('foo-command', commandHandler)
|
||||
|
||||
atom.keymap.bindKeys('*', 'x': 'foo-command')
|
||||
atom.keymap.bindKeys('name', '*', 'x': 'foo-command')
|
||||
|
||||
describe "when a keydown event is triggered in the RootView", ->
|
||||
it "triggers matching keybindings for that event", ->
|
||||
event = keydownEvent 'x', target: rootView[0]
|
||||
event = keydownEvent 'x', target: atom.rootView[0]
|
||||
|
||||
rootView.trigger(event)
|
||||
atom.rootView.trigger(event)
|
||||
expect(commandHandler).toHaveBeenCalled()
|
||||
|
||||
describe "window title", ->
|
||||
describe "when the project has no path", ->
|
||||
it "sets the title to 'untitled'", ->
|
||||
project.setPath(undefined)
|
||||
expect(rootView.title).toBe 'untitled'
|
||||
atom.project.setPath(undefined)
|
||||
expect(atom.rootView.title).toBe 'untitled'
|
||||
|
||||
describe "when the project has a path", ->
|
||||
beforeEach ->
|
||||
rootView.openSync('b')
|
||||
atom.rootView.openSync('b')
|
||||
|
||||
describe "when there is an active pane item", ->
|
||||
it "sets the title to the pane item's title plus the project path", ->
|
||||
item = rootView.getActivePaneItem()
|
||||
expect(rootView.title).toBe "#{item.getTitle()} - #{project.getPath()}"
|
||||
item = atom.rootView.getActivePaneItem()
|
||||
expect(atom.rootView.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
describe "when the title of the active pane item changes", ->
|
||||
it "updates the window title based on the item's new title", ->
|
||||
editSession = rootView.getActivePaneItem()
|
||||
editSession.buffer.setPath(path.join(temp.dir, 'hi'))
|
||||
expect(rootView.title).toBe "#{editSession.getTitle()} - #{project.getPath()}"
|
||||
editor = atom.rootView.getActivePaneItem()
|
||||
editor.buffer.setPath(path.join(temp.dir, 'hi'))
|
||||
expect(atom.rootView.title).toBe "#{editor.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
describe "when the active pane's item changes", ->
|
||||
it "updates the title to the new item's title plus the project path", ->
|
||||
rootView.getActivePane().showNextItem()
|
||||
item = rootView.getActivePaneItem()
|
||||
expect(rootView.title).toBe "#{item.getTitle()} - #{project.getPath()}"
|
||||
atom.rootView.getActivePane().showNextItem()
|
||||
item = atom.rootView.getActivePaneItem()
|
||||
expect(atom.rootView.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
|
||||
describe "when the last pane item is removed", ->
|
||||
it "updates the title to contain the project's path", ->
|
||||
rootView.getActivePane().remove()
|
||||
expect(rootView.getActivePaneItem()).toBeUndefined()
|
||||
expect(rootView.title).toBe project.getPath()
|
||||
atom.rootView.getActivePane().remove()
|
||||
expect(atom.rootView.getActivePaneItem()).toBeUndefined()
|
||||
expect(atom.rootView.title).toBe atom.project.getPath()
|
||||
|
||||
describe "when an inactive pane's item changes", ->
|
||||
it "does not update the title", ->
|
||||
pane = rootView.getActivePane()
|
||||
pane = atom.rootView.getActivePane()
|
||||
pane.splitRight()
|
||||
initialTitle = rootView.title
|
||||
initialTitle = atom.rootView.title
|
||||
pane.showNextItem()
|
||||
expect(rootView.title).toBe initialTitle
|
||||
expect(atom.rootView.title).toBe initialTitle
|
||||
|
||||
describe "when the root view is deserialized", ->
|
||||
it "updates the title to contain the project's path", ->
|
||||
rootView2 = atom.deserializers.deserialize(rootView.serialize())
|
||||
item = rootView.getActivePaneItem()
|
||||
expect(rootView2.title).toBe "#{item.getTitle()} - #{project.getPath()}"
|
||||
rootView2 = atom.deserializers.deserialize(atom.rootView.serialize())
|
||||
item = atom.rootView.getActivePaneItem()
|
||||
expect(rootView2.title).toBe "#{item.getTitle()} - #{atom.project.getPath()}"
|
||||
rootView2.remove()
|
||||
|
||||
describe "font size adjustment", ->
|
||||
it "increases/decreases font size when increase/decrease-font-size events are triggered", ->
|
||||
fontSizeBefore = atom.config.get('editor.fontSize')
|
||||
rootView.trigger 'window:increase-font-size'
|
||||
atom.rootView.trigger 'window:increase-font-size'
|
||||
expect(atom.config.get('editor.fontSize')).toBe fontSizeBefore + 1
|
||||
rootView.trigger 'window:increase-font-size'
|
||||
atom.rootView.trigger 'window:increase-font-size'
|
||||
expect(atom.config.get('editor.fontSize')).toBe fontSizeBefore + 2
|
||||
rootView.trigger 'window:decrease-font-size'
|
||||
atom.rootView.trigger 'window:decrease-font-size'
|
||||
expect(atom.config.get('editor.fontSize')).toBe fontSizeBefore + 1
|
||||
rootView.trigger 'window:decrease-font-size'
|
||||
atom.rootView.trigger 'window:decrease-font-size'
|
||||
expect(atom.config.get('editor.fontSize')).toBe fontSizeBefore
|
||||
|
||||
it "does not allow the font size to be less than 1", ->
|
||||
atom.config.set("editor.fontSize", 1)
|
||||
rootView.trigger 'window:decrease-font-size'
|
||||
atom.rootView.trigger 'window:decrease-font-size'
|
||||
expect(atom.config.get('editor.fontSize')).toBe 1
|
||||
|
||||
describe ".openSync(filePath, options)", ->
|
||||
describe "when there is no active pane", ->
|
||||
beforeEach ->
|
||||
spyOn(Pane.prototype, 'focus')
|
||||
rootView.getActivePane().remove()
|
||||
expect(rootView.getActivePane()).toBeUndefined()
|
||||
atom.rootView.getActivePane().remove()
|
||||
expect(atom.rootView.getActivePane()).toBeUndefined()
|
||||
|
||||
describe "when called with no path", ->
|
||||
it "creates a empty edit session as an item on a new pane, and focuses the pane", ->
|
||||
editSession = rootView.openSync()
|
||||
expect(rootView.getActivePane().activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBeUndefined()
|
||||
expect(rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
editor = atom.rootView.openSync()
|
||||
expect(atom.rootView.getActivePane().activeItem).toBe editor
|
||||
expect(editor.getPath()).toBeUndefined()
|
||||
expect(atom.rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
|
||||
it "can create multiple empty edit sessions as an item on a new pane", ->
|
||||
editSession = rootView.openSync()
|
||||
editSession2 = rootView.openSync()
|
||||
expect(rootView.getActivePane().getItems().length).toBe 2
|
||||
expect(editSession).not.toBe editSession2
|
||||
editor = atom.rootView.openSync()
|
||||
editor2 = atom.rootView.openSync()
|
||||
expect(atom.rootView.getActivePane().getItems().length).toBe 2
|
||||
expect(editor).not.toBe editor2
|
||||
|
||||
describe "when called with a path", ->
|
||||
it "creates an edit session for the given path as an item on a new pane, and focuses the pane", ->
|
||||
editSession = rootView.openSync('b')
|
||||
expect(rootView.getActivePane().activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
expect(rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
editor = atom.rootView.openSync('b')
|
||||
expect(atom.rootView.getActivePane().activeItem).toBe editor
|
||||
expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
expect(atom.rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
|
||||
describe "when the changeFocus option is false", ->
|
||||
it "does not focus the new pane", ->
|
||||
editSession = rootView.openSync('b', changeFocus: false)
|
||||
expect(rootView.getActivePane().focus).not.toHaveBeenCalled()
|
||||
editor = atom.rootView.openSync('b', changeFocus: false)
|
||||
expect(atom.rootView.getActivePane().focus).not.toHaveBeenCalled()
|
||||
|
||||
describe "when the split option is 'right'", ->
|
||||
it "creates a new pane and opens the file in said pane", ->
|
||||
editSession = rootView.openSync('b', split: 'right')
|
||||
expect(rootView.getActivePane().activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
editor = atom.rootView.openSync('b', split: 'right')
|
||||
expect(atom.rootView.getActivePane().activeItem).toBe editor
|
||||
expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
|
||||
describe "when there is an active pane", ->
|
||||
[activePane, initialItemCount] = []
|
||||
beforeEach ->
|
||||
activePane = rootView.getActivePane()
|
||||
activePane = atom.rootView.getActivePane()
|
||||
spyOn(activePane, 'focus')
|
||||
initialItemCount = activePane.getItems().length
|
||||
|
||||
describe "when called with no path", ->
|
||||
it "opens an edit session with an empty buffer as an item in the active pane and focuses it", ->
|
||||
editSession = rootView.openSync()
|
||||
editor = atom.rootView.openSync()
|
||||
expect(activePane.getItems().length).toBe initialItemCount + 1
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBeUndefined()
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(editor.getPath()).toBeUndefined()
|
||||
expect(activePane.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when called with a path", ->
|
||||
@@ -268,97 +269,97 @@ describe "RootView", ->
|
||||
it "shows the existing edit session in the pane", ->
|
||||
previousEditSession = activePane.activeItem
|
||||
|
||||
editSession = rootView.openSync('b')
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(editSession).not.toBe previousEditSession
|
||||
editor = atom.rootView.openSync('b')
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(editor).not.toBe previousEditSession
|
||||
|
||||
editSession = rootView.openSync(previousEditSession.getPath())
|
||||
expect(editSession).toBe previousEditSession
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
editor = atom.rootView.openSync(previousEditSession.getPath())
|
||||
expect(editor).toBe previousEditSession
|
||||
expect(activePane.activeItem).toBe editor
|
||||
|
||||
expect(activePane.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when the active pane does not have an edit session item for the path being opened", ->
|
||||
it "creates a new edit session for the given path in the active editor", ->
|
||||
editSession = rootView.openSync('b')
|
||||
editor = atom.rootView.openSync('b')
|
||||
expect(activePane.items.length).toBe 2
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(activePane.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when the changeFocus option is false", ->
|
||||
it "does not focus the active pane", ->
|
||||
editSession = rootView.openSync('b', changeFocus: false)
|
||||
editor = atom.rootView.openSync('b', changeFocus: false)
|
||||
expect(activePane.focus).not.toHaveBeenCalled()
|
||||
|
||||
describe "when the split option is 'right'", ->
|
||||
it "creates a new pane and opens the file in said pane", ->
|
||||
pane1 = rootView.getActivePane()
|
||||
pane1 = atom.rootView.getActivePane()
|
||||
|
||||
editSession = rootView.openSync('b', split: 'right')
|
||||
pane2 = rootView.getActivePane()
|
||||
editor = atom.rootView.openSync('b', split: 'right')
|
||||
pane2 = atom.rootView.getActivePane()
|
||||
expect(pane2[0]).not.toBe pane1[0]
|
||||
expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
|
||||
expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(atom.rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
|
||||
editSession = rootView.openSync('file1', split: 'right')
|
||||
pane3 = rootView.getActivePane()
|
||||
editor = atom.rootView.openSync('file1', split: 'right')
|
||||
pane3 = atom.rootView.getActivePane()
|
||||
expect(pane3[0]).toBe pane2[0]
|
||||
expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/file1')
|
||||
expect(editor.getPath()).toBe require.resolve('./fixtures/dir/file1')
|
||||
|
||||
expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(atom.rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
|
||||
describe ".openSingletonSync(filePath, options)", ->
|
||||
describe "when there is an active pane", ->
|
||||
[pane1] = []
|
||||
beforeEach ->
|
||||
spyOn(Pane.prototype, 'focus').andCallFake -> @makeActive()
|
||||
pane1 = rootView.getActivePane()
|
||||
pane1 = atom.rootView.getActivePane()
|
||||
|
||||
it "creates a new pane and reuses the file when already open", ->
|
||||
rootView.openSingletonSync('b', split: 'right')
|
||||
pane2 = rootView.getActivePane()
|
||||
atom.rootView.openSingletonSync('b', split: 'right')
|
||||
pane2 = atom.rootView.getActivePane()
|
||||
expect(pane2[0]).not.toBe pane1[0]
|
||||
expect(pane1.itemForUri('b')).toBeFalsy()
|
||||
expect(pane2.itemForUri('b')).not.toBeFalsy()
|
||||
expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(atom.rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
|
||||
pane1.focus()
|
||||
expect(rootView.getActivePane()[0]).toBe pane1[0]
|
||||
expect(atom.rootView.getActivePane()[0]).toBe pane1[0]
|
||||
|
||||
rootView.openSingletonSync('b', split: 'right')
|
||||
pane3 = rootView.getActivePane()
|
||||
atom.rootView.openSingletonSync('b', split: 'right')
|
||||
pane3 = atom.rootView.getActivePane()
|
||||
expect(pane3[0]).toBe pane2[0]
|
||||
expect(pane1.itemForUri('b')).toBeFalsy()
|
||||
expect(pane2.itemForUri('b')).not.toBeFalsy()
|
||||
expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(atom.rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
|
||||
it "handles split: left by opening to the left pane when necessary", ->
|
||||
rootView.openSingletonSync('b', split: 'right')
|
||||
pane2 = rootView.getActivePane()
|
||||
atom.rootView.openSingletonSync('b', split: 'right')
|
||||
pane2 = atom.rootView.getActivePane()
|
||||
expect(pane2[0]).not.toBe pane1[0]
|
||||
|
||||
rootView.openSingletonSync('file1', split: 'left')
|
||||
atom.rootView.openSingletonSync('file1', split: 'left')
|
||||
|
||||
activePane = rootView.getActivePane()
|
||||
activePane = atom.rootView.getActivePane()
|
||||
expect(activePane[0]).toBe pane1[0]
|
||||
|
||||
expect(pane1.itemForUri('file1')).toBeTruthy()
|
||||
expect(pane2.itemForUri('file1')).toBeFalsy()
|
||||
expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(atom.rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
|
||||
pane2.focus()
|
||||
expect(rootView.getActivePane()[0]).toBe pane2[0]
|
||||
expect(atom.rootView.getActivePane()[0]).toBe pane2[0]
|
||||
|
||||
rootView.openSingletonSync('file1', split: 'left')
|
||||
activePane = rootView.getActivePane()
|
||||
atom.rootView.openSingletonSync('file1', split: 'left')
|
||||
activePane = atom.rootView.getActivePane()
|
||||
expect(activePane[0]).toBe pane1[0]
|
||||
expect(rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
expect(atom.rootView.panes.find('.row .pane').toArray()).toEqual [pane1[0], pane2[0]]
|
||||
|
||||
it "reuses the file when already open", ->
|
||||
rootView.openSync('b')
|
||||
rootView.openSingletonSync('b', split: 'right')
|
||||
expect(rootView.panes.find('.pane').toArray()).toEqual [pane1[0]]
|
||||
atom.rootView.openSync('b')
|
||||
atom.rootView.openSingletonSync('b', split: 'right')
|
||||
expect(atom.rootView.panes.find('.pane').toArray()).toEqual [pane1[0]]
|
||||
|
||||
describe ".open(filePath)", ->
|
||||
beforeEach ->
|
||||
@@ -366,65 +367,65 @@ describe "RootView", ->
|
||||
|
||||
describe "when there is no active pane", ->
|
||||
beforeEach ->
|
||||
rootView.getActivePane().remove()
|
||||
expect(rootView.getActivePane()).toBeUndefined()
|
||||
atom.rootView.getActivePane().remove()
|
||||
expect(atom.rootView.getActivePane()).toBeUndefined()
|
||||
|
||||
describe "when called with no path", ->
|
||||
it "creates a empty edit session as an item on a new pane, and focuses the pane", ->
|
||||
editSession = null
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
rootView.open().then (o) -> editSession = o
|
||||
atom.rootView.open().then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(rootView.getActivePane().activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBeUndefined()
|
||||
expect(rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
expect(atom.rootView.getActivePane().activeItem).toBe editor
|
||||
expect(editor.getPath()).toBeUndefined()
|
||||
expect(atom.rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
|
||||
it "can create multiple empty edit sessions as items on a pane", ->
|
||||
editSession1 = null
|
||||
editSession2 = null
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
|
||||
waitsForPromise ->
|
||||
rootView.open()
|
||||
atom.rootView.open()
|
||||
.then (o) ->
|
||||
editSession1 = o
|
||||
rootView.open()
|
||||
editor1 = o
|
||||
atom.rootView.open()
|
||||
.then (o) ->
|
||||
editSession2 = o
|
||||
editor2 = o
|
||||
|
||||
runs ->
|
||||
expect(rootView.getActivePane().getItems().length).toBe 2
|
||||
expect(editSession1).not.toBe editSession2
|
||||
expect(atom.rootView.getActivePane().getItems().length).toBe 2
|
||||
expect(editor1).not.toBe editor2
|
||||
|
||||
describe "when called with a path", ->
|
||||
it "creates an edit session for the given path as an item on a new pane, and focuses the pane", ->
|
||||
editSession = null
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
rootView.open('b').then (o) -> editSession = o
|
||||
atom.rootView.open('b').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(rootView.getActivePane().activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
expect(rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
expect(atom.rootView.getActivePane().activeItem).toBe editor
|
||||
expect(editor.getPath()).toBe require.resolve('./fixtures/dir/b')
|
||||
expect(atom.rootView.getActivePane().focus).toHaveBeenCalled()
|
||||
|
||||
describe "when there is an active pane", ->
|
||||
[activePane] = []
|
||||
|
||||
beforeEach ->
|
||||
activePane = rootView.getActivePane()
|
||||
activePane = atom.rootView.getActivePane()
|
||||
|
||||
describe "when called with no path", ->
|
||||
it "opens an edit session with an empty buffer as an item in the active pane and focuses it", ->
|
||||
editSession = null
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
rootView.open().then (o) -> editSession = o
|
||||
atom.rootView.open().then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(activePane.getItems().length).toBe 2
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(editSession.getPath()).toBeUndefined()
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(editor.getPath()).toBeUndefined()
|
||||
expect(activePane.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when called with a path", ->
|
||||
@@ -432,39 +433,39 @@ describe "RootView", ->
|
||||
it "shows the existing edit session in the pane", ->
|
||||
previousEditSession = activePane.activeItem
|
||||
|
||||
editSession = null
|
||||
editor = null
|
||||
waitsForPromise ->
|
||||
rootView.open('b').then (o) -> editSession = o
|
||||
atom.rootView.open('b').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(editSession).not.toBe previousEditSession
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(editor).not.toBe previousEditSession
|
||||
|
||||
waitsForPromise ->
|
||||
rootView.open(previousEditSession.getPath()).then (o) -> editSession = o
|
||||
atom.rootView.open(previousEditSession.getPath()).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editSession).toBe previousEditSession
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(editor).toBe previousEditSession
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(activePane.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when the active pane does not have an existing item for the given path", ->
|
||||
it "creates a new edit session for the given path in the active pane", ->
|
||||
editSession = null
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
rootView.open('b').then (o) -> editSession = o
|
||||
atom.rootView.open('b').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(activePane.activeItem).toBe editSession
|
||||
expect(activePane.activeItem).toBe editor
|
||||
expect(activePane.getItems().length).toBe 2
|
||||
expect(activePane.focus).toHaveBeenCalled()
|
||||
|
||||
describe "window:toggle-invisibles event", ->
|
||||
it "shows/hides invisibles in all open and future editors", ->
|
||||
rootView.height(200)
|
||||
rootView.attachToDom()
|
||||
rightEditor = rootView.getActiveView()
|
||||
atom.rootView.height(200)
|
||||
atom.rootView.attachToDom()
|
||||
rightEditor = atom.rootView.getActiveView()
|
||||
rightEditor.setText(" \t ")
|
||||
leftEditor = rightEditor.splitLeft()
|
||||
expect(rightEditor.find(".line:first").text()).toBe " "
|
||||
@@ -472,14 +473,14 @@ describe "RootView", ->
|
||||
|
||||
withInvisiblesShowing = "#{rightEditor.invisibles.space}#{rightEditor.invisibles.tab} #{rightEditor.invisibles.space}#{rightEditor.invisibles.eol}"
|
||||
|
||||
rootView.trigger "window:toggle-invisibles"
|
||||
atom.rootView.trigger "window:toggle-invisibles"
|
||||
expect(rightEditor.find(".line:first").text()).toBe withInvisiblesShowing
|
||||
expect(leftEditor.find(".line:first").text()).toBe withInvisiblesShowing
|
||||
|
||||
lowerLeftEditor = leftEditor.splitDown()
|
||||
expect(lowerLeftEditor.find(".line:first").text()).toBe withInvisiblesShowing
|
||||
|
||||
rootView.trigger "window:toggle-invisibles"
|
||||
atom.rootView.trigger "window:toggle-invisibles"
|
||||
expect(rightEditor.find(".line:first").text()).toBe " "
|
||||
expect(leftEditor.find(".line:first").text()).toBe " "
|
||||
|
||||
@@ -488,7 +489,7 @@ describe "RootView", ->
|
||||
|
||||
describe ".eachEditor(callback)", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
atom.rootView.attachToDom()
|
||||
|
||||
it "invokes the callback for existing editor", ->
|
||||
count = 0
|
||||
@@ -496,9 +497,9 @@ describe "RootView", ->
|
||||
callback = (editor) ->
|
||||
callbackEditor = editor
|
||||
count++
|
||||
rootView.eachEditor(callback)
|
||||
atom.rootView.eachEditor(callback)
|
||||
expect(count).toBe 1
|
||||
expect(callbackEditor).toBe rootView.getActiveView()
|
||||
expect(callbackEditor).toBe atom.rootView.getActiveView()
|
||||
|
||||
it "invokes the callback for new editor", ->
|
||||
count = 0
|
||||
@@ -507,28 +508,28 @@ describe "RootView", ->
|
||||
callbackEditor = editor
|
||||
count++
|
||||
|
||||
rootView.eachEditor(callback)
|
||||
atom.rootView.eachEditor(callback)
|
||||
count = 0
|
||||
callbackEditor = null
|
||||
rootView.getActiveView().splitRight()
|
||||
atom.rootView.getActiveView().splitRight()
|
||||
expect(count).toBe 1
|
||||
expect(callbackEditor).toBe rootView.getActiveView()
|
||||
expect(callbackEditor).toBe atom.rootView.getActiveView()
|
||||
|
||||
it "returns a subscription that can be disabled", ->
|
||||
count = 0
|
||||
callback = (editor) -> count++
|
||||
|
||||
subscription = rootView.eachEditor(callback)
|
||||
subscription = atom.rootView.eachEditor(callback)
|
||||
expect(count).toBe 1
|
||||
rootView.getActiveView().splitRight()
|
||||
atom.rootView.getActiveView().splitRight()
|
||||
expect(count).toBe 2
|
||||
subscription.off()
|
||||
rootView.getActiveView().splitRight()
|
||||
atom.rootView.getActiveView().splitRight()
|
||||
expect(count).toBe 2
|
||||
|
||||
describe ".eachBuffer(callback)", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
atom.rootView.attachToDom()
|
||||
|
||||
it "invokes the callback for existing buffer", ->
|
||||
count = 0
|
||||
@@ -537,9 +538,9 @@ describe "RootView", ->
|
||||
callback = (buffer) ->
|
||||
callbackBuffer = buffer
|
||||
count++
|
||||
rootView.eachBuffer(callback)
|
||||
atom.rootView.eachBuffer(callback)
|
||||
expect(count).toBe 1
|
||||
expect(callbackBuffer).toBe rootView.getActiveView().getBuffer()
|
||||
expect(callbackBuffer).toBe atom.rootView.getActiveView().getBuffer()
|
||||
|
||||
it "invokes the callback for new buffer", ->
|
||||
count = 0
|
||||
@@ -548,9 +549,9 @@ describe "RootView", ->
|
||||
callbackBuffer = buffer
|
||||
count++
|
||||
|
||||
rootView.eachBuffer(callback)
|
||||
atom.rootView.eachBuffer(callback)
|
||||
count = 0
|
||||
callbackBuffer = null
|
||||
rootView.openSync(require.resolve('./fixtures/sample.txt'))
|
||||
atom.rootView.openSync(require.resolve('./fixtures/sample.txt'))
|
||||
expect(count).toBe 1
|
||||
expect(callbackBuffer).toBe rootView.getActiveView().getBuffer()
|
||||
expect(callbackBuffer).toBe atom.rootView.getActiveView().getBuffer()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
EditSession = require '../src/edit-session'
|
||||
Editor = require '../src/editor'
|
||||
|
||||
describe "Selection", ->
|
||||
[buffer, editSession, selection] = []
|
||||
[buffer, editor, selection] = []
|
||||
|
||||
beforeEach ->
|
||||
buffer = project.buildBufferSync('sample.js')
|
||||
editSession = new EditSession(buffer: buffer, tabLength: 2)
|
||||
selection = editSession.getSelection()
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
editor = new Editor(buffer: buffer, tabLength: 2)
|
||||
selection = editor.getSelection()
|
||||
|
||||
afterEach ->
|
||||
buffer.destroy()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{View, $$} = require 'atom'
|
||||
{View, $, $$} = require 'atom'
|
||||
|
||||
describe "SpacePen extensions", ->
|
||||
class TestView extends View
|
||||
@@ -51,3 +51,17 @@ describe "SpacePen extensions", ->
|
||||
it "subscribes to the given event emitter and unsubscribes when unsubscribe is called", ->
|
||||
emitter.trigger "foo"
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
describe "tooltips", ->
|
||||
describe "replaceModifiers", ->
|
||||
replaceModifiers = $.fn.setTooltip.replaceModifiers
|
||||
|
||||
it "replaces single keystroke", ->
|
||||
expect(replaceModifiers('cmd-O')).toEqual '⌘⇧O'
|
||||
expect(replaceModifiers('cmd-shift-up')).toEqual '⌘⇧↑'
|
||||
expect(replaceModifiers('cmd-option-down')).toEqual '⌘⌥↓'
|
||||
expect(replaceModifiers('cmd-option-left')).toEqual '⌘⌥←'
|
||||
expect(replaceModifiers('cmd-option-right')).toEqual '⌘⌥→'
|
||||
|
||||
it "replaces multiple keystroke", ->
|
||||
expect(replaceModifiers('cmd-o ctrl-2')).toEqual '⌘O ⌃2'
|
||||
|
||||
+26
-39
@@ -1,5 +1,5 @@
|
||||
require '../src/window'
|
||||
window.setUpEnvironment('spec')
|
||||
atom.setUpEnvironment('spec')
|
||||
atom.restoreDimensions()
|
||||
|
||||
require '../vendor/jasmine-jquery'
|
||||
@@ -9,7 +9,7 @@ Keymap = require '../src/keymap'
|
||||
Config = require '../src/config'
|
||||
{Point} = require 'telepath'
|
||||
Project = require '../src/project'
|
||||
Editor = require '../src/editor'
|
||||
EditorView = require '../src/editor-view'
|
||||
TokenizedBuffer = require '../src/tokenized-buffer'
|
||||
pathwatcher = require 'pathwatcher'
|
||||
platform = require './spec-helper-platform'
|
||||
@@ -23,7 +23,7 @@ atom.themes.requireStylesheet '../static/jasmine'
|
||||
fixturePackagesPath = path.resolve(__dirname, './fixtures/packages')
|
||||
atom.packages.packageDirPaths.unshift(fixturePackagesPath)
|
||||
atom.keymap.loadBundledKeymaps()
|
||||
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
|
||||
keyBindingsToRestore = atom.keymap.getKeyBindings()
|
||||
|
||||
$(window).on 'core:close', -> window.close()
|
||||
$(window).on 'unload', ->
|
||||
@@ -39,7 +39,9 @@ specPackageName = null
|
||||
specPackagePath = null
|
||||
specProjectPath = null
|
||||
|
||||
if specDirectory = atom.getLoadSettings().specDirectory
|
||||
{specDirectory, resourcePath} = atom.getLoadSettings()
|
||||
|
||||
if specDirectory
|
||||
specPackagePath = path.resolve(specDirectory, '..')
|
||||
try
|
||||
specPackageName = fs.readObjectSync(path.join(specPackagePath, 'package.json'))?.name
|
||||
@@ -47,11 +49,9 @@ if specDirectory = atom.getLoadSettings().specDirectory
|
||||
|
||||
beforeEach ->
|
||||
$.fx.off = true
|
||||
if specProjectPath
|
||||
atom.project = new Project(specProjectPath)
|
||||
else
|
||||
atom.project = new Project(path.join(@specDirectory, 'fixtures'))
|
||||
window.project = atom.project
|
||||
projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures')
|
||||
atom.project = atom.getWindowState().set('project', new Project(path: projectPath))
|
||||
atom.keymap.keyBindings = _.clone(keyBindingsToRestore)
|
||||
|
||||
window.resetTimeouts()
|
||||
atom.packages.packageStates = {}
|
||||
@@ -66,21 +66,15 @@ beforeEach ->
|
||||
resolvePackagePath(packageName)
|
||||
resolvePackagePath = _.bind(spy.originalValue, atom.packages)
|
||||
|
||||
# used to reset keymap after each spec
|
||||
bindingSetsToRestore = _.clone(atom.keymap.bindingSets)
|
||||
bindingSetsByFirstKeystrokeToRestore = _.clone(atom.keymap.bindingSetsByFirstKeystroke)
|
||||
|
||||
# prevent specs from modifying Atom's menus
|
||||
spyOn(atom.menu, 'sendToBrowserProcess')
|
||||
|
||||
# reset config before each spec; don't load or save from/to `config.json`
|
||||
config = new Config
|
||||
resourcePath: window.resourcePath
|
||||
configDirPath: atom.getConfigDirPath()
|
||||
config = new Config({resourcePath, configDirPath: atom.getConfigDirPath()})
|
||||
spyOn(config, 'load')
|
||||
spyOn(config, 'save')
|
||||
config.setDefaults('core', RootView.configDefaults)
|
||||
config.setDefaults('editor', Editor.configDefaults)
|
||||
config.setDefaults('editor', EditorView.configDefaults)
|
||||
config.set "editor.fontFamily", "Courier"
|
||||
config.set "editor.fontSize", 16
|
||||
config.set "editor.autoIndent", false
|
||||
@@ -88,10 +82,9 @@ beforeEach ->
|
||||
"package-with-broken-package-json", "package-with-broken-keymap"]
|
||||
config.save.reset()
|
||||
atom.config = config
|
||||
window.config = config
|
||||
|
||||
# make editor display updates synchronous
|
||||
spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()
|
||||
spyOn(EditorView.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()
|
||||
spyOn(RootView.prototype, 'setTitle').andCallFake (@title) ->
|
||||
spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout
|
||||
spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout
|
||||
@@ -108,19 +101,13 @@ beforeEach ->
|
||||
addCustomMatchers(this)
|
||||
|
||||
afterEach ->
|
||||
atom.keymap.bindingSets = bindingSetsToRestore
|
||||
atom.keymap.bindingSetsByFirstKeystroke = bindingSetsByFirstKeystrokeToRestore
|
||||
atom.deactivatePackages()
|
||||
atom.packages.deactivatePackages()
|
||||
atom.menu.template = []
|
||||
|
||||
window.rootView?.remove?()
|
||||
atom.rootView?.remove?() if atom.rootView isnt window.rootView
|
||||
window.rootView = null
|
||||
atom.rootView?.remove?()
|
||||
atom.rootView = null
|
||||
|
||||
window.project?.destroy?()
|
||||
atom.project?.destroy?() if atom.project isnt window.project
|
||||
window.project = null
|
||||
atom.project?.destroy?()
|
||||
atom.project = null
|
||||
|
||||
$('#jasmine-content').empty() unless window.debugContent
|
||||
@@ -181,8 +168,8 @@ window.keydownEvent = (key, properties={}) ->
|
||||
|
||||
window.mouseEvent = (type, properties) ->
|
||||
if properties.point
|
||||
{point, editor} = properties
|
||||
{top, left} = @pagePixelPositionForPoint(editor, point)
|
||||
{point, editorView} = properties
|
||||
{top, left} = @pagePixelPositionForPoint(editorView, point)
|
||||
properties.pageX = left + 1
|
||||
properties.pageY = top + 1
|
||||
properties.originalEvent ?= {detail: 1}
|
||||
@@ -243,22 +230,22 @@ window.advanceClock = (delta=1) ->
|
||||
|
||||
callback() for callback in callbacks
|
||||
|
||||
window.pagePixelPositionForPoint = (editor, point) ->
|
||||
window.pagePixelPositionForPoint = (editorView, point) ->
|
||||
point = Point.fromObject point
|
||||
top = editor.renderedLines.offset().top + point.row * editor.lineHeight
|
||||
left = editor.renderedLines.offset().left + point.column * editor.charWidth - editor.renderedLines.scrollLeft()
|
||||
top = editorView.renderedLines.offset().top + point.row * editorView.lineHeight
|
||||
left = editorView.renderedLines.offset().left + point.column * editorView.charWidth - editorView.renderedLines.scrollLeft()
|
||||
{ top, left }
|
||||
|
||||
window.tokensText = (tokens) ->
|
||||
_.pluck(tokens, 'value').join('')
|
||||
|
||||
window.setEditorWidthInChars = (editor, widthInChars, charWidth=editor.charWidth) ->
|
||||
editor.width(charWidth * widthInChars + editor.gutter.outerWidth())
|
||||
$(window).trigger 'resize' # update width of editor's on-screen lines
|
||||
window.setEditorWidthInChars = (editorView, widthInChars, charWidth=editorView.charWidth) ->
|
||||
editorView.width(charWidth * widthInChars + editorView.gutter.outerWidth())
|
||||
$(window).trigger 'resize' # update width of editor view's on-screen lines
|
||||
|
||||
window.setEditorHeightInLines = (editor, heightInChars, charHeight=editor.lineHeight) ->
|
||||
editor.height(charHeight * heightInChars + editor.renderedLines.position().top)
|
||||
$(window).trigger 'resize' # update editor's on-screen lines
|
||||
window.setEditorHeightInLines = (editorView, heightInChars, charHeight=editorView.lineHeight) ->
|
||||
editorView.height(charHeight * heightInChars + editorView.renderedLines.position().top)
|
||||
$(window).trigger 'resize' # update editor view's on-screen lines
|
||||
|
||||
$.fn.resultOfTrigger = (type) ->
|
||||
event = $.Event(type)
|
||||
|
||||
+45
-44
@@ -1,54 +1,55 @@
|
||||
measure 'spec suite require time', ->
|
||||
{_, fs, Git} = require 'atom'
|
||||
path = require 'path'
|
||||
require './spec-helper'
|
||||
{_, fs, Git} = require 'atom'
|
||||
path = require 'path'
|
||||
require './spec-helper'
|
||||
|
||||
requireSpecs = (specDirectory, specType) ->
|
||||
for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.coffee$/.test specFilePath
|
||||
require specFilePath
|
||||
requireSpecs = (specDirectory, specType) ->
|
||||
for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.coffee$/.test specFilePath
|
||||
require specFilePath
|
||||
|
||||
# Set spec directory on spec for setting up the project in spec-helper
|
||||
setSpecDirectory(specDirectory)
|
||||
# Set spec directory on spec for setting up the project in spec-helper
|
||||
setSpecDirectory(specDirectory)
|
||||
|
||||
setSpecField = (name, value) ->
|
||||
specs = jasmine.getEnv().currentRunner().specs()
|
||||
return if specs.length is 0
|
||||
for index in [specs.length-1..0]
|
||||
break if specs[index][name]?
|
||||
specs[index][name] = value
|
||||
setSpecField = (name, value) ->
|
||||
specs = jasmine.getEnv().currentRunner().specs()
|
||||
return if specs.length is 0
|
||||
for index in [specs.length-1..0]
|
||||
break if specs[index][name]?
|
||||
specs[index][name] = value
|
||||
|
||||
setSpecType = (specType) ->
|
||||
setSpecField('specType', specType)
|
||||
setSpecType = (specType) ->
|
||||
setSpecField('specType', specType)
|
||||
|
||||
setSpecDirectory = (specDirectory) ->
|
||||
setSpecField('specDirectory', specDirectory)
|
||||
setSpecDirectory = (specDirectory) ->
|
||||
setSpecField('specDirectory', specDirectory)
|
||||
|
||||
runAllSpecs = ->
|
||||
# Only run core specs when resource path is the Atom repository
|
||||
if Git.exists(window.resourcePath)
|
||||
requireSpecs(path.join(window.resourcePath, 'spec'))
|
||||
setSpecType('core')
|
||||
runAllSpecs = ->
|
||||
{resourcePath} = atom.getLoadSettings()
|
||||
# Only run core specs when resource path is the Atom repository
|
||||
if Git.exists(resourcePath)
|
||||
requireSpecs(path.join(resourcePath, 'spec'))
|
||||
setSpecType('core')
|
||||
|
||||
fixturesPackagesPath = path.join(__dirname, 'fixtures', 'packages')
|
||||
packagePaths = atom.getAvailablePackageNames().map (packageName) -> atom.resolvePackagePath(packageName)
|
||||
packagePaths = _.groupBy packagePaths, (packagePath) ->
|
||||
if packagePath.indexOf("#{fixturesPackagesPath}#{path.sep}") is 0
|
||||
'fixtures'
|
||||
else if packagePath.indexOf("#{window.resourcePath}#{path.sep}") is 0
|
||||
'bundled'
|
||||
else
|
||||
'user'
|
||||
fixturesPackagesPath = path.join(__dirname, 'fixtures', 'packages')
|
||||
packagePaths = atom.packages.getAvailablePackageNames().map (packageName) ->
|
||||
atom.packages.resolvePackagePath(packageName)
|
||||
packagePaths = _.groupBy packagePaths, (packagePath) ->
|
||||
if packagePath.indexOf("#{fixturesPackagesPath}#{path.sep}") is 0
|
||||
'fixtures'
|
||||
else if packagePath.indexOf("#{resourcePath}#{path.sep}") is 0
|
||||
'bundled'
|
||||
else
|
||||
'user'
|
||||
|
||||
# Run bundled package specs
|
||||
requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.bundled ? []
|
||||
setSpecType('bundled')
|
||||
# Run bundled package specs
|
||||
requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.bundled ? []
|
||||
setSpecType('bundled')
|
||||
|
||||
# Run user package specs
|
||||
requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.user ? []
|
||||
setSpecType('user')
|
||||
# Run user package specs
|
||||
requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.user ? []
|
||||
setSpecType('user')
|
||||
|
||||
if specDirectory = atom.getLoadSettings().specDirectory
|
||||
requireSpecs(specDirectory)
|
||||
setSpecType('user')
|
||||
else
|
||||
runAllSpecs()
|
||||
if specDirectory = atom.getLoadSettings().specDirectory
|
||||
requireSpecs(specDirectory)
|
||||
setSpecType('user')
|
||||
else
|
||||
runAllSpecs()
|
||||
|
||||
@@ -5,23 +5,23 @@ TextMateGrammar = require '../src/text-mate-grammar'
|
||||
|
||||
describe "the `syntax` global", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-text', sync: true)
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
atom.activatePackage('language-coffee-script', sync: true)
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.activatePackage('language-text', sync: true)
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
atom.packages.activatePackage('language-coffee-script', sync: true)
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
|
||||
describe "serialization", ->
|
||||
it "remembers grammar overrides by path", ->
|
||||
filePath = '/foo/bar/file.js'
|
||||
expect(atom.syntax.selectGrammar(filePath).name).not.toBe 'Ruby'
|
||||
atom.syntax.setGrammarOverrideForPath(filePath, 'source.ruby')
|
||||
syntax2 = deserialize(atom.syntax.serialize())
|
||||
syntax2 = atom.deserializers.deserialize(atom.syntax.serialize())
|
||||
syntax2.addGrammar(grammar) for grammar in atom.syntax.grammars when grammar isnt atom.syntax.nullGrammar
|
||||
expect(syntax2.selectGrammar(filePath).name).toBe 'Ruby'
|
||||
|
||||
describe ".selectGrammar(filePath)", ->
|
||||
it "can use the filePath to load the correct grammar based on the grammar's filetype", ->
|
||||
atom.activatePackage('language-git', sync: true)
|
||||
atom.packages.activatePackage('language-git', sync: true)
|
||||
|
||||
expect(atom.syntax.selectGrammar("file.js").name).toBe "JavaScript" # based on extension (.js)
|
||||
expect(atom.syntax.selectGrammar(path.join(temp.dir, '.git', 'config')).name).toBe "Git Config" # based on end of the path (.git/config)
|
||||
@@ -34,7 +34,7 @@ describe "the `syntax` global", ->
|
||||
expect(atom.syntax.selectGrammar(filePath).name).toBe "Ruby"
|
||||
|
||||
it "uses the number of newlines in the first line regex to determine the number of lines to test against", ->
|
||||
atom.activatePackage('language-property-list', sync: true)
|
||||
atom.packages.activatePackage('language-property-list', sync: true)
|
||||
|
||||
fileContent = "first-line\n<html>"
|
||||
expect(atom.syntax.selectGrammar("dummy.coffee", fileContent).name).toBe "CoffeeScript"
|
||||
|
||||
@@ -10,26 +10,26 @@ describe 'TextBuffer', ->
|
||||
beforeEach ->
|
||||
filePath = require.resolve('./fixtures/sample.js')
|
||||
fileContents = fs.readFileSync(filePath, 'utf8')
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
|
||||
afterEach ->
|
||||
buffer?.release()
|
||||
buffer?.destroy()
|
||||
|
||||
describe 'constructor', ->
|
||||
beforeEach ->
|
||||
buffer.release()
|
||||
buffer.destroy()
|
||||
buffer = null
|
||||
|
||||
describe "when given a path", ->
|
||||
describe "when a file exists for the path", ->
|
||||
it "loads the contents of that file", ->
|
||||
filePath = require.resolve './fixtures/sample.txt'
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
expect(buffer.getText()).toBe fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
it "does not allow the initial state of the buffer to be undone", ->
|
||||
filePath = require.resolve './fixtures/sample.txt'
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
buffer.undo()
|
||||
expect(buffer.getText()).toBe fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
@@ -37,13 +37,13 @@ describe 'TextBuffer', ->
|
||||
it "is modified and is initially empty", ->
|
||||
filePath = "does-not-exist.txt"
|
||||
expect(fs.existsSync(filePath)).toBeFalsy()
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
expect(buffer.isModified()).toBeTruthy()
|
||||
expect(buffer.getText()).toBe ''
|
||||
|
||||
describe "when no path is given", ->
|
||||
it "creates an empty buffer", ->
|
||||
buffer = project.bufferForPathSync(null)
|
||||
buffer = atom.project.bufferForPathSync(null)
|
||||
expect(buffer .getText()).toBe ""
|
||||
|
||||
describe "path-changed event", ->
|
||||
@@ -53,7 +53,7 @@ describe 'TextBuffer', ->
|
||||
filePath = path.join(__dirname, "fixtures", "atom-manipulate-me")
|
||||
newPath = "#{filePath}-i-moved"
|
||||
fs.writeFileSync(filePath, "")
|
||||
bufferToChange = project.bufferForPathSync(filePath)
|
||||
bufferToChange = atom.project.bufferForPathSync(filePath)
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
bufferToChange.on 'path-changed', eventHandler
|
||||
|
||||
@@ -85,7 +85,7 @@ describe 'TextBuffer', ->
|
||||
buffer.release()
|
||||
filePath = temp.openSync('atom').path
|
||||
fs.writeFileSync(filePath, "first")
|
||||
buffer = project.bufferForPathSync(filePath).retain()
|
||||
buffer = atom.project.bufferForPathSync(filePath).retain()
|
||||
|
||||
afterEach ->
|
||||
buffer.release()
|
||||
@@ -156,7 +156,7 @@ describe 'TextBuffer', ->
|
||||
beforeEach ->
|
||||
filePath = path.join(temp.dir, 'atom-file-to-delete.txt')
|
||||
fs.writeFileSync(filePath, 'delete me')
|
||||
bufferToDelete = project.bufferForPathSync(filePath)
|
||||
bufferToDelete = atom.project.bufferForPathSync(filePath)
|
||||
filePath = bufferToDelete.getPath() # symlinks may have been converted
|
||||
|
||||
expect(bufferToDelete.getPath()).toBe filePath
|
||||
@@ -214,7 +214,7 @@ describe 'TextBuffer', ->
|
||||
buffer.release()
|
||||
filePath = path.join(temp.dir, 'atom-tmp-file')
|
||||
fs.writeFileSync(filePath, 'delete me')
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
modifiedHandler = jasmine.createSpy("modifiedHandler")
|
||||
buffer.on 'modified-status-changed', modifiedHandler
|
||||
|
||||
@@ -227,7 +227,7 @@ describe 'TextBuffer', ->
|
||||
filePath = path.join(temp.dir, 'atom-tmp-file')
|
||||
fs.writeFileSync(filePath, '')
|
||||
buffer.release()
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
modifiedHandler = jasmine.createSpy("modifiedHandler")
|
||||
buffer.on 'modified-status-changed', modifiedHandler
|
||||
|
||||
@@ -251,7 +251,7 @@ describe 'TextBuffer', ->
|
||||
filePath = path.join(temp.dir, 'atom-tmp-file')
|
||||
fs.writeFileSync(filePath, '')
|
||||
buffer.release()
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
modifiedHandler = jasmine.createSpy("modifiedHandler")
|
||||
buffer.on 'modified-status-changed', modifiedHandler
|
||||
|
||||
@@ -275,7 +275,7 @@ describe 'TextBuffer', ->
|
||||
fs.removeSync(filePath) if fs.existsSync(filePath)
|
||||
expect(fs.existsSync(filePath)).toBeFalsy()
|
||||
buffer.release()
|
||||
buffer = project.bufferForPathSync(filePath)
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
modifiedHandler = jasmine.createSpy("modifiedHandler")
|
||||
buffer.on 'modified-status-changed', modifiedHandler
|
||||
|
||||
@@ -298,12 +298,12 @@ describe 'TextBuffer', ->
|
||||
|
||||
it "returns false for an empty buffer with no path", ->
|
||||
buffer.release()
|
||||
buffer = project.bufferForPathSync(null)
|
||||
buffer = atom.project.bufferForPathSync(null)
|
||||
expect(buffer.isModified()).toBeFalsy()
|
||||
|
||||
it "returns true for a non-empty buffer with no path", ->
|
||||
buffer.release()
|
||||
buffer = project.bufferForPathSync(null)
|
||||
buffer = atom.project.bufferForPathSync(null)
|
||||
buffer.setText('a')
|
||||
expect(buffer.isModified()).toBeTruthy()
|
||||
buffer.setText('\n')
|
||||
@@ -311,8 +311,8 @@ describe 'TextBuffer', ->
|
||||
|
||||
it "returns false until the buffer is fully loaded", ->
|
||||
buffer.release()
|
||||
filePath = temp.openSync('atom').path
|
||||
buffer = new TextBuffer({project, filePath})
|
||||
buffer = new TextBuffer({filePath: temp.openSync('atom').path})
|
||||
atom.project.addBuffer(buffer)
|
||||
|
||||
expect(buffer.isModified()).toBeFalsy()
|
||||
|
||||
@@ -432,7 +432,7 @@ describe 'TextBuffer', ->
|
||||
expect(event.newText).toBe "foo\nbar"
|
||||
|
||||
it "allows a 'changed' event handler to safely undo the change", ->
|
||||
buffer.one 'changed', -> buffer.undo()
|
||||
buffer.once 'changed', -> buffer.undo()
|
||||
buffer.change([0, 0], "hello")
|
||||
expect(buffer.lineForRow(0)).toBe "var quicksort = function () {"
|
||||
|
||||
@@ -466,7 +466,7 @@ describe 'TextBuffer', ->
|
||||
beforeEach ->
|
||||
filePath = path.join(temp.dir, 'temp.txt')
|
||||
fs.writeFileSync(filePath, "")
|
||||
saveBuffer = project.bufferForPathSync(filePath)
|
||||
saveBuffer = atom.project.bufferForPathSync(filePath)
|
||||
saveBuffer.setText("blah")
|
||||
|
||||
it "saves the contents of the buffer to the path", ->
|
||||
@@ -500,7 +500,7 @@ describe 'TextBuffer', ->
|
||||
|
||||
describe "when the buffer has no path", ->
|
||||
it "throws an exception", ->
|
||||
saveBuffer = project.bufferForPathSync(null)
|
||||
saveBuffer = atom.project.bufferForPathSync(null)
|
||||
saveBuffer.setText "hi"
|
||||
expect(-> saveBuffer.save()).toThrow()
|
||||
|
||||
@@ -524,7 +524,7 @@ describe 'TextBuffer', ->
|
||||
filePath = path.join(temp.dir, 'temp.txt')
|
||||
fs.removeSync filePath if fs.existsSync(filePath)
|
||||
|
||||
saveAsBuffer = project.bufferForPathSync(null).retain()
|
||||
saveAsBuffer = atom.project.bufferForPathSync(null).retain()
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
saveAsBuffer.on 'path-changed', eventHandler
|
||||
|
||||
@@ -539,7 +539,7 @@ describe 'TextBuffer', ->
|
||||
newPath = path.join(temp.dir, 'new.txt')
|
||||
fs.writeFileSync(originalPath, "")
|
||||
|
||||
saveAsBuffer = project.bufferForPathSync(originalPath).retain()
|
||||
saveAsBuffer = atom.project.bufferForPathSync(originalPath).retain()
|
||||
changeHandler = jasmine.createSpy('changeHandler')
|
||||
saveAsBuffer.on 'changed', changeHandler
|
||||
saveAsBuffer.saveAs(newPath)
|
||||
@@ -554,35 +554,6 @@ describe 'TextBuffer', ->
|
||||
waitsFor ->
|
||||
changeHandler.callCount > 0
|
||||
|
||||
describe ".getRelativePath()", ->
|
||||
[filePath, newPath, bufferToChange, eventHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
filePath = path.join(__dirname, "fixtures", "atom-manipulate-me")
|
||||
newPath = "#{filePath}-i-moved"
|
||||
fs.writeFileSync(filePath, "")
|
||||
bufferToChange = project.bufferForPathSync(filePath)
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
bufferToChange.on 'path-changed', eventHandler
|
||||
|
||||
afterEach ->
|
||||
bufferToChange.destroy()
|
||||
fs.removeSync(filePath) if fs.existsSync(filePath)
|
||||
fs.removeSync(newPath) if fs.existsSync(newPath)
|
||||
|
||||
it "updates when the text buffer's file is moved", ->
|
||||
expect(bufferToChange.getRelativePath()).toBe('atom-manipulate-me')
|
||||
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
eventHandler.reset()
|
||||
fs.moveSync(filePath, newPath)
|
||||
|
||||
waitsFor "buffer path change", ->
|
||||
eventHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(bufferToChange.getRelativePath()).toBe('atom-manipulate-me-i-moved')
|
||||
|
||||
describe ".getTextInRange(range)", ->
|
||||
describe "when range is empty", ->
|
||||
it "returns an empty string", ->
|
||||
@@ -926,22 +897,28 @@ describe 'TextBuffer', ->
|
||||
expect(buffer.getText()).toBe "\ninitialtexthello\n1\n2\n"
|
||||
|
||||
describe "serialization", ->
|
||||
buffer2 = null
|
||||
[buffer2, project2] = []
|
||||
|
||||
beforeEach ->
|
||||
buffer.destroy()
|
||||
|
||||
filePath = temp.openSync('atom').path
|
||||
fs.writeFileSync(filePath, "words")
|
||||
buffer = atom.project.bufferForPathSync(filePath)
|
||||
|
||||
afterEach ->
|
||||
buffer2?.release()
|
||||
project2?.destroy()
|
||||
|
||||
describe "when the serialized buffer had no unsaved changes", ->
|
||||
it "loads the current contents of the file at the serialized path", ->
|
||||
expect(buffer.isModified()).toBeFalsy()
|
||||
|
||||
state = buffer.serialize()
|
||||
state.get('text').insertTextAtPoint([0, 0], 'simulate divergence of on-disk contents from serialized contents')
|
||||
project2 = atom.replicate().get('project')
|
||||
buffer2 = project2.getBuffers()[0]
|
||||
|
||||
buffer2 = deserialize(state, {project})
|
||||
|
||||
waitsFor ->
|
||||
buffer2.cachedDiskContents
|
||||
waitsForPromise ->
|
||||
buffer2.load()
|
||||
|
||||
runs ->
|
||||
expect(buffer2.isModified()).toBeFalsy()
|
||||
@@ -951,18 +928,11 @@ describe 'TextBuffer', ->
|
||||
describe "when the serialized buffer had unsaved changes", ->
|
||||
describe "when the disk contents were changed since serialization", ->
|
||||
it "loads the disk contents instead of the previous unsaved state", ->
|
||||
buffer.release()
|
||||
|
||||
filePath = temp.openSync('atom').path
|
||||
fs.writeFileSync(filePath, "words")
|
||||
{buffer} = project.openSync(filePath)
|
||||
buffer.setText("BUFFER CHANGE")
|
||||
|
||||
state = buffer.serialize()
|
||||
expect(state.getObject('text')).toBe 'BUFFER CHANGE'
|
||||
fs.writeFileSync(filePath, "DISK CHANGE")
|
||||
|
||||
buffer2 = deserialize(state, {project})
|
||||
project2 = atom.replicate().get('project')
|
||||
buffer2 = project2.getBuffers()[0]
|
||||
|
||||
waitsFor ->
|
||||
buffer2.cachedDiskContents
|
||||
@@ -976,14 +946,14 @@ describe 'TextBuffer', ->
|
||||
it "restores the previous unsaved state of the buffer", ->
|
||||
previousText = buffer.getText()
|
||||
buffer.setText("abc")
|
||||
buffer.retain()
|
||||
|
||||
state = buffer.serialize()
|
||||
expect(state.getObject('text')).toBe 'abc'
|
||||
buffer.getState().serializeForPersistence()
|
||||
project2 = atom.replicate().get('project')
|
||||
buffer2 = project2.getBuffers()[0]
|
||||
|
||||
buffer2 = deserialize(state, {project})
|
||||
|
||||
waitsFor ->
|
||||
buffer2.cachedDiskContents
|
||||
waitsForPromise ->
|
||||
buffer2.load()
|
||||
|
||||
runs ->
|
||||
expect(buffer2.getPath()).toBe(buffer.getPath())
|
||||
@@ -996,13 +966,13 @@ describe 'TextBuffer', ->
|
||||
it "restores the previous unsaved state of the buffer", ->
|
||||
buffer.release()
|
||||
|
||||
buffer = project.bufferForPathSync()
|
||||
buffer = atom.project.bufferForPathSync()
|
||||
buffer.setText("abc")
|
||||
|
||||
state = buffer.serialize()
|
||||
state = buffer.getState().clone()
|
||||
expect(state.get('path')).toBeUndefined()
|
||||
expect(state.getObject('text')).toBe 'abc'
|
||||
|
||||
buffer2 = deserialize(state)
|
||||
buffer2 = atom.project.addBuffer(new TextBuffer(state))
|
||||
expect(buffer2.getPath()).toBeUndefined()
|
||||
expect(buffer2.getText()).toBe("abc")
|
||||
|
||||
@@ -6,13 +6,13 @@ describe "TextMateGrammar", ->
|
||||
grammar = null
|
||||
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-text', sync: true)
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
atom.activatePackage('language-coffee-script', sync: true)
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.activatePackage('language-html', sync: true)
|
||||
atom.activatePackage('language-php', sync: true)
|
||||
atom.activatePackage('language-python', sync: true)
|
||||
atom.packages.activatePackage('language-text', sync: true)
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
atom.packages.activatePackage('language-coffee-script', sync: true)
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.activatePackage('language-html', sync: true)
|
||||
atom.packages.activatePackage('language-php', sync: true)
|
||||
atom.packages.activatePackage('language-python', sync: true)
|
||||
grammar = atom.syntax.selectGrammar("hello.coffee")
|
||||
|
||||
describe "@loadSync(path)", ->
|
||||
@@ -211,8 +211,8 @@ describe "TextMateGrammar", ->
|
||||
describe "when the pattern includes rules from another grammar", ->
|
||||
describe "when a grammar matching the desired scope is available", ->
|
||||
it "parses tokens inside the begin/end patterns based on the included grammar's rules", ->
|
||||
atom.activatePackage('language-html', sync: true)
|
||||
atom.activatePackage('language-ruby-on-rails', sync: true)
|
||||
atom.packages.activatePackage('language-html', sync: true)
|
||||
atom.packages.activatePackage('language-ruby-on-rails', sync: true)
|
||||
|
||||
grammar = atom.syntax.grammarForScopeName('text.html.ruby')
|
||||
{tokens} = grammar.tokenizeLine("<div class='name'><%= User.find(2).full_name %></div>")
|
||||
@@ -242,8 +242,8 @@ describe "TextMateGrammar", ->
|
||||
expect(tokens[22]).toEqual value: '>', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.end.html"]
|
||||
|
||||
it "updates the grammar if the included grammar is updated later", ->
|
||||
atom.activatePackage('language-html', sync: true)
|
||||
atom.activatePackage('language-ruby-on-rails', sync: true)
|
||||
atom.packages.activatePackage('language-html', sync: true)
|
||||
atom.packages.activatePackage('language-ruby-on-rails', sync: true)
|
||||
|
||||
grammar = atom.syntax.selectGrammar('foo.html.erb')
|
||||
grammarUpdatedHandler = jasmine.createSpy("grammarUpdatedHandler")
|
||||
@@ -252,7 +252,7 @@ describe "TextMateGrammar", ->
|
||||
{tokens} = grammar.tokenizeLine("<div class='name'><% <<-SQL select * from users;")
|
||||
expect(tokens[12].value).toBe " select * from users;"
|
||||
|
||||
atom.activatePackage('language-sql', sync: true)
|
||||
atom.packages.activatePackage('language-sql', sync: true)
|
||||
expect(grammarUpdatedHandler).toHaveBeenCalled()
|
||||
{tokens} = grammar.tokenizeLine("<div class='name'><% <<-SQL select * from users;")
|
||||
expect(tokens[12].value).toBe " "
|
||||
@@ -260,8 +260,8 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "when a grammar matching the desired scope is unavailable", ->
|
||||
it "updates the grammar if a matching grammar is added later", ->
|
||||
atom.deactivatePackage('language-html')
|
||||
atom.activatePackage('language-ruby-on-rails', sync: true)
|
||||
atom.packages.deactivatePackage('language-html')
|
||||
atom.packages.activatePackage('language-ruby-on-rails', sync: true)
|
||||
|
||||
grammar = atom.syntax.grammarForScopeName('text.html.ruby')
|
||||
{tokens} = grammar.tokenizeLine("<div class='name'><%= User.find(2).full_name %></div>")
|
||||
@@ -270,7 +270,7 @@ describe "TextMateGrammar", ->
|
||||
expect(tokens[2]).toEqual value: ' ', scopes: ["text.html.ruby","source.ruby.rails.embedded.html"]
|
||||
expect(tokens[3]).toEqual value: 'User', scopes: ["text.html.ruby","source.ruby.rails.embedded.html","support.class.ruby"]
|
||||
|
||||
atom.activatePackage('language-html', sync: true)
|
||||
atom.packages.activatePackage('language-html', sync: true)
|
||||
{tokens} = grammar.tokenizeLine("<div class='name'><%= User.find(2).full_name %></div>")
|
||||
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
|
||||
expect(tokens[1]).toEqual value: 'div', scopes: ["text.html.ruby","meta.tag.block.any.html","entity.name.tag.block.any.html"]
|
||||
@@ -314,7 +314,7 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "when inside a C block", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-c', sync: true)
|
||||
atom.packages.activatePackage('language-c', sync: true)
|
||||
|
||||
it "correctly parses a method. (regression)", ->
|
||||
grammar = atom.syntax.selectGrammar("hello.c")
|
||||
@@ -330,7 +330,7 @@ describe "TextMateGrammar", ->
|
||||
describe "when the grammar can infinitely loop over a line", ->
|
||||
it "aborts tokenization", ->
|
||||
spyOn(console, 'error')
|
||||
atom.activatePackage("package-with-infinite-loop-grammar")
|
||||
atom.packages.activatePackage("package-with-infinite-loop-grammar")
|
||||
grammar = atom.syntax.selectGrammar("something.package-with-infinite-loop-grammar")
|
||||
{tokens} = grammar.tokenizeLine("abc")
|
||||
expect(tokens[0].value).toBe "a"
|
||||
@@ -339,7 +339,7 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "when a grammar has a pattern that has back references in the match value", ->
|
||||
it "does not special handle the back references and instead allows oniguruma to resolve them", ->
|
||||
atom.activatePackage('language-sass', sync: true)
|
||||
atom.packages.activatePackage('language-sass', sync: true)
|
||||
grammar = atom.syntax.selectGrammar("style.scss")
|
||||
{tokens} = grammar.tokenizeLine("@mixin x() { -moz-selector: whatever; }")
|
||||
expect(tokens[9]).toEqual value: "-moz-selector", scopes: ["source.css.scss", "meta.property-list.scss", "meta.property-name.scss"]
|
||||
@@ -428,14 +428,14 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "when the grammar's pattern name has a group number in it", ->
|
||||
it "replaces the group number with the matched captured text", ->
|
||||
atom.activatePackage('language-hyperlink', sync: true)
|
||||
atom.packages.activatePackage('language-hyperlink', sync: true)
|
||||
grammar = atom.syntax.grammarForScopeName("text.hyperlink")
|
||||
{tokens} = grammar.tokenizeLine("https://github.com")
|
||||
expect(tokens[0].scopes).toEqual ["text.hyperlink", "markup.underline.link.https.hyperlink"]
|
||||
|
||||
describe "when the grammar has an injection selector", ->
|
||||
it "includes the grammar's patterns when the selector matches the current scope in other grammars", ->
|
||||
atom.activatePackage('language-hyperlink', sync: true)
|
||||
atom.packages.activatePackage('language-hyperlink', sync: true)
|
||||
grammar = atom.syntax.selectGrammar("text.js")
|
||||
{tokens} = grammar.tokenizeLine("var i; // http://github.com")
|
||||
|
||||
@@ -447,25 +447,25 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "when the grammar is added", ->
|
||||
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
|
||||
editSession = project.openSync('sample.js')
|
||||
editSession.setText("// http://github.com")
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.setText("// http://github.com")
|
||||
|
||||
{tokens} = editSession.lineForScreenRow(0)
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " http://github.com"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
atom.activatePackage('language-hyperlink', sync: true)
|
||||
atom.packages.activatePackage('language-hyperlink', sync: true)
|
||||
|
||||
{tokens} = editSession.lineForScreenRow(0)
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[2].value).toBe "http://github.com"
|
||||
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
|
||||
|
||||
describe "when the grammar is updated", ->
|
||||
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
|
||||
editSession = project.openSync('sample.js')
|
||||
editSession.setText("// SELECT * FROM OCTOCATS")
|
||||
editor = atom.project.openSync('sample.js')
|
||||
editor.setText("// SELECT * FROM OCTOCATS")
|
||||
|
||||
{tokens} = editSession.lineForScreenRow(0)
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
@@ -477,13 +477,13 @@ describe "TextMateGrammar", ->
|
||||
patterns: [ { include: "source.sql" } ]
|
||||
))
|
||||
|
||||
{tokens} = editSession.lineForScreenRow(0)
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
atom.activatePackage('language-sql', sync: true)
|
||||
atom.packages.activatePackage('language-sql', sync: true)
|
||||
|
||||
{tokens} = editSession.lineForScreenRow(0)
|
||||
{tokens} = editor.lineForScreenRow(0)
|
||||
expect(tokens[2].value).toBe "SELECT"
|
||||
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]
|
||||
|
||||
@@ -514,7 +514,7 @@ describe "TextMateGrammar", ->
|
||||
lines = null
|
||||
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-todo', sync: true)
|
||||
atom.packages.activatePackage('language-todo', sync: true)
|
||||
grammar = atom.syntax.selectGrammar('main.rb')
|
||||
lines = grammar.tokenizeLines "# TODO be nicer"
|
||||
|
||||
@@ -528,7 +528,7 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "Git commit messages", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-git', sync: true)
|
||||
atom.packages.activatePackage('language-git', sync: true)
|
||||
grammar = atom.syntax.selectGrammar('COMMIT_EDITMSG')
|
||||
lines = grammar.tokenizeLines """
|
||||
longggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
@@ -547,7 +547,7 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "C++", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-c', sync: true)
|
||||
atom.packages.activatePackage('language-c', sync: true)
|
||||
grammar = atom.syntax.selectGrammar('includes.cc')
|
||||
lines = grammar.tokenizeLines """
|
||||
#include "a.h"
|
||||
@@ -585,8 +585,8 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "Objective-C", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-c', sync: true)
|
||||
atom.activatePackage('language-objective-c', sync: true)
|
||||
atom.packages.activatePackage('language-c', sync: true)
|
||||
atom.packages.activatePackage('language-objective-c', sync: true)
|
||||
grammar = atom.syntax.selectGrammar('function.mm')
|
||||
lines = grammar.tokenizeLines """
|
||||
void test() {
|
||||
@@ -612,7 +612,7 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "Java", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-java', sync: true)
|
||||
atom.packages.activatePackage('language-java', sync: true)
|
||||
grammar = atom.syntax.selectGrammar('Function.java')
|
||||
|
||||
it "correctly parses single line comments", ->
|
||||
@@ -664,7 +664,7 @@ describe "TextMateGrammar", ->
|
||||
|
||||
describe "when the line contains unicode characters", ->
|
||||
it "correctly parses tokens starting after them", ->
|
||||
atom.activatePackage('language-json', sync: true)
|
||||
atom.packages.activatePackage('language-json', sync: true)
|
||||
grammar = atom.syntax.selectGrammar('package.json')
|
||||
{tokens} = grammar.tokenizeLine '{"\u2026": 1}'
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "requireStylesheet(path)", ->
|
||||
it "synchronously loads css at the given path and installs a style tag for it in the head", ->
|
||||
cssPath = project.resolve('css.css')
|
||||
cssPath = atom.project.resolve('css.css')
|
||||
lengthBefore = $('head style').length
|
||||
|
||||
themeManager.requireStylesheet(cssPath)
|
||||
@@ -97,7 +97,7 @@ describe "ThemeManager", ->
|
||||
$('head style[id*="css.css"]').remove()
|
||||
|
||||
it "synchronously loads and parses less files at the given path and installs a style tag for it in the head", ->
|
||||
lessPath = project.resolve('sample.less')
|
||||
lessPath = atom.project.resolve('sample.less')
|
||||
lengthBefore = $('head style').length
|
||||
themeManager.requireStylesheet(lessPath)
|
||||
expect($('head style').length).toBe lengthBefore + 1
|
||||
@@ -121,9 +121,9 @@ describe "ThemeManager", ->
|
||||
|
||||
it "supports requiring css and less stylesheets without an explicit extension", ->
|
||||
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'css')
|
||||
expect($('head style[id*="css.css"]').attr('id')).toBe themeManager.stringToId(project.resolve('css.css'))
|
||||
expect($('head style[id*="css.css"]').attr('id')).toBe themeManager.stringToId(atom.project.resolve('css.css'))
|
||||
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
|
||||
expect($('head style[id*="sample.less"]').attr('id')).toBe themeManager.stringToId(project.resolve('sample.less'))
|
||||
expect($('head style[id*="sample.less"]').attr('id')).toBe themeManager.stringToId(atom.project.resolve('sample.less'))
|
||||
|
||||
$('head style[id*="css.css"]').remove()
|
||||
$('head style[id*="sample.less"]').remove()
|
||||
@@ -140,16 +140,16 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.append $$ -> @div class: 'editor'
|
||||
rootView.attachToDom()
|
||||
atom.rootView = new RootView
|
||||
atom.rootView.append $$ -> @div class: 'editor'
|
||||
atom.rootView.attachToDom()
|
||||
themeManager.activateThemes()
|
||||
|
||||
it "loads the correct values from the theme's ui-variables file", ->
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables'])
|
||||
|
||||
# an override loaded in the base css
|
||||
expect(rootView.css("background-color")).toBe "rgb(0, 0, 255)"
|
||||
expect(atom.rootView.css("background-color")).toBe "rgb(0, 0, 255)"
|
||||
|
||||
# from within the theme itself
|
||||
expect($(".editor").css("padding-top")).toBe "150px"
|
||||
|
||||
@@ -5,7 +5,7 @@ describe "TokenizedBuffer", ->
|
||||
[tokenizedBuffer, buffer, changeHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
# enable async tokenization
|
||||
TokenizedBuffer.prototype.chunkSize = 5
|
||||
jasmine.unspy(TokenizedBuffer.prototype, 'tokenizeInBackground')
|
||||
@@ -20,15 +20,15 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "@deserialize(state)", ->
|
||||
it "constructs a tokenized buffer with the same buffer and tabLength setting", ->
|
||||
buffer = project.bufferForPathSync('sample.js')
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer1 = new TokenizedBuffer(buffer: buffer, tabLength: 4)
|
||||
tokenizedBuffer2 = deserialize(tokenizedBuffer1.serialize())
|
||||
tokenizedBuffer2 = atom.deserializers.deserialize(tokenizedBuffer1.serialize())
|
||||
expect(tokenizedBuffer2.buffer).toBe tokenizedBuffer1.buffer
|
||||
expect(tokenizedBuffer2.getTabLength()).toBe tokenizedBuffer1.getTabLength()
|
||||
|
||||
describe "when the buffer is destroyed", ->
|
||||
beforeEach ->
|
||||
buffer = project.bufferForPathSync('sample.js')
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
startTokenizing(tokenizedBuffer)
|
||||
|
||||
@@ -40,7 +40,7 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when the buffer contains soft-tabs", ->
|
||||
beforeEach ->
|
||||
buffer = project.bufferForPathSync('sample.js')
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
startTokenizing(tokenizedBuffer)
|
||||
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
|
||||
@@ -319,8 +319,8 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when the buffer contains hard-tabs", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-coffee-script', sync: true)
|
||||
buffer = project.bufferForPathSync('sample-with-tabs.coffee')
|
||||
atom.packages.activatePackage('language-coffee-script', sync: true)
|
||||
buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
startTokenizing(tokenizedBuffer)
|
||||
|
||||
@@ -349,8 +349,8 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when the buffer contains surrogate pairs", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
buffer = project.buildBufferSync 'sample-with-pairs.js'
|
||||
atom.packages.activatePackage('language-javascript', sync: true)
|
||||
buffer = atom.project.bufferForPathSync 'sample-with-pairs.js'
|
||||
buffer.setText """
|
||||
'abc\uD835\uDF97def'
|
||||
//\uD835\uDF97xyz
|
||||
@@ -387,10 +387,10 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when the grammar is updated because a grammar it includes is activated", ->
|
||||
it "retokenizes the buffer", ->
|
||||
atom.activatePackage('language-ruby-on-rails', sync: true)
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
atom.packages.activatePackage('language-ruby-on-rails', sync: true)
|
||||
atom.packages.activatePackage('language-ruby', sync: true)
|
||||
|
||||
buffer = project.bufferForPathSync()
|
||||
buffer = atom.project.bufferForPathSync()
|
||||
buffer.setText "<div class='name'><%= User.find(2).full_name %></div>"
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
tokenizedBuffer.setGrammar(atom.syntax.selectGrammar('test.erb'))
|
||||
@@ -399,7 +399,7 @@ describe "TokenizedBuffer", ->
|
||||
{tokens} = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(tokens[0]).toEqual value: "<div class='name'>", scopes: ["text.html.ruby"]
|
||||
|
||||
atom.activatePackage('language-html', sync: true)
|
||||
atom.packages.activatePackage('language-html', sync: true)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
{tokens} = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
|
||||
@@ -410,7 +410,7 @@ describe "TokenizedBuffer", ->
|
||||
buffer.release()
|
||||
|
||||
it "returns the correct token (regression)", ->
|
||||
buffer = project.bufferForPathSync('sample.js')
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
expect(tokenizedBuffer.tokenForPosition([1,0]).scopes).toEqual ["source.js"]
|
||||
@@ -419,7 +419,7 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe ".bufferRangeForScopeAtPosition(selector, position)", ->
|
||||
beforeEach ->
|
||||
buffer = project.bufferForPathSync('sample.js')
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
|
||||
+26
-26
@@ -8,11 +8,11 @@ describe "Window", ->
|
||||
beforeEach ->
|
||||
spyOn(atom, 'hide')
|
||||
atom.getLoadSettings() # Causes atom.loadSettings to be initialized
|
||||
atom.loadSettings.initialPath = project.getPath()
|
||||
project.destroy()
|
||||
atom.loadSettings.initialPath = atom.project.getPath()
|
||||
atom.project.destroy()
|
||||
windowEventHandler = new WindowEventHandler()
|
||||
window.deserializeEditorWindow()
|
||||
projectPath = project.getPath()
|
||||
atom.deserializeEditorWindow()
|
||||
projectPath = atom.project.getPath()
|
||||
|
||||
afterEach ->
|
||||
windowEventHandler.unsubscribe()
|
||||
@@ -59,49 +59,49 @@ describe "Window", ->
|
||||
|
||||
describe "when pane items are are modified", ->
|
||||
it "prompts user to save and and calls rootView.confirmClose", ->
|
||||
spyOn(rootView, 'confirmClose').andCallThrough()
|
||||
spyOn(atom, "confirmSync").andReturn(2)
|
||||
editSession = rootView.openSync("sample.js")
|
||||
editSession.insertText("I look different, I feel different.")
|
||||
spyOn(atom.rootView, 'confirmClose').andCallThrough()
|
||||
spyOn(atom, "confirm").andReturn(2)
|
||||
editor = atom.rootView.openSync("sample.js")
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(rootView.confirmClose).toHaveBeenCalled()
|
||||
expect(atom.confirmSync).toHaveBeenCalled()
|
||||
expect(atom.rootView.confirmClose).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
it "prompts user to save and handler returns true if don't save", ->
|
||||
spyOn(atom, "confirmSync").andReturn(2)
|
||||
editSession = rootView.openSync("sample.js")
|
||||
editSession.insertText("I look different, I feel different.")
|
||||
spyOn(atom, "confirm").andReturn(2)
|
||||
editor = atom.rootView.openSync("sample.js")
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.confirmSync).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
it "prompts user to save and handler returns false if dialog is canceled", ->
|
||||
spyOn(atom, "confirmSync").andReturn(1)
|
||||
editSession = rootView.openSync("sample.js")
|
||||
editSession.insertText("I look different, I feel different.")
|
||||
spyOn(atom, "confirm").andReturn(1)
|
||||
editor = atom.rootView.openSync("sample.js")
|
||||
editor.insertText("I look different, I feel different.")
|
||||
$(window).trigger(beforeUnloadEvent)
|
||||
expect(atom.confirmSync).toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
describe ".unloadEditorWindow()", ->
|
||||
it "saves the serialized state of the window so it can be deserialized after reload", ->
|
||||
rootViewState = rootView.serialize()
|
||||
rootViewState = atom.rootView.serialize()
|
||||
syntaxState = atom.syntax.serialize()
|
||||
|
||||
window.unloadEditorWindow()
|
||||
atom.unloadEditorWindow()
|
||||
|
||||
expect(atom.getWindowState().getObject('rootView')).toEqual rootViewState.toObject()
|
||||
expect(atom.getWindowState().getObject('syntax')).toEqual syntaxState
|
||||
expect(atom.saveWindowState).toHaveBeenCalled()
|
||||
|
||||
it "unsubscribes from all buffers", ->
|
||||
rootView.openSync('sample.js')
|
||||
buffer = rootView.getActivePaneItem().buffer
|
||||
pane = rootView.getActivePane()
|
||||
atom.rootView.openSync('sample.js')
|
||||
buffer = atom.rootView.getActivePaneItem().buffer
|
||||
pane = atom.rootView.getActivePane()
|
||||
pane.splitRight(pane.copyActiveItem())
|
||||
expect(window.rootView.find('.editor').length).toBe 2
|
||||
expect(atom.rootView.find('.editor').length).toBe 2
|
||||
|
||||
window.unloadEditorWindow()
|
||||
atom.unloadEditorWindow()
|
||||
|
||||
expect(buffer.subscriptionCount()).toBe 0
|
||||
expect(buffer.getSubscriptionCount()).toBe 0
|
||||
|
||||
describe "drag and drop", ->
|
||||
buildDragEvent = (type, files) ->
|
||||
|
||||
@@ -212,18 +212,18 @@ class AtomPackage extends Package
|
||||
|
||||
registerDeferredDeserializers: ->
|
||||
for deserializerName in @metadata.deferredDeserializers ? []
|
||||
registerDeferredDeserializer deserializerName, =>
|
||||
atom.deserializers.addDeferred deserializerName, =>
|
||||
@activateStylesheets()
|
||||
@requireMainModule()
|
||||
|
||||
subscribeToActivationEvents: ->
|
||||
return unless @metadata.activationEvents?
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
|
||||
atom.rootView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
|
||||
else if _.isString(@metadata.activationEvents)
|
||||
rootView.command(@metadata.activationEvents, @handleActivationEvent)
|
||||
atom.rootView.command(@metadata.activationEvents, @handleActivationEvent)
|
||||
else
|
||||
rootView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
|
||||
atom.rootView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
|
||||
|
||||
handleActivationEvent: (event) =>
|
||||
bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
|
||||
@@ -234,11 +234,11 @@ class AtomPackage extends Package
|
||||
|
||||
unsubscribeFromActivationEvents: ->
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
rootView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
|
||||
atom.rootView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
|
||||
else if _.isString(@metadata.activationEvents)
|
||||
rootView.off(@metadata.activationEvents, @handleActivationEvent)
|
||||
atom.rootView.off(@metadata.activationEvents, @handleActivationEvent)
|
||||
else
|
||||
rootView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
|
||||
atom.rootView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
|
||||
|
||||
disableEventHandlersOnBubblePath: (event) ->
|
||||
bubblePathEventHandlers = []
|
||||
|
||||
+203
-79
@@ -1,49 +1,52 @@
|
||||
#TODO remove once all packages have been updated
|
||||
{Emitter} = require 'emissary'
|
||||
Emitter::one = (args...) -> @once(args...)
|
||||
Emitter::trigger = (args...) -> @emit(args...)
|
||||
Emitter::subscriptionCount = (args...) -> @getSubscriptionCount(args...)
|
||||
|
||||
#TODO remove once all packages have been updated
|
||||
fs = require 'fs-plus'
|
||||
fs.exists = fs.existsSync
|
||||
fs.makeTree = fs.makeTreeSync
|
||||
fs.move = fs.moveSync
|
||||
fs.read = (filePath) -> fs.readFileSync(filePath, 'utf8')
|
||||
fs.remove = fs.removeSync
|
||||
fs.write = fs.writeFile
|
||||
fs.writeSync = fs.writeFileSync
|
||||
|
||||
fs = require 'fs-plus'
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
Package = require './package'
|
||||
crypto = require 'crypto'
|
||||
ipc = require 'ipc'
|
||||
os = require 'os'
|
||||
path = require 'path'
|
||||
remote = require 'remote'
|
||||
shell = require 'shell'
|
||||
crypto = require 'crypto'
|
||||
path = require 'path'
|
||||
os = require 'os'
|
||||
dialog = remote.require 'dialog'
|
||||
app = remote.require 'app'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
{Document} = require 'telepath'
|
||||
DeserializerManager = require './deserializer-manager'
|
||||
fs = require 'fs-plus'
|
||||
{Subscriber} = require 'emissary'
|
||||
|
||||
{$} = require './space-pen-extensions'
|
||||
DeserializerManager = require './deserializer-manager'
|
||||
Package = require './package'
|
||||
SiteShim = require './site-shim'
|
||||
WindowEventHandler = require './window-event-handler'
|
||||
|
||||
# Public: Atom global for dealing with packages, themes, menus, and the window.
|
||||
#
|
||||
# An instance of this class is always available as the `atom` global.
|
||||
#
|
||||
# ## Useful properties available:
|
||||
#
|
||||
# * `atom.config` - A {Config} instance
|
||||
# * `atom.contextMenu` - A {ContextMenuManager} instance
|
||||
# * `atom.keymap` - A {Keymap} instance
|
||||
# * `atom.menu` - A {MenuManager} instance
|
||||
# * `atom.rootView` - A {RootView} instance
|
||||
# * `atom.packages` - A {PackageManager} instance
|
||||
# * `atom.pasteboard` - A {Pasteboard} instance
|
||||
# * `atom.project` - A {Project} instance
|
||||
# * `atom.syntax` - A {Syntax} instance
|
||||
# * `atom.themes` - A {ThemeManager} instance
|
||||
module.exports =
|
||||
class Atom
|
||||
Subscriber.includeInto(this)
|
||||
|
||||
# Private:
|
||||
constructor: ->
|
||||
@rootViewParentSelector = 'body'
|
||||
@deserializers = new DeserializerManager()
|
||||
|
||||
# Private: Initialize all the properties in this object.
|
||||
initialize: ->
|
||||
@unsubscribe()
|
||||
@setBodyPlatformClass()
|
||||
|
||||
{devMode, resourcePath} = atom.getLoadSettings()
|
||||
configDirPath = @getConfigDirPath()
|
||||
@@ -66,8 +69,17 @@ class Atom
|
||||
@contextMenu = new ContextMenuManager(devMode)
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@pasteboard = new Pasteboard()
|
||||
@syntax = deserialize(@getWindowState('syntax')) ? new Syntax()
|
||||
@syntax = @deserializers.deserialize(@getWindowState('syntax')) ? new Syntax()
|
||||
|
||||
# Private: This method is called in any window needing a general environment, including specs
|
||||
setUpEnvironment: (@windowMode) ->
|
||||
@initialize()
|
||||
|
||||
# Private:
|
||||
setBodyPlatformClass: ->
|
||||
document.body.classList.add("platform-#{process.platform}")
|
||||
|
||||
# Public: Get the current window
|
||||
getCurrentWindow: ->
|
||||
remote.getCurrentWindow()
|
||||
|
||||
@@ -102,6 +114,7 @@ class Atom
|
||||
else
|
||||
browserWindow.center()
|
||||
|
||||
# Private:
|
||||
restoreDimensions: ->
|
||||
dimensions = @getWindowState().getObject('dimensions')
|
||||
unless dimensions?.width and dimensions?.height
|
||||
@@ -118,54 +131,95 @@ class Atom
|
||||
@loadSettings ?= _.deepClone(@getCurrentWindow().loadSettings)
|
||||
_.deepClone(@loadSettings)
|
||||
|
||||
# Private:
|
||||
deserializeProject: ->
|
||||
Project = require './project'
|
||||
state = @getWindowState()
|
||||
@project = deserialize(state.get('project'))
|
||||
unless @project?
|
||||
@project = new Project(@getLoadSettings().initialPath)
|
||||
state.set('project', @project.getState())
|
||||
@project = @getWindowState('project')
|
||||
unless @project instanceof Project
|
||||
@project = new Project(path: @getLoadSettings().initialPath)
|
||||
@setWindowState('project', @project)
|
||||
|
||||
# Private:
|
||||
deserializeRootView: ->
|
||||
RootView = require './root-view'
|
||||
state = @getWindowState()
|
||||
@rootView = deserialize(state.get('rootView'))
|
||||
@rootView = @deserializers.deserialize(state.get('rootView'))
|
||||
unless @rootView?
|
||||
@rootView = new RootView()
|
||||
state.set('rootView', @rootView.getState())
|
||||
$(@rootViewParentSelector).append(@rootView)
|
||||
|
||||
# Private:
|
||||
deserializePackageStates: ->
|
||||
state = @getWindowState()
|
||||
@packages.packageStates = state.getObject('packageStates') ? {}
|
||||
state.remove('packageStates')
|
||||
|
||||
#TODO Remove theses once packages have been migrated
|
||||
getPackageState: (args...) -> @packages.getPackageState(args...)
|
||||
setPackageState: (args...) -> @packages.setPackageState(args...)
|
||||
activatePackages: (args...) -> @packages.activatePackages(args...)
|
||||
activatePackage: (args...) -> @packages.activatePackage(args...)
|
||||
deactivatePackages: (args...) -> @packages.deactivatePackages(args...)
|
||||
deactivatePackage: (args...) -> @packages.deactivatePackage(args...)
|
||||
getActivePackage: (args...) -> @packages.getActivePackage(args...)
|
||||
isPackageActive: (args...) -> @packages.isPackageActive(args...)
|
||||
getActivePackages: (args...) -> @packages.getActivePackages(args...)
|
||||
loadPackages: (args...) -> @packages.loadPackages(args...)
|
||||
loadPackage: (args...) -> @packages.loadPackage(args...)
|
||||
unloadPackage: (args...) -> @packages.unloadPackage(args...)
|
||||
resolvePackagePath: (args...) -> @packages.resolvePackagePath(args...)
|
||||
isInternalPackage: (args...) -> @packages.isInternalPackage(args...)
|
||||
getLoadedPackage: (args...) -> @packages.getLoadedPackage(args...)
|
||||
isPackageLoaded: (args...) -> @packages.isPackageLoaded(args...)
|
||||
getLoadedPackages: (args...) -> @packages.getLoadedPackages(args...)
|
||||
isPackageDisabled: (args...) -> @packages.isPackageDisabled(args...)
|
||||
getAvailablePackagePaths: (args...) -> @packages.getAvailablePackagePaths(args...)
|
||||
getAvailablePackageNames: (args...) -> @packages.getAvailablePackageNames(args...)
|
||||
getAvailablePackageMetadata: (args...)-> @packages.getAvailablePackageMetadata(args...)
|
||||
# Private:
|
||||
deserializeEditorWindow: ->
|
||||
@deserializePackageStates()
|
||||
@deserializeProject()
|
||||
@deserializeRootView()
|
||||
|
||||
# Private: This method is only called when opening a real application window
|
||||
startEditorWindow: ->
|
||||
if process.platform is 'darwin'
|
||||
CommandInstaller = require './command-installer'
|
||||
CommandInstaller.installAtomCommand()
|
||||
CommandInstaller.installApmCommand()
|
||||
|
||||
@windowEventHandler = new WindowEventHandler
|
||||
@restoreDimensions()
|
||||
@config.load()
|
||||
@config.setDefaults('core', require('./root-view').configDefaults)
|
||||
@config.setDefaults('editor', require('./editor-view').configDefaults)
|
||||
@keymap.loadBundledKeymaps()
|
||||
@themes.loadBaseStylesheets()
|
||||
@packages.loadPackages()
|
||||
@deserializeEditorWindow()
|
||||
@packages.activate()
|
||||
@keymap.loadUserKeymap()
|
||||
@requireUserInitScript()
|
||||
@menu.update()
|
||||
|
||||
$(window).on 'unload', =>
|
||||
$(document.body).hide()
|
||||
@unloadEditorWindow()
|
||||
false
|
||||
|
||||
@displayWindow()
|
||||
|
||||
# Private:
|
||||
unloadEditorWindow: ->
|
||||
return if not @project and not @rootView
|
||||
|
||||
windowState = @getWindowState()
|
||||
windowState.set('project', @project)
|
||||
windowState.set('syntax', @syntax.serialize())
|
||||
windowState.set('rootView', @rootView.serialize())
|
||||
@packages.deactivatePackages()
|
||||
windowState.set('packageStates', @packages.packageStates)
|
||||
@saveWindowState()
|
||||
@rootView.remove()
|
||||
@project.destroy()
|
||||
@windowEventHandler?.unsubscribe()
|
||||
|
||||
# Set up the default event handlers and menus for a non-editor window.
|
||||
#
|
||||
# This can be used by packages to have a minimum level of keybindings and
|
||||
# menus available when not using the standard editor window.
|
||||
#
|
||||
# This should only be called after setUpEnvironment() has been called.
|
||||
setUpDefaultEvents: ->
|
||||
@windowEventHandler = new WindowEventHandler
|
||||
@keymap.loadBundledKeymaps()
|
||||
@menu.update()
|
||||
|
||||
# Private:
|
||||
loadThemes: ->
|
||||
@themes.load()
|
||||
|
||||
# Private:
|
||||
watchThemes: ->
|
||||
@themes.on 'reloaded', =>
|
||||
# Only reload stylesheets from non-theme packages
|
||||
@@ -173,91 +227,144 @@ class Atom
|
||||
pack.reloadStylesheets?()
|
||||
null
|
||||
|
||||
# Public: Open a new Atom window using the given options.
|
||||
#
|
||||
# Calling this method without an options parameter will open a prompt to pick
|
||||
# a file/folder to open in the new window.
|
||||
#
|
||||
# * options
|
||||
# * pathsToOpen: A string array of paths to open
|
||||
open: (options) ->
|
||||
ipc.sendChannel('open', options)
|
||||
|
||||
confirm: (message, detailedMessage, buttonLabelsAndCallbacks...) ->
|
||||
buttons = []
|
||||
callbacks = []
|
||||
while buttonLabelsAndCallbacks.length
|
||||
do =>
|
||||
buttons.push buttonLabelsAndCallbacks.shift()
|
||||
callbacks.push buttonLabelsAndCallbacks.shift()
|
||||
# Public: Open a confirm dialog.
|
||||
#
|
||||
# ## Example:
|
||||
# ```coffeescript
|
||||
# atom.confirm
|
||||
# message: 'How you feeling?'
|
||||
# detailedMessage: 'Be honest.'
|
||||
# buttons:
|
||||
# Good: -> window.alert('good to hear')
|
||||
# Bad: -> window.alert('bummer')
|
||||
# ```
|
||||
#
|
||||
# * options:
|
||||
# + message: The string message to display.
|
||||
# + detailedMessage: The string detailed message to display.
|
||||
# + buttons: Either an array of strings or an object where the values
|
||||
# are callbacks to invoke when clicked.
|
||||
#
|
||||
# Returns the chosen index if buttons was an array or the return of the
|
||||
# callback if buttons was an object.
|
||||
confirm: ({message, detailedMessage, buttons}={}) ->
|
||||
buttons ?= {}
|
||||
if _.isArray(buttons)
|
||||
buttonLabels = buttons
|
||||
else
|
||||
buttonLabels = Object.keys(buttons)
|
||||
|
||||
chosen = @confirmSync(message, detailedMessage, buttons)
|
||||
callbacks[chosen]?()
|
||||
|
||||
confirmSync: (message, detailedMessage, buttons, browserWindow=@getCurrentWindow()) ->
|
||||
dialog.showMessageBox browserWindow,
|
||||
chosen = dialog.showMessageBox @getCurrentWindow(),
|
||||
type: 'info'
|
||||
message: message
|
||||
detail: detailedMessage
|
||||
buttons: buttons
|
||||
buttons: buttonLabels
|
||||
|
||||
if _.isArray(buttons)
|
||||
chosen
|
||||
else
|
||||
callback = buttons[buttonLabels[chosen]]
|
||||
callback?()
|
||||
|
||||
# Private:
|
||||
showSaveDialog: (callback) ->
|
||||
callback(showSaveDialogSync())
|
||||
|
||||
# Private:
|
||||
showSaveDialogSync: (defaultPath) ->
|
||||
defaultPath ?= project?.getPath()
|
||||
defaultPath ?= @project?.getPath()
|
||||
currentWindow = @getCurrentWindow()
|
||||
dialog.showSaveDialog currentWindow, {title: 'Save File', defaultPath}
|
||||
|
||||
# Public: Open the dev tools for the current window.
|
||||
openDevTools: ->
|
||||
@getCurrentWindow().openDevTools()
|
||||
|
||||
# Public: Toggle the visibility of the dev tools for the current window.
|
||||
toggleDevTools: ->
|
||||
@getCurrentWindow().toggleDevTools()
|
||||
|
||||
# Public: Reload the current window.
|
||||
reload: ->
|
||||
@getCurrentWindow().restart()
|
||||
|
||||
# Public: Focus the current window.
|
||||
focus: ->
|
||||
@getCurrentWindow().focus()
|
||||
$(window).focus()
|
||||
|
||||
# Public: Show the current window.
|
||||
show: ->
|
||||
@getCurrentWindow().show()
|
||||
|
||||
# Public: Hide the current window.
|
||||
hide: ->
|
||||
@getCurrentWindow().hide()
|
||||
|
||||
# Private: Schedule the window to be shown and focused on the next tick.
|
||||
#
|
||||
# This is done in a next tick to prevent a white flicker from occurring
|
||||
# if called synchronously.
|
||||
displayWindow: ->
|
||||
setImmediate =>
|
||||
@show()
|
||||
@focus()
|
||||
@setFullScreen(true) if @rootView.getState().get('fullScreen')
|
||||
|
||||
# Public: Close the current window.
|
||||
close: ->
|
||||
@getCurrentWindow().close()
|
||||
|
||||
# Private:
|
||||
exit: (status) -> app.exit(status)
|
||||
|
||||
# Public: Is the current window in development mode?
|
||||
inDevMode: ->
|
||||
@getLoadSettings().devMode
|
||||
|
||||
# Public: Is the current window running specs?
|
||||
inSpecMode: ->
|
||||
@getLoadSettings().isSpec
|
||||
|
||||
# Public: Toggle the full screen state of the current window.
|
||||
toggleFullScreen: ->
|
||||
@setFullScreen(!@isFullScreen())
|
||||
|
||||
# Public: Set the full screen state of the current window.
|
||||
setFullScreen: (fullScreen=false) ->
|
||||
@getCurrentWindow().setFullScreen(fullScreen)
|
||||
|
||||
# Public: Is the current window in full screen mode?
|
||||
isFullScreen: ->
|
||||
@getCurrentWindow().isFullScreen()
|
||||
|
||||
# Public: Get the version of the Atom application.
|
||||
getVersion: ->
|
||||
app.getVersion()
|
||||
|
||||
getHomeDirPath: ->
|
||||
process.env[if process.platform is 'win32' then 'USERPROFILE' else 'HOME']
|
||||
|
||||
getTempDirPath: ->
|
||||
if process.platform is 'win32' then os.tmpdir() else '/tmp'
|
||||
|
||||
# Public: Get the directory path to Atom's configuration area.
|
||||
#
|
||||
# Returns the absolute path to ~/.atom
|
||||
getConfigDirPath: ->
|
||||
@configDirPath ?= fs.absolute('~/.atom')
|
||||
|
||||
# Public: Get the directory path to Atom's storage area.
|
||||
#
|
||||
# Returns the absoluste path to ~/.atom/storage
|
||||
getStorageDirPath: ->
|
||||
@storageDirPath ?= path.join(@getConfigDirPath(), 'storage')
|
||||
|
||||
# Private:
|
||||
getWindowStatePath: ->
|
||||
switch @windowMode
|
||||
when 'spec'
|
||||
@@ -273,11 +380,13 @@ class Atom
|
||||
else
|
||||
null
|
||||
|
||||
# Public: Set the window state of the given keypath to the value.
|
||||
setWindowState: (keyPath, value) ->
|
||||
windowState = @getWindowState()
|
||||
windowState.set(keyPath, value)
|
||||
windowState
|
||||
|
||||
# Private:
|
||||
loadWindowState: ->
|
||||
if windowStatePath = @getWindowStatePath()
|
||||
if fs.existsSync(windowStatePath)
|
||||
@@ -295,6 +404,7 @@ class Atom
|
||||
|
||||
doc = Document.deserialize(documentState) if documentState?
|
||||
doc ?= Document.create()
|
||||
doc.registerModelClasses(require('./text-buffer'), require('./project'))
|
||||
# TODO: Remove this when everything is using telepath models
|
||||
if @site?
|
||||
@site.setRootDocument(doc)
|
||||
@@ -302,13 +412,15 @@ class Atom
|
||||
@site = new SiteShim(doc)
|
||||
doc
|
||||
|
||||
# Private:
|
||||
saveWindowState: ->
|
||||
windowState = @getWindowState()
|
||||
if windowStatePath = @getWindowStatePath()
|
||||
windowState.saveSync(windowStatePath)
|
||||
else
|
||||
@getCurrentWindow().loadSettings.windowState = JSON.stringify(windowState.serialize())
|
||||
@getCurrentWindow().loadSettings.windowState = JSON.stringify(windowState.serializeForPersistence())
|
||||
|
||||
# Public: Get the window state for the key path.
|
||||
getWindowState: (keyPath) ->
|
||||
@windowState ?= @loadWindowState()
|
||||
if keyPath
|
||||
@@ -316,23 +428,35 @@ class Atom
|
||||
else
|
||||
@windowState
|
||||
|
||||
# Private: Returns a replicated copy of the current state.
|
||||
replicate: ->
|
||||
@getWindowState().replicate()
|
||||
|
||||
# Private:
|
||||
crashMainProcess: ->
|
||||
remote.process.crash()
|
||||
|
||||
# Private:
|
||||
crashRenderProcess: ->
|
||||
process.crash()
|
||||
|
||||
# Public: Visually and audibly trigger a beep.
|
||||
beep: ->
|
||||
shell.beep() if @config.get('core.audioBeep')
|
||||
@rootView.trigger 'beep'
|
||||
|
||||
# Private:
|
||||
requireUserInitScript: ->
|
||||
userInitScriptPath = path.join(@getConfigDirPath(), "user.coffee")
|
||||
try
|
||||
require userInitScriptPath if fs.isFileSync(userInitScriptPath)
|
||||
catch error
|
||||
console.error "Failed to load `#{userInitScriptPath}`", error.stack, error
|
||||
if userInitScriptPath = fs.resolve(@getConfigDirPath(), 'user', ['js', 'coffee'])
|
||||
try
|
||||
require userInitScriptPath
|
||||
catch error
|
||||
console.error "Failed to load `#{userInitScriptPath}`", error.stack, error
|
||||
|
||||
# Public: Require the module with the given globals.
|
||||
#
|
||||
# The globals will be set on the `window` object and removed after the
|
||||
# require completes.
|
||||
requireWithGlobals: (id, globals={}) ->
|
||||
existingGlobals = {}
|
||||
for key, value of globals
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
{specificity} = require 'clear-cut'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class BindingSet
|
||||
|
||||
@parser: null
|
||||
|
||||
selector: null
|
||||
commandsByKeystrokes: null
|
||||
parser: null
|
||||
name: null
|
||||
|
||||
constructor: (selector, commandsByKeystrokes, @index, @name) ->
|
||||
keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8')
|
||||
BindingSet.parser ?= PEG.buildParser(keystrokePattern)
|
||||
@specificity = specificity(selector)
|
||||
@selector = selector.replace(/!important/g, '')
|
||||
@commandsByKeystrokes = @normalizeCommandsByKeystrokes(commandsByKeystrokes)
|
||||
|
||||
# Private:
|
||||
getName: ->
|
||||
@name
|
||||
|
||||
# Private:
|
||||
getSelector: ->
|
||||
@selector
|
||||
|
||||
# Private:
|
||||
getCommandsByKeystrokes: ->
|
||||
@commandsByKeystrokes
|
||||
|
||||
commandForEvent: (event) ->
|
||||
for keystrokes, command of @commandsByKeystrokes
|
||||
return command if event.keystrokes == keystrokes
|
||||
null
|
||||
|
||||
matchesKeystrokePrefix: (event) ->
|
||||
eventKeystrokes = event.keystrokes.split(' ')
|
||||
for keystrokes, command of @commandsByKeystrokes
|
||||
bindingKeystrokes = keystrokes.split(' ')
|
||||
continue unless eventKeystrokes.length < bindingKeystrokes.length
|
||||
return true if _.isEqual(eventKeystrokes, bindingKeystrokes[0...eventKeystrokes.length])
|
||||
false
|
||||
|
||||
normalizeCommandsByKeystrokes: (commandsByKeystrokes) ->
|
||||
normalizedCommandsByKeystrokes = {}
|
||||
for keystrokes, command of commandsByKeystrokes
|
||||
normalizedCommandsByKeystrokes[@normalizeKeystrokes(keystrokes)] = command
|
||||
normalizedCommandsByKeystrokes
|
||||
|
||||
normalizeKeystrokes: (keystrokes) ->
|
||||
normalizedKeystrokes = keystrokes.split(/\s+/).map (keystroke) =>
|
||||
@normalizeKeystroke(keystroke)
|
||||
normalizedKeystrokes.join(' ')
|
||||
|
||||
normalizeKeystroke: (keystroke) ->
|
||||
keys = BindingSet.parser.parse(keystroke)
|
||||
modifiers = keys[0...-1]
|
||||
modifiers.sort()
|
||||
[modifiers..., _.last(keys)].join('-')
|
||||
@@ -22,7 +22,7 @@ class ApplicationMenu
|
||||
# The Object which describes the menu to display.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystrokes.
|
||||
# the keystroke.
|
||||
update: (template, keystrokesByCommand) ->
|
||||
@translateTemplate(template, keystrokesByCommand)
|
||||
@substituteVersion(template)
|
||||
@@ -97,14 +97,14 @@ class ApplicationMenu
|
||||
]
|
||||
]
|
||||
|
||||
# Private: Combines a menu template with the appropriate keystrokes.
|
||||
# Private: Combines a menu template with the appropriate keystroke.
|
||||
#
|
||||
# * template:
|
||||
# An Object conforming to atom-shell's menu api but lacking accelerator and
|
||||
# click properties.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystrokes.
|
||||
# the keystroke.
|
||||
#
|
||||
# Returns a complete menu configuration object for atom-shell's menu API.
|
||||
translateTemplate: (template, keystrokesByCommand) ->
|
||||
@@ -123,21 +123,21 @@ class ApplicationMenu
|
||||
# The name of the command.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystrokes.
|
||||
# the keystroke.
|
||||
#
|
||||
# Returns a String containing the keystroke in a format that can be interpreted
|
||||
# by atom shell to provide nice icons where available.
|
||||
acceleratorForCommand: (command, keystrokesByCommand) ->
|
||||
keystroke = keystrokesByCommand[command]?[0]
|
||||
return null unless keystroke
|
||||
firstKeystroke = keystrokesByCommand[command]?[0]
|
||||
return null unless firstKeystroke
|
||||
|
||||
modifiers = keystroke.split('-')
|
||||
modifiers = firstKeystroke.split('-')
|
||||
key = modifiers.pop()
|
||||
|
||||
modifiers.push("Shift") if key != key.toLowerCase()
|
||||
modifiers = modifiers.map (modifier) ->
|
||||
modifier.replace(/shift/ig, "Shift")
|
||||
.replace(/meta/ig, "Command")
|
||||
.replace(/cmd/ig, "Command")
|
||||
.replace(/ctrl/ig, "Ctrl")
|
||||
.replace(/alt/ig, "Alt")
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Menu = require 'menu'
|
||||
|
||||
# Private:
|
||||
module.exports =
|
||||
class ContextMenu
|
||||
constructor: (template, browserWindow) ->
|
||||
|
||||
@@ -62,7 +62,7 @@ delegate.browserMainParts.preMainMessageLoopRun = ->
|
||||
AtomApplication = require './atom-application'
|
||||
|
||||
AtomApplication.open(args)
|
||||
console.log("App load time: #{Date.now() - startTime}ms")
|
||||
console.log("App load time: #{Date.now() - startTime}ms") unless args.test
|
||||
|
||||
global.devResourcePath = path.join(app.getHomeDir(), 'github', 'atom')
|
||||
|
||||
|
||||
@@ -47,3 +47,13 @@ module.exports =
|
||||
symlinkCommand(commandPath, destinationPath, installCallback)
|
||||
else
|
||||
installCallback(new Error("No destination directory exists to install"))
|
||||
|
||||
installAtomCommand: (callback) ->
|
||||
{resourcePath} = atom.getLoadSettings()
|
||||
commandPath = path.join(resourcePath, 'atom.sh')
|
||||
@install(commandPath, callback)
|
||||
|
||||
installApmCommand: (callback) ->
|
||||
{resourcePath} = atom.getLoadSettings()
|
||||
commandPath = path.join(resourcePath, 'node_modules', '.bin', 'apm')
|
||||
@install(commandPath, callback)
|
||||
|
||||
@@ -5,5 +5,5 @@ module.exports =
|
||||
|
||||
unobserveConfig: ->
|
||||
if @configSubscriptions?
|
||||
subscription.cancel() for keyPath, subscription of @configSubscriptions
|
||||
subscription.off() for keyPath, subscription of @configSubscriptions
|
||||
@configSubscriptions = null
|
||||
|
||||
+1
-2
@@ -216,8 +216,7 @@ class Config
|
||||
callback(value, {previous})
|
||||
|
||||
eventName = "updated.#{keyPath.replace(/\./, '-')}"
|
||||
subscription = { cancel: => @off eventName, updateCallback }
|
||||
@on eventName, updateCallback
|
||||
subscription = @on eventName, updateCallback
|
||||
callback(value) if options.callNow ? true
|
||||
subscription
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ class CursorView extends View
|
||||
@div class: 'cursor idle', => @raw ' '
|
||||
|
||||
blinkPeriod: 800
|
||||
editor: null
|
||||
editorView: null
|
||||
visible: true
|
||||
|
||||
needsUpdate: true
|
||||
needsRemoval: false
|
||||
shouldPauseBlinking: false
|
||||
|
||||
initialize: (@cursor, @editor) ->
|
||||
initialize: (@cursor, @editorView) ->
|
||||
@cursor.on 'moved.cursor-view', =>
|
||||
@needsUpdate = true
|
||||
@shouldPauseBlinking = true
|
||||
@@ -25,7 +25,7 @@ class CursorView extends View
|
||||
@needsUpdate = true
|
||||
|
||||
@cursor.on 'autoscrolled.cursor-view', =>
|
||||
@editor.requestDisplayUpdate()
|
||||
@editorView.requestDisplayUpdate()
|
||||
|
||||
@cursor.on 'destroyed.cursor-view', =>
|
||||
@needsRemoval = true
|
||||
@@ -34,7 +34,7 @@ class CursorView extends View
|
||||
@addClass("site-#{@cursor.marker.getOriginSiteId()}")
|
||||
|
||||
beforeRemove: ->
|
||||
@editor.removeCursorView(this)
|
||||
@editorView.removeCursorView(this)
|
||||
@cursor.off('.cursor-view')
|
||||
@stopBlinking()
|
||||
|
||||
@@ -52,7 +52,7 @@ class CursorView extends View
|
||||
else if !@startBlinkingTimeout
|
||||
@startBlinking()
|
||||
|
||||
@setVisible(@cursor.isVisible() and not @editor.isFoldedAtScreenRow(screenPosition.row))
|
||||
@setVisible(@cursor.isVisible() and not @editorView.isFoldedAtScreenRow(screenPosition.row))
|
||||
|
||||
# Override for speed. The base function checks the computedStyle
|
||||
isHidden: ->
|
||||
@@ -69,7 +69,7 @@ class CursorView extends View
|
||||
@cursor.clearAutoscroll()
|
||||
|
||||
getPixelPosition: ->
|
||||
@editor.pixelPositionForScreenPosition(@getScreenPosition())
|
||||
@editorView.pixelPositionForScreenPosition(@getScreenPosition())
|
||||
|
||||
setVisible: (visible) ->
|
||||
unless @visible == visible
|
||||
|
||||
+44
-32
@@ -5,7 +5,7 @@ _ = require 'underscore-plus'
|
||||
# Public: The `Cursor` class represents the little blinking line identifying
|
||||
# where text can be inserted.
|
||||
#
|
||||
# Cursors belong to {EditSession}s and have some metadata attached in the form
|
||||
# Cursors belong to {Editor}s and have some metadata attached in the form
|
||||
# of a {StringMarker}.
|
||||
module.exports =
|
||||
class Cursor
|
||||
@@ -17,8 +17,8 @@ class Cursor
|
||||
visible: true
|
||||
needsAutoscroll: null
|
||||
|
||||
# Private: Instantiated by an {EditSession}
|
||||
constructor: ({@editSession, @marker}) ->
|
||||
# Private: Instantiated by an {Editor}
|
||||
constructor: ({@editor, @marker}) ->
|
||||
@updateVisibility()
|
||||
@marker.on 'changed', (e) =>
|
||||
@updateVisibility()
|
||||
@@ -37,10 +37,10 @@ class Cursor
|
||||
textChanged: textChanged
|
||||
|
||||
@emit 'moved', movedEvent
|
||||
@editSession.emit 'cursor-moved', movedEvent
|
||||
@editor.emit 'cursor-moved', movedEvent
|
||||
@marker.on 'destroyed', =>
|
||||
@destroyed = true
|
||||
@editSession.removeCursor(this)
|
||||
@editor.removeCursor(this)
|
||||
@emit 'destroyed'
|
||||
@needsAutoscroll = true
|
||||
|
||||
@@ -62,7 +62,7 @@ class Cursor
|
||||
# An {Array} of two numbers: the screen row, and the screen column.
|
||||
# * options:
|
||||
# + autoscroll:
|
||||
# A Boolean which, if `true`, scrolls the {EditSession} to wherever the
|
||||
# A Boolean which, if `true`, scrolls the {Editor} to wherever the
|
||||
# cursor moves to.
|
||||
setScreenPosition: (screenPosition, options={}) ->
|
||||
@changePosition options, =>
|
||||
@@ -78,7 +78,7 @@ class Cursor
|
||||
# An {Array} of two numbers: the buffer row, and the buffer column.
|
||||
# * options:
|
||||
# + autoscroll:
|
||||
# A Boolean which, if `true`, scrolls the {EditSession} to wherever the
|
||||
# A Boolean which, if `true`, scrolls the {Editor} to wherever the
|
||||
# cursor moves to.
|
||||
setBufferPosition: (bufferPosition, options={}) ->
|
||||
@changePosition options, =>
|
||||
@@ -118,13 +118,13 @@ class Cursor
|
||||
segments.push("[#{_.escapeRegExp(nonWordCharacters)}]+")
|
||||
new RegExp(segments.join("|"), "g")
|
||||
|
||||
# Public: Identifies if this cursor is the last in the {EditSession}.
|
||||
# Public: Identifies if this cursor is the last in the {Editor}.
|
||||
#
|
||||
# "Last" is defined as the most recently added cursor.
|
||||
#
|
||||
# Returns a Boolean.
|
||||
isLastCursor: ->
|
||||
this == @editSession.getCursor()
|
||||
this == @editor.getCursor()
|
||||
|
||||
# Public: Identifies if the cursor is surrounded by whitespace.
|
||||
#
|
||||
@@ -135,7 +135,7 @@ class Cursor
|
||||
isSurroundedByWhitespace: ->
|
||||
{row, column} = @getBufferPosition()
|
||||
range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]]
|
||||
/^\s+$/.test @editSession.getTextInBufferRange(range)
|
||||
/^\s+$/.test @editor.getTextInBufferRange(range)
|
||||
|
||||
# Public: Returns whether the cursor is currently between a word and non-word
|
||||
# character. The non-word characters are defined by the
|
||||
@@ -150,7 +150,7 @@ class Cursor
|
||||
|
||||
{row, column} = @getBufferPosition()
|
||||
range = [[row, column - 1], [row, column + 1]]
|
||||
[before, after] = @editSession.getTextInBufferRange(range)
|
||||
[before, after] = @editor.getTextInBufferRange(range)
|
||||
return false if /\s/.test(before) or /\s/.test(after)
|
||||
|
||||
nonWordCharacters = atom.config.get('editor.nonWordCharacters').split('')
|
||||
@@ -160,7 +160,7 @@ class Cursor
|
||||
isInsideWord: ->
|
||||
{row, column} = @getBufferPosition()
|
||||
range = [[row, column], [row, Infinity]]
|
||||
@editSession.getTextInBufferRange(range).search(@wordRegExp()) == 0
|
||||
@editor.getTextInBufferRange(range).search(@wordRegExp()) == 0
|
||||
|
||||
# Public: Prevents this cursor from causing scrolling.
|
||||
clearAutoscroll: ->
|
||||
@@ -189,7 +189,7 @@ class Cursor
|
||||
# Public: Returns the cursor's current buffer row of text excluding its line
|
||||
# ending.
|
||||
getCurrentBufferLine: ->
|
||||
@editSession.lineForBufferRow(@getBufferRow())
|
||||
@editor.lineForBufferRow(@getBufferRow())
|
||||
|
||||
# Public: Moves the cursor up one screen row.
|
||||
moveUp: (rowCount = 1, {moveToEndOfSelection}={}) ->
|
||||
@@ -248,7 +248,7 @@ class Cursor
|
||||
|
||||
# Public: Moves the cursor to the bottom of the buffer.
|
||||
moveToBottom: ->
|
||||
@setBufferPosition(@editSession.getEofBufferPosition())
|
||||
@setBufferPosition(@editor.getEofBufferPosition())
|
||||
|
||||
# Public: Moves the cursor to the beginning of the screen line.
|
||||
moveToBeginningOfLine: ->
|
||||
@@ -258,7 +258,7 @@ class Cursor
|
||||
# line.
|
||||
moveToFirstCharacterOfLine: ->
|
||||
{row, column} = @getScreenPosition()
|
||||
screenline = @editSession.lineForScreenRow(row)
|
||||
screenline = @editor.lineForScreenRow(row)
|
||||
|
||||
goalColumn = screenline.text.search(/\S/)
|
||||
return if goalColumn == -1
|
||||
@@ -272,7 +272,7 @@ class Cursor
|
||||
position = @getBufferPosition()
|
||||
scanRange = @getCurrentLineBufferRange()
|
||||
endOfLeadingWhitespace = null
|
||||
@editSession.scanInBufferRange /^[ \t]*/, scanRange, ({range}) =>
|
||||
@editor.scanInBufferRange /^[ \t]*/, scanRange, ({range}) =>
|
||||
endOfLeadingWhitespace = range.end
|
||||
|
||||
@setBufferPosition(endOfLeadingWhitespace) if endOfLeadingWhitespace.isGreaterThan(position)
|
||||
@@ -318,11 +318,11 @@ class Cursor
|
||||
getBeginningOfCurrentWordBufferPosition: (options = {}) ->
|
||||
allowPrevious = options.allowPrevious ? true
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
previousNonBlankRow = @editSession.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
scanRange = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
|
||||
beginningOfWordPosition = null
|
||||
@editSession.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) =>
|
||||
@editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) =>
|
||||
if range.end.isGreaterThanOrEqual(currentBufferPosition) or allowPrevious
|
||||
beginningOfWordPosition = range.start
|
||||
if not beginningOfWordPosition?.isEqual(currentBufferPosition)
|
||||
@@ -334,11 +334,11 @@ class Cursor
|
||||
# the current word, or the previous word.
|
||||
getPreviousWordBoundaryBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
previousNonBlankRow = @editSession.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
scanRange = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
|
||||
beginningOfWordPosition = null
|
||||
@editSession.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
|
||||
@editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
|
||||
if range.start.row < currentBufferPosition.row and currentBufferPosition.column > 0
|
||||
# force it to stop at the beginning of each line
|
||||
beginningOfWordPosition = new Point(currentBufferPosition.row, 0)
|
||||
@@ -356,10 +356,10 @@ class Cursor
|
||||
# the current word, or the previous word.
|
||||
getMoveNextWordBoundaryBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
scanRange = [currentBufferPosition, @editSession.getEofBufferPosition()]
|
||||
scanRange = [currentBufferPosition, @editor.getEofBufferPosition()]
|
||||
|
||||
endOfWordPosition = null
|
||||
@editSession.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
|
||||
@editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
|
||||
if range.start.row > currentBufferPosition.row
|
||||
# force it to stop at the beginning of each line
|
||||
endOfWordPosition = new Point(range.start.row, 0)
|
||||
@@ -386,10 +386,10 @@ class Cursor
|
||||
getEndOfCurrentWordBufferPosition: (options = {}) ->
|
||||
allowNext = options.allowNext ? true
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
scanRange = [currentBufferPosition, @editSession.getEofBufferPosition()]
|
||||
scanRange = [currentBufferPosition, @editor.getEofBufferPosition()]
|
||||
|
||||
endOfWordPosition = null
|
||||
@editSession.scanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) =>
|
||||
@editor.scanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) =>
|
||||
if range.start.isLessThanOrEqual(currentBufferPosition) or allowNext
|
||||
endOfWordPosition = range.end
|
||||
if not endOfWordPosition?.isEqual(currentBufferPosition)
|
||||
@@ -407,10 +407,10 @@ class Cursor
|
||||
getBeginningOfNextWordBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
start = if @isInsideWord() then @getEndOfCurrentWordBufferPosition() else currentBufferPosition
|
||||
scanRange = [start, @editSession.getEofBufferPosition()]
|
||||
scanRange = [start, @editor.getEofBufferPosition()]
|
||||
|
||||
beginningOfNextWordPosition = null
|
||||
@editSession.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
|
||||
@editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) =>
|
||||
beginningOfNextWordPosition = range.start
|
||||
stop()
|
||||
|
||||
@@ -432,7 +432,7 @@ class Cursor
|
||||
# + includeNewline:
|
||||
# A boolean which controls whether the Range should include the newline.
|
||||
getCurrentLineBufferRange: (options) ->
|
||||
@editSession.bufferRangeForBufferRow(@getBufferRow(), options)
|
||||
@editor.bufferRangeForBufferRow(@getBufferRow(), options)
|
||||
|
||||
# Public: Retrieves the range for the current paragraph.
|
||||
#
|
||||
@@ -440,11 +440,11 @@ class Cursor
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getCurrentParagraphBufferRange: ->
|
||||
@editSession.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow())
|
||||
@editor.languageMode.rowRangeForParagraphAtBufferRow(@getBufferRow())
|
||||
|
||||
# Public: Returns the characters preceeding the cursor in the current word.
|
||||
getCurrentWordPrefix: ->
|
||||
@editSession.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()])
|
||||
@editor.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()])
|
||||
|
||||
# Public: Returns whether the cursor is at the start of a line.
|
||||
isAtBeginningOfLine: ->
|
||||
@@ -452,8 +452,8 @@ class Cursor
|
||||
|
||||
# Public: Returns the indentation level of the current line.
|
||||
getIndentLevel: ->
|
||||
if @editSession.getSoftTabs()
|
||||
@getBufferColumn() / @editSession.getTabLength()
|
||||
if @editor.getSoftTabs()
|
||||
@getBufferColumn() / @editor.getTabLength()
|
||||
else
|
||||
@getBufferColumn()
|
||||
|
||||
@@ -465,4 +465,16 @@ class Cursor
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
getScopes: ->
|
||||
@editSession.scopesForBufferPosition(@getBufferPosition())
|
||||
@editor.scopesForBufferPosition(@getBufferPosition())
|
||||
|
||||
# Public: Returns true if this cursor has no non-whitespace characters before
|
||||
# its current position.
|
||||
hasPrecedingCharactersOnLine: ->
|
||||
bufferPosition = @getBufferPosition()
|
||||
line = @editor.lineForBufferRow(bufferPosition.row)
|
||||
firstCharacterColumn = line.search(/\S/)
|
||||
|
||||
if firstCharacterColumn is -1
|
||||
false
|
||||
else
|
||||
bufferPosition.column > firstCharacterColumn
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
{Document} = require 'telepath'
|
||||
|
||||
# Public: Manages the deserializers used for serialized state
|
||||
#
|
||||
# Should be accessed via `atom.deserializers`
|
||||
module.exports =
|
||||
class DeserializerManager
|
||||
constructor: ->
|
||||
@deserializers = {}
|
||||
@deferredDeserializers = {}
|
||||
|
||||
# Public: Add a deserializer.
|
||||
# Public: Register the given class(es) as deserializers.
|
||||
add: (klasses...) ->
|
||||
@deserializers[klass.name] = klass for klass in klasses
|
||||
|
||||
# Public: Add a deferred deserializer.
|
||||
# Public: Add a deferred deserializer for the given class name.
|
||||
addDeferred: (name, fn) ->
|
||||
@deferredDeserializers[name] = fn
|
||||
|
||||
# Public: Remove a deserializer.
|
||||
# Public: Remove the given class(es) as deserializers.
|
||||
remove: (klasses...) ->
|
||||
delete @deserializers[klass.name] for klass in klasses
|
||||
|
||||
@@ -32,7 +34,7 @@ class DeserializerManager
|
||||
else
|
||||
console.warn "No deserializer found for", state
|
||||
|
||||
# Public: Get the deserializer for the state.
|
||||
# Private: Get the deserializer for the state.
|
||||
get: (state) ->
|
||||
return unless state?
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class DisplayBuffer
|
||||
_.extend @prototype, ConfigObserver
|
||||
|
||||
@acceptsDocuments: true
|
||||
registerDeserializer(this)
|
||||
atom.deserializers.add(this)
|
||||
@version: 2
|
||||
|
||||
@deserialize: (state) -> new this(state)
|
||||
@@ -27,7 +27,7 @@ class DisplayBuffer
|
||||
if optionsOrState instanceof telepath.Document
|
||||
@state = optionsOrState
|
||||
@id = @state.get('id')
|
||||
@tokenizedBuffer = deserialize(@state.get('tokenizedBuffer'))
|
||||
@tokenizedBuffer = atom.deserializers.deserialize(@state.get('tokenizedBuffer'))
|
||||
@buffer = @tokenizedBuffer.buffer
|
||||
else
|
||||
{@buffer, softWrap, editorWidthInChars} = optionsOrState
|
||||
@@ -365,7 +365,9 @@ class DisplayBuffer
|
||||
setTabLength: (tabLength) ->
|
||||
@tokenizedBuffer.setTabLength(tabLength)
|
||||
|
||||
# Retrieves the grammar for the buffer.
|
||||
# Get the grammar for this buffer.
|
||||
#
|
||||
# Returns the current {TextMateGrammar} or the {NullGrammar}.
|
||||
getGrammar: ->
|
||||
@tokenizedBuffer.grammar
|
||||
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+1316
-1731
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+3
-1
@@ -58,7 +58,7 @@ class File
|
||||
previouslyExisted = @exists()
|
||||
@cachedContents = text
|
||||
fs.writeFileSync(@getPath(), text)
|
||||
@subscribeToNativeChangeEvents() if not previouslyExisted and @subscriptionCount() > 0
|
||||
@subscribeToNativeChangeEvents() if not previouslyExisted and @hasSubscriptions()
|
||||
|
||||
# Private: Deprecated
|
||||
readSync: (flushCache) ->
|
||||
@@ -112,9 +112,11 @@ class File
|
||||
exists: ->
|
||||
fs.existsSync(@getPath())
|
||||
|
||||
# Private:
|
||||
setDigest: (contents) ->
|
||||
@digest = crypto.createHash('sha1').update(contents ? '').digest('hex')
|
||||
|
||||
# Public: Get the SHA-1 digest of this file
|
||||
getDigest: ->
|
||||
@digest ? @setDigest(@readSync())
|
||||
|
||||
|
||||
+5
-6
@@ -12,7 +12,7 @@ GitUtils = require 'git-utils'
|
||||
# ## Example
|
||||
#
|
||||
# ```coffeescript
|
||||
# git = global.project.getRepo()
|
||||
# git = atom.project.getRepo()
|
||||
# console.log git.getOriginUrl()
|
||||
# ```
|
||||
module.exports =
|
||||
@@ -61,7 +61,7 @@ class Git
|
||||
|
||||
@statuses = {}
|
||||
@upstream = {ahead: 0, behind: 0}
|
||||
{project, refreshOnWindowFocus} = options
|
||||
{@project, refreshOnWindowFocus} = options
|
||||
|
||||
refreshOnWindowFocus ?= true
|
||||
if refreshOnWindowFocus
|
||||
@@ -70,9 +70,8 @@ class Git
|
||||
@refreshIndex()
|
||||
@refreshStatus()
|
||||
|
||||
if project?
|
||||
@subscribeToBuffer(buffer) for buffer in project.getBuffers()
|
||||
@subscribe project, 'buffer-created', (buffer) => @subscribeToBuffer(buffer)
|
||||
if @project?
|
||||
@subscribe @project.buffers.onEach (buffer) => @subscribeToBuffer(buffer)
|
||||
|
||||
# Private: Subscribes to buffer events.
|
||||
subscribeToBuffer: (buffer) ->
|
||||
@@ -146,7 +145,7 @@ class Git
|
||||
# Public: Returns true if at the root, false if in a subfolder of the
|
||||
# repository.
|
||||
isProjectAtRoot: ->
|
||||
@projectAtRoot ?= project.relativize(@getWorkingDirectory()) is ''
|
||||
@projectAtRoot ?= @project?.relativize(@getWorkingDirectory()) is ''
|
||||
|
||||
# Public: Makes a path relative to the repository's working directory.
|
||||
relativize: (path) -> @getRepo().relativize(path)
|
||||
|
||||
+22
-22
@@ -2,7 +2,7 @@
|
||||
{Range} = require 'telepath'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
# Private: Represents the portion of the {Editor} containing row numbers.
|
||||
# Private: Represents the portion of the {EditorView} containing row numbers.
|
||||
#
|
||||
# The gutter also indicates if rows are folded.
|
||||
module.exports =
|
||||
@@ -25,37 +25,37 @@ class Gutter extends View
|
||||
@attached = true
|
||||
|
||||
highlightLines = => @highlightLines()
|
||||
@getEditor().on 'cursor:moved', highlightLines
|
||||
@getEditor().on 'selection:changed', highlightLines
|
||||
@getEditorView().on 'cursor:moved', highlightLines
|
||||
@getEditorView().on 'selection:changed', highlightLines
|
||||
@on 'mousedown', (e) => @handleMouseEvents(e)
|
||||
|
||||
beforeRemove: ->
|
||||
$(document).off(".gutter-#{@getEditor().id}")
|
||||
$(document).off(".gutter-#{@getEditorView().id}")
|
||||
|
||||
handleMouseEvents: (e) ->
|
||||
editor = @getEditor()
|
||||
startRow = editor.screenPositionFromMouseEvent(e).row
|
||||
editorView = @getEditorView()
|
||||
startRow = editorView.screenPositionFromMouseEvent(e).row
|
||||
if e.shiftKey
|
||||
editor.selectToScreenPosition([startRow + 1, 0])
|
||||
editorView.selectToScreenPosition([startRow + 1, 0])
|
||||
return
|
||||
else
|
||||
editor.getSelection().setScreenRange([[startRow, 0], [startRow, 0]])
|
||||
editorView.getSelection().setScreenRange([[startRow, 0], [startRow, 0]])
|
||||
|
||||
moveHandler = (e) =>
|
||||
start = startRow
|
||||
end = editor.screenPositionFromMouseEvent(e).row
|
||||
end = editorView.screenPositionFromMouseEvent(e).row
|
||||
if end > start then end++ else start++
|
||||
editor.getSelection().setScreenRange([[start, 0], [end, 0]])
|
||||
editorView.getSelection().setScreenRange([[start, 0], [end, 0]])
|
||||
|
||||
$(document).on "mousemove.gutter-#{@getEditor().id}", moveHandler
|
||||
$(document).one "mouseup.gutter-#{@getEditor().id}", => $(document).off 'mousemove', moveHandler
|
||||
$(document).on "mousemove.gutter-#{@getEditorView().id}", moveHandler
|
||||
$(document).one "mouseup.gutter-#{@getEditorView().id}", => $(document).off 'mousemove', moveHandler
|
||||
|
||||
### Public ###
|
||||
|
||||
# Retrieves the containing {Editor}.
|
||||
# Retrieves the containing {EditorView}.
|
||||
#
|
||||
# Returns an {Editor}.
|
||||
getEditor: ->
|
||||
# Returns an {EditorView}.
|
||||
getEditorView: ->
|
||||
@parentView
|
||||
|
||||
# Defines whether to show the gutter or not.
|
||||
@@ -192,9 +192,9 @@ class Gutter extends View
|
||||
@elementBuilder.children
|
||||
|
||||
buildLineElementsHtml: (startScreenRow, endScreenRow) =>
|
||||
editor = @getEditor()
|
||||
maxDigits = editor.getLineCount().toString().length
|
||||
rows = editor.bufferRowsForScreenRows(startScreenRow, endScreenRow)
|
||||
editorView = @getEditorView()
|
||||
maxDigits = editorView.getLineCount().toString().length
|
||||
rows = editorView.bufferRowsForScreenRows(startScreenRow, endScreenRow)
|
||||
|
||||
html = ''
|
||||
for row in rows
|
||||
@@ -204,7 +204,7 @@ class Gutter extends View
|
||||
rowValue = (row + 1).toString()
|
||||
|
||||
classes = "line-number line-number-#{row}"
|
||||
classes += ' fold' if editor.isFoldedAtBufferRow(row)
|
||||
classes += ' fold' if editorView.isFoldedAtBufferRow(row)
|
||||
|
||||
rowValuePadding = _.multiplyString(' ', maxDigits - rowValue.length)
|
||||
|
||||
@@ -230,8 +230,8 @@ class Gutter extends View
|
||||
@highlightedLineNumbers.push(highlightedLineNumber)
|
||||
|
||||
highlightLines: ->
|
||||
if @getEditor().getSelection().isEmpty()
|
||||
row = @getEditor().getCursorScreenPosition().row
|
||||
if @getEditorView().getSelection().isEmpty()
|
||||
row = @getEditorView().getCursorScreenPosition().row
|
||||
rowRange = new Range([row, 0], [row, 0])
|
||||
return if @selectionEmpty and @highlightedRows?.isEqual(rowRange)
|
||||
|
||||
@@ -240,7 +240,7 @@ class Gutter extends View
|
||||
@highlightedRows = rowRange
|
||||
@selectionEmpty = true
|
||||
else
|
||||
selectedRows = @getEditor().getSelection().getScreenRange()
|
||||
selectedRows = @getEditorView().getSelection().getScreenRange()
|
||||
endRow = selectedRows.end.row
|
||||
endRow-- if selectedRows.end.column is 0
|
||||
selectedRows = new Range([selectedRows.start.row, 0], [endRow, 0])
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
{specificity} = require 'clear-cut'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class KeyBinding
|
||||
@parser: null
|
||||
@currentIndex: 1
|
||||
|
||||
@normalizeKeystroke: (keystroke) ->
|
||||
normalizedKeystroke = keystroke.split(/\s+/).map (keystroke) =>
|
||||
keys = @getParser().parse(keystroke)
|
||||
modifiers = keys[0...-1]
|
||||
modifiers.sort()
|
||||
[modifiers..., _.last(keys)].join('-')
|
||||
normalizedKeystroke.join(' ')
|
||||
|
||||
@getParser: ->
|
||||
if not KeyBinding.parser
|
||||
keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8')
|
||||
KeyBinding.parser = PEG.buildParser(keystrokePattern)
|
||||
|
||||
KeyBinding.parser
|
||||
|
||||
constructor: (source, command, keystroke, selector) ->
|
||||
@source = source
|
||||
@command = command
|
||||
@keystroke = KeyBinding.normalizeKeystroke(keystroke)
|
||||
@selector = selector.replace(/!important/g, '')
|
||||
@specificity = specificity(selector)
|
||||
@index = KeyBinding.currentIndex++
|
||||
|
||||
matches: (keystroke) ->
|
||||
multiKeystroke = /\s/.test keystroke
|
||||
if multiKeystroke
|
||||
keystroke == @keystroke
|
||||
else
|
||||
keystroke.split(' ')[0] == @keystroke.split(' ')[0]
|
||||
|
||||
compare: (keyBinding) ->
|
||||
if keyBinding.specificity == @specificity
|
||||
keyBinding.index - @index
|
||||
else
|
||||
keyBinding.specificity - @specificity
|
||||
+124
-169
@@ -3,10 +3,10 @@ _ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
CSON = require 'season'
|
||||
BindingSet = require './binding-set'
|
||||
KeyBinding = require './key-binding'
|
||||
{Emitter} = require 'emissary'
|
||||
|
||||
Modifiers = ['alt', 'control', 'ctrl', 'shift', 'meta']
|
||||
Modifiers = ['alt', 'control', 'ctrl', 'shift', 'cmd']
|
||||
|
||||
# Internal: Associates keymaps with actions.
|
||||
#
|
||||
@@ -25,14 +25,94 @@ module.exports =
|
||||
class Keymap
|
||||
Emitter.includeInto(this)
|
||||
|
||||
bindingSets: null
|
||||
nextBindingSetIndex: 0
|
||||
bindingSetsByFirstKeystroke: null
|
||||
queuedKeystrokes: null
|
||||
|
||||
constructor: ({@resourcePath, @configDirPath})->
|
||||
@bindingSets = []
|
||||
@bindingSetsByFirstKeystroke = {}
|
||||
@keyBindings = []
|
||||
|
||||
# Public: Returns an array of all {KeyBinding}s.
|
||||
getKeyBindings: ->
|
||||
_.clone(@keyBindings)
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# that match a keystroke and element.
|
||||
#
|
||||
# * keystroke:
|
||||
# The string representing the keys pressed (e.g. ctrl-P).
|
||||
# * element:
|
||||
# The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsForKeystrokeMatchingElement: (keystroke, element) ->
|
||||
keyBindings = @keyBindingsForKeystroke(keystroke)
|
||||
@keyBindingsMatchingElement(element, keyBindings)
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# that match a command.
|
||||
#
|
||||
# * command:
|
||||
# The string representing the command (tree-view:toggle)
|
||||
# * element:
|
||||
# The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsForCommandMatchingElement: (command, element) ->
|
||||
keyBindings = @keyBindingsForCommand(command)
|
||||
@keyBindingsMatchingElement(element, keyBindings)
|
||||
|
||||
# Public: Returns an array of {KeyBinding}s that match a keystroke
|
||||
# * keystroke:
|
||||
# The string representing the keys pressed (e.g. ctrl-P)
|
||||
keyBindingsForKeystroke: (keystroke) ->
|
||||
keystroke = KeyBinding.normalizeKeystroke(keystroke)
|
||||
@keyBindings.filter (keyBinding) -> keyBinding.matches(keystroke)
|
||||
|
||||
# Public: Returns an array of {KeyBinding}s that match a command
|
||||
# * keystroke:
|
||||
# The string representing the keys pressed (e.g. ctrl-P)
|
||||
keyBindingsForCommand: (command) ->
|
||||
@keyBindings.filter (keyBinding) -> keyBinding.command == command
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# whos selector matches the element.
|
||||
#
|
||||
# * element:
|
||||
# The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsMatchingElement: (element, keyBindings=@keyBindings) ->
|
||||
keyBindings = keyBindings.filter ({selector}) -> $(element).closest(selector).length > 0
|
||||
keyBindings.sort (a, b) -> a.compare(b)
|
||||
|
||||
# Public: Returns a keystroke string derived from an event.
|
||||
# * event:
|
||||
# A DOM or jQuery event
|
||||
# * previousKeystroke:
|
||||
# An optional string used for multiKeystrokes
|
||||
keystrokeStringForEvent: (event, previousKeystroke) ->
|
||||
if event.originalEvent.keyIdentifier.indexOf('U+') == 0
|
||||
hexCharCode = event.originalEvent.keyIdentifier[2..]
|
||||
charCode = parseInt(hexCharCode, 16)
|
||||
charCode = event.which if !@isAscii(charCode) and @isAscii(event.which)
|
||||
key = @keyFromCharCode(charCode)
|
||||
else
|
||||
key = event.originalEvent.keyIdentifier.toLowerCase()
|
||||
|
||||
modifiers = []
|
||||
if event.altKey and key not in Modifiers
|
||||
modifiers.push 'alt'
|
||||
if event.metaKey and key not in Modifiers
|
||||
modifiers.push 'cmd'
|
||||
if event.ctrlKey and key not in Modifiers
|
||||
modifiers.push 'ctrl'
|
||||
|
||||
if event.shiftKey and key not in Modifiers
|
||||
isNamedKey = key.length > 1
|
||||
modifiers.push 'shift' if isNamedKey
|
||||
else
|
||||
key = key.toLowerCase()
|
||||
|
||||
keystroke = [modifiers..., key].join('-')
|
||||
|
||||
if previousKeystroke
|
||||
if keystroke in Modifiers
|
||||
previousKeystroke
|
||||
else
|
||||
"#{previousKeystroke} #{keystroke}"
|
||||
else
|
||||
keystroke
|
||||
|
||||
loadBundledKeymaps: ->
|
||||
@loadDirectory(path.join(@resourcePath, 'keymaps'))
|
||||
@@ -48,175 +128,50 @@ class Keymap
|
||||
load: (path) ->
|
||||
@add(path, CSON.readFileSync(path))
|
||||
|
||||
add: (args...) ->
|
||||
name = args.shift() if args.length > 1
|
||||
keymap = args.shift()
|
||||
for selector, bindings of keymap
|
||||
@bindKeys(name, selector, bindings)
|
||||
add: (source, keyMappingsBySelector) ->
|
||||
for selector, keyMappings of keyMappingsBySelector
|
||||
@bindKeys(source, selector, keyMappings)
|
||||
|
||||
remove: (name) ->
|
||||
for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name)
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0]
|
||||
_.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet)
|
||||
remove: (source) ->
|
||||
@keyBindings = @keyBindings.filter (keyBinding) -> keyBinding.source isnt source
|
||||
|
||||
# Public: Returns an array of objects that represent every keystroke to
|
||||
# command mapping. Each object contains the following keys `source`,
|
||||
# `selector`, `command`, `keystrokes`.
|
||||
getAllKeyMappings: ->
|
||||
mappings = []
|
||||
for bindingSet in @bindingSets
|
||||
selector = bindingSet.getSelector()
|
||||
source = @determineSource(bindingSet.getName())
|
||||
for keystrokes, command of bindingSet.getCommandsByKeystrokes()
|
||||
mappings.push {keystrokes, command, selector, source}
|
||||
bindKeys: (source, selector, keyMappings) ->
|
||||
for keystroke, command of keyMappings
|
||||
@keyBindings.push new KeyBinding(source, command, keystroke, selector)
|
||||
|
||||
mappings
|
||||
handleKeyEvent: (event) ->
|
||||
element = event.target
|
||||
element = atom.rootView if element == document.body
|
||||
keystroke = @keystrokeStringForEvent(event, @queuedKeystroke)
|
||||
keyBindings = @keyBindingsForKeystrokeMatchingElement(keystroke, element)
|
||||
|
||||
# Private: Returns a user friendly description of where a keybinding was
|
||||
# loaded from.
|
||||
#
|
||||
# * filePath:
|
||||
# The absolute path from which the keymap was loaded
|
||||
#
|
||||
# Returns one of:
|
||||
# * `Core` indicates it comes from a bundled package.
|
||||
# * `User` indicates that it was defined by a user.
|
||||
# * `<package-name>` the package which defined it.
|
||||
# * `Unknown` if an invalid path was passed in.
|
||||
determineSource: (filePath) ->
|
||||
return 'Unknown' unless filePath
|
||||
|
||||
pathParts = filePath.split(path.sep)
|
||||
if _.contains(pathParts, 'node_modules') or _.contains(pathParts, 'atom') or _.contains(pathParts, 'src')
|
||||
'Core'
|
||||
else if _.contains(pathParts, '.atom') and _.contains(pathParts, 'keymaps') and !_.contains(pathParts, 'packages')
|
||||
'User'
|
||||
if keyBindings.length == 0 and @queuedKeystroke
|
||||
@queuedKeystroke = null
|
||||
return false
|
||||
else
|
||||
packageNameIndex = pathParts.length - 3
|
||||
pathParts[packageNameIndex]
|
||||
@queuedKeystroke = null
|
||||
|
||||
bindKeys: (args...) ->
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, bindings] = args
|
||||
bindingSet = new BindingSet(selector, bindings, @nextBindingSetIndex++, name)
|
||||
@bindingSets.unshift(bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0] # only index by first keystroke
|
||||
@bindingSetsByFirstKeystroke[keystroke] ?= []
|
||||
@bindingSetsByFirstKeystroke[keystroke].push(bindingSet)
|
||||
|
||||
unbindKeys: (selector, bindings) ->
|
||||
bindingSet = _.detect @bindingSets, (bindingSet) ->
|
||||
bindingSet.selector is selector and bindingSet.bindings is bindings
|
||||
|
||||
if bindingSet
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
|
||||
bindingsForElement: (element) ->
|
||||
keystrokeMap = {}
|
||||
currentNode = $(element)
|
||||
|
||||
while currentNode.length
|
||||
bindingSets = @bindingSetsForNode(currentNode)
|
||||
_.defaults(keystrokeMap, set.commandsByKeystrokes) for set in bindingSets
|
||||
currentNode = currentNode.parent()
|
||||
|
||||
keystrokeMap
|
||||
|
||||
handleKeyEvent: (event) =>
|
||||
event.keystrokes = @multiKeystrokeStringForEvent(event)
|
||||
isMultiKeystroke = @queuedKeystrokes?
|
||||
@queuedKeystrokes = null
|
||||
|
||||
firstKeystroke = event.keystrokes.split(' ')[0]
|
||||
bindingSetsForFirstKeystroke = @bindingSetsByFirstKeystroke[firstKeystroke]
|
||||
if bindingSetsForFirstKeystroke?
|
||||
currentNode = $(event.target)
|
||||
currentNode = rootView if currentNode is $('body')[0]
|
||||
while currentNode.length
|
||||
candidateBindingSets = @bindingSetsForNode(currentNode, bindingSetsForFirstKeystroke)
|
||||
for bindingSet in candidateBindingSets
|
||||
command = bindingSet.commandForEvent(event)
|
||||
if command is 'native!'
|
||||
return true
|
||||
else if command
|
||||
continue if @triggerCommandEvent(event, command)
|
||||
return false
|
||||
else if command == false
|
||||
return false
|
||||
|
||||
if bindingSet.matchesKeystrokePrefix(event)
|
||||
@queuedKeystrokes = event.keystrokes
|
||||
return false
|
||||
currentNode = currentNode.parent()
|
||||
|
||||
return false if isMultiKeystroke
|
||||
return false if firstKeystroke is 'tab'
|
||||
|
||||
bindingSetsForNode: (node, candidateBindingSets = @bindingSets) ->
|
||||
bindingSets = candidateBindingSets.filter (set) -> node.is(set.selector)
|
||||
bindingSets.sort (a, b) ->
|
||||
if b.specificity == a.specificity
|
||||
b.index - a.index
|
||||
for keyBinding in keyBindings
|
||||
partialMatch = keyBinding.keystroke isnt keystroke
|
||||
if partialMatch
|
||||
@queuedKeystroke = keystroke
|
||||
shouldBubble = false
|
||||
else
|
||||
b.specificity - a.specificity
|
||||
if keyBinding.command is 'native!'
|
||||
shouldBubble = true
|
||||
else if @triggerCommandEvent(element, keyBinding.command, event)
|
||||
shouldBubble = false
|
||||
|
||||
triggerCommandEvent: (keyEvent, commandName) ->
|
||||
keyEvent.target = rootView[0] if keyEvent.target == document.body and window.rootView
|
||||
break if shouldBubble?
|
||||
|
||||
shouldBubble ? true
|
||||
|
||||
triggerCommandEvent: (element, commandName, event) ->
|
||||
commandEvent = $.Event(commandName)
|
||||
commandEvent.keyEvent = keyEvent
|
||||
aborted = false
|
||||
commandEvent.abortKeyBinding = ->
|
||||
@stopImmediatePropagation()
|
||||
aborted = true
|
||||
$(keyEvent.target).trigger(commandEvent)
|
||||
aborted
|
||||
|
||||
multiKeystrokeStringForEvent: (event) ->
|
||||
currentKeystroke = @keystrokeStringForEvent(event)
|
||||
if @queuedKeystrokes
|
||||
if currentKeystroke in Modifiers
|
||||
@queuedKeystrokes
|
||||
else
|
||||
@queuedKeystrokes + ' ' + currentKeystroke
|
||||
else
|
||||
currentKeystroke
|
||||
|
||||
keystrokeStringForEvent: (event) ->
|
||||
if event.originalEvent.keyIdentifier.indexOf('U+') == 0
|
||||
hexCharCode = event.originalEvent.keyIdentifier[2..]
|
||||
charCode = parseInt(hexCharCode, 16)
|
||||
charCode = event.which if !@isAscii(charCode) and @isAscii(event.which)
|
||||
key = @keyFromCharCode(charCode)
|
||||
else
|
||||
key = event.originalEvent.keyIdentifier.toLowerCase()
|
||||
|
||||
modifiers = []
|
||||
if event.altKey and key not in Modifiers
|
||||
modifiers.push 'alt'
|
||||
if event.ctrlKey and key not in Modifiers
|
||||
modifiers.push 'ctrl'
|
||||
if event.metaKey and key not in Modifiers
|
||||
modifiers.push 'meta'
|
||||
|
||||
if event.shiftKey and key not in Modifiers
|
||||
isNamedKey = key.length > 1
|
||||
modifiers.push 'shift' if isNamedKey
|
||||
else
|
||||
key = key.toLowerCase()
|
||||
|
||||
[modifiers..., key].join('-')
|
||||
|
||||
keystrokesByCommandForSelector: (selector)->
|
||||
keystrokesByCommand = {}
|
||||
for bindingSet in @bindingSets
|
||||
for keystroke, command of bindingSet.commandsByKeystrokes
|
||||
continue if selector? and selector != bindingSet.selector
|
||||
keystrokesByCommand[command] ?= []
|
||||
keystrokesByCommand[command].push keystroke
|
||||
keystrokesByCommand
|
||||
commandEvent.originalEvent = event
|
||||
commandEvent.abortKeyBinding = -> commandEvent.stopImmediatePropagation()
|
||||
$(element).trigger(commandEvent)
|
||||
not commandEvent.isImmediatePropagationStopped()
|
||||
|
||||
isAscii: (charCode) ->
|
||||
0 <= charCode <= 127
|
||||
|
||||
+45
-45
@@ -12,7 +12,7 @@ class LanguageMode
|
||||
|
||||
buffer: null
|
||||
grammar: null
|
||||
editSession: null
|
||||
editor: null
|
||||
currentGrammarScore: null
|
||||
|
||||
### Internal ###
|
||||
@@ -22,11 +22,11 @@ class LanguageMode
|
||||
|
||||
### Public ###
|
||||
|
||||
# Sets up a `LanguageMode` for the given {EditSession}.
|
||||
# Sets up a `LanguageMode` for the given {Editor}.
|
||||
#
|
||||
# editSession - The {EditSession} to associate with
|
||||
constructor: (@editSession) ->
|
||||
@buffer = @editSession.buffer
|
||||
# editor - The {Editor} to associate with
|
||||
constructor: (@editor) ->
|
||||
@buffer = @editor.buffer
|
||||
|
||||
# Wraps the lines between two rows in comments.
|
||||
#
|
||||
@@ -37,7 +37,7 @@ class LanguageMode
|
||||
#
|
||||
# Returns an {Array} of the commented {Ranges}.
|
||||
toggleLineCommentsForBufferRows: (start, end) ->
|
||||
scopes = @editSession.scopesForBufferPosition([start, 0])
|
||||
scopes = @editor.scopesForBufferPosition([start, 0])
|
||||
properties = atom.syntax.propertiesForScope(scopes, "editor.commentStart")[0]
|
||||
return unless properties
|
||||
|
||||
@@ -46,7 +46,7 @@ class LanguageMode
|
||||
|
||||
return unless commentStartString
|
||||
|
||||
buffer = @editSession.buffer
|
||||
buffer = @editor.buffer
|
||||
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?')
|
||||
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
|
||||
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
|
||||
@@ -83,8 +83,8 @@ class LanguageMode
|
||||
buffer.change([[row, columnStart], [row, columnEnd]], "")
|
||||
else
|
||||
indent = @minIndentLevelForRowRange(start, end)
|
||||
indentString = @editSession.buildIndentString(indent)
|
||||
tabLength = @editSession.getTabLength()
|
||||
indentString = @editor.buildIndentString(indent)
|
||||
tabLength = @editor.getTabLength()
|
||||
indentRegex = new RegExp("(\t|[ ]{#{tabLength}}){#{Math.floor(indent)}}")
|
||||
for row in [start..end]
|
||||
line = buffer.lineForRow(row)
|
||||
@@ -98,12 +98,12 @@ class LanguageMode
|
||||
for currentRow in [0..@buffer.getLastRow()]
|
||||
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
continue unless startRow?
|
||||
@editSession.createFold(startRow, endRow)
|
||||
@editor.createFold(startRow, endRow)
|
||||
|
||||
# Unfolds all the foldable lines in the buffer.
|
||||
unfoldAll: ->
|
||||
for row in [@buffer.getLastRow()..0]
|
||||
fold.destroy() for fold in @editSession.displayBuffer.foldsStartingAtBufferRow(row)
|
||||
fold.destroy() for fold in @editor.displayBuffer.foldsStartingAtBufferRow(row)
|
||||
|
||||
# Fold all comment and code blocks at a given indentLevel
|
||||
#
|
||||
@@ -114,8 +114,8 @@ class LanguageMode
|
||||
continue unless startRow?
|
||||
|
||||
# assumption: startRow will always be the min indent level for the entire range
|
||||
if @editSession.indentationForBufferRow(startRow) == indentLevel
|
||||
@editSession.createFold(startRow, endRow)
|
||||
if @editor.indentationForBufferRow(startRow) == indentLevel
|
||||
@editor.createFold(startRow, endRow)
|
||||
|
||||
# Given a buffer row, creates a fold at it.
|
||||
#
|
||||
@@ -126,14 +126,14 @@ class LanguageMode
|
||||
for currentRow in [bufferRow..0]
|
||||
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
continue unless startRow? and startRow <= bufferRow <= endRow
|
||||
fold = @editSession.displayBuffer.largestFoldStartingAtBufferRow(startRow)
|
||||
return @editSession.createFold(startRow, endRow) unless fold
|
||||
fold = @editor.displayBuffer.largestFoldStartingAtBufferRow(startRow)
|
||||
return @editor.createFold(startRow, endRow) unless fold
|
||||
|
||||
# Given a buffer row, this unfolds it.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
unfoldBufferRow: (bufferRow) ->
|
||||
@editSession.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy()
|
||||
@editor.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy()
|
||||
|
||||
# Find the row range for a fold at a given bufferRow. Will handle comments
|
||||
# and code.
|
||||
@@ -147,30 +147,30 @@ class LanguageMode
|
||||
rowRange
|
||||
|
||||
rowRangeForCommentAtBufferRow: (bufferRow) ->
|
||||
return unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment()
|
||||
return unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment()
|
||||
|
||||
startRow = bufferRow
|
||||
for currentRow in [bufferRow-1..0]
|
||||
break if @buffer.isRowBlank(currentRow)
|
||||
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
startRow = currentRow
|
||||
endRow = bufferRow
|
||||
for currentRow in [bufferRow+1..@buffer.getLastRow()]
|
||||
break if @buffer.isRowBlank(currentRow)
|
||||
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
endRow = currentRow
|
||||
return [startRow, endRow] if startRow isnt endRow
|
||||
|
||||
rowRangeForCodeFoldAtBufferRow: (bufferRow) ->
|
||||
return null unless @doesBufferRowStartFold(bufferRow)
|
||||
|
||||
startIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
||||
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
|
||||
for row in [(bufferRow + 1)..@editSession.getLastBufferRow()]
|
||||
continue if @editSession.isBufferRowBlank(row)
|
||||
indentation = @editSession.indentationForBufferRow(row)
|
||||
startIndentLevel = @editor.indentationForBufferRow(bufferRow)
|
||||
scopes = @editor.scopesForBufferPosition([bufferRow, 0])
|
||||
for row in [(bufferRow + 1)..@editor.getLastBufferRow()]
|
||||
continue if @editor.isBufferRowBlank(row)
|
||||
indentation = @editor.indentationForBufferRow(row)
|
||||
if indentation <= startIndentLevel
|
||||
includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editSession.lineForBufferRow(row))
|
||||
includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editor.lineForBufferRow(row))
|
||||
foldEndRow = row if includeRowInFold
|
||||
break
|
||||
|
||||
@@ -179,19 +179,19 @@ class LanguageMode
|
||||
[bufferRow, foldEndRow]
|
||||
|
||||
doesBufferRowStartFold: (bufferRow) ->
|
||||
return false if @editSession.isBufferRowBlank(bufferRow)
|
||||
nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow)
|
||||
return false if @editor.isBufferRowBlank(bufferRow)
|
||||
nextNonEmptyRow = @editor.nextNonBlankBufferRow(bufferRow)
|
||||
return false unless nextNonEmptyRow?
|
||||
@editSession.indentationForBufferRow(nextNonEmptyRow) > @editSession.indentationForBufferRow(bufferRow)
|
||||
@editor.indentationForBufferRow(nextNonEmptyRow) > @editor.indentationForBufferRow(bufferRow)
|
||||
|
||||
# Find a row range for a 'paragraph' around specified bufferRow.
|
||||
# Right now, a paragraph is a block of text bounded by and empty line or a
|
||||
# block of text that is not the same type (comments next to source code).
|
||||
rowRangeForParagraphAtBufferRow: (bufferRow) ->
|
||||
return unless /\w/.test(@editSession.lineForBufferRow(bufferRow))
|
||||
return unless /\w/.test(@editor.lineForBufferRow(bufferRow))
|
||||
|
||||
isRowComment = (row) =>
|
||||
@editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
|
||||
@editor.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
|
||||
|
||||
if isRowComment(bufferRow)
|
||||
isOriginalRowComment = true
|
||||
@@ -199,22 +199,22 @@ class LanguageMode
|
||||
[firstRow, lastRow] = range or [bufferRow, bufferRow]
|
||||
else
|
||||
isOriginalRowComment = false
|
||||
[firstRow, lastRow] = [0, @editSession.getLastBufferRow()-1]
|
||||
[firstRow, lastRow] = [0, @editor.getLastBufferRow()-1]
|
||||
|
||||
startRow = bufferRow
|
||||
while startRow > firstRow
|
||||
break if isRowComment(startRow - 1) != isOriginalRowComment
|
||||
break unless /\w/.test(@editSession.lineForBufferRow(startRow - 1))
|
||||
break unless /\w/.test(@editor.lineForBufferRow(startRow - 1))
|
||||
startRow--
|
||||
|
||||
endRow = bufferRow
|
||||
lastRow = @editSession.getLastBufferRow()
|
||||
lastRow = @editor.getLastBufferRow()
|
||||
while endRow < lastRow
|
||||
break if isRowComment(endRow + 1) != isOriginalRowComment
|
||||
break unless /\w/.test(@editSession.lineForBufferRow(endRow + 1))
|
||||
break unless /\w/.test(@editor.lineForBufferRow(endRow + 1))
|
||||
endRow++
|
||||
|
||||
new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)])
|
||||
new Range([startRow, 0], [endRow, @editor.lineLengthForBufferRow(endRow)])
|
||||
|
||||
# Given a buffer row, this returns a suggested indentation level.
|
||||
#
|
||||
@@ -224,8 +224,8 @@ class LanguageMode
|
||||
#
|
||||
# Returns a {Number}.
|
||||
suggestedIndentForBufferRow: (bufferRow) ->
|
||||
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
||||
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
|
||||
currentIndentLevel = @editor.indentationForBufferRow(bufferRow)
|
||||
scopes = @editor.scopesForBufferPosition([bufferRow, 0])
|
||||
return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
|
||||
|
||||
currentLine = @buffer.lineForRow(bufferRow)
|
||||
@@ -233,8 +233,8 @@ class LanguageMode
|
||||
return currentIndentLevel unless precedingRow?
|
||||
|
||||
precedingLine = @buffer.lineForRow(precedingRow)
|
||||
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
|
||||
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editSession.isBufferRowCommented(precedingRow)
|
||||
desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
|
||||
desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editor.isBufferRowCommented(precedingRow)
|
||||
|
||||
return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
|
||||
desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine)
|
||||
@@ -248,7 +248,7 @@ class LanguageMode
|
||||
#
|
||||
# Returns a {Number} of the indent level of the block of lines.
|
||||
minIndentLevelForRowRange: (startRow, endRow) ->
|
||||
indents = (@editSession.indentationForBufferRow(row) for row in [startRow..endRow] when not @editSession.isBufferRowBlank(row))
|
||||
indents = (@editor.indentationForBufferRow(row) for row in [startRow..endRow] when not @editor.isBufferRowBlank(row))
|
||||
indents = [0] unless indents.length
|
||||
Math.min(indents...)
|
||||
|
||||
@@ -264,13 +264,13 @@ class LanguageMode
|
||||
# bufferRow - The row {Number}
|
||||
autoIndentBufferRow: (bufferRow) ->
|
||||
indentLevel = @suggestedIndentForBufferRow(bufferRow)
|
||||
@editSession.setIndentationForBufferRow(bufferRow, indentLevel)
|
||||
@editor.setIndentationForBufferRow(bufferRow, indentLevel)
|
||||
|
||||
# Given a buffer row, this decreases the indentation.
|
||||
#
|
||||
# bufferRow - The row {Number}
|
||||
autoDecreaseIndentForBufferRow: (bufferRow) ->
|
||||
scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
|
||||
scopes = @editor.scopesForBufferPosition([bufferRow, 0])
|
||||
increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
|
||||
decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
|
||||
return unless increaseIndentRegex and decreaseIndentRegex
|
||||
@@ -278,16 +278,16 @@ class LanguageMode
|
||||
line = @buffer.lineForRow(bufferRow)
|
||||
return unless decreaseIndentRegex.test(line)
|
||||
|
||||
currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
|
||||
currentIndentLevel = @editor.indentationForBufferRow(bufferRow)
|
||||
return if currentIndentLevel is 0
|
||||
precedingRow = @buffer.previousNonBlankRow(bufferRow)
|
||||
return unless precedingRow?
|
||||
precedingLine = @buffer.lineForRow(precedingRow)
|
||||
|
||||
desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
|
||||
desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
|
||||
desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine)
|
||||
if desiredIndentLevel >= 0 and desiredIndentLevel < currentIndentLevel
|
||||
@editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
||||
@editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
||||
|
||||
tokenizeLine: (line, stack, firstLine) ->
|
||||
{tokens, stack} = @grammar.tokenizeLine(line, stack, firstLine)
|
||||
|
||||
@@ -5,27 +5,32 @@ LessCache = require 'less-cache'
|
||||
|
||||
tmpDir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
|
||||
|
||||
# Private: {LessCache} wrapper used by {ThemeManager} to read stylesheets.
|
||||
module.exports =
|
||||
class LessCompileCache
|
||||
Subscriber.includeInto(this)
|
||||
|
||||
@cacheDir: path.join(tmpDir, 'atom-compile-cache', 'less')
|
||||
|
||||
constructor: ({resourcePath}) ->
|
||||
constructor: ({resourcePath, importPaths}) ->
|
||||
@lessSearchPaths = [
|
||||
path.join(resourcePath, 'static', 'variables')
|
||||
path.join(resourcePath, 'static')
|
||||
]
|
||||
|
||||
if importPaths?
|
||||
importPaths = importPaths.concat(@lessSearchPaths)
|
||||
else
|
||||
importPaths = @lessSearchPaths
|
||||
|
||||
@cache = new LessCache
|
||||
cacheDir: @constructor.cacheDir
|
||||
importPaths: @getImportPaths()
|
||||
importPaths: importPaths
|
||||
resourcePath: resourcePath
|
||||
fallbackDir: path.join(resourcePath, 'less-compile-cache')
|
||||
|
||||
@subscribe atom.themes, 'reloaded', => @cache.setImportPaths(@getImportPaths())
|
||||
|
||||
getImportPaths: -> atom.themes.getImportPaths().concat(@lessSearchPaths)
|
||||
setImportPaths: (importPaths=[]) ->
|
||||
@cache.setImportPaths(importPaths.concat(@lessSearchPaths))
|
||||
|
||||
read: (stylesheetPath) -> @cache.readFileSync(stylesheetPath)
|
||||
|
||||
|
||||
+44
-15
@@ -14,7 +14,7 @@ class MenuManager
|
||||
# Private:
|
||||
constructor: ({@resourcePath}) ->
|
||||
@template = []
|
||||
atom.keymap.on 'bundled-keymaps-loaded', => @loadCoreItems()
|
||||
atom.keymap.on 'bundled-keymaps-loaded', => @loadPlatformItems()
|
||||
|
||||
# Public: Adds the given item definition to the existing template.
|
||||
#
|
||||
@@ -27,35 +27,55 @@ class MenuManager
|
||||
@merge(@template, item) for item in items
|
||||
@update()
|
||||
|
||||
# Private: Should the binding for the given selector be included in the menu
|
||||
# commands.
|
||||
#
|
||||
# * selector: A String selector to check.
|
||||
#
|
||||
# Returns true to include the selector, false otherwise.
|
||||
includeSelector: (selector) ->
|
||||
return true if document.body.webkitMatchesSelector(selector)
|
||||
|
||||
# Simulate an .editor element attached to a body element that has the same
|
||||
# classes as the current body element.
|
||||
unless @testEditor?
|
||||
@testEditor = document.createElement('div')
|
||||
@testEditor.classList.add('editor')
|
||||
testBody = document.createElement('body')
|
||||
testBody.classList.add(document.body.classList.toString().split(' ')...)
|
||||
testBody.appendChild(@testEditor)
|
||||
|
||||
@testEditor.webkitMatchesSelector(selector)
|
||||
|
||||
# Public: Refreshes the currently visible menu.
|
||||
update: ->
|
||||
keystrokesByCommand = atom.keymap.keystrokesByCommandForSelector('body')
|
||||
_.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor'))
|
||||
_.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor:not(.mini)'))
|
||||
keystrokesByCommand = {}
|
||||
for binding in atom.keymap.getKeyBindings() when @includeSelector(binding.selector)
|
||||
keystrokesByCommand[binding.command] ?= []
|
||||
keystrokesByCommand[binding.command].push binding.keystroke
|
||||
@sendToBrowserProcess(@template, keystrokesByCommand)
|
||||
|
||||
# Private
|
||||
loadCoreItems: ->
|
||||
# Private:
|
||||
loadPlatformItems: ->
|
||||
menusDirPath = path.join(@resourcePath, 'menus')
|
||||
menuPaths = fs.listSync(menusDirPath, ['cson', 'json'])
|
||||
for menuPath in menuPaths
|
||||
data = CSON.readFileSync(menuPath)
|
||||
@add(data.menu)
|
||||
platformMenuPath = fs.resolve(menusDirPath, process.platform, ['cson', 'json'])
|
||||
{menu} = CSON.readFileSync(platformMenuPath)
|
||||
@add(menu)
|
||||
|
||||
# Private: Merges an item in a submenu aware way such that new items are always
|
||||
# appended to the bottom of existing menus where possible.
|
||||
merge: (menu, item) ->
|
||||
item = _.deepClone(item)
|
||||
|
||||
if item.submenu? and match = _.find(menu, (i) -> i.submenu? and i.label == item.label)
|
||||
if item.submenu? and match = _.find(menu, (i) => i.submenu? and @normalizeLabel(i.label) == @normalizeLabel(item.label))
|
||||
@merge(match.submenu, i) for i in item.submenu
|
||||
else
|
||||
menu.push(item) unless _.find(menu, (i) -> i.label == item.label)
|
||||
menu.push(item) unless _.find(menu, (i) => @normalizeLabel(i.label) == @normalizeLabel(item.label))
|
||||
|
||||
# Private: OSX can't handle displaying accelerators for multiple keystrokes.
|
||||
# If they are sent across, it will stop processing accelerators for the rest
|
||||
# of the menu items.
|
||||
filterMultipleKeystrokes: (keystrokesByCommand) ->
|
||||
filterMultipleKeystroke: (keystrokesByCommand) ->
|
||||
filtered = {}
|
||||
for key, bindings of keystrokesByCommand
|
||||
for binding in bindings
|
||||
@@ -65,7 +85,16 @@ class MenuManager
|
||||
filtered[key].push(binding)
|
||||
filtered
|
||||
|
||||
# Private
|
||||
# Private:
|
||||
sendToBrowserProcess: (template, keystrokesByCommand) ->
|
||||
keystrokesByCommand = @filterMultipleKeystrokes(keystrokesByCommand)
|
||||
keystrokesByCommand = @filterMultipleKeystroke(keystrokesByCommand)
|
||||
ipc.sendChannel 'update-application-menu', template, keystrokesByCommand
|
||||
|
||||
# Private:
|
||||
normalizeLabel: (label) ->
|
||||
return undefined unless label?
|
||||
|
||||
if process.platform is 'win32'
|
||||
label.replace(/\&/g, '')
|
||||
else
|
||||
label
|
||||
|
||||
@@ -4,25 +4,26 @@ _ = require 'underscore-plus'
|
||||
Package = require './package'
|
||||
path = require 'path'
|
||||
|
||||
###
|
||||
Packages have a lifecycle
|
||||
|
||||
* The paths to all non-disabled packages and themes are found on disk (these are available packages)
|
||||
* Every package (except those in core.disabledPackages) is 'loaded', meaning
|
||||
`Package` objects are created, and their metadata loaded. This includes themes,
|
||||
as themes are packages
|
||||
* The ThemeManager.activateThemes() is called 'activating' all the themes, meaning
|
||||
their stylesheets are loaded into the window.
|
||||
* The PackageManager.activatePackages() function is called 'activating' non-theme
|
||||
package, meaning its resources -- keymaps, classes, etc. -- are loaded, and
|
||||
the package's activate() method is called.
|
||||
* Packages and themes can then be enabled and disabled via the public
|
||||
.enablePackage(name) and .disablePackage(name) functions.
|
||||
###
|
||||
# Public: Package manager for coordinating the lifecycle of Atom packages.
|
||||
#
|
||||
# Packages can be loaded, activated, and deactivated, and unloaded:
|
||||
# * Loading a package reads and parses the package's metadata and resources
|
||||
# such as keymaps, menus, stylesheets, etc.
|
||||
# * Activating a package registers the loaded resources and calls `activate()`
|
||||
# on the package's main module.
|
||||
# * Deactivating a package unregisters the package's resources and calls
|
||||
# `deactivate()` on the package's main module.
|
||||
# * Unloading a package removes it completely from the package manager.
|
||||
#
|
||||
# Packages can also be enabled/disabled via the `core.disabledPackages` config
|
||||
# settings and also by calling `enablePackage()/disablePackage()`.
|
||||
#
|
||||
# An instance of this class is globally available via `atom.packages`.
|
||||
module.exports =
|
||||
class PackageManager
|
||||
Emitter.includeInto(this)
|
||||
|
||||
# Private:
|
||||
constructor: ({configDirPath, devMode, @resourcePath}) ->
|
||||
@packageDirPaths = [path.join(configDirPath, "packages")]
|
||||
if devMode
|
||||
@@ -46,42 +47,44 @@ class PackageManager
|
||||
getPackageDirPaths: ->
|
||||
_.clone(@packageDirPaths)
|
||||
|
||||
# Private:
|
||||
getPackageState: (name) ->
|
||||
@packageStates[name]
|
||||
|
||||
# Private:
|
||||
setPackageState: (name, state) ->
|
||||
@packageStates[name] = state
|
||||
|
||||
# Public:
|
||||
# Public: Enable the package with the given name
|
||||
enablePackage: (name) ->
|
||||
pack = @loadPackage(name)
|
||||
pack?.enable()
|
||||
pack
|
||||
|
||||
# Public:
|
||||
# Public: Disable the package with the given name
|
||||
disablePackage: (name) ->
|
||||
pack = @loadPackage(name)
|
||||
pack?.disable()
|
||||
pack
|
||||
|
||||
# Internal-only: Activate all the packages that should be activated.
|
||||
# Private: Activate all the packages that should be activated.
|
||||
activate: ->
|
||||
for [activator, types] in @packageActivators
|
||||
packages = @getLoadedPackagesForTypes(types)
|
||||
activator.activatePackages(packages)
|
||||
@emit 'activated'
|
||||
|
||||
# Public: another type of package manager can handle other package types.
|
||||
# Private: another type of package manager can handle other package types.
|
||||
# See ThemeManager
|
||||
registerPackageActivator: (activator, types) ->
|
||||
@packageActivators.push([activator, types])
|
||||
|
||||
# Internal-only:
|
||||
# Private:
|
||||
activatePackages: (packages) ->
|
||||
@activatePackage(pack.name) for pack in packages
|
||||
@observeDisabledPackages()
|
||||
|
||||
# Internal-only: Activate a single package by name
|
||||
# Private: Activate a single package by name
|
||||
activatePackage: (name, options) ->
|
||||
return pack if pack = @getActivePackage(name)
|
||||
if pack = @loadPackage(name, options)
|
||||
@@ -89,10 +92,12 @@ class PackageManager
|
||||
pack.activate(options)
|
||||
pack
|
||||
|
||||
# Private: Deactivate all packages
|
||||
deactivatePackages: ->
|
||||
@deactivatePackage(pack.name) for pack in @getActivePackages()
|
||||
@unobserveDisabledPackages()
|
||||
|
||||
# Private: Deactivate the package with the given name
|
||||
deactivatePackage: (name) ->
|
||||
if pack = @getActivePackage(name)
|
||||
@setPackageState(pack.name, state) if state = pack.serialize?()
|
||||
@@ -101,20 +106,25 @@ class PackageManager
|
||||
else
|
||||
throw new Error("No active package for name '#{name}'")
|
||||
|
||||
# Public: Get an array of all the active packages
|
||||
getActivePackages: ->
|
||||
_.values(@activePackages)
|
||||
|
||||
# Public: Get the active package with the given name
|
||||
getActivePackage: (name) ->
|
||||
@activePackages[name]
|
||||
|
||||
# Public: Is the package with the given name active?
|
||||
isPackageActive: (name) ->
|
||||
@getActivePackage(name)?
|
||||
|
||||
# Private:
|
||||
unobserveDisabledPackages: ->
|
||||
return unless @observingDisabledPackages
|
||||
atom.config.unobserve('core.disabledPackages')
|
||||
@observingDisabledPackages = false
|
||||
|
||||
# Private:
|
||||
observeDisabledPackages: ->
|
||||
return if @observingDisabledPackages
|
||||
|
||||
@@ -128,6 +138,7 @@ class PackageManager
|
||||
|
||||
@observingDisabledPackages = true
|
||||
|
||||
# Private:
|
||||
loadPackages: (options) ->
|
||||
# Ensure atom exports is already in the require cache so the load time
|
||||
# of the first package isn't skewed by being the first to require atom
|
||||
@@ -139,6 +150,7 @@ class PackageManager
|
||||
@loadPackage(packagePath, options) for packagePath in packagePaths
|
||||
@emit 'loaded'
|
||||
|
||||
# Private:
|
||||
loadPackage: (nameOrPath, options) ->
|
||||
if packagePath = @resolvePackagePath(nameOrPath)
|
||||
name = path.basename(nameOrPath)
|
||||
@@ -150,10 +162,12 @@ class PackageManager
|
||||
else
|
||||
throw new Error("Could not resolve '#{nameOrPath}' to a package path")
|
||||
|
||||
# Private:
|
||||
unloadPackages: ->
|
||||
@unloadPackage(name) for name in _.keys(@loadedPackages)
|
||||
null
|
||||
|
||||
# Private:
|
||||
unloadPackage: (name) ->
|
||||
if @isPackageActive(name)
|
||||
throw new Error("Tried to unload active package '#{name}'")
|
||||
@@ -163,12 +177,15 @@ class PackageManager
|
||||
else
|
||||
throw new Error("No loaded package for name '#{name}'")
|
||||
|
||||
# Public: Get the loaded package with the given name
|
||||
getLoadedPackage: (name) ->
|
||||
@loadedPackages[name]
|
||||
|
||||
# Public: Is the package with the given name loaded?
|
||||
isPackageLoaded: (name) ->
|
||||
@getLoadedPackage(name)?
|
||||
|
||||
# Public: Get an array of all the loaded packages
|
||||
getLoadedPackages: ->
|
||||
_.values(@loadedPackages)
|
||||
|
||||
@@ -178,6 +195,7 @@ class PackageManager
|
||||
getLoadedPackagesForTypes: (types) ->
|
||||
pack for pack in @getLoadedPackages() when pack.getType() in types
|
||||
|
||||
# Public: Resolve the given package name to a path on disk.
|
||||
resolvePackagePath: (name) ->
|
||||
return name if fs.isDirectorySync(name)
|
||||
|
||||
@@ -185,18 +203,22 @@ class PackageManager
|
||||
return packagePath if fs.isDirectorySync(packagePath)
|
||||
|
||||
packagePath = path.join(@resourcePath, 'node_modules', name)
|
||||
return packagePath if @isInternalPackage(packagePath)
|
||||
return packagePath if @hasAtomEngine(packagePath)
|
||||
|
||||
# Public: Is the package with the given name disabled?
|
||||
isPackageDisabled: (name) ->
|
||||
_.include(atom.config.get('core.disabledPackages') ? [], name)
|
||||
|
||||
isInternalPackage: (packagePath) ->
|
||||
{engines} = Package.loadMetadata(packagePath, true)
|
||||
engines?.atom?
|
||||
# Private:
|
||||
hasAtomEngine: (packagePath) ->
|
||||
metadata = Package.loadMetadata(packagePath, true)
|
||||
metadata?.engines?.atom?
|
||||
|
||||
isBundledPackage: (packageName) ->
|
||||
@getPackageDependencies().hasOwnProperty(packageName)
|
||||
# Public: Is the package with the given name bundled with Atom?
|
||||
isBundledPackage: (name) ->
|
||||
@getPackageDependencies().hasOwnProperty(name)
|
||||
|
||||
# Private:
|
||||
getPackageDependencies: ->
|
||||
unless @packageDependencies?
|
||||
try
|
||||
@@ -206,6 +228,7 @@ class PackageManager
|
||||
|
||||
@packageDependencies
|
||||
|
||||
# Public: Get an array of all the available package paths.
|
||||
getAvailablePackagePaths: ->
|
||||
packagePaths = []
|
||||
|
||||
@@ -220,9 +243,11 @@ class PackageManager
|
||||
|
||||
_.uniq(packagePaths)
|
||||
|
||||
# Public: Get an array of all the available package names.
|
||||
getAvailablePackageNames: ->
|
||||
_.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
|
||||
|
||||
# Public: Get an array of all the available package metadata.
|
||||
getAvailablePackageMetadata: ->
|
||||
packages = []
|
||||
for packagePath in @getAvailablePackagePaths()
|
||||
|
||||
@@ -45,7 +45,7 @@ class Package
|
||||
@name = basename(@path)
|
||||
|
||||
isActive: ->
|
||||
atom.isPackageActive(@name)
|
||||
atom.packages.isPackageActive(@name)
|
||||
|
||||
isTheme: ->
|
||||
!!@metadata?.theme
|
||||
|
||||
@@ -12,7 +12,8 @@ class PaneAxis extends View
|
||||
initialize: (args...) ->
|
||||
if args[0] instanceof telepath.Document
|
||||
@state = args[0]
|
||||
@state.get('children').each (child, index) => @addChild(deserialize(child), index, updateState: false)
|
||||
@state.get('children').each (child, index) =>
|
||||
@addChild(atom.deserializers.deserialize(child), index, updateState: false)
|
||||
else
|
||||
@state = atom.site.createDocument(deserializer: @className(), children: [])
|
||||
@addChild(child) for child in args
|
||||
@@ -22,7 +23,7 @@ class PaneAxis extends View
|
||||
for childState in removedValues
|
||||
@removeChild(@children(":eq(#{index})").view(), updateState: false)
|
||||
for childState, i in insertedValues
|
||||
@addChild(deserialize(childState), index + i, updateState: false)
|
||||
@addChild(atom.deserializers.deserialize(childState), index + i, updateState: false)
|
||||
|
||||
addChild: (child, index=@children().length, options={}) ->
|
||||
@insertAt(index, child)
|
||||
|
||||
@@ -5,7 +5,7 @@ telepath = require 'telepath'
|
||||
# Private: Manages the list of panes within a {RootView}
|
||||
module.exports =
|
||||
class PaneContainer extends View
|
||||
registerDeserializer(this)
|
||||
atom.deserializers.add(this)
|
||||
|
||||
### Internal ###
|
||||
@acceptsDocuments: true
|
||||
@@ -23,7 +23,7 @@ class PaneContainer extends View
|
||||
|
||||
if state instanceof telepath.Document
|
||||
@state = state
|
||||
@setRoot(deserialize(@state.get('root')))
|
||||
@setRoot(atom.deserializers.deserialize(@state.get('root')))
|
||||
else
|
||||
@state = atom.site.createDocument(deserializer: 'PaneContainer')
|
||||
|
||||
@@ -89,10 +89,10 @@ class PaneContainer extends View
|
||||
reopenItem: ->
|
||||
if lastItemState = @destroyedItemStates.pop()
|
||||
if activePane = @getActivePane()
|
||||
activePane.showItem(deserialize(lastItemState))
|
||||
activePane.showItem(atom.deserializers.deserialize(lastItemState))
|
||||
true
|
||||
else
|
||||
newPane = new Pane(deserialize(lastItemState))
|
||||
newPane = new Pane(atom.deserializers.deserialize(lastItemState))
|
||||
@setRoot(newPane)
|
||||
newPane.focus()
|
||||
|
||||
@@ -147,7 +147,7 @@ class PaneContainer extends View
|
||||
callback(pane) for pane in @getPanes()
|
||||
paneAttached = (e) -> callback($(e.target).view())
|
||||
@on 'pane:attached', paneAttached
|
||||
cancel: => @off 'pane:attached', paneAttached
|
||||
off: => @off 'pane:attached', paneAttached
|
||||
|
||||
getFocusedPane: ->
|
||||
@find('.pane:has(:focus)').view()
|
||||
|
||||
+12
-12
@@ -7,7 +7,7 @@ PaneColumn = require './pane-column'
|
||||
|
||||
# Public: A container which can contains multiple items to be switched between.
|
||||
#
|
||||
# Items can be almost anything however most commonly they're {Editor}s.
|
||||
# Items can be almost anything however most commonly they're {EditorView}s.
|
||||
#
|
||||
# Most packages won't need to use this class, unless you're interested in
|
||||
# building a package that deals with switching between panes or tiems.
|
||||
@@ -33,7 +33,8 @@ class Pane extends View
|
||||
initialize: (args...) ->
|
||||
if args[0] instanceof telepath.Document
|
||||
@state = args[0]
|
||||
@items = _.compact(@state.get('items').map (item) -> deserialize(item))
|
||||
@items = _.compact @state.get('items').map (item) ->
|
||||
atom.deserializers.deserialize(item)
|
||||
else
|
||||
@items = args
|
||||
@state = atom.site.createDocument
|
||||
@@ -45,10 +46,10 @@ class Pane extends View
|
||||
for itemState in removedValues
|
||||
@removeItemAtIndex(index, updateState: false)
|
||||
for itemState, i in insertedValues
|
||||
@addItem(deserialize(itemState), index + i, updateState: false)
|
||||
@addItem(atom.deserializers.deserialize(itemState), index + i, updateState: false)
|
||||
|
||||
@subscribe @state, 'changed', ({newValues, siteId}) =>
|
||||
return if site is @state.siteId
|
||||
return if siteId is @state.siteId
|
||||
if newValues.activeItemUri
|
||||
@showItemForUri(newValues.activeItemUri)
|
||||
|
||||
@@ -219,12 +220,11 @@ class Pane extends View
|
||||
return true unless item.shouldPromptToSave?()
|
||||
|
||||
uri = item.getUri()
|
||||
chosen = atom.confirmSync(
|
||||
"'#{item.getTitle?() ? item.getUri()}' has changes, do you want to save them?"
|
||||
"Your changes will be lost if you close this item without saving."
|
||||
["Save", "Cancel", "Don't Save"]
|
||||
atom.getCurrentWindow()
|
||||
)
|
||||
chosen = atom.confirm
|
||||
message: "'#{item.getTitle?() ? item.getUri()}' has changes, do you want to save them?"
|
||||
detailedMessage: "Your changes will be lost if you close this item without saving."
|
||||
buttons: ["Save", "Cancel", "Don't Save"]
|
||||
|
||||
switch chosen
|
||||
when 0 then @saveItem(item, -> true)
|
||||
when 1 then false
|
||||
@@ -416,7 +416,7 @@ class Pane extends View
|
||||
|
||||
# Private:
|
||||
copyActiveItem: ->
|
||||
@activeItem.copy?() ? deserialize(@activeItem.serialize())
|
||||
@activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize())
|
||||
|
||||
# Private:
|
||||
remove: (selector, keepData) ->
|
||||
@@ -426,7 +426,7 @@ class Pane extends View
|
||||
# Private:
|
||||
beforeRemove: ->
|
||||
if @is(':has(:focus)')
|
||||
@getContainer().focusNextPane() or rootView?.focus()
|
||||
@getContainer().focusNextPane() or atom.rootView?.focus()
|
||||
else if @isActive()
|
||||
@getContainer().makeNextPaneActive()
|
||||
|
||||
|
||||
+73
-105
@@ -5,10 +5,9 @@ _ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
Q = require 'q'
|
||||
telepath = require 'telepath'
|
||||
{Range} = telepath
|
||||
|
||||
TextBuffer = require './text-buffer'
|
||||
EditSession = require './edit-session'
|
||||
Editor = require './editor'
|
||||
{Emitter} = require 'emissary'
|
||||
Directory = require './directory'
|
||||
Task = require './task'
|
||||
@@ -19,16 +18,12 @@ Git = require './git'
|
||||
# Ultimately, a project is a git directory that's been opened. It's a collection
|
||||
# of directories and files that you can operate on.
|
||||
module.exports =
|
||||
class Project
|
||||
class Project extends telepath.Model
|
||||
Emitter.includeInto(this)
|
||||
|
||||
@acceptsDocuments: true
|
||||
@version: 1
|
||||
|
||||
registerDeserializer(this)
|
||||
|
||||
# Private:
|
||||
@deserialize: (state) -> new Project(state)
|
||||
@properties
|
||||
buffers: []
|
||||
path: null
|
||||
|
||||
# Public: Find the local path for the given repository URL.
|
||||
@pathForRepositoryUrl: (repoUrl) ->
|
||||
@@ -36,20 +31,39 @@ class Project
|
||||
repoName = repoName.replace(/\.git$/, '')
|
||||
path.join(atom.config.get('core.projectHome'), repoName)
|
||||
|
||||
rootDirectory: null
|
||||
editSessions: null
|
||||
ignoredPathRegexes: null
|
||||
openers: null
|
||||
# Private: Called by telepath.
|
||||
attached: ->
|
||||
for buffer in @buffers.getValues()
|
||||
buffer.once 'destroyed', (buffer) => @removeBuffer(buffer)
|
||||
|
||||
# Public:
|
||||
@openers = []
|
||||
@editors = []
|
||||
@setPath(@path)
|
||||
|
||||
# Private: Called by telepath.
|
||||
beforePersistence: ->
|
||||
@destroyUnretainedBuffers()
|
||||
|
||||
# Public: Register an opener for project files.
|
||||
#
|
||||
# An {Editor} will be used if no openers return a value.
|
||||
#
|
||||
# ## Example:
|
||||
# ```coffeescript
|
||||
# atom.project.registerOpener (filePath) ->
|
||||
# if path.extname(filePath) is '.toml'
|
||||
# return new TomlEditor(filePath)
|
||||
# ```
|
||||
#
|
||||
# * opener: A function to be called when a path is being opened.
|
||||
registerOpener: (opener) -> @openers.push(opener)
|
||||
|
||||
# Public:
|
||||
# Public: Remove a previously registered opener.
|
||||
unregisterOpener: (opener) -> _.remove(@openers, opener)
|
||||
|
||||
# Private:
|
||||
destroy: ->
|
||||
editSession.destroy() for editSession in @getEditSessions()
|
||||
editor.destroy() for editor in @getEditSessions()
|
||||
buffer.release() for buffer in @getBuffers()
|
||||
@destroyRepo()
|
||||
|
||||
@@ -59,51 +73,10 @@ class Project
|
||||
@repo.destroy()
|
||||
@repo = null
|
||||
|
||||
# Public: Establishes a new project at a given path.
|
||||
#
|
||||
# path - The {String} name of the path
|
||||
constructor: (pathOrState) ->
|
||||
@openers = []
|
||||
@editSessions = []
|
||||
@buffers = []
|
||||
|
||||
if pathOrState instanceof telepath.Document
|
||||
@state = pathOrState
|
||||
if projectPath = @state.remove('path')
|
||||
@setPath(projectPath)
|
||||
else
|
||||
@setPath(@constructor.pathForRepositoryUrl(@state.get('repoUrl')))
|
||||
|
||||
@state.get('buffers').each (bufferState) =>
|
||||
if buffer = deserialize(bufferState, project: this)
|
||||
@addBuffer(buffer, updateState: false)
|
||||
else
|
||||
@state = atom.site.createDocument(deserializer: @constructor.name, version: @constructor.version, buffers: [])
|
||||
@setPath(pathOrState)
|
||||
|
||||
@state.get('buffers').on 'changed', ({index, insertedValues, removedValues, siteId}) =>
|
||||
return if siteId is @state.siteId
|
||||
|
||||
for removedBuffer in removedValues
|
||||
@removeBufferAtIndex(index, updateState: false)
|
||||
for insertedBuffer, i in insertedValues
|
||||
@addBufferAtIndex(deserialize(insertedBuffer, project: this), index + i, updateState: false)
|
||||
|
||||
# Private:
|
||||
serialize: ->
|
||||
state = @state.clone()
|
||||
state.set('path', @getPath())
|
||||
@destroyUnretainedBuffers()
|
||||
state.set('buffers', buffer.serialize() for buffer in @getBuffers())
|
||||
state
|
||||
|
||||
# Private:
|
||||
destroyUnretainedBuffers: ->
|
||||
buffer.destroy() for buffer in @getBuffers() when not buffer.isRetained()
|
||||
|
||||
# Public: ?
|
||||
getState: -> @state
|
||||
|
||||
# Public: Returns the {Git} repository if available.
|
||||
getRepo: -> @repo
|
||||
|
||||
@@ -113,6 +86,7 @@ class Project
|
||||
|
||||
# Public: Sets the project's fullpath.
|
||||
setPath: (projectPath) ->
|
||||
@path = projectPath
|
||||
@rootDirectory?.off()
|
||||
|
||||
@destroyRepo()
|
||||
@@ -125,12 +99,9 @@ class Project
|
||||
else
|
||||
@rootDirectory = null
|
||||
|
||||
if originUrl = @repo?.getOriginUrl()
|
||||
@state.set('repoUrl', originUrl)
|
||||
|
||||
@emit "path-changed"
|
||||
|
||||
# Public: Returns the name of the root directory.
|
||||
# Public: Returns the root {Directory} object for this project.
|
||||
getRootDirectory: ->
|
||||
@rootDirectory
|
||||
|
||||
@@ -173,14 +144,14 @@ class Project
|
||||
@rootDirectory?.contains(pathToCheck) ? false
|
||||
|
||||
# Public: Given a path to a file, this constructs and associates a new
|
||||
# {EditSession}, showing the file.
|
||||
# {Editor}, showing the file.
|
||||
#
|
||||
# * filePath:
|
||||
# The {String} path of the file to associate with
|
||||
# * editSessionOptions:
|
||||
# Options that you can pass to the {EditSession} constructor
|
||||
# * options:
|
||||
# Options that you can pass to the {Editor} constructor
|
||||
#
|
||||
# Returns a promise that resolves to an {EditSession}.
|
||||
# Returns a promise that resolves to an {Editor}.
|
||||
open: (filePath, options={}) ->
|
||||
filePath = @resolve(filePath)
|
||||
resource = null
|
||||
@@ -200,40 +171,38 @@ class Project
|
||||
|
||||
@buildEditSessionForBuffer(@bufferForPathSync(filePath), options)
|
||||
|
||||
# Public: Retrieves all {EditSession}s for all open files.
|
||||
# Public: Retrieves all {Editor}s for all open files.
|
||||
#
|
||||
# Returns an {Array} of {EditSession}s.
|
||||
# Returns an {Array} of {Editor}s.
|
||||
getEditSessions: ->
|
||||
new Array(@editSessions...)
|
||||
new Array(@editors...)
|
||||
|
||||
# Public: Add the given {EditSession}.
|
||||
addEditSession: (editSession) ->
|
||||
@editSessions.push editSession
|
||||
@emit 'edit-session-created', editSession
|
||||
# Public: Add the given {Editor}.
|
||||
addEditSession: (editor) ->
|
||||
@editors.push editor
|
||||
@emit 'editor-created', editor
|
||||
|
||||
# Public: Return and removes the given {EditSession}.
|
||||
removeEditSession: (editSession) ->
|
||||
_.remove(@editSessions, editSession)
|
||||
# Public: Return and removes the given {Editor}.
|
||||
removeEditSession: (editor) ->
|
||||
_.remove(@editors, editor)
|
||||
|
||||
# Private: Retrieves all the {TextBuffer}s in the project; that is, the
|
||||
# buffers for all open files.
|
||||
#
|
||||
# Returns an {Array} of {TextBuffer}s.
|
||||
getBuffers: ->
|
||||
new Array(@buffers...)
|
||||
new Array(@buffers.getValues()...)
|
||||
|
||||
isPathModified: (filePath) ->
|
||||
absoluteFilePath = @resolve(filePath)
|
||||
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
|
||||
existingBuffer?.isModified()
|
||||
@findBufferForPath(@resolve(filePath))?.isModified()
|
||||
|
||||
findBufferForPath: (filePath) ->
|
||||
_.find @buffers.getValues(), (buffer) -> buffer.getPath() == filePath
|
||||
|
||||
# Private: Only to be used in specs
|
||||
bufferForPathSync: (filePath) ->
|
||||
absoluteFilePath = @resolve(filePath)
|
||||
|
||||
if filePath
|
||||
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
|
||||
|
||||
existingBuffer = @findBufferForPath(absoluteFilePath) if filePath
|
||||
existingBuffer ? @buildBufferSync(absoluteFilePath)
|
||||
|
||||
# Private: Given a file path, this retrieves or creates a new {TextBuffer}.
|
||||
@@ -246,9 +215,7 @@ class Project
|
||||
# Returns a promise that resolves to the {TextBuffer}.
|
||||
bufferForPath: (filePath) ->
|
||||
absoluteFilePath = @resolve(filePath)
|
||||
if absoluteFilePath
|
||||
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
|
||||
|
||||
existingBuffer = @findBufferForPath(absoluteFilePath) if absoluteFilePath
|
||||
Q(existingBuffer ? @buildBuffer(absoluteFilePath))
|
||||
|
||||
# Private:
|
||||
@@ -257,9 +224,9 @@ class Project
|
||||
|
||||
# Private: DEPRECATED
|
||||
buildBufferSync: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({project: this, filePath: absoluteFilePath})
|
||||
buffer.loadSync()
|
||||
buffer = new TextBuffer({filePath: absoluteFilePath})
|
||||
@addBuffer(buffer)
|
||||
buffer.loadSync()
|
||||
buffer
|
||||
|
||||
# Private: Given a file path, this sets its {TextBuffer}.
|
||||
@@ -269,10 +236,11 @@ class Project
|
||||
#
|
||||
# Returns a promise that resolves to the {TextBuffer}.
|
||||
buildBuffer: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({project: this, filePath: absoluteFilePath})
|
||||
buffer.load().then (buffer) =>
|
||||
@addBuffer(buffer)
|
||||
buffer
|
||||
buffer = new TextBuffer({filePath: absoluteFilePath})
|
||||
@addBuffer(buffer)
|
||||
buffer.load()
|
||||
.then((buffer) -> buffer)
|
||||
.catch(=> @removeBuffer(buffer))
|
||||
|
||||
# Private:
|
||||
addBuffer: (buffer, options={}) ->
|
||||
@@ -280,9 +248,10 @@ class Project
|
||||
|
||||
# Private:
|
||||
addBufferAtIndex: (buffer, index, options={}) ->
|
||||
@buffers[index] = buffer
|
||||
@state.get('buffers').insert(index, buffer.getState()) if options.updateState ? true
|
||||
buffer = @buffers.insert(index, buffer)
|
||||
buffer.once 'destroyed', => @removeBuffer(buffer)
|
||||
@emit 'buffer-created', buffer
|
||||
buffer
|
||||
|
||||
# Private: Removes a {TextBuffer} association from the project.
|
||||
#
|
||||
@@ -294,7 +263,6 @@ class Project
|
||||
# Private:
|
||||
removeBufferAtIndex: (index, options={}) ->
|
||||
[buffer] = @buffers.splice(index, 1)
|
||||
@state.get('buffers')?.remove(index) if options.updateState ? true
|
||||
buffer?.destroy()
|
||||
|
||||
# Public: Performs a search across all the files in the project.
|
||||
@@ -329,7 +297,7 @@ class Project
|
||||
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
|
||||
options.onPathsSearched(numberOfPathsSearched)
|
||||
|
||||
for buffer in @buffers when buffer.isModified()
|
||||
for buffer in @buffers.getValues() when buffer.isModified()
|
||||
filePath = buffer.getPath()
|
||||
matches = []
|
||||
buffer.scan regex, (match) -> matches.push match
|
||||
@@ -346,7 +314,7 @@ class Project
|
||||
replace: (regex, replacementText, filePaths, iterator) ->
|
||||
deferred = Q.defer()
|
||||
|
||||
openPaths = (buffer.getPath() for buffer in @buffers)
|
||||
openPaths = (buffer.getPath() for buffer in @buffers.getValues())
|
||||
outOfProcessPaths = _.difference(filePaths, openPaths)
|
||||
|
||||
inProcessFinished = !openPaths.length
|
||||
@@ -364,7 +332,7 @@ class Project
|
||||
|
||||
task.on 'replace:path-replaced', iterator
|
||||
|
||||
for buffer in @buffers
|
||||
for buffer in @buffers.getValues()
|
||||
replacements = buffer.replace(regex, replacementText, iterator)
|
||||
iterator({filePath: buffer.getPath(), replacements}) if replacements
|
||||
|
||||
@@ -374,15 +342,15 @@ class Project
|
||||
deferred.promise
|
||||
|
||||
# Private:
|
||||
buildEditSessionForBuffer: (buffer, editSessionOptions) ->
|
||||
editSession = new EditSession(_.extend({buffer}, editSessionOptions))
|
||||
@addEditSession(editSession)
|
||||
editSession
|
||||
buildEditSessionForBuffer: (buffer, editorOptions) ->
|
||||
editor = new Editor(_.extend({buffer}, editorOptions))
|
||||
@addEditSession(editor)
|
||||
editor
|
||||
|
||||
# Private:
|
||||
eachEditSession: (callback) ->
|
||||
callback(editSession) for editSession in @getEditSessions()
|
||||
@on 'edit-session-created', (editSession) -> callback(editSession)
|
||||
callback(editor) for editor in @getEditSessions()
|
||||
@on 'editor-created', (editor) -> callback(editor)
|
||||
|
||||
# Private:
|
||||
eachBuffer: (args...) ->
|
||||
|
||||
+33
-36
@@ -5,12 +5,12 @@ Q = require 'q'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
telepath = require 'telepath'
|
||||
Editor = require './editor'
|
||||
EditorView = require './editor-view'
|
||||
Pane = require './pane'
|
||||
PaneColumn = require './pane-column'
|
||||
PaneRow = require './pane-row'
|
||||
PaneContainer = require './pane-container'
|
||||
EditSession = require './edit-session'
|
||||
Editor = require './editor'
|
||||
|
||||
# Public: The container for the entire Atom application.
|
||||
#
|
||||
@@ -38,7 +38,7 @@ EditSession = require './edit-session'
|
||||
#
|
||||
module.exports =
|
||||
class RootView extends View
|
||||
registerDeserializers(this, Pane, PaneRow, PaneColumn, Editor)
|
||||
atom.deserializers.add(this, Pane, PaneRow, PaneColumn, EditorView)
|
||||
|
||||
@version: 1
|
||||
|
||||
@@ -47,7 +47,7 @@ class RootView extends View
|
||||
excludeVcsIgnoredPaths: true
|
||||
disabledPackages: []
|
||||
themes: ['atom-dark-ui', 'atom-dark-syntax']
|
||||
projectHome: path.join(atom.getHomeDirPath(), 'github')
|
||||
projectHome: path.join(fs.getHomeDirectory(), 'github')
|
||||
audioBeep: true
|
||||
|
||||
@acceptsDocuments: true
|
||||
@@ -69,7 +69,7 @@ class RootView extends View
|
||||
|
||||
if state instanceof telepath.Document
|
||||
@state = state
|
||||
panes = deserialize(state.get('panes'))
|
||||
panes = atom.deserializers.deserialize(state.get('panes'))
|
||||
else
|
||||
panes = new PaneContainer
|
||||
@state = atom.site.createDocument
|
||||
@@ -85,7 +85,7 @@ class RootView extends View
|
||||
@subscribe $(window), 'focus', (e) =>
|
||||
@handleFocus(e) if document.activeElement is document.body
|
||||
|
||||
project.on 'path-changed', => @updateTitle()
|
||||
atom.project.on 'path-changed', => @updateTitle()
|
||||
@on 'pane-container:active-pane-item-changed', => @updateTitle()
|
||||
@on 'pane:active-item-title-changed', '.active.pane', => @updateTitle()
|
||||
|
||||
@@ -105,12 +105,12 @@ class RootView extends View
|
||||
@command 'application:zoom', -> ipc.sendChannel('command', 'application:zoom')
|
||||
@command 'application:bring-all-windows-to-front', -> ipc.sendChannel('command', 'application:bring-all-windows-to-front')
|
||||
|
||||
@command 'window:run-package-specs', => ipc.sendChannel('run-package-specs', path.join(project.getPath(), 'spec'))
|
||||
@command 'window:run-package-specs', => ipc.sendChannel('run-package-specs', path.join(atom.project.getPath(), 'spec'))
|
||||
@command 'window:increase-font-size', =>
|
||||
atom.config.set("editor.fontSize", config.get("editor.fontSize") + 1)
|
||||
atom.config.set("editor.fontSize", atom.config.get("editor.fontSize") + 1)
|
||||
|
||||
@command 'window:decrease-font-size', =>
|
||||
fontSize = config.get "editor.fontSize"
|
||||
fontSize = atom.config.get "editor.fontSize"
|
||||
atom.config.set("editor.fontSize", fontSize - 1) if fontSize > 1
|
||||
|
||||
@command 'window:focus-next-pane', => @focusNextPane()
|
||||
@@ -127,9 +127,6 @@ class RootView extends View
|
||||
@command 'pane:reopen-closed-item', =>
|
||||
@panes.reopenItem()
|
||||
|
||||
if @state.get('fullScreen')
|
||||
setImmediate => atom.setFullScreen(true)
|
||||
|
||||
# Private:
|
||||
serialize: ->
|
||||
state = @state.clone()
|
||||
@@ -169,26 +166,26 @@ class RootView extends View
|
||||
# * options
|
||||
# + initialLine: The buffer line number to open to.
|
||||
#
|
||||
# Returns a promise that resolves to the {EditSession} for the file URI.
|
||||
# Returns a promise that resolves to the {Editor} for the file URI.
|
||||
open: (filePath, options={}) ->
|
||||
changeFocus = options.changeFocus ? true
|
||||
filePath = project.resolve(filePath)
|
||||
filePath = atom.project.resolve(filePath)
|
||||
initialLine = options.initialLine
|
||||
activePane = @getActivePane()
|
||||
|
||||
editSession = activePane.itemForUri(project.relativize(filePath)) if activePane and filePath
|
||||
promise = project.open(filePath, {initialLine}) if not editSession
|
||||
editor = activePane.itemForUri(atom.project.relativize(filePath)) if activePane and filePath
|
||||
promise = atom.project.open(filePath, {initialLine}) if not editor
|
||||
|
||||
Q(editSession ? promise)
|
||||
.then (editSession) =>
|
||||
Q(editor ? promise)
|
||||
.then (editor) =>
|
||||
if not activePane
|
||||
activePane = new Pane(editSession)
|
||||
activePane = new Pane(editor)
|
||||
@panes.setRoot(activePane)
|
||||
|
||||
activePane.showItem(editSession)
|
||||
activePane.showItem(editor)
|
||||
activePane.focus() if changeFocus
|
||||
@trigger "uri-opened"
|
||||
editSession
|
||||
editor
|
||||
.catch (error) ->
|
||||
console.error(error.stack ? error)
|
||||
|
||||
@@ -196,13 +193,13 @@ class RootView extends View
|
||||
openSync: (uri, {changeFocus, initialLine, pane, split}={}) ->
|
||||
changeFocus ?= true
|
||||
pane ?= @getActivePane()
|
||||
uri = project.relativize(uri)
|
||||
uri = atom.project.relativize(uri)
|
||||
|
||||
if pane
|
||||
if uri
|
||||
paneItem = pane.itemForUri(uri) ? project.openSync(uri, {initialLine})
|
||||
paneItem = pane.itemForUri(uri) ? atom.project.openSync(uri, {initialLine})
|
||||
else
|
||||
paneItem = project.openSync()
|
||||
paneItem = atom.project.openSync()
|
||||
|
||||
if split == 'right'
|
||||
panes = @getPanes()
|
||||
@@ -215,7 +212,7 @@ class RootView extends View
|
||||
|
||||
pane.showItem(paneItem)
|
||||
else
|
||||
paneItem = project.openSync(uri, {initialLine})
|
||||
paneItem = atom.project.openSync(uri, {initialLine})
|
||||
pane = new Pane(paneItem)
|
||||
@panes.setRoot(pane)
|
||||
|
||||
@@ -224,7 +221,7 @@ class RootView extends View
|
||||
|
||||
openSingletonSync: (uri, {changeFocus, initialLine, split}={}) ->
|
||||
changeFocus ?= true
|
||||
uri = project.relativize(uri)
|
||||
uri = atom.project.relativize(uri)
|
||||
pane = @panes.paneForUri(uri)
|
||||
|
||||
if pane
|
||||
@@ -237,7 +234,7 @@ class RootView extends View
|
||||
|
||||
# Public: Updates the application's title, based on whichever file is open.
|
||||
updateTitle: ->
|
||||
if projectPath = project.getPath()
|
||||
if projectPath = atom.project.getPath()
|
||||
if item = @getActivePaneItem()
|
||||
@setTitle("#{item.getTitle?() ? 'untitled'} - #{projectPath}")
|
||||
else
|
||||
@@ -249,7 +246,7 @@ class RootView extends View
|
||||
setTitle: (title) ->
|
||||
document.title = title
|
||||
|
||||
# Private: Returns an Array of all of the application's {Editor}s.
|
||||
# Private: Returns an Array of all of the application's {EditorView}s.
|
||||
getEditors: ->
|
||||
@panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray()
|
||||
|
||||
@@ -259,7 +256,7 @@ class RootView extends View
|
||||
getModifiedBuffers: ->
|
||||
modifiedBuffers = []
|
||||
for pane in @getPanes()
|
||||
for item in pane.getItems() when item instanceof EditSession
|
||||
for item in pane.getItems() when item instanceof Editor
|
||||
modifiedBuffers.push item.buffer if item.buffer.isModified()
|
||||
modifiedBuffers
|
||||
|
||||
@@ -267,7 +264,7 @@ class RootView extends View
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
getOpenBufferPaths: ->
|
||||
_.uniq(_.flatten(@getEditors().map (editor) -> editor.getOpenBufferPaths()))
|
||||
_.uniq(_.flatten(@getEditors().map (editorView) -> editorView.getOpenBufferPaths()))
|
||||
|
||||
# Public: Returns the currently focused {Pane}.
|
||||
getActivePane: ->
|
||||
@@ -308,23 +305,23 @@ class RootView extends View
|
||||
indexOfPane: (pane) ->
|
||||
@panes.indexOfPane(pane)
|
||||
|
||||
# Private: Fires a callback on each open {Editor}.
|
||||
# Private: Fires a callback on each open {EditorView}.
|
||||
eachEditor: (callback) ->
|
||||
callback(editor) for editor in @getEditors()
|
||||
attachedCallback = (e, editor) -> callback(editor)
|
||||
@on('editor:attached', attachedCallback)
|
||||
off: => @off('editor:attached', attachedCallback)
|
||||
|
||||
# Public: Fires a callback on each open {EditSession}.
|
||||
# Public: Fires a callback on each open {Editor}.
|
||||
eachEditSession: (callback) ->
|
||||
project.eachEditSession(callback)
|
||||
atom.project.eachEditSession(callback)
|
||||
|
||||
# Private: Fires a callback on each open {TextBuffer}.
|
||||
eachBuffer: (callback) ->
|
||||
project.eachBuffer(callback)
|
||||
atom.project.eachBuffer(callback)
|
||||
|
||||
# Private: Destroys everything.
|
||||
remove: ->
|
||||
editor.remove() for editor in @getEditors()
|
||||
project?.destroy()
|
||||
editorView.remove() for editorView in @getEditors()
|
||||
atom.project?.destroy()
|
||||
super
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{$, View} = require './space-pen-extensions'
|
||||
Editor = require './editor'
|
||||
EditorView = require './editor-view'
|
||||
fuzzyFilter = require('fuzzaldrin').filter
|
||||
|
||||
# Public: Provides a widget for users to make a selection from a list of
|
||||
@@ -10,7 +10,7 @@ class SelectList extends View
|
||||
# Private:
|
||||
@content: ->
|
||||
@div class: @viewClass(), =>
|
||||
@subview 'miniEditor', new Editor(mini: true)
|
||||
@subview 'miniEditor', new EditorView(mini: true)
|
||||
@div class: 'error-message', outlet: 'error'
|
||||
@div class: 'loading', outlet: 'loadingArea', =>
|
||||
@span class: 'loading-message', outlet: 'loading'
|
||||
@@ -171,7 +171,7 @@ class SelectList extends View
|
||||
if @previouslyFocusedElement?.isOnDom()
|
||||
@previouslyFocusedElement.focus()
|
||||
else
|
||||
rootView.focus()
|
||||
atom.rootView.focus()
|
||||
|
||||
# Public:
|
||||
cancelled: ->
|
||||
|
||||
@@ -11,12 +11,12 @@ class SelectionView extends View
|
||||
regions: null
|
||||
needsRemoval: false
|
||||
|
||||
initialize: ({@editor, @selection} = {}) ->
|
||||
initialize: ({@editorView, @selection} = {}) ->
|
||||
@regions = []
|
||||
@selection.on 'screen-range-changed', => @editor.requestDisplayUpdate()
|
||||
@selection.on 'screen-range-changed', => @editorView.requestDisplayUpdate()
|
||||
@selection.on 'destroyed', =>
|
||||
@needsRemoval = true
|
||||
@editor.requestDisplayUpdate()
|
||||
@editorView.requestDisplayUpdate()
|
||||
|
||||
if @selection.marker.isRemote()
|
||||
@addClass("site-#{@selection.marker.getOriginSiteId()}")
|
||||
@@ -26,7 +26,7 @@ class SelectionView extends View
|
||||
range = @getScreenRange()
|
||||
|
||||
@trigger 'selection:changed'
|
||||
@editor.highlightFoldsContainingBufferRange(@getBufferRange())
|
||||
@editorView.highlightFoldsContainingBufferRange(@getBufferRange())
|
||||
return if range.isEmpty()
|
||||
|
||||
rowSpan = range.end.row - range.start.row
|
||||
@@ -40,11 +40,11 @@ class SelectionView extends View
|
||||
@appendRegion(1, { row: range.end.row, column: 0 }, range.end)
|
||||
|
||||
appendRegion: (rows, start, end) ->
|
||||
{ lineHeight, charWidth } = @editor
|
||||
css = @editor.pixelPositionForScreenPosition(start)
|
||||
{ lineHeight, charWidth } = @editorView
|
||||
css = @editorView.pixelPositionForScreenPosition(start)
|
||||
css.height = lineHeight * rows
|
||||
if end
|
||||
css.width = @editor.pixelPositionForScreenPosition(end).left - css.left
|
||||
css.width = @editorView.pixelPositionForScreenPosition(end).left - css.left
|
||||
else
|
||||
css.right = 0
|
||||
|
||||
@@ -57,7 +57,7 @@ class SelectionView extends View
|
||||
startRow = start.row
|
||||
endRow = end.row
|
||||
endRow-- if end.column == 0
|
||||
@editor.pixelPositionForScreenPosition([((startRow + endRow + 1) / 2), start.column])
|
||||
@editorView.pixelPositionForScreenPosition([((startRow + endRow + 1) / 2), start.column])
|
||||
|
||||
clearRegions: ->
|
||||
region.remove() for region in @regions
|
||||
@@ -85,5 +85,5 @@ class SelectionView extends View
|
||||
@removeClass('highlighted')
|
||||
|
||||
remove: ->
|
||||
@editor.removeSelectionView(this)
|
||||
@editorView.removeSelectionView(this)
|
||||
super
|
||||
|
||||
+58
-53
@@ -2,27 +2,26 @@
|
||||
{Emitter} = require 'emissary'
|
||||
{pick} = require 'underscore-plus'
|
||||
|
||||
# Public: Represents a selection in the {EditSession}.
|
||||
# Public: Represents a selection in the {Editor}.
|
||||
module.exports =
|
||||
class Selection
|
||||
Emitter.includeInto(this)
|
||||
|
||||
cursor: null
|
||||
marker: null
|
||||
editSession: null
|
||||
editor: null
|
||||
initialScreenRange: null
|
||||
wordwise: false
|
||||
needsAutoscroll: null
|
||||
|
||||
|
||||
# Private:
|
||||
constructor: ({@cursor, @marker, @editSession}) ->
|
||||
constructor: ({@cursor, @marker, @editor}) ->
|
||||
@cursor.selection = this
|
||||
@marker.on 'changed', => @screenRangeChanged()
|
||||
@marker.on 'destroyed', =>
|
||||
@destroyed = true
|
||||
@editSession.removeSelection(this)
|
||||
@emit 'destroyed' unless @editSession.destroyed
|
||||
@editor.removeSelection(this)
|
||||
@emit 'destroyed' unless @editor.destroyed
|
||||
|
||||
# Private:
|
||||
destroy: ->
|
||||
@@ -65,7 +64,7 @@ class Selection
|
||||
# * options:
|
||||
# + A hash of options matching those found in {.setBufferRange}
|
||||
setScreenRange: (screenRange, options) ->
|
||||
@setBufferRange(@editSession.bufferRangeForScreenRange(screenRange), options)
|
||||
@setBufferRange(@editor.bufferRangeForScreenRange(screenRange), options)
|
||||
|
||||
# Public: Returns the buffer {Range} for the selection.
|
||||
getBufferRange: ->
|
||||
@@ -79,12 +78,12 @@ class Selection
|
||||
# + preserveFolds:
|
||||
# if `true`, the fold settings are preserved after the selection moves
|
||||
# + autoscroll:
|
||||
# if `true`, the {EditSession} scrolls to the new selection
|
||||
# if `true`, the {Editor} scrolls to the new selection
|
||||
setBufferRange: (bufferRange, options={}) ->
|
||||
bufferRange = Range.fromObject(bufferRange)
|
||||
@needsAutoscroll = options.autoscroll
|
||||
options.isReversed ?= @isReversed()
|
||||
@editSession.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
|
||||
@editor.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
|
||||
@modifySelection =>
|
||||
@cursor.needsAutoscroll = false if options.autoscroll?
|
||||
@marker.setBufferRange(bufferRange, options)
|
||||
@@ -102,7 +101,7 @@ class Selection
|
||||
|
||||
# Public: Returns the text in the selection.
|
||||
getText: ->
|
||||
@editSession.buffer.getTextInRange(@getBufferRange())
|
||||
@editor.buffer.getTextInRange(@getBufferRange())
|
||||
|
||||
# Public: Clears the selection, moving the marker to the head.
|
||||
clear: ->
|
||||
@@ -132,7 +131,7 @@ class Selection
|
||||
# * row:
|
||||
# The line Number to select (default: the row of the cursor)
|
||||
selectLine: (row=@cursor.getBufferPosition().row) ->
|
||||
range = @editSession.bufferRangeForBufferRow(row, includeNewline: true)
|
||||
range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
|
||||
@setBufferRange(range)
|
||||
@linewise = true
|
||||
@wordwise = false
|
||||
@@ -202,7 +201,7 @@ class Selection
|
||||
|
||||
# Public: Selects all the text in the buffer.
|
||||
selectAll: ->
|
||||
@setBufferRange(@editSession.buffer.getRange(), autoscroll: false)
|
||||
@setBufferRange(@editor.buffer.getRange(), autoscroll: false)
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the
|
||||
# beginning of the line.
|
||||
@@ -247,17 +246,17 @@ class Selection
|
||||
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
|
||||
nextRow = range.end.row + 1
|
||||
|
||||
for row in [nextRow..@editSession.getLastBufferRow()]
|
||||
for row in [nextRow..@editor.getLastBufferRow()]
|
||||
range.start.row = row
|
||||
range.end.row = row
|
||||
clippedRange = @editSession.clipBufferRange(range)
|
||||
clippedRange = @editor.clipBufferRange(range)
|
||||
|
||||
if range.isEmpty()
|
||||
continue if range.end.column > 0 and clippedRange.end.column is 0
|
||||
else
|
||||
continue if clippedRange.isEmpty()
|
||||
|
||||
@editSession.addSelectionForBufferRange(range, goalBufferRange: range)
|
||||
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
|
||||
break
|
||||
|
||||
# Public:
|
||||
@@ -274,14 +273,14 @@ class Selection
|
||||
for row in [previousRow..0]
|
||||
range.start.row = row
|
||||
range.end.row = row
|
||||
clippedRange = @editSession.clipBufferRange(range)
|
||||
clippedRange = @editor.clipBufferRange(range)
|
||||
|
||||
if range.isEmpty()
|
||||
continue if range.end.column > 0 and clippedRange.end.column is 0
|
||||
else
|
||||
continue if clippedRange.isEmpty()
|
||||
|
||||
@editSession.addSelectionForBufferRange(range, goalBufferRange: range)
|
||||
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
|
||||
break
|
||||
|
||||
# Public: Replaces text at the current selection.
|
||||
@@ -302,7 +301,7 @@ class Selection
|
||||
# if `skip`, skips the undo stack for this operation.
|
||||
insertText: (text, options={}) ->
|
||||
oldBufferRange = @getBufferRange()
|
||||
@editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
|
||||
@editor.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
|
||||
wasReversed = @isReversed()
|
||||
@clear()
|
||||
@cursor.needsAutoscroll = @cursor.isLastCursor()
|
||||
@@ -310,18 +309,18 @@ class Selection
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
text = @normalizeIndents(text, options.indentBasis)
|
||||
|
||||
newBufferRange = @editSession.buffer.change(oldBufferRange, text, pick(options, 'undo'))
|
||||
newBufferRange = @editor.buffer.change(oldBufferRange, text, pick(options, 'undo'))
|
||||
if options.select
|
||||
@setBufferRange(newBufferRange, isReversed: wasReversed)
|
||||
else
|
||||
@cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed
|
||||
|
||||
if options.autoIndent
|
||||
@editSession.autoIndentBufferRow(row) for row in newBufferRange.getRows()
|
||||
@editor.autoIndentBufferRow(row) for row in newBufferRange.getRows()
|
||||
else if options.autoIndentNewline and text == '\n'
|
||||
@editSession.autoIndentBufferRow(newBufferRange.end.row)
|
||||
@editor.autoIndentBufferRow(newBufferRange.end.row)
|
||||
else if options.autoDecreaseIndent and /\S/.test text
|
||||
@editSession.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
|
||||
@editor.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
|
||||
|
||||
newBufferRange
|
||||
|
||||
@@ -336,9 +335,9 @@ class Selection
|
||||
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
|
||||
|
||||
lines = text.split('\n')
|
||||
firstLineIndentLevel = @editSession.indentLevelForLine(lines[0])
|
||||
firstLineIndentLevel = @editor.indentLevelForLine(lines[0])
|
||||
if isCursorInsideExistingLine
|
||||
minimumIndentLevel = @editSession.indentationForBufferRow(@cursor.getBufferRow())
|
||||
minimumIndentLevel = @editor.indentationForBufferRow(@cursor.getBufferRow())
|
||||
else
|
||||
minimumIndentLevel = @cursor.getIndentLevel()
|
||||
|
||||
@@ -349,7 +348,7 @@ class Selection
|
||||
else if line == '' # remove all indentation from empty lines
|
||||
indentLevel = 0
|
||||
else
|
||||
lineIndentLevel = @editSession.indentLevelForLine(lines[i])
|
||||
lineIndentLevel = @editor.indentLevelForLine(lines[i])
|
||||
indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis)
|
||||
|
||||
normalizedLines.push(@setIndentationForLine(line, indentLevel))
|
||||
@@ -361,19 +360,19 @@ class Selection
|
||||
# * options - A hash with one key,
|
||||
# + autoIndent:
|
||||
# If `true`, the indentation is performed appropriately. Otherwise,
|
||||
# {EditSession.getTabText} is used
|
||||
# {Editor.getTabText} is used
|
||||
indent: ({ autoIndent }={})->
|
||||
{ row, column } = @cursor.getBufferPosition()
|
||||
|
||||
if @isEmpty()
|
||||
@cursor.skipLeadingWhitespace()
|
||||
desiredIndent = @editSession.suggestedIndentForBufferRow(row)
|
||||
desiredIndent = @editor.suggestedIndentForBufferRow(row)
|
||||
delta = desiredIndent - @cursor.getIndentLevel()
|
||||
|
||||
if autoIndent and delta > 0
|
||||
@insertText(@editSession.buildIndentString(delta))
|
||||
@insertText(@editor.buildIndentString(delta))
|
||||
else
|
||||
@insertText(@editSession.getTabText())
|
||||
@insertText(@editor.getTabText())
|
||||
else
|
||||
@indentSelectedRows()
|
||||
|
||||
@@ -381,18 +380,18 @@ class Selection
|
||||
indentSelectedRows: ->
|
||||
[start, end] = @getBufferRowRange()
|
||||
for row in [start..end]
|
||||
@editSession.buffer.insert([row, 0], @editSession.getTabText()) unless @editSession.buffer.lineLengthForRow(row) == 0
|
||||
@editor.buffer.insert([row, 0], @editor.getTabText()) unless @editor.buffer.lineLengthForRow(row) == 0
|
||||
|
||||
# Public: ?
|
||||
setIndentationForLine: (line, indentLevel) ->
|
||||
desiredIndentLevel = Math.max(0, indentLevel)
|
||||
desiredIndentString = @editSession.buildIndentString(desiredIndentLevel)
|
||||
desiredIndentString = @editor.buildIndentString(desiredIndentLevel)
|
||||
line.replace(/^[\t ]*/, desiredIndentString)
|
||||
|
||||
# Public: Removes the first character before the selection if the selection
|
||||
# is empty otherwise it deletes the selection.
|
||||
backspace: ->
|
||||
@selectLeft() if @isEmpty() and not @editSession.isFoldedAtScreenRow(@cursor.getScreenRow())
|
||||
@selectLeft() if @isEmpty() and not @editor.isFoldedAtScreenRow(@cursor.getScreenRow())
|
||||
@deleteSelectedText()
|
||||
|
||||
# Public: Removes from the start of the selection to the beginning of the
|
||||
@@ -414,7 +413,7 @@ class Selection
|
||||
# selection if the selection is empty.
|
||||
delete: ->
|
||||
if @isEmpty()
|
||||
if @cursor.isAtEndOfLine() and fold = @editSession.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1)
|
||||
if @cursor.isAtEndOfLine() and fold = @editor.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1)
|
||||
@selectToBufferPosition(fold.getBufferRange().end)
|
||||
else
|
||||
@selectRight()
|
||||
@@ -429,9 +428,9 @@ class Selection
|
||||
# Public: Removes only the selected text.
|
||||
deleteSelectedText: ->
|
||||
bufferRange = @getBufferRange()
|
||||
if bufferRange.isEmpty() and fold = @editSession.largestFoldContainingBufferRow(bufferRange.start.row)
|
||||
if bufferRange.isEmpty() and fold = @editor.largestFoldContainingBufferRow(bufferRange.start.row)
|
||||
bufferRange = bufferRange.union(fold.getBufferRange(includeNewline: true))
|
||||
@editSession.buffer.delete(bufferRange) unless bufferRange.isEmpty()
|
||||
@editor.buffer.delete(bufferRange) unless bufferRange.isEmpty()
|
||||
@cursor?.setBufferPosition(bufferRange.start)
|
||||
|
||||
# Public: Removes the line at the beginning of the selection if the selection
|
||||
@@ -440,18 +439,18 @@ class Selection
|
||||
deleteLine: ->
|
||||
if @isEmpty()
|
||||
start = @cursor.getScreenRow()
|
||||
range = @editSession.bufferRowsForScreenRows(start, start + 1)
|
||||
range = @editor.bufferRowsForScreenRows(start, start + 1)
|
||||
if range[1] > range[0]
|
||||
@editSession.buffer.deleteRows(range[0], range[1] - 1)
|
||||
@editor.buffer.deleteRows(range[0], range[1] - 1)
|
||||
else
|
||||
@editSession.buffer.deleteRow(range[0])
|
||||
@editor.buffer.deleteRow(range[0])
|
||||
else
|
||||
range = @getBufferRange()
|
||||
start = range.start.row
|
||||
end = range.end.row
|
||||
if end isnt @editSession.buffer.getLastRow() and range.end.column is 0
|
||||
if end isnt @editor.buffer.getLastRow() and range.end.column is 0
|
||||
end--
|
||||
@editSession.buffer.deleteRows(start, end)
|
||||
@editor.buffer.deleteRows(start, end)
|
||||
|
||||
# Public: Joins the current line with the one below it.
|
||||
#
|
||||
@@ -459,16 +458,16 @@ class Selection
|
||||
joinLine: ->
|
||||
selectedRange = @getBufferRange()
|
||||
if selectedRange.isEmpty()
|
||||
return if selectedRange.start.row is @editSession.buffer.getLastRow()
|
||||
return if selectedRange.start.row is @editor.buffer.getLastRow()
|
||||
else
|
||||
joinMarker = @editSession.markBufferRange(selectedRange, invalidationStrategy: 'never')
|
||||
joinMarker = @editor.markBufferRange(selectedRange, invalidationStrategy: 'never')
|
||||
|
||||
rowCount = Math.max(1, selectedRange.getRowCount() - 1)
|
||||
for row in [0...rowCount]
|
||||
@cursor.setBufferPosition([selectedRange.start.row])
|
||||
@cursor.moveToEndOfLine()
|
||||
nextRow = selectedRange.start.row + 1
|
||||
if nextRow <= @editSession.buffer.getLastRow() and @editSession.buffer.lineLengthForRow(nextRow) > 0
|
||||
if nextRow <= @editor.buffer.getLastRow() and @editor.buffer.lineLengthForRow(nextRow) > 0
|
||||
@insertText(' ')
|
||||
@cursor.moveToEndOfLine()
|
||||
@modifySelection =>
|
||||
@@ -484,8 +483,8 @@ class Selection
|
||||
# Public: Removes one level of indent from the currently selected rows.
|
||||
outdentSelectedRows: ->
|
||||
[start, end] = @getBufferRowRange()
|
||||
buffer = @editSession.buffer
|
||||
leadingTabRegex = new RegExp("^ {1,#{@editSession.getTabLength()}}|\t")
|
||||
buffer = @editor.buffer
|
||||
leadingTabRegex = new RegExp("^ {1,#{@editor.getTabLength()}}|\t")
|
||||
for row in [start..end]
|
||||
if matchLength = buffer.lineForRow(row).match(leadingTabRegex)?[0].length
|
||||
buffer.delete [[row, 0], [row, matchLength]]
|
||||
@@ -494,7 +493,7 @@ class Selection
|
||||
# by the relevant grammars.
|
||||
autoIndentSelectedRows: ->
|
||||
[start, end] = @getBufferRowRange()
|
||||
@editSession.autoIndentBufferRows(start, end)
|
||||
@editor.autoIndentBufferRows(start, end)
|
||||
|
||||
# Public: Wraps the selected lines in comments if they aren't currently part
|
||||
# of a comment.
|
||||
@@ -503,7 +502,7 @@ class Selection
|
||||
#
|
||||
# Returns an Array of the commented {Range}s.
|
||||
toggleLineComments: ->
|
||||
@editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
|
||||
@editor.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
|
||||
|
||||
# Public: Cuts the selection until the end of the line.
|
||||
#
|
||||
@@ -527,19 +526,19 @@ class Selection
|
||||
# ?
|
||||
copy: (maintainPasteboard=false) ->
|
||||
return if @isEmpty()
|
||||
text = @editSession.buffer.getTextInRange(@getBufferRange())
|
||||
text = @editor.buffer.getTextInRange(@getBufferRange())
|
||||
if maintainPasteboard
|
||||
[currentText, metadata] = atom.pasteboard.read()
|
||||
text = currentText + '\n' + text
|
||||
else
|
||||
metadata = { indentBasis: @editSession.indentationForBufferRow(@getBufferRange().start.row) }
|
||||
metadata = { indentBasis: @editor.indentationForBufferRow(@getBufferRange().start.row) }
|
||||
|
||||
atom.pasteboard.write(text, metadata)
|
||||
|
||||
# Public: Creates a fold containing the current selection.
|
||||
fold: ->
|
||||
range = @getBufferRange()
|
||||
@editSession.createFold(range.start.row, range.end.row)
|
||||
@editor.createFold(range.start.row, range.end.row)
|
||||
@cursor.setBufferPosition([range.end.row + 1, 0])
|
||||
|
||||
# Public: ?
|
||||
@@ -592,9 +591,15 @@ class Selection
|
||||
@setBufferRange(@getBufferRange().union(otherSelection.getBufferRange()), options)
|
||||
otherSelection.destroy()
|
||||
|
||||
# Public: ?
|
||||
compare: (other) ->
|
||||
@getBufferRange().compare(other.getBufferRange())
|
||||
# Public: Compare this selection's buffer range to another selection's buffer
|
||||
# range.
|
||||
#
|
||||
# See {Range.compare} for more details.
|
||||
#
|
||||
# * otherSelection:
|
||||
# A {Selection} to compare with.
|
||||
compare: (otherSelection) ->
|
||||
@getBufferRange().compare(otherSelection.getBufferRange())
|
||||
|
||||
# Public: Returns true if it was locally created.
|
||||
isLocal: ->
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Private: TODO remove once telepath upgrades are complete.
|
||||
module.exports =
|
||||
class SiteShim
|
||||
constructor: (document) ->
|
||||
|
||||
@@ -15,4 +15,68 @@ jQuery.cleanData = (elements) ->
|
||||
view.unsubscribe()
|
||||
originalCleanData(elements)
|
||||
|
||||
tooltipDefaults =
|
||||
delay:
|
||||
show: 500
|
||||
hide: 100
|
||||
container: 'body'
|
||||
html: true
|
||||
placement: 'auto top'
|
||||
viewportPadding: 2
|
||||
|
||||
modifiers =
|
||||
cmd: '⌘'
|
||||
ctrl: '⌃'
|
||||
alt: '⌥'
|
||||
option: '⌥'
|
||||
shift: '⇧'
|
||||
enter: '⏎'
|
||||
left: '←'
|
||||
right: '→'
|
||||
up: '↑'
|
||||
down: '↓'
|
||||
|
||||
replaceKey = (key) ->
|
||||
if modifiers[key]
|
||||
modifiers[key]
|
||||
else if key.length == 1 and key == key.toUpperCase() and key.toUpperCase() != key.toLowerCase()
|
||||
[modifiers.shift, key.toUpperCase()]
|
||||
else if key.length == 1
|
||||
key.toUpperCase()
|
||||
else
|
||||
key
|
||||
|
||||
replaceModifiersInSingleKeystroke = (keystroke) ->
|
||||
keys = keystroke.split('-')
|
||||
keys = _.flatten(replaceKey(key) for key in keys)
|
||||
keys.join('')
|
||||
|
||||
replaceModifiers = (keystroke) ->
|
||||
keystrokes = keystroke.split(' ')
|
||||
keystrokes = (replaceModifiersInSingleKeystroke(stroke) for stroke in keystrokes)
|
||||
keystrokes.join(' ')
|
||||
|
||||
getKeystroke = (bindings) ->
|
||||
if bindings?.length
|
||||
"<span class=\"keystroke\">#{replaceModifiers(bindings[0].keystroke)}</span>"
|
||||
else
|
||||
''
|
||||
# options from http://getbootstrap.com/javascript/#tooltips
|
||||
jQuery.fn.setTooltip = (tooltipOptions, {command, commandElement}={}) ->
|
||||
atom.requireWithGlobals('bootstrap/js/tooltip', {jQuery})
|
||||
|
||||
tooltipOptions = {title: tooltipOptions} if _.isString(tooltipOptions)
|
||||
|
||||
bindings = if commandElement
|
||||
atom.keymap.keyBindingsForCommandMatchingElement(command, commandElement)
|
||||
else
|
||||
atom.keymap.keyBindingsForCommand(command)
|
||||
|
||||
tooltipOptions.title = "#{tooltipOptions.title} #{getKeystroke(bindings)}"
|
||||
|
||||
this.tooltip(jQuery.extend({}, tooltipDefaults, tooltipOptions))
|
||||
|
||||
jQuery.fn.setTooltip.getKeystroke = getKeystroke
|
||||
jQuery.fn.setTooltip.replaceModifiers = replaceModifiers
|
||||
|
||||
module.exports = spacePen
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ module.exports =
|
||||
class Syntax
|
||||
Emitter.includeInto(this)
|
||||
|
||||
registerDeserializer(this)
|
||||
atom.deserializers.add(this)
|
||||
|
||||
@deserialize: ({grammarOverridesByPath}) ->
|
||||
syntax = new Syntax()
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ class Task
|
||||
@callback = args.pop() if _.isFunction(args[args.length - 1])
|
||||
@send({event: 'start', args})
|
||||
|
||||
# Public: Send message to the task
|
||||
# Public: Send message to the task.
|
||||
#
|
||||
# * message:
|
||||
# The message to send
|
||||
|
||||
+39
-67
@@ -1,32 +1,28 @@
|
||||
crypto = require 'crypto'
|
||||
_ = require 'underscore-plus'
|
||||
{Emitter, Subscriber} = require 'emissary'
|
||||
guid = require 'guid'
|
||||
Q = require 'q'
|
||||
{P} = require 'scandal'
|
||||
telepath = require 'telepath'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
File = require './file'
|
||||
|
||||
{Point, Range} = telepath
|
||||
|
||||
# Private: Represents the contents of a file.
|
||||
#
|
||||
# The `Buffer` is often associated with a {File}. However, this is not always
|
||||
# the case, as a `Buffer` could be an unsaved chunk of text.
|
||||
# The `TextBuffer` is often associated with a {File}. However, this is not always
|
||||
# the case, as a `TextBuffer` could be an unsaved chunk of text.
|
||||
module.exports =
|
||||
class TextBuffer
|
||||
class TextBuffer extends telepath.Model
|
||||
Emitter.includeInto(this)
|
||||
Subscriber.includeInto(this)
|
||||
|
||||
@acceptsDocuments: true
|
||||
@version: 2
|
||||
registerDeserializer(this)
|
||||
|
||||
@deserialize: (state, params) ->
|
||||
buffer = new this(state, params)
|
||||
buffer.load()
|
||||
buffer
|
||||
@properties
|
||||
text: -> new telepath.String('', replicated: false)
|
||||
filePath: null
|
||||
relativePath: null
|
||||
modifiedWhenLastPersisted: false
|
||||
digestWhenLastPersisted: null
|
||||
|
||||
stoppedChangingDelay: 300
|
||||
stoppedChangingTimeout: null
|
||||
@@ -36,34 +32,28 @@ class TextBuffer
|
||||
file: null
|
||||
refcount: 0
|
||||
|
||||
# Creates a new buffer.
|
||||
#
|
||||
# * optionsOrState - An {Object} or a telepath.Document
|
||||
# + filePath - A {String} representing the file path
|
||||
constructor: (optionsOrState={}, params={}) ->
|
||||
if optionsOrState instanceof telepath.Document
|
||||
{@project} = params
|
||||
@state = optionsOrState
|
||||
@id = @state.get('id')
|
||||
filePath = @state.get('relativePath')
|
||||
@text = @state.get('text')
|
||||
@useSerializedText = @state.get('isModified') != false
|
||||
else
|
||||
{@project, filePath} = optionsOrState
|
||||
@text = new telepath.String(initialText ? '', replicated: false)
|
||||
@id = guid.create().toString()
|
||||
@state = atom.site.createDocument
|
||||
id: @id
|
||||
deserializer: @constructor.name
|
||||
version: @constructor.version
|
||||
text: @text
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@loadWhenAttached = @getState()?
|
||||
|
||||
# Private: Called by telepath.
|
||||
attached: ->
|
||||
@loaded = false
|
||||
@useSerializedText = @modifiedWhenLastPersisted != false
|
||||
|
||||
@subscribe @text, 'changed', @handleTextChange
|
||||
@subscribe @text, 'marker-created', (marker) => @emit 'marker-created', marker
|
||||
@subscribe @text, 'markers-updated', => @emit 'markers-updated'
|
||||
|
||||
@setPath(@project.resolve(filePath)) if @project
|
||||
@setPath(@filePath)
|
||||
|
||||
@load() if @loadWhenAttached
|
||||
|
||||
# Private: Called by telepath.
|
||||
beforePersistence: ->
|
||||
@modifiedWhenLastPersisted = @isModified()
|
||||
@digestWhenLastPersisted = @file?.getDigest()
|
||||
|
||||
loadSync: ->
|
||||
@updateCachedDiskContentsSync()
|
||||
@@ -74,7 +64,7 @@ class TextBuffer
|
||||
|
||||
finishLoading: ->
|
||||
@loaded = true
|
||||
if @useSerializedText and @state.get('diskContentsDigest') == @file?.getDigest()
|
||||
if @useSerializedText and @digestWhenLastPersisted is @file?.getDigest()
|
||||
@emitModifiedStatusChanged(true)
|
||||
else
|
||||
@reload()
|
||||
@@ -92,11 +82,11 @@ class TextBuffer
|
||||
|
||||
destroy: ->
|
||||
unless @destroyed
|
||||
@cancelStoppedChangingTimeout()
|
||||
@file?.off()
|
||||
@unsubscribe()
|
||||
@destroyed = true
|
||||
@project?.removeBuffer(this)
|
||||
@emit 'destroyed'
|
||||
@emit 'destroyed', this
|
||||
|
||||
isRetained: -> @refcount > 0
|
||||
|
||||
@@ -109,16 +99,6 @@ class TextBuffer
|
||||
@destroy() unless @isRetained()
|
||||
this
|
||||
|
||||
serialize: ->
|
||||
state = @state.clone()
|
||||
state.set('isModified', @isModified())
|
||||
state.set('diskContentsDigest', @file.getDigest()) if @file
|
||||
for marker in state.get('text').getMarkers() when marker.isRemote()
|
||||
marker.destroy()
|
||||
state
|
||||
|
||||
getState: -> @state
|
||||
|
||||
subscribeToFile: ->
|
||||
@file.on "contents-changed", =>
|
||||
@conflict = true if @isModified()
|
||||
@@ -140,19 +120,18 @@ class TextBuffer
|
||||
@emitModifiedStatusChanged(@isModified())
|
||||
|
||||
@file.on "moved", =>
|
||||
@state.set('relativePath', @project.relativize(@getPath()))
|
||||
@emit "path-changed", this
|
||||
|
||||
### Public ###
|
||||
|
||||
# Identifies if the buffer belongs to multiple editors.
|
||||
#
|
||||
# For example, if the {Editor} was split.
|
||||
# For example, if the {EditorView} was split.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
hasMultipleEditors: -> @refcount > 1
|
||||
|
||||
# Reloads a file in the {EditSession}.
|
||||
# Reloads a file in the {Editor}.
|
||||
#
|
||||
# Sets the buffer's content to the cached disk contents
|
||||
reload: ->
|
||||
@@ -183,10 +162,7 @@ class TextBuffer
|
||||
@file?.getPath()
|
||||
|
||||
getUri: ->
|
||||
@getRelativePath()
|
||||
|
||||
getRelativePath: ->
|
||||
@state.get('relativePath')
|
||||
atom.project.relativize(@getPath())
|
||||
|
||||
# Sets the path for the file.
|
||||
#
|
||||
@@ -202,7 +178,6 @@ class TextBuffer
|
||||
else
|
||||
@file = null
|
||||
|
||||
@state.set('relativePath', @project.relativize(path))
|
||||
@emit "path-changed", this
|
||||
|
||||
# Retrieves the current buffer's file extension.
|
||||
@@ -411,12 +386,12 @@ class TextBuffer
|
||||
saveAs: (path) ->
|
||||
unless path then throw new Error("Can't save buffer with no file path")
|
||||
|
||||
@emit 'will-be-saved'
|
||||
@emit 'will-be-saved', this
|
||||
@setPath(path)
|
||||
@cachedDiskContents = @getText()
|
||||
@file.write(@getText())
|
||||
@emitModifiedStatusChanged(false)
|
||||
@emit 'saved'
|
||||
@emit 'saved', this
|
||||
|
||||
# Identifies if the buffer was modified.
|
||||
#
|
||||
@@ -653,12 +628,6 @@ class TextBuffer
|
||||
return match[0][0] != '\t'
|
||||
undefined
|
||||
|
||||
# Checks out the current `HEAD` revision of the file.
|
||||
checkoutHead: ->
|
||||
path = @getPath()
|
||||
return unless path
|
||||
@project.getRepo()?.checkoutHead(path)
|
||||
|
||||
### Internal ###
|
||||
|
||||
transact: (fn) -> @text.transact fn
|
||||
@@ -680,8 +649,11 @@ class TextBuffer
|
||||
else
|
||||
text
|
||||
|
||||
scheduleModifiedEvents: ->
|
||||
cancelStoppedChangingTimeout: ->
|
||||
clearTimeout(@stoppedChangingTimeout) if @stoppedChangingTimeout
|
||||
|
||||
scheduleModifiedEvents: ->
|
||||
@cancelStoppedChangingTimeout()
|
||||
stoppedChangingCallback = =>
|
||||
@stoppedChangingTimeout = null
|
||||
modifiedStatus = @isModified()
|
||||
@@ -700,7 +672,7 @@ class TextBuffer
|
||||
console.log row, line, line.length
|
||||
|
||||
getDebugSnapshot: ->
|
||||
lines = ['Buffer:']
|
||||
lines = ['TextBuffer:']
|
||||
for row in [0..@getLastRow()]
|
||||
lines.push "#{row}: #{@lineForRow(row)}"
|
||||
lines.join('\n')
|
||||
|
||||
+18
-15
@@ -8,11 +8,9 @@ Package = require './package'
|
||||
AtomPackage = require './atom-package'
|
||||
{$} = require './space-pen-extensions'
|
||||
|
||||
|
||||
# Private: Handles discovering and loading available themes.
|
||||
###
|
||||
Themes are a subset of packages
|
||||
###
|
||||
#
|
||||
# Themes are a subset of packages
|
||||
module.exports =
|
||||
class ThemeManager
|
||||
Emitter.includeInto(this)
|
||||
@@ -56,6 +54,7 @@ class ThemeManager
|
||||
themeNames = _.clone(themeNames).reverse()
|
||||
|
||||
@packageManager.activatePackage(themeName) for themeName in themeNames
|
||||
@refreshLessCache()
|
||||
@loadUserStylesheet()
|
||||
@reloadBaseStylesheets()
|
||||
@emit('reloaded')
|
||||
@@ -66,6 +65,10 @@ class ThemeManager
|
||||
@packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes()
|
||||
null
|
||||
|
||||
# Internal-only:
|
||||
refreshLessCache: ->
|
||||
@lessCache?.setImportPaths(@getImportPaths())
|
||||
|
||||
# Public: Set the list of enabled themes.
|
||||
#
|
||||
# * enabledThemeNames: An {Array} of {String} theme names.
|
||||
@@ -112,8 +115,8 @@ class ThemeManager
|
||||
@requireStylesheet(nativeStylesheetPath)
|
||||
|
||||
# Internal-only:
|
||||
stylesheetElementForId: (id) ->
|
||||
$("""head style[id="#{id}"]""")
|
||||
stylesheetElementForId: (id, htmlElement=$('html')) ->
|
||||
htmlElement.find("""head style[id="#{id}"]""")
|
||||
|
||||
# Internal-only:
|
||||
resolveStylesheet: (stylesheetPath) ->
|
||||
@@ -128,10 +131,10 @@ class ThemeManager
|
||||
# LESS file in the stylesheets path.
|
||||
#
|
||||
# Returns the absolute path to the stylesheet
|
||||
requireStylesheet: (stylesheetPath) ->
|
||||
requireStylesheet: (stylesheetPath, ttype = 'bundled', htmlElement) ->
|
||||
if fullPath = @resolveStylesheet(stylesheetPath)
|
||||
content = @loadStylesheet(fullPath)
|
||||
@applyStylesheet(fullPath, content)
|
||||
@applyStylesheet(fullPath, content, ttype = 'bundled', htmlElement)
|
||||
else
|
||||
throw new Error("Could not find a file at path '#{stylesheetPath}'")
|
||||
|
||||
@@ -146,9 +149,9 @@ class ThemeManager
|
||||
|
||||
# Internal-only:
|
||||
loadLessStylesheet: (lessStylesheetPath) ->
|
||||
unless lessCache?
|
||||
unless @lessCache?
|
||||
LessCompileCache = require './less-compile-cache'
|
||||
@lessCache = new LessCompileCache({@resourcePath})
|
||||
@lessCache = new LessCompileCache({@resourcePath, importPaths: @getImportPaths()})
|
||||
|
||||
try
|
||||
@lessCache.read(lessStylesheetPath)
|
||||
@@ -170,12 +173,12 @@ class ThemeManager
|
||||
@stylesheetElementForId(@stringToId(fullPath)).remove()
|
||||
|
||||
# Internal-only:
|
||||
applyStylesheet: (path, text, ttype = 'bundled') ->
|
||||
styleElement = @stylesheetElementForId(@stringToId(path))
|
||||
applyStylesheet: (path, text, ttype = 'bundled', htmlElement=$('html')) ->
|
||||
styleElement = @stylesheetElementForId(@stringToId(path), htmlElement)
|
||||
if styleElement.length
|
||||
styleElement.text(text)
|
||||
else
|
||||
if $("head style.#{ttype}").length
|
||||
$("head style.#{ttype}:last").after "<style class='#{ttype}' id='#{@stringToId(path)}'>#{text}</style>"
|
||||
if htmlElement.find("head style.#{ttype}").length
|
||||
htmlElement.find("head style.#{ttype}:last").after "<style class='#{ttype}' id='#{@stringToId(path)}'>#{text}</style>"
|
||||
else
|
||||
$("head").append "<style class='#{ttype}' id='#{@stringToId(path)}'>#{text}</style>"
|
||||
htmlElement.find("head").append "<style class='#{ttype}' id='#{@stringToId(path)}'>#{text}</style>"
|
||||
|
||||
@@ -21,7 +21,7 @@ class TokenizedBuffer
|
||||
visible: false
|
||||
|
||||
@acceptsDocuments: true
|
||||
registerDeserializer(this)
|
||||
atom.deserializers.add(this)
|
||||
|
||||
@deserialize: (state) ->
|
||||
new this(state)
|
||||
@@ -31,15 +31,15 @@ class TokenizedBuffer
|
||||
@state = optionsOrState
|
||||
|
||||
# TODO: This needs to be made async, but should wait until the new Telepath changes land
|
||||
@buffer = project.bufferForPathSync(optionsOrState.get('bufferPath'))
|
||||
@buffer = atom.project.bufferForPathSync(optionsOrState.get('bufferPath'))
|
||||
else
|
||||
{ @buffer, tabLength } = optionsOrState
|
||||
@state = atom.site.createDocument
|
||||
deserializer: @constructor.name
|
||||
bufferPath: @buffer.getRelativePath()
|
||||
bufferPath: @buffer.getPath()
|
||||
tabLength: tabLength ? atom.config.get('editor.tabLength') ? 2
|
||||
|
||||
@subscribe syntax, 'grammar-added grammar-updated', (grammar) =>
|
||||
@subscribe atom.syntax, 'grammar-added grammar-updated', (grammar) =>
|
||||
if grammar.injectionSelector?
|
||||
@resetTokenizedLines() if @hasTokenForSelector(grammar.injectionSelector)
|
||||
else
|
||||
@@ -48,7 +48,7 @@ class TokenizedBuffer
|
||||
|
||||
@on 'grammar-changed grammar-updated', => @resetTokenizedLines()
|
||||
@subscribe @buffer, "changed", (e) => @handleBufferChange(e)
|
||||
@subscribe @buffer, "path-changed", => @state.set('bufferPath', @buffer.getRelativePath())
|
||||
@subscribe @buffer, "path-changed", => @state.set('bufferPath', @buffer.getPath())
|
||||
|
||||
@reloadGrammar()
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@ require './window'
|
||||
|
||||
Atom = require './atom'
|
||||
window.atom = new Atom()
|
||||
window.setUpEnvironment('editor')
|
||||
window.startEditorWindow()
|
||||
atom.setUpEnvironment('editor')
|
||||
atom.startEditorWindow()
|
||||
console.log "Window load time: #{Date.now() - startTime}ms"
|
||||
|
||||
@@ -54,7 +54,8 @@ class WindowEventHandler
|
||||
|
||||
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
|
||||
|
||||
@subscribe $(document), 'keydown', atom.keymap.handleKeyEvent
|
||||
@subscribe $(document), 'keydown', (event) ->
|
||||
atom.keymap.handleKeyEvent(event)
|
||||
|
||||
@subscribe $(document), 'drop', (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
+2
-116
@@ -1,120 +1,6 @@
|
||||
path = require 'path'
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
ipc = require 'ipc'
|
||||
WindowEventHandler = require './window-event-handler'
|
||||
|
||||
### Internal ###
|
||||
|
||||
windowEventHandler = null
|
||||
|
||||
# Schedule the window to be shown and focused on the next tick
|
||||
#
|
||||
# This is done in a next tick to prevent a white flicker from occurring
|
||||
# if called synchronously.
|
||||
displayWindow = ->
|
||||
setImmediate ->
|
||||
atom.show()
|
||||
atom.focus()
|
||||
|
||||
# This method is called in any window needing a general environment, including specs
|
||||
window.setUpEnvironment = (windowMode) ->
|
||||
atom.windowMode = windowMode
|
||||
window.resourcePath = atom.getLoadSettings().resourcePath
|
||||
atom.initialize()
|
||||
#TODO remove once all packages use the atom global
|
||||
window.config = atom.config
|
||||
window.syntax = atom.syntax
|
||||
window.pasteboard = atom.pasteboard
|
||||
window.keymap = atom.keymap
|
||||
window.site = atom.site
|
||||
|
||||
# Set up the default event handlers and menus for a non-editor windows.
|
||||
#
|
||||
# This can be used by packages to have a minimum level of keybindings and
|
||||
# menus available when not using the standard editor window.
|
||||
#
|
||||
# This should only be called after setUpEnvironment() has been called.
|
||||
window.setUpDefaultEvents = ->
|
||||
windowEventHandler = new WindowEventHandler
|
||||
atom.keymap.loadBundledKeymaps()
|
||||
atom.menu.update()
|
||||
|
||||
# This method is only called when opening a real application window
|
||||
window.startEditorWindow = ->
|
||||
if process.platform is 'darwin'
|
||||
installAtomCommand()
|
||||
installApmCommand()
|
||||
|
||||
windowEventHandler = new WindowEventHandler
|
||||
atom.restoreDimensions()
|
||||
atom.config.load()
|
||||
atom.config.setDefaults('core', require('./root-view').configDefaults)
|
||||
atom.config.setDefaults('editor', require('./editor').configDefaults)
|
||||
atom.keymap.loadBundledKeymaps()
|
||||
atom.themes.loadBaseStylesheets()
|
||||
atom.packages.loadPackages()
|
||||
deserializeEditorWindow()
|
||||
atom.packages.activate()
|
||||
atom.keymap.loadUserKeymap()
|
||||
atom.requireUserInitScript()
|
||||
atom.menu.update()
|
||||
$(window).on 'unload', ->
|
||||
$(document.body).hide()
|
||||
unloadEditorWindow()
|
||||
false
|
||||
|
||||
displayWindow()
|
||||
|
||||
window.unloadEditorWindow = ->
|
||||
return if not atom.project and not atom.rootView
|
||||
windowState = atom.getWindowState()
|
||||
windowState.set('project', atom.project.serialize())
|
||||
windowState.set('syntax', atom.syntax.serialize())
|
||||
windowState.set('rootView', atom.rootView.serialize())
|
||||
atom.packages.deactivatePackages()
|
||||
windowState.set('packageStates', atom.packages.packageStates)
|
||||
atom.saveWindowState()
|
||||
atom.rootView.remove()
|
||||
atom.project.destroy()
|
||||
windowEventHandler?.unsubscribe()
|
||||
window.rootView = null
|
||||
window.project = null
|
||||
|
||||
installAtomCommand = (callback) ->
|
||||
commandPath = path.join(window.resourcePath, 'atom.sh')
|
||||
require('./command-installer').install(commandPath, callback)
|
||||
|
||||
installApmCommand = (callback) ->
|
||||
commandPath = path.join(window.resourcePath, 'node_modules', '.bin', 'apm')
|
||||
require('./command-installer').install(commandPath, callback)
|
||||
|
||||
window.deserializeEditorWindow = ->
|
||||
atom.deserializePackageStates()
|
||||
atom.deserializeProject()
|
||||
window.project = atom.project
|
||||
atom.deserializeRootView()
|
||||
window.rootView = atom.rootView
|
||||
|
||||
window.onerror = ->
|
||||
atom.openDevTools()
|
||||
|
||||
#TODO remove once all packages use the atom global
|
||||
window.registerDeserializers = (args...) ->
|
||||
atom.deserializers.add(args...)
|
||||
window.registerDeserializer = (args...) ->
|
||||
atom.deserializers.add(args...)
|
||||
window.registerDeferredDeserializer = (args...) ->
|
||||
atom.deserializers.addDeferred(args...)
|
||||
window.unregisterDeserializer = (args...) ->
|
||||
atom.deserializers.remove(args...)
|
||||
window.deserialize = (args...) ->
|
||||
atom.deserializers.deserialize(args...)
|
||||
window.getDeserializer = (args...) ->
|
||||
atom.deserializers.get(args...)
|
||||
window.requireWithGlobals = (args...) ->
|
||||
atom.requireWithGlobals(args...)
|
||||
|
||||
# Public: Measure how long a function takes to run.
|
||||
#
|
||||
# * description:
|
||||
@@ -124,9 +10,9 @@ window.requireWithGlobals = (args...) ->
|
||||
#
|
||||
# Returns the value returned by the given function.
|
||||
window.measure = (description, fn) ->
|
||||
start = new Date().getTime()
|
||||
start = Date.now()
|
||||
value = fn()
|
||||
result = new Date().getTime() - start
|
||||
result = Date.now() - start
|
||||
console.log description, result
|
||||
value
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
-webkit-user-select: none;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
font-family: Inconsolata, Monaco, Courier;
|
||||
font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -22,6 +22,6 @@
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body tabindex="-1">
|
||||
<body class="workspace" tabindex="-1">
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -20,7 +20,7 @@ body {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#HTMLReporter { font-size: 11px; font-family: Monaco, monospace; line-height: 1.6em; color: #333333; }
|
||||
#HTMLReporter { font-size: 11px; font-family: Monaco, Consolas, monospace; line-height: 1.6em; color: #333333; }
|
||||
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
|
||||
|
||||
#HTMLReporter .symbolHeader {
|
||||
|
||||
@@ -9,6 +9,7 @@ body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-family: @font-family;
|
||||
font-size: @font-size;
|
||||
}
|
||||
|
||||
h1,
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
// Sizes
|
||||
|
||||
@font-size: 12px;
|
||||
@font-size: 13px;
|
||||
|
||||
@disclosure-arrow-size: 12px;
|
||||
|
||||
@@ -81,4 +81,4 @@
|
||||
|
||||
// Other
|
||||
|
||||
@font-family: 'Lucida Grande', Arial, sans-serif;
|
||||
@font-family: 'Lucida Grande', 'Segoe UI', sans-serif;
|
||||
|
||||
@@ -30,16 +30,16 @@ module.exports = (grunt) ->
|
||||
themeMains.push(mainPath) if grunt.file.isFile(mainPath)
|
||||
importPaths.unshift(stylesheetsDir) if grunt.file.isDir(stylesheetsDir)
|
||||
|
||||
grunt.log.writeln("Building LESS cache for #{configuration.join(', ').yellow}")
|
||||
grunt.verbose.writeln("Building LESS cache for #{configuration.join(', ').yellow}")
|
||||
lessCache = new LessCache
|
||||
cacheDir: directory
|
||||
resourcePath: path.resolve('.')
|
||||
importPaths: importPaths
|
||||
|
||||
for file in @filesSrc
|
||||
grunt.log.writeln("File #{file.cyan} created in cache.")
|
||||
grunt.verbose.writeln("File #{file.cyan} created in cache.")
|
||||
lessCache.readFileSync(file)
|
||||
|
||||
for file in themeMains
|
||||
grunt.log.writeln("File #{file.cyan} created in cache.")
|
||||
grunt.verbose.writeln("File #{file.cyan} created in cache.")
|
||||
lessCache.readFileSync(file)
|
||||
|
||||
@@ -84,7 +84,7 @@ module.exports = (grunt) ->
|
||||
for name, version of packageDependencies
|
||||
do (name, version) ->
|
||||
tasks.push (callback) ->
|
||||
grunt.log.writeln("Publishing #{name}@#{version}")
|
||||
grunt.verbose.writeln("Publishing #{name}@#{version}")
|
||||
tag = "v#{version}"
|
||||
packageExists name, token, (error, exists) ->
|
||||
if error?
|
||||
|
||||
+16
-10
@@ -2,6 +2,7 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
async = require 'async'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
@@ -10,7 +11,7 @@ module.exports = (grunt) ->
|
||||
packageSpecQueue = null
|
||||
|
||||
runPackageSpecs = (callback) ->
|
||||
passed = true
|
||||
failedPackages = []
|
||||
rootDir = grunt.config.get('atom.shellAppDir')
|
||||
appDir = grunt.config.get('atom.appDir')
|
||||
atomPath = path.join(appDir, 'atom.sh')
|
||||
@@ -23,10 +24,10 @@ module.exports = (grunt) ->
|
||||
opts:
|
||||
cwd: packagePath
|
||||
env: _.extend({}, process.env, ATOM_PATH: rootDir)
|
||||
grunt.log.writeln("Launching #{path.basename(packagePath)} specs.")
|
||||
grunt.verbose.writeln "Launching #{path.basename(packagePath)} specs."
|
||||
spawn options, (error, results, code) ->
|
||||
grunt.log.writeln()
|
||||
passed = passed and not error and code is 0
|
||||
|
||||
failedPackages.push path.basename(packagePath) if error
|
||||
callback()
|
||||
|
||||
modulesDirectory = path.resolve('node_modules')
|
||||
@@ -37,7 +38,7 @@ module.exports = (grunt) ->
|
||||
packageSpecQueue.push(packagePath)
|
||||
|
||||
packageSpecQueue.concurrency = 1
|
||||
packageSpecQueue.drain = -> callback(null, passed)
|
||||
packageSpecQueue.drain = -> callback(null, failedPackages)
|
||||
|
||||
runCoreSpecs = (callback) ->
|
||||
contentsDir = grunt.config.get('atom.contentsDir')
|
||||
@@ -49,15 +50,20 @@ module.exports = (grunt) ->
|
||||
cmd: appPath
|
||||
args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}"]
|
||||
spawn options, (error, results, code) ->
|
||||
grunt.log.writeln()
|
||||
packageSpecQueue.concurrency = 2
|
||||
callback(null, not error and code is 0)
|
||||
callback(null, error)
|
||||
|
||||
grunt.registerTask 'run-specs', 'Run the specs', ->
|
||||
done = @async()
|
||||
startTime = Date.now()
|
||||
|
||||
async.parallel [runCoreSpecs, runPackageSpecs], (error, results) ->
|
||||
[coreSpecPassed, packageSpecsPassed] = results
|
||||
[coreSpecFailed, failedPackages] = results
|
||||
elapsedTime = Math.round((Date.now() - startTime) / 100) / 10
|
||||
grunt.log.writeln("Total spec time: #{elapsedTime}s")
|
||||
done(coreSpecPassed and packageSpecsPassed)
|
||||
grunt.verbose.writeln("Total spec time: #{elapsedTime}s")
|
||||
failures = failedPackages
|
||||
failures.push "atom core" if coreSpecFailed
|
||||
|
||||
grunt.log.error("[Error]".red + " #{failures.join(', ')} spec(s) failed") if failures.length > 0
|
||||
|
||||
done(!coreSpecFailed and failedPackages.length == 0)
|
||||
|
||||
@@ -23,7 +23,7 @@ module.exports = (grunt) ->
|
||||
catch error
|
||||
grunt.fatal(error)
|
||||
|
||||
grunt.log.writeln("Copied #{source.cyan} to #{destination.cyan}.")
|
||||
grunt.verbose.writeln("Copied #{source.cyan} to #{destination.cyan}.")
|
||||
|
||||
mkdir: (args...) ->
|
||||
grunt.file.mkdir(args...)
|
||||
@@ -32,9 +32,18 @@ module.exports = (grunt) ->
|
||||
grunt.file.delete(args..., force: true) if grunt.file.exists(args...)
|
||||
|
||||
spawn: (options, callback) ->
|
||||
grunt.util.spawn options, (error, results, code) ->
|
||||
grunt.log.errorlns results.stderr if results.stderr
|
||||
callback(error, results, code)
|
||||
childProcess = require 'child_process'
|
||||
stdout = []
|
||||
stderr = []
|
||||
error = null
|
||||
proc = childProcess.spawn(options.cmd, options.args, options.opts)
|
||||
proc.stdout.on 'data', (data) -> stdout.push(data.toString())
|
||||
proc.stderr.on 'data', (data) -> stderr.push(data.toString())
|
||||
proc.on 'exit', (exitCode, signal) ->
|
||||
error = new Error(signal) if exitCode != 0
|
||||
results = {stderr: stderr.join(''), stdout: stdout.join(''), code: exitCode}
|
||||
grunt.log.error results.stderr if exitCode != 0
|
||||
callback(error, results, exitCode)
|
||||
|
||||
isAtomPackage: (packagePath) ->
|
||||
try
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = (grunt) ->
|
||||
return
|
||||
|
||||
spawn {cmd: 'security', args: ['-q', 'find-generic-password', '-ws', 'GitHub API Token']}, (error, result, code) ->
|
||||
accessToken = result unless error?
|
||||
accessToken = result.stdout unless error?
|
||||
callback(error, accessToken)
|
||||
|
||||
callAtomShellReposApi = (path, callback) ->
|
||||
@@ -112,7 +112,7 @@ module.exports = (grunt) ->
|
||||
# Manually handle redirection so headers would not be sent for S3.
|
||||
downloadAtomShell(version, response.headers.location, callback)
|
||||
else if response.statusCode is 200
|
||||
grunt.log.writeln("Downloading atom-shell version #{version.cyan}")
|
||||
grunt.verbose.writeln("Downloading atom-shell version #{version.cyan}")
|
||||
cacheDirectory = getCachePath(version)
|
||||
rm(cacheDirectory)
|
||||
mkdir(cacheDirectory)
|
||||
@@ -146,7 +146,7 @@ module.exports = (grunt) ->
|
||||
downloadAtomShell version, url, callback
|
||||
|
||||
unzipAtomShell = (zipPath, callback) ->
|
||||
grunt.log.writeln('Unzipping atom-shell')
|
||||
grunt.verbose.writeln('Unzipping atom-shell')
|
||||
directoryPath = path.dirname(zipPath)
|
||||
|
||||
if process.platform is 'darwin'
|
||||
@@ -167,7 +167,7 @@ module.exports = (grunt) ->
|
||||
rebuildNativeModules = (previousVersion, callback) ->
|
||||
newVersion = getAtomShellVersion()
|
||||
if newVersion and newVersion isnt previousVersion
|
||||
grunt.log.writeln("Rebuilding native modules for new atom-shell version #{newVersion.cyan}.")
|
||||
grunt.verbose.writeln("Rebuilding native modules for new atom-shell version #{newVersion.cyan}.")
|
||||
cmd = path.join('node_modules', '.bin', 'apm')
|
||||
cmd += ".cmd" if process.platform is 'win32'
|
||||
spawn {cmd, args: ['rebuild']}, (error) -> callback(error)
|
||||
@@ -186,7 +186,7 @@ module.exports = (grunt) ->
|
||||
currentAtomShellVersion = getAtomShellVersion()
|
||||
if atomShellVersion isnt currentAtomShellVersion
|
||||
if isAtomShellVersionCached(atomShellVersion)
|
||||
grunt.log.writeln("Installing cached atom-shell #{atomShellVersion.cyan}")
|
||||
grunt.verbose.writeln("Installing cached atom-shell #{atomShellVersion.cyan}")
|
||||
installAtomShell(atomShellVersion)
|
||||
rebuildNativeModules(currentAtomShellVersion, done)
|
||||
else
|
||||
@@ -198,7 +198,7 @@ module.exports = (grunt) ->
|
||||
if error?
|
||||
done(error)
|
||||
else
|
||||
grunt.log.writeln("Installing atom-shell #{atomShellVersion.cyan}")
|
||||
grunt.verbose.writeln("Installing atom-shell #{atomShellVersion.cyan}")
|
||||
installAtomShell(atomShellVersion)
|
||||
rebuildNativeModules(currentAtomShellVersion, done)
|
||||
else
|
||||
|
||||
externo
+1
-1
Submodule vendor/apm updated: 687d81f5a1...809d8d42f7
Referência em uma Nova Issue
Bloquear um usuário