Merge branch 'master' of github.com:probablycorey/Atomicity

This commit is contained in:
Nathan Sobo
2012-01-06 19:57:35 -08:00
9 changed files with 117 additions and 59 deletions

View File

@@ -14,30 +14,14 @@ describe "App", ->
describe "open", ->
describe "when opening a filePath", ->
it "displays it in a new window", ->
it "displays it in a new window with the contents of the file loaded", ->
filePath = require.resolve 'fixtures/sample.txt'
expect(app.windows().length).toBe 0
app.open filePath
expect(app.windows().length).toBe 1
it "loads a buffer with filePath contents", ->
filePath = require.resolve 'fixtures/sample.txt'
app.open filePath
newWindow = app.windows()[0]
expect(newWindow.rootView.editor.buffer.url).toEqual filePath
expect(newWindow.rootView.editor.buffer.getText()).toEqual fs.read(filePath)
describe "when opening a dirPath", ->
it "loads an empty buffer", ->
dirPath = require.resolve 'fixtures'
app.open dirPath
newWindow = app.windows()[0]
expect(newWindow.rootView.editor.buffer.url).toBeUndefined
expect(newWindow.rootView.editor.buffer.getText()).toBe ""

View File

@@ -1,3 +1,4 @@
Buffer = require 'buffer'
Editor = require 'editor'
$ = require 'jquery'
ck = require 'coffeekup'
@@ -12,7 +13,6 @@ describe "Editor", ->
beforeEach ->
filePath = require.resolve 'fixtures/sample.txt'
tempFilePath = '/tmp/temp.txt'
spyOn(Editor.prototype.viewProperties, 'open').andCallThrough()
editor = Editor.build()
afterEach ->
@@ -29,41 +29,45 @@ describe "Editor", ->
editor.destroy()
expect(editor.aceEditor.destroy).toHaveBeenCalled()
describe "open(url)", ->
describe "when called with a url", ->
it "loads a buffer for the given url into the editor", ->
editor.open(filePath)
fileContents = fs.read(filePath)
expect(editor.getAceSession().getValue()).toBe fileContents
expect(editor.buffer.url).toBe(filePath)
expect(editor.buffer.getText()).toEqual fileContents
describe "setBuffer(buffer)", ->
it "sets the document on the aceSession", ->
buffer = new Buffer filePath
editor.setBuffer buffer
it "sets the mode on the session based on the file extension", ->
editor.open('something.js')
expect(editor.getAceSession().getMode().name).toBe 'javascript'
fileContents = fs.read(filePath)
expect(editor.getAceSession().getValue()).toBe fileContents
editor.open('something.text')
expect(editor.getAceSession().getMode().name).toBe 'text'
it "restores the ace edit session for a previously assigned buffer", ->
buffer = new Buffer filePath
editor.setBuffer buffer
describe "when called with null", ->
it "loads an empty buffer with no url", ->
editor.open()
expect(editor.getAceSession().getValue()).toBe ""
expect(editor.buffer.url).toBeUndefined()
expect(editor.buffer.getText()).toEqual ""
aceSession = editor.getAceSession()
editor.setBuffer new Buffer(tempFilePath)
expect(editor.getAceSession()).not.toBe(aceSession)
editor.setBuffer(buffer)
expect(editor.getAceSession()).toBe aceSession
it "sets the language mode based on the file extension", ->
buffer = new Buffer "something.js"
editor.setBuffer buffer
expect(editor.getAceSession().getMode().name).toBe 'javascript'
describe "when the text is changed via the ace editor", ->
it "updates the buffer text", ->
editor.open(filePath)
expect(editor.buffer.getText()).not.toMatch /^.ooo/
buffer = new Buffer(filePath)
editor.setBuffer(buffer)
expect(buffer.getText()).not.toMatch /^.ooo/
editor.getAceSession().insert {row: 0, column: 1}, 'ooo'
expect(editor.buffer.getText()).toMatch /^.ooo/
expect(buffer.getText()).toMatch /^.ooo/
describe "save", ->
describe "when the current buffer has a url", ->
beforeEach ->
editor.open tempFilePath
expect(editor.buffer.url).toBe tempFilePath
buffer = new Buffer(tempFilePath)
editor.setBuffer(buffer)
it "saves the current buffer to disk", ->
editor.buffer.setText 'Edited buffer!'

View File

@@ -14,3 +14,28 @@ describe "Project", ->
project.getFilePaths().done (result) ->
expect(result).toEqual(expectedPaths)
describe ".open(path)", ->
absolutePath = null
beforeEach ->
absolutePath = require.resolve('fixtures/dir/a')
it "always returns the same buffer for the same canonical path", ->
buffer = project.open(absolutePath)
expect(project.open(absolutePath)).toBe buffer
expect(project.open('a')).toBe buffer
describe "when given an absolute path", ->
it "returns a buffer for the given path", ->
expect(project.open(absolutePath).url).toBe absolutePath
describe "when given a relative path", ->
it "returns a buffer for the given path (relative to the project root)", ->
expect(project.open('a').url).toBe absolutePath
describe ".resolve(path)", ->
it "returns an absolute path based on the project's root", ->
absolutePath = require.resolve('fixtures/dir/a')
expect(project.resolve('a')).toBe absolutePath
expect(project.resolve(absolutePath + '/../a')).toBe absolutePath
expect(project.resolve('a/../a')).toBe absolutePath

View File

