diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..155b060 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +npm-debug.log +node_modules +*.iml +.idea/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7a6bc05 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "lib/tree-view"] + path = lib/tree-view + url = git://github.com/atom/tree-view.git +[submodule "lib/tabs"] + path = lib/tabs + url = git://github.com/atom/tabs.git diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c3d858c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 - First Release +* Every feature added +* Every bug fixed diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..7ce8c08 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2014 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ebe95e --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# sublime-tabs package + +A short description of your package. + +![A screenshot of your spankin' package](https://f.cloud.github.com/assets/69169/2290250/c35d867a-a017-11e3-86be-cd7c5bf3ff9b.gif) diff --git a/lib/sublime-tab-bar-view.coffee b/lib/sublime-tab-bar-view.coffee new file mode 100644 index 0000000..b98e4a4 --- /dev/null +++ b/lib/sublime-tab-bar-view.coffee @@ -0,0 +1,20 @@ +BrowserWindow = null # Defer require until actually used +RendererIpc = require('ipc') + +{$} = require 'atom' +_ = require 'underscore-plus' +TabBarView = require './tabs/lib/tab-bar-view' +SublimeTabView = require './sublime-tab-view' + +module.exports = +class SublimeTabBarView extends TabBarView + + initialize: (@pane) -> + super(@pane) + + addTabForItem: (item, index) -> + for tab in @getTabs() + @closeTab(tab) if tab.is('.temp') + + tab.updateTitle() for tab in @getTabs() + @insertTabAtIndex(new SublimeTabView(item, @pane), index) diff --git a/lib/sublime-tab-view.coffee b/lib/sublime-tab-view.coffee new file mode 100644 index 0000000..d7983d2 --- /dev/null +++ b/lib/sublime-tab-view.coffee @@ -0,0 +1,21 @@ +{$} = require 'atom' +_ = require 'underscore-plus' +path = require 'path' +TabView = require './tabs/lib/tab-view' + +module.exports = +class SublimeTabView extends TabView + + initialize: (@item, @pane) -> + super(@item, @pane) + @addClass('temp') + + updateModifiedStatus: -> + if @item.isModified?() + console.log "modified: #{@item.isModified?()} : #{@is('.temp')}" + @addClass('modified') unless @isModified + @removeClass('temp') if @is('.temp') + @isModified = true + else + @removeClass('modified') if @isModified + @isModified = false diff --git a/lib/sublime-tabs.coffee b/lib/sublime-tabs.coffee new file mode 100644 index 0000000..e9e1a78 --- /dev/null +++ b/lib/sublime-tabs.coffee @@ -0,0 +1,22 @@ +SublimeTabBarView = require './sublime-tab-bar-view' +_ = require 'underscore-plus' + +module.exports = + configDefaults: + showIcons: true + + activate: -> + @paneSubscription = atom.workspaceView.eachPaneView (paneView) => + tabBarView = new SublimeTabBarView(paneView) + @tabBarViews ?= [] + @tabBarViews.push(tabBarView) + onPaneViewRemoved = (event, removedPaneView) => + return unless paneView is removedPaneView + _.remove(@tabBarViews, tabBarView) + atom.workspaceView.off('pane:removed', onPaneViewRemoved) + atom.workspaceView.on('pane:removed', onPaneViewRemoved) + tabBarView + + deactivate: -> + @paneSubscription?.off() + tabBarView.remove() for tabBarView in @tabBarViews ? [] diff --git a/lib/tabs b/lib/tabs new file mode 160000 index 0000000..47fc97d --- /dev/null +++ b/lib/tabs @@ -0,0 +1 @@ +Subproject commit 47fc97de75b3622c4d97bd38248601b27f85af8e diff --git a/menus/sublime-tabs.cson b/menus/sublime-tabs.cson new file mode 120000 index 0000000..811b319 --- /dev/null +++ b/menus/sublime-tabs.cson @@ -0,0 +1 @@ +../lib/tabs/menus/tabs.cson \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..38e41e1 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "sublime-tabs", + "main": "./lib/sublime-tabs", + "version": "0.0.0", + "description": "Sublime style tabs", + "repository": "https://github.com/ddavison/sublime-tabs", + "license": "MIT", + "private": true, + "engines": { + "atom": ">0.50.0" + }, + "dependencies": { + "fs-plus": "^2.0.4", + "runas": "~0.5.4", + "temp": "~0.6.0", + "theorist": "1.x", + "underscore-plus": "1.x", + "wrench": "1.5.x" + } +} diff --git a/spec/sublime-tabs-spec.coffee b/spec/sublime-tabs-spec.coffee new file mode 100644 index 0000000..b1328cf --- /dev/null +++ b/spec/sublime-tabs-spec.coffee @@ -0,0 +1,30 @@ +{WorkspaceView} = require 'atom' +SublimeTabs = require '../lib/sublime-tabs' + +# Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. +# +# To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` +# or `fdescribe`). Remove the `f` to unfocus the block. + +describe "SublimeTabs", -> + activationPromise = null + + beforeEach -> + atom.workspaceView = new WorkspaceView + activationPromise = atom.packages.activatePackage('sublime-tabs') + + describe "when the sublime-tabs:toggle event is triggered", -> + it "attaches and then detaches the view", -> + expect(atom.workspaceView.find('.sublime-tabs')).not.toExist() + + # This is an activation event, triggering it will cause the package to be + # activated. + atom.workspaceView.trigger 'sublime-tabs:toggle' + + waitsForPromise -> + activationPromise + + runs -> + expect(atom.workspaceView.find('.sublime-tabs')).toExist() + atom.workspaceView.trigger 'sublime-tabs:toggle' + expect(atom.workspaceView.find('.sublime-tabs')).not.toExist() diff --git a/spec/sublime-tabs-view-spec.coffee b/spec/sublime-tabs-view-spec.coffee new file mode 100644 index 0000000..6383141 --- /dev/null +++ b/spec/sublime-tabs-view-spec.coffee @@ -0,0 +1,5 @@ +SublimeTabsView = require '../lib/sublime-tabs-view' + +describe "SublimeTabsView", -> + it "has one valid test", -> + expect("life").toBe "easy" diff --git a/stylesheets/sublime-tabs.less b/stylesheets/sublime-tabs.less new file mode 100644 index 0000000..83a999a --- /dev/null +++ b/stylesheets/sublime-tabs.less @@ -0,0 +1,99 @@ +// @import url(lib/tabs/stylesheets/tabs) - todo: how to import?! +// in the meantime, just use tabs stylesheet. +@import "ui-variables"; +@import "octicon-mixins"; + +@close-icon-size: 12px; + +.temp { + font-style: italic; +} + +.tab-bar { + display: -webkit-flex; + -webkit-user-select: none; + margin: 0; + + .tab { + font-size: 11px; + position: relative; + padding-left: 10px; + padding-right: 10px + @close-icon-size + 2px; + -webkit-user-drag: element; + -webkit-flex: 1; + max-width: 175px; + min-width: 40px; + + &.active { + -webkit-flex: 2; + min-width: -webkit-fit-content; + + .title { + padding-right: 10px; + } + } + + .title { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .hide-icon { + &.icon:before { + display: none; + } + } + + .close-icon { + .octicon(x, @close-icon-size); + position: absolute; + top: 1px; + right: 10px; + cursor: default; + } + + &.modified:hover .close-icon { + color: @background-color-info; + } + + &.modified:not(:hover) .close-icon { + &:before { content: "" } + top: 11px; + right: 11px; + width: 8px; + height: 8px; + border: 2px solid @background-color-info; + border-radius: 12px; + } + } + + /* Drag and Drop */ + .placeholder { + position: absolute; + top: 0; + z-index: 999; + display: inline-block; + width: 2px; + margin: -1px; padding: 0; + + height: @tab-height; + display: inline-block; + background: @background-color-info; + + list-style: none; + + &:after { + content: ""; + position: absolute; + top: @tab-height; + margin: -1px; + z-index: 9999; + width: 4px; + height: 4px; + background: @background-color-info; + border-radius: 4px; + border: 1px solid transparent; + } + } +}