diff --git a/extensions-to-port/project/index.coffee b/extensions-to-port/project/index.coffee
deleted file mode 100644
index e677baaf7..000000000
--- a/extensions-to-port/project/index.coffee
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = Project = require 'project/project'
diff --git a/extensions-to-port/project/project.coffee b/extensions-to-port/project/project.coffee
deleted file mode 100644
index d8453d27f..000000000
--- a/extensions-to-port/project/project.coffee
+++ /dev/null
@@ -1,45 +0,0 @@
-_ = require 'underscore'
-
-File = require 'fs'
-Extension = require 'extension'
-ProjectPane = require 'project/projectpane'
-
-module.exports =
-class Project extends Extension
- keymap: ->
- 'Command-Ctrl-N': -> @pane.toggle()
-
- storageNamespace: ->
- @.constructor.name + @window.path
-
- constructor: (args...) ->
- super args...
-
- @pane = new ProjectPane @window, @
- @pane.toggle()
-
- @window.on 'open', ({filename}) =>
- if File.isDirectory filename
- @pane.reload filename # I don't think this can ever happen.
- else
- openedPaths = @get 'openedPaths', []
- if not _.include openedPaths, filename
- openedPaths.push filename
- @set 'openedPaths', openedPaths
-
- @window.on 'close', ({filename}) =>
- if File.isFile filename
- openedPaths = @get 'openedPaths', []
- openedPaths = _.without openedPaths, filename
- @set 'openedPaths', openedPaths
-
- load: ->
- # Reopen files (remove ones that no longer exist)
- openedPaths = @get 'openedPaths', []
- for path in openedPaths
- if File.isFile path
- @window.open path
- else if not File.exists path
- openedPaths = _.without openedPaths, path
- @set 'openedPaths', openedPaths
-
diff --git a/extensions-to-port/project/projectpane.coffee b/extensions-to-port/project/projectpane.coffee
deleted file mode 100644
index 83d82cfcc..000000000
--- a/extensions-to-port/project/projectpane.coffee
+++ /dev/null
@@ -1,71 +0,0 @@
-$ = require 'jquery'
-_ = require 'underscore'
-
-File = require 'fs'
-Pane = require 'pane'
-
-module.exports =
-class ProjectPane extends Pane
- position: 'left'
-
- project: null
-
- html: $ require "project/project.html"
-
- constructor: (@window, @project) ->
- super @window
-
- @reload()
-
- $('#project li').live 'click', (event) =>
- return true if event.__projectClicked__
-
- $('#project .active').removeClass 'active'
- el = $(event.currentTarget)
- path = decodeURIComponent el.attr 'path'
- if File.isDirectory path
- openedPaths = @project.get 'openedPaths', []
- if el.hasClass 'open'
- openedPaths = _.without openedPaths, path
- el.removeClass 'open'
- el.children("ul").remove()
- else
- openedPaths.push path unless _.include openedPaths, path
- el.addClass 'open'
- list = @createList path
- el.append list
-
- @project.set 'openedPaths', openedPaths
- else
- el.addClass 'active'
- @window.open path
-
- # HACK I need the event to propogate beyond the project pane,
- # but I need the project pane to ignore it. Need somehting
- # cleaner here.
- event.__projectClicked__ = true
-
- true
-
- reload: ->
- @html.children('#project .cwd').text _.last @window.path.split '/'
- fileList = @createList @window.path
- fileList.addClass('files')
- @html.children('#project .files').replaceWith(fileList)
-
- createList: (root) ->
- paths = File.list root
-
- list = $('
')
- for path in paths
- filename = path.replace(root, "").substring 1
- type = if File.isDirectory path then 'dir' else 'file'
- encodedPath = encodeURIComponent path
- listItem = $("- #{filename}
")
- openedPaths = @project.get 'openedPaths', []
- if _.include(openedPaths, path) and type == 'dir'
- listItem.append @createList path
- listItem.addClass "open"
- list.append listItem
-
- list
diff --git a/extensions/tabs/tabs.coffee b/extensions/tabs/tabs.coffee
index 96a97cd95..17a6a3dc0 100644
--- a/extensions/tabs/tabs.coffee
+++ b/extensions/tabs/tabs.coffee
@@ -3,7 +3,7 @@ $ = require 'jquery'
Extension = require 'extension'
KeyBinder = require 'key-binder'
Event = require 'event'
-TabsPane = require 'tabs/tabspane'
+TabsPane = require 'tabs/tabs-pane'
fs = require 'fs'
diff --git a/extensions/tabs/tabsPane.coffee b/extensions/tabs/tabsPane.coffee
deleted file mode 100644
index 2e51b0487..000000000
--- a/extensions/tabs/tabsPane.coffee
+++ /dev/null
@@ -1,57 +0,0 @@
-$ = require 'jquery'
-_ = require 'underscore'
-
-Pane = require 'pane'
-
-module.exports =
-class TabsPane extends Pane
- position: 'top'
-
- html: $ require 'tabs/tabs.html'
-
- constructor: ->
- # Style html
- @html.parents('.pane').css height: 'inherit'
- css = $('').html require 'tabs/tabs.css'
- $('head').append css
-
- # click tab
- tabPane = this
- $('#tabs ul li').live 'mousedown', ->
- tabPane.switchToTab this
- false
-
- nextTab: ->
- @switchToTab $('#tabs ul .active').next()
-
- prevTab: ->
- @switchToTab $('#tabs ul .active').prev()
-
- switchToTab: (tab) ->
- tab = $("#tabs ul li").get(tab - 1) if _.isNumber tab
- return if tab.length is 0
-
- $("#tabs ul .active").removeClass("active")
- $(tab).addClass 'active'
- window.editor.focusBuffer $(tab).data 'path'
-
- addTab: (path) ->
- existing = $("#tabs [data-path='#{path}']")
- if existing.length
- return @switchToTab existing
-
- name = if path then _.last path.split '/' else "untitled"
- $("#tabs ul .active").removeClass()
- $("#tabs ul").append """
- - #{name}
- """
- $("#tabs ul li:last").addClass 'active'
-
- removeTab: (path) ->
- tab = $("#tabs li[data-path='#{path}']")
- if tab.hasClass("active")
- nextTab = tab.next()
- nextTab = tab.prev() if nextTab.length == 0
- @switchToTab nextTab if nextTab.length != 0
-
- tab.remove()
diff --git a/extensions-to-port/project/images/dir-toggle.png b/extensions/tree/images/dir-toggle.png
similarity index 100%
rename from extensions-to-port/project/images/dir-toggle.png
rename to extensions/tree/images/dir-toggle.png
diff --git a/extensions/tree/index.coffee b/extensions/tree/index.coffee
new file mode 100644
index 000000000..bf78b0cdd
--- /dev/null
+++ b/extensions/tree/index.coffee
@@ -0,0 +1 @@
+module.exports = Tree = require 'tree/tree'
diff --git a/extensions/tree/key-bindings.coffee b/extensions/tree/key-bindings.coffee
new file mode 100644
index 000000000..8cc62b428
--- /dev/null
+++ b/extensions/tree/key-bindings.coffee
@@ -0,0 +1,2 @@
+tree:
+ 'cmd-ctrl-n': (tree) -> tree.pane.toggle()
diff --git a/extensions/tree/tree-pane.coffee b/extensions/tree/tree-pane.coffee
new file mode 100644
index 000000000..0212fe7ae
--- /dev/null
+++ b/extensions/tree/tree-pane.coffee
@@ -0,0 +1,73 @@
+$ = require 'jquery'
+_ = require 'underscore'
+
+fs = require 'fs'
+
+Pane = require 'pane'
+
+module.exports =
+class TreePane extends Pane
+ position: 'left'
+
+ tree: null
+
+ html: $ require "tree/tree.html"
+
+ constructor: (@tree) ->
+ @reload()
+
+ $('#tree li').live 'click', (event) =>
+ return true if event.__treeClicked__
+
+ $('#tree .active').removeClass 'active'
+
+ el = $(event.currentTarget)
+ path = decodeURIComponent el.data 'path'
+
+ if fs.isDirectory path
+ window.x = @tree
+ openedDirs = @tree.getOpenedDirs()
+ if el.hasClass 'open'
+ openedDirs = _.without openedDirs, path
+ el.removeClass 'open'
+ el.children("ul").remove()
+ else
+ openedDirs.push path unless path in openedDirs
+ el.addClass 'open'
+ list = @createList path
+ el.append list
+ @tree.setOpenedDirs openedDirs
+ else
+ el.addClass 'active'
+ window.open path
+
+ # HACK I need the event to propogate beyond the tree pane,
+ # but I need the tree pane to ignore it. Need somehting
+ # cleaner here.
+ event.__treeClicked__ = true
+
+ true
+
+ reload: ->
+ @html.children('#tree .cwd').text _.last atomController.path.split '/'
+ fileList = @createList atomController.path
+ fileList.addClass 'files'
+ @html.children('#tree .files').replaceWith fileList
+
+ createList: (root) ->
+ paths = fs.list root
+
+ list = $('')
+ for path in paths
+ filename = path.replace(root, "").substring 1
+ type = if fs.isDirectory path then 'dir' else 'file'
+ encodedPath = encodeURIComponent path
+ listItem = $("- #{filename}
")
+ openedDirs = @tree.getOpenedDirs()
+
+ if path in openedDirs and fs.isDirectory path
+ listItem.append @createList path
+ listItem.addClass "open"
+ list.append listItem
+
+ list
diff --git a/extensions/tree/tree.coffee b/extensions/tree/tree.coffee
new file mode 100644
index 000000000..2c37852b6
--- /dev/null
+++ b/extensions/tree/tree.coffee
@@ -0,0 +1,35 @@
+_ = require 'underscore'
+
+Event = require 'event'
+Extension = require 'extension'
+KeyBinder = require 'key-binder'
+Storage = require 'storage'
+TreePane = require 'tree/tree-pane'
+
+fs = require 'fs'
+
+module.exports =
+class Tree extends Extension
+ constructor: ->
+ KeyBinder.register "tree", @
+ KeyBinder.load require.resolve "tree/key-bindings.coffee"
+
+ # Remove dirs that no longer exist
+ openedPaths = @getOpenedDirs()
+ for dir in openedPaths when not fs.exists dir
+ openedDirs = _.without openedDirs, path
+ @setOpenedDirs openedDirs
+
+ @pane = new TreePane @
+
+ storageNamespace: ->
+ @.constructor.name + ":" + atomController.path
+
+ getOpenedDirs: ->
+ Storage.get @storageNamespace() + ':openedDirs', []
+
+ setOpenedDirs: (value) ->
+ Storage.set @storageNamespace() + ':openedDirs', value
+
+ startup: ->
+ @pane.show()
diff --git a/extensions-to-port/project/project.html b/extensions/tree/tree.html
similarity index 74%
rename from extensions-to-port/project/project.html
rename to extensions/tree/tree.html
index db3695c1c..c4e5705e2 100644
--- a/extensions-to-port/project/project.html
+++ b/extensions/tree/tree.html
@@ -1,5 +1,5 @@
-
+
diff --git a/src/extension.coffee b/src/extension.coffee
index cb3bd0975..88c0f2206 100644
--- a/src/extension.coffee
+++ b/src/extension.coffee
@@ -3,6 +3,8 @@ fs = require 'fs'
module.exports =
class Extension
+ pane: null
+
constructor: ->
console.log "#{@constructor.name}: Loaded"
@@ -11,33 +13,3 @@ class Extension
startup: ->
shutdown: ->
-
- pane: ->
-
- # This should be stored keyed on the window path I think? But what if the path
- # changes?
- get: (key, defaultValue) ->
- try
- object = JSON.parse(localStorage[@storageNamespace()] ? "{}")
- catch error
- error.message += "\nGetting #{key}"
- console.error(error)
-
- object[key] ? defaultValue
-
- set: (key, value) ->
- try
- object = JSON.parse(localStorage[@storageNamespace()] ? "{}")
- catch error
- error.message += "\nSetting #{key}: #{value}"
- console.error(error)
-
- if value == undefined
- delete object[key]
- else
- object[key] = value
-
- localStorage[@storageNamespace()] = JSON.stringify(object)
-
-
-
diff --git a/src/storage.coffee b/src/storage.coffee
index 62f851314..283123084 100644
--- a/src/storage.coffee
+++ b/src/storage.coffee
@@ -2,12 +2,12 @@ module.exports =
class Storage
@get: (key, defaultValue) ->
try
- object = JSON.parse(localStorage[key] ? "{}")
+ value = JSON.parse(localStorage[key] ? null) ? defaultValue
catch error
error.message += "\nGetting #{key}"
console.error(error)
- object ? defaultValue
+ value
@set: (key, value) ->
if value == undefined