├── .eslintrc
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── block-cursor.png
├── cursor-bordered-box.png
├── cursor-i-beam.png
├── cursor-pulse.gif
├── cursor-underline.png
├── lib
└── block-cursor.js
├── package.json
└── styles
└── block-cursor.less
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint", // https://github.com/babel/babel-eslint
3 | "env": { // http://eslint.org/docs/user-guide/configuring.html#specifying-environments
4 | "browser": true, // browser global variables
5 | "node": true // Node.js global variables and Node.js-specific rules
6 | },
7 | "globals": {
8 | "atom": true
9 | },
10 | "ecmaFeatures": {
11 | "arrowFunctions": true,
12 | "blockBindings": true,
13 | "classes": true,
14 | "defaultParams": true,
15 | "destructuring": true,
16 | "forOf": true,
17 | "generators": false,
18 | "modules": true,
19 | "objectLiteralComputedProperties": true,
20 | "objectLiteralDuplicateProperties": false,
21 | "objectLiteralShorthandMethods": true,
22 | "objectLiteralShorthandProperties": true,
23 | "spread": true,
24 | "superInFunctions": true,
25 | "templateStrings": true
26 | },
27 | "rules": {
28 | /**
29 | * Strict mode
30 | */
31 | // babel inserts "use strict"; for us
32 | "strict": [2, "never"], // http://eslint.org/docs/rules/strict
33 |
34 | /**
35 | * ES6
36 | */
37 | "no-var": 0, // http://eslint.org/docs/rules/no-var
38 | "prefer-const": 0, // http://eslint.org/docs/rules/prefer-const
39 |
40 | /**
41 | * Variables
42 | */
43 | "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow
44 | "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names
45 | "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars
46 | "vars": "local",
47 | "args": "after-used"
48 | }],
49 | "no-use-before-define": 0, // http://eslint.org/docs/rules/no-use-before-define
50 |
51 | /**
52 | * Expressions
53 | */
54 |
55 | "no-unused-expressions": 0,
56 |
57 | /**
58 | * Possible errors
59 | */
60 | "comma-dangle": [2, "always-multiline"], // http://eslint.org/docs/rules/comma-dangle
61 | "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign
62 | "no-console": 1, // http://eslint.org/docs/rules/no-console
63 | "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger
64 | "no-alert": 1, // http://eslint.org/docs/rules/no-alert
65 | "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition
66 | "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys
67 | "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case
68 | "no-empty": 2, // http://eslint.org/docs/rules/no-empty
69 | "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign
70 | "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast
71 | "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi
72 | "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign
73 | "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations
74 | "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp
75 | "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace
76 | "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls
77 | "no-reserved-keys": 0, // http://eslint.org/docs/rules/no-reserved-keys
78 | "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays
79 | "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable
80 | "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan
81 | "block-scoped-var": 0, // http://eslint.org/docs/rules/block-scoped-var
82 |
83 | /**
84 | * Best practices
85 | */
86 | "consistent-return": 0, // http://eslint.org/docs/rules/consistent-return
87 | "curly": [0, "multi-line"], // http://eslint.org/docs/rules/curly
88 | "default-case": 2, // http://eslint.org/docs/rules/default-case
89 | "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation
90 | "allowKeywords": true
91 | }],
92 | "eqeqeq": 0, // http://eslint.org/docs/rules/eqeqeq
93 | "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in
94 | "no-caller": 2, // http://eslint.org/docs/rules/no-caller
95 | "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return
96 | "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null
97 | "no-eval": 2, // http://eslint.org/docs/rules/no-eval
98 | "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native
99 | "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind
100 | "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough
101 | "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal
102 | "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval
103 | "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks
104 | "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func
105 | "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str
106 | "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign
107 | "no-new": 2, // http://eslint.org/docs/rules/no-new
108 | "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func
109 | "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers
110 | "no-octal": 2, // http://eslint.org/docs/rules/no-octal
111 | "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape
112 | "no-param-reassign": 0, // http://eslint.org/docs/rules/no-param-reassign
113 | "no-proto": 2, // http://eslint.org/docs/rules/no-proto
114 | "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare
115 | "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign
116 | "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url
117 | "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare
118 | "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences
119 | "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal
120 | "no-with": 2, // http://eslint.org/docs/rules/no-with
121 | "radix": 0, // http://eslint.org/docs/rules/radix
122 | "vars-on-top": 0, // http://eslint.org/docs/rules/vars-on-top
123 | "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife
124 | "yoda": 2, // http://eslint.org/docs/rules/yoda
125 |
126 | /**
127 | * Style
128 | */
129 | "indent": [2, 2], // http://eslint.org/docs/rules/indent
130 | "brace-style": [2, // http://eslint.org/docs/rules/brace-style
131 | "1tbs", {
132 | "allowSingleLine": true
133 | }],
134 | "quotes": [
135 | 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes
136 | ],
137 | "camelcase": [2, { // http://eslint.org/docs/rules/camelcase
138 | "properties": "never"
139 | }],
140 | "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing
141 | "before": false,
142 | "after": true
143 | }],
144 | "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style
145 | "eol-last": 2, // http://eslint.org/docs/rules/eol-last
146 | "func-names": 1, // http://eslint.org/docs/rules/func-names
147 | "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing
148 | "beforeColon": false,
149 | "afterColon": true
150 | }],
151 | "new-cap": [2, { // http://eslint.org/docs/rules/new-cap
152 | "newIsCap": true
153 | }],
154 | "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines
155 | "max": 2
156 | }],
157 | "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary
158 | "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object
159 | "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func
160 | "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces
161 | "no-wrap-func": 2, // http://eslint.org/docs/rules/no-wrap-func
162 | "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle
163 | "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var
164 | "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks
165 | "semi": [2, "always"], // http://eslint.org/docs/rules/semi
166 | "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing
167 | "before": false,
168 | "after": true
169 | }],
170 | "space-after-keywords": 0, // http://eslint.org/docs/rules/space-after-keywords
171 | "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks
172 | "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren
173 | "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops
174 | "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case
175 | "spaced-line-comment": 2, // http://eslint.org/docs/rules/spaced-line-comment
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # block-cursor changelog
2 |
3 | ## 0.13.3
4 |
5 | * Fix [#37](https://github.com/adamrenklint/atom-block-cursor/issues/37) *Broken underline style*
6 |
7 | ## 0.13.2
8 |
9 | * Fix #33 *Deprecated selector in `block-cursor/styles/block-cursor.less`*
10 |
11 | ## 0.13.1
12 | * Fix #23
13 |
14 | ## 0.13.0
15 | * Rewrite. Breaks current configuration. See [README.md](README.md).
16 | * Disable `cursorLineFix` setting temporarily, because of a conflict with tile rendering introduced in Atom v0.209.0.
17 |
18 | ## 0.12.5
19 | * Fix bug where cursor blinking wasn't disabled properly
20 | * Add specs
21 |
22 | ## 0.12.4
23 | * Fix #14
24 |
25 | ## 0.12.3
26 | * Merge #12
27 |
28 | ## 0.12.2
29 | * Fix #11 by adding `useHardwareAcceleration` setting
30 |
31 | ## 0.12.1
32 | * Animate opacity when `secondaryColorAlpha` is `0`. Fixes #9
33 | * Fix #10
34 |
35 | ## 0.12.0
36 | * Rewrite
37 | * Separate scoped config observation into its own npm package
38 |
39 | ## 0.11.2
40 | * Fix #8
41 |
42 | ## 0.11.1
43 | * Fix some minor issues
44 |
45 | ## 0.11.0
46 | * Add support for scoped config
47 |
48 | ## 0.10.1
49 | * Fix readme
50 | * Some rewriting
51 |
52 | ## 0.10.0
53 | * Add separate alpha channel configs for both the color configs because the color picker on Linux doesn't support them.
54 | * Add fix for syntax themes with a `background-color` on the `.cursor-line`
55 | * Some rewriting
56 |
57 | ## 0.9.9
58 | * Fix #6
59 |
60 | ## 0.9.8
61 | * Don't set secondaryColor when changing blinkInterval
62 |
63 | ## 0.9.7
64 | * Better fix for #5
65 |
66 | ## 0.9.6
67 | * Fix #5
68 |
69 | ## 0.9.5
70 | * Fix cursor blink
71 | * Remove underscore dependency
72 |
73 | ## 0.9.4
74 | * Fix `blinkInterval` config description
75 |
76 | ## 0.9.3
77 | * Updated readme's `blink interval` section
78 | * Set default value for the `preview` field, to avoid a warning at activation
79 | * Workaround for disabling cursor blinking in `mini` editors
80 |
81 | ## 0.9.2
82 | * Fixed issue where package deactivation sometimes throws an exception
83 |
84 | ## 0.9.1
85 | * Changed `blinkInterval`'s default from 500 to 400 to match Atom's default behavior
86 | * Dispose of editor subscription on package deactivation
87 |
88 | ## 0.9.0
89 | * Added `blinkInterval` option
90 | * Removed `pulseDuration` maximum
91 |
92 | ## 0.8.1
93 | * Added preview field to the package settings
94 |
95 | ## 0.8.0
96 | * Added `cursorThickness` option
97 |
98 | ## 0.7.6
99 | * Use CompositeDisposable for the config subscriptions
100 |
101 | ## 0.7.5
102 | * Fix: remove cursorStyle element from the dom on package deactivation
103 |
104 | ## 0.7.4
105 | * Workaround for [#atom/5306](https://github.com/atom/atom/issues/5306)
106 |
107 | ## 0.7.3
108 | * Created a map between `cursorType` names/values for clearer options in the settings view select box
109 |
110 | ## 0.7.2
111 | * Show cursor examples in the settings view
112 |
113 | ## 0.7.1
114 | * Write less rules to the stylesheet
115 |
116 | ## 0.7.0 - Modernizing
117 | * Removed deprecated functions
118 | * atom.themes.removeStylesheet
119 | * atom.themes.requireStylesheet
120 |
121 | ## 0.6.1
122 | * Nicer looking readme
123 |
124 | ## 0.6.0 - Cursor galore
125 | * Added 3 types of cursors. See readme for images
126 | * I-beam
127 | * Bordered box
128 | * Underline
129 |
130 | ## 0.5.1
131 | * Updated readme
132 |
133 | ## 0.5.0 - Fancy pulse
134 | * Replaced the `enablePulse` option with `pulseDuration` option
135 |
136 | ## 0.4.6
137 | * Fix: make block-cursor.coffee look for vars.less instead of colors.less
138 | * Fix: make block-cursor.less look for vars.less instead of colors.less
139 |
140 | ## 0.4.5
141 | * Removed the block-cursor class from the workspaceView
142 | * Removed the block-cursor-pulse class from the workspaceView
143 | * Renamed styles/includes/colors.less -> styles/includes/vars.less
144 |
145 | ## 0.4.4 - Cleanup
146 | * Removed some console.logs
147 |
148 | ## 0.4.3 - Keeping track
149 | * Fixed false changelog information
150 |
151 | ## 0.4.2 - Config stuff
152 | * Changed the configuration mechanism, much easier to keep track of the config
153 |
154 | ## 0.4.1 - Cleanup
155 | * Removed some stray console.logs
156 |
157 | ## 0.4.0
158 | * Added pulse option
159 |
160 | ## 0.3.1 - Some fixes
161 | * Force cursor opacity to 1, also in blink-off state
162 | * Slightly changed the atom-text-editor[mini] selector
163 |
164 | ## 0.3.0 - Fancy blinking
165 | * Removed `cursorBlink` option
166 | * Renamed `cursorColor` option -> `primaryColor`
167 | * Added `secondaryColor` option
168 |
169 | ## 0.2.4 - Specs
170 | * Created specs for testing
171 |
172 | ## 0.2.3 - !important stuff
173 | * Made compatible with certain syntax themes that set !important on the border color of the cursor
174 |
175 | ## 0.2.2 - Grammar nazi
176 | * Fixed capitalization in config descriptions
177 |
178 | ## 0.2.1 - Blinking cursors
179 | * Fixed the `cursorBlink` config option
180 |
181 | ## 0.2.0 - Config color
182 | * Using new `color` type for the cursorColor option
183 |
184 | ## 0.1.1 - Readme fix
185 | * Fixed the image's url in the readme
186 |
187 | ## 0.1.0 - First Release
188 | * Every feature added
189 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Olmo Kramer
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ## Configure
4 |
5 | Multiple cursor types can be registered in `config.cson`. The `block-cursor:new-custom-cursor` command can register a new cursor type.
6 |
7 | The following properties can be set for each cursor type:
8 |
9 | ```coffee
10 | selector: 'atom-text-editor'
11 | scopes: [ '*' ]
12 | blinkOn:
13 | backgroundColor: '#393939'
14 | borderStyle: 'none'
15 | borderColor: 'transparent'
16 | borderWidth: 0
17 | blinkOff:
18 | backgroundColor: 'transparent'
19 | borderStyle: 'none'
20 | borderColor: 'transparent'
21 | borderWidth: 0
22 | pulseDuration: 0
23 | cursorLineFix: false
24 | ```
25 |
26 | ### selector
27 |
28 | Defines which `atom-text-editor` elements the cursor type should apply to. The selector should select an `atom-text-editor` element.
29 |
30 | ### scopes
31 |
32 | List of scopes that the cursor type should apply to.
33 |
34 | ### blinkOn.backgroundColor & blinkOff.backgroundColor
35 |
36 | The background color of the cursor in blink-on or blink-off state.
37 |
38 | ### blinkOn.borderStyle & blinkOff.borderStyle
39 |
40 | The border style of the cursor in blink-on or blink-off state. Can be one of the following:
41 |
42 | 
43 |
44 | 
45 |
46 | 
47 |
48 | `none`
49 |
50 | ### blinkOn.borderColor & blinkOff.borderColor
51 |
52 | The border color of the cursor in blink-on or blink-off state.
53 |
54 | ### blinkOn.borderWidth & blinkOff.borderWidth
55 |
56 | The border width of the cursor in blink-on or blink-off state.
57 |
58 | ### pulseDuration
59 |
60 | Pulse effect that fades the cursor from blink-on to blink-off state (instead of blinking). Set to 0 to disable.
61 |
62 | 
63 |
64 | ### cursorLineFix
65 |
66 | When your syntax theme uses a `background-color` on `.cursor-line` - the line the cursor is on - the `block` cursor may become invisible. This is because the cursor has a `z-index` of `-1`, to make it render behind the text instead of above it. This fix sets the cursor's `z-index` to `1`, to make it render above the text, so you should use low `alpha` values for `primaryColor` and `secondaryColor` if you enable this fix.
67 |
68 | The `cursorLineFix` is currently ignored due to the new tile rendering of the editor that was introduced in Atom v0.209.0. It will always be set to `true`, to allow the cursor to render above the text, so make sure the background colors you use have low alpha values. Otherwise the character under the cursor will not be visible.
69 |
70 | You can also add this to your `styles.less` to disable the line highlight:
71 | ```less
72 | atom-text-editor.editor .lines .line.cursor-line {
73 | background-color: transparent;
74 | }
75 | ```
76 |
77 |
78 |
79 | ### Example config
80 |
81 | ```coffee
82 | "block-cursor":
83 | # white cursor by default
84 | global:
85 | blinkOn:
86 | backgroundColor: "white"
87 | # dary grey cursor on [mini] editors
88 | mini:
89 | selector: "atom-text-editor[mini]"
90 | blinkOn:
91 | backgroundColor: "darkgrey"
92 | # box cursor when editor is not focused
93 | "no-focus":
94 | selector: "atom-text-editor:not(.is-focused)"
95 | blinkOn:
96 | backgroundColor: "transparent"
97 | borderColor: "white"
98 | borderStyle: "bordered-box"
99 | borderWidth: 1
100 | # red cursor in coffeescript
101 | "coffee-script":
102 | scopes: [ ".source.coffee" ],
103 | blinkOn:
104 | backgroundColor: "red"
105 | # lightgray cursor when using the one-dark-syntax theme
106 | "one-dark-syntax":
107 | selector: ".theme-one-dark-syntax atom-text-editor"
108 | blinkOn:
109 | backgroundColor: "lightgray"
110 | # darkgray cursor when using the one-light-syntax theme
111 | "one-light-syntax":
112 | selector: ".theme-one-light-syntax atom-text-editor"
113 | blinkOn:
114 | backgroundColor: "darkgray"
115 | ```
116 |
117 |
118 |
119 | ## Commands
120 |
121 | ### `block-cursor:new-custom-cursor`
122 |
123 | This command adds a new cursor type that can be customised customise to `config.cson`, that can be configured from the settings view. By default it will be called `custom-X`, but it can be renamed to anything you like.
124 |
125 |
126 | ## Contribute
127 |
128 | Have other neat ideas for cursor customization? Found a bug?
129 |
130 | 1. :fork_and_knife: Fork the repo
131 | 2. :rocket: Make awesome things happen
132 | 3. :octocat: Create a pull request
133 |
134 | Or [create a new issue](https://github.com/adamrenklint/atom-block-cursor/issues/new) at the repository if you can't do it yourself.
135 |
136 | ## License and credits
137 |
138 | © 2015 Olmo Kramer
139 | Maintainer: [Adam Renklint](http://adamrenklint.com)
140 | [MIT license](LICENSE.md)
141 |
--------------------------------------------------------------------------------
/block-cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrenklint/atom-block-cursor/295bbf70df68295451c694c88079657feb74b05f/block-cursor.png
--------------------------------------------------------------------------------
/cursor-bordered-box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrenklint/atom-block-cursor/295bbf70df68295451c694c88079657feb74b05f/cursor-bordered-box.png
--------------------------------------------------------------------------------
/cursor-i-beam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrenklint/atom-block-cursor/295bbf70df68295451c694c88079657feb74b05f/cursor-i-beam.png
--------------------------------------------------------------------------------
/cursor-pulse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrenklint/atom-block-cursor/295bbf70df68295451c694c88079657feb74b05f/cursor-pulse.gif
--------------------------------------------------------------------------------
/cursor-underline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrenklint/atom-block-cursor/295bbf70df68295451c694c88079657feb74b05f/cursor-underline.png
--------------------------------------------------------------------------------
/lib/block-cursor.js:
--------------------------------------------------------------------------------
1 | 'use babel';
2 | import 'object-assign-shim';
3 | import {Disposable, CompositeDisposable} from 'atom';
4 |
5 | // helper functions
6 |
7 | // get the key in namespace
8 | function getConfig(key, namespace = 'block-cursor') {
9 | return atom.config.get(key ? `${namespace}.${key}` : namespace);
10 | }
11 |
12 | // set the key in namespace
13 | function setConfig(key, value, namespace = 'block-cursor') {
14 | return atom.config.set(`${namespace}.${key}`, value);
15 | }
16 |
17 | // get a clone of the global config
18 | function getGlobalConfig() {
19 | var config = Object.assign({}, getConfig('global'));
20 | Object.assign(config.blinkOn, getConfig('global.blinkOn'));
21 | Object.assign(config.blinkOff, getConfig('global.blinkOff'));
22 | return config;
23 | }
24 |
25 | // convert a color to a string
26 | function toRGBAString(color) {
27 | if(typeof color == 'string') return color;
28 | if(typeof color.toRGBAString == 'function') return color.toRGBAString();
29 | return `rgba(${color.red}, ${color.green}, ${color.blue}, ${color.alpha})`;
30 | }
31 |
32 | // private API
33 |
34 | // keep a reference to the stylesheet
35 | var style;
36 |
37 | // create a stylesheet element and
38 | // attach it to the DOM
39 | function setupStylesheet() {
40 | style = document.createElement('style');
41 | style.type = 'text/css';
42 | document.querySelector('head atom-styles').appendChild(style);
43 |
44 | // return a disposable for easy removal :)
45 | return new Disposable(() => {
46 | style.parentNode.removeChild(style);
47 | style = null;
48 | });
49 | }
50 |
51 | // update the stylesheet when config changes
52 | function updateCursorStyles(config) {
53 | // clear stylesheet
54 | style.innerHTML = '';
55 | for(let key of Object.keys(config)) {
56 | // and add styles for each cursor style
57 | style.innerHTML += cssForCursorStyle(config[key]);
58 | }
59 | }
60 |
61 | function cssForCursorStyle(cursorStyle) {
62 | // fill the cursor style with global as defaults
63 | cursorStyle = Object.assign(getGlobalConfig(), cursorStyle);
64 | var blinkOn = Object.assign({}, getConfig('global.blinkOn'), cursorStyle.blinkOn);
65 | var blinkOff = Object.assign({}, getConfig('global.blinkOff'), cursorStyle.blinkOff);
66 | var {selector, scopes, pulseDuration, cursorLineFix} = cursorStyle;
67 |
68 | // if cursor blinking is off, set the secondaryColor the same
69 | // as primaryColor to prevent cursor blinking in [mini] editors
70 | if(atom.packages.isPackageActive('cursor-blink-interval') &&
71 | getConfig('cursorBlinkInterval', 'cursor-blink-interval') == 0)
72 | blinkOff = Object.assign({}, blinkOn);
73 |
74 | // blink on rule
75 | Object.assign(blinkOn, {
76 | selector: selectorForScopes(selector, scopes),
77 | properties: Object.assign({
78 | // blink on background color
79 | 'background-color': toRGBAString(blinkOn.backgroundColor),
80 | // pulse animation duration
81 | 'transition-duration': `${pulseDuration}ms`,
82 | // cursor line fix
83 | // 'z-index': cursorLineFix ? 1 : -1 // @TODO: enable this when a solution is found for #20
84 | }, createBorderStyle(blinkOn)),
85 | });
86 | // end blink on rule
87 |
88 | // blink off rule
89 | Object.assign(blinkOff, {
90 | selector: selectorForScopes(selector, scopes, true),
91 | properties: {},
92 | });
93 | if(blinkOff.backgroundColor.alpha == 0 && (blinkOff.borderWidth == 0 ||
94 | blinkOff.borderStyle == 'none' || blinkOff.borderColor.alpha == 0)) {
95 | // better animation performance by animating opacity
96 | // if blink off cursor is invisible
97 | blinkOff.properties.opacity = 0;
98 | } else {
99 | Object.assign(blinkOff.properties, {
100 | // blink off background color
101 | 'background-color': toRGBAString(blinkOff.backgroundColor),
102 | }, createBorderStyle(blinkOff));
103 | }
104 | // end blink off rule
105 |
106 | return createCSSRule(blinkOn) + createCSSRule(blinkOff);
107 | }
108 |
109 | // create a css properties object for given border properties
110 | function createBorderStyle({borderWidth, borderStyle, borderColor}) {
111 | var borderString = `${borderWidth}px solid ${toRGBAString(borderColor)}`;
112 | switch(borderStyle) {
113 | case 'bordered-box':
114 | // border on all sides
115 | return { border: borderString };
116 | case 'i-beam':
117 | // border on left side
118 | return { border: 'none', 'border-left': borderString };
119 | case 'underline':
120 | // border on bottom side
121 | return { border: 'none', 'border-bottom': borderString };
122 | default:
123 | // no border
124 | return { border: 'none' };
125 | }
126 | }
127 |
128 | // create a css rule from a selector and an
129 | // object containint propertyNames and values
130 | // of the form
131 | // {
132 | // : ;
133 | // : ;
134 | // ...
135 | // }
136 |
137 | function createCSSRule({selector, properties}) {
138 | return `${selector} { ${Object.keys(properties).map((key) => `${key}: ${properties[key]};`).join('')} }`;
139 | }
140 |
141 | // creates a css selector for the given scopes
142 | // @param base: selector that selects the atom-text-editor element
143 | // @param scopes: array of scopes to select
144 | // @param blinkOff: create a blink-off selector?
145 | function selectorForScopes(base, scopes, blinkOff = '') {
146 | var selectors = [];
147 |
148 | function grammarSelectorsForScopeName(scopeName) {
149 | return scopeName.split('.').map(scope => `[data-grammar~="${scope}"]`).join('');
150 | }
151 |
152 | if(blinkOff) blinkOff = '.blink-off';
153 |
154 | for(let scopeName of scopes) {
155 | let grammarSelectors = scopeName == '*' ? '' : grammarSelectorsForScopeName(scopeName);
156 | selectors.push(`${base}${grammarSelectors}.editor .cursors${blinkOff} .cursor`);
157 | }
158 | return selectors.join(',');
159 | }
160 |
161 | // add a custom cursor to the config. an easy
162 | // shortcut when you want to define a new cursor type
163 | function addCustomCursor() {
164 | var i = 0;
165 | while(getConfig(`custom-${i}`)) i++;
166 | setConfig(`custom-${i}`, getGlobalConfig());
167 | }
168 |
169 | // public API
170 |
171 | // module.exports = BlockCursor = {
172 | const config = {
173 | global: {
174 | type: 'object',
175 | properties: {
176 | scopes: {
177 | type: 'array',
178 | default: [ '*' ],
179 | },
180 | selector: {
181 | type: 'string',
182 | default: 'atom-text-editor',
183 | },
184 | blinkOn: {
185 | type: 'object',
186 | properties: {
187 | backgroundColor: {
188 | type: 'color',
189 | default: '#393939',
190 | },
191 | borderWidth: {
192 | type: 'integer',
193 | default: 1,
194 | minimum: 0,
195 | },
196 | borderStyle: {
197 | type: 'string',
198 | default: 'none',
199 | enum: [
200 | 'none',
201 | 'bordered-box',
202 | 'i-beam',
203 | 'underline',
204 | ],
205 | },
206 | borderColor: {
207 | type: 'color',
208 | default: 'transparent',
209 | },
210 | },
211 | },
212 | blinkOff: {
213 | type: 'object',
214 | properties: {
215 | backgroundColor: {
216 | type: 'color',
217 | default: 'transparent',
218 | },
219 | borderWidth: {
220 | type: 'integer',
221 | default: 1,
222 | minimum: 0,
223 | },
224 | borderStyle: {
225 | type: 'string',
226 | default: 'none',
227 | enum: [
228 | 'none',
229 | 'bordered-box',
230 | 'i-beam',
231 | 'underline',
232 | ],
233 | },
234 | borderColor: {
235 | type: 'color',
236 | default: 'transparent',
237 | },
238 | },
239 | },
240 | pulseDuration: {
241 | type: 'integer',
242 | default: 0,
243 | minimum: 0,
244 | },
245 | cursorLineFix: {
246 | description: 'Temporarily ignored (always true) because of an issue with the tile rendering introduced in Atom 0.209.0.',
247 | type: 'boolean',
248 | default: false,
249 | },
250 | },
251 | },
252 | };
253 |
254 | var disposables;
255 |
256 | function activate() {
257 | // wait for cursor-blink-interval package to activate
258 | // if it is loaded
259 | Promise.resolve(
260 | atom.packages.isPackageLoaded('cursor-blink-interval') &&
261 | atom.packages.activatePackage('cursor-blink-interval')
262 | ).then(function go() {
263 | disposables = new CompositeDisposable(
264 | setupStylesheet(),
265 | atom.config.observe('block-cursor', updateCursorStyles),
266 | atom.commands.add('atom-workspace', 'block-cursor:new-custom-cursor', addCustomCursor)
267 | );
268 | }).catch(error => {
269 | console.error(error.message);
270 | });
271 | }
272 |
273 | function deactivate() {
274 | disposables.dispose();
275 | disposables = null;
276 | }
277 |
278 | export {config, activate, deactivate};
279 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "block-cursor",
3 | "main": "./lib/block-cursor",
4 | "version": "0.13.3",
5 | "description": "Fancy cursor customisation plugin",
6 | "keywords": [
7 | "ui",
8 | "cursor"
9 | ],
10 | "repository": "git@github.com:adamrenklint/atom-block-cursor.git",
11 | "license": "MIT",
12 | "engines": {
13 | "atom": ">=1.13.0"
14 | },
15 | "dependencies": {
16 | "object-assign-shim": "^1.0.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/styles/block-cursor.less:
--------------------------------------------------------------------------------
1 | atom-text-editor.editor .cursors .cursor {
2 | opacity: 1;
3 | color: transparent;
4 | background-color: transparent;
5 | border: none;
6 | transition-property: background-color, border-color, opacity;
7 | }
8 |
9 | atom-text-editor[mini]:not(.is-focused).editor .cursors .cursor {
10 | display: none;
11 | }
12 |
--------------------------------------------------------------------------------