├── .github ├── ISSUE_TEMPLATE.md ├── dependabot.yml └── workflows │ └── main.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── keymaps └── project-view.cson ├── lib ├── project-view.coffee └── project.coffee ├── package-lock.json ├── package.json ├── screenshot-path-regex.png ├── screenshot-settings.png ├── screenshot.png ├── spec └── project-view-spec.coffee └── styles └── project-view.less /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --- 5 | 6 | 7 | Package Version: 8 | 9 | OS: 10 | Atom Version: 11 | Atom UI Theme: 12 | Atom Syntax Theme: 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | 9 | - package-ecosystem: "npm" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/atom/ci 2 | 3 | name: CI 4 | 5 | on: 6 | push: 7 | schedule: 8 | - cron: "0 0 * * *" 9 | 10 | env: 11 | CI: true 12 | 13 | jobs: 14 | Test: 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, windows-latest] 18 | channel: [stable, beta] 19 | runs-on: ${{ matrix.os }} 20 | steps: 21 | - uses: actions/checkout@v3 22 | - uses: UziTech/action-setup-atom@v2 23 | with: 24 | version: ${{ matrix.channel }} 25 | - name: Install dependencies 26 | run: apm install 27 | - name: Run tests 28 | run: atom --test spec 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Subesokun 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project View package 2 | 3 | > This project is no longer maintained as Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in the [official announcement](https://github.blog/2022-06-08-sunsetting-atom/). Thank you for your interest in this project and your support! 4 | 5 | [![Version](https://img.shields.io/apm/v/project-view.svg)](https://atom.io/packages/project-view) 6 | [![Downloads](https://img.shields.io/apm/dm/project-view.svg)](https://atom.io/packages/project-view) 7 | 8 | Shows project details in the Atom tree-view. 9 | 10 | ### Screenshots 11 | 12 | ![project-view Screenshot](https://github.com/subesokun/atom-project-view/blob/master/screenshot.png?raw=true) 13 | 14 | ![project-view Screenshot Settings](https://github.com/subesokun/atom-project-view/blob/master/screenshot-settings.png?raw=true) 15 | 16 | ### Installation 17 | 18 | ``` 19 | apm install project-view 20 | ``` 21 | 22 | ### Features 23 | 24 | * Replaces the Atom tree-view root folder name by the corresponding project name if available 25 | * Shows the project folder path next to the project name 26 | * Supported files to retrieve the project name (ordered by priority): 27 | * `package.json` (npm-like) 28 | * `.bower.json` (bower) 29 | * `composer.json` (Composer) 30 | 31 | #### Customize the project path via regex 32 | 33 | Via a regex you can easily shorten the project path or show other additional information that are useful for you. Furthermore you could also obfuscate the project path for more privacy. 34 | 35 | ![project-view Screenshot Project Path Regex](https://github.com/subesokun/atom-project-view/blob/master/screenshot-path-regex.png?raw=true) 36 | 37 | ### License 38 | 39 | MIT 40 | -------------------------------------------------------------------------------- /keymaps/project-view.cson: -------------------------------------------------------------------------------- 1 | '.platform-darwin': 2 | 'ctrl-?': 'project-view:toggle-path' 3 | 4 | '.platform-win32': 5 | 'ctrl-?': 'project-view:toggle-path' 6 | 7 | '.platform-linux': 8 | 'ctrl-?': 'project-view:toggle-path' 9 | -------------------------------------------------------------------------------- /lib/project-view.coffee: -------------------------------------------------------------------------------- 1 | {CompositeDisposable} = require 'atom' 2 | fs = require 'fs-plus' 3 | path = require 'path' 4 | Project = require './project' 5 | 6 | isRoot = (x) -> x && x.matches '[is=tree-view-directory].project-root' 7 | rootNodes = (x) -> Array.from(x).filter(isRoot) 8 | 9 | module.exports = ProjectView = 10 | config: 11 | displayPath: 12 | type: 'boolean' 13 | default: true 14 | description: 'Show the project path after project name in tree-view root.' 15 | regexMatch: 16 | type: 'string' 17 | default: '' 18 | description: 'Define a custom regex to match the parts in the project path that shall be replaced.' 19 | regexSubStr: 20 | type: 'string' 21 | default: '$&' 22 | description: 'If the regex matches, then substitute all matches with this string.' 23 | 24 | activate: -> 25 | @projectMap = {} 26 | # Events subscribed to in atom's system can be easily cleaned up with 27 | # a CompositeDisposable 28 | @subscriptions = new CompositeDisposable 29 | @subscriptions.add atom.packages.onDidActivateInitialPackages => 30 | @initProjectView() 31 | # Bind DOM mutation observer 32 | @observer = new MutationObserver((mutations) => 33 | added = [] 34 | added.push.apply added, rootNodes(m.addedNodes) for m in mutations 35 | if added.length > 0 36 | process.nextTick => @updateRoots() 37 | ) 38 | # Workaround for the isse that "onDidActivateInitialPackages" never gets 39 | # fired if one or more packages are failing to initialize 40 | @activateInterval = setInterval (=> 41 | @initProjectView() 42 | ), 1000 43 | @initProjectView() 44 | @subscriptions.add(atom.commands.add('atom-workspace', { 45 | 'project-view:toggle-path': -> 46 | atom.config.set('project-view.displayPath', !atom.config.get('project-view.displayPath')) 47 | })) 48 | 49 | initProjectView: -> 50 | if not @treeView? 51 | if atom.packages.getActivePackage('nuclide-tree-view')? 52 | treeViewPkg = atom.packages.getActivePackage('nuclide-tree-view') 53 | else if atom.packages.getActivePackage('tree-view')? 54 | treeViewPkg = atom.packages.getActivePackage('tree-view') 55 | 56 | @regexSubStr = atom.config.get('project-view.regexSubStr') 57 | @regexMatch = atom.config.get('project-view.regexMatch') 58 | @regex = new RegExp @regexMatch 59 | 60 | if treeViewPkg?.mainModule?.treeView? 61 | clearInterval(@activateInterval) 62 | @treeView = treeViewPkg.mainModule.treeView 63 | # Bind against events which are causing an update of the tree view 64 | @subscribeUpdateEvents() 65 | # Initally update the root names 66 | @updateRoots(@treeView.roots) 67 | 68 | deactivate: -> 69 | @observer?.disconnect() 70 | @subscriptions?.dispose() 71 | if @treeView? 72 | @clearRoots() 73 | @subscriptions = null 74 | @treeView = null 75 | @projectMap = null 76 | @regex = null 77 | @regexSubStr = '' 78 | @regexMatch = '' 79 | 80 | 81 | subscribeUpdateEvents: -> 82 | @subscriptions.add atom.project.onDidChangePaths => 83 | @updateRoots() 84 | @subscriptions.add atom.config.onDidChange 'tree-view.hideVcsIgnoredFiles', => 85 | @updateRoots() 86 | @subscriptions.add atom.config.onDidChange 'tree-view.hideIgnoredNames', => 87 | @updateRoots() 88 | @subscriptions.add atom.config.onDidChange 'core.ignoredNames', => 89 | @updateRoots() if atom.config.get('tree-view.hideIgnoredNames') 90 | @subscriptions.add atom.config.onDidChange 'tree-view.sortFoldersBeforeFiles', => 91 | @updateRoots() 92 | @subscriptions.add atom.config.onDidChange 'project-view.displayPath', => 93 | @updateRoots() 94 | @subscriptions.add atom.config.onDidChange 'project-view.regexMatch', => 95 | @regexMatch = atom.config.get('project-view.regexMatch') 96 | @regex = new RegExp @regexMatch 97 | @updateRoots() 98 | @subscriptions.add atom.config.onDidChange 'project-view.regexSubStr', => 99 | @regexSubStr = atom.config.get('project-view.regexSubStr') 100 | @updateRoots() 101 | @observer.observe(@treeView.list, { childList: true }); 102 | 103 | updateRoots: -> 104 | if not @treeView? 105 | return 106 | roots = @treeView.roots 107 | for root in roots 108 | rootPath = root.getPath() 109 | project = @projectMap[rootPath] 110 | if not project? 111 | project = new Project(root) 112 | @projectMap[rootPath] = project 113 | # Bind for name changes and activate watcher 114 | project.onDidChange 'name', ({root, name}) => 115 | @updateProjectRoot(root.getPath(), name) 116 | project.watch() 117 | if project.projectName 118 | # Project name has been already cached 119 | @updateProjectRoot(rootPath, project.projectName) 120 | else 121 | # Find the project name as it hasn't been cached yet 122 | project.findProjectName().then ({_, name}) => 123 | @updateProjectRoot(rootPath, name) 124 | .catch (error) -> 125 | console.error(error, error.stack) 126 | # Clean up removed projects 127 | projectsToRemove = [] 128 | for rootPath, project of @projectMap 129 | if not @findRootByPath(rootPath)? 130 | projectsToRemove.push(rootPath) 131 | for rootPath in projectsToRemove 132 | @projectMap[rootPath]?.destroy() 133 | delete @projectMap[rootPath] 134 | 135 | findRootByPath: (rootPath) -> 136 | for root in @treeView.roots 137 | if rootPath is root.getPath() 138 | return root 139 | 140 | clearRoots: -> 141 | roots = @treeView.roots 142 | for root in roots 143 | project = @projectMap[root.getPath()] 144 | if project? 145 | project.destroy() 146 | root.directoryName.textContent = root.directoryName.dataset.name 147 | root.directoryName.classList.remove('project-view') 148 | directoryPath = root.header.querySelector('.project-view-path') 149 | root.header.removeChild(directoryPath) if directoryPath? 150 | delete root.directoryPath 151 | @projectMap = {} 152 | 153 | updateProjectRoot: (rootPath, name) -> 154 | root = @findRootByPath(rootPath) 155 | if name? 156 | root.directoryName.textContent = name 157 | root.directoryName.classList.add('project-view') 158 | else 159 | root.directoryName.textContent = root.directoryName.dataset.name 160 | root.directoryName.classList.remove('project-view') 161 | if not root.directoryPath? 162 | root.directoryPath = document.createElement('span') 163 | root.header.appendChild(root.directoryPath) 164 | root.directoryPath.classList.add('name','project-view-path','status-ignored') 165 | if atom.config.get 'project-view.displayPath' 166 | root.directoryPath.textContent = '(' + @shortenRootPath(root.directory.path) + ')' 167 | else 168 | root.directoryPath.textContent = '' 169 | 170 | shortenRootPath: (rootPath) -> 171 | # Shorten root path if possible 172 | userHome = fs.getHomeDirectory() 173 | normRootPath = path.normalize(rootPath) 174 | 175 | if @regexMatch isnt '' 176 | replacedPath = normRootPath.replace(@regex, @regexSubStr) 177 | return replacedPath if replacedPath isnt normRootPath 178 | 179 | if normRootPath.indexOf(userHome) is 0 180 | # Use also tilde in case of Windows as synonym for the home folder 181 | return '~' + normRootPath.substring(userHome.length) 182 | else 183 | return normRootPath 184 | -------------------------------------------------------------------------------- /lib/project.coffee: -------------------------------------------------------------------------------- 1 | {Emitter} = require 'atom' 2 | path = require 'path' 3 | fs = require 'fs-plus' 4 | 5 | class Project 6 | 7 | constructor: (@root) -> 8 | @emitter = new Emitter 9 | @projectName = null 10 | @trackedFile = null 11 | 12 | destroy: -> 13 | @unwatch() 14 | @projectName = null 15 | @trackedFile = null 16 | @emitter?.dispose() 17 | @emitter = null 18 | 19 | unwatch: -> 20 | if @watchSubscription? 21 | @watchSubscription.close() 22 | @watchSubscription = null 23 | 24 | watch: -> 25 | if not @watchSubscription? 26 | try 27 | @watchSubscription = fs.watch @root.getPath(), (event, filename) => 28 | if event is 'change' 29 | @findProjectName() if filename is @trackedFile 30 | else 31 | @findProjectName() 32 | 33 | onDidChange: (eventType, callback) -> 34 | @emitter.on eventType, callback 35 | 36 | findProjectName: -> 37 | rootPath = @root.getPath() 38 | return new Promise (resolve, reject) -> 39 | fs.readdir rootPath, (error, files) -> 40 | resolve(files) 41 | .then (files) => 42 | return if not files? 43 | if files.indexOf('package.json') isnt -1 44 | pkgFile = path.join rootPath, 'package.json' 45 | @trackedFile = 'package.json' 46 | return @getPropertyFromPackageJson(pkgFile, 'name') 47 | else if files.indexOf('bower.json') isnt -1 48 | pkgFile = path.join rootPath, 'bower.json' 49 | @trackedFile = 'bower.json' 50 | return @getPropertyFromPackageJson(pkgFile, 'name') 51 | else if files.indexOf('composer.json') isnt -1 52 | pkgFile = path.join rootPath, 'composer.json' 53 | @trackedFile = 'composer.json' 54 | return @getPropertyFromPackageJson(pkgFile, 'name') 55 | else 56 | @trackedFile = null 57 | return 58 | .then (name) => 59 | result = {root: @root, name: name} 60 | @projectName = name 61 | @emitter.emit 'name', result 62 | return result 63 | 64 | getProjectName: -> 65 | return @projectName 66 | 67 | getPropertyFromPackageJson: (rootPath, property) -> 68 | return new Promise (resolve, reject) -> 69 | fs.readFile rootPath, 'utf8', (error, data) -> 70 | if error 71 | resolve(null) 72 | try 73 | pkgData = JSON.parse(data) 74 | if pkgData[property] 75 | resolve(pkgData[property]) 76 | else 77 | resolve(null) 78 | catch error 79 | resolve(null) 80 | 81 | module.exports = Project 82 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-view", 3 | "version": "0.6.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "async": { 8 | "version": "1.5.2", 9 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 10 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" 11 | }, 12 | "balanced-match": { 13 | "version": "1.0.0", 14 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 15 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 16 | }, 17 | "brace-expansion": { 18 | "version": "1.1.11", 19 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 20 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 21 | "requires": { 22 | "balanced-match": "^1.0.0", 23 | "concat-map": "0.0.1" 24 | } 25 | }, 26 | "concat-map": { 27 | "version": "0.0.1", 28 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 29 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 30 | }, 31 | "fs-plus": { 32 | "version": "3.1.1", 33 | "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.1.1.tgz", 34 | "integrity": "sha512-Se2PJdOWXqos1qVTkvqqjb0CSnfBnwwD+pq+z4ksT+e97mEShod/hrNg0TRCCsXPbJzcIq+NuzQhigunMWMJUA==", 35 | "requires": { 36 | "async": "^1.5.2", 37 | "mkdirp": "^0.5.1", 38 | "rimraf": "^2.5.2", 39 | "underscore-plus": "1.x" 40 | } 41 | }, 42 | "fs.realpath": { 43 | "version": "1.0.0", 44 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 45 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 46 | }, 47 | "glob": { 48 | "version": "7.1.6", 49 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 50 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 51 | "requires": { 52 | "fs.realpath": "^1.0.0", 53 | "inflight": "^1.0.4", 54 | "inherits": "2", 55 | "minimatch": "^3.0.4", 56 | "once": "^1.3.0", 57 | "path-is-absolute": "^1.0.0" 58 | } 59 | }, 60 | "inflight": { 61 | "version": "1.0.6", 62 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 63 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 64 | "requires": { 65 | "once": "^1.3.0", 66 | "wrappy": "1" 67 | } 68 | }, 69 | "inherits": { 70 | "version": "2.0.4", 71 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 72 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 73 | }, 74 | "minimatch": { 75 | "version": "3.0.4", 76 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 77 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 78 | "requires": { 79 | "brace-expansion": "^1.1.7" 80 | } 81 | }, 82 | "minimist": { 83 | "version": "1.2.6", 84 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 85 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" 86 | }, 87 | "mkdirp": { 88 | "version": "0.5.5", 89 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 90 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 91 | "requires": { 92 | "minimist": "^1.2.5" 93 | } 94 | }, 95 | "once": { 96 | "version": "1.4.0", 97 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 98 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 99 | "requires": { 100 | "wrappy": "1" 101 | } 102 | }, 103 | "path-is-absolute": { 104 | "version": "1.0.1", 105 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 106 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 107 | }, 108 | "rimraf": { 109 | "version": "2.7.1", 110 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 111 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 112 | "requires": { 113 | "glob": "^7.1.3" 114 | } 115 | }, 116 | "underscore": { 117 | "version": "1.13.1", 118 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", 119 | "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" 120 | }, 121 | "underscore-plus": { 122 | "version": "1.7.0", 123 | "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.7.0.tgz", 124 | "integrity": "sha512-A3BEzkeicFLnr+U/Q3EyWwJAQPbA19mtZZ4h+lLq3ttm9kn8WC4R3YpuJZEXmWdLjYP47Zc8aLZm9kwdv+zzvA==", 125 | "requires": { 126 | "underscore": "^1.9.1" 127 | } 128 | }, 129 | "wrappy": { 130 | "version": "1.0.2", 131 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 132 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-view", 3 | "main": "./lib/project-view", 4 | "version": "0.6.5", 5 | "description": "Show project details in the Atom tree-view", 6 | "repository": "https://github.com/subesokun/atom-project-view", 7 | "license": "MIT", 8 | "engines": { 9 | "atom": ">=0.174.0 <2.0.0" 10 | }, 11 | "dependencies": { 12 | "fs-plus": "^3.1.1" 13 | }, 14 | "keywords": [ 15 | "project", 16 | "productivity", 17 | "settings" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /screenshot-path-regex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subesokun/atom-project-view/df853472bb33a94b052882daab62a17e57f555de/screenshot-path-regex.png -------------------------------------------------------------------------------- /screenshot-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subesokun/atom-project-view/df853472bb33a94b052882daab62a17e57f555de/screenshot-settings.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/subesokun/atom-project-view/df853472bb33a94b052882daab62a17e57f555de/screenshot.png -------------------------------------------------------------------------------- /spec/project-view-spec.coffee: -------------------------------------------------------------------------------- 1 | ProjectView = require '../lib/project-view' 2 | 3 | # Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. 4 | # 5 | # To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` 6 | # or `fdescribe`). Remove the `f` to unfocus the block. 7 | 8 | describe "ProjectView", -> 9 | [workspaceElement, activationPromise] = [] 10 | 11 | beforeEach -> 12 | workspaceElement = atom.views.getView(atom.workspace) 13 | activationPromise = atom.packages.activatePackage('project-view') 14 | -------------------------------------------------------------------------------- /styles/project-view.less: -------------------------------------------------------------------------------- 1 | // The ui-variables file is provided by base themes provided by Atom. 2 | // 3 | // See https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less 4 | // for a full listing of what's available. 5 | @import "ui-variables"; 6 | 7 | .list-item { 8 | .name.project-view { 9 | font-weight: bold; 10 | } 11 | 12 | .name.project-view:not(:first-child) { 13 | margin-left: 5px; 14 | } 15 | 16 | .name.project-view-path { 17 | margin-left: 5px; 18 | } 19 | } 20 | --------------------------------------------------------------------------------