From 7d8b5bc1fcd7e7543d65653916efc37582310f66 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 14 Oct 2014 12:39:37 -0700 Subject: [PATCH 1/5] Add scopes and scope descriptors docs --- docs/advanced/scopes-and-scope-descriptors.md | 84 +++++++++++++++++++ docs/index.md | 1 + 2 files changed, 85 insertions(+) create mode 100644 docs/advanced/scopes-and-scope-descriptors.md diff --git a/docs/advanced/scopes-and-scope-descriptors.md b/docs/advanced/scopes-and-scope-descriptors.md new file mode 100644 index 000000000..095f4c271 --- /dev/null +++ b/docs/advanced/scopes-and-scope-descriptors.md @@ -0,0 +1,84 @@ +# Scoped Settings, Scopes and Scope Descriptors + +Atom supports language-specific settings. You can soft wrap only markdown files, or set the tab length to 4 in python files. + +Language-specific settings are but a subset of something more general we call "scoped settings". Scoped settings allow targeting down to a specific syntax token type. For example, you could conceivably set a setting to target only ruby comments, only code inside markdown files, or even only JavaScript function names. + +## Scope names in syntax tokens + +Each token in the editor has a collection of scope names. For example, the aformentioned JavaScript function name might have the scope names `function` and `name`. An open paren might have the scope names `punctuation`, `parameters`, `begin`. + +Scope names work just like CSS classes. In fact, in the editor, scope names are attached to a token's dom node as CSS classes. + +Take this piece of JavaScript: + +```js +function functionName() { + console.log('Log it out'); +} +``` + +In the dev tools, the first line's markup looks like this. + +![screen shot 2014-10-14 at 11 21 35 am](https://cloud.githubusercontent.com/assets/69169/4634321/2b1b923c-53cf-11e4-9268-6e57bcb14ec8.png) + +All the class names on the spans are scope names. Any scope name can be used to target a setting's value. + +## Scope Selectors + +Scope selectors allow you to target specific tokens just like a CSS selector targets specific nodes in the DOM. Some examples: + +```coffee +'.source.js' # selects all javascript tokens +'.source.js .function.name' # selects all javascript function names +'.function.name' # selects all function names in any language +``` + +[Config::set][config-set] accepts a `scopeSelector`. If you'd like to set a setting for JavaScript function names, you can give it the js function name `scopeSelector`: + +```coffee +atom.config.set('.source.js .function.name', 'my-package.my-setting', 'special value') +``` + +## Scope Descriptors + +A scope descriptor is an `Array` of `String`s describing a path from the root of the syntax tree to a token including _all_ scope names for the entire path. + +In our JavaScript example above, a scope descriptor for the function name token would be: + +```coffee +['source.js', 'meta.function.js', 'entity.name.function.js'] +``` + +[Config::get][config-get] accepts a `scopeDescriptor`. You can get the value for your setting scoped to JavaScript function names via: + +```coffee +scopeDescriptor = ['source.js', 'meta.function.js', 'entity.name.function.js'] +value = atom.config.get(scopeDescriptor, 'my-package.my-setting') +``` + +But, you are not meant to generate scope descriptors by hand. There are a couple methods available to get the scope descriptor from the editor: + +* [Editor::getRootScopeDescriptor][editor-getRootScopeDescriptor] to get the language's descriptor. eg. `[".source.js"]` +* [Editor::scopeDescriptorForBufferPosition][editor-scopeDescriptorForBufferPosition] to get the descriptor at a specific position in the buffer. +* [Cursor::getScopeDescriptor][cursor-getScopeDescriptor] to get a cursor's descriptor based on position. eg. if the cursor were in the name of the method in our example it would return `["source.js", "meta.function.js", "entity.name.function.js"]` + +Let's revisit our example using these methods: + +```coffee +editor = atom.workspace.getActiveTextEditor() +cursor = editor.getLastCursor() +valueAtCursor = atom.config.get(cursor.getScopeDescriptor(), 'my-package.my-setting') +valueForLanguage = atom.config.get(editor.getRootScopeDescriptor(), 'my-package.my-setting') +``` + + +[config]:https://atom.io/docs/api/latest/Config +[config-get]:https://atom.io/docs/api/latest/Config#instance-get +[config-set]:https://atom.io/docs/api/latest/Config#instance-set +[config-observe]:https://atom.io/docs/api/latest/Config#instance-observe + +[editor-getRootScopeDescriptor]:https://atom.io/docs/api/latest/TextEditor#instance-getRootScopeDescriptor +[editor-scopeDescriptorForBufferPosition]:https://atom.io/docs/api/latest/TextEditor#instance-scopeDescriptorForBufferPosition + +[cursor-getScopeDescriptor]:https://atom.io/docs/api/latest/Cursor#instance-getScopeDescriptor diff --git a/docs/index.md b/docs/index.md index 66170370f..c0bfd3065 100644 --- a/docs/index.md +++ b/docs/index.md @@ -18,3 +18,4 @@ * [Keymaps](advanced/keymaps.md) * [Serialization](advanced/serialization.md) * [View System](advanced/view-system.md) +* [Scopes and Scope Descriptors](advanced/scopes-and-scope-descriptors.md) From ee23131688b42cdd4203fd2b8feb53473a84375c Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 14 Oct 2014 12:42:32 -0700 Subject: [PATCH 2/5] Rename scopes -> Scope selectors in config::set docs --- src/config.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 0a7384bfd..e0a8e795d 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -486,7 +486,7 @@ class Config # atom.config.get(['source.js'], 'editor.tabLength') # => 4 # ``` # - # * `scope` (optional) {String}. eg. '.source.ruby' + # * `scopeSelector` (optional) {String}. eg. '.source.ruby' # * `keyPath` The {String} name of the key. # * `value` The value of the setting. Passing `undefined` will revert the # setting to the default value. @@ -494,11 +494,11 @@ class Config # 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: (scope, keyPath, value) -> + set: (scopeSelector, keyPath, value) -> if arguments.length < 3 value = keyPath - keyPath = scope - scope = undefined + keyPath = scopeSelector + scopeSelector = undefined unless value == undefined try @@ -506,8 +506,8 @@ class Config catch e return false - if scope? - @setRawScopedValue(scope, keyPath, value) + if scopeSelector? + @setRawScopedValue(scopeSelector, keyPath, value) else @setRawValue(keyPath, value) From 1577a28ad4b18ac95bc4cf20421175c94b7b7e36 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 14 Oct 2014 12:47:03 -0700 Subject: [PATCH 3/5] Add links to the new doc in the API docs --- src/config.coffee | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/config.coffee b/src/config.coffee index e0a8e795d..51d36f06b 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -338,6 +338,8 @@ class Config # * `scopeDescriptor` (optional) {Array} of {String}s 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 # * `callback` {Function} to call when the value of the key changes. # * `value` the new value of the key @@ -374,6 +376,8 @@ class Config # * `scopeDescriptor` (optional) {Array} of {String}s 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. # * `callback` {Function} to call when the value of the key changes. @@ -443,6 +447,8 @@ class Config # * `scopeDescriptor` (optional) {Array} of {String}s 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. # # Returns the value from Atom's default settings, the user's configuration @@ -487,6 +493,8 @@ class Config # ``` # # * `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. From 072c537b6b4c93ed8dbee96f3f4b3b8893e1e64a Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 14 Oct 2014 13:59:43 -0700 Subject: [PATCH 4/5] Upgrade language-gfm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b367cf413..671568d8d 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "language-c": "0.28.0", "language-coffee-script": "0.36.0", "language-css": "0.21.0", - "language-gfm": "0.51.0", + "language-gfm": "0.52.0", "language-git": "0.9.0", "language-go": "0.19.0", "language-html": "0.26.0", From da86c8657788c5134270c133de3c921733c1221e Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 16 Oct 2014 13:26:07 -0700 Subject: [PATCH 5/5] Integrate feedback --- docs/advanced/scopes-and-scope-descriptors.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/advanced/scopes-and-scope-descriptors.md b/docs/advanced/scopes-and-scope-descriptors.md index 095f4c271..9cf12bed9 100644 --- a/docs/advanced/scopes-and-scope-descriptors.md +++ b/docs/advanced/scopes-and-scope-descriptors.md @@ -1,14 +1,14 @@ # Scoped Settings, Scopes and Scope Descriptors -Atom supports language-specific settings. You can soft wrap only markdown files, or set the tab length to 4 in python files. +Atom supports language-specific settings. You can soft wrap only Markdown files, or set the tab length to 4 in Python files. -Language-specific settings are but a subset of something more general we call "scoped settings". Scoped settings allow targeting down to a specific syntax token type. For example, you could conceivably set a setting to target only ruby comments, only code inside markdown files, or even only JavaScript function names. +Language-specific settings are a subset of something more general we call "scoped settings". Scoped settings allow targeting down to a specific syntax token type. For example, you could conceivably set a setting to target only Ruby comments, only code inside Markdown files, or even only JavaScript function names. ## Scope names in syntax tokens Each token in the editor has a collection of scope names. For example, the aformentioned JavaScript function name might have the scope names `function` and `name`. An open paren might have the scope names `punctuation`, `parameters`, `begin`. -Scope names work just like CSS classes. In fact, in the editor, scope names are attached to a token's dom node as CSS classes. +Scope names work just like CSS classes. In fact, in the editor, scope names are attached to a token's DOM node as CSS classes. Take this piece of JavaScript: @@ -57,7 +57,7 @@ scopeDescriptor = ['source.js', 'meta.function.js', 'entity.name.function.js'] value = atom.config.get(scopeDescriptor, 'my-package.my-setting') ``` -But, you are not meant to generate scope descriptors by hand. There are a couple methods available to get the scope descriptor from the editor: +But, you do not need to generate scope descriptors by hand. There are a couple methods available to get the scope descriptor from the editor: * [Editor::getRootScopeDescriptor][editor-getRootScopeDescriptor] to get the language's descriptor. eg. `[".source.js"]` * [Editor::scopeDescriptorForBufferPosition][editor-scopeDescriptorForBufferPosition] to get the descriptor at a specific position in the buffer.