Merge remote-tracking branch 'origin/dev' into fuzzy

This commit is contained in:
Corey Johnson
2013-01-21 12:42:14 -08:00
44 changed files with 332 additions and 155 deletions

View File

@@ -35,10 +35,7 @@ class AtomPackage extends Package
keymaps.map (relativePath) =>
fs.resolve(@keymapsDirPath, relativePath, ['cson', 'json', ''])
else
if fs.exists(@keymapsDirPath)
fs.list(@keymapsDirPath)
else
[]
fs.list(@keymapsDirPath)
loadStylesheets: ->
for stylesheetPath in @getStylesheetPaths()
@@ -46,7 +43,4 @@ class AtomPackage extends Package
getStylesheetPaths: ->
stylesheetDirPath = fs.join(@path, 'stylesheets')
if fs.exists stylesheetDirPath
fs.list stylesheetDirPath
else
[]
fs.list(stylesheetDirPath)

View File

@@ -75,6 +75,9 @@ _.extend atom,
focus: ->
@sendMessageToBrowserProcess('focus')
show: ->
@sendMessageToBrowserProcess('show')
exit: (status) ->
@sendMessageToBrowserProcess('exit', [status])

View File

@@ -7,13 +7,16 @@ PEG = require 'pegjs'
module.exports =
class BindingSet
@parser: null
selector: null
commandsByKeystrokes: null
commandForEvent: null
parser: null
constructor: (@selector, commandsByKeystrokes, @index) ->
@parser = PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs'))
BindingSet.parser ?= PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs'))
@specificity = Specificity(@selector)
@commandsByKeystrokes = @normalizeCommandsByKeystrokes(commandsByKeystrokes)
@@ -42,7 +45,7 @@ class BindingSet
normalizedKeystrokes.join(' ')
normalizeKeystroke: (keystroke) ->
keys = @parser.parse(keystroke)
keys = BindingSet.parser.parse(keystroke)
modifiers = keys[0...-1]
modifiers.sort()
[modifiers..., _.last(keys)].join('-')

View File

@@ -54,6 +54,8 @@ class Buffer
@destroy() if @refcount <= 0
this
hasEditors: -> @refcount > 1
subscribeToFile: ->
@file.on "contents-changed", =>
if @isModified()

View File

@@ -142,6 +142,8 @@ class EditSession
lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row)
scanInRange: (args...) -> @buffer.scanInRange(args...)
backwardsScanInRange: (args...) -> @buffer.backwardsScanInRange(args...)
isModified: -> @buffer.isModified()
hasEditors: -> @buffer.hasEditors()
screenPositionForBufferPosition: (bufferPosition, options) -> @displayBuffer.screenPositionForBufferPosition(bufferPosition, options)
bufferPositionForScreenPosition: (screenPosition, options) -> @displayBuffer.bufferPositionForScreenPosition(screenPosition, options)
@@ -206,6 +208,9 @@ class EditSession
toggleLineCommentsInSelection: ->
@mutateSelectedText (selection) -> selection.toggleLineComments()
autoIndentSelectedRows: ->
@mutateSelectedText (selection) -> selection.autoIndentSelectedRows()
cutToEndOfLine: ->
maintainPasteboard = false
@mutateSelectedText (selection) ->

View File