@@ -4,11 +4,13 @@ RootView = require 'root-view'
describe "RootView", ->
rootView = null
project = null
url = null
beforeEach ->
url = require.resolve 'fixtures/dir/a'
rootView = RootView.build {url}
project = rootView.project
describe "initialize", ->
describe "when called with a url that references a file", ->
@@ -49,11 +51,17 @@ describe "RootView", ->
rootView.toggleFileFinder()
expect(rootView.find('.file-finder')).not.toExist()
it "shows all urls for the current project", ->
it "shows all relative file paths for the current project", ->
waitsForPromise ->
rootView.toggleFileFinder()
runs ->
expect(rootView.fileFinder.urlList.children('li').length).toBe 3
waitsForPromise ->
project.getFilePaths().done (paths) ->
expect(rootView.fileFinder.urlList.children('li').length).toBe paths.length
for path in paths
relativePath = path.replace(project.url, '')
expect(rootView.fileFinder.urlList.find("li:contains(#{relativePath}):not(:contains(#{project.url}))")).toExist()
describe "when there is no project", ->
beforeEach ->
@@ -65,3 +73,14 @@ describe "RootView", ->
rootView.toggleFileFinder()
expect(rootView.find('.file-finder')).not.toExist()
describe "when a path is selected in the file finder", ->
it "opens the file associated with that path in the editor", ->
waitsForPromise -> rootView.toggleFileFinder()
runs ->
firstLi = rootView.fileFinder.find('li:first')
rootView.fileFinder.select()
expect(rootView.editor.buffer.url).toBe(project.url + firstLi.text())

View File

@@ -11,6 +11,12 @@ describe "fs", ->
expect(fs.directory(require.resolve('fixtures/dir'))).toBe require.resolve('fixtures/dir/')
expect(fs.directory(require.resolve('fixtures/dir/'))).toBe require.resolve('fixtures/dir/')
describe ".join(paths...)", ->
it "concatenates the given paths with the directory seperator", ->
expect(fs.join('a')).toBe 'a'
expect(fs.join('a', 'b', 'c')).toBe 'a/b/c'
expect(fs.join('/a/b/', 'c', 'd')).toBe '/a/b/c/d'
expect(fs.join('a', 'b/c/', 'd/')).toBe 'a/b/c/d/'
describe ".async", ->
describe ".listFiles(directoryPath, recursive)", ->
@@ -19,15 +25,13 @@ describe "fs", ->
describe "when recursive is true", ->
it "returns a promise that resolves to the recursive contents of that directory that are files", ->
waitsFor (complete) ->
waitsForPromise ->
fs.async.listFiles(directoryPath, true).done (result) ->
expect(result).toEqual (path for path in fs.list(directoryPath, true) when fs.isFile(path))
complete()
describe "when recursive is false", ->
it "returns a promise that resolves to the contents of that directory that are files", ->
waitsFor (complete) ->
waitsForPromise ->
fs.async.listFiles(directoryPath).done (result) ->
expect(result).toEqual (path for path in fs.list(directoryPath) when fs.isFile(path))
complete()

View File

@@ -12,11 +12,11 @@ class Editor extends Template
viewProperties:
aceEditor: null
buffer: null
editorElement: null
initialize: () ->
@aceSessions = {}
@buildAceEditor()
@open()
@setBuffer(new Buffer)
shutdown: ->
@destroy()
@@ -24,10 +24,11 @@ class Editor extends Template
destroy: ->
@aceEditor.destroy()
open: (url) ->
@buffer = new Buffer(url)
session = new EditSession(@buffer.aceDocument, @buffer.getMode())
@aceEditor.setSession(session)
setBuffer: (@buffer) ->
@aceEditor.setSession @getAceSessionForBuffer(buffer)
getAceSessionForBuffer: (buffer) ->
@aceSessions[@buffer.url] ?= new EditSession(@buffer.aceDocument, @buffer.getMode())
buildAceEditor: ->
@aceEditor = ace.edit this[0]

View File

@@ -1,9 +1,13 @@
fs = require 'fs'
Buffer = require 'buffer'
module.exports =
class Project
buffers: null
constructor: (@url) ->
@buffers = {}
getFilePaths: ->
projectUrl = @url
@@ -11,3 +15,11 @@ class Project
urls = (url.replace(projectUrl, "") for url in urls when fs.isFile(url))
urls
open: (filePath) ->
filePath = @resolve filePath
@buffers[filePath] ?= new Buffer(filePath)
resolve: (filePath) ->
filePath = fs.join(@url, filePath) unless filePath[0] == '/'
fs.absolute filePath

View File

@@ -2,6 +2,7 @@ $ = require 'jquery'
fs = require 'fs'
Template = require 'template'
Buffer = require 'buffer'
Editor = require 'editor'
FileFinder = require 'file-finder'
Project = require 'project'
@@ -23,7 +24,7 @@ class RootView extends Template
if url
@project = new Project(fs.directory(url))
@editor.open(url) if fs.isFile(url)
@editor.setBuffer(@project.open(url)) if fs.isFile(url)
addPane: (view) ->
pane = $('<div class="pane">')
@@ -37,7 +38,10 @@ class RootView extends Template
@fileFinder.remove()
@fileFinder = null
else
@project.getFilePaths().done (urls) =>
@fileFinder = FileFinder.build({urls, selected: (url) => @editor.open(url)})
@addPane(@fileFinder)
@project.getFilePaths().done (paths) =>
relativePaths = (path.replace(@project.url, "") for path in paths)
@fileFinder = FileFinder.build
urls: relativePaths
selected: (relativePath) => @editor.setBuffer(@project.open(relativePath))
@addPane @fileFinder
@fileFinder.input.focus()

View File

@@ -35,6 +35,11 @@ module.exports =
exists: (path) ->
OSX.NSFileManager.defaultManager.fileExistsAtPath_isDirectory path, null
join: (paths...) ->
return paths[0] if paths.length == 1
[first, rest...] = paths
first.replace(/\/?$/, "/") + @join(rest...)
# Returns true if the file specified by path exists and is a
# directory.
isDirectory: (path) ->