mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge branch 'master' into absolute-paths-in-fuzzy-finder
Conflicts: src/packages/fuzzy-finder/lib/load-paths-handler.coffee
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
$ = require 'jquery'
|
||||
AutocompleteView = require 'autocomplete/lib/autocomplete-view'
|
||||
Autocomplete = require 'autocomplete/lib/autocomplete'
|
||||
Buffer = require 'buffer'
|
||||
Buffer = require 'text-buffer'
|
||||
Editor = require 'editor'
|
||||
RootView = require 'root-view'
|
||||
|
||||
@@ -14,7 +14,7 @@ describe "Autocomplete", ->
|
||||
describe "@activate()", ->
|
||||
it "activates autocomplete on all existing and future editors (but not on autocomplete's own mini editor)", ->
|
||||
spyOn(AutocompleteView.prototype, 'initialize').andCallThrough()
|
||||
autocompletePackage = window.loadPackage("autocomplete")
|
||||
autocompletePackage = atom.activatePackage("autocomplete")
|
||||
expect(AutocompleteView.prototype.initialize).not.toHaveBeenCalled()
|
||||
|
||||
leftEditor = rootView.getActiveView()
|
||||
@@ -41,7 +41,7 @@ describe "AutocompleteView", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
editor = new Editor(editSession: project.buildEditSession('sample.js'))
|
||||
window.loadPackage('autocomplete')
|
||||
atom.activatePackage('autocomplete')
|
||||
autocomplete = new AutocompleteView(editor)
|
||||
miniEditor = autocomplete.miniEditor
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "Autoflow package", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open()
|
||||
window.loadPackage 'autoflow'
|
||||
atom.activatePackage('autoflow')
|
||||
editor = rootView.getActiveView()
|
||||
config.set('editor.preferredLineLength', 30)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ module.exports =
|
||||
|
||||
goToMatchingPair: (editor) ->
|
||||
return unless @pairHighlighted
|
||||
return unless underlayer = editor.pane()?.find('.underlayer')
|
||||
return unless underlayer = editor.getPane()?.find('.underlayer')
|
||||
|
||||
position = editor.getCursorBufferPosition()
|
||||
previousPosition = position.translate([0, -1])
|
||||
@@ -127,7 +127,7 @@ module.exports =
|
||||
startPairPosition
|
||||
|
||||
updateMatch: (editor) ->
|
||||
return unless underlayer = editor.pane()?.find('.underlayer')
|
||||
return unless underlayer = editor.getPane()?.find('.underlayer')
|
||||
|
||||
@hideHighlightViews(editor) if @pairHighlighted
|
||||
@pairHighlighted = false
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "bracket matching", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage('bracket-matcher')
|
||||
atom.activatePackage('bracket-matcher')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
editSession = editor.activeEditSession
|
||||
|
||||
@@ -96,7 +96,7 @@ class CommandLoggerView extends ScrollView
|
||||
w = @treeMap.width()
|
||||
h = @treeMap.height()
|
||||
|
||||
d3 = require 'd3.v3'
|
||||
d3 = require 'd3'
|
||||
|
||||
x = d3.scale.linear().range([0, w])
|
||||
y = d3.scale.linear().range([0, h])
|
||||
|
||||
@@ -21,8 +21,8 @@ module.exports =
|
||||
eventNameLog.lastRun = new Date().getTime()
|
||||
trigger = $.fn.trigger
|
||||
@originalTrigger = trigger
|
||||
$.fn.trigger = (eventName) ->
|
||||
eventName = eventName.type if eventName.type
|
||||
$.fn.trigger = (event) ->
|
||||
eventName = event.type ? event
|
||||
registerTriggeredEvent(eventName) if $(this).events()[eventName]
|
||||
trigger.apply(this, arguments)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "CommandLogger", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
commandLogger = window.loadPackage('command-logger').mainModule
|
||||
commandLogger = atom.activatePackage('command-logger').mainModule
|
||||
commandLogger.eventLog = {}
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ class CommandPaletteView extends SelectList
|
||||
|
||||
filterKey: 'eventDescription'
|
||||
|
||||
previouslyFocusedElement: null
|
||||
keyBindings: null
|
||||
|
||||
initialize: ->
|
||||
@@ -30,10 +29,14 @@ class CommandPaletteView extends SelectList
|
||||
attach: ->
|
||||
super
|
||||
|
||||
@keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement))
|
||||
if @previouslyFocusedElement[0]
|
||||
@eventElement = @previouslyFocusedElement
|
||||
else
|
||||
@eventElement = rootView
|
||||
@keyBindings = _.losslessInvert(keymap.bindingsForElement(@eventElement))
|
||||
|
||||
events = []
|
||||
for eventName, eventDescription of _.extend($(window).events(), @previouslyFocusedElement.events())
|
||||
for eventName, eventDescription of _.extend($(window).events(), @eventElement.events())
|
||||
events.push({eventName, eventDescription}) if eventDescription
|
||||
|
||||
events = _.sortBy events, (e) -> e.eventDescription
|
||||
@@ -53,4 +56,4 @@ class CommandPaletteView extends SelectList
|
||||
|
||||
confirmed: ({eventName}) ->
|
||||
@cancel()
|
||||
@previouslyFocusedElement.trigger(eventName)
|
||||
@eventElement.trigger(eventName)
|
||||
|
||||
@@ -9,7 +9,7 @@ describe "CommandPalette", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage("command-palette")
|
||||
atom.activatePackage("command-palette")
|
||||
rootView.attachToDom().focus()
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
palette = rootView.find('.command-palette').view()
|
||||
@@ -81,3 +81,20 @@ describe "CommandPalette", ->
|
||||
expect(activeEditor.isFocused).toBeTruthy()
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
expect(palette.hasParent()).toBeFalsy()
|
||||
|
||||
describe "when no element has focus", ->
|
||||
it "uses the root view as the element to display and trigger events for", ->
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
$(':focus').blur()
|
||||
rootView.trigger 'command-palette:toggle'
|
||||
keyBindings = _.losslessInvert(keymap.bindingsForElement(rootView.getActiveView()))
|
||||
for eventName, description of rootView.events()
|
||||
eventLi = palette.list.children("[data-event-name='#{eventName}']")
|
||||
if description
|
||||
expect(eventLi).toExist()
|
||||
expect(eventLi.find('.label')).toHaveText(description)
|
||||
expect(eventLi.find('.label').attr('title')).toBe(eventName)
|
||||
for binding in keyBindings[eventName] ? []
|
||||
expect(eventLi.find(".key-binding:contains(#{binding})")).toExist()
|
||||
else
|
||||
expect(eventLi).not.toExist()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
module.exports =
|
||||
@@ -11,8 +11,12 @@ class CommandInterpreter
|
||||
@lastRelativeAddress = compositeCommand if compositeCommand.isRelativeAddress()
|
||||
compositeCommand.execute(@project, activeEditSession)
|
||||
|
||||
repeatRelativeAddress: (activeEditSession) ->
|
||||
@lastRelativeAddress?.execute(@project, activeEditSession)
|
||||
repeatRelativeAddress: (activeEditSession, {reverse}={}) ->
|
||||
return unless @lastRelativeAddress
|
||||
reverse ?= false
|
||||
previousSelectionRange = activeEditSession.getSelection().getBufferRange()
|
||||
address = if reverse then @lastRelativeAddress.reverse() else @lastRelativeAddress
|
||||
|
||||
repeatRelativeAddressInReverse: (activeEditSession) ->
|
||||
@lastRelativeAddress?.reverse().execute(@project, activeEditSession)
|
||||
address.execute(@project, activeEditSession).done ->
|
||||
currentSelectionRange = activeEditSession.getSelection().getBufferRange()
|
||||
$native.beep() if previousSelectionRange.isEqual(currentSelectionRange)
|
||||
|
||||
@@ -44,7 +44,7 @@ class CommandPanelView extends View
|
||||
rootView.command 'command-panel:find-in-file', => @attach('/')
|
||||
rootView.command 'command-panel:find-in-project', => @attach('Xx/')
|
||||
rootView.command 'command-panel:repeat-relative-address', => @repeatRelativeAddress()
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse()
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddress(reverse: true)
|
||||
rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
|
||||
@on 'click', '.expand', @onExpandAll
|
||||
@@ -65,6 +65,9 @@ class CommandPanelView extends View
|
||||
|
||||
destroy: ->
|
||||
@previewList.destroy()
|
||||
rootView.off "command-panel:toggle-preview command-panel:find-in-file command-panel:find-in-project \
|
||||
command-panel:repeat-relative-address command-panel:repeat-relative-address-in-reverse command-panel:set-selection-as-regex-address"
|
||||
@remove()
|
||||
|
||||
toggle: ->
|
||||
if @miniEditor.isFocused
|
||||
@@ -115,7 +118,7 @@ class CommandPanelView extends View
|
||||
escapedCommand: ->
|
||||
@miniEditor.getText()
|
||||
|
||||
execute: (command=@escapedCommand())->
|
||||
execute: (command=@escapedCommand()) ->
|
||||
@loadingMessage.show()
|
||||
@errorMessages.empty()
|
||||
|
||||
@@ -138,6 +141,7 @@ class CommandPanelView extends View
|
||||
else
|
||||
@detach()
|
||||
catch error
|
||||
@loadingMessage.hide()
|
||||
if error.name is "SyntaxError"
|
||||
@flashError()
|
||||
return
|
||||
@@ -154,11 +158,8 @@ class CommandPanelView extends View
|
||||
@historyIndex++
|
||||
@miniEditor.setText(@history[@historyIndex] or '')
|
||||
|
||||
repeatRelativeAddress: ->
|
||||
@commandInterpreter.repeatRelativeAddress(rootView.getActivePaneItem())
|
||||
|
||||
repeatRelativeAddressInReverse: ->
|
||||
@commandInterpreter.repeatRelativeAddressInReverse(rootView.getActivePaneItem())
|
||||
repeatRelativeAddress: (options) ->
|
||||
@commandInterpreter.repeatRelativeAddress(rootView.getActivePaneItem(), options)
|
||||
|
||||
setSelectionAsLastRelativeAddress: ->
|
||||
selection = rootView.getActiveView().getSelectedText()
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports =
|
||||
class Address extends Command
|
||||
compile: (project, buffer, ranges) ->
|
||||
deferred = $.Deferred()
|
||||
deferred.resolve ranges.map (range) =>
|
||||
operations = ranges.map (range) =>
|
||||
newRange = @getRange(buffer, range)
|
||||
|
||||
new Operation
|
||||
@@ -15,6 +15,7 @@ class Address extends Command
|
||||
bufferRange: newRange
|
||||
errorMessage: @errorMessage
|
||||
|
||||
deferred.resolve(operations)
|
||||
deferred.promise()
|
||||
|
||||
isAddress: -> true
|
||||
|
||||
@@ -16,7 +16,7 @@ class SelectAllMatchesInProject extends Command
|
||||
promise = project.scan @regex, ({path, range}) ->
|
||||
operations.push(new Operation(
|
||||
project: project
|
||||
buffer: project.bufferForPath(path)
|
||||
path: path
|
||||
bufferRange: range
|
||||
))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ module.exports =
|
||||
class OperationView extends View
|
||||
@content: ({operation} = {}) ->
|
||||
{prefix, suffix, match, range} = operation.preview()
|
||||
@li 'data-index': operation.index, class: 'operation', =>
|
||||
@li class: 'operation', =>
|
||||
@span range.start.row + 1, class: 'line-number'
|
||||
@span class: 'preview', =>
|
||||
@span prefix
|
||||
|
||||
@@ -1,22 +1,30 @@
|
||||
module.exports =
|
||||
class Operation
|
||||
constructor: ({@project, @buffer, bufferRange, @newText, @preserveSelection, @errorMessage}) ->
|
||||
@buffer.retain()
|
||||
@marker = @buffer.markRange(bufferRange)
|
||||
constructor: ({@project, @path, @buffer, @bufferRange, @newText, @preserveSelection, @errorMessage}) ->
|
||||
if @buffer?
|
||||
@buffer.retain()
|
||||
@getMarker()
|
||||
|
||||
getMarker: ->
|
||||
@marker ?= @getBuffer().markRange(@bufferRange)
|
||||
|
||||
getBuffer: ->
|
||||
@buffer ?= @project.bufferForPath(@path).retain()
|
||||
|
||||
getPath: ->
|
||||
@project.relativize(@buffer.getPath())
|
||||
path = @path ? @getBuffer().getPath()
|
||||
@project.relativize(path)
|
||||
|
||||
getBufferRange: ->
|
||||
@buffer.getMarkerRange(@marker)
|
||||
@getBuffer().getMarkerRange(@getMarker())
|
||||
|
||||
execute: (editSession) ->
|
||||
@buffer.change(@getBufferRange(), @newText) if @newText
|
||||
@getBuffer().change(@getBufferRange(), @newText) if @newText
|
||||
@getBufferRange() unless @preserveSelection
|
||||
|
||||
preview: ->
|
||||
range = @buffer.getMarkerRange(@marker)
|
||||
line = @buffer.lineForRow(range.start.row)
|
||||
range = @getBuffer().getMarkerRange(@getMarker())
|
||||
line = @getBuffer().lineForRow(range.start.row)
|
||||
prefix = line[0...range.start.column]
|
||||
match = line[range.start.column...range.end.column]
|
||||
suffix = line[range.end.column..]
|
||||
@@ -24,5 +32,5 @@ class Operation
|
||||
{prefix, suffix, match, range}
|
||||
|
||||
destroy: ->
|
||||
@buffer.destroyMarker(@marker)
|
||||
@buffer.release()
|
||||
@buffer?.destroyMarker(@marker) if @marker?
|
||||
@buffer?.release()
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
OperationView = require './operation-view'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class PathView extends View
|
||||
@content: ({path, operations, previewList} = {}) ->
|
||||
@content: ({path, previewList} = {}) ->
|
||||
classes = ['path']
|
||||
classes.push('readme') if fs.isReadmePath(path)
|
||||
@li class: classes.join(' '), =>
|
||||
@div outlet: 'pathDetails', class: 'path-details', =>
|
||||
@span class: 'path-name', path
|
||||
@span "(#{operations.length})", class: 'path-match-number'
|
||||
@span outlet: 'description', class: 'path-match-number'
|
||||
@ul outlet: 'matches', class: 'matches', =>
|
||||
for operation in operations
|
||||
@subview "operation#{operation.index}", new OperationView({operation, previewList})
|
||||
|
||||
initialize: ({@previewList}) ->
|
||||
@pathDetails.on 'mousedown', => @toggle(true)
|
||||
@@ -27,6 +25,10 @@ class PathView extends View
|
||||
@toggle(true)
|
||||
false
|
||||
|
||||
addOperation: (operation) ->
|
||||
@matches.append new OperationView({operation, @previewList})
|
||||
@description.text("(#{@matches.find('li').length})")
|
||||
|
||||
isSelected: ->
|
||||
@hasClass('selected') or @find('.selected').length
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
$ = require 'jquery'
|
||||
ScrollView = require 'scroll-view'
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
PathView = require './path-view'
|
||||
OperationView = require './operation-view'
|
||||
|
||||
@@ -11,12 +11,17 @@ class PreviewList extends ScrollView
|
||||
@ol class: 'preview-list', tabindex: -1
|
||||
|
||||
operations: null
|
||||
viewsForPath: null
|
||||
pixelOverdraw: 100
|
||||
lastRenderedOperationIndex: null
|
||||
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
@on 'core:move-down', => @selectNextOperation(); false
|
||||
@on 'core:move-up', => @selectPreviousOperation(); false
|
||||
@on 'scroll', =>
|
||||
@renderOperations() if @scrollBottom() >= (@prop('scrollHeight'))
|
||||
|
||||
@command 'command-panel:collapse-all', => @collapseAllPaths()
|
||||
@command 'command-panel:expand-all', => @expandAllPaths()
|
||||
@@ -25,6 +30,7 @@ class PreviewList extends ScrollView
|
||||
@children().each (index, element) -> $(element).view().expand()
|
||||
|
||||
collapseAllPaths: ->
|
||||
@renderOperations(renderAll: true)
|
||||
@children().each (index, element) -> $(element).view().collapse()
|
||||
|
||||
destroy: ->
|
||||
@@ -35,23 +41,31 @@ class PreviewList extends ScrollView
|
||||
populate: (operations) ->
|
||||
@destroyOperations() if @operations
|
||||
@operations = operations
|
||||
@lastRenderedOperationIndex = 0
|
||||
@empty()
|
||||
|
||||
operation.index = index for operation, index in operations
|
||||
operationsByPath = _.groupBy(operations, (operation) -> operation.getPath())
|
||||
for path, operations of operationsByPath
|
||||
@append new PathView({path, operations, previewList: this})
|
||||
@viewsForPath = {}
|
||||
|
||||
@show()
|
||||
@find('.operation:first').addClass('selected')
|
||||
@setLineNumberWidth()
|
||||
@renderOperations()
|
||||
|
||||
setLineNumberWidth: ->
|
||||
lineNumbers = @find('.line-number')
|
||||
maxWidth = 0
|
||||
lineNumbers.each (index, element) ->
|
||||
maxWidth = Math.max($(element).outerWidth(), maxWidth)
|
||||
lineNumbers.width(maxWidth)
|
||||
@find('.operation:first').addClass('selected')
|
||||
|
||||
renderOperations: ({renderAll}={}) ->
|
||||
renderAll ?= false
|
||||
startingScrollHeight = @prop('scrollHeight')
|
||||
for operation in @operations[@lastRenderedOperationIndex..]
|
||||
pathView = @pathViewForPath(operation.getPath())
|
||||
pathView.addOperation(operation)
|
||||
@lastRenderedOperationIndex++
|
||||
break if not renderAll and @prop('scrollHeight') >= startingScrollHeight + @pixelOverdraw and @prop('scrollHeight') > @height() + @pixelOverdraw
|
||||
|
||||
pathViewForPath: (path) ->
|
||||
pathView = @viewsForPath[path]
|
||||
if not pathView
|
||||
pathView = new PathView({path: path, previewList: this})
|
||||
@viewsForPath[path] = pathView
|
||||
@append(pathView)
|
||||
pathView
|
||||
|
||||
selectNextOperation: ->
|
||||
selectedView = @find('.selected').view()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CommandInterpreter = require 'command-panel/lib/command-interpreter'
|
||||
Project = require 'project'
|
||||
Buffer = require 'buffer'
|
||||
Buffer = require 'text-buffer'
|
||||
EditSession = require 'edit-session'
|
||||
|
||||
_ = require 'underscore'
|
||||
|
||||
@@ -11,7 +11,7 @@ describe "CommandPanel", ->
|
||||
rootView.enableKeymap()
|
||||
editSession = rootView.getActivePaneItem()
|
||||
buffer = editSession.buffer
|
||||
commandPanelMain = window.loadPackage('command-panel', activateImmediately: true).mainModule
|
||||
commandPanelMain = atom.activatePackage('command-panel', immediate: true).mainModule
|
||||
commandPanel = commandPanelMain.commandPanelView
|
||||
commandPanel.history = []
|
||||
commandPanel.historyIndex = 0
|
||||
@@ -28,11 +28,8 @@ describe "CommandPanel", ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
window.rootView = RootView.deserialize(rootViewState)
|
||||
rootView.attachToDom()
|
||||
window.loadPackage('command-panel')
|
||||
atom.deactivatePackage('command-panel')
|
||||
atom.activatePackage('command-panel')
|
||||
|
||||
expect(rootView.find('.command-panel')).not.toExist()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
@@ -55,13 +52,12 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.history[2]).toBe('/test3')
|
||||
expect(commandPanel.historyIndex).toBe(3)
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
RootView.deserialize(rootViewState).attachToDom()
|
||||
window.loadPackage('command-panel')
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
atom.deactivatePackage('command-panel')
|
||||
atom.activatePackage('command-panel')
|
||||
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel = rootView.find('.command-panel').view()
|
||||
|
||||
expect(commandPanel.history.length).toBe(2)
|
||||
expect(commandPanel.history[0]).toBe('/test2')
|
||||
expect(commandPanel.history[1]).toBe('/test3')
|
||||
@@ -216,39 +212,69 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.miniEditor.hiddenInput).not.toMatchSelector ':focus'
|
||||
|
||||
describe "when command-panel:repeat-relative-address is triggered on the root view", ->
|
||||
it "repeats the last search command if there is one", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
describe "when there is more than one match", ->
|
||||
it "repeats the last search command if there is one", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
|
||||
editSession.setCursorScreenPosition([4, 0])
|
||||
editSession.setCursorScreenPosition([4, 0])
|
||||
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
|
||||
commandPanel.execute('s/r/R/g')
|
||||
commandPanel.execute('s/r/R/g')
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,34], [6,41]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,34], [6,41]]
|
||||
|
||||
commandPanel.execute('0')
|
||||
commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated
|
||||
commandPanel.execute('0')
|
||||
commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[3,31], [3,38]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[3,31], [3,38]]
|
||||
|
||||
describe "when there is only one match and it is selected", ->
|
||||
it "maintains the current selection and plays a beep", ->
|
||||
editSession.setCursorScreenPosition([0, 0])
|
||||
waitsForPromise ->
|
||||
commandPanel.execute("/Array")
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
spyOn($native, 'beep')
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
waitsFor ->
|
||||
$native.beep.callCount > 0
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
|
||||
describe "when command-panel:repeat-relative-address-in-reverse is triggered on the root view", ->
|
||||
it "it repeats the last relative address in the reverse direction", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
describe "when there is more than one match", ->
|
||||
it "it repeats the last relative address in the reverse direction", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
|
||||
editSession.setCursorScreenPosition([6, 0])
|
||||
editSession.setCursorScreenPosition([6, 0])
|
||||
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
commandPanel.execute("/current")
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[6,6], [6,13]]
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5,6], [5,13]]
|
||||
|
||||
describe "when there is only one match and it is selected", ->
|
||||
it "maintains the current selection and plays a beep", ->
|
||||
editSession.setCursorScreenPosition([0, 0])
|
||||
waitsForPromise ->
|
||||
commandPanel.execute("/Array")
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
spyOn($native, 'beep')
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
waitsFor ->
|
||||
$native.beep.callCount > 0
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[11,14], [11,19]]
|
||||
|
||||
describe "when command-panel:set-selection-as-regex-address is triggered on the root view", ->
|
||||
it "sets the @lastRelativeAddress to a RegexAddress of the current selection", ->
|
||||
@@ -319,13 +345,15 @@ describe "CommandPanel", ->
|
||||
# there shouldn't be any dangling operations after this
|
||||
|
||||
describe "if the command is malformed", ->
|
||||
it "adds and removes an error class to the command panel and does not close it", ->
|
||||
it "adds and removes an error class to the command panel and does not close it or display a loading message", ->
|
||||
rootView.attachToDom()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel.miniEditor.insertText 'garbage-command!!'
|
||||
|
||||
commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter')
|
||||
expect(commandPanel.parent()).toExist()
|
||||
expect(commandPanel).toHaveClass 'error'
|
||||
expect(commandPanel.loadingMessage).toBeHidden()
|
||||
|
||||
advanceClock 400
|
||||
|
||||
|
||||
45
src/packages/command-panel/spec/preview-list-spec.coffee
Normal file
45
src/packages/command-panel/spec/preview-list-spec.coffee
Normal file
@@ -0,0 +1,45 @@
|
||||
RootView = require 'root-view'
|
||||
CommandPanelView = require 'command-panel/lib/command-panel-view'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "Preview List", ->
|
||||
[previewList, commandPanelMain, commandPanelView] = []
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView()
|
||||
rootView.attachToDom()
|
||||
commandPanelMain = atom.activatePackage('command-panel', immediate: true).mainModule
|
||||
commandPanelView = commandPanelMain.commandPanelView
|
||||
previewList = commandPanelView.previewList
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
describe "when the list is scrollable", ->
|
||||
it "adds more operations to the DOM when `scrollBottom` nears the `pixelOverdraw`", ->
|
||||
waitsForPromise ->
|
||||
commandPanelView.execute('X x/so/')
|
||||
|
||||
runs ->
|
||||
expect(previewList.prop('scrollHeight')).toBeGreaterThan previewList.height()
|
||||
previousScrollHeight = previewList.prop('scrollHeight')
|
||||
previousOperationCount = previewList.find("li").length
|
||||
|
||||
previewList.scrollTop(previewList.pixelOverdraw / 2)
|
||||
previewList.trigger('scroll') # Not sure why scroll event isn't being triggered on it's own
|
||||
expect(previewList.prop('scrollHeight')).toBe previousScrollHeight
|
||||
expect(previewList.find("li").length).toBe previousOperationCount
|
||||
|
||||
previewList.scrollToBottom()
|
||||
previewList.trigger('scroll') # Not sure why scroll event isn't being triggered on it's own
|
||||
expect(previewList.prop('scrollHeight')).toBeGreaterThan previousScrollHeight
|
||||
expect(previewList.find("li").length).toBeGreaterThan previousOperationCount
|
||||
|
||||
it "renders all operations if the preview items are collapsed", ->
|
||||
waitsForPromise ->
|
||||
commandPanelView.execute('X x/so/')
|
||||
|
||||
runs ->
|
||||
expect(previewList.prop('scrollHeight')).toBeGreaterThan previewList.height()
|
||||
previousScrollHeight = previewList.prop('scrollHeight')
|
||||
previousOperationCount = previewList.find("li").length
|
||||
previewList.collapseAllPaths()
|
||||
expect(previewList.find("li").length).toBeGreaterThan previousOperationCount
|
||||
132
src/packages/command-panel/stylesheets/command-panel.less
Normal file
132
src/packages/command-panel/stylesheets/command-panel.less
Normal file
@@ -0,0 +1,132 @@
|
||||
.command-panel {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
|
||||
.is-loading {
|
||||
display: block;
|
||||
margin: 0 auto 10px auto;
|
||||
width: 100px;
|
||||
background-color: #111111;
|
||||
background-size: auto;
|
||||
background-position: 5px 5px;
|
||||
padding: 5px 5px 10px 30px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
border-top: 1px solid rgba(0,0,0,1);
|
||||
border-left: 1px solid rgba(0,0,0,1);
|
||||
}
|
||||
|
||||
.preview-count {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.preview-list {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
margin: 0 0 10px 0;
|
||||
position: relative;
|
||||
cursor: default;
|
||||
|
||||
.path {
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.path-details:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 12px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 5px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
content: "\f05b";
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.is-collapsed .path-details:before {
|
||||
content: "\f05a";
|
||||
}
|
||||
|
||||
.path-name:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
content: "\f011";
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.path.readme .path-name:before {
|
||||
content: "\f007";
|
||||
}
|
||||
|
||||
.operation {
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.line-number {
|
||||
margin-right: 1ex;
|
||||
text-align: right;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.path-match-number {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
word-break: break-all;
|
||||
|
||||
.match {
|
||||
-webkit-border-radius: 2px;
|
||||
padding: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.expand-collapse {
|
||||
float: right;
|
||||
-webkit-user-select: none;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
margin-left: 5px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.prompt-and-editor {
|
||||
display: -webkit-flex;
|
||||
|
||||
.editor {
|
||||
position: relative;
|
||||
-webkit-flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-messages {
|
||||
padding: 5px 1em;
|
||||
color: white;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
ScrollView = require 'scroll-view'
|
||||
d3 = require 'd3.v3'
|
||||
d3 = require 'd3'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ describe "EditorStats", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
editorStats = window.loadPackage('editor-stats').mainModule.stats
|
||||
editorStats = atom.activatePackage('editor-stats').mainModule.stats
|
||||
|
||||
describe "when a keyup event is triggered", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.editor-stats {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
SelectList = require 'select-list'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
LoadPathsTask = require './load-paths-task'
|
||||
|
||||
module.exports =
|
||||
@@ -139,7 +139,7 @@ class FuzzyFinderView extends SelectList
|
||||
@setArray(paths)
|
||||
|
||||
populateProjectPaths: (options = {}) ->
|
||||
if @projectPaths?.length > 0
|
||||
if @projectPaths?
|
||||
listedItems =
|
||||
if options.filter?
|
||||
@projectPaths.filter (path) ->
|
||||
@@ -156,21 +156,15 @@ class FuzzyFinderView extends SelectList
|
||||
callback = (paths) =>
|
||||
@projectPaths = paths
|
||||
@reloadProjectPaths = false
|
||||
listedItems =
|
||||
if options.filter?
|
||||
@projectPaths.filter (path) ->
|
||||
path.indexOf(options.filter) >= 0
|
||||
else
|
||||
@projectPaths
|
||||
|
||||
@setArray(listedItems)
|
||||
options.done(listedItems) if options.done?
|
||||
@populateProjectPaths(options)
|
||||
@loadPathsTask = new LoadPathsTask(callback)
|
||||
@loadPathsTask.start()
|
||||
|
||||
populateOpenBufferPaths: ->
|
||||
editSessions = project.getEditSessions().filter (editSession)->
|
||||
editSessions = project.getEditSessions().filter (editSession) ->
|
||||
editSession.getPath()?
|
||||
editSessions = _.uniq editSessions, (editSession) ->
|
||||
editSession.getPath()
|
||||
|
||||
editSessions = _.sortBy editSessions, (editSession) =>
|
||||
if editSession is rootView.getActivePaneItem()
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
fs = require 'fs'
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
loadPaths: (rootPath, ignoredNames, excludeGitIgnoredPaths) ->
|
||||
if excludeGitIgnoredPaths
|
||||
Git = require 'git'
|
||||
repo = Git.open(rootPath, refreshOnWindowFocus: false)
|
||||
|
||||
paths = []
|
||||
isIgnored = (path) ->
|
||||
path = path.substring(rootPath.length + 1)
|
||||
for segment in path.split('/')
|
||||
return true if _.contains(ignoredNames, segment)
|
||||
repo?.isPathIgnored(fs.join(rootPath, path))
|
||||
onFile = (path) ->
|
||||
paths.push(path) unless isIgnored(path)
|
||||
onDirectory = (path) ->
|
||||
not isIgnored(path)
|
||||
fs.traverseTree(rootPath, onFile, onDirectory)
|
||||
|
||||
repo?.destroy()
|
||||
|
||||
callTaskMethod('pathsLoaded', paths)
|
||||
@@ -1,17 +1,33 @@
|
||||
Task = require 'task'
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
class LoadPathsTask extends Task
|
||||
constructor: (@callback) ->
|
||||
super('fuzzy-finder/lib/load-paths-handler')
|
||||
class LoadPathsTask
|
||||
aborted: false
|
||||
|
||||
started: ->
|
||||
constructor: (@callback) ->
|
||||
|
||||
start: ->
|
||||
rootPath = project.getPath()
|
||||
ignoredNames = config.get('fuzzyFinder.ignoredNames') ? []
|
||||
ignoredNames = ignoredNames.concat(config.get('core.ignoredNames') ? [])
|
||||
excludeGitIgnoredPaths = config.get('core.hideGitIgnoredFiles')
|
||||
rootPath = project.getPath()
|
||||
@callWorkerMethod('loadPaths', rootPath, ignoredNames, excludeGitIgnoredPaths)
|
||||
ignoreGitIgnoredFiles = config.get('core.hideGitIgnoredFiles')
|
||||
|
||||
pathsLoaded: (paths) ->
|
||||
@done()
|
||||
@callback(paths)
|
||||
paths = []
|
||||
isIgnored = (path) ->
|
||||
for segment in path.split('/')
|
||||
return true if _.contains(ignoredNames, segment)
|
||||
ignoreGitIgnoredFiles and git?.isPathIgnored(fs.join(rootPath, path))
|
||||
onFile = (path) ->
|
||||
return if @aborted
|
||||
path = path.substring(rootPath.length + 1)
|
||||
paths.push(path) unless isIgnored(path)
|
||||
onDirectory = (path) =>
|
||||
not @aborted and not isIgnored(path.substring(rootPath.length + 1))
|
||||
onDone = =>
|
||||
@callback(paths) unless @aborted
|
||||
|
||||
fs.traverseTree(rootPath, onFile, onDirectory, onDone)
|
||||
|
||||
abort: ->
|
||||
@aborted = true
|
||||
|
||||
@@ -4,7 +4,7 @@ LoadPathsTask = require 'fuzzy-finder/lib/load-paths-task'
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
{$$} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
describe 'FuzzyFinder', ->
|
||||
[finderView] = []
|
||||
@@ -13,7 +13,7 @@ describe 'FuzzyFinder', ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
rootView.enableKeymap()
|
||||
finderView = window.loadPackage("fuzzy-finder").mainModule.createView()
|
||||
finderView = atom.activatePackage("fuzzy-finder").mainModule.createView()
|
||||
|
||||
describe "file-finder behavior", ->
|
||||
describe "toggling", ->
|
||||
@@ -43,13 +43,14 @@ describe 'FuzzyFinder', ->
|
||||
it "shows all relative file paths for the current project and selects the first", ->
|
||||
rootView.attachToDom()
|
||||
finderView.maxItems = Infinity
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
paths = null
|
||||
expect(finderView.find(".loading")).toBeVisible()
|
||||
expect(finderView.find(".loading")).toHaveText "Indexing..."
|
||||
|
||||
waitsFor "all project paths to load", 5000, ->
|
||||
if finderView.projectPaths?.length > 0
|
||||
unless finderView.reloadProjectPaths
|
||||
paths = finderView.projectPaths
|
||||
true
|
||||
|
||||
@@ -142,8 +143,8 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
rootView.open()
|
||||
|
||||
states = rootView.serialize().packages
|
||||
states = _.map states['fuzzy-finder'], (path, time) -> [ path, time ]
|
||||
atom.deactivatePackage('fuzzy-finder')
|
||||
states = _.map atom.getPackageState('fuzzy-finder'), (path, time) -> [ path, time ]
|
||||
states = _.sortBy states, (path, time) -> -time
|
||||
|
||||
paths = [ 'sample-with-tabs.coffee', 'sample.txt', 'sample.js' ]
|
||||
@@ -165,6 +166,13 @@ describe 'FuzzyFinder', ->
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
|
||||
describe "when multiple sessions are opened on the same path", ->
|
||||
it "does not display duplicates for that path in the list", ->
|
||||
rootView.open 'sample.js'
|
||||
rootView.getActivePane().splitRight()
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(_.pluck(finderView.list.children('li'), 'outerText')).toEqual ['sample.js']
|
||||
|
||||
describe "when a path selection is confirmed", ->
|
||||
[editor1, editor2] = []
|
||||
|
||||
@@ -271,6 +279,7 @@ describe 'FuzzyFinder', ->
|
||||
describe "cached file paths", ->
|
||||
it "caches file paths after first time", ->
|
||||
spyOn(LoadPathsTask.prototype, "start").andCallThrough()
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
|
||||
waitsFor ->
|
||||
@@ -290,6 +299,7 @@ describe 'FuzzyFinder', ->
|
||||
|
||||
it "doesn't cache buffer paths", ->
|
||||
spyOn(project, "getEditSessions").andCallThrough()
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
|
||||
waitsFor ->
|
||||
@@ -309,6 +319,7 @@ describe 'FuzzyFinder', ->
|
||||
|
||||
it "busts the cache when the window gains focus", ->
|
||||
spyOn(LoadPathsTask.prototype, "start").andCallThrough()
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
|
||||
waitsFor ->
|
||||
@@ -325,6 +336,7 @@ describe 'FuzzyFinder', ->
|
||||
describe "path ignoring", ->
|
||||
it "ignores paths that match entries in config.fuzzyFinder.ignoredNames", ->
|
||||
config.set("fuzzyFinder.ignoredNames", ["tree-view.js"])
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
finderView.maxItems = Infinity
|
||||
|
||||
@@ -343,6 +355,7 @@ describe 'FuzzyFinder', ->
|
||||
|
||||
it "opens the fuzzy finder window when there are multiple matches", ->
|
||||
editor.setText("sample")
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:find-under-cursor'
|
||||
|
||||
waitsFor ->
|
||||
@@ -354,6 +367,7 @@ describe 'FuzzyFinder', ->
|
||||
|
||||
it "opens a file directly when there is a single match", ->
|
||||
editor.setText("sample.txt")
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:find-under-cursor'
|
||||
|
||||
openedPath = null
|
||||
@@ -367,10 +381,11 @@ describe 'FuzzyFinder', ->
|
||||
expect(finderView).not.toBeVisible()
|
||||
expect(openedPath).toBe "sample.txt"
|
||||
|
||||
it "displays error when the word under the cursor doesn't match any files", ->
|
||||
it "displays an error when the word under the cursor doesn't match any files", ->
|
||||
editor.setText("moogoogaipan")
|
||||
editor.setCursorBufferPosition([0,5])
|
||||
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
rootView.trigger 'fuzzy-finder:find-under-cursor'
|
||||
|
||||
waitsFor ->
|
||||
|
||||
64
src/packages/fuzzy-finder/stylesheets/fuzzy-finder.less
Normal file
64
src/packages/fuzzy-finder/stylesheets/fuzzy-finder.less
Normal file
@@ -0,0 +1,64 @@
|
||||
.fuzzy-finder .directory {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
word-break: break-word;
|
||||
margin-left: 5px;
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
.fuzzy-finder .file:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #9d9d9d;
|
||||
}
|
||||
|
||||
.fuzzy-finder .status {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #9d9d9d;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fuzzy-finder .status.new:before {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
content: "\f06b";
|
||||
}
|
||||
|
||||
.fuzzy-finder .status.modified:before {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
content: "\f06d";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.text-name:before {
|
||||
content: "\f011";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.image-name:before {
|
||||
content: "\f012";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.compressed-name:before {
|
||||
content: "\f013";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.pdf-name:before {
|
||||
content: "\f014";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.readme-name:before {
|
||||
content: "\f007";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.binary-name:before {
|
||||
content: "\f094";
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
'name': 'Indent'
|
||||
'scope': 'source.gfm'
|
||||
'settings':
|
||||
'increaseIndentPattern': '^\\s*([\\*\\+-])[ \\t]+'
|
||||
@@ -1,4 +0,0 @@
|
||||
'name': 'bold text'
|
||||
'scope': 'source.gfm'
|
||||
'tabTrigger': 'b'
|
||||
'content': '**$1**$0'
|
||||
@@ -1,4 +0,0 @@
|
||||
'name': 'code block'
|
||||
'scope': 'source.gfm'
|
||||
'tabTrigger': 'code'
|
||||
'content': '```$1\n$2\n```$0'
|
||||
@@ -1,4 +0,0 @@
|
||||
'name': 'embedded image'
|
||||
'scope': 'source.gfm'
|
||||
'tabTrigger': 'img'
|
||||
'content': '$0'
|
||||
@@ -1,4 +0,0 @@
|
||||
'name': 'italic text'
|
||||
'scope': 'source.gfm'
|
||||
'tabTrigger': 'i'
|
||||
'content': '*$1*$0'
|
||||
@@ -1,4 +0,0 @@
|
||||
'name': 'link'
|
||||
'scope': 'source.gfm'
|
||||
'tabTrigger': 'l'
|
||||
'content': '[$1]($2)$0'
|
||||
@@ -7,6 +7,7 @@
|
||||
'mkdown'
|
||||
'ron'
|
||||
]
|
||||
|
||||
'patterns': [
|
||||
{
|
||||
'match': '(?:^|\\s)(\\*\\*[^\\*]+\\*\\*)'
|
||||
3
src/packages/gfm/scoped-properties/gfm.cson
Normal file
3
src/packages/gfm/scoped-properties/gfm.cson
Normal file
@@ -0,0 +1,3 @@
|
||||
'.source.gfm':
|
||||
'editor':
|
||||
'increaseIndentPattern': '^\\s*([\\*\\+-])[ \\t]+'
|
||||
16
src/packages/gfm/snippets/gfm.cson
Normal file
16
src/packages/gfm/snippets/gfm.cson
Normal file
@@ -0,0 +1,16 @@
|
||||
'.source.gfm':
|
||||
'bold text':
|
||||
prefix: 'b'
|
||||
body: '**$1**$0'
|
||||
'embedded image':
|
||||
prefix: 'img'
|
||||
body: '$0'
|
||||
'italic text':
|
||||
prefix: 'i'
|
||||
body: '*$1*$0'
|
||||
'link':
|
||||
prefix: 'l'
|
||||
body: '[$1]($2)$0'
|
||||
'code':
|
||||
prefix: 'code'
|
||||
body: '```$1\n$2\n```$0'
|
||||
@@ -4,13 +4,13 @@ describe "GitHub Flavored Markdown grammar", ->
|
||||
grammar = null
|
||||
|
||||
beforeEach ->
|
||||
spyOn(syntax, "addGrammar")
|
||||
pack = new TextMatePackage(require.resolve("gfm.tmbundle"))
|
||||
pack.load()
|
||||
grammar = pack.grammars[0]
|
||||
spyOn(syntax, "addGrammar").andCallThrough()
|
||||
atom.activatePackage("gfm")
|
||||
expect(syntax.addGrammar).toHaveBeenCalled()
|
||||
grammar = syntax.addGrammar.argsForCall[0][0]
|
||||
|
||||
it "parses the grammar", ->
|
||||
expect(grammar).toBeTruthy()
|
||||
expect(grammar).toBeDefined()
|
||||
expect(grammar.scopeName).toBe "source.gfm"
|
||||
|
||||
it "tokenizes horizontal rules", ->
|
||||
@@ -8,7 +8,7 @@ class Gists
|
||||
constructor: ->
|
||||
rootView.command 'gist:create', '.editor', => @createGist()
|
||||
|
||||
createGist: (editor) ->
|
||||
createGist: ->
|
||||
editor = rootView.getActiveView()
|
||||
return unless editor?
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "Gists package", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage('gists')
|
||||
atom.activatePackage('gists')
|
||||
editor = rootView.getActiveView()
|
||||
spyOn($, 'ajax')
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
'.editor':
|
||||
'meta-L': 'grammar-selector:show'
|
||||
|
||||
64
src/packages/grammar-selector/lib/grammar-selector.coffee
Normal file
64
src/packages/grammar-selector/lib/grammar-selector.coffee
Normal file
@@ -0,0 +1,64 @@
|
||||
SelectList = require 'select-list'
|
||||
Editor = require 'editor'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
module.exports =
|
||||
class GrammarSelector extends SelectList
|
||||
@viewClass: -> "#{super} grammar-selector from-top overlay mini"
|
||||
|
||||
@activate: ->
|
||||
rootView.command 'grammar-selector:show', '.editor', => new GrammarSelector()
|
||||
|
||||
filterKey: 'name'
|
||||
|
||||
initialize: ->
|
||||
@editor = rootView.getActiveView()
|
||||
return unless @editor instanceof Editor
|
||||
@currentGrammar = @editor.getGrammar()
|
||||
@path = @editor.getPath()
|
||||
@autoDetect = name: 'Auto Detect'
|
||||
@command 'grammar-selector:show', =>
|
||||
@cancel()
|
||||
false
|
||||
super
|
||||
|
||||
@populate()
|
||||
@attach()
|
||||
|
||||
itemForElement: (grammar) ->
|
||||
if grammar is @currentGrammar
|
||||
grammarClass = 'active-item'
|
||||
else
|
||||
grammarClass = 'inactive-item'
|
||||
|
||||
$$ ->
|
||||
@li grammar.name, class: grammarClass
|
||||
|
||||
populate: ->
|
||||
grammars = new Array(syntax.grammars...)
|
||||
grammars.sort (grammarA, grammarB) ->
|
||||
if grammarA.scopeName is 'text.plain'
|
||||
-1
|
||||
else if grammarB.scopeName is 'text.plain'
|
||||
1
|
||||
else if grammarA.name < grammarB.name
|
||||
-1
|
||||
else if grammarA.name > grammarB.name
|
||||
1
|
||||
else
|
||||
0
|
||||
grammars.unshift(@autoDetect)
|
||||
@setArray(grammars)
|
||||
|
||||
confirmed: (grammar) ->
|
||||
@cancel()
|
||||
if grammar is @autoDetect
|
||||
syntax.clearGrammarOverrideForPath(@path)
|
||||
else
|
||||
syntax.setGrammarOverrideForPath(@path, grammar.scopeName)
|
||||
@editor.reloadGrammar()
|
||||
|
||||
attach: ->
|
||||
super
|
||||
rootView.append(this)
|
||||
@miniEditor.focus()
|
||||
2
src/packages/grammar-selector/package.cson
Normal file
2
src/packages/grammar-selector/package.cson
Normal file
@@ -0,0 +1,2 @@
|
||||
'main': 'lib/grammar-selector'
|
||||
'activationEvents': ['grammar-selector:show']
|
||||
@@ -0,0 +1,47 @@
|
||||
GrammarSelector = require '../lib/grammar-selector'
|
||||
RootView = require 'root-view'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "GrammarSelector", ->
|
||||
[editor, textGrammar, jsGrammar] = []
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
atom.activatePackage('grammar-selector')
|
||||
atom.activatePackage('text.tmbundle', sync: true)
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
rootView.open('sample.js')
|
||||
editor = rootView.getActiveView()
|
||||
textGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'Plain Text'
|
||||
expect(textGrammar).toBeTruthy()
|
||||
jsGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'JavaScript'
|
||||
expect(jsGrammar).toBeTruthy()
|
||||
expect(editor.getGrammar()).toBe jsGrammar
|
||||
|
||||
describe "when grammar-selector:show is triggered", ->
|
||||
it "displays a list of all the available grammars", ->
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
expect(grammarView).toExist()
|
||||
grammars = syntax.grammars
|
||||
expect(grammarView.list.children('li').length).toBe grammars.length + 1
|
||||
expect(grammarView.list.children('li:first').text()).toBe 'Auto Detect'
|
||||
|
||||
describe "when a grammar is selected", ->
|
||||
it "sets the new grammar on the editor", ->
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
grammarView.confirmed(textGrammar)
|
||||
expect(editor.getGrammar()).toBe textGrammar
|
||||
|
||||
describe "when auto-detect is selected", ->
|
||||
it "restores the auto-detected grammar on the editor", ->
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
grammarView.confirmed(textGrammar)
|
||||
expect(editor.getGrammar()).toBe textGrammar
|
||||
|
||||
editor.trigger 'grammar-selector:show'
|
||||
grammarView = rootView.find('.grammar-selector').view()
|
||||
grammarView.confirmed(grammarView.array[0])
|
||||
expect(editor.getGrammar()).toBe jsGrammar
|
||||
@@ -1,4 +1,4 @@
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
$ = require 'jquery'
|
||||
ScrollView = require 'scroll-view'
|
||||
{$$$} = require 'space-pen'
|
||||
@@ -29,6 +29,9 @@ class MarkdownPreviewView extends ScrollView
|
||||
getUri: ->
|
||||
"markdown-preview:#{@buffer.getPath()}"
|
||||
|
||||
getPath: ->
|
||||
@buffer.getPath()
|
||||
|
||||
setErrorHtml: ->
|
||||
@html $$$ ->
|
||||
@h2 'Previewing Markdown Failed'
|
||||
|
||||
@@ -22,4 +22,4 @@ module.exports =
|
||||
nextPane.showItem(new MarkdownPreviewView(editSession.buffer))
|
||||
else
|
||||
activePane.splitRight(new MarkdownPreviewView(editSession.buffer))
|
||||
activePane.focus()
|
||||
activePane.focus()
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "MarkdownPreview package", ->
|
||||
beforeEach ->
|
||||
project.setPath(project.resolve('markdown'))
|
||||
window.rootView = new RootView
|
||||
window.loadPackage("markdown-preview", activateImmediately: true)
|
||||
atom.activatePackage("markdown-preview", immediate: true)
|
||||
spyOn(MarkdownPreviewView.prototype, 'fetchRenderedMarkdown')
|
||||
|
||||
describe "markdown-preview:show", ->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Editor = require 'editor'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
class PackageGeneratorView extends View
|
||||
@@ -56,7 +56,7 @@ class PackageGeneratorView extends View
|
||||
true
|
||||
|
||||
createPackageFiles: ->
|
||||
templatePath = require.resolve(fs.join("package-generator", "template"))
|
||||
templatePath = fs.resolveOnLoadPath(fs.join("package-generator", "template"))
|
||||
packageName = fs.base(@getPackagePath())
|
||||
|
||||
for path in fs.listTree(templatePath)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
RootView = require 'root-view'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
describe 'Package Generator', ->
|
||||
[packageGenerator] = []
|
||||
@@ -7,7 +7,7 @@ describe 'Package Generator', ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage("package-generator")
|
||||
atom.activatePackage("package-generator")
|
||||
|
||||
describe "when package-generator:generate is triggered", ->
|
||||
it "displays a miniEditor", ->
|
||||
|
||||
@@ -10,7 +10,7 @@ fdescribe "__PackageName__View", ->
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
__packageName__ = window.loadPackage('__packageName__', activateImmediately: true)
|
||||
__packageName__ = atom.activatePackage('__packageName__', immediate: true)
|
||||
|
||||
describe "when the __package-name__:toggle event is triggered", ->
|
||||
it "attaches and then detaches the view", ->
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
fs = require 'fs'
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
SnippetBodyParser = require './snippet-body-parser'
|
||||
|
||||
module.exports =
|
||||
snippetsLoaded: (snippets) ->
|
||||
for snippet in snippets
|
||||
for selector, snippetsByName of snippet
|
||||
for name, attributes of snippetsByName
|
||||
attributes.bodyTree = SnippetBodyParser.parse(attributes.body)
|
||||
callTaskMethod('snippetsLoaded', snippets)
|
||||
|
||||
loadTextMateSnippets: (path) ->
|
||||
snippetsDirPath = fs.join(path, 'Snippets')
|
||||
snippets = []
|
||||
|
||||
for snippetsPath in fs.list(snippetsDirPath)
|
||||
logWarning = ->
|
||||
console.warn "Error reading TextMate snippets file '#{snippetsPath}'"
|
||||
|
||||
continue if fs.base(snippetsPath).indexOf('.') is 0
|
||||
try
|
||||
if fs.isObjectPath(snippetsPath) and object = fs.readObject(snippetsPath)
|
||||
snippets.push(object)
|
||||
else if object = fs.readPlist(snippetsPath)
|
||||
snippets.push(object)
|
||||
else
|
||||
logWarning()
|
||||
catch e
|
||||
logWarning()
|
||||
|
||||
@snippetsLoaded(@translateTextmateSnippets(snippets))
|
||||
|
||||
loadAtomSnippets: (path) ->
|
||||
snippetsDirPath = fs.join(path, 'snippets')
|
||||
snippets = []
|
||||
for snippetsPath in fs.list(snippetsDirPath)
|
||||
continue if fs.base(snippetsPath).indexOf('.') is 0
|
||||
try
|
||||
snippets.push(fs.readObject(snippetsPath))
|
||||
catch e
|
||||
console.warn "Error reading snippets file '#{snippetsPath}'"
|
||||
@snippetsLoaded(snippets)
|
||||
|
||||
translateTextmateSnippets: (tmSnippets) ->
|
||||
atomSnippets = {}
|
||||
for { scope, name, content, tabTrigger } in tmSnippets
|
||||
if scope
|
||||
scope = TextMatePackage.cssSelectorFromScopeSelector(scope)
|
||||
else
|
||||
scope = '*'
|
||||
|
||||
snippetsForScope = (atomSnippets[scope] ?= {})
|
||||
snippetsForScope[name] = { prefix: tabTrigger, body: content }
|
||||
[atomSnippets]
|
||||
@@ -1,34 +0,0 @@
|
||||
Task = require 'task'
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
|
||||
module.exports =
|
||||
class LoadSnippetsTask extends Task
|
||||
constructor: (@snippets) ->
|
||||
super('snippets/lib/load-snippets-handler')
|
||||
@packages = atom.getLoadedPackages()
|
||||
@packages.push(path: config.configDirPath)
|
||||
|
||||
started: ->
|
||||
@loadNextPackageSnippets()
|
||||
|
||||
loadNextPackageSnippets: ->
|
||||
unless @packages.length
|
||||
@done()
|
||||
@snippets.loaded = true
|
||||
return
|
||||
|
||||
@packageBeingLoaded = @packages.shift()
|
||||
if @packageBeingLoaded instanceof TextMatePackage
|
||||
@loadTextMateSnippets(@packageBeingLoaded.path)
|
||||
else
|
||||
@loadAtomSnippets(@packageBeingLoaded.path)
|
||||
|
||||
loadAtomSnippets: (path) ->
|
||||
@callWorkerMethod('loadAtomSnippets', path)
|
||||
|
||||
loadTextMateSnippets: (path) ->
|
||||
@callWorkerMethod('loadTextMateSnippets', path)
|
||||
|
||||
snippetsLoaded: (snippets) ->
|
||||
@snippets.add(snippet) for snippet in snippets
|
||||
@loadNextPackageSnippets()
|
||||
@@ -1,4 +1,4 @@
|
||||
PEG = require 'pegjs'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
grammarSrc = fs.read(require.resolve('./snippet-body.pegjs'))
|
||||
module.exports = PEG.buildParser(grammarSrc, trackLineAndColumn: true)
|
||||
|
||||
@@ -27,7 +27,7 @@ class SnippetExpansion
|
||||
return if @settingTabStop or bufferChanged
|
||||
oldTabStops = @tabStopsForBufferPosition(oldBufferPosition)
|
||||
newTabStops = @tabStopsForBufferPosition(newBufferPosition)
|
||||
@destroy() unless _.intersect(oldTabStops, newTabStops).length
|
||||
@destroy() unless _.intersection(oldTabStops, newTabStops).length
|
||||
|
||||
placeTabStopMarkers: (startPosition, tabStopRanges) ->
|
||||
@tabStopMarkers = tabStopRanges.map ({start, end}) =>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
fs = require 'fs'
|
||||
fsUtils = require 'fs-utils'
|
||||
_ = require 'underscore'
|
||||
SnippetExpansion = require './snippet-expansion'
|
||||
Snippet = require './snippet'
|
||||
LoadSnippetsTask = require './load-snippets-task'
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
CSON = require 'cson'
|
||||
async = require 'async'
|
||||
|
||||
module.exports =
|
||||
snippetsByExtension: {}
|
||||
@@ -16,22 +19,85 @@ module.exports =
|
||||
@enableSnippetsInEditor(editor) if editor.attached
|
||||
|
||||
deactivate: ->
|
||||
@loadSnippetsTask?.abort()
|
||||
|
||||
loadAll: ->
|
||||
@loadSnippetsTask = new LoadSnippetsTask(this)
|
||||
@loadSnippetsTask.start()
|
||||
packages = atom.getLoadedPackages()
|
||||
packages.push(path: config.configDirPath)
|
||||
async.eachSeries packages, @loadSnippetsFromPackage.bind(this), @doneLoading.bind(this)
|
||||
|
||||
loadDirectory: (snippetsDirPath) ->
|
||||
for snippetsPath in fs.list(snippetsDirPath) when fs.base(snippetsPath).indexOf('.') isnt 0
|
||||
snippets.loadFile(snippetsPath)
|
||||
doneLoading: ->
|
||||
@loaded = true
|
||||
|
||||
loadFile: (snippetsPath) ->
|
||||
try
|
||||
snippets = fs.readObject(snippetsPath)
|
||||
catch e
|
||||
console.warn "Error reading snippets file '#{snippetsPath}'"
|
||||
@add(snippets)
|
||||
loadSnippetsFromPackage: (pack, done) ->
|
||||
if pack instanceof TextMatePackage
|
||||
@loadTextMateSnippets(pack.path, done)
|
||||
else
|
||||
@loadAtomSnippets(pack.path, done)
|
||||
|
||||
loadAtomSnippets: (path, done) ->
|
||||
snippetsDirPath = fsUtils.join(path, 'snippets')
|
||||
return done() unless fsUtils.isDirectory(snippetsDirPath)
|
||||
|
||||
loadSnippetFile = (filename, done) =>
|
||||
return done() if filename.indexOf('.') is 0
|
||||
filepath = fsUtils.join(snippetsDirPath, filename)
|
||||
CSON.readObjectAsync filepath, (err, object) =>
|
||||
if err
|
||||
console.warn "Error reading snippets file '#{filepath}': #{err.stack}"
|
||||
else
|
||||
@add(object)
|
||||
done()
|
||||
|
||||
fs.readdir snippetsDirPath, (err, paths) ->
|
||||
async.eachSeries(paths, loadSnippetFile, done)
|
||||
|
||||
loadTextMateSnippets: (path, done) ->
|
||||
snippetsDirPath = fsUtils.join(path, 'Snippets')
|
||||
return done() unless fsUtils.isDirectory(snippetsDirPath)
|
||||
|
||||
loadSnippetFile = (filename, done) =>
|
||||
return done() if filename.indexOf('.') is 0
|
||||
|
||||
filepath = fsUtils.join(snippetsDirPath, filename)
|
||||
|
||||
logError = (err) ->
|
||||
console.warn "Error reading snippets file '#{filepath}': #{err.stack ? err}"
|
||||
|
||||
try
|
||||
readObject =
|
||||
if CSON.isObjectPath(filepath)
|
||||
CSON.readObjectAsync.bind(CSON)
|
||||
else
|
||||
fsUtils.readPlistAsync.bind(fsUtils)
|
||||
|
||||
readObject filepath, (err, object) =>
|
||||
try
|
||||
if err
|
||||
logError(err)
|
||||
else
|
||||
@add(@translateTextmateSnippet(object))
|
||||
catch err
|
||||
logError(err)
|
||||
finally
|
||||
done()
|
||||
catch err
|
||||
logError(err)
|
||||
done()
|
||||
|
||||
fs.readdir snippetsDirPath, (err, paths) ->
|
||||
if err
|
||||
console.warn err
|
||||
return done()
|
||||
async.eachSeries(paths, loadSnippetFile, done)
|
||||
|
||||
translateTextmateSnippet: ({ scope, name, content, tabTrigger }) ->
|
||||
scope = syntax.cssSelectorFromScopeSelector(scope) if scope
|
||||
scope ?= '*'
|
||||
snippetsByScope = {}
|
||||
snippetsByName = {}
|
||||
snippetsByScope[scope] = snippetsByName
|
||||
snippetsByName[name] = { prefix: tabTrigger, body: content }
|
||||
snippetsByScope
|
||||
|
||||
add: (snippetsBySelector) ->
|
||||
for selector, snippetsByName of snippetsBySelector
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
Snippet = require 'snippets/lib/snippet'
|
||||
LoadSnippetsTask = require 'snippets/lib/load-snippets-task'
|
||||
RootView = require 'root-view'
|
||||
Buffer = require 'buffer'
|
||||
Buffer = require 'text-buffer'
|
||||
Editor = require 'editor'
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
Package = require 'package'
|
||||
|
||||
describe "Snippets extension", ->
|
||||
[buffer, editor, editSession] = []
|
||||
beforeEach ->
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
spyOn(LoadSnippetsTask.prototype, 'start')
|
||||
|
||||
packageWithSnippets = window.loadPackage("package-with-snippets")
|
||||
packageWithSnippets = atom.loadPackage("package-with-snippets")
|
||||
|
||||
spyOn(atom, "getLoadedPackages").andCallFake ->
|
||||
window.textMatePackages.concat([packageWithSnippets])
|
||||
|
||||
window.loadPackage("snippets")
|
||||
spyOn(require("snippets/lib/snippets"), 'loadAll')
|
||||
atom.activatePackage("snippets")
|
||||
|
||||
editor = rootView.getActiveView()
|
||||
editSession = rootView.getActivePaneItem()
|
||||
@@ -239,12 +236,16 @@ describe "Snippets extension", ->
|
||||
|
||||
describe "snippet loading", ->
|
||||
beforeEach ->
|
||||
jasmine.unspy(LoadSnippetsTask.prototype, 'start')
|
||||
spyOn(LoadSnippetsTask.prototype, 'loadAtomSnippets').andCallFake -> @snippetsLoaded({})
|
||||
spyOn(LoadSnippetsTask.prototype, 'loadTextMateSnippets').andCallFake -> @snippetsLoaded({})
|
||||
atom.loadPackage('package-with-broken-snippets.tmbundle', sync: true)
|
||||
atom.loadPackage('package-with-snippets')
|
||||
|
||||
jasmine.unspy(window, "setTimeout")
|
||||
jasmine.unspy(snippets, 'loadAll')
|
||||
spyOn(snippets, 'loadAtomSnippets').andCallFake (path, done) -> done()
|
||||
spyOn(snippets, 'loadTextMateSnippets').andCallFake (path, done) -> done()
|
||||
|
||||
it "loads non-hidden snippet files from all atom packages with snippets directories, logging a warning if a file can't be parsed", ->
|
||||
jasmine.unspy(LoadSnippetsTask.prototype, 'loadAtomSnippets')
|
||||
jasmine.unspy(snippets, 'loadAtomSnippets')
|
||||
spyOn(console, 'warn')
|
||||
snippets.loaded = false
|
||||
snippets.loadAll()
|
||||
@@ -259,7 +260,7 @@ describe "Snippets extension", ->
|
||||
expect(console.warn.calls.length).toBe 1
|
||||
|
||||
it "loads snippets from all TextMate packages with snippets", ->
|
||||
jasmine.unspy(LoadSnippetsTask.prototype, 'loadTextMateSnippets')
|
||||
jasmine.unspy(snippets, 'loadTextMateSnippets')
|
||||
spyOn(console, 'warn')
|
||||
snippets.loaded = false
|
||||
snippets.loadAll()
|
||||
@@ -281,37 +282,6 @@ describe "Snippets extension", ->
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
expect(console.warn.calls.length).toBe 1
|
||||
|
||||
it "terminates the worker when loading completes", ->
|
||||
jasmine.unspy(LoadSnippetsTask.prototype, 'loadAtomSnippets')
|
||||
spyOn(console, "warn")
|
||||
spyOn(Worker.prototype, 'terminate').andCallThrough()
|
||||
snippets.loaded = false
|
||||
snippets.loadAll()
|
||||
|
||||
waitsFor "all snippets to load", 5000, -> snippets.loaded
|
||||
|
||||
runs ->
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
expect(console.warn.argsForCall[0]).toMatch /Error reading snippets file '.*?\/spec\/fixtures\/packages\/package-with-snippets\/snippets\/junk-file'/
|
||||
expect(Worker.prototype.terminate).toHaveBeenCalled()
|
||||
expect(Worker.prototype.terminate.calls.length).toBe 1
|
||||
|
||||
it "loads CSON snippets from TextMate packages", ->
|
||||
jasmine.unspy(LoadSnippetsTask.prototype, 'loadTextMateSnippets')
|
||||
snippets.loaded = false
|
||||
task = new LoadSnippetsTask(snippets)
|
||||
task.packages = [Package.build(project.resolve('packages/package-with-a-cson-grammar.tmbundle'))]
|
||||
task.start()
|
||||
|
||||
waitsFor "CSON snippets to load", 5000, -> snippets.loaded
|
||||
|
||||
runs ->
|
||||
snippet = syntax.getProperty(['.source.alot'], 'snippets.really')
|
||||
expect(snippet).toBeTruthy()
|
||||
expect(snippet.prefix).toBe 'really'
|
||||
expect(snippet.name).toBe 'Really'
|
||||
expect(snippet.body).toBe "I really like alot"
|
||||
|
||||
describe "snippet body parser", ->
|
||||
it "breaks a snippet body into lines, with each line containing tab stops at the appropriate position", ->
|
||||
bodyTree = snippets.getBodyParser().parse """
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{View} = require 'space-pen'
|
||||
Range = require 'range'
|
||||
CorrectionsView = require './corrections-view'
|
||||
SpellChecker = require 'spellchecker'
|
||||
|
||||
module.exports =
|
||||
class MisspellingView extends View
|
||||
@@ -30,7 +31,7 @@ class MisspellingView extends View
|
||||
|
||||
screenRange = @getScreenRange()
|
||||
misspelling = @editor.getTextInRange(@editor.bufferRangeForScreenRange(screenRange))
|
||||
corrections = $native.getCorrectionsForMisspelling(misspelling)
|
||||
corrections = SpellChecker.getCorrectionsForMisspelling(misspelling)
|
||||
@correctionsView?.remove()
|
||||
@correctionsView = new CorrectionsView(@editor, corrections, screenRange)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
SpellChecker = require 'spellchecker'
|
||||
|
||||
module.exports =
|
||||
findMisspellings: (text) ->
|
||||
wordRegex = /(?:^|[\s\[\]])([a-zA-Z']+)(?=[\s\.\[\]]|$)/g
|
||||
@@ -6,7 +8,7 @@ module.exports =
|
||||
for line in text.split('\n')
|
||||
while matches = wordRegex.exec(line)
|
||||
word = matches[1]
|
||||
continue unless $native.isMisspelled(word)
|
||||
continue unless SpellChecker.isMisspelled(word)
|
||||
startColumn = matches.index + matches[0].length - word.length
|
||||
endColumn = startColumn + word.length
|
||||
misspellings.push([[row, startColumn], [row, endColumn]])
|
||||
|
||||
@@ -9,10 +9,10 @@ module.exports =
|
||||
]
|
||||
|
||||
activate: ->
|
||||
if syntax.grammars.length > 1
|
||||
@subscribeToEditors()
|
||||
else
|
||||
syntax.on 'grammars-loaded', => @subscribeToEditors()
|
||||
syntax.on 'grammars-loaded.spell-check', => @subscribeToEditors()
|
||||
|
||||
deactivate: ->
|
||||
syntax.off '.spell-check'
|
||||
|
||||
subscribeToEditors: ->
|
||||
rootView.eachEditor (editor) ->
|
||||
|
||||
@@ -4,10 +4,13 @@ describe "Spell check", ->
|
||||
[editor] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.activatePackage('text.tmbundle', sync: true)
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
config.set('spell-check.grammars', [])
|
||||
window.loadPackage('spell-check', activateImmediately: true)
|
||||
atom.activatePackage('spell-check', immediate: true)
|
||||
syntax.trigger 'grammars-loaded'
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ class StatusBarView extends View
|
||||
@appendToEditorPane(rootView, editor) if editor.attached
|
||||
|
||||
@appendToEditorPane: (rootView, editor) ->
|
||||
if pane = editor.pane()
|
||||
if pane = editor.getPane()
|
||||
pane.append(new StatusBarView(rootView, editor))
|
||||
|
||||
@content: ->
|
||||
@@ -34,7 +34,7 @@ class StatusBarView extends View
|
||||
|
||||
@updateCursorPositionText()
|
||||
@subscribe @editor, 'cursor:moved', => @updateCursorPositionText()
|
||||
@subscribe @grammarName, 'click', => @editor.trigger 'editor:select-grammar'
|
||||
@subscribe @grammarName, 'click', => @editor.trigger 'grammar-selector:show'
|
||||
@subscribe @editor, 'editor:grammar-changed', => @updateGrammarText()
|
||||
if git?
|
||||
@subscribe git, 'status-changed', (path, status) =>
|
||||
@@ -58,7 +58,11 @@ class StatusBarView extends View
|
||||
@updateStatusText()
|
||||
|
||||
updateGrammarText: ->
|
||||
@grammarName.text(@editor.getGrammar().name)
|
||||
grammar = @editor.getGrammar()
|
||||
if grammar is syntax.nullGrammar
|
||||
@grammarName.text('').hide()
|
||||
else
|
||||
@grammarName.text(grammar.name).show()
|
||||
|
||||
updateBufferHasModifiedText: (isModified)->
|
||||
if isModified
|
||||
@@ -110,6 +114,9 @@ class StatusBarView extends View
|
||||
else if git.isStatusNew(status)
|
||||
@gitStatusIcon.addClass('new-status-icon')
|
||||
@gitStatusIcon.text("+#{@buffer.getLineCount()}")
|
||||
else if git.isPathIgnored(path)
|
||||
@gitStatusIcon.addClass('ignored-status-icon')
|
||||
@gitStatusIcon.text('')
|
||||
|
||||
updatePathText: ->
|
||||
if path = @editor.getPath()
|
||||
|
||||
@@ -2,7 +2,7 @@ $ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
RootView = require 'root-view'
|
||||
StatusBar = require 'status-bar/lib/status-bar-view'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
describe "StatusBar", ->
|
||||
[editor, statusBar, buffer] = []
|
||||
@@ -32,7 +32,7 @@ describe "StatusBar", ->
|
||||
|
||||
describe "when associated with an unsaved buffer", ->
|
||||
it "displays 'untitled' instead of the buffer's path, but still displays the buffer position", ->
|
||||
rootView.deactivate()
|
||||
rootView.remove()
|
||||
window.rootView = new RootView
|
||||
rootView.open()
|
||||
rootView.simulateDomAttachment()
|
||||
@@ -112,7 +112,7 @@ describe "StatusBar", ->
|
||||
|
||||
it "displays the current branch for files in repositories", ->
|
||||
path = require.resolve('fixtures/git/master.git/HEAD')
|
||||
project.setPath(require.resolve('fixtures/git/master.git'))
|
||||
project.setPath(fs.resolveOnLoadPath('fixtures/git/master.git'))
|
||||
rootView.open(path)
|
||||
expect(statusBar.branchArea).toBeVisible()
|
||||
expect(statusBar.branchLabel.text()).toBe 'master'
|
||||
@@ -124,12 +124,14 @@ describe "StatusBar", ->
|
||||
expect(statusBar.branchLabel.text()).toBe ''
|
||||
|
||||
describe "git status label", ->
|
||||
[repo, path, originalPathText, newPath] = []
|
||||
[repo, path, originalPathText, newPath, ignoredPath] = []
|
||||
|
||||
beforeEach ->
|
||||
path = require.resolve('fixtures/git/working-dir/file.txt')
|
||||
newPath = fs.join(require.resolve('fixtures/git/working-dir'), 'new.txt')
|
||||
newPath = fs.join(fs.resolveOnLoadPath('fixtures/git/working-dir'), 'new.txt')
|
||||
fs.write(newPath, "I'm new here")
|
||||
ignoredPath = fs.join(fs.resolveOnLoadPath('fixtures/git/working-dir'), 'ignored.txt')
|
||||
fs.write(ignoredPath, 'ignored.txt')
|
||||
git.getPathStatus(path)
|
||||
git.getPathStatus(newPath)
|
||||
originalPathText = fs.read(path)
|
||||
@@ -138,6 +140,7 @@ describe "StatusBar", ->
|
||||
afterEach ->
|
||||
fs.write(path, originalPathText)
|
||||
fs.remove(newPath) if fs.exists(newPath)
|
||||
fs.remove(ignoredPath) if fs.exists(ignoredPath)
|
||||
|
||||
it "displays the modified icon for a changed file", ->
|
||||
fs.write(path, "i've changed for the worse")
|
||||
@@ -153,6 +156,10 @@ describe "StatusBar", ->
|
||||
rootView.open(newPath)
|
||||
expect(statusBar.gitStatusIcon).toHaveClass('new-status-icon')
|
||||
|
||||
it "displays the ignored icon for an ignored file", ->
|
||||
rootView.open(ignoredPath)
|
||||
expect(statusBar.gitStatusIcon).toHaveClass('ignored-status-icon')
|
||||
|
||||
it "updates when a status-changed event occurs", ->
|
||||
fs.write(path, "i've changed for the worse")
|
||||
git.getPathStatus(path)
|
||||
@@ -173,19 +180,33 @@ describe "StatusBar", ->
|
||||
expect(statusBar.gitStatusIcon).toHaveText('+1')
|
||||
|
||||
describe "grammar label", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('text.tmbundle', sync: true)
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
syntax.trigger 'grammars-loaded'
|
||||
|
||||
it "displays the name of the current grammar", ->
|
||||
expect(statusBar.find('.grammar-name').text()).toBe 'JavaScript'
|
||||
|
||||
it "hides the label when the current grammar is the null grammar", ->
|
||||
rootView.attachToDom()
|
||||
editor.activeEditSession.languageMode.grammar = syntax.nullGrammar
|
||||
editor.activeEditSession.trigger 'grammar-changed'
|
||||
expect(statusBar.find('.grammar-name')).toBeHidden()
|
||||
expect(statusBar.find('.grammar-name').text()).toBe ''
|
||||
editor.reloadGrammar()
|
||||
expect(statusBar.find('.grammar-name')).toBeVisible()
|
||||
expect(statusBar.find('.grammar-name').text()).toBe 'JavaScript'
|
||||
|
||||
describe "when the editor's grammar changes", ->
|
||||
it "displays the new grammar of the editor", ->
|
||||
textGrammar = _.find syntax.grammars, (grammar) -> grammar.name is 'Plain Text'
|
||||
project.addGrammarOverrideForPath(editor.getPath(), textGrammar)
|
||||
syntax.setGrammarOverrideForPath(editor.getPath(), 'text.plain')
|
||||
editor.reloadGrammar()
|
||||
expect(statusBar.find('.grammar-name').text()).toBe textGrammar.name
|
||||
expect(statusBar.find('.grammar-name').text()).toBe 'Plain Text'
|
||||
|
||||
describe "when clicked", ->
|
||||
it "toggles the editor:select-grammar event", ->
|
||||
it "toggles the grammar-selector:show event", ->
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
editor.on 'editor:select-grammar', eventHandler
|
||||
editor.on 'grammar-selector:show', eventHandler
|
||||
statusBar.find('.grammar-name').click()
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
77
src/packages/status-bar/stylesheets/status-bar.less
Normal file
77
src/packages/status-bar/stylesheets/status-bar.less
Normal file
@@ -0,0 +1,77 @@
|
||||
.status-bar {
|
||||
padding: 5px 10px;
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.status-bar .git-branch {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.status-bar .cursor-position,
|
||||
.status-bar .grammar-name {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.status-bar .grammar-name {
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
|
||||
.status-bar .branch-label {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.status-bar .git-status.octicons {
|
||||
display: none;
|
||||
padding-left: 10px;
|
||||
margin-top:-2px;
|
||||
}
|
||||
|
||||
.status-bar .octicons:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 14px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.status-bar .branch-icon:before {
|
||||
content: "\f020";
|
||||
}
|
||||
|
||||
.status-bar .modified-status-icon:before {
|
||||
content: "\f26d";
|
||||
}
|
||||
|
||||
.status-bar .new-status-icon:before {
|
||||
content: "\f26b";
|
||||
}
|
||||
|
||||
.status-bar .ignored-status-icon:before {
|
||||
content: "\f099";
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.status-bar .commits-behind-label:before {
|
||||
margin-top: -3px;
|
||||
margin-left: 3px;
|
||||
margin-right: 1px;
|
||||
content: "\f03f";
|
||||
}
|
||||
|
||||
.status-bar .commits-ahead-label:before {
|
||||
margin-top: -3px;
|
||||
margin-left: 3px;
|
||||
margin-right: 1px;
|
||||
content: "\f03d";
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
RootView = require 'root-view'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
describe "StripTrailingWhitespace", ->
|
||||
[editor, path] = []
|
||||
@@ -10,7 +10,7 @@ describe "StripTrailingWhitespace", ->
|
||||
window.rootView = new RootView
|
||||
rootView.open(path)
|
||||
|
||||
window.loadPackage('strip-trailing-whitespace')
|
||||
atom.activatePackage('strip-trailing-whitespace')
|
||||
rootView.focus()
|
||||
editor = rootView.getActiveView()
|
||||
|
||||
|
||||
17
src/packages/symbols-view/lib/load-tags-handler.coffee
Normal file
17
src/packages/symbols-view/lib/load-tags-handler.coffee
Normal file
@@ -0,0 +1,17 @@
|
||||
ctags = require 'ctags'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
getTagsFile: (path) ->
|
||||
tagsFile = fs.join(path, "tags")
|
||||
return tagsFile if fs.isFile(tagsFile)
|
||||
|
||||
tagsFile = fs.join(path, "TAGS")
|
||||
return tagsFile if fs.isFile(tagsFile)
|
||||
|
||||
loadTags: (path) ->
|
||||
tagsFile = @getTagsFile(path)
|
||||
if tagsFile
|
||||
callTaskMethod("tagsLoaded", ctags.getTags(tagsFile))
|
||||
else
|
||||
callTaskMethod("tagsLoaded", [])
|
||||
13
src/packages/symbols-view/lib/load-tags-task.coffee
Normal file
13
src/packages/symbols-view/lib/load-tags-task.coffee
Normal file
@@ -0,0 +1,13 @@
|
||||
Task = require 'task'
|
||||
|
||||
module.exports =
|
||||
class LoadTagsTask extends Task
|
||||
constructor: (@callback) ->
|
||||
super('symbols-view/lib/load-tags-handler')
|
||||
|
||||
started: ->
|
||||
@callWorkerMethod('loadTags', project.getPath())
|
||||
|
||||
tagsLoaded: (tags) ->
|
||||
@done()
|
||||
@callback(tags)
|
||||
@@ -3,7 +3,7 @@ SelectList = require 'select-list'
|
||||
TagGenerator = require './tag-generator'
|
||||
TagReader = require './tag-reader'
|
||||
Point = require 'point'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
@@ -41,12 +41,10 @@ class SymbolsView extends SelectList
|
||||
@attach()
|
||||
|
||||
populateFileSymbols: ->
|
||||
tags = []
|
||||
callback = (tag) -> tags.push tag
|
||||
path = rootView.getActiveView().getPath()
|
||||
@list.empty()
|
||||
@setLoading("Generating symbols...")
|
||||
new TagGenerator(path, callback).generate().done =>
|
||||
new TagGenerator(path).generate().done (tags) =>
|
||||
if tags.length > 0
|
||||
@miniEditor.show()
|
||||
@maxItem = Infinity
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
Point = require 'point'
|
||||
ChildProcess = require 'child-process'
|
||||
$ = require 'jquery'
|
||||
BufferedProcess = require 'buffered-process'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
class TagGenerator
|
||||
|
||||
constructor: (@path, @callback) ->
|
||||
constructor: (@path) ->
|
||||
|
||||
parseTagLine: (line) ->
|
||||
sections = line.split('\t')
|
||||
@@ -15,12 +16,15 @@ class TagGenerator
|
||||
null
|
||||
|
||||
generate: ->
|
||||
options =
|
||||
bufferLines: true
|
||||
stdout: (data) =>
|
||||
lines = data.split('\n')
|
||||
for line in lines
|
||||
tag = @parseTagLine(line)
|
||||
@callback(tag) if tag
|
||||
command = "#{require.resolve('ctags')} --fields=+KS -nf - #{@path}"
|
||||
ChildProcess.exec(command, options)
|
||||
deferred = $.Deferred()
|
||||
tags = []
|
||||
command = fs.resolveOnLoadPath('ctags')
|
||||
args = ['--fields=+KS', '-nf', '-', @path]
|
||||
stdout = (lines) =>
|
||||
for line in lines.split('\n')
|
||||
tag = @parseTagLine(line)
|
||||
tags.push(tag) if tag
|
||||
exit = ->
|
||||
deferred.resolve(tags)
|
||||
new BufferedProcess({command, args, stdout, exit})
|
||||
deferred
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
$ = require 'jquery'
|
||||
LoadTagsTask = require './load-tags-task'
|
||||
ctags = require 'ctags'
|
||||
|
||||
module.exports =
|
||||
|
||||
@@ -14,14 +16,11 @@ find: (editor) ->
|
||||
tagsFile = @getTagsFile(project)
|
||||
return [] unless tagsFile
|
||||
|
||||
$tags.find(tagsFile, word) or []
|
||||
ctags.findTags(tagsFile, word)
|
||||
|
||||
getAllTags: (project, callback) ->
|
||||
deferred = $.Deferred()
|
||||
tagsFile = @getTagsFile(project)
|
||||
if tagsFile
|
||||
$tags.getAllTagsAsync tagsFile, (tags) =>
|
||||
deferred.resolve(tags)
|
||||
else
|
||||
deferred.resolve([])
|
||||
callback = (tags=[]) =>
|
||||
deferred.resolve(tags)
|
||||
new LoadTagsTask(callback).start()
|
||||
deferred.promise()
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
RootView = require 'root-view'
|
||||
SymbolsView = require 'symbols-view/lib/symbols-view'
|
||||
TagGenerator = require 'symbols-view/lib/tag-generator'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
describe "SymbolsView", ->
|
||||
[symbolsView, setArraySpy] = []
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
window.loadPackage("symbols-view")
|
||||
atom.activatePackage("symbols-view")
|
||||
|
||||
rootView.attachToDom()
|
||||
setArraySpy = spyOn(SymbolsView.prototype, 'setArray').andCallThrough()
|
||||
@@ -83,13 +83,12 @@ describe "SymbolsView", ->
|
||||
|
||||
it "moves the cursor to the selected function", ->
|
||||
tags = []
|
||||
|
||||
waitsForPromise ->
|
||||
tags = []
|
||||
path = require.resolve('fixtures/sample.js')
|
||||
callback = (tag) ->
|
||||
tags.push tag
|
||||
generator = new TagGenerator(path, callback)
|
||||
generator.generate()
|
||||
generator = new TagGenerator(path)
|
||||
generator.generate().done (generatedTags) ->
|
||||
tags = generatedTags
|
||||
|
||||
runs ->
|
||||
rootView.open('sample.js')
|
||||
@@ -108,10 +107,9 @@ describe "SymbolsView", ->
|
||||
|
||||
waitsForPromise ->
|
||||
path = require.resolve('fixtures/sample.js')
|
||||
callback = (tag) ->
|
||||
tags.push tag
|
||||
generator = new TagGenerator(path, callback)
|
||||
generator.generate()
|
||||
generator = new TagGenerator(path)
|
||||
generator.generate().done (generatedTags) ->
|
||||
tags = generatedTags
|
||||
|
||||
runs ->
|
||||
expect(tags.length).toBe 2
|
||||
@@ -125,10 +123,9 @@ describe "SymbolsView", ->
|
||||
|
||||
waitsForPromise ->
|
||||
path = require.resolve('fixtures/sample.txt')
|
||||
callback = (tag) ->
|
||||
tags.push tag
|
||||
generator = new TagGenerator(path, callback)
|
||||
generator.generate()
|
||||
generator = new TagGenerator(path)
|
||||
generator.generate().done (generatedTags) ->
|
||||
tags = generatedTags
|
||||
|
||||
runs ->
|
||||
expect(tags.length).toBe 0
|
||||
|
||||
@@ -47,9 +47,11 @@ class TabBarView extends SortableList
|
||||
tab.insertBefore(followingTab)
|
||||
else
|
||||
@append(tab)
|
||||
tab.updateTitle()
|
||||
|
||||
removeTabForItem: (item) ->
|
||||
@tabForItem(item).remove()
|
||||
tab.updateTitle() for tab in @getTabs()
|
||||
|
||||
getTabs: ->
|
||||
@children('.tab').toArray().map (elt) -> $(elt).view()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
$ = require 'jquery'
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
class TabView extends View
|
||||
|
||||
@@ -4,14 +4,14 @@ RootView = require 'root-view'
|
||||
Pane = require 'pane'
|
||||
PaneContainer = require 'pane-container'
|
||||
TabBarView = require 'tabs/lib/tab-bar-view'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
{View} = require 'space-pen'
|
||||
|
||||
describe "Tabs package main", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage("tabs")
|
||||
atom.activatePackage("tabs")
|
||||
|
||||
describe ".activate()", ->
|
||||
it "appends a tab bar all existing and new panes", ->
|
||||
@@ -88,6 +88,17 @@ describe "TabBarView", ->
|
||||
expect(tabBar.getTabs().length).toBe 2
|
||||
expect(tabBar.find('.tab:contains(Item 2)')).not.toExist()
|
||||
|
||||
it "updates the titles of the remaining tabs", ->
|
||||
expect(tabBar.tabForItem(item2)).toHaveText 'Item 2'
|
||||
item2.longTitle = '2'
|
||||
item2a = new TestView('Item 2')
|
||||
item2a.longTitle = '2a'
|
||||
pane.showItem(item2a)
|
||||
expect(tabBar.tabForItem(item2)).toHaveText '2'
|
||||
expect(tabBar.tabForItem(item2a)).toHaveText '2a'
|
||||
pane.removeItem(item2a)
|
||||
expect(tabBar.tabForItem(item2)).toHaveText 'Item 2'
|
||||
|
||||
describe "when a tab is clicked", ->
|
||||
it "shows the associated item on the pane and focuses the pane", ->
|
||||
spyOn(pane, 'focus')
|
||||
|
||||
110
src/packages/tabs/stylesheets/tabs.less
Normal file
110
src/packages/tabs/stylesheets/tabs.less
Normal file
@@ -0,0 +1,110 @@
|
||||
.tabs {
|
||||
font: caption;
|
||||
display: -webkit-flex;
|
||||
-webkit-box-align: center;
|
||||
}
|
||||
|
||||
.tab {
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: element;
|
||||
cursor: default;
|
||||
-webkit-flex: 1;
|
||||
width: 175px;
|
||||
max-width: 175px;
|
||||
min-width: 40px;
|
||||
box-sizing: border-box;
|
||||
text-shadow: -1px -1px 0 #000;
|
||||
font-size: 11px;
|
||||
padding: 5px 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
-webkit-flex: 2;
|
||||
}
|
||||
|
||||
.tab .title {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding: 3px 10px 3px 0;
|
||||
}
|
||||
|
||||
.tab .close-icon {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 12px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
right: 8px;
|
||||
top: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.tab .close-icon:before {
|
||||
content: "\f081";
|
||||
}
|
||||
|
||||
.tab .close-icon:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tab.modified .close-icon {
|
||||
top: 11px;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
right: 9px;
|
||||
border: 2px solid #66a6ff;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.tab.modified .close-icon:before {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.tab.modified:hover .close-icon {
|
||||
border: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 8px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.tab.modified:hover .close-icon:before {
|
||||
content: "\f081";
|
||||
color: #66a6ff;
|
||||
}
|
||||
|
||||
/* Drag and Drop */
|
||||
.tab.is-dragging {
|
||||
|
||||
}
|
||||
|
||||
.tab.is-drop-target:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -2px;
|
||||
content: "";
|
||||
z-index: 999;
|
||||
display: inline-block;
|
||||
width: 2px;
|
||||
height: 30px;
|
||||
display: inline-block;
|
||||
background: #0098ff;
|
||||
}
|
||||
|
||||
.tab.is-drop-target:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: #0098ff;
|
||||
right: -4px;
|
||||
top: 30px;
|
||||
border-radius: 4px;
|
||||
z-index: 9999;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
@@ -5,9 +5,9 @@ describe "TOML grammar", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(syntax, "addGrammar")
|
||||
pack = new TextMatePackage(require.resolve("toml.tmbundle"))
|
||||
pack.load()
|
||||
grammar = pack.grammars[0]
|
||||
atom.activatePackage("toml")
|
||||
expect(syntax.addGrammar).toHaveBeenCalled()
|
||||
grammar = syntax.addGrammar.argsForCall[0][0]
|
||||
|
||||
it "parses the grammar", ->
|
||||
expect(grammar).toBeTruthy()
|
||||
@@ -1,6 +1,6 @@
|
||||
{View} = require 'space-pen'
|
||||
Editor = require 'editor'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{View} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
Git = require 'git'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
class FileView extends View
|
||||
@@ -14,19 +14,22 @@ class FileView extends View
|
||||
file: null
|
||||
|
||||
initialize: ({@file, @project} = {}) ->
|
||||
extension = fs.extension(@getPath())
|
||||
if fs.isReadmePath(@getPath())
|
||||
@fileName.addClass('readme-icon')
|
||||
else if fs.isCompressedExtension(extension)
|
||||
@fileName.addClass('compressed-icon')
|
||||
else if fs.isImageExtension(extension)
|
||||
@fileName.addClass('image-icon')
|
||||
else if fs.isPdfExtension(extension)
|
||||
@fileName.addClass('pdf-icon')
|
||||
else if fs.isBinaryExtension(extension)
|
||||
@fileName.addClass('binary-icon')
|
||||
if @file.symlink
|
||||
@fileName.addClass('symlink-icon')
|
||||
else
|
||||
@fileName.addClass('text-icon')
|
||||
extension = fs.extension(@getPath())
|
||||
if fs.isReadmePath(@getPath())
|
||||
@fileName.addClass('readme-icon')
|
||||
else if fs.isCompressedExtension(extension)
|
||||
@fileName.addClass('compressed-icon')
|
||||
else if fs.isImageExtension(extension)
|
||||
@fileName.addClass('image-icon')
|
||||
else if fs.isPdfExtension(extension)
|
||||
@fileName.addClass('pdf-icon')
|
||||
else if fs.isBinaryExtension(extension)
|
||||
@fileName.addClass('binary-icon')
|
||||
else
|
||||
@fileName.addClass('text-icon')
|
||||
|
||||
if git?
|
||||
@subscribe git, 'status-changed', (path, status) =>
|
||||
|
||||
@@ -4,7 +4,7 @@ Directory = require 'directory'
|
||||
DirectoryView = require './directory-view'
|
||||
FileView = require './file-view'
|
||||
Dialog = require './dialog'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
@@ -40,8 +40,8 @@ class TreeView extends ScrollView
|
||||
else
|
||||
@selectActiveFile()
|
||||
|
||||
rootView.on 'pane:active-item-changed pane:became-active', => @selectActiveFile()
|
||||
project.on 'path-changed', => @updateRoot()
|
||||
rootView.on 'pane:active-item-changed.tree-view pane:became-active.tree-view', => @selectActiveFile()
|
||||
project.on 'path-changed.tree-view', => @updateRoot()
|
||||
@observeConfig 'core.hideGitIgnoredFiles', => @updateRoot()
|
||||
|
||||
if @root
|
||||
@@ -67,6 +67,9 @@ class TreeView extends ScrollView
|
||||
|
||||
deactivate: ->
|
||||
@root?.unwatchEntries()
|
||||
rootView.off('.tree-view')
|
||||
project.off('.tree-view')
|
||||
@remove()
|
||||
|
||||
toggle: ->
|
||||
if @hasFocus()
|
||||
@@ -222,6 +225,14 @@ class TreeView extends ScrollView
|
||||
iconClass: 'move'
|
||||
onConfirm: (newPath) =>
|
||||
newPath = project.resolve(newPath)
|
||||
if oldPath is newPath
|
||||
dialog.close()
|
||||
return
|
||||
|
||||
if fs.exists(newPath)
|
||||
dialog.showError("Error: #{newPath} already exists. Try a different path.")
|
||||
return
|
||||
|
||||
directoryPath = fs.directory(newPath)
|
||||
try
|
||||
fs.makeTree(directoryPath) unless fs.exists(directoryPath)
|
||||
|
||||
@@ -4,7 +4,7 @@ _ = require 'underscore'
|
||||
TreeView = require 'tree-view/lib/tree-view'
|
||||
RootView = require 'root-view'
|
||||
Directory = require 'directory'
|
||||
fs = require 'fs'
|
||||
fs = require 'fs-utils'
|
||||
|
||||
describe "TreeView", ->
|
||||
[treeView, sampleJs, sampleTxt] = []
|
||||
@@ -13,7 +13,7 @@ describe "TreeView", ->
|
||||
project.setPath(project.resolve('tree-view'))
|
||||
window.rootView = new RootView
|
||||
|
||||
window.loadPackage("tree-view")
|
||||
atom.activatePackage("tree-view")
|
||||
rootView.trigger 'tree-view:toggle'
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
treeView.root = treeView.find('ol > li:first').view()
|
||||
@@ -47,10 +47,8 @@ describe "TreeView", ->
|
||||
describe "when the project has no path", ->
|
||||
beforeEach ->
|
||||
project.setPath(undefined)
|
||||
rootView.deactivate()
|
||||
window.rootView = new RootView()
|
||||
rootView.open()
|
||||
treeView = window.loadPackage("tree-view").mainModule.createView()
|
||||
atom.deactivatePackage("tree-view")
|
||||
treeView = atom.activatePackage("tree-view").mainModule.createView()
|
||||
|
||||
it "does not attach to the root view or create a root node when initialized", ->
|
||||
expect(treeView.hasParent()).toBeFalsy()
|
||||
@@ -66,23 +64,24 @@ describe "TreeView", ->
|
||||
|
||||
describe "when the project is assigned a path because a new buffer is saved", ->
|
||||
it "creates a root directory view but does not attach to the root view", ->
|
||||
rootView.open()
|
||||
rootView.getActivePaneItem().saveAs("/tmp/test.txt")
|
||||
expect(treeView.hasParent()).toBeFalsy()
|
||||
expect(treeView.root.getPath()).toBe require.resolve('/tmp')
|
||||
expect(treeView.root.getPath()).toBe '/tmp'
|
||||
expect(treeView.root.parent()).toMatchSelector(".tree-view")
|
||||
|
||||
describe "when the root view is opened to a file path", ->
|
||||
it "does not attach to the root view but does create a root node when initialized", ->
|
||||
rootView.deactivate()
|
||||
window.rootView = new RootView
|
||||
atom.deactivatePackage("tree-view")
|
||||
atom.packageStates = {}
|
||||
rootView.open('tree-view.js')
|
||||
treeView = window.loadPackage("tree-view").mainModule.createView()
|
||||
treeView = atom.activatePackage("tree-view").mainModule.createView()
|
||||
expect(treeView.hasParent()).toBeFalsy()
|
||||
expect(treeView.root).toExist()
|
||||
|
||||
describe "when the root view is opened to a directory", ->
|
||||
it "attaches to the root view", ->
|
||||
treeView = window.loadPackage("tree-view").mainModule.createView()
|
||||
treeView = atom.activatePackage("tree-view").mainModule.createView()
|
||||
expect(treeView.hasParent()).toBeTruthy()
|
||||
expect(treeView.root).toExist()
|
||||
|
||||
@@ -91,10 +90,8 @@ describe "TreeView", ->
|
||||
treeView.find('.directory:contains(dir1)').click()
|
||||
sampleJs.click()
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
window.rootView = RootView.deserialize(rootViewState)
|
||||
window.loadPackage("tree-view")
|
||||
atom.deactivatePackage("tree-view")
|
||||
atom.activatePackage("tree-view")
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
|
||||
expect(treeView).toExist()
|
||||
@@ -105,13 +102,8 @@ describe "TreeView", ->
|
||||
rootView.attachToDom()
|
||||
treeView.focus()
|
||||
expect(treeView.find(".tree-view")).toMatchSelector ':focus'
|
||||
|
||||
rootViewState = rootView.serialize()
|
||||
rootView.deactivate()
|
||||
window.rootView = RootView.deserialize(rootViewState)
|
||||
|
||||
rootView.attachToDom()
|
||||
window.loadPackage("tree-view")
|
||||
atom.deactivatePackage("tree-view")
|
||||
atom.activatePackage("tree-view")
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
expect(treeView.find(".tree-view")).toMatchSelector ':focus'
|
||||
|
||||
@@ -267,20 +259,20 @@ describe "TreeView", ->
|
||||
|
||||
sampleJs.trigger clickEvent(originalEvent: { detail: 1 })
|
||||
expect(sampleJs).toHaveClass 'selected'
|
||||
expect(rootView.getActiveView().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveView().getPath()).toBe fs.resolveOnLoadPath('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveView().isFocused).toBeFalsy()
|
||||
|
||||
sampleTxt.trigger clickEvent(originalEvent: { detail: 1 })
|
||||
expect(sampleTxt).toHaveClass 'selected'
|
||||
expect(treeView.find('.selected').length).toBe 1
|
||||
expect(rootView.getActiveView().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.txt')
|
||||
expect(rootView.getActiveView().getPath()).toBe fs.resolveOnLoadPath('fixtures/tree-view/tree-view.txt')
|
||||
expect(rootView.getActiveView().isFocused).toBeFalsy()
|
||||
|
||||
describe "when a file is double-clicked", ->
|
||||
it "selects the file and opens it in the active editor on the first click, then changes focus to the active editor on the second", ->
|
||||
sampleJs.trigger clickEvent(originalEvent: { detail: 1 })
|
||||
expect(sampleJs).toHaveClass 'selected'
|
||||
expect(rootView.getActiveView().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveView().getPath()).toBe fs.resolveOnLoadPath('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveView().isFocused).toBeFalsy()
|
||||
|
||||
sampleJs.trigger clickEvent(originalEvent: { detail: 2 })
|
||||
@@ -576,7 +568,7 @@ describe "TreeView", ->
|
||||
it "opens the file in the editor and focuses it", ->
|
||||
treeView.root.find('.file:contains(tree-view.js)').click()
|
||||
treeView.root.trigger 'tree-view:open-selected-entry'
|
||||
expect(rootView.getActiveView().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveView().getPath()).toBe fs.resolveOnLoadPath('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveView().isFocused).toBeTruthy()
|
||||
|
||||
describe "when a directory is selected", ->
|
||||
@@ -599,9 +591,9 @@ describe "TreeView", ->
|
||||
[dirView, fileView, rootDirPath, dirPath, filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView.deactivate()
|
||||
atom.deactivatePackage('tree-view')
|
||||
|
||||
rootDirPath = "/tmp/atom-tests"
|
||||
rootDirPath = fs.join(fs.absolute("/tmp"), "atom-tests")
|
||||
fs.remove(rootDirPath) if fs.exists(rootDirPath)
|
||||
|
||||
dirPath = fs.join(rootDirPath, "test-dir")
|
||||
@@ -611,8 +603,8 @@ describe "TreeView", ->
|
||||
fs.write(filePath, "doesn't matter")
|
||||
|
||||
project.setPath(rootDirPath)
|
||||
window.rootView = new RootView(rootDirPath)
|
||||
window.loadPackage('tree-view')
|
||||
|
||||
atom.activatePackage('tree-view')
|
||||
rootView.trigger 'tree-view:toggle'
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
dirView = treeView.root.entries.find('.directory:contains(test-dir)').view()
|
||||
@@ -883,7 +875,7 @@ describe "TreeView", ->
|
||||
temporaryFilePath = null
|
||||
|
||||
beforeEach ->
|
||||
temporaryFilePath = fs.join(require.resolve('fixtures/tree-view'), 'temporary')
|
||||
temporaryFilePath = fs.join(fs.resolveOnLoadPath('fixtures/tree-view'), 'temporary')
|
||||
if fs.exists(temporaryFilePath)
|
||||
fs.remove(temporaryFilePath)
|
||||
waits(20)
|
||||
@@ -915,7 +907,7 @@ describe "TreeView", ->
|
||||
[ignoreFile] = []
|
||||
|
||||
beforeEach ->
|
||||
ignoreFile = fs.join(require.resolve('fixtures/tree-view'), '.gitignore')
|
||||
ignoreFile = fs.join(fs.resolveOnLoadPath('fixtures/tree-view'), '.gitignore')
|
||||
fs.write(ignoreFile, 'tree-view.js')
|
||||
config.set "core.hideGitIgnoredFiles", false
|
||||
|
||||
@@ -938,15 +930,15 @@ describe "TreeView", ->
|
||||
|
||||
beforeEach ->
|
||||
config.set "core.hideGitIgnoredFiles", false
|
||||
ignoreFile = fs.join(require.resolve('fixtures/tree-view'), '.gitignore')
|
||||
ignoreFile = fs.join(fs.resolveOnLoadPath('fixtures/tree-view'), '.gitignore')
|
||||
fs.write(ignoreFile, 'tree-view.js')
|
||||
git.getPathStatus(ignoreFile)
|
||||
|
||||
newFile = fs.join(require.resolve('fixtures/tree-view/dir2'), 'new2')
|
||||
newFile = fs.join(fs.resolveOnLoadPath('fixtures/tree-view/dir2'), 'new2')
|
||||
fs.write(newFile, '')
|
||||
git.getPathStatus(newFile)
|
||||
|
||||
modifiedFile = fs.join(require.resolve('fixtures/tree-view/dir1'), 'file1')
|
||||
modifiedFile = fs.join(fs.resolveOnLoadPath('fixtures/tree-view/dir1'), 'file1')
|
||||
originalFileContent = fs.read(modifiedFile)
|
||||
fs.write modifiedFile, 'ch ch changes'
|
||||
git.getPathStatus(modifiedFile)
|
||||
|
||||
@@ -1,3 +1,144 @@
|
||||
.tree-view .entries {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.tree-view .entries .file .name {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.tree-view .file .name,
|
||||
.tree-view .directory .header {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.tree-view .directory .header {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.tree-view-dialog {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.tree-view-dialog .prompt {
|
||||
padding-bottom: 3px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.tree-view-dialog .prompt span {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.tree-view-dialog .prompt:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 3px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.tree-view-dialog .prompt.add-file:before {
|
||||
content: "\f086";
|
||||
}
|
||||
|
||||
.tree-view-dialog .prompt.add-directory:before {
|
||||
content: "\f095";
|
||||
}
|
||||
|
||||
.tree-view-dialog .prompt.move:before {
|
||||
content: "\f03e";
|
||||
}
|
||||
|
||||
.tree-view .directory .header .name,
|
||||
.tree-view .file .name {
|
||||
position: relative;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
.tree-view .directory .header .name:before,
|
||||
.tree-view .file .name:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.tree-view .disclosure-arrow:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 12px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
line-height: 16px;
|
||||
margin-right: 3px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.tree-view .directory .header .directory-icon:before {
|
||||
content: "\f016";
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
.tree-view .directory .header .repository-icon:before {
|
||||
content: "\f001";
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.tree-view .directory .header .submodule-icon:before {
|
||||
content: "\f017";
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
.tree-view .file .text-icon:before {
|
||||
content: "\f011";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .file .image-icon:before {
|
||||
content: "\f012";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .file .compressed-icon:before {
|
||||
content: "\f013";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .file .pdf-icon:before {
|
||||
content: "\f014";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .file .readme-icon:before {
|
||||
content: "\f007";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .file .binary-icon:before {
|
||||
content: "\f094";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .file .symlink-icon:before {
|
||||
content: "\f09b";
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.tree-view .directory > .header .disclosure-arrow:before {
|
||||
content: "\f05a";
|
||||
}
|
||||
|
||||
.tree-view .directory.expanded > .header .disclosure-arrow:before {
|
||||
content: "\f05b";
|
||||
}
|
||||
|
||||
.tree-view-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
@@ -6,7 +6,7 @@ describe "WrapGuide", ->
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
rootView.open('sample.js')
|
||||
window.loadPackage('wrap-guide')
|
||||
atom.activatePackage('wrap-guide')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveView()
|
||||
wrapGuide = rootView.find('.wrap-guide').view()
|
||||
|
||||
Reference in New Issue
Block a user