@@ -117,6 +117,7 @@ class Editor extends View
'editor:select-word': @selectWord
'editor:newline': @insertNewline
'editor:indent': @indent
'editor:auto-indent': @autoIndent
'editor:indent-selected-rows': @indentSelectedRows
'editor:outdent-selected-rows': @outdentSelectedRows
'editor:backspace-to-beginning-of-word': @backspaceToBeginningOfWord
@@ -151,6 +152,7 @@ class Editor extends View
'core:select-to-bottom': @selectToBottom
'core:close': @destroyActiveEditSession
'editor:save': @save
'editor:save-as': @saveAs
'editor:newline-below': @insertNewlineBelow
'editor:toggle-soft-tabs': @toggleSoftTabs
'editor:toggle-soft-wrap': @toggleSoftWrap
@@ -247,6 +249,7 @@ class Editor extends View
insertNewline: -> @activeEditSession.insertNewline()
insertNewlineBelow: -> @activeEditSession.insertNewlineBelow()
indent: (options) -> @activeEditSession.indent(options)
autoIndent: (options) -> @activeEditSession.autoIndentSelectedRows(options)
indentSelectedRows: -> @activeEditSession.indentSelectedRows()
outdentSelectedRows: -> @activeEditSession.outdentSelectedRows()
cutSelection: -> @activeEditSession.cutSelectedText()
@@ -463,7 +466,7 @@ class Editor extends View
@remove() if @editSessions.length is 0
callback(index) if callback
if editSession.buffer.isModified()
if editSession.isModified() and not editSession.hasEditors()
@promptToSaveDirtySession(editSession, destroySession)
else
destroySession(editSession)
@@ -653,6 +656,9 @@ class Editor extends View
session.save()
onSuccess?()
else
@saveAs(session, onSuccess)
saveAs: (session=@activeEditSession, onSuccess) ->
atom.showSaveDialog (path) =>
if path
session.saveAs(path)

View File

@@ -22,7 +22,7 @@
'pageup': 'core:page-up'
'pagedown': 'core:page-down'
'meta-S': 'window:save-all'
'meta-alt-s': 'window:save-all'
'meta-W': 'window:close'
'meta-+': 'window:increase-font-size'
'meta--': 'window:decrease-font-size'
@@ -33,4 +33,4 @@
'.tool-panel':
'meta-escape': 'tool-panel:unfocus'
'escape': 'core:close'
'meta-w': 'noop'
'meta-w': 'noop'

View File

@@ -1,8 +1,10 @@
'.editor':
'meta-s': 'editor:save'
'meta-S': 'editor:save-as'
'enter': 'editor:newline'
'meta-enter': 'editor:newline-below'
'tab': 'editor:indent'
'meta-=': 'editor:auto-indent'
'meta-d': 'editor:delete-line'
'ctrl-[': 'editor:fold-current-row'
'ctrl-]': 'editor:unfold-current-row'

View File

@@ -6,14 +6,14 @@ module.exports =
class Pane extends View
@content: (wrappedView) ->
@div class: 'pane', =>
@subview 'wrappedView', wrappedView
@subview 'wrappedView', wrappedView if wrappedView
@deserialize: ({wrappedView}, rootView) ->
new Pane(rootView.deserializeView(wrappedView))
serialize: ->
viewClass: "Pane"
wrappedView: @wrappedView.serialize()
wrappedView: @wrappedView?.serialize()
adjustDimensions: -> # do nothing

View File

@@ -42,6 +42,12 @@ class RootView extends View
window.rootView = this
@packageStates ?= {}
@packageModules = {}
@viewClasses = {
"Pane": Pane,
"PaneRow": PaneRow,
"PaneColumn": PaneColumn,
"Editor": Editor
}
@handleEvents()
if not projectOrPathToOpen or _.isString(projectOrPathToOpen)
@@ -121,12 +127,11 @@ class RootView extends View
console?.error("Exception serializing '#{name}' package's module\n", e.stack)
packageStates
registerViewClass: (viewClass) ->
@viewClasses[viewClass.name] = viewClass
deserializeView: (viewState) ->
switch viewState.viewClass
when 'Pane' then Pane.deserialize(viewState, this)
when 'PaneRow' then PaneRow.deserialize(viewState, this)
when 'PaneColumn' then PaneColumn.deserialize(viewState, this)
when 'Editor' then Editor.deserialize(viewState, this)
@viewClasses[viewState.viewClass]?.deserialize(viewState, this)
activatePackage: (name, packageModule) ->
config.setDefaults(name, packageModule.configDefaults) if packageModule.configDefaults?

View File

@@ -307,6 +307,10 @@ class Selection
if matchLength = buffer.lineForRow(row).match(leadingTabRegex)?[0].length
buffer.delete [[row, 0], [row, matchLength]]
autoIndentSelectedRows: ->
[start, end] = @getBufferRowRange()
@editSession.autoIndentBufferRows(start, end)
toggleLineComments: ->
@modifySelection =>
@editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...)

View File

@@ -99,9 +99,10 @@ windowAdditions =
measure: (description, fn) ->
start = new Date().getTime()
fn()
value = fn()
result = new Date().getTime() - start
console.log description, result
value
window[key] = value for key, value of windowAdditions
window.startup()

View File

@@ -2,7 +2,6 @@
ScrollView = require 'scroll-view'
$ = require 'jquery'
_ = require 'underscore'
d3 = require 'd3.v3'
module.exports =
class CommandLogger extends ScrollView
@@ -121,6 +120,8 @@ class CommandLogger extends ScrollView
w = @treeMap.width()
h = @treeMap.height()
d3 = require 'd3.v3'
x = d3.scale.linear().range([0, w])
y = d3.scale.linear().range([0, h])
color = d3.scale.category20()

View File

@@ -4,9 +4,9 @@ PEG = require 'pegjs'
module.exports =
class CommandInterpreter
constructor: (@project) ->
@parser = PEG.buildParser(fs.read(require.resolve 'command-panel/commands.pegjs'))
eval: (string, activeEditSession) ->
@parser ?= PEG.buildParser(fs.read(require.resolve 'command-panel/commands.pegjs'))
compositeCommand = @parser.parse(string)
@lastRelativeAddress = compositeCommand if compositeCommand.isRelativeAddress()
compositeCommand.execute(@project, activeEditSession)

View File

@@ -36,7 +36,7 @@ class CommandPanel extends View
@subview 'previewList', new PreviewList(rootView)
@ul class: 'error-messages', outlet: 'errorMessages'
@div class: 'prompt-and-editor', =>
@div ':', class: 'prompt', outlet: 'prompt'
@div class: 'prompt', outlet: 'prompt'
@subview 'miniEditor', new Editor(mini: true)
commandInterpreter: null
@@ -67,6 +67,7 @@ class CommandPanel extends View
@previewList.hide()
@errorMessages.hide()
@prompt.iconSize(@miniEditor.fontSize)
destroy: ->
@previewList.destroy()

View File

@@ -67,10 +67,20 @@
display: -webkit-box;
}
.command-panel .prompt {
color: white;
font-weight: bold;
padding-right: 5px;
.command-panel .prompt-and-editor .prompt:before {
color: #969696;
content: '\f078';
font-family: 'Octicons Regular';
position: relative;
top: -5px;
left: -5px;
-webkit-font-smoothing: antialiased;
}
.command-panel .prompt-and-editor .editor {
position: relative;
left: -4px;
margin-right: -4px;
}
.error-messages {

View File

@@ -1,4 +1,4 @@
{View, $$} = require 'space-pen'
{$$} = require 'space-pen'
SelectList = require 'select-list'
TagGenerator = require 'outline-view/src/tag-generator'
TagReader = require 'outline-view/src/tag-reader'
@@ -30,7 +30,7 @@ class OutlineView extends SelectList
if position
text = "Line #{position.row + 1}"
else
text = fs.base(file)
text = fs.base(file)
@div text, class: 'function-details'
@div class: 'clear-float'

View File

@@ -2,6 +2,8 @@
background: #333333;
border-bottom: 4px solid #424242;
font: caption;
-webkit-user-select: none;
user-select: none;
}
.tab {

View File

@@ -445,6 +445,14 @@ describe "TreeView", ->
treeView.trigger 'core:move-to-top'
expect(treeView.scrollTop()).toBe 0
it "selects the root entry", ->
entryCount = treeView.find(".entry").length
_.times entryCount, -> treeView.moveDown()
expect(treeView.root).not.toHaveClass 'selected'
treeView.trigger 'core:move-to-top'
expect(treeView.root).toHaveClass 'selected'
describe "core:move-to-bottom", ->
it "scrolls to the bottom", ->
treeView.height(100)
@@ -456,6 +464,11 @@ describe "TreeView", ->
treeView.trigger 'core:move-to-bottom'
expect(treeView.scrollBottom()).toBe treeView.prop('scrollHeight')
it "selects the last entry", ->
expect(treeView.root).toHaveClass 'selected'
treeView.trigger 'core:move-to-bottom'
expect(treeView.root.find('.entry:last')).toHaveClass 'selected'
describe "core:page-up", ->
it "scrolls up a page", ->
treeView.height(5)

View File

@@ -1,4 +1,4 @@
{View, $$} = require 'space-pen'
{View} = require 'space-pen'
Editor = require 'editor'
fs = require 'fs'
$ = require 'jquery'

View File

@@ -27,7 +27,8 @@ class TreeView extends ScrollView
@instance.serialize()
@content: (rootView) ->
@ol class: 'tree-view tool-panel', tabindex: -1
@ol class: 'tree-view tool-panel', tabindex: -1, =>
@div class: 'tree-view-resizer', outlet: 'resizer'
@deserialize: (state, rootView) ->
treeView = new TreeView(rootView)
@@ -35,6 +36,7 @@ class TreeView extends ScrollView
treeView.selectEntryForPath(state.selectedPath)
treeView.focusAfterAttach = state.hasFocus
treeView.scrollTopAfterAttach = state.scrollTop
treeView.width(state.width)
treeView.attach() if state.attached
treeView
@@ -46,6 +48,7 @@ class TreeView extends ScrollView
initialize: (@rootView) ->
super
@on 'click', '.entry', (e) => @entryClicked(e)
@on 'mousedown', '.tree-view-resizer', (e) => @resizeStarted(e)
@command 'core:move-up', => @moveUp()
@command 'core:move-down', => @moveDown()
@command 'core:close', => @detach(); false
@@ -79,6 +82,7 @@ class TreeView extends ScrollView
hasFocus: @hasFocus()
attached: @hasParent()
scrollTop: @scrollTop()
width: @width()
deactivate: ->
@root?.unwatchEntries()
@@ -119,6 +123,20 @@ class TreeView extends ScrollView
false
resizeStarted: (e) =>
$(document.body).on('mousemove', @resizeTreeView)
$(document.body).on('mouseup', @resizeStopped)
@css(overflow: 'hidden')
resizeStopped: (e) =>
$(document.body).off('mousemove', @resizeTreeView)
$(document.body).off('mouseup', @resizeStopped)
@css(overflow: 'auto')
resizeTreeView: (e) =>
@css(width: e.pageX)
@resizer.css(left: e.pageX)
updateRoot: ->
@root?.remove()
if rootDirectory = @rootView.project.getRootDirectory()
@@ -296,3 +314,13 @@ class TreeView extends ScrollView
@scrollBottom(bottom)
if top < @scrollTop()
@scrollTop(top)
scrollToBottom: ->
super()
@selectEntry(@root.find('.entry:last')) if @root
scrollToTop: ->
super()
@selectEntry(@root) if @root

View File

@@ -8,11 +8,20 @@
border-right: 2px solid #191919;
min-width: 100px;
z-index: 2;
padding-left: 12px;
}
.tree-view .tree-view-resizer {
float: right;
height: 100%;
width: 10px;
background: transparent;
cursor: col-resize;
}
.tree-view .entry {
text-shadow: 0 -1px 0 #000;
text-wrap: none;
white-space: nowrap;
}
.tree-view .entries {

View File

@@ -15,7 +15,6 @@ class WrapGuide extends View
@content: ->
@div class: 'wrap-guide'
getGuideColumn: null
defaultColumn: 80
initialize: (@rootView, @editor) =>
@@ -29,9 +28,9 @@ class WrapGuide extends View
return @defaultColumn unless _.isArray(customColumns)
for customColumn in customColumns
continue unless _.isObject(customColumn)
regex = customColumn['pattern']
continue unless regex
return parseInt(customColumn['column']) if new RegExp(regex).test(path)
pattern = customColumn['pattern']
continue unless pattern
return parseInt(customColumn['column']) if new RegExp(pattern).test(path)
@defaultColumn
updateGuide: ->

View File

@@ -161,6 +161,7 @@ module.exports =
'.jpeg'
'.jpg'
'.png'
'.tiff'
], ext)
isPdfExtension: (ext) ->

View File

@@ -73,6 +73,9 @@ $.fn.command = (args...) ->
@document(documentation)
@on(args...)
$.fn.iconSize = (size) ->
@width(size).height(size).css('font-size', size)
$.Event.prototype.abortKeyBinding = ->
$.Event.prototype.currentTargetView = -> $(this.currentTarget).view()
$.Event.prototype.targetView = -> $(this.target).view()

View File

@@ -28,7 +28,7 @@ require = (path, cb) ->
parts = file.split '.'
ext = parts[parts.length-1]
if __modules[file]?
if __moduleExists file
if not __modules.loaded[file.toLowerCase()]?
console.warn "Circular require: #{__filename} required #{file}"
return __modules[file]
@@ -73,16 +73,26 @@ resolve = (name, {verifyExistence}={}) ->
file = file.replace '../', "#{prefix}/"
if file[0] isnt '/'
paths.some (path) ->
fileExists = /\.(.+)$/.test(file) and __exists "#{path}/#{file}"
jsFileExists = not /\.(.+)$/.test(file) and __exists "#{path}/#{file}.js"
if jsFileExists
file = "#{path}/#{file}.js"
else if fileExists
moduleAlreadyLoaded = paths.some (path) ->
if __moduleExists "#{path}/#{file}"
file = "#{path}/#{file}"
else if expanded = __expand "#{path}/#{file}"
else if __moduleExists "#{path}/#{file}.js"
file = "#{path}/#{file}.js"
else if expanded = __moduleExpand "#{path}/#{file}"
file = expanded
if not moduleAlreadyLoaded
hasExtension = /\.(.+)$/.test(file)
paths.some (path) ->
fileExists = hasExtension and __exists "#{path}/#{file}"
jsFileExists = not hasExtension and __exists "#{path}/#{file}.js"
if jsFileExists
file = "#{path}/#{file}.js"
else if fileExists
file = "#{path}/#{file}"
else if expanded = __expand "#{path}/#{file}"
file = expanded
else
file = __expand(file) or file
@@ -92,16 +102,27 @@ resolve = (name, {verifyExistence}={}) ->
console.warn("Failed to resolve '#{name}'") if verifyExistence
null
__moduleExists = (path) ->
__modules[path]?
__moduleExpand = (path) ->
return path if __moduleExists path
for ext, handler of exts
return "#{path}.#{ext}" if __moduleExists "#{path}.#{ext}"
return "#{path}/index.#{ext}" if __moduleExists "#{path}/index.#{ext}"
null
__expand = (path) ->
modulePath = __moduleExpand path
return modulePath if modulePath
return path if __isFile path
for ext, handler of exts
if __exists "#{path}.#{ext}"
return "#{path}.#{ext}"
else if __exists "#{path}/index.#{ext}"
return "#{path}/index.#{ext}"
return "#{path}.#{ext}" if __exists "#{path}.#{ext}"
return "#{path}/index.#{ext}" if __exists "#{path}/index.#{ext}"
return path if __exists path
return null
null
__exists = (path) ->
$native.exists path

View File

@@ -4,3 +4,4 @@ require 'window'
pathToOpen = atom.getWindowState('pathToOpen') ? window.location.params.pathToOpen
window.attachRootView(pathToOpen)
atom.show()