Comparar commits
120 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| a8b5960bc0 | |||
| 70e3484a16 | |||
| 5ac3f58cdb | |||
| 692f6947f2 | |||
| 08fad809d2 | |||
| ba63239928 | |||
| d90c8c0fb7 | |||
| 35e782f05d | |||
| 00af9a93d7 | |||
| 018e22ad8d | |||
| f73d3df233 | |||
| 25b44ceb1a | |||
| c28ecf1a7d | |||
| 478e80e585 | |||
| 08be377004 | |||
| 4db3e47377 | |||
| 76857b4486 | |||
| e743d93d6d | |||
| f443c375d4 | |||
| b9b488bee2 | |||
| e192922f0e | |||
| d1c41fbf68 | |||
| aa8b97a039 | |||
| 5276cb716a | |||
| 03f8a32f86 | |||
| eabb498af7 | |||
| a1e4c0bb05 | |||
| 6a285b695f | |||
| 7f66a2fca4 | |||
| 6565f6d608 | |||
| 493035fe4e | |||
| 6e30998ef5 | |||
| 825c4f6098 | |||
| b4756aa9b7 | |||
| 651fa1aa42 | |||
| db17fe2daa | |||
| 1e0c839257 | |||
| 18481789b0 | |||
| 304f63532e | |||
| 6e7364c7c6 | |||
| 339f331776 | |||
| 32275b27a3 | |||
| 5c730415b7 | |||
| 637b2b0aba | |||
| b4246a2f07 | |||
| 31170dcfae | |||
| f784b51f12 | |||
| 3c6dab22d8 | |||
| e80f5acd50 | |||
| 90aca1c6ad | |||
| c7771ffde9 | |||
| bdfc862dac | |||
| 2c7aa170e9 | |||
| 6c8d624e73 | |||
| 57a876e677 | |||
| 20adc96e4c | |||
| d508d1eedf | |||
| 2949ebfe86 | |||
| dbaef8e593 | |||
| 3edd2f9590 | |||
| f2652bcb40 | |||
| d6c8ec83d4 | |||
| b4b492a321 | |||
| ba6a976013 | |||
| d0486cc923 | |||
| fb09f28c4c | |||
| 883c48b490 | |||
| ceefc15b15 | |||
| a0cc63273c | |||
| c328092463 | |||
| b1a3d89af3 | |||
| bd92acba7e | |||
| d90daf07f8 | |||
| 388428b074 | |||
| f439d0d996 | |||
| 4142845632 | |||
| 60c5293b5e | |||
| a1b4820c04 | |||
| 1cf8479831 | |||
| a14d57ceac | |||
| c1d5d96aca | |||
| b5632b6988 | |||
| fe02442b23 | |||
| 04ceaf36bf | |||
| 08d183dff1 | |||
| 134daa1fe2 | |||
| 360fbe2a3f | |||
| 8148446a86 | |||
| 16f56a068b | |||
| 11112cb374 | |||
| 5c7177746c | |||
| ab947ba87a | |||
| 8a4db34cb8 | |||
| 669088612c | |||
| 0a14d232d2 | |||
| 651fe5d71c | |||
| 7d49d50b34 | |||
| aab51d15ab | |||
| 1926156eee | |||
| b12a6abc90 | |||
| 46762c293f | |||
| 6b8ef25c8e | |||
| 03a769b516 | |||
| 229e7e03b2 | |||
| 45ee6df36e | |||
| 9422a8047a | |||
| 85456ad920 | |||
| 2f3d54db8a | |||
| bae903a772 | |||
| aabf4dfbab | |||
| 44327724a8 | |||
| 3c3e72e36d | |||
| e0741d2073 | |||
| d973ce9832 | |||
| 25cb56a936 | |||
| 9640678c29 | |||
| 2ce1677aa5 | |||
| a0038b6f56 | |||
| aff1aa5112 | |||
| 3b6d55dbbb |
@@ -87,6 +87,7 @@ For more information on how to work with Atom's official packages, see
|
||||
* :white_check_mark: `:white_check_mark:` when adding tests
|
||||
* :lock: `:lock:` when dealing with security
|
||||
* :arrow_up: `:arrow_up:` when upgrading dependencies
|
||||
* :arrow_down: `:arrow_down:` when downgrading dependencies
|
||||
|
||||
## CoffeeScript Styleguide
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"fs-plus": "2.x",
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-atom-shell-installer": "^0.13.0",
|
||||
"grunt-atom-shell-installer": "^0.13.2",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git#cfb99aa99811d52687969532bd5a98011ed95bfe",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
|
||||
@@ -12,11 +12,18 @@ module.exports = (grunt) ->
|
||||
packageSpecQueue = null
|
||||
|
||||
logDeprecations = (label, {stderr}={}) ->
|
||||
if process.env.JANKY_SHA1 and stderr?.indexOf('Calls to deprecated functions') isnt -1
|
||||
grunt.log.error(label)
|
||||
stderr = stderr.replace(/^\[.*\] "/g, '')
|
||||
stderr = stderr.replace(/source: .*$/g, '')
|
||||
grunt.log.error(stderr)
|
||||
return unless process.env.JANKY_SHA1
|
||||
stderr ?= ''
|
||||
deprecatedStart = stderr.indexOf('Calls to deprecated functions')
|
||||
return if deprecatedStart.length is -1
|
||||
|
||||
grunt.log.error(label)
|
||||
stderr = stderr.substring(deprecatedStart)
|
||||
stderr = stderr.replace(/^\s*\[[^\]]+\]\s+/gm, '')
|
||||
stderr = stderr.replace(/source: .*$/gm, '')
|
||||
stderr = stderr.replace(/^"/gm, '')
|
||||
stderr = stderr.replace(/",\s*$/gm, '')
|
||||
grunt.log.error(stderr)
|
||||
|
||||
getAppPath = ->
|
||||
contentsDir = grunt.config.get('atom.contentsDir')
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
path = require 'path'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
grunt.registerTask 'update-octicons', 'Update octicon font and LESS variables', ->
|
||||
pathToOcticons = path.resolve('..', 'octicons')
|
||||
if grunt.file.isDir(pathToOcticons)
|
||||
# Copy font-file
|
||||
fontSrc = path.join(pathToOcticons, 'octicons', 'octicons.woff')
|
||||
fontDest = path.resolve('static', 'octicons.woff')
|
||||
grunt.file.copy(fontSrc, fontDest)
|
||||
|
||||
# Update Octicon UTF codes
|
||||
glyphsSrc = path.join(pathToOcticons, 'data', 'glyphs.yml')
|
||||
output = []
|
||||
for {css, code} in grunt.file.readYAML(glyphsSrc)
|
||||
output.push "@#{css}: \"\\#{code}\";"
|
||||
|
||||
octiconUtfDest = path.resolve('static', 'variables', 'octicon-utf-codes.less')
|
||||
grunt.file.write(octiconUtfDest, "#{output.join('\n')}\n")
|
||||
else
|
||||
grunt.log.error("octicons repo must be cloned to #{pathToOcticons}")
|
||||
false
|
||||
@@ -30,8 +30,8 @@ All requests that take parameters require `application/json`.
|
||||
Parameters:
|
||||
|
||||
- **page** (optional)
|
||||
- **sort** (optional, values: `created_at`, `updated_at`, `downloads`)
|
||||
- **direction** (optional, values: `asc`, `desc`)
|
||||
- **sort** (optional) - One of `downloads`, `created_at`, `updated_at`, `stars`. Defaults to `downloads`
|
||||
- **direction** (optional) - `asc` or `desc`. Defaults to `desc`. `stars` can only be ordered `desc`
|
||||
|
||||
Returns a list of all packages in the following format:
|
||||
```json
|
||||
@@ -61,17 +61,18 @@ Link: <https://www.atom.io/api/packages?page=1>; rel="self",
|
||||
|
||||
By default, results are sorted by download count, descending.
|
||||
|
||||
### Searching packages
|
||||
|
||||
#### GET /api/packages/search
|
||||
|
||||
Parameters:
|
||||
|
||||
- **q** String query to search
|
||||
- **sort** (optional, values: `created_at`, `updated_at`, `downloads`)
|
||||
- **direction** (optional, values: `asc`, `desc`)
|
||||
- **q** (required) - Search query
|
||||
- **page** (optional)
|
||||
- **sort** (optional) - One of `downloads`, `created_at`, `updated_at`, `stars`. Defaults to the relevance of the search query.
|
||||
- **direction** (optional) - `asc` or `desc`. Defaults to `desc`.
|
||||
|
||||
Returns a list of all packages in the same format as `/api/packages`.
|
||||
|
||||
By default, results sorted by relevance to search query.
|
||||
Returns results in the same format as [listing packages](#listing-packages).
|
||||
|
||||
### Showing package details
|
||||
|
||||
|
||||
@@ -26,13 +26,17 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
|
||||
|
||||
### Arch
|
||||
|
||||
* `sudo pacman -S base-devel git nodejs libgnome-keyring python2`
|
||||
* `sudo pacman -S gconf base-devel git nodejs libgnome-keyring python2`
|
||||
* `export PYTHON=/usr/bin/python2` before building Atom.
|
||||
|
||||
### Slackware
|
||||
|
||||
* `sbopkg -k -i node -i atom`
|
||||
|
||||
### openSUSE
|
||||
|
||||
* `sudo zypper install nodejs make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools`
|
||||
|
||||
## Instructions
|
||||
|
||||
If you have problems with permissions don't forget to prefix with `sudo`
|
||||
|
||||
@@ -105,6 +105,7 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu.
|
||||
- `core`
|
||||
- `disabledPackages`: An array of package names to disable
|
||||
- `excludeVcsIgnoredPaths`: Don't search within files specified by _.gitignore_
|
||||
- `followSymlinks`: Follow symlinks when searching and scanning root directory
|
||||
- `ignoredNames`: File names to ignore across all of Atom
|
||||
- `projectHome`: The directory where projects are assumed to be located
|
||||
- `themes`: An array of theme names to load, in cascading order
|
||||
|
||||
+48
-48
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.163.0",
|
||||
"version": "0.166.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -20,20 +20,20 @@
|
||||
"atomShellVersion": "0.19.4",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.3.0",
|
||||
"atom-keymap": "^2.3.3",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.7.0",
|
||||
"coffeestack": "0.7.0",
|
||||
"delegato": "^1",
|
||||
"emissary": "^1.3.1",
|
||||
"event-kit": "0.8.1",
|
||||
"first-mate": "^2.2.0",
|
||||
"event-kit": "^1.0.0",
|
||||
"first-mate": "^2.2.2",
|
||||
"fs-plus": "^2.3.2",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^2.1",
|
||||
"git-utils": "^2.2",
|
||||
"grim": "0.12.0",
|
||||
"grim": "1.0.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
@@ -45,7 +45,7 @@
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.4",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^2.3.5",
|
||||
"pathwatcher": "^2.3.7",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
@@ -53,7 +53,7 @@
|
||||
"reactionary-atom-fork": "^1.0.0",
|
||||
"runas": "1.0.1",
|
||||
"scandal": "1.0.3",
|
||||
"scoped-property-store": "^0.15.4",
|
||||
"scoped-property-store": "^0.16.2",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^1.0.2",
|
||||
"semver": "2.2.1",
|
||||
@@ -61,7 +61,7 @@
|
||||
"service-hub": "^0.1.0",
|
||||
"space-pen": "3.8.2",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.8.2",
|
||||
"text-buffer": "^3.8.4",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.6",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
@@ -73,74 +73,74 @@
|
||||
"atom-light-ui": "0.36.0",
|
||||
"base16-tomorrow-dark-theme": "0.22.0",
|
||||
"base16-tomorrow-light-theme": "0.5.0",
|
||||
"solarized-dark-syntax": "0.29.0",
|
||||
"solarized-light-syntax": "0.13.0",
|
||||
"archive-view": "0.40.0",
|
||||
"autocomplete": "0.34.0",
|
||||
"solarized-dark-syntax": "0.30.0",
|
||||
"solarized-light-syntax": "0.15.0",
|
||||
"archive-view": "0.43.0",
|
||||
"autocomplete": "0.38.0",
|
||||
"autoflow": "0.20.0",
|
||||
"autosave": "0.19.0",
|
||||
"background-tips": "0.18.0",
|
||||
"bookmarks": "0.31.0",
|
||||
"background-tips": "0.19.0",
|
||||
"bookmarks": "0.33.0",
|
||||
"bracket-matcher": "0.64.0",
|
||||
"command-palette": "0.30.0",
|
||||
"deprecation-cop": "0.20.0",
|
||||
"command-palette": "0.32.0",
|
||||
"deprecation-cop": "0.22.0",
|
||||
"dev-live-reload": "0.36.0",
|
||||
"encoding-selector": "0.12.0",
|
||||
"encoding-selector": "0.14.0",
|
||||
"exception-reporting": "0.21.0",
|
||||
"find-and-replace": "0.152.0",
|
||||
"fuzzy-finder": "0.62.0",
|
||||
"git-diff": "0.45.0",
|
||||
"go-to-line": "0.27.0",
|
||||
"grammar-selector": "0.40.0",
|
||||
"image-view": "0.44.0",
|
||||
"incompatible-packages": "0.16.0",
|
||||
"keybinding-resolver": "0.24.0",
|
||||
"find-and-replace": "0.154.0",
|
||||
"fuzzy-finder": "0.64.0",
|
||||
"git-diff": "0.47.0",
|
||||
"go-to-line": "0.29.0",
|
||||
"grammar-selector": "0.42.0",
|
||||
"image-view": "0.46.0",
|
||||
"incompatible-packages": "0.18.0",
|
||||
"keybinding-resolver": "0.25.0",
|
||||
"link": "0.28.0",
|
||||
"markdown-preview": "0.112.0",
|
||||
"markdown-preview": "0.115.0",
|
||||
"metrics": "0.40.0",
|
||||
"notifications": "0.20.0",
|
||||
"notifications": "0.22.0",
|
||||
"open-on-github": "0.31.0",
|
||||
"package-generator": "0.34.0",
|
||||
"release-notes": "0.43.0",
|
||||
"package-generator": "0.36.0",
|
||||
"release-notes": "0.45.0",
|
||||
"settings-view": "0.161.0",
|
||||
"snippets": "0.59.0",
|
||||
"spell-check": "0.45.0",
|
||||
"status-bar": "0.54.0",
|
||||
"styleguide": "0.36.0",
|
||||
"symbols-view": "0.70.0",
|
||||
"tabs": "0.58.0",
|
||||
"timecop": "0.24.0",
|
||||
"tree-view": "0.139.0",
|
||||
"snippets": "0.63.0",
|
||||
"spell-check": "0.47.0",
|
||||
"status-bar": "0.56.0",
|
||||
"styleguide": "0.38.0",
|
||||
"symbols-view": "0.77.0",
|
||||
"tabs": "0.59.0",
|
||||
"timecop": "0.26.0",
|
||||
"tree-view": "0.145.0",
|
||||
"update-package-dependencies": "0.7.0",
|
||||
"welcome": "0.21.0",
|
||||
"whitespace": "0.27.0",
|
||||
"wrap-guide": "0.27.0",
|
||||
"language-c": "0.33.0",
|
||||
"wrap-guide": "0.28.0",
|
||||
"language-c": "0.35.0",
|
||||
"language-clojure": "0.9.0",
|
||||
"language-coffee-script": "0.38.1",
|
||||
"language-css": "0.24.0",
|
||||
"language-gfm": "0.55.0",
|
||||
"language-gfm": "0.58.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.19.1",
|
||||
"language-html": "0.27.0",
|
||||
"language-hyperlink": "0.12.2",
|
||||
"language-java": "0.13.0",
|
||||
"language-javascript": "0.51.0",
|
||||
"language-javascript": "0.52.0",
|
||||
"language-json": "0.10.0",
|
||||
"language-less": "0.21.0",
|
||||
"language-less": "0.22.0",
|
||||
"language-make": "0.12.0",
|
||||
"language-mustache": "0.11.0",
|
||||
"language-objective-c": "0.12.0",
|
||||
"language-objective-c": "0.14.0",
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.18.0",
|
||||
"language-php": "0.19.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.26.0",
|
||||
"language-ruby": "0.44.0",
|
||||
"language-python": "0.27.0",
|
||||
"language-ruby": "0.46.0",
|
||||
"language-ruby-on-rails": "0.18.0",
|
||||
"language-sass": "0.29.0",
|
||||
"language-shellscript": "0.10.1",
|
||||
"language-shellscript": "0.11.0",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.11.0",
|
||||
"language-sql": "0.12.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.15.0",
|
||||
"language-toml": "0.14.1",
|
||||
|
||||
@@ -54,6 +54,7 @@ describe "the `atom` global", ->
|
||||
describe "loading default config", ->
|
||||
it 'loads the default core config', ->
|
||||
expect(atom.config.get('core.excludeVcsIgnoredPaths')).toBe true
|
||||
expect(atom.config.get('core.followSymlinks')).toBe false
|
||||
expect(atom.config.get('editor.showInvisibles')).toBe false
|
||||
|
||||
describe "window onerror handler", ->
|
||||
|
||||
+1060
-836
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -381,6 +381,23 @@ describe "LanguageMode", ->
|
||||
expect(languageMode.isFoldableAtBufferRow(3)).toBe false
|
||||
expect(languageMode.isFoldableAtBufferRow(4)).toBe true
|
||||
|
||||
describe ".foldAllAtIndentLevel(indentLevel)", ->
|
||||
it "folds blocks of text at the given indentation level", ->
|
||||
languageMode.foldAllAtIndentLevel(0)
|
||||
expect(editor.lineTextForScreenRow(0)).toBe "var quicksort = function () {"
|
||||
expect(editor.getLastScreenRow()).toBe 0
|
||||
|
||||
languageMode.foldAllAtIndentLevel(1)
|
||||
expect(editor.lineTextForScreenRow(0)).toBe "var quicksort = function () {"
|
||||
expect(editor.lineTextForScreenRow(1)).toBe " var sort = function(items) {"
|
||||
expect(editor.getLastScreenRow()).toBe 4
|
||||
|
||||
languageMode.foldAllAtIndentLevel(2)
|
||||
expect(editor.lineTextForScreenRow(0)).toBe "var quicksort = function () {"
|
||||
expect(editor.lineTextForScreenRow(1)).toBe " var sort = function(items) {"
|
||||
expect(editor.lineTextForScreenRow(2)).toBe " if (items.length <= 1) return items;"
|
||||
expect(editor.getLastScreenRow()).toBe 9
|
||||
|
||||
describe "folding with comments", ->
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
|
||||
@@ -3,19 +3,36 @@ Package = require '../src/package'
|
||||
|
||||
describe "PackageManager", ->
|
||||
workspaceElement = null
|
||||
|
||||
beforeEach ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
|
||||
describe "::loadPackage(name)", ->
|
||||
it "continues if the package has an invalid package.json", ->
|
||||
spyOn(console, 'warn')
|
||||
beforeEach ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
expect(-> atom.packages.loadPackage("package-with-broken-package-json")).not.toThrow()
|
||||
|
||||
it "continues if the package has an invalid keymap", ->
|
||||
it "returns the package", ->
|
||||
pack = atom.packages.loadPackage("package-with-index")
|
||||
expect(pack instanceof Package).toBe true
|
||||
expect(pack.metadata.name).toBe "package-with-index"
|
||||
|
||||
it "returns the package if it has an invalid keymap", ->
|
||||
spyOn(console, 'warn')
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
expect(-> atom.packages.loadPackage("package-with-broken-keymap")).not.toThrow()
|
||||
pack = atom.packages.loadPackage("package-with-broken-keymap")
|
||||
expect(pack instanceof Package).toBe true
|
||||
expect(pack.metadata.name).toBe "package-with-broken-keymap"
|
||||
|
||||
it "returns null if the package has an invalid package.json", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.loadPackage("package-with-broken-package-json")).toBeNull()
|
||||
expect(console.warn.callCount).toBe(1)
|
||||
expect(console.warn.argsForCall[0][0]).toContain("Failed to load package.json")
|
||||
|
||||
it "returns null if the package is not found in any package directory", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.loadPackage("this-package-cannot-be-found")).toBeNull()
|
||||
expect(console.warn.callCount).toBe(1)
|
||||
expect(console.warn.argsForCall[0][0]).toContain("Could not resolve")
|
||||
|
||||
describe "::unloadPackage(name)", ->
|
||||
describe "when the package is active", ->
|
||||
@@ -197,11 +214,30 @@ describe "PackageManager", ->
|
||||
runs ->
|
||||
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
|
||||
|
||||
it "logs warning instead of throwing an exception if the package fails to load", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
spyOn(console, "warn")
|
||||
expect(-> atom.packages.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
describe "when the package throws an error while loading", ->
|
||||
it "logs a warning instead of throwing an exception", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
spyOn(console, "warn")
|
||||
expect(-> atom.packages.activatePackage("package-that-throws-an-exception")).not.toThrow()
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
|
||||
describe "when the package is not found", ->
|
||||
it "rejects the promise", ->
|
||||
atom.config.set("core.disabledPackages", [])
|
||||
|
||||
onSuccess = jasmine.createSpy('onSuccess')
|
||||
onFailure = jasmine.createSpy('onFailure')
|
||||
spyOn(console, 'warn')
|
||||
|
||||
atom.packages.activatePackage("this-doesnt-exist").then(onSuccess, onFailure)
|
||||
|
||||
waitsFor "promise to be rejected", ->
|
||||
onFailure.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(onFailure.mostRecentCall.args[0] instanceof Error).toBe true
|
||||
expect(onFailure.mostRecentCall.args[0].message).toContain "Failed to load package 'this-doesnt-exist'"
|
||||
|
||||
describe "keymap loading", ->
|
||||
describe "when the metadata does not contain a 'keymaps' manifest", ->
|
||||
@@ -364,10 +400,10 @@ describe "PackageManager", ->
|
||||
describe "scoped-property loading", ->
|
||||
it "loads the scoped properties", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-scoped-properties")
|
||||
atom.packages.activatePackage("package-with-settings")
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBe '^a'
|
||||
|
||||
describe "converted textmate packages", ->
|
||||
it "loads the package's grammars", ->
|
||||
@@ -380,13 +416,13 @@ describe "PackageManager", ->
|
||||
expect(atom.grammars.selectGrammar("file.rb").name).toBe "Ruby"
|
||||
|
||||
it "loads the translated scoped properties", ->
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
expect(atom.config.get('editor.commentStart', scope: ['.source.ruby'])).toBeUndefined()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-ruby')
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBe '# '
|
||||
expect(atom.config.get('editor.commentStart', scope: ['.source.ruby'])).toBe '# '
|
||||
|
||||
describe "::deactivatePackage(id)", ->
|
||||
afterEach ->
|
||||
@@ -490,12 +526,12 @@ describe "PackageManager", ->
|
||||
|
||||
it "removes the package's scoped-properties", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage("package-with-scoped-properties")
|
||||
atom.packages.activatePackage("package-with-settings")
|
||||
|
||||
runs ->
|
||||
expect(atom.config.get ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
|
||||
atom.packages.deactivatePackage("package-with-scoped-properties")
|
||||
expect(atom.config.get ['.source.omg'], 'editor.increaseIndentPattern').toBeUndefined()
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBe '^a'
|
||||
atom.packages.deactivatePackage("package-with-settings")
|
||||
expect(atom.config.get 'editor.increaseIndentPattern', scope: ['.source.omg']).toBeUndefined()
|
||||
|
||||
describe "textmate packages", ->
|
||||
it "removes the package's grammars", ->
|
||||
@@ -515,7 +551,7 @@ describe "PackageManager", ->
|
||||
|
||||
runs ->
|
||||
atom.packages.deactivatePackage('language-ruby')
|
||||
expect(atom.config.get(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
|
||||
expect(atom.config.get('editor.commentStart', scope: ['.source.ruby'])).toBeUndefined()
|
||||
|
||||
describe "::activate()", ->
|
||||
packageActivator = null
|
||||
@@ -552,9 +588,9 @@ describe "PackageManager", ->
|
||||
themes = themeActivator.mostRecentCall.args[0]
|
||||
expect(['theme']).toContain(theme.getType()) for theme in themes
|
||||
|
||||
describe "::enablePackage() and ::disablePackage()", ->
|
||||
describe "::enablePackage(id) and ::disablePackage(id)", ->
|
||||
describe "with packages", ->
|
||||
it ".enablePackage() enables a disabled package", ->
|
||||
it "enables a disabled package", ->
|
||||
packageName = 'package-with-main'
|
||||
atom.config.pushAtKeyPath('core.disabledPackages', packageName)
|
||||
atom.packages.observeDisabledPackages()
|
||||
@@ -572,7 +608,7 @@ describe "PackageManager", ->
|
||||
expect(activatedPackages).toContain(pack)
|
||||
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
|
||||
|
||||
it ".disablePackage() disables an enabled package", ->
|
||||
it "disables an enabled package", ->
|
||||
packageName = 'package-with-main'
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage(packageName)
|
||||
@@ -587,6 +623,11 @@ describe "PackageManager", ->
|
||||
expect(activatedPackages).not.toContain(pack)
|
||||
expect(atom.config.get('core.disabledPackages')).toContain packageName
|
||||
|
||||
it "returns null if the package cannot be loaded", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(atom.packages.enablePackage("this-doesnt-exist")).toBeNull()
|
||||
expect(console.warn.callCount).toBe 1
|
||||
|
||||
describe "with themes", ->
|
||||
reloadedHandler = null
|
||||
|
||||
@@ -597,7 +638,7 @@ describe "PackageManager", ->
|
||||
afterEach ->
|
||||
atom.themes.deactivateThemes()
|
||||
|
||||
it ".enablePackage() and .disablePackage() enables and disables a theme", ->
|
||||
it "enables and disables a theme", ->
|
||||
packageName = 'theme-with-package-file'
|
||||
|
||||
expect(atom.config.get('core.themes')).not.toContain packageName
|
||||
|
||||
@@ -4,7 +4,6 @@ Project = require '../src/project'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
platform = require './spec-helper-platform'
|
||||
BufferedProcess = require '../src/buffered-process'
|
||||
|
||||
describe "Project", ->
|
||||
@@ -195,290 +194,6 @@ describe "Project", ->
|
||||
expect(atom.project.getPaths()[0]).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
expect(atom.project.getDirectories()[0].path).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
|
||||
|
||||
describe ".replace()", ->
|
||||
[filePath, commentFilePath, sampleContent, sampleCommentContent] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.project.setPaths([atom.project.resolve('../')])
|
||||
|
||||
filePath = atom.project.resolve('sample.js')
|
||||
commentFilePath = atom.project.resolve('sample-with-comments.js')
|
||||
sampleContent = fs.readFileSync(filePath).toString()
|
||||
sampleCommentContent = fs.readFileSync(commentFilePath).toString()
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, sampleContent)
|
||||
fs.writeFileSync(commentFilePath, sampleCommentContent)
|
||||
|
||||
describe "when a file doesn't exist", ->
|
||||
it "calls back with an error", ->
|
||||
errors = []
|
||||
missingPath = path.resolve('/not-a-file.js')
|
||||
expect(fs.existsSync(missingPath)).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [missingPath], (result, error) ->
|
||||
errors.push(error)
|
||||
|
||||
runs ->
|
||||
expect(errors).toHaveLength 1
|
||||
expect(errors[0].path).toBe missingPath
|
||||
|
||||
describe "when called with unopened files", ->
|
||||
it "replaces properly", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
describe "when a buffer is already open", ->
|
||||
it "replaces properly and saves when not modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
it "does not replace when the path is not specified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample-with-comments.js').then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', [commentFilePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe commentFilePath
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'okthen', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
describe ".scan(options, callback)", ->
|
||||
describe "when called with a regex", ->
|
||||
it "calls the callback with all regex results in all files in the project", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /(a)+/, (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results[0].filePath).toBe atom.project.resolve('a')
|
||||
expect(results[0].matches).toHaveLength(3)
|
||||
expect(results[0].matches[0]).toEqual
|
||||
matchText: 'aaa'
|
||||
lineText: 'aaa bbb'
|
||||
lineTextOffset: 0
|
||||
range: [[0, 0], [0, 3]]
|
||||
|
||||
it "works with with escaped literals (like $ and ^)", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /\$\w+/, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results.length).toBe 1
|
||||
|
||||
{filePath, matches} = results[0]
|
||||
expect(filePath).toBe atom.project.resolve('a')
|
||||
expect(matches).toHaveLength 1
|
||||
expect(matches[0]).toEqual
|
||||
matchText: '$bill'
|
||||
lineText: 'dollar$bill'
|
||||
lineTextOffset: 0
|
||||
range: [[2, 6], [2, 11]]
|
||||
|
||||
it "works on evil filenames", ->
|
||||
platform.generateEvilFiles()
|
||||
atom.project.setPaths([path.join(__dirname, 'fixtures', 'evil-files')])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /evil/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
_.each(matches, (m) -> expect(m.matchText).toEqual 'evil')
|
||||
|
||||
if platform.isWindows()
|
||||
expect(paths.length).toBe 3
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(path.basename(paths[2])).toBe "utfa\u0306.md"
|
||||
else
|
||||
expect(paths.length).toBe 5
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(paths[2]).toMatch /goddam\nnewlines$/m
|
||||
expect(paths[3]).toMatch /quote".txt$/m
|
||||
expect(path.basename(paths[4])).toBe "utfa\u0306.md"
|
||||
|
||||
it "ignores case if the regex includes the `i` flag", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /DOLLAR/i, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
|
||||
describe "when the core.excludeVcsIgnoredPaths config is truthy", ->
|
||||
[projectPath, ignoredPath] = []
|
||||
|
||||
beforeEach ->
|
||||
sourceProjectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
projectPath = path.join(temp.mkdirSync("atom"))
|
||||
|
||||
writerStream = fstream.Writer(projectPath)
|
||||
fstream.Reader(sourceProjectPath).pipe(writerStream)
|
||||
|
||||
waitsFor (done) ->
|
||||
writerStream.on 'close', done
|
||||
writerStream.on 'error', done
|
||||
|
||||
runs ->
|
||||
fs.rename(path.join(projectPath, 'git.git'), path.join(projectPath, '.git'))
|
||||
ignoredPath = path.join(projectPath, 'ignored.txt')
|
||||
fs.writeFileSync(ignoredPath, 'this match should not be included')
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(projectPath) if fs.existsSync(projectPath)
|
||||
|
||||
it "excludes ignored files", ->
|
||||
atom.project.setPaths([projectPath])
|
||||
atom.config.set('core.excludeVcsIgnoredPaths', true)
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.project.scan /match/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "includes only files when a directory filter is specified", ->
|
||||
projectPath = path.join(path.join(__dirname, 'fixtures', 'dir'))
|
||||
atom.project.setPaths([projectPath])
|
||||
|
||||
filePath = path.join(projectPath, 'a-dir', 'oh-git')
|
||||
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /aaa/, paths: ["a-dir#{path.sep}"], (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "includes files and folders that begin with a '.'", ->
|
||||
projectPath = temp.mkdirSync()
|
||||
filePath = path.join(projectPath, '.text')
|
||||
fs.writeFileSync(filePath, 'match this')
|
||||
atom.project.setPaths([projectPath])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.project.scan /match this/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "excludes values in core.ignoredNames", ->
|
||||
projectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
ignoredNames = atom.config.get("core.ignoredNames")
|
||||
ignoredNames.push("a")
|
||||
atom.config.set("core.ignoredNames", ignoredNames)
|
||||
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.project.scan /dollar/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('a').then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.scan /a|Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 3
|
||||
resultForA = _.find results, ({filePath}) -> path.basename(filePath) == 'a'
|
||||
expect(resultForA.matches).toHaveLength 1
|
||||
expect(resultForA.matches[0].matchText).toBe 'Elephant'
|
||||
|
||||
it "ignores buffers outside the project", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(temp.openSync().path).then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.scan /Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 0
|
||||
|
||||
describe ".eachBuffer(callback)", ->
|
||||
beforeEach ->
|
||||
atom.project.bufferForPathSync('a')
|
||||
|
||||
@@ -84,6 +84,10 @@ beforeEach ->
|
||||
atom.workspaceViewParentSelector = '#jasmine-content'
|
||||
|
||||
window.resetTimeouts()
|
||||
spyOn(_._, "now").andCallFake -> window.now
|
||||
spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout
|
||||
spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout
|
||||
|
||||
atom.packages.packageStates = {}
|
||||
|
||||
serializedWindowState = null
|
||||
@@ -102,9 +106,9 @@ beforeEach ->
|
||||
spyOn(atom.menu, 'sendToBrowserProcess')
|
||||
|
||||
# reset config before each spec; don't load or save from/to `config.json`
|
||||
spyOn(Config::, 'load')
|
||||
spyOn(Config::, 'save')
|
||||
config = new Config({resourcePath, configDirPath: atom.getConfigDirPath()})
|
||||
spyOn(config, 'load')
|
||||
spyOn(config, 'save')
|
||||
atom.config = config
|
||||
atom.loadConfig()
|
||||
config.set "core.destroyEmptyPanes", false
|
||||
@@ -114,6 +118,7 @@ beforeEach ->
|
||||
config.set "core.disabledPackages", ["package-that-throws-an-exception",
|
||||
"package-with-broken-package-json", "package-with-broken-keymap"]
|
||||
config.set "editor.useShadowDOM", true
|
||||
advanceClock(1000)
|
||||
config.load.reset()
|
||||
config.save.reset()
|
||||
|
||||
@@ -121,8 +126,6 @@ beforeEach ->
|
||||
TextEditorElement::setUpdatedSynchronously(true)
|
||||
|
||||
spyOn(atom, "setRepresentedFilename")
|
||||
spyOn(window, "setTimeout").andCallFake window.fakeSetTimeout
|
||||
spyOn(window, "clearTimeout").andCallFake window.fakeClearTimeout
|
||||
spyOn(pathwatcher.File.prototype, "detectResurrectionAfterDelay").andCallFake -> @detectResurrection()
|
||||
spyOn(TextEditor.prototype, "shouldPromptToSave").andReturn false
|
||||
|
||||
|
||||
@@ -755,7 +755,6 @@ describe "TextEditorComponent", ->
|
||||
expect(cursorNode.offsetWidth).toBe charWidth
|
||||
|
||||
it "blinks cursors when they aren't moving", ->
|
||||
spyOn(_._, 'now').andCallFake -> window.now # Ensure _.debounce is based on our fake spec timeline
|
||||
cursorsNode = componentNode.querySelector('.cursors')
|
||||
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe false
|
||||
@@ -2048,8 +2047,6 @@ describe "TextEditorComponent", ->
|
||||
expect(component.mouseWheelScreenRow).toBe null
|
||||
|
||||
it "clears the mouseWheelScreenRow after a delay even if the event does not cause scrolling", ->
|
||||
spyOn(_._, 'now').andCallFake -> window.now # Ensure _.debounce is based on our fake spec timeline
|
||||
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
|
||||
lineNode = componentNode.querySelector('.line')
|
||||
@@ -2593,9 +2590,9 @@ describe "TextEditorComponent", ->
|
||||
|
||||
describe 'soft wrap settings', ->
|
||||
beforeEach ->
|
||||
atom.config.set '.source.coffee', 'editor.softWrap', true
|
||||
atom.config.set '.source.coffee', 'editor.preferredLineLength', 17
|
||||
atom.config.set '.source.coffee', 'editor.softWrapAtPreferredLineLength', true
|
||||
atom.config.set 'editor.softWrap', true, scopeSelector: '.source.coffee'
|
||||
atom.config.set 'editor.preferredLineLength', 17, scopeSelector: '.source.coffee'
|
||||
atom.config.set 'editor.softWrapAtPreferredLineLength', true, scopeSelector: '.source.coffee'
|
||||
|
||||
editor.setEditorWidthInChars(20)
|
||||
coffeeEditor.setEditorWidthInChars(20)
|
||||
@@ -2605,18 +2602,18 @@ describe "TextEditorComponent", ->
|
||||
expect(coffeeEditor.lineTextForScreenRow(3)).toEqual ' return items '
|
||||
|
||||
it 'updates the wrapped lines when editor.preferredLineLength changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.preferredLineLength', 20
|
||||
atom.config.set 'editor.preferredLineLength', 20, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(2)).toEqual ' return items if '
|
||||
|
||||
it 'updates the wrapped lines when editor.softWrapAtPreferredLineLength changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.softWrapAtPreferredLineLength', false
|
||||
atom.config.set 'editor.softWrapAtPreferredLineLength', false, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(2)).toEqual ' return items if '
|
||||
|
||||
it 'updates the wrapped lines when editor.softWrap changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.softWrap', false
|
||||
atom.config.set 'editor.softWrap', false, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(2)).toEqual ' return items if items.length <= 1'
|
||||
|
||||
atom.config.set '.source.coffee', 'editor.softWrap', true
|
||||
atom.config.set 'editor.softWrap', true, scopeSelector: '.source.coffee'
|
||||
expect(coffeeEditor.lineTextForScreenRow(3)).toEqual ' return items '
|
||||
|
||||
it 'updates the wrapped lines when the grammar changes', ->
|
||||
@@ -2644,11 +2641,11 @@ describe "TextEditorComponent", ->
|
||||
tab: 'F'
|
||||
cr: 'E'
|
||||
|
||||
atom.config.set '.source.js', 'editor.showInvisibles', true
|
||||
atom.config.set '.source.js', 'editor.invisibles', jsInvisibles
|
||||
atom.config.set 'editor.showInvisibles', true, scopeSelector: '.source.js'
|
||||
atom.config.set 'editor.invisibles', jsInvisibles, scopeSelector: '.source.js'
|
||||
|
||||
atom.config.set '.source.coffee', 'editor.showInvisibles', false
|
||||
atom.config.set '.source.coffee', 'editor.invisibles', coffeeInvisibles
|
||||
atom.config.set 'editor.showInvisibles', false, scopeSelector: '.source.coffee'
|
||||
atom.config.set 'editor.invisibles', coffeeInvisibles, scopeSelector: '.source.coffee'
|
||||
|
||||
editor.setText " a line with tabs\tand spaces \n"
|
||||
nextAnimationFrame()
|
||||
@@ -2664,7 +2661,7 @@ describe "TextEditorComponent", ->
|
||||
it "re-renders the invisibles when the invisible settings change", ->
|
||||
jsGrammar = editor.getGrammar()
|
||||
editor.setGrammar(coffeeEditor.getGrammar())
|
||||
atom.config.set '.source.coffee', 'editor.showInvisibles', true
|
||||
atom.config.set 'editor.showInvisibles', true, scopeSelector: '.source.coffee'
|
||||
nextAnimationFrame()
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{coffeeInvisibles.space}a line with tabs#{coffeeInvisibles.tab}and spaces#{coffeeInvisibles.space}#{coffeeInvisibles.eol}"
|
||||
|
||||
@@ -2673,7 +2670,7 @@ describe "TextEditorComponent", ->
|
||||
space: 'E'
|
||||
tab: 'W'
|
||||
cr: 'I'
|
||||
atom.config.set '.source.coffee', 'editor.invisibles', newInvisibles
|
||||
atom.config.set 'editor.invisibles', newInvisibles, scopeSelector: '.source.coffee'
|
||||
nextAnimationFrame()
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe "#{newInvisibles.space}a line with tabs#{newInvisibles.tab}and spaces#{newInvisibles.space}#{newInvisibles.eol}"
|
||||
|
||||
@@ -2683,8 +2680,8 @@ describe "TextEditorComponent", ->
|
||||
|
||||
describe 'editor.showIndentGuide', ->
|
||||
beforeEach ->
|
||||
atom.config.set '.source.js', 'editor.showIndentGuide', true
|
||||
atom.config.set '.source.coffee', 'editor.showIndentGuide', false
|
||||
atom.config.set 'editor.showIndentGuide', true, scopeSelector: '.source.js'
|
||||
atom.config.set 'editor.showIndentGuide', false, scopeSelector: '.source.coffee'
|
||||
|
||||
it "has an 'indent-guide' class when scoped editor.showIndentGuide is true, but not when scoped editor.showIndentGuide is false", ->
|
||||
line1LeafNodes = getLeafNodes(component.lineNodeForScreenRow(1))
|
||||
@@ -2705,7 +2702,7 @@ describe "TextEditorComponent", ->
|
||||
expect(line1LeafNodes[0].classList.contains('indent-guide')).toBe true
|
||||
expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false
|
||||
|
||||
atom.config.set '.source.js', 'editor.showIndentGuide', false
|
||||
atom.config.set 'editor.showIndentGuide', false, scopeSelector: '.source.js'
|
||||
|
||||
line1LeafNodes = getLeafNodes(component.lineNodeForScreenRow(1))
|
||||
expect(line1LeafNodes[0].textContent).toBe ' '
|
||||
|
||||
@@ -62,7 +62,6 @@ describe "TextEditor", ->
|
||||
atom.workspace.open('sample.less', initialLine: 5).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 5
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 0
|
||||
|
||||
@@ -74,10 +73,37 @@ describe "TextEditor", ->
|
||||
atom.workspace.open('sample.less', initialColumn: 8).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
buffer = editor.buffer
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 0
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 8
|
||||
|
||||
describe "when the editor is reopened with an initialLine option", ->
|
||||
it "positions the cursor on the specified line", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialLine: 5).then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialLine: 4).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 4
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 0
|
||||
|
||||
describe "when the editor is reopened with an initialColumn option", ->
|
||||
it "positions the cursor on the specified column", ->
|
||||
editor = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialColumn: 8).then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.less', initialColumn: 7).then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.getLastCursor().getBufferPosition().row).toEqual 0
|
||||
expect(editor.getLastCursor().getBufferPosition().column).toEqual 7
|
||||
|
||||
describe ".copy()", ->
|
||||
it "returns a different edit session with the same initial state", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 4]])
|
||||
@@ -1327,7 +1353,7 @@ describe "TextEditor", ->
|
||||
coffeeEditor.selectWordsContainingCursors()
|
||||
expect(coffeeEditor.getSelectedBufferRange()).toEqual [[0, 6], [0, 15]]
|
||||
|
||||
atom.config.set '.source.coffee', 'editor.nonWordCharacters', 'qusort'
|
||||
atom.config.set 'editor.nonWordCharacters', 'qusort', scopeSelector: '.source.coffee'
|
||||
|
||||
coffeeEditor.setCursorBufferPosition [0, 9]
|
||||
coffeeEditor.selectWordsContainingCursors()
|
||||
@@ -3276,7 +3302,7 @@ describe "TextEditor", ->
|
||||
atom.packages.unloadPackages()
|
||||
|
||||
it 'returns correct values based on the scope of the set grammars', ->
|
||||
atom.config.set '.source.coffee', 'editor.tabLength', 6
|
||||
atom.config.set 'editor.tabLength', 6, scopeSelector: '.source.coffee'
|
||||
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(coffeeEditor.getTabLength()).toBe 6
|
||||
@@ -3298,12 +3324,12 @@ describe "TextEditor", ->
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
|
||||
atom.config.set '.source.js', 'editor.tabLength', 6
|
||||
atom.config.set 'editor.tabLength', 6, scopeSelector: '.source.js'
|
||||
expect(editor.getTabLength()).toBe 6
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 6
|
||||
|
||||
it 'updates the tab length when the grammar changes', ->
|
||||
atom.config.set '.source.coffee', 'editor.tabLength', 6
|
||||
atom.config.set 'editor.tabLength', 6, scopeSelector: '.source.coffee'
|
||||
|
||||
expect(editor.getTabLength()).toBe 2
|
||||
expect(editor.tokenizedLineForScreenRow(5).tokens[0].firstNonWhitespaceIndex).toBe 2
|
||||
@@ -3473,8 +3499,8 @@ describe "TextEditor", ->
|
||||
atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o
|
||||
|
||||
runs ->
|
||||
atom.config.set('.source.js', 'editor.autoIndent', true)
|
||||
atom.config.set('.source.coffee', 'editor.autoIndent', false)
|
||||
atom.config.set('editor.autoIndent', true, scopeSelector: '.source.js')
|
||||
atom.config.set('editor.autoIndent', false, scopeSelector: '.source.coffee')
|
||||
|
||||
afterEach: ->
|
||||
atom.packages.deactivatePackages()
|
||||
@@ -3766,8 +3792,12 @@ describe "TextEditor", ->
|
||||
it "updates the grammar based on grammar overrides", ->
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
atom.grammars.setGrammarOverrideForPath(editor.getPath(), 'source.coffee')
|
||||
callback = jasmine.createSpy('callback')
|
||||
editor.onDidChangeGrammar(callback)
|
||||
editor.reloadGrammar()
|
||||
expect(editor.getGrammar().name).toBe 'CoffeeScript'
|
||||
expect(callback.callCount).toBe 1
|
||||
expect(callback.argsForCall[0][0]).toBe atom.grammars.grammarForScopeName('source.coffee')
|
||||
|
||||
describe "when the editor's grammar has an injection selector", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -128,10 +128,35 @@ describe "ThemeManager", ->
|
||||
expect(importPaths.length).toBe 1
|
||||
expect(importPaths[0]).toContain 'atom-dark-ui'
|
||||
|
||||
it 'adds theme-* classes to the workspace for each active theme', ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
expect(workspaceElement).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when a theme fails to load", ->
|
||||
it "logs a warning", ->
|
||||
spyOn(console, 'warn')
|
||||
expect(-> atom.packages.activatePackage('a-theme-that-will-not-be-found')).toThrow()
|
||||
atom.packages.activatePackage('a-theme-that-will-not-be-found')
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0]).toContain "Could not resolve 'a-theme-that-will-not-be-found'"
|
||||
|
||||
describe "::requireStylesheet(path)", ->
|
||||
beforeEach ->
|
||||
@@ -223,11 +248,9 @@ describe "ThemeManager", ->
|
||||
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
describe "base style sheet loading", ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
jasmine.snapshotDeprecations()
|
||||
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
workspaceElement.appendChild document.createElement('atom-text-editor')
|
||||
@@ -235,9 +258,6 @@ describe "ThemeManager", ->
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
beforeEach ->
|
||||
jasmine.restoreDeprecationsSnapshot()
|
||||
|
||||
it "loads the correct values from the theme's ui-variables file", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
@@ -269,22 +289,6 @@ describe "ThemeManager", ->
|
||||
# from within the theme itself
|
||||
expect($("atom-text-editor").css("background-color")).toBe "rgb(0, 152, 255)"
|
||||
|
||||
describe "theme classes on the workspace", ->
|
||||
it 'adds theme-* classes to the workspace for each active theme', ->
|
||||
expect(workspaceElement).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(workspaceElement).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(workspaceElement).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -14,14 +14,14 @@ describe "ViewRegistry", ->
|
||||
expect(registry.getView(node)).toBe node
|
||||
|
||||
describe "when passed a SpacePen view", ->
|
||||
it "returns the root node of the view with a __spacePenView property pointing at the SpacePen view", ->
|
||||
it "returns the root node of the view with a .spacePenView property pointing at the SpacePen view", ->
|
||||
class TestView extends View
|
||||
@content: -> @div "Hello"
|
||||
|
||||
view = new TestView
|
||||
node = registry.getView(view)
|
||||
expect(node.textContent).toBe "Hello"
|
||||
expect(node.__spacePenView).toBe view
|
||||
expect(node.spacePenView).toBe view
|
||||
|
||||
describe "when passed a model object", ->
|
||||
describe "when a view provider is registered matching the object's constructor", ->
|
||||
@@ -62,7 +62,7 @@ describe "ViewRegistry", ->
|
||||
node = registry.getView(model)
|
||||
|
||||
expect(node.textContent).toBe "hello"
|
||||
view = node.__spacePenView
|
||||
view = node.spacePenView
|
||||
expect(view instanceof TestView).toBe true
|
||||
expect(view.model).toBe model
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ path = require 'path'
|
||||
temp = require 'temp'
|
||||
Workspace = require '../src/workspace'
|
||||
{View} = require '../src/space-pen-extensions'
|
||||
platform = require './spec-helper-platform'
|
||||
_ = require 'underscore-plus'
|
||||
fstream = require 'fstream'
|
||||
fs = require 'fs-plus'
|
||||
|
||||
describe "Workspace", ->
|
||||
workspace = null
|
||||
@@ -553,3 +557,287 @@ describe "Workspace", ->
|
||||
|
||||
expect(atom.workspace.panelForItem(item)).toBe panel
|
||||
expect(atom.workspace.panelForItem(itemWithNoPanel)).toBe null
|
||||
|
||||
describe "::scan(regex, options, callback)", ->
|
||||
describe "when called with a regex", ->
|
||||
it "calls the callback with all regex results in all files in the project", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /(a)+/, (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results[0].filePath).toBe atom.project.resolve('a')
|
||||
expect(results[0].matches).toHaveLength(3)
|
||||
expect(results[0].matches[0]).toEqual
|
||||
matchText: 'aaa'
|
||||
lineText: 'aaa bbb'
|
||||
lineTextOffset: 0
|
||||
range: [[0, 0], [0, 3]]
|
||||
|
||||
it "works with with escaped literals (like $ and ^)", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /\$\w+/, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results.length).toBe 1
|
||||
|
||||
{filePath, matches} = results[0]
|
||||
expect(filePath).toBe atom.project.resolve('a')
|
||||
expect(matches).toHaveLength 1
|
||||
expect(matches[0]).toEqual
|
||||
matchText: '$bill'
|
||||
lineText: 'dollar$bill'
|
||||
lineTextOffset: 0
|
||||
range: [[2, 6], [2, 11]]
|
||||
|
||||
it "works on evil filenames", ->
|
||||
platform.generateEvilFiles()
|
||||
atom.project.setPaths([path.join(__dirname, 'fixtures', 'evil-files')])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /evil/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
_.each(matches, (m) -> expect(m.matchText).toEqual 'evil')
|
||||
|
||||
if platform.isWindows()
|
||||
expect(paths.length).toBe 3
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(path.basename(paths[2])).toBe "utfa\u0306.md"
|
||||
else
|
||||
expect(paths.length).toBe 5
|
||||
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
|
||||
expect(paths[1]).toMatch /file with spaces.txt$/
|
||||
expect(paths[2]).toMatch /goddam\nnewlines$/m
|
||||
expect(paths[3]).toMatch /quote".txt$/m
|
||||
expect(path.basename(paths[4])).toBe "utfa\u0306.md"
|
||||
|
||||
it "ignores case if the regex includes the `i` flag", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /DOLLAR/i, (result) -> results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
|
||||
describe "when the core.excludeVcsIgnoredPaths config is truthy", ->
|
||||
[projectPath, ignoredPath] = []
|
||||
|
||||
beforeEach ->
|
||||
sourceProjectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
projectPath = path.join(temp.mkdirSync("atom"))
|
||||
|
||||
writerStream = fstream.Writer(projectPath)
|
||||
fstream.Reader(sourceProjectPath).pipe(writerStream)
|
||||
|
||||
waitsFor (done) ->
|
||||
writerStream.on 'close', done
|
||||
writerStream.on 'error', done
|
||||
|
||||
runs ->
|
||||
fs.rename(path.join(projectPath, 'git.git'), path.join(projectPath, '.git'))
|
||||
ignoredPath = path.join(projectPath, 'ignored.txt')
|
||||
fs.writeFileSync(ignoredPath, 'this match should not be included')
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(projectPath) if fs.existsSync(projectPath)
|
||||
|
||||
it "excludes ignored files", ->
|
||||
atom.project.setPaths([projectPath])
|
||||
atom.config.set('core.excludeVcsIgnoredPaths', true)
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /match/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "includes only files when a directory filter is specified", ->
|
||||
projectPath = path.join(path.join(__dirname, 'fixtures', 'dir'))
|
||||
atom.project.setPaths([projectPath])
|
||||
|
||||
filePath = path.join(projectPath, 'a-dir', 'oh-git')
|
||||
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /aaa/, paths: ["a-dir#{path.sep}"], (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "includes files and folders that begin with a '.'", ->
|
||||
projectPath = temp.mkdirSync()
|
||||
filePath = path.join(projectPath, '.text')
|
||||
fs.writeFileSync(filePath, 'match this')
|
||||
atom.project.setPaths([projectPath])
|
||||
paths = []
|
||||
matches = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /match this/, (result) ->
|
||||
paths.push(result.filePath)
|
||||
matches = matches.concat(result.matches)
|
||||
|
||||
runs ->
|
||||
expect(paths.length).toBe 1
|
||||
expect(paths[0]).toBe filePath
|
||||
expect(matches.length).toBe 1
|
||||
|
||||
it "excludes values in core.ignoredNames", ->
|
||||
projectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
|
||||
ignoredNames = atom.config.get("core.ignoredNames")
|
||||
ignoredNames.push("a")
|
||||
atom.config.set("core.ignoredNames", ignoredNames)
|
||||
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /dollar/, (results) ->
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('a').then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /a|Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 3
|
||||
resultForA = _.find results, ({filePath}) -> path.basename(filePath) == 'a'
|
||||
expect(resultForA.matches).toHaveLength 1
|
||||
expect(resultForA.matches[0].matchText).toBe 'Elephant'
|
||||
|
||||
it "ignores buffers outside the project", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(temp.openSync().path).then (o) ->
|
||||
editor = o
|
||||
editor.setText("Elephant")
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.scan /Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 0
|
||||
|
||||
describe "::replace(regex, replacementText, paths, iterator)", ->
|
||||
[filePath, commentFilePath, sampleContent, sampleCommentContent] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.project.setPaths([atom.project.resolve('../')])
|
||||
|
||||
filePath = atom.project.resolve('sample.js')
|
||||
commentFilePath = atom.project.resolve('sample-with-comments.js')
|
||||
sampleContent = fs.readFileSync(filePath).toString()
|
||||
sampleCommentContent = fs.readFileSync(commentFilePath).toString()
|
||||
|
||||
afterEach ->
|
||||
fs.writeFileSync(filePath, sampleContent)
|
||||
fs.writeFileSync(commentFilePath, sampleCommentContent)
|
||||
|
||||
describe "when a file doesn't exist", ->
|
||||
it "calls back with an error", ->
|
||||
errors = []
|
||||
missingPath = path.resolve('/not-a-file.js')
|
||||
expect(fs.existsSync(missingPath)).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [missingPath], (result, error) ->
|
||||
errors.push(error)
|
||||
|
||||
runs ->
|
||||
expect(errors).toHaveLength 1
|
||||
expect(errors[0].path).toBe missingPath
|
||||
|
||||
describe "when called with unopened files", ->
|
||||
it "replaces properly", ->
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
describe "when a buffer is already open", ->
|
||||
it "replaces properly and saves when not modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeFalsy()
|
||||
|
||||
it "does not replace when the path is not specified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample-with-comments.js').then (o) -> editor = o
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'items', [commentFilePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe commentFilePath
|
||||
|
||||
it "does NOT save when modified", ->
|
||||
editor = null
|
||||
results = []
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('sample.js').then (o) -> editor = o
|
||||
|
||||
runs ->
|
||||
editor.buffer.setTextInRange([[0,0],[0,0]], 'omg')
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.replace /items/gi, 'okthen', [filePath], (result) ->
|
||||
results.push(result)
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 1
|
||||
expect(results[0].filePath).toBe filePath
|
||||
expect(results[0].replacements).toBe 6
|
||||
|
||||
expect(editor.isModified()).toBeTruthy()
|
||||
|
||||
@@ -359,7 +359,7 @@ class AtomApplication
|
||||
|
||||
if existingWindow?
|
||||
openedWindow = existingWindow
|
||||
openedWindow.openPath(pathToOpen, initialLine)
|
||||
openedWindow.openPath(pathToOpen, initialLine, initialColumn)
|
||||
if openedWindow.isMinimized()
|
||||
openedWindow.restore()
|
||||
else
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
_ = require 'underscore-plus'
|
||||
ChildProcess = require 'child_process'
|
||||
{Emitter} = require 'event-kit'
|
||||
path = require 'path'
|
||||
|
||||
# Extended: A wrapper which provides standard error/output line buffering for
|
||||
# Node's ChildProcess.
|
||||
@@ -201,7 +202,7 @@ class BufferedProcess
|
||||
|
||||
getCmdPath: ->
|
||||
if process.env.comspec
|
||||
process.env.compec
|
||||
process.env.comspec
|
||||
else if process.env.SystemRoot
|
||||
path.join(process.env.SystemRoot, 'System32', 'cmd.exe')
|
||||
else
|
||||
|
||||
@@ -16,6 +16,11 @@ module.exports =
|
||||
type: 'boolean'
|
||||
default: true
|
||||
title: 'Exclude VCS Ignored Paths'
|
||||
followSymlinks:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
title: 'Follow symlinks'
|
||||
description: 'Used when searching and when opening files with the fuzzy finder.'
|
||||
disabledPackages:
|
||||
type: 'array'
|
||||
default: []
|
||||
@@ -93,6 +98,11 @@ module.exports =
|
||||
type: ['string', 'null']
|
||||
|
||||
# These can be used as globals or scoped, thus defaults.
|
||||
completions:
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
default: []
|
||||
fontFamily:
|
||||
type: 'string'
|
||||
default: ''
|
||||
@@ -158,9 +168,9 @@ module.exports =
|
||||
description: 'Disabling will improve editor font rendering but reduce scrolling performance.'
|
||||
useShadowDOM:
|
||||
type: 'boolean'
|
||||
default: false
|
||||
default: true
|
||||
title: 'Use Shadow DOM'
|
||||
description: 'Enable to test out themes and packages with the new shadow DOM before it ships by default.'
|
||||
description: 'Disable if you experience styling issues with packages or themes. Be sure to open an issue on the relevant package or theme, because this option is going away eventually.'
|
||||
confirmCheckoutHeadRevision:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
|
||||
+244
-176
@@ -313,13 +313,14 @@ class Config
|
||||
@defaultSettings = {}
|
||||
@settings = {}
|
||||
@scopedSettingsStore = new ScopedPropertyStore
|
||||
@usersScopedSettings = new CompositeDisposable
|
||||
@usersScopedSettingPriority = {priority: 1000}
|
||||
@configFileHasErrors = false
|
||||
@configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson'])
|
||||
@configFilePath ?= path.join(@configDirPath, 'config.cson')
|
||||
@transactDepth = 0
|
||||
|
||||
@debouncedSave = _.debounce(@save, 100)
|
||||
@debouncedLoad = _.debounce(@loadUserConfig, 100)
|
||||
|
||||
###
|
||||
Section: Config Subscription
|
||||
###
|
||||
@@ -338,32 +339,36 @@ class Config
|
||||
# # do stuff with value
|
||||
# ```
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` {String} name of the key to observe
|
||||
# * `options` {Object}
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `callback` {Function} to call when the value of the key changes.
|
||||
# * `value` the new value of the key
|
||||
#
|
||||
# Returns a {Disposable} with the following keys on which you can call
|
||||
# `.dispose()` to unsubscribe.
|
||||
observe: (scopeDescriptor, keyPath, options, callback) ->
|
||||
args = Array::slice.call(arguments)
|
||||
if args.length is 2
|
||||
# observe(keyPath, callback)
|
||||
[keyPath, callback, scopeDescriptor, options] = args
|
||||
else if args.length is 3 and (Array.isArray(scopeDescriptor) or scopeDescriptor instanceof ScopeDescriptor)
|
||||
# observe(scopeDescriptor, keyPath, callback)
|
||||
[scopeDescriptor, keyPath, callback, options] = args
|
||||
else if args.length is 3 and _.isString(scopeDescriptor) and _.isObject(keyPath)
|
||||
# observe(keyPath, options, callback) # Deprecated!
|
||||
[keyPath, options, callback, scopeDescriptor] = args
|
||||
|
||||
message = ""
|
||||
message = "`callNow` was set to false. Use ::onDidChange instead. Note that ::onDidChange calls back with different arguments." if options.callNow == false
|
||||
Grim.deprecate "Config::observe no longer supports options; see https://atom.io/docs/api/latest/Config. #{message}"
|
||||
observe: ->
|
||||
if arguments.length is 2
|
||||
[keyPath, callback] = arguments
|
||||
else if arguments.length is 3 and (_.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor)
|
||||
Grim.deprecate """
|
||||
Passing a scope descriptor as the first argument to Config::observe is deprecated.
|
||||
Pass a `scope` in an options hash as the third argument instead.
|
||||
"""
|
||||
[scopeDescriptor, keyPath, callback] = arguments
|
||||
else if arguments.length is 3 and (_.isString(arguments[0]) and _.isObject(arguments[1]))
|
||||
[keyPath, options, callback] = arguments
|
||||
scopeDescriptor = options.scope
|
||||
if options.callNow?
|
||||
Grim.deprecate """
|
||||
Config::observe no longer takes a `callNow` option. Use ::onDidChange instead.
|
||||
Note that ::onDidChange passes its callback different arguments.
|
||||
See https://atom.io/docs/api/latest/Config
|
||||
"""
|
||||
else
|
||||
console.error 'An unsupported form of Config::observe is being used. See https://atom.io/docs/api/latest/Config for details'
|
||||
return
|
||||
@@ -376,13 +381,14 @@ class Config
|
||||
# Essential: Add a listener for changes to a given key path. If `keyPath` is
|
||||
# not specified, your callback will be called on changes to any key.
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` (optional) {String} name of the key to observe. Must be
|
||||
# specified if `scopeDescriptor` is specified.
|
||||
# * `optional` (optional) {Object}
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `callback` {Function} to call when the value of the key changes.
|
||||
# * `event` {Object}
|
||||
# * `newValue` the new value of the key
|
||||
@@ -391,12 +397,20 @@ class Config
|
||||
#
|
||||
# Returns a {Disposable} with the following keys on which you can call
|
||||
# `.dispose()` to unsubscribe.
|
||||
onDidChange: (scopeDescriptor, keyPath, callback) ->
|
||||
args = Array::slice.call(arguments)
|
||||
onDidChange: ->
|
||||
if arguments.length is 1
|
||||
[callback, scopeDescriptor, keyPath] = args
|
||||
[callback] = arguments
|
||||
else if arguments.length is 2
|
||||
[keyPath, callback, scopeDescriptor] = args
|
||||
[keyPath, callback] = arguments
|
||||
else if _.isArray(arguments[0]) or arguments[0] instanceof ScopeDescriptor
|
||||
Grim.deprecate """
|
||||
Passing a scope descriptor as the first argument to Config::onDidChange is deprecated.
|
||||
Pass a `scope` in an options hash as the third argument instead.
|
||||
"""
|
||||
[scopeDescriptor, keyPath, callback] = arguments
|
||||
else
|
||||
[keyPath, options, callback] = arguments
|
||||
scopeDescriptor = options.scope
|
||||
|
||||
if scopeDescriptor?
|
||||
@onDidChangeScopedKeyPath(scopeDescriptor, keyPath, callback)
|
||||
@@ -422,14 +436,14 @@ class Config
|
||||
# files.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 2
|
||||
# ```
|
||||
#
|
||||
# This setting in ruby files might be different than the global tabLength setting
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get('editor.tabLength') # => 4
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 2
|
||||
# ```
|
||||
#
|
||||
# You can get the language scope descriptor via
|
||||
@@ -437,34 +451,72 @@ class Config
|
||||
# for the editor's language.
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get(@editor.getRootScopeDescriptor(), 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: @editor.getRootScopeDescriptor()) # => 2
|
||||
# ```
|
||||
#
|
||||
# Additionally, you can get the setting at the specific cursor position.
|
||||
#
|
||||
# ```coffee
|
||||
# scopeDescriptor = @editor.getLastCursor().getScopeDescriptor()
|
||||
# atom.config.get(scopeDescriptor, 'editor.tabLength') # => 2
|
||||
# atom.config.get('editor.tabLength', scope: scopeDescriptor) # => 2
|
||||
# ```
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key to retrieve.
|
||||
# * `options` (optional) {Object}
|
||||
# * `sources` (optional) {Array} of {String} source names. If provided, only
|
||||
# values that were associated with these sources during {::set} will be used.
|
||||
# * `excludeSources` (optional) {Array} of {String} source names. If provided,
|
||||
# values that were associated with these sources during {::set} will not
|
||||
# be used.
|
||||
# * `scope` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
# file in the type specified by the configuration schema.
|
||||
get: (scopeDescriptor, keyPath) ->
|
||||
if arguments.length == 1
|
||||
# cannot assign to keyPath for the sake of v8 optimization
|
||||
globalKeyPath = scopeDescriptor
|
||||
@getRawValue(globalKeyPath)
|
||||
get: ->
|
||||
if arguments.length > 1
|
||||
if typeof arguments[0] is 'string' or not arguments[0]?
|
||||
[keyPath, options] = arguments
|
||||
{scope} = options
|
||||
else
|
||||
Grim.deprecate """
|
||||
Passing a scope descriptor as the first argument to Config::get is deprecated.
|
||||
Pass a `scope` in an options hash as the final argument instead.
|
||||
"""
|
||||
[scope, keyPath] = arguments
|
||||
else
|
||||
value = @getRawScopedValue(scopeDescriptor, keyPath)
|
||||
value ?= @getRawValue(keyPath)
|
||||
value
|
||||
[keyPath] = arguments
|
||||
|
||||
if scope?
|
||||
value = @getRawScopedValue(scope, keyPath, options)
|
||||
value ? @getRawValue(keyPath, options)
|
||||
else
|
||||
@getRawValue(keyPath, options)
|
||||
|
||||
# Extended: Get all of the values for the given key-path, along with their
|
||||
# associated scope selector.
|
||||
#
|
||||
# * `keyPath` The {String} name of the key to retrieve
|
||||
# * `options` (optional) {Object} see the `options` argument to {::get}
|
||||
#
|
||||
# Returns an {Array} of {Object}s with the following keys:
|
||||
# * `scopeSelector` The scope-selector {String} with which the value is associated
|
||||
# * `value` The value for the key-path
|
||||
getAll: (keyPath, options) ->
|
||||
{scope, sources} = options if options?
|
||||
result = []
|
||||
|
||||
if scope?
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scope)
|
||||
result = result.concat @scopedSettingsStore.getAll(scopeDescriptor.getScopeChain(), keyPath, options)
|
||||
|
||||
if globalValue = @getRawValue(keyPath, options)
|
||||
result.push(scopeSelector: '*', value: globalValue)
|
||||
|
||||
result
|
||||
|
||||
# Essential: Sets the value for a configuration setting.
|
||||
#
|
||||
@@ -483,75 +535,113 @@ class Config
|
||||
#
|
||||
# ```coffee
|
||||
# atom.config.get('editor.tabLength') # => 4
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 4
|
||||
# atom.config.get(['source.js'], 'editor.tabLength') # => 4
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 4
|
||||
# atom.config.get('editor.tabLength', scope: ['source.js']) # => 4
|
||||
#
|
||||
# # Set ruby to 2
|
||||
# atom.config.set('source.ruby', 'editor.tabLength', 2) # => true
|
||||
# atom.config.set('editor.tabLength', 2, scopeSelector: 'source.ruby') # => true
|
||||
#
|
||||
# # Notice it's only set to 2 in the case of ruby
|
||||
# atom.config.get('editor.tabLength') # => 4
|
||||
# atom.config.get(['source.ruby'], 'editor.tabLength') # => 2
|
||||
# atom.config.get(['source.js'], 'editor.tabLength') # => 4
|
||||
# atom.config.get('editor.tabLength', scope: ['source.ruby']) # => 2
|
||||
# atom.config.get('editor.tabLength', scope: ['source.js']) # => 4
|
||||
# ```
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key.
|
||||
# * `value` The value of the setting. Passing `undefined` will revert the
|
||||
# setting to the default value.
|
||||
# * `options` (optional) {Object}
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `source` (optional) {String} The name of a file with which the setting
|
||||
# is associated. Defaults to the user's config file.
|
||||
#
|
||||
# Returns a {Boolean}
|
||||
# * `true` if the value was set.
|
||||
# * `false` if the value was not able to be coerced to the type specified in the setting's schema.
|
||||
set: (scopeSelector, keyPath, value) ->
|
||||
if arguments.length < 3
|
||||
value = keyPath
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = undefined
|
||||
set: ->
|
||||
if arguments[0]?[0] is '.'
|
||||
Grim.deprecate """
|
||||
Passing a scope selector as the first argument to Config::set is deprecated.
|
||||
Pass a `scopeSelector` in an options hash as the final argument instead.
|
||||
"""
|
||||
[scopeSelector, keyPath, value] = arguments
|
||||
else
|
||||
[keyPath, value, options] = arguments
|
||||
scopeSelector = options?.scopeSelector
|
||||
source = options?.source
|
||||
shouldSave = options?.save ? true
|
||||
|
||||
unless value == undefined
|
||||
if source and not scopeSelector
|
||||
throw new Error("::set with a 'source' and no 'sourceSelector' is not yet implemented!")
|
||||
|
||||
source ?= @getUserConfigPath()
|
||||
|
||||
unless value is undefined
|
||||
try
|
||||
value = @makeValueConformToSchema(keyPath, value)
|
||||
catch e
|
||||
return false
|
||||
|
||||
if scopeSelector?
|
||||
@setRawScopedValue(scopeSelector, keyPath, value)
|
||||
@setRawScopedValue(source, scopeSelector, keyPath, value)
|
||||
else
|
||||
@setRawValue(keyPath, value)
|
||||
|
||||
@save() unless @configFileHasErrors
|
||||
@debouncedSave() if source is @getUserConfigPath() and shouldSave and not @configFileHasErrors
|
||||
true
|
||||
|
||||
# Extended: Restore the global setting at `keyPath` to its default value.
|
||||
# Essential: Restore the setting at `keyPath` to its default value.
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key.
|
||||
# * `options` (optional) {Object}
|
||||
# * `scopeSelector` (optional) {String}. See {::set}
|
||||
# * `source` (optional) {String}. See {::set}
|
||||
unset: (keyPath, options) ->
|
||||
if typeof options is 'string'
|
||||
Grim.deprecate """
|
||||
Passing a scope selector as the first argument to Config::unset is deprecated.
|
||||
Pass a `scopeSelector` in an options hash as the second argument instead.
|
||||
"""
|
||||
scopeSelector = keyPath
|
||||
keyPath = options
|
||||
else
|
||||
{scopeSelector, source} = options ? {}
|
||||
|
||||
source ?= @getUserConfigPath()
|
||||
|
||||
if scopeSelector?
|
||||
if keyPath?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector(source, scopeSelector)
|
||||
if _.valueForKeyPath(settings, keyPath)?
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector(source, scopeSelector)
|
||||
_.setValueForKeyPath(settings, keyPath, undefined)
|
||||
settings = withoutEmptyObjects(settings)
|
||||
@set(null, settings, {scopeSelector, source, priority: @priorityForSource(source)}) if settings?
|
||||
@debouncedSave()
|
||||
else
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector(source, scopeSelector)
|
||||
@emitChangeEvent()
|
||||
else
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
if keyPath?
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
|
||||
# Extended: Get an {Array} of all of the `source` {String}s with which
|
||||
# settings have been added via {::set}.
|
||||
getSources: ->
|
||||
_.uniq(_.pluck(@scopedSettingsStore.propertySets, 'source')).sort()
|
||||
|
||||
# Deprecated: Restore the global setting at `keyPath` to its default value.
|
||||
#
|
||||
# Returns the new value.
|
||||
restoreDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
Grim.deprecate("Use ::unset instead.")
|
||||
@unset(scopeSelector, keyPath)
|
||||
@get(keyPath)
|
||||
|
||||
if scopeSelector?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
if _.valueForKeyPath(settings, keyPath)?
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
_.setValueForKeyPath(settings, keyPath, undefined)
|
||||
settings = withoutEmptyObjects(settings)
|
||||
@addScopedSettings('user-config', scopeSelector, settings, @usersScopedSettingPriority) if settings?
|
||||
@save() unless @configFileHasErrors
|
||||
@getDefault(scopeSelector, keyPath)
|
||||
else
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
@get(keyPath)
|
||||
|
||||
# Extended: Get the global default value of the key path. _Please note_ that in most
|
||||
# Deprecated: Get the global default value of the key path. _Please note_ that in most
|
||||
# cases calling this is not necessary! {::get} returns the default value when
|
||||
# a custom value is not specified.
|
||||
#
|
||||
@@ -559,35 +649,30 @@ class Config
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns the default value.
|
||||
getDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
defaultValue = @scopedSettingsStore.getPropertyValue(scopeSelector, keyPath, excludeSources: ['user-config'])
|
||||
defaultValue ?= _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
getDefault: ->
|
||||
Grim.deprecate("Use `::get(keyPath, {scope, excludeSources: [atom.config.getUserConfigPath()]})` instead")
|
||||
if arguments.length is 1
|
||||
[keyPath] = arguments
|
||||
else
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
_.deepClone(defaultValue)
|
||||
[scopeSelector, keyPath] = arguments
|
||||
scope = [scopeSelector]
|
||||
@get(keyPath, {scope, excludeSources: [@getUserConfigPath()]})
|
||||
|
||||
# Extended: Is the value at `keyPath` its default value?
|
||||
# Deprecated: Is the value at `keyPath` its default value?
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns a {Boolean}, `true` if the current value is the default, `false`
|
||||
# otherwise.
|
||||
isDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
not _.valueForKeyPath(settings, keyPath)?
|
||||
isDefault: ->
|
||||
Grim.deprecate("Use `not ::get(keyPath, {scope, sources: [atom.config.getUserConfigPath()]})?` instead")
|
||||
if arguments.length is 1
|
||||
[keyPath] = arguments
|
||||
else
|
||||
not _.valueForKeyPath(@settings, keyPath)?
|
||||
[scopeSelector, keyPath] = arguments
|
||||
scope = [scopeSelector]
|
||||
not @get(keyPath, {scope, sources: [@getUserConfigPath()]})?
|
||||
|
||||
# Extended: Retrieve the schema for a specific key path. The schema will tell
|
||||
# you what type the keyPath expects, and other metadata about the config
|
||||
@@ -736,7 +821,7 @@ class Config
|
||||
observeUserConfig: ->
|
||||
try
|
||||
@watchSubscription ?= pathWatcher.watch @configFilePath, (eventType) =>
|
||||
@loadUserConfig() if eventType is 'change' and @watchSubscription?
|
||||
@debouncedLoad() if eventType is 'change' and @watchSubscription?
|
||||
catch error
|
||||
@notifyFailure('Failed to watch user config', error)
|
||||
|
||||
@@ -752,8 +837,8 @@ class Config
|
||||
console.error detail
|
||||
|
||||
save: ->
|
||||
allSettings = global: @settings
|
||||
allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource('user-config')
|
||||
allSettings = {'*': @settings}
|
||||
allSettings = _.extend allSettings, @scopedSettingsStore.propertiesForSource(@getUserConfigPath())
|
||||
CSON.writeFileSync(@configFilePath, allSettings)
|
||||
|
||||
###
|
||||
@@ -767,40 +852,24 @@ class Config
|
||||
return
|
||||
|
||||
if newSettings.global?
|
||||
newSettings['*'] = newSettings.global
|
||||
delete newSettings.global
|
||||
|
||||
if newSettings['*']?
|
||||
scopedSettings = newSettings
|
||||
newSettings = newSettings.global
|
||||
delete scopedSettings.global
|
||||
newSettings = newSettings['*']
|
||||
delete scopedSettings['*']
|
||||
@resetUserScopedSettings(scopedSettings)
|
||||
|
||||
unsetUnspecifiedValues = (keyPath, value) =>
|
||||
if isPlainObject(value)
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of value
|
||||
continue unless value.hasOwnProperty(key)
|
||||
unsetUnspecifiedValues(keys.concat([key]).join('.'), childValue)
|
||||
else
|
||||
@setRawValue(keyPath, undefined) unless _.valueForKeyPath(newSettings, keyPath)?
|
||||
return
|
||||
@transact =>
|
||||
@settings = {}
|
||||
@set(key, value, save: false) for key, value of newSettings
|
||||
|
||||
@setRecursive(null, newSettings)
|
||||
unsetUnspecifiedValues(null, @settings)
|
||||
|
||||
setRecursive: (keyPath, value) ->
|
||||
if isPlainObject(value)
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of value
|
||||
continue unless value.hasOwnProperty(key)
|
||||
@setRecursive(keys.concat([key]).join('.'), childValue)
|
||||
else
|
||||
try
|
||||
value = @makeValueConformToSchema(keyPath, value)
|
||||
@setRawValue(keyPath, value)
|
||||
catch e
|
||||
console.warn("'#{keyPath}' could not be set. Attempted value: #{JSON.stringify(value)}; Schema: #{JSON.stringify(@getSchema(keyPath))}")
|
||||
|
||||
getRawValue: (keyPath) ->
|
||||
value = _.valueForKeyPath(@settings, keyPath)
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
getRawValue: (keyPath, options) ->
|
||||
unless options?.excludeSources?.indexOf(@getUserConfigPath()) >= 0
|
||||
value = _.valueForKeyPath(@settings, keyPath)
|
||||
unless options?.sources?.length > 0
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
|
||||
if value?
|
||||
value = _.deepClone(value)
|
||||
@@ -814,7 +883,10 @@ class Config
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
value = undefined if _.isEqual(defaultValue, value)
|
||||
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
if keyPath?
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
else
|
||||
@settings = value
|
||||
@emitChangeEvent()
|
||||
|
||||
observeKeyPath: (keyPath, options, callback) ->
|
||||
@@ -823,13 +895,12 @@ class Config
|
||||
|
||||
onDidChangeKeyPath: (keyPath, callback) ->
|
||||
oldValue = @get(keyPath)
|
||||
|
||||
didChange = =>
|
||||
@emitter.on 'did-change', =>
|
||||
newValue = @get(keyPath)
|
||||
callback({oldValue, newValue}) unless _.isEqual(oldValue, newValue)
|
||||
oldValue = newValue
|
||||
|
||||
@emitter.on 'did-change', didChange
|
||||
unless _.isEqual(oldValue, newValue)
|
||||
event = {oldValue, newValue}
|
||||
oldValue = newValue
|
||||
callback(event)
|
||||
|
||||
isSubKeyPath: (keyPath, subKeyPath) ->
|
||||
return false unless keyPath? and subKeyPath?
|
||||
@@ -897,16 +968,23 @@ class Config
|
||||
Section: Private Scoped Settings
|
||||
###
|
||||
|
||||
priorityForSource: (source) ->
|
||||
if source is @getUserConfigPath()
|
||||
1000
|
||||
else
|
||||
0
|
||||
|
||||
emitChangeEvent: ->
|
||||
@emitter.emit 'did-change' unless @transactDepth > 0
|
||||
|
||||
resetUserScopedSettings: (newScopedSettings) ->
|
||||
@usersScopedSettings?.dispose()
|
||||
@usersScopedSettings = new CompositeDisposable
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', newScopedSettings, @usersScopedSettingPriority)
|
||||
source = @getUserConfigPath()
|
||||
@scopedSettingsStore.removePropertiesForSource(source)
|
||||
@scopedSettingsStore.addProperties(source, newScopedSettings, priority: @priorityForSource(source))
|
||||
@emitChangeEvent()
|
||||
|
||||
addScopedSettings: (source, selector, value, options) ->
|
||||
Grim.deprecate("Use ::set instead")
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
disposable = @scopedSettingsStore.addProperties(source, settingsBySelector, options)
|
||||
@@ -915,7 +993,7 @@ class Config
|
||||
disposable.dispose()
|
||||
@emitChangeEvent()
|
||||
|
||||
setRawScopedValue: (selector, keyPath, value) ->
|
||||
setRawScopedValue: (source, selector, keyPath, value) ->
|
||||
if keyPath?
|
||||
newValue = {}
|
||||
_.setValueForKeyPath(newValue, keyPath, value)
|
||||
@@ -923,40 +1001,30 @@ class Config
|
||||
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', settingsBySelector, @usersScopedSettingPriority)
|
||||
@scopedSettingsStore.addProperties(source, settingsBySelector, priority: @priorityForSource(source))
|
||||
@emitChangeEvent()
|
||||
|
||||
getRawScopedValue: (scopeDescriptor, keyPath) ->
|
||||
getRawScopedValue: (scopeDescriptor, keyPath, options) ->
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor)
|
||||
@scopedSettingsStore.getPropertyValue(scopeDescriptor.getScopeChain(), keyPath)
|
||||
@scopedSettingsStore.getPropertyValue(scopeDescriptor.getScopeChain(), keyPath, options)
|
||||
|
||||
observeScopedKeyPath: (scopeDescriptor, keyPath, callback) ->
|
||||
oldValue = @get(scopeDescriptor, keyPath)
|
||||
observeScopedKeyPath: (scope, keyPath, callback) ->
|
||||
callback(@get(keyPath, {scope}))
|
||||
@onDidChangeScopedKeyPath scope, keyPath, (event) -> callback(event.newValue)
|
||||
|
||||
callback(oldValue)
|
||||
onDidChangeScopedKeyPath: (scope, keyPath, callback) ->
|
||||
oldValue = @get(keyPath, {scope})
|
||||
@emitter.on 'did-change', =>
|
||||
newValue = @get(keyPath, {scope})
|
||||
unless _.isEqual(oldValue, newValue)
|
||||
event = {oldValue, newValue}
|
||||
oldValue = newValue
|
||||
callback(event)
|
||||
|
||||
didChange = =>
|
||||
newValue = @get(scopeDescriptor, keyPath)
|
||||
callback(newValue) unless _.isEqual(oldValue, newValue)
|
||||
oldValue = newValue
|
||||
|
||||
@emitter.on 'did-change', didChange
|
||||
|
||||
onDidChangeScopedKeyPath: (scopeDescriptor, keyPath, callback) ->
|
||||
oldValue = @get(scopeDescriptor, keyPath)
|
||||
didChange = =>
|
||||
newValue = @get(scopeDescriptor, keyPath)
|
||||
callback({oldValue, newValue}) unless _.isEqual(oldValue, newValue)
|
||||
oldValue = newValue
|
||||
|
||||
@emitter.on 'did-change', didChange
|
||||
|
||||
# TODO: figure out how to change / remove this. The return value is awkward.
|
||||
# * language mode uses it for one thing.
|
||||
# * autocomplete uses it for editor.completions
|
||||
settingsForScopeDescriptor: (scopeDescriptor, keyPath) ->
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor)
|
||||
@scopedSettingsStore.getProperties(scopeDescriptor.getScopeChain(), keyPath)
|
||||
Grim.deprecate("Use Config::getAll instead")
|
||||
entries = @getAll(null, scope: scopeDescriptor)
|
||||
value for {value} in entries when _.valueForKeyPath(value, keyPath)?
|
||||
|
||||
# Base schema enforcers. These will coerce raw input into the specified type,
|
||||
# and will throw an error when the value cannot be coerced. Throwing the error
|
||||
|
||||
+11
-5
@@ -202,14 +202,20 @@ class Cursor extends Model
|
||||
[before, after] = @editor.getTextInBufferRange(range)
|
||||
return false if /\s/.test(before) or /\s/.test(after)
|
||||
|
||||
nonWordCharacters = atom.config.get(@getScopeDescriptor(), 'editor.nonWordCharacters').split('')
|
||||
nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()).split('')
|
||||
_.contains(nonWordCharacters, before) isnt _.contains(nonWordCharacters, after)
|
||||
|
||||
# Public: Returns whether this cursor is between a word's start and end.
|
||||
isInsideWord: ->
|
||||
#
|
||||
# * `options` (optional) {Object}
|
||||
# * `wordRegex` A {RegExp} indicating what constitutes a "word"
|
||||
# (default: {::wordRegExp}).
|
||||
#
|
||||
# Returns a {Boolean}
|
||||
isInsideWord: (options) ->
|
||||
{row, column} = @getBufferPosition()
|
||||
range = [[row, column], [row, Infinity]]
|
||||
@editor.getTextInBufferRange(range).search(@wordRegExp()) == 0
|
||||
@editor.getTextInBufferRange(range).search(options?.wordRegex ? @wordRegExp()) == 0
|
||||
|
||||
# Public: Returns the indentation level of the current line.
|
||||
getIndentLevel: ->
|
||||
@@ -544,7 +550,7 @@ class Cursor extends Model
|
||||
# Returns a {Range}
|
||||
getBeginningOfNextWordBufferPosition: (options = {}) ->
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
start = if @isInsideWord() then @getEndOfCurrentWordBufferPosition() else currentBufferPosition
|
||||
start = if @isInsideWord(options) then @getEndOfCurrentWordBufferPosition(options) else currentBufferPosition
|
||||
scanRange = [start, @editor.getEofBufferPosition()]
|
||||
|
||||
beginningOfNextWordPosition = null
|
||||
@@ -636,7 +642,7 @@ class Cursor extends Model
|
||||
# Returns a {RegExp}.
|
||||
wordRegExp: ({includeNonWordCharacters}={}) ->
|
||||
includeNonWordCharacters ?= true
|
||||
nonWordCharacters = atom.config.get(@getScopeDescriptor(), 'editor.nonWordCharacters')
|
||||
nonWordCharacters = atom.config.get('editor.nonWordCharacters', scope: @getScopeDescriptor())
|
||||
segments = ["^[\t ]*$"]
|
||||
segments.push("[^\\s#{_.escapeRegExp(nonWordCharacters)}]+")
|
||||
if includeNonWordCharacters
|
||||
|
||||
@@ -67,24 +67,24 @@ class DisplayBuffer extends Model
|
||||
|
||||
oldConfigSettings = @configSettings
|
||||
@configSettings =
|
||||
scrollPastEnd: atom.config.get(scopeDescriptor, 'editor.scrollPastEnd')
|
||||
softWrap: atom.config.get(scopeDescriptor, 'editor.softWrap')
|
||||
softWrapAtPreferredLineLength: atom.config.get(scopeDescriptor, 'editor.softWrapAtPreferredLineLength')
|
||||
preferredLineLength: atom.config.get(scopeDescriptor, 'editor.preferredLineLength')
|
||||
scrollPastEnd: atom.config.get('editor.scrollPastEnd', scope: scopeDescriptor)
|
||||
softWrap: atom.config.get('editor.softWrap', scope: scopeDescriptor)
|
||||
softWrapAtPreferredLineLength: atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor)
|
||||
preferredLineLength: atom.config.get('editor.preferredLineLength', scope: scopeDescriptor)
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.softWrap', ({newValue}) =>
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrap', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrap = newValue
|
||||
@updateWrappedScreenLines()
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.softWrapAtPreferredLineLength', ({newValue}) =>
|
||||
subscriptions.add atom.config.onDidChange 'editor.softWrapAtPreferredLineLength', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.softWrapAtPreferredLineLength = newValue
|
||||
@updateWrappedScreenLines() if @isSoftWrapped()
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.preferredLineLength', ({newValue}) =>
|
||||
subscriptions.add atom.config.onDidChange 'editor.preferredLineLength', scope: scopeDescriptor, ({newValue}) =>
|
||||
@configSettings.preferredLineLength = newValue
|
||||
@updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get(scopeDescriptor, 'editor.softWrapAtPreferredLineLength')
|
||||
@updateWrappedScreenLines() if @isSoftWrapped() and atom.config.get('editor.softWrapAtPreferredLineLength', scope: scopeDescriptor)
|
||||
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.scrollPastEnd', (value) =>
|
||||
subscriptions.add atom.config.observe 'editor.scrollPastEnd', scope: scopeDescriptor, (value) =>
|
||||
@configSettings.scrollPastEnd = value
|
||||
|
||||
@updateWrappedScreenLines() if oldConfigSettings? and not _.isEqual(oldConfigSettings, @configSettings)
|
||||
|
||||
@@ -67,5 +67,5 @@ class GrammarRegistry extends FirstMate.GrammarRegistry
|
||||
atom.config.getRawScopedValue(scope, keyPath)
|
||||
|
||||
propertiesForScope: (scope, keyPath) ->
|
||||
deprecate 'A direct (but private) replacement is available at atom.config.scopedSettingsForScopeDescriptor().'
|
||||
deprecate 'Use atom.config.getAll instead.'
|
||||
atom.config.settingsForScopeDescriptor(scope, keyPath)
|
||||
|
||||
@@ -26,17 +26,16 @@ class LanguageMode
|
||||
#
|
||||
# startRow - The row {Number} to start at
|
||||
# endRow - The row {Number} to end at
|
||||
#
|
||||
# Returns an {Array} of the commented {Ranges}.
|
||||
toggleLineCommentsForBufferRows: (start, end) ->
|
||||
scopeDescriptor = @editor.scopeDescriptorForBufferPosition([start, 0])
|
||||
properties = atom.config.settingsForScopeDescriptor(scopeDescriptor, 'editor.commentStart')[0]
|
||||
return unless properties
|
||||
scope = @editor.scopeDescriptorForBufferPosition([start, 0])
|
||||
commentStartEntry = atom.config.getAll('editor.commentStart', {scope})[0]
|
||||
|
||||
commentStartString = _.valueForKeyPath(properties, 'editor.commentStart')
|
||||
commentEndString = _.valueForKeyPath(properties, 'editor.commentEnd')
|
||||
return unless commentStartEntry?
|
||||
|
||||
return unless commentStartString
|
||||
commentEndEntry = atom.config.getAll('editor.commentEnd', {scope}).find (entry) ->
|
||||
entry.scopeSelector is commentStartEntry.scopeSelector
|
||||
commentStartString = commentStartEntry?.value
|
||||
commentEndString = commentEndEntry?.value
|
||||
|
||||
buffer = @editor.buffer
|
||||
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '(?:$1)?')
|
||||
@@ -96,6 +95,7 @@ class LanguageMode
|
||||
buffer.insert([row, indentLength], commentStartString)
|
||||
else
|
||||
buffer.setTextInRange([[row, 0], [row, indentString.length]], indentString + commentStartString)
|
||||
return
|
||||
|
||||
# Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
@@ -113,6 +113,7 @@ class LanguageMode
|
||||
#
|
||||
# indentLevel - A {Number} indicating indentLevel; 0 based.
|
||||
foldAllAtIndentLevel: (indentLevel) ->
|
||||
@unfoldAll()
|
||||
for currentRow in [0..@buffer.getLastRow()]
|
||||
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
continue unless startRow?
|
||||
@@ -316,7 +317,7 @@ class LanguageMode
|
||||
@editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
||||
|
||||
getRegexForProperty: (scopeDescriptor, property) ->
|
||||
if pattern = atom.config.get(scopeDescriptor, property)
|
||||
if pattern = atom.config.get(property, scope: scopeDescriptor)
|
||||
new OnigRegExp(pattern)
|
||||
|
||||
increaseIndentRegexForScopeDescriptor: (scopeDescriptor) ->
|
||||
|
||||
@@ -295,12 +295,12 @@ class PackageManager
|
||||
pack = new Package(packagePath, metadata)
|
||||
pack.load()
|
||||
@loadedPackages[pack.name] = pack
|
||||
pack
|
||||
return pack
|
||||
catch error
|
||||
console.warn "Failed to load package.json '#{path.basename(packagePath)}'", error.stack ? error
|
||||
|
||||
else
|
||||
throw new Error("Could not resolve '#{nameOrPath}' to a package path")
|
||||
console.warn "Could not resolve '#{nameOrPath}' to a package path"
|
||||
null
|
||||
|
||||
unloadPackages: ->
|
||||
@unloadPackage(name) for name in _.keys(@loadedPackages)
|
||||
@@ -337,11 +337,12 @@ class PackageManager
|
||||
activatePackage: (name) ->
|
||||
if pack = @getActivePackage(name)
|
||||
Q(pack)
|
||||
else
|
||||
pack = @loadPackage(name)
|
||||
else if pack = @loadPackage(name)
|
||||
pack.activate().then =>
|
||||
@activePackages[pack.name] = pack
|
||||
pack
|
||||
else
|
||||
Q.reject(new Error("Failed to load package '#{name}'"))
|
||||
|
||||
# Deactivate all packages
|
||||
deactivatePackages: ->
|
||||
|
||||
+24
-19
@@ -9,7 +9,6 @@ EmitterMixin = require('emissary').Emitter
|
||||
Q = require 'q'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
$ = null # Defer require in case this is in the window-less browser process
|
||||
ModuleCache = require './module-cache'
|
||||
ScopedProperties = require './scoped-properties'
|
||||
|
||||
@@ -52,7 +51,7 @@ class Package
|
||||
stylesheets: null
|
||||
stylesheetDisposables: null
|
||||
grammars: null
|
||||
scopedProperties: null
|
||||
settings: null
|
||||
mainModulePath: null
|
||||
resolvedMainModulePath: false
|
||||
mainModule: null
|
||||
@@ -118,7 +117,7 @@ class Package
|
||||
@loadKeymaps()
|
||||
@loadMenus()
|
||||
@loadStylesheets()
|
||||
@scopedPropertiesPromise = @loadScopedProperties()
|
||||
@settingsPromise = @loadSettings()
|
||||
@requireMainModule() unless @hasActivationCommands()
|
||||
|
||||
catch error
|
||||
@@ -130,7 +129,7 @@ class Package
|
||||
@keymaps = []
|
||||
@menus = []
|
||||
@grammars = []
|
||||
@scopedProperties = []
|
||||
@settings = []
|
||||
|
||||
activate: ->
|
||||
@grammarsPromise ?= @loadGrammars()
|
||||
@@ -144,7 +143,7 @@ class Package
|
||||
else
|
||||
@activateNow()
|
||||
|
||||
Q.all([@grammarsPromise, @scopedPropertiesPromise, @activationDeferred.promise])
|
||||
Q.all([@grammarsPromise, @settingsPromise, @activationDeferred.promise])
|
||||
|
||||
activateNow: ->
|
||||
try
|
||||
@@ -199,8 +198,8 @@ class Package
|
||||
grammar.activate() for grammar in @grammars
|
||||
@grammarsActivated = true
|
||||
|
||||
scopedProperties.activate() for scopedProperties in @scopedProperties
|
||||
@scopedPropertiesActivated = true
|
||||
settings.activate() for settings in @settings
|
||||
@settingsActivated = true
|
||||
|
||||
loadKeymaps: ->
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
@@ -283,22 +282,28 @@ class Package
|
||||
async.each grammarPaths, loadGrammar, -> deferred.resolve()
|
||||
deferred.promise
|
||||
|
||||
loadScopedProperties: ->
|
||||
@scopedProperties = []
|
||||
loadSettings: ->
|
||||
@settings = []
|
||||
|
||||
loadScopedPropertiesFile = (scopedPropertiesPath, callback) =>
|
||||
ScopedProperties.load scopedPropertiesPath, (error, scopedProperties) =>
|
||||
loadSettingsFile = (settingsPath, callback) =>
|
||||
ScopedProperties.load settingsPath, (error, settings) =>
|
||||
if error?
|
||||
console.warn("Failed to load scoped properties: #{scopedPropertiesPath}", error.stack ? error)
|
||||
console.warn("Failed to load package settings: #{settingsPath}", error.stack ? error)
|
||||
else
|
||||
@scopedProperties.push(scopedProperties)
|
||||
scopedProperties.activate() if @scopedPropertiesActivated
|
||||
@settings.push(settings)
|
||||
settings.activate() if @settingsActivated
|
||||
callback()
|
||||
|
||||
deferred = Q.defer()
|
||||
scopedPropertiesDirPath = path.join(@path, 'scoped-properties')
|
||||
fs.list scopedPropertiesDirPath, ['json', 'cson'], (error, scopedPropertiesPaths=[]) ->
|
||||
async.each scopedPropertiesPaths, loadScopedPropertiesFile, -> deferred.resolve()
|
||||
|
||||
if fs.isDirectorySync(path.join(@path, 'scoped-properties'))
|
||||
settingsDirPath = path.join(@path, 'scoped-properties')
|
||||
deprecate("Store package settings files in the `settings` directory instead of `scoped-properties`")
|
||||
else
|
||||
settingsDirPath = path.join(@path, 'settings')
|
||||
|
||||
fs.list settingsDirPath, ['json', 'cson'], (error, settingsPaths=[]) ->
|
||||
async.each settingsPaths, loadSettingsFile, -> deferred.resolve()
|
||||
deferred.promise
|
||||
|
||||
serialize: ->
|
||||
@@ -328,12 +333,12 @@ class Package
|
||||
|
||||
deactivateResources: ->
|
||||
grammar.deactivate() for grammar in @grammars
|
||||
scopedProperties.deactivate() for scopedProperties in @scopedProperties
|
||||
settings.deactivate() for settings in @settings
|
||||
@stylesheetDisposables?.dispose()
|
||||
@activationDisposables?.dispose()
|
||||
@stylesheetsActivated = false
|
||||
@grammarsActivated = false
|
||||
@scopedPropertiesActivated = false
|
||||
@settingsActivated = false
|
||||
|
||||
reloadStylesheets: ->
|
||||
oldSheets = _.clone(@stylesheets)
|
||||
|
||||
@@ -153,7 +153,9 @@ class PaneView extends View
|
||||
activeItemModifiedChanged: =>
|
||||
@trigger 'pane:active-item-modified-status-changed'
|
||||
|
||||
@::accessor 'activeView', -> atom.views.getView(@activeItem)?.__spacePenView
|
||||
@::accessor 'activeView', ->
|
||||
element = atom.views.getView(@activeItem)
|
||||
$(element).view() ? element
|
||||
|
||||
splitLeft: (items...) -> atom.views.getView(@model.splitLeft({items})).__spacePenView
|
||||
|
||||
|
||||
+4
-82
@@ -176,91 +176,13 @@ class Project extends Model
|
||||
Section: Searching and Replacing
|
||||
###
|
||||
|
||||
# Public: Performs a search across all the files in the project.
|
||||
#
|
||||
# * `regex` {RegExp} to search with.
|
||||
# * `options` (optional) {Object} (default: {})
|
||||
# * `paths` An {Array} of glob patterns to search within
|
||||
# * `iterator` {Function} callback on each file found
|
||||
scan: (regex, options={}, iterator) ->
|
||||
if _.isFunction(options)
|
||||
iterator = options
|
||||
options = {}
|
||||
Grim.deprecate("Use atom.workspace.scan instead of atom.project.scan")
|
||||
atom.workspace.scan(regex, options, iterator)
|
||||
|
||||
deferred = Q.defer()
|
||||
|
||||
searchOptions =
|
||||
ignoreCase: regex.ignoreCase
|
||||
inclusions: options.paths
|
||||
includeHidden: true
|
||||
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
|
||||
exclusions: atom.config.get('core.ignoredNames')
|
||||
|
||||
# TODO: need to support all paths in @getPaths()
|
||||
task = Task.once require.resolve('./scan-handler'), @getPaths()[0], regex.source, searchOptions, ->
|
||||
deferred.resolve()
|
||||
|
||||
task.on 'scan:result-found', (result) =>
|
||||
iterator(result) unless @isPathModified(result.filePath)
|
||||
|
||||
task.on 'scan:file-error', (error) ->
|
||||
iterator(null, error)
|
||||
|
||||
if _.isFunction(options.onPathsSearched)
|
||||
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
|
||||
options.onPathsSearched(numberOfPathsSearched)
|
||||
|
||||
for buffer in @getBuffers() when buffer.isModified()
|
||||
filePath = buffer.getPath()
|
||||
continue unless @contains(filePath)
|
||||
matches = []
|
||||
buffer.scan regex, (match) -> matches.push match
|
||||
iterator {filePath, matches} if matches.length > 0
|
||||
|
||||
promise = deferred.promise
|
||||
promise.cancel = ->
|
||||
task.terminate()
|
||||
deferred.resolve('cancelled')
|
||||
promise
|
||||
|
||||
# Public: Performs a replace across all the specified files in the project.
|
||||
#
|
||||
# * `regex` A {RegExp} to search with.
|
||||
# * `replacementText` Text to replace all matches of regex with
|
||||
# * `filePaths` List of file path strings to run the replace on.
|
||||
# * `iterator` A {Function} callback on each file with replacements:
|
||||
# * `options` {Object} with keys `filePath` and `replacements`
|
||||
replace: (regex, replacementText, filePaths, iterator) ->
|
||||
deferred = Q.defer()
|
||||
|
||||
openPaths = (buffer.getPath() for buffer in @getBuffers())
|
||||
outOfProcessPaths = _.difference(filePaths, openPaths)
|
||||
|
||||
inProcessFinished = !openPaths.length
|
||||
outOfProcessFinished = !outOfProcessPaths.length
|
||||
checkFinished = ->
|
||||
deferred.resolve() if outOfProcessFinished and inProcessFinished
|
||||
|
||||
unless outOfProcessFinished.length
|
||||
flags = 'g'
|
||||
flags += 'i' if regex.ignoreCase
|
||||
|
||||
task = Task.once require.resolve('./replace-handler'), outOfProcessPaths, regex.source, flags, replacementText, ->
|
||||
outOfProcessFinished = true
|
||||
checkFinished()
|
||||
|
||||
task.on 'replace:path-replaced', iterator
|
||||
task.on 'replace:file-error', (error) -> iterator(null, error)
|
||||
|
||||
for buffer in @getBuffers()
|
||||
continue unless buffer.getPath() in filePaths
|
||||
replacements = buffer.replace(regex, replacementText, iterator)
|
||||
iterator({filePath: buffer.getPath(), replacements}) if replacements
|
||||
|
||||
inProcessFinished = true
|
||||
checkFinished()
|
||||
|
||||
deferred.promise
|
||||
Grim.deprecate("Use atom.workspace.replace instead of atom.project.replace")
|
||||
atom.workspace.replace(regex, replacementText, filePaths, iterator)
|
||||
|
||||
###
|
||||
Section: Private
|
||||
|
||||
@@ -11,12 +11,13 @@ class ScopedProperties
|
||||
callback(null, new ScopedProperties(scopedPropertiesPath, scopedProperties))
|
||||
|
||||
constructor: (@path, @scopedProperties) ->
|
||||
@propertyDisposable = new CompositeDisposable
|
||||
|
||||
activate: ->
|
||||
for selector, properties of @scopedProperties
|
||||
@propertyDisposable.add atom.config.addScopedSettings(@path, selector, properties)
|
||||
atom.config.set(null, properties, scopeSelector: selector, source: @path)
|
||||
return
|
||||
|
||||
deactivate: ->
|
||||
@propertyDisposable.dispose()
|
||||
for selector of @scopedProperties
|
||||
atom.config.unset(null, scopeSelector: selector, source: @path)
|
||||
return
|
||||
|
||||
@@ -536,8 +536,6 @@ class Selection extends Model
|
||||
# of a comment.
|
||||
#
|
||||
# Removes the comment if they are currently wrapped in a comment.
|
||||
#
|
||||
# Returns an Array of the commented {Range}s.
|
||||
toggleLineComments: ->
|
||||
@editor.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ TextEditorComponent = React.createClass
|
||||
trackSelectionClipboard: ->
|
||||
timeoutId = null
|
||||
{editor} = @props
|
||||
writeSelectedTextToSelectionClipboard = =>
|
||||
writeSelectedTextToSelectionClipboard = ->
|
||||
return if editor.isDestroyed()
|
||||
if selectedText = editor.getSelectedText()
|
||||
# This uses ipc.send instead of clipboard.writeText because
|
||||
@@ -462,9 +462,9 @@ TextEditorComponent = React.createClass
|
||||
|
||||
scopeDescriptor = editor.getRootScopeDescriptor()
|
||||
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.showIndentGuide', @setShowIndentGuide
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.showLineNumbers', @setShowLineNumbers
|
||||
subscriptions.add atom.config.observe scopeDescriptor, 'editor.scrollSensitivity', @setScrollSensitivity
|
||||
subscriptions.add atom.config.observe 'editor.showIndentGuide', scope: scopeDescriptor, @setShowIndentGuide
|
||||
subscriptions.add atom.config.observe 'editor.showLineNumbers', scope: scopeDescriptor, @setShowLineNumbers
|
||||
subscriptions.add atom.config.observe 'editor.scrollSensitivity', scope: scopeDescriptor, @setScrollSensitivity
|
||||
|
||||
focused: ->
|
||||
if @isMounted()
|
||||
|
||||
@@ -168,8 +168,8 @@ class TextEditor extends Model
|
||||
|
||||
scopeDescriptor = @getRootScopeDescriptor()
|
||||
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.showInvisibles', => @updateInvisibles()
|
||||
subscriptions.add atom.config.onDidChange scopeDescriptor, 'editor.invisibles', => @updateInvisibles()
|
||||
subscriptions.add atom.config.onDidChange 'editor.showInvisibles', scope: scopeDescriptor, => @updateInvisibles()
|
||||
subscriptions.add atom.config.onDidChange 'editor.invisibles', scope: scopeDescriptor, => @updateInvisibles()
|
||||
|
||||
getViewClass: ->
|
||||
require './text-editor-view'
|
||||
@@ -998,8 +998,6 @@ class TextEditor extends Model
|
||||
# Extended: Toggle line comments for rows intersecting selections.
|
||||
#
|
||||
# If the current grammar doesn't support comments, does nothing.
|
||||
#
|
||||
# Returns an {Array} of the commented {Range}s.
|
||||
toggleLineCommentsInSelection: ->
|
||||
@mutateSelectedText (selection) -> selection.toggleLineComments()
|
||||
|
||||
@@ -2812,17 +2810,17 @@ class TextEditor extends Model
|
||||
###
|
||||
|
||||
shouldAutoIndent: ->
|
||||
atom.config.get(@getRootScopeDescriptor(), "editor.autoIndent")
|
||||
atom.config.get("editor.autoIndent", scope: @getRootScopeDescriptor())
|
||||
|
||||
shouldAutoIndentOnPaste: ->
|
||||
atom.config.get(@getRootScopeDescriptor(), "editor.autoIndentOnPaste")
|
||||
atom.config.get("editor.autoIndentOnPaste", scope: @getRootScopeDescriptor())
|
||||
|
||||
shouldShowInvisibles: ->
|
||||
not @mini and atom.config.get(@getRootScopeDescriptor(), 'editor.showInvisibles')
|
||||
not @mini and atom.config.get('editor.showInvisibles', scope: @getRootScopeDescriptor())
|
||||
|
||||
updateInvisibles: ->
|
||||
if @shouldShowInvisibles()
|
||||
@displayBuffer.setInvisibles(atom.config.get(@getRootScopeDescriptor(), 'editor.invisibles'))
|
||||
@displayBuffer.setInvisibles(atom.config.get('editor.invisibles', scope: @getRootScopeDescriptor()))
|
||||
else
|
||||
@displayBuffer.setInvisibles(null)
|
||||
|
||||
@@ -2838,7 +2836,7 @@ class TextEditor extends Model
|
||||
@subscribeToScopedConfigSettings()
|
||||
@unfoldAll()
|
||||
@emit 'grammar-changed'
|
||||
@emitter.emit 'did-change-grammar'
|
||||
@emitter.emit 'did-change-grammar', @getGrammar()
|
||||
|
||||
handleMarkerCreated: (marker) =>
|
||||
if marker.matchesProperties(@getSelectionMarkerAttributes())
|
||||
|
||||
@@ -84,10 +84,10 @@ class TokenizedBuffer extends Model
|
||||
@currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText())
|
||||
@subscribe @grammar.onDidUpdate => @retokenizeLines()
|
||||
|
||||
@configSettings = tabLength: atom.config.get(@rootScopeDescriptor, 'editor.tabLength')
|
||||
@configSettings = tabLength: atom.config.get('editor.tabLength', scope: @rootScopeDescriptor)
|
||||
|
||||
@grammarTabLengthSubscription?.dispose()
|
||||
@grammarTabLengthSubscription = atom.config.onDidChange @rootScopeDescriptor, 'editor.tabLength', ({newValue}) =>
|
||||
@grammarTabLengthSubscription = atom.config.onDidChange 'editor.tabLength', scope: @rootScopeDescriptor, ({newValue}) =>
|
||||
@configSettings.tabLength = newValue
|
||||
@retokenizeLines()
|
||||
@subscribe @grammarTabLengthSubscription
|
||||
|
||||
@@ -132,7 +132,6 @@ class ViewRegistry
|
||||
if object instanceof HTMLElement
|
||||
object
|
||||
else if object?.jquery
|
||||
object[0]?.__spacePenView ?= object
|
||||
object[0]
|
||||
else if provider = @findProvider(object)
|
||||
element = provider.createView?(object)
|
||||
@@ -142,7 +141,6 @@ class ViewRegistry
|
||||
element
|
||||
else if viewConstructor = object?.getViewClass?()
|
||||
view = new viewConstructor(object)
|
||||
view[0].__spacePenView ?= view
|
||||
view[0]
|
||||
else
|
||||
throw new Error("Can't create a view for #{object.constructor.name} instance. Please register a view provider.")
|
||||
|
||||
@@ -229,7 +229,7 @@ class WorkspaceView extends View
|
||||
when 'cursor:moved'
|
||||
deprecate('Use TextEditor::onDidChangeCursorPosition instead')
|
||||
when 'editor:attached'
|
||||
deprecate('Use TextEditor::onDidAddTextEditor instead')
|
||||
deprecate('Use Workspace::onDidAddTextEditor instead')
|
||||
when 'editor:detached'
|
||||
deprecate('Use TextEditor::onDidDestroy instead')
|
||||
when 'editor:will-be-removed'
|
||||
|
||||
+109
-1
@@ -14,6 +14,7 @@ PanelElement = require './panel-element'
|
||||
PanelContainer = require './panel-container'
|
||||
PanelContainerElement = require './panel-container-element'
|
||||
WorkspaceElement = require './workspace-element'
|
||||
Task = require './task'
|
||||
|
||||
# Essential: Represents the state of the user interface for the entire window.
|
||||
# An instance of this class is available via the `atom.workspace` global.
|
||||
@@ -455,6 +456,8 @@ class Workspace extends Model
|
||||
@itemOpened(item)
|
||||
pane.activateItem(item)
|
||||
pane.activate() if activatePane
|
||||
if options.initialLine? or options.initialColumn?
|
||||
item.setCursorBufferPosition?([options.initialLine, options.initialColumn])
|
||||
index = pane.getActiveItemIndex()
|
||||
@emit "uri-opened"
|
||||
@emitter.emit 'did-open', {uri, pane, item, index}
|
||||
@@ -645,7 +648,7 @@ class Workspace extends Model
|
||||
|
||||
# Restore to a default editor font size.
|
||||
resetFontSize: ->
|
||||
atom.config.restoreDefault("editor.fontSize")
|
||||
atom.config.unset("editor.fontSize")
|
||||
|
||||
# Removes the item's uri from the list of potential items to reopen.
|
||||
itemOpened: (item) ->
|
||||
@@ -665,6 +668,16 @@ class Workspace extends Model
|
||||
|
||||
###
|
||||
Section: Panels
|
||||
|
||||
Panels are used to display UI related to an editor window. They are placed at one of the four
|
||||
edges of the window: left, right, top or bottom. If there are multiple panels on the same window
|
||||
edge they are stacked in order of priority: higher priority is closer to the center, lower
|
||||
priority towards the edge.
|
||||
|
||||
*Note:* If your panel changes its size throughout its lifetime, consider giving it a higher
|
||||
priority, allowing fixed size panels to be closer to the edge. This allows control targets to
|
||||
remain more static for easier targeting by users that employ mice or trackpads. (See
|
||||
[atom/atom#4834](https://github.com/atom/atom/issues/4834) for discussion.)
|
||||
###
|
||||
|
||||
# Essential: Get an {Array} of all the panel items at the bottom of the editor window.
|
||||
@@ -778,3 +791,98 @@ class Workspace extends Model
|
||||
addPanel: (location, options) ->
|
||||
options ?= {}
|
||||
@panelContainers[location].addPanel(new Panel(options))
|
||||
|
||||
###
|
||||
Section: Searching and Replacing
|
||||
###
|
||||
|
||||
# Public: Performs a search across all the files in the workspace.
|
||||
#
|
||||
# * `regex` {RegExp} to search with.
|
||||
# * `options` (optional) {Object} (default: {})
|
||||
# * `paths` An {Array} of glob patterns to search within
|
||||
# * `iterator` {Function} callback on each file found
|
||||
#
|
||||
# Returns a `Promise`.
|
||||
scan: (regex, options={}, iterator) ->
|
||||
if _.isFunction(options)
|
||||
iterator = options
|
||||
options = {}
|
||||
|
||||
deferred = Q.defer()
|
||||
|
||||
searchOptions =
|
||||
ignoreCase: regex.ignoreCase
|
||||
inclusions: options.paths
|
||||
includeHidden: true
|
||||
excludeVcsIgnores: atom.config.get('core.excludeVcsIgnoredPaths')
|
||||
exclusions: atom.config.get('core.ignoredNames')
|
||||
follow: atom.config.get('core.followSymlinks')
|
||||
|
||||
# TODO: need to support all paths in @getPaths()
|
||||
task = Task.once require.resolve('./scan-handler'), atom.project.getPaths()[0], regex.source, searchOptions, ->
|
||||
deferred.resolve()
|
||||
|
||||
task.on 'scan:result-found', (result) =>
|
||||
iterator(result) unless atom.project.isPathModified(result.filePath)
|
||||
|
||||
task.on 'scan:file-error', (error) ->
|
||||
iterator(null, error)
|
||||
|
||||
if _.isFunction(options.onPathsSearched)
|
||||
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
|
||||
options.onPathsSearched(numberOfPathsSearched)
|
||||
|
||||
for buffer in atom.project.getBuffers() when buffer.isModified()
|
||||
filePath = buffer.getPath()
|
||||
continue unless atom.project.contains(filePath)
|
||||
matches = []
|
||||
buffer.scan regex, (match) -> matches.push match
|
||||
iterator {filePath, matches} if matches.length > 0
|
||||
|
||||
promise = deferred.promise
|
||||
promise.cancel = ->
|
||||
task.terminate()
|
||||
deferred.resolve('cancelled')
|
||||
promise
|
||||
|
||||
# Public: Performs a replace across all the specified files in the project.
|
||||
#
|
||||
# * `regex` A {RegExp} to search with.
|
||||
# * `replacementText` Text to replace all matches of regex with
|
||||
# * `filePaths` List of file path strings to run the replace on.
|
||||
# * `iterator` A {Function} callback on each file with replacements:
|
||||
# * `options` {Object} with keys `filePath` and `replacements`
|
||||
#
|
||||
# Returns a `Promise`.
|
||||
replace: (regex, replacementText, filePaths, iterator) ->
|
||||
deferred = Q.defer()
|
||||
|
||||
openPaths = (buffer.getPath() for buffer in atom.project.getBuffers())
|
||||
outOfProcessPaths = _.difference(filePaths, openPaths)
|
||||
|
||||
inProcessFinished = !openPaths.length
|
||||
outOfProcessFinished = !outOfProcessPaths.length
|
||||
checkFinished = ->
|
||||
deferred.resolve() if outOfProcessFinished and inProcessFinished
|
||||
|
||||
unless outOfProcessFinished.length
|
||||
flags = 'g'
|
||||
flags += 'i' if regex.ignoreCase
|
||||
|
||||
task = Task.once require.resolve('./replace-handler'), outOfProcessPaths, regex.source, flags, replacementText, ->
|
||||
outOfProcessFinished = true
|
||||
checkFinished()
|
||||
|
||||
task.on 'replace:path-replaced', iterator
|
||||
task.on 'replace:file-error', (error) -> iterator(null, error)
|
||||
|
||||
for buffer in atom.project.getBuffers()
|
||||
continue unless buffer.getPath() in filePaths
|
||||
replacements = buffer.replace(regex, replacementText, iterator)
|
||||
iterator({filePath: buffer.getPath(), replacements}) if replacements
|
||||
|
||||
inProcessFinished = true
|
||||
checkFinished()
|
||||
|
||||
deferred.promise
|
||||
|
||||
+8
-16
@@ -26,6 +26,7 @@
|
||||
.make-icon(beer);
|
||||
.make-icon(book);
|
||||
.make-icon(bookmark);
|
||||
.make-icon(briefcase);
|
||||
.make-icon(broadcast);
|
||||
.make-icon(browser);
|
||||
.make-icon(bug);
|
||||
@@ -37,6 +38,7 @@
|
||||
.make-icon(chevron-right);
|
||||
.make-icon(chevron-up);
|
||||
.make-icon(circle-slash);
|
||||
.make-icon(circuit-board);
|
||||
.make-icon(clippy);
|
||||
.make-icon(clock);
|
||||
.make-icon(cloud-download);
|
||||
@@ -114,6 +116,7 @@
|
||||
.make-icon(jump-up);
|
||||
.make-icon(key);
|
||||
.make-icon(keyboard);
|
||||
.make-icon(law);
|
||||
.make-icon(light-bulb);
|
||||
.make-icon(link);
|
||||
.make-icon(link-external);
|
||||
@@ -123,36 +126,26 @@
|
||||
.make-icon(lock);
|
||||
.make-icon(log-in);
|
||||
.make-icon(log-out);
|
||||
.make-icon(logo-apps);
|
||||
.make-icon(logo-atom);
|
||||
.make-icon(logo-chat);
|
||||
.make-icon(logo-gist);
|
||||
.make-icon(logo-github);
|
||||
.make-icon(logo-octicons);
|
||||
.make-icon(logo-talks);
|
||||
.make-icon(mail);
|
||||
.make-icon(mail-read);
|
||||
.make-icon(mail-reply);
|
||||
.make-icon(mark-facebook);
|
||||
.make-icon(mark-github);
|
||||
.make-icon(mark-github-detail);
|
||||
.make-icon(mark-google);
|
||||
.make-icon(mark-twitter);
|
||||
.make-icon(markdown);
|
||||
.make-icon(megaphone);
|
||||
.make-icon(mention);
|
||||
.make-icon(microscope);
|
||||
.make-icon(milestone);
|
||||
.make-icon(mirror);
|
||||
.make-icon(mirror-private);
|
||||
.make-icon(mirror-public);
|
||||
.make-icon(mortar-board);
|
||||
.make-icon(move-down);
|
||||
.make-icon(move-left);
|
||||
.make-icon(move-right);
|
||||
.make-icon(move-up);
|
||||
.make-icon(mute);
|
||||
.make-icon(mute-video);
|
||||
.make-icon(no-newline);
|
||||
.make-icon(node-js);
|
||||
.make-icon(octoface);
|
||||
.make-icon(organization);
|
||||
.make-icon(package);
|
||||
@@ -161,12 +154,12 @@
|
||||
.make-icon(person);
|
||||
.make-icon(person-add);
|
||||
.make-icon(person-follow);
|
||||
.make-icon(person-remove);
|
||||
.make-icon(pin);
|
||||
.make-icon(playback-fast-forward);
|
||||
.make-icon(playback-pause);
|
||||
.make-icon(playback-play);
|
||||
.make-icon(playback-rewind);
|
||||
.make-icon(plug);
|
||||
.make-icon(plus);
|
||||
.make-icon(podium);
|
||||
.make-icon(primitive-dot);
|
||||
@@ -187,7 +180,6 @@
|
||||
.make-icon(repo-push);
|
||||
.make-icon(repo-sync);
|
||||
.make-icon(rocket);
|
||||
.make-icon(rohan);
|
||||
.make-icon(rss);
|
||||
.make-icon(ruby);
|
||||
.make-icon(screen-full);
|
||||
@@ -196,6 +188,8 @@
|
||||
.make-icon(search-save);
|
||||
.make-icon(server);
|
||||
.make-icon(settings);
|
||||
.make-icon(sign-in);
|
||||
.make-icon(sign-out);
|
||||
.make-icon(split);
|
||||
.make-icon(squirrel);
|
||||
.make-icon(star);
|
||||
@@ -216,10 +210,8 @@
|
||||
.make-icon(triangle-left);
|
||||
.make-icon(triangle-right);
|
||||
.make-icon(triangle-up);
|
||||
.make-icon(trollface);
|
||||
.make-icon(unfold);
|
||||
.make-icon(unmute);
|
||||
.make-icon(unmute-video);
|
||||
.make-icon(versions);
|
||||
.make-icon(x);
|
||||
.make-icon(zap);
|
||||
|
||||
Arquivo normal → Arquivo executável
BIN
Arquivo binário não exibido.
@@ -13,6 +13,7 @@
|
||||
@beer: "\f069";
|
||||
@book: "\f007";
|
||||
@bookmark: "\f07b";
|
||||
@briefcase: "\f0d3";
|
||||
@broadcast: "\f048";
|
||||
@browser: "\f0c5";
|
||||
@bug: "\f091";
|
||||
@@ -24,6 +25,7 @@
|
||||
@chevron-right: "\f078";
|
||||
@chevron-up: "\f0a2";
|
||||
@circle-slash: "\f084";
|
||||
@circuit-board: "\f0d6";
|
||||
@clippy: "\f035";
|
||||
@clock: "\f046";
|
||||
@cloud-download: "\f00b";
|
||||
@@ -31,7 +33,7 @@
|
||||
@code: "\f05f";
|
||||
@color-mode: "\f065";
|
||||
@comment: "\f02b";
|
||||
@comment-add: "\f06f";
|
||||
@comment-add: "\f02b";
|
||||
@comment-discussion: "\f04f";
|
||||
@credit-card: "\f045";
|
||||
@dash: "\f0ca";
|
||||
@@ -49,13 +51,13 @@
|
||||
@diff-renamed: "\f06e";
|
||||
@ellipsis: "\f09a";
|
||||
@eye: "\f04e";
|
||||
@eye-unwatch: "\f01e";
|
||||
@eye-watch: "\f01d";
|
||||
@file-add: "\f086";
|
||||
@eye-unwatch: "\f04e";
|
||||
@eye-watch: "\f04e";
|
||||
@file-add: "\f05d";
|
||||
@file-binary: "\f094";
|
||||
@file-code: "\f010";
|
||||
@file-directory: "\f016";
|
||||
@file-directory-create: "\f095";
|
||||
@file-directory-create: "\f05d";
|
||||
@file-media: "\f012";
|
||||
@file-pdf: "\f014";
|
||||
@file-submodule: "\f017";
|
||||
@@ -68,19 +70,19 @@
|
||||
@gear: "\f02f";
|
||||
@gift: "\f042";
|
||||
@gist: "\f00e";
|
||||
@gist-fork: "\f079";
|
||||
@gist-new: "\f07a";
|
||||
@gist-private: "\f00f";
|
||||
@gist-fork: "\f002";
|
||||
@gist-new: "\f05d";
|
||||
@gist-private: "\f06a";
|
||||
@gist-secret: "\f08c";
|
||||
@git-branch: "\f020";
|
||||
@git-branch-create: "\f098";
|
||||
@git-branch-delete: "\f09b";
|
||||
@git-branch-create: "\f020";
|
||||
@git-branch-delete: "\f020";
|
||||
@git-commit: "\f01f";
|
||||
@git-compare: "\f0ac";
|
||||
@git-fork-private: "\f021";
|
||||
@git-fork-private: "\f06a";
|
||||
@git-merge: "\f023";
|
||||
@git-pull-request: "\f009";
|
||||
@git-pull-request-abandoned: "\f090";
|
||||
@git-pull-request-abandoned: "\f009";
|
||||
@globe: "\f0b6";
|
||||
@graph: "\f043";
|
||||
@heart: "\2665";
|
||||
@@ -101,6 +103,7 @@
|
||||
@jump-up: "\f073";
|
||||
@key: "\f049";
|
||||
@keyboard: "\f00d";
|
||||
@law: "\f0d8";
|
||||
@light-bulb: "\f000";
|
||||
@link: "\f05c";
|
||||
@link-external: "\f07f";
|
||||
@@ -110,50 +113,40 @@
|
||||
@lock: "\f06a";
|
||||
@log-in: "\f036";
|
||||
@log-out: "\f032";
|
||||
@logo-apps: "\f0b3";
|
||||
@logo-atom: "\f0b7";
|
||||
@logo-chat: "\f0b4";
|
||||
@logo-gist: "\f0ad";
|
||||
@logo-github: "\f092";
|
||||
@logo-octicons: "\f0ab";
|
||||
@logo-talks: "\f0b5";
|
||||
@mail: "\f03b";
|
||||
@mail-read: "\f03c";
|
||||
@mail-reply: "\f051";
|
||||
@mark-facebook: "\f0ce";
|
||||
@mark-github: "\f00a";
|
||||
@mark-github-detail: "\f093";
|
||||
@mark-google: "\f0cd";
|
||||
@mark-twitter: "\f0ae";
|
||||
@markdown: "\f0c9";
|
||||
@megaphone: "\f077";
|
||||
@mention: "\f0be";
|
||||
@microscope: "\f089";
|
||||
@milestone: "\f075";
|
||||
@mirror-private: "\f025";
|
||||
@mirror: "\f024";
|
||||
@mirror-private: "\f06a";
|
||||
@mirror-public: "\f024";
|
||||
@mortar-board: "\f0d7";
|
||||
@move-down: "\f0a8";
|
||||
@move-left: "\f074";
|
||||
@move-right: "\f0a9";
|
||||
@move-up: "\f0a7";
|
||||
@mute: "\f080";
|
||||
@mute-video: "\f0b8";
|
||||
@no-newline: "\f09c";
|
||||
@node-js: "\f0c3";
|
||||
@octoface: "\f008";
|
||||
@organization: "\f037";
|
||||
@package: "\f0c4";
|
||||
@paintcan: "\f0d1";
|
||||
@pencil: "\f058";
|
||||
@person: "\f018";
|
||||
@person-add: "\f01a";
|
||||
@person-follow: "\f01c";
|
||||
@person-remove: "\f01b";
|
||||
@person-add: "\f018";
|
||||
@person-follow: "\f018";
|
||||
@pin: "\f041";
|
||||
@playback-fast-forward: "\f0bd";
|
||||
@playback-pause: "\f0bb";
|
||||
@playback-play: "\f0bf";
|
||||
@playback-rewind: "\f0bc";
|
||||
@plug: "\f0d4";
|
||||
@plus: "\f05d";
|
||||
@podium: "\f0af";
|
||||
@primitive-dot: "\f052";
|
||||
@@ -163,37 +156,38 @@
|
||||
@question: "\f02c";
|
||||
@quote: "\f063";
|
||||
@radio-tower: "\f030";
|
||||
@remove-close: "\f050";
|
||||
@remove-close: "\f081";
|
||||
@repo: "\f001";
|
||||
@repo-clone: "\f04c";
|
||||
@repo-create: "\f003";
|
||||
@repo-delete: "\f004";
|
||||
@repo-create: "\f05d";
|
||||
@repo-delete: "\f001";
|
||||
@repo-force-push: "\f04a";
|
||||
@repo-forked: "\f002";
|
||||
@repo-pull: "\f006";
|
||||
@repo-push: "\f005";
|
||||
@repo-sync: "\f04b";
|
||||
@repo-sync: "\f087";
|
||||
@rocket: "\f033";
|
||||
@rohan: "\f022";
|
||||
@rss: "\f034";
|
||||
@ruby: "\f047";
|
||||
@screen-full: "\f066";
|
||||
@screen-normal: "\f067";
|
||||
@search: "\f02e";
|
||||
@search-save: "\f0cb";
|
||||
@search-save: "\f02e";
|
||||
@server: "\f097";
|
||||
@settings: "\f07c";
|
||||
@sign-in: "\f036";
|
||||
@sign-out: "\f032";
|
||||
@split: "\f0c6";
|
||||
@squirrel: "\f0b2";
|
||||
@star: "\f02a";
|
||||
@star-add: "\f082";
|
||||
@star-delete: "\f083";
|
||||
@star-add: "\f02a";
|
||||
@star-delete: "\f02a";
|
||||
@steps: "\f0c7";
|
||||
@stop: "\f08f";
|
||||
@sync: "\f087";
|
||||
@tag: "\f015";
|
||||
@tag-add: "\f054";
|
||||
@tag-remove: "\f055";
|
||||
@tag-add: "\f015";
|
||||
@tag-remove: "\f015";
|
||||
@telescope: "\f088";
|
||||
@terminal: "\f0c8";
|
||||
@three-bars: "\f05e";
|
||||
@@ -203,10 +197,8 @@
|
||||
@triangle-left: "\f044";
|
||||
@triangle-right: "\f05a";
|
||||
@triangle-up: "\f0aa";
|
||||
@trollface: "\f029";
|
||||
@unfold: "\f039";
|
||||
@unmute: "\f0ba";
|
||||
@unmute-video: "\f0b9";
|
||||
@versions: "\f064";
|
||||
@x: "\f081";
|
||||
@zap: "\26A1";
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário