├── spec
├── fixtures
│ ├── dir
│ │ ├── file1
│ │ ├── b
│ │ ├── a-dir
│ │ │ └── oh-git
│ │ └── a
│ ├── git
│ │ ├── working-dir
│ │ │ ├── a.txt
│ │ │ ├── .gitignore
│ │ │ └── git.git
│ │ │ │ ├── HEAD
│ │ │ │ ├── refs
│ │ │ │ └── heads
│ │ │ │ │ └── master
│ │ │ │ ├── index
│ │ │ │ ├── config
│ │ │ │ └── objects
│ │ │ │ ├── 16
│ │ │ │ └── 735fb793d7b038818219c4b8c6295346e20eef
│ │ │ │ ├── 52
│ │ │ │ └── f56457b6fca045ce41bb9d32e6ca79d23192af
│ │ │ │ ├── 65
│ │ │ │ └── a457425a679cbe9adf0d2741785d3ceabb44a7
│ │ │ │ ├── 66
│ │ │ │ └── dc9051da651c15d98d017a88658263cab28f02
│ │ │ │ ├── 06
│ │ │ │ └── 15f9a45968b3515e0a202530ef9f61aba26b6c
│ │ │ │ ├── 5b
│ │ │ │ └── 24ab4c3baadf534242b1acc220c8fa051b9b20
│ │ │ │ ├── 8a
│ │ │ │ └── 9c86f1cb1f14b8f436eb91f4b052c8802ca99e
│ │ │ │ ├── e6
│ │ │ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ │ │ │ ├── ec
│ │ │ │ └── 5e386905ff2d36e291086a1207f2585aaa8920
│ │ │ │ ├── ef
│ │ │ │ └── 046e9eecaa5255ea5e9817132d4001724d6ae1
│ │ │ │ ├── fe
│ │ │ │ └── bde178cdf35e9df6279d87aa27590c6d92e354
│ │ │ │ └── ff
│ │ │ │ └── c8218bd2240a0cb92f6f02548d45784428349b
│ │ ├── ignore.git
│ │ │ ├── info
│ │ │ │ └── exclude
│ │ │ ├── HEAD
│ │ │ ├── refs
│ │ │ │ └── heads
│ │ │ │ │ └── master
│ │ │ ├── index
│ │ │ ├── config
│ │ │ └── objects
│ │ │ │ ├── 65
│ │ │ │ └── a457425a679cbe9adf0d2741785d3ceabb44a7
│ │ │ │ ├── e6
│ │ │ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ │ │ │ └── ef
│ │ │ │ └── 046e9eecaa5255ea5e9817132d4001724d6ae1
│ │ └── master.git
│ │ │ ├── HEAD
│ │ │ ├── refs
│ │ │ └── heads
│ │ │ │ └── master
│ │ │ ├── index
│ │ │ ├── config
│ │ │ └── objects
│ │ │ ├── 65
│ │ │ └── a457425a679cbe9adf0d2741785d3ceabb44a7
│ │ │ ├── e6
│ │ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ │ │ └── ef
│ │ │ └── 046e9eecaa5255ea5e9817132d4001724d6ae1
│ ├── sample.txt
│ ├── packages
│ │ ├── package-with-empty-menu
│ │ │ ├── menus
│ │ │ │ └── menu.cson
│ │ │ └── package.json
│ │ ├── package-with-empty-keymap
│ │ │ ├── keymaps
│ │ │ │ └── keymap.cson
│ │ │ └── package.json
│ │ ├── package-with-incompatible-native-module
│ │ │ ├── main.js
│ │ │ ├── node_modules
│ │ │ │ └── native-module
│ │ │ │ │ ├── build
│ │ │ │ │ └── Release
│ │ │ │ │ │ └── native.node
│ │ │ │ │ ├── main.js
│ │ │ │ │ └── package.json
│ │ │ └── package.json
│ │ ├── theme-with-syntax-variables
│ │ │ ├── styles
│ │ │ │ └── editor.less
│ │ │ └── package.json
│ │ ├── package-with-invalid-styles
│ │ │ ├── styles
│ │ │ │ └── index.less
│ │ │ └── package.json
│ │ ├── package-with-styles
│ │ │ └── styles
│ │ │ │ ├── 4.css
│ │ │ │ ├── 1.css
│ │ │ │ ├── 3.test-context.css
│ │ │ │ └── 2.less
│ │ ├── package-with-broken-keymap
│ │ │ └── keymaps
│ │ │ │ └── broken.json
│ │ ├── package-with-broken-package-json
│ │ │ └── package.json
│ │ ├── package-with-main
│ │ │ ├── package.cson
│ │ │ └── main-module.coffee
│ │ ├── package-without-module
│ │ │ └── package.cson
│ │ ├── theme-with-index-css
│ │ │ ├── package.json
│ │ │ └── index.css
│ │ ├── package-with-index
│ │ │ └── index.coffee
│ │ ├── package-with-serialize-error
│ │ │ ├── package.cson
│ │ │ └── index.coffee
│ │ ├── theme-with-index-less
│ │ │ ├── package.json
│ │ │ └── index.less
│ │ ├── package-with-menus-manifest
│ │ │ ├── package.cson
│ │ │ └── menus
│ │ │ │ ├── menu-3.cson
│ │ │ │ ├── menu-1.cson
│ │ │ │ └── menu-2.cson
│ │ ├── package-with-style-sheets-manifest
│ │ │ ├── package.cson
│ │ │ └── styles
│ │ │ │ ├── 1.css
│ │ │ │ ├── 3.css
│ │ │ │ └── 2.less
│ │ ├── package-with-stylesheets-manifest
│ │ │ └── package.cson
│ │ ├── package-with-keymaps-manifest
│ │ │ ├── package.cson
│ │ │ └── keymaps
│ │ │ │ ├── keymap-3.cson
│ │ │ │ ├── keymap-1.json
│ │ │ │ └── keymap-2.cson
│ │ ├── package-with-empty-activation-commands
│ │ │ ├── index.coffee
│ │ │ └── package.json
│ │ ├── package-with-keymaps
│ │ │ └── keymaps
│ │ │ │ ├── keymap-1.cson
│ │ │ │ ├── keymap-2.cson
│ │ │ │ └── keymap-3.cjson
│ │ ├── package-with-deactivate
│ │ │ └── index.coffee
│ │ ├── package-that-throws-an-exception
│ │ │ └── index.coffee
│ │ ├── theme-with-ui-variables
│ │ │ ├── package.json
│ │ │ └── styles
│ │ │ │ ├── editor.less
│ │ │ │ └── ui-variables.less
│ │ ├── package-with-activation-commands
│ │ │ ├── package.cson
│ │ │ └── index.coffee
│ │ ├── package-with-settings
│ │ │ └── settings
│ │ │ │ └── omg.cson
│ │ ├── theme-with-incomplete-ui-variables
│ │ │ ├── package.json
│ │ │ └── styles
│ │ │ │ ├── ui-variables.less
│ │ │ │ └── editor.less
│ │ ├── theme-without-package-file
│ │ │ └── styles
│ │ │ │ ├── b.css
│ │ │ │ ├── c.less
│ │ │ │ ├── a.css
│ │ │ │ └── d.csv
│ │ ├── theme-with-package-file
│ │ │ ├── package.json
│ │ │ └── styles
│ │ │ │ ├── last.css
│ │ │ │ ├── first.css
│ │ │ │ └── second.less
│ │ ├── package-that-throws-on-activate
│ │ │ └── index.coffee
│ │ ├── package-that-throws-on-deactivate
│ │ │ └── index.coffee
│ │ ├── package-with-config-defaults
│ │ │ └── index.coffee
│ │ ├── package-with-serialization
│ │ │ └── index.coffee
│ │ ├── package-with-deprecated-pane-item-method
│ │ │ └── index.coffee
│ │ ├── package-with-injection-selector
│ │ │ └── grammars
│ │ │ │ └── grammar.cson
│ │ ├── package-with-menus
│ │ │ └── menus
│ │ │ │ ├── menu-2.cson
│ │ │ │ ├── menu-1.cson
│ │ │ │ └── menu-3.cson
│ │ ├── package-with-consumed-services
│ │ │ ├── index.coffee
│ │ │ └── package.json
│ │ ├── package-with-grammars
│ │ │ └── grammars
│ │ │ │ ├── alot.cson
│ │ │ │ └── alittle.cson
│ │ ├── package-with-provided-services
│ │ │ ├── index.coffee
│ │ │ └── package.json
│ │ └── package-with-config-schema
│ │ │ └── index.coffee
│ ├── module-cache
│ │ └── file.json
│ ├── script.js
│ ├── shebang
│ ├── 6to5
│ │ ├── invalid.js
│ │ ├── double-quotes.js
│ │ └── single-quotes.js
│ ├── script-with-deprecations.js
│ ├── task-spec-handler.coffee
│ ├── css.css
│ ├── sample.less
│ ├── sample-with-tabs.coffee
│ ├── sample-with-tabs-and-leading-comment.coffee
│ ├── sample-with-tabs-and-initial-comment.js
│ ├── sample.js
│ ├── coffee.coffee
│ └── sample-with-comments.js
├── atom-protocol-handler-spec.coffee
├── clipboard-spec.coffee
├── panel-spec.coffee
├── spec-bootstrap.coffee
├── spec-helper-platform.coffee
├── buffered-node-process-spec.coffee
├── space-pen-extensions-spec.coffee
├── command-installer-spec.coffee
├── task-spec.coffee
├── 6to5-spec.coffee
├── jasmine-helper.coffee
├── tokenized-line-spec.coffee
├── notification-spec.coffee
├── spec-suite.coffee
├── deserializer-manager-spec.coffee
├── menu-manager-spec.coffee
├── time-reporter.coffee
├── notification-manager-spec.coffee
├── panel-element-spec.coffee
└── text-utils-spec.coffee
├── .node-version
├── .python-version
├── .npmrc
├── docs
├── contributing.md
├── README.md
├── build-instructions
│ ├── freebsd.md
│ └── os-x.md
├── advanced
│ ├── node-modules.md
│ └── configuration.md
├── index.md
├── upgrading
│ └── upgrading-your-syntax-theme.md
├── converting-a-text-mate-bundle.md
├── contributing-to-packages.md
└── converting-a-text-mate-theme.md
├── dot-atom
├── .gitignore
├── packages
│ └── README.md
├── config.cson
├── init.coffee
├── styles.less
├── snippets.cson
└── keymap.cson
├── resources
├── atom.png
├── mac
│ ├── atom.icns
│ ├── file.icns
│ ├── helper-Info.plist
│ └── speakeasy.pem
├── win
│ ├── atom.ico
│ ├── loading.gif
│ ├── apm.sh
│ ├── atom.js
│ ├── atom.sh
│ └── atom.cmd
└── linux
│ ├── icons
│ ├── 16.png
│ ├── 24.png
│ ├── 32.png
│ ├── 48.png
│ ├── 64.png
│ ├── 1024.png
│ ├── 128.png
│ ├── 256.png
│ └── 512.png
│ ├── atom.desktop.in
│ ├── debian
│ ├── lintian-overrides
│ └── control.in
│ └── redhat
│ └── atom.spec.in
├── static
├── octicons.woff
├── images
│ ├── octocat-spinner-128.gif
│ └── transparent-background.gif
├── links.less
├── icons.less
├── markdown.less
├── linux.less
├── popover-list.less
├── index.html
├── bootstrap-overrides.less
├── messages.less
├── workspace-view.less
├── select-list.less
├── atom.less
├── sections.less
├── syntax.less
├── variables
│ ├── octicon-mixins.less
│ ├── syntax-variables.less
│ └── ui-variables.less
├── panes.less
├── bootstrap.less
├── utilities.less
└── buttons.less
├── apm
├── README.md
└── package.json
├── script
├── rpmbuild
├── build.cmd
├── clean.cmd
├── grunt.cmd
├── utils
│ ├── compile-main-to-app
│ ├── clean-open-with-menu
│ ├── fix-author
│ ├── clean-merged-branches
│ ├── child-process-wrapper.js
│ └── translate-crash-log-addresses.coffee
├── bootstrap.cmd
├── cibuild-atom-rpm
├── copy-folder.cmd
├── cibuild-atom-linux
├── test
├── mkrpm
├── build
├── create-shortcut.cmd
├── set-version
├── grunt
├── mkdeb
├── clean
└── cibuild
├── src
├── subscriber-mixin.coffee
├── item-registry.coffee
├── window-bootstrap.coffee
├── replace-handler.coffee
├── custom-event-mixin.coffee
├── cursor-component.coffee
├── scrollbar-corner-component.coffee
├── scoped-properties.coffee
├── theme-package.coffee
├── scan-handler.coffee
├── window.coffee
├── browser
│ ├── context-menu.coffee
│ ├── atom-protocol-handler.coffee
│ └── auto-updater-win32.coffee
├── less-compile-cache.coffee
├── repository-status-handler.coffee
├── panel-element.coffee
├── scroll-view.coffee
├── input-component.coffee
├── task-bootstrap.coffee
├── highlights-component.coffee
├── notification.coffee
├── scope-descriptor.coffee
├── notification-manager.coffee
├── pane-axis-element.coffee
├── clipboard.coffee
├── panel-container-element.coffee
├── overlay-manager.coffee
├── panel-container.coffee
├── menu-helpers.coffee
├── cursors-component.coffee
├── keymap-extensions.coffee
├── deserializer-manager.coffee
├── panel.coffee
├── buffered-node-process.coffee
├── pane-container-view.coffee
├── text-utils.coffee
├── coffee-cache.coffee
├── fold.coffee
└── color.coffee
├── .gitignore
├── keymaps
├── emacs.cson
└── base.cson
├── coffeelint.json
├── benchmark
├── benchmark-bootstrap.coffee
└── browser-process-startup.coffee
├── .pairs
├── Dockerfile
├── .gitattributes
├── LICENSE.md
└── README.md
/spec/fixtures/dir/file1:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | v0.10.33
2 |
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
1 | 2.7.6
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | cache = ~/.atom/.npm
2 |
--------------------------------------------------------------------------------
/spec/fixtures/dir/b:
--------------------------------------------------------------------------------
1 | aaa ccc
2 |
--------------------------------------------------------------------------------
/docs/contributing.md:
--------------------------------------------------------------------------------
1 | ../CONTRIBUTING.md
--------------------------------------------------------------------------------
/spec/fixtures/dir/a-dir/oh-git:
--------------------------------------------------------------------------------
1 | bbb aaaa
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/a.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/sample.txt:
--------------------------------------------------------------------------------
1 | Some text.
2 |
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/info/exclude:
--------------------------------------------------------------------------------
1 | a.txt
2 |
--------------------------------------------------------------------------------
/spec/fixtures/dir/a:
--------------------------------------------------------------------------------
1 | aaa bbb
2 | cc aa cc
3 | dollar$bill
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/HEAD:
--------------------------------------------------------------------------------
1 | ref: refs/heads/master
2 |
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/HEAD:
--------------------------------------------------------------------------------
1 | ref: refs/heads/master
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-empty-menu/menus/menu.cson:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/.gitignore:
--------------------------------------------------------------------------------
1 | poop
2 | ignored.txt
3 |
--------------------------------------------------------------------------------
/spec/fixtures/module-cache/file.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar"
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-empty-keymap/keymaps/keymap.cson:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/script.js:
--------------------------------------------------------------------------------
1 | process.stdout.write(process.argv[2]);
2 |
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/HEAD:
--------------------------------------------------------------------------------
1 | ref: refs/heads/master
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-incompatible-native-module/main.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-syntax-variables/styles/editor.less:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/shebang:
--------------------------------------------------------------------------------
1 | #!/usr/bin/ruby
2 |
3 | puts "America – fuck yeah!"
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-invalid-styles/styles/index.less:
--------------------------------------------------------------------------------
1 | {
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-styles/styles/4.css:
--------------------------------------------------------------------------------
1 | a { color: red }
2 |
--------------------------------------------------------------------------------
/dot-atom/.gitignore:
--------------------------------------------------------------------------------
1 | storage
2 | compile-cache
3 | dev
4 | .npm
5 | .node-gyp
6 |
--------------------------------------------------------------------------------
/spec/fixtures/6to5/invalid.js:
--------------------------------------------------------------------------------
1 | 'use 6to6';
2 |
3 | module.exports = v => v + 1
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-broken-keymap/keymaps/broken.json:
--------------------------------------------------------------------------------
1 | INVALID
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-broken-package-json/package.json:
--------------------------------------------------------------------------------
1 | INVALID
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-main/package.cson:
--------------------------------------------------------------------------------
1 | 'main': 'main-module.coffee'
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-without-module/package.cson:
--------------------------------------------------------------------------------
1 | "name": "perfect"
2 |
--------------------------------------------------------------------------------
/resources/atom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/atom.png
--------------------------------------------------------------------------------
/spec/fixtures/6to5/double-quotes.js:
--------------------------------------------------------------------------------
1 | "use 6to5";
2 |
3 | module.exports = v => v + 1
4 |
--------------------------------------------------------------------------------
/spec/fixtures/6to5/single-quotes.js:
--------------------------------------------------------------------------------
1 | 'use 6to5';
2 |
3 | module.exports = v => v + 1
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-index-css/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "theme": "ui"
3 | }
4 |
--------------------------------------------------------------------------------
/dot-atom/packages/README.md:
--------------------------------------------------------------------------------
1 | All packages in this directory will be automatically loaded
2 |
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/refs/heads/master:
--------------------------------------------------------------------------------
1 | ef046e9eecaa5255ea5e9817132d4001724d6ae1
2 |
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/refs/heads/master:
--------------------------------------------------------------------------------
1 | ef046e9eecaa5255ea5e9817132d4001724d6ae1
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-index/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-serialize-error/package.cson:
--------------------------------------------------------------------------------
1 | 'main': 'index.coffee'
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-index-less/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "theme": "ui"
3 | }
4 |
--------------------------------------------------------------------------------
/static/octicons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/static/octicons.woff
--------------------------------------------------------------------------------
/resources/mac/atom.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/mac/atom.icns
--------------------------------------------------------------------------------
/resources/mac/file.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/mac/file.icns
--------------------------------------------------------------------------------
/resources/win/atom.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/win/atom.ico
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-main/main-module.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus-manifest/package.cson:
--------------------------------------------------------------------------------
1 | menus: ["menu-2", "menu-1"]
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-style-sheets-manifest/package.cson:
--------------------------------------------------------------------------------
1 | styleSheets: ['2', '1']
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-stylesheets-manifest/package.cson:
--------------------------------------------------------------------------------
1 | styleSheets: ['2', '1']
2 |
--------------------------------------------------------------------------------
/resources/win/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/win/loading.gif
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/refs/heads/master:
--------------------------------------------------------------------------------
1 | 8a9c86f1cb1f14b8f436eb91f4b052c8802ca99e
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps-manifest/package.cson:
--------------------------------------------------------------------------------
1 | keymaps: ["keymap-2", "keymap-1"]
2 |
--------------------------------------------------------------------------------
/resources/linux/icons/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/16.png
--------------------------------------------------------------------------------
/resources/linux/icons/24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/24.png
--------------------------------------------------------------------------------
/resources/linux/icons/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/32.png
--------------------------------------------------------------------------------
/resources/linux/icons/48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/48.png
--------------------------------------------------------------------------------
/resources/linux/icons/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/64.png
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-empty-activation-commands/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports = activate: ->
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps/keymaps/keymap-1.cson:
--------------------------------------------------------------------------------
1 | ".test-1":
2 | "ctrl-z": "test-1"
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps/keymaps/keymap-2.cson:
--------------------------------------------------------------------------------
1 | ".test-2":
2 | "ctrl-z": "test-2"
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps/keymaps/keymap-3.cjson:
--------------------------------------------------------------------------------
1 | ".test-3":
2 | "ctrl-z": "test-3"
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-styles/styles/1.css:
--------------------------------------------------------------------------------
1 | #jasmine-content {
2 | font-size: 1px;
3 | }
4 |
--------------------------------------------------------------------------------
/resources/linux/icons/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/1024.png
--------------------------------------------------------------------------------
/resources/linux/icons/128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/128.png
--------------------------------------------------------------------------------
/resources/linux/icons/256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/256.png
--------------------------------------------------------------------------------
/resources/linux/icons/512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/resources/linux/icons/512.png
--------------------------------------------------------------------------------
/resources/win/apm.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | "$0/../../app/apm/bin/node.exe" "$0/../../app/apm/lib/cli.js" "$@"
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-index-css/index.css:
--------------------------------------------------------------------------------
1 | atom-text-editor {
2 | padding-top: 1234px;
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/script-with-deprecations.js:
--------------------------------------------------------------------------------
1 | require('fs').existsSync('hi');
2 | process.stdout.write('hi');
3 |
--------------------------------------------------------------------------------
/spec/fixtures/task-spec-handler.coffee:
--------------------------------------------------------------------------------
1 | module.exports = ->
2 | emit("some-event", 1, 2, 3)
3 | 'hello'
4 |
--------------------------------------------------------------------------------
/spec/fixtures/css.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-size: 1234px;
3 | width: 110%;
4 | font-weight: bold !important;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-incompatible-native-module/node_modules/native-module/build/Release/native.node:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps-manifest/keymaps/keymap-3.cson:
--------------------------------------------------------------------------------
1 | ".test-3":
2 | "ctrl-y": "keymap-3"
3 |
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/index:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/ignore.git/index
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/index:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/master.git/index
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-deactivate/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 | deactivate: ->
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-style-sheets-manifest/styles/1.css:
--------------------------------------------------------------------------------
1 | #jasmine-content {
2 | font-size: 1px;
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-style-sheets-manifest/styles/3.css:
--------------------------------------------------------------------------------
1 | #jasmine-content {
2 | font-size: 3px;
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-styles/styles/3.test-context.css:
--------------------------------------------------------------------------------
1 | #jasmine-content {
2 | font-size: 3px;
3 | }
4 |
--------------------------------------------------------------------------------
/spec/fixtures/sample.less:
--------------------------------------------------------------------------------
1 | @color: #4D926F;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/apm/README.md:
--------------------------------------------------------------------------------
1 | This folder is where [apm](https://github.com/atom/apm) is installed to so that
2 | it is bundled with Atom.
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-that-throws-an-exception/index.coffee:
--------------------------------------------------------------------------------
1 | throw new Error("This package throws an exception")
2 |
--------------------------------------------------------------------------------
/static/images/octocat-spinner-128.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/static/images/octocat-spinner-128.gif
--------------------------------------------------------------------------------
/script/rpmbuild:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | script/build
6 | script/grunt mkrpm publish-build --stack --install-dir /usr
7 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-styles/styles/2.less:
--------------------------------------------------------------------------------
1 | @size: 2px;
2 |
3 | #jasmine-content {
4 | font-size: @size;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-ui-variables/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "theme": "ui",
3 | "styleSheets": ["editor.less"]
4 | }
5 |
--------------------------------------------------------------------------------
/static/images/transparent-background.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/static/images/transparent-background.gif
--------------------------------------------------------------------------------
/script/build.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 | "%~dp0\node.exe" "%~dp0\build" %*
3 | ) ELSE (
4 | node "%~dp0\build" %*
5 | )
6 |
--------------------------------------------------------------------------------
/script/clean.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 | "%~dp0\node.exe" "%~dp0\clean" %*
3 | ) ELSE (
4 | node "%~dp0\clean" %*
5 | )
6 |
--------------------------------------------------------------------------------
/script/grunt.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 | "%~dp0\node.exe" "%~dp0\grunt" %*
3 | ) ELSE (
4 | node "%~dp0\grunt" %*
5 | )
6 |
--------------------------------------------------------------------------------
/script/utils/compile-main-to-app:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | coffee -c -o /Applications/Atom.app/Contents/Resources/app/src/ src/main.coffee
4 |
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/index:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/index
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-activation-commands/package.cson:
--------------------------------------------------------------------------------
1 | 'activationCommands':
2 | '.workspace': 'activation-command'
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-empty-menu/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package-with-empty-menu",
3 | "version": "1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-settings/settings/omg.cson:
--------------------------------------------------------------------------------
1 | '.source.omg':
2 | 'editor':
3 | 'increaseIndentPattern': '^a'
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-syntax-variables/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "theme": "syntax",
3 | "styleSheets": ["editor.less"]
4 | }
5 |
--------------------------------------------------------------------------------
/dot-atom/config.cson:
--------------------------------------------------------------------------------
1 | 'editor':
2 | 'fontSize': 16
3 | 'core':
4 | 'themes': [
5 | 'atom-dark-ui'
6 | 'atom-dark-syntax'
7 | ]
8 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-empty-keymap/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package-with-empty-keymap",
3 | "version": "1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps-manifest/keymaps/keymap-1.json:
--------------------------------------------------------------------------------
1 | {
2 | ".test-1": {
3 | "ctrl-z": "keymap-1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-keymaps-manifest/keymaps/keymap-2.cson:
--------------------------------------------------------------------------------
1 | ".test-1":
2 | "ctrl-z": "keymap-2"
3 | "ctrl-n": "keymap-2"
4 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-incomplete-ui-variables/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "theme": "ui",
3 | "styleSheets": ["editor.less"]
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-index-less/index.less:
--------------------------------------------------------------------------------
1 | @padding: 4321px;
2 |
3 | atom-text-editor {
4 | padding-top: @padding;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-invalid-styles/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package-with-invalid-styles",
3 | "version": "1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-style-sheets-manifest/styles/2.less:
--------------------------------------------------------------------------------
1 | @size: 2px;
2 |
3 | #jasmine-content {
4 | font-size: @size;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-without-package-file/styles/b.css:
--------------------------------------------------------------------------------
1 | atom-text-editor {
2 | padding-right: 20px;
3 | padding-bottom: 20px;
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-without-package-file/styles/c.less:
--------------------------------------------------------------------------------
1 | @number: 30px;
2 |
3 | atom-text-editor {
4 | padding-bottom: @number;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/sample-with-tabs.coffee:
--------------------------------------------------------------------------------
1 | # Econ 101
2 | if this.studyingEconomics
3 | buy() while supply > demand
4 | sell() until supply > demand
5 |
--------------------------------------------------------------------------------
/script/bootstrap.cmd:
--------------------------------------------------------------------------------
1 | @IF EXIST "%~dp0\node.exe" (
2 | "%~dp0\node.exe" "%~dp0\bootstrap" %*
3 | ) ELSE (
4 | node "%~dp0\bootstrap" %*
5 | )
6 |
7 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-package-file/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "theme": "ui",
3 | "styleSheets": ["first.css", "second.less", "last.css"]
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus-manifest/menus/menu-3.cson:
--------------------------------------------------------------------------------
1 | 'context-menu':
2 | '.test-1': [
3 | {label: 'Menu item 3', command: 'command-3'}
4 | ]
5 |
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/config:
--------------------------------------------------------------------------------
1 | [core]
2 | repositoryformatversion = 0
3 | filemode = true
4 | bare = false
5 | logallrefupdates = true
6 | ignorecase = true
7 |
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/config:
--------------------------------------------------------------------------------
1 | [core]
2 | repositoryformatversion = 0
3 | filemode = true
4 | bare = false
5 | logallrefupdates = true
6 | ignorecase = true
7 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-incompatible-native-module/node_modules/native-module/main.js:
--------------------------------------------------------------------------------
1 | throw new Error("this simulates a native module's failure to load")
2 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-incompatible-native-module/node_modules/native-module/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "native-module",
3 | "main": "./main.js"
4 | }
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-package-file/styles/last.css:
--------------------------------------------------------------------------------
1 | atom-text-editor {
2 | /* padding-top: 103px;
3 | padding-right: 103px;*/
4 | padding-bottom: 103px;
5 | }
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-without-package-file/styles/a.css:
--------------------------------------------------------------------------------
1 | atom-text-editor {
2 | padding-top: 10px;
3 | padding-right: 10px;
4 | padding-bottom: 10px;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-that-throws-on-activate/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: -> throw new Error('Top that')
3 | deactivate: ->
4 | serialize: ->
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-that-throws-on-deactivate/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 | deactivate: -> throw new Error('Top that')
4 | serialize: ->
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-config-defaults/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | configDefaults:
3 | numbers: { one: 1, two: 2 }
4 |
5 | activate: -> # no-op
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-without-package-file/styles/d.csv:
--------------------------------------------------------------------------------
1 | atom-text-editor {
2 | padding-top: 100px;
3 | padding-right: 100px;
4 | padding-bottom: 100px;
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/config:
--------------------------------------------------------------------------------
1 | [core]
2 | repositoryformatversion = 0
3 | filemode = true
4 | bare = false
5 | logallrefupdates = true
6 | ignorecase = true
7 |
--------------------------------------------------------------------------------
/spec/fixtures/sample-with-tabs-and-leading-comment.coffee:
--------------------------------------------------------------------------------
1 | # This is a comment
2 | if this.studyingEconomics
3 | buy() while supply > demand
4 | sell() until supply > demand
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-empty-activation-commands/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "no events",
3 | "version": "0.1.0",
4 | "activationCommands": {"atom-workspace": []}
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-serialization/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ({@someNumber}) ->
3 | @someNumber ?= 1
4 |
5 | serialize: ->
6 | {@someNumber}
7 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-package-file/styles/first.css:
--------------------------------------------------------------------------------
1 | atom-text-editor {
2 | padding-top: 101px;
3 | padding-right: 101px;
4 | padding-bottom: 101px;
5 |
6 | color: red;
7 | }
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-deprecated-pane-item-method/index.coffee:
--------------------------------------------------------------------------------
1 | class TestItem
2 | getUri: -> "test"
3 |
4 | exports.activate = ->
5 | atom.workspace.addOpener -> new TestItem
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-incompatible-native-module/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package-with-incompatible-native-module",
3 | "version": "1.0",
4 | "main": "./main.js"
5 | }
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-serialize-error/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 |
4 | deactivate: ->
5 |
6 | serialize: ->
7 | throw new Error("I'm no good at this.")
8 |
--------------------------------------------------------------------------------
/src/subscriber-mixin.coffee:
--------------------------------------------------------------------------------
1 | {Subscriber} = require 'emissary'
2 | SubscriberMixin = componentDidUnmount: -> @unsubscribe()
3 | Subscriber.extend(SubscriberMixin)
4 | module.exports = SubscriberMixin
5 |
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/ignore.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/ignore.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
--------------------------------------------------------------------------------
/spec/fixtures/git/ignore.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/ignore.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/master.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/master.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
--------------------------------------------------------------------------------
/spec/fixtures/git/master.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/master.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-injection-selector/grammars/grammar.cson:
--------------------------------------------------------------------------------
1 | 'name': 'test'
2 | 'scopeName': 'source.test'
3 | 'injectionSelector': 'comment'
4 | 'patterns': [{'include': 'source.sql'}]
5 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-package-file/styles/second.less:
--------------------------------------------------------------------------------
1 | @number: 102px;
2 |
3 | atom-text-editor {
4 | /* padding-top: 102px;*/
5 | padding-right: @number;
6 | padding-bottom: @number;
7 | }
--------------------------------------------------------------------------------
/script/utils/clean-open-with-menu:
--------------------------------------------------------------------------------
1 | /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user
2 | killall Finder
3 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus/menus/menu-2.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | { 'label': 'Last' }
3 | ]
4 |
5 | 'context-menu':
6 | '.test-1': [
7 | {label: 'Menu item 2', command: 'command-2'}
8 | ]
9 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to the Atom Docs
2 |
3 | 
4 |
5 | TODO: Write when docs move to a dedicated repo.
6 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus/menus/menu-1.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | {'label': 'Second to Last'}
3 | ]
4 |
5 | 'context-menu':
6 | '.test-1': [
7 | {label: 'Menu item 1', command: 'command-1'}
8 | ]
9 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus-manifest/menus/menu-1.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | { 'label': 'Last' }
3 | ]
4 |
5 | 'context-menu':
6 | '.test-1': [
7 | {label: 'Menu item 1', command: 'command-1'}
8 | ]
9 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus/menus/menu-3.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | { 'label': 'Second to Last' }
3 | ]
4 |
5 | 'context-menu':
6 | '.test-1': [
7 | {label: 'Menu item 3', command: 'command-3'}
8 | ]
9 |
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/06/15f9a45968b3515e0a202530ef9f61aba26b6c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/06/15f9a45968b3515e0a202530ef9f61aba26b6c
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/16/735fb793d7b038818219c4b8c6295346e20eef:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/16/735fb793d7b038818219c4b8c6295346e20eef
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/52/f56457b6fca045ce41bb9d32e6ca79d23192af:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/52/f56457b6fca045ce41bb9d32e6ca79d23192af
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/5b/24ab4c3baadf534242b1acc220c8fa051b9b20:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/5b/24ab4c3baadf534242b1acc220c8fa051b9b20
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/66/dc9051da651c15d98d017a88658263cab28f02:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/66/dc9051da651c15d98d017a88658263cab28f02
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/8a/9c86f1cb1f14b8f436eb91f4b052c8802ca99e:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/8a/9c86f1cb1f14b8f436eb91f4b052c8802ca99e
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/ec/5e386905ff2d36e291086a1207f2585aaa8920:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/ec/5e386905ff2d36e291086a1207f2585aaa8920
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/fe/bde178cdf35e9df6279d87aa27590c6d92e354:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/fe/bde178cdf35e9df6279d87aa27590c6d92e354
--------------------------------------------------------------------------------
/spec/fixtures/git/working-dir/git.git/objects/ff/c8218bd2240a0cb92f6f02548d45784428349b:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krasimir/atom/master/spec/fixtures/git/working-dir/git.git/objects/ff/c8218bd2240a0cb92f6f02548d45784428349b
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-menus-manifest/menus/menu-2.cson:
--------------------------------------------------------------------------------
1 | 'menu': [
2 | { 'label': 'Second to Last' }
3 | ]
4 |
5 | 'context-menu':
6 | '.test-1': [
7 | {label: 'Menu item 2', command: 'command-2'}
8 | ]
9 |
--------------------------------------------------------------------------------
/static/links.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | a {
4 | cursor: pointer;
5 | color: @text-color-highlight;
6 | &:hover {
7 | color: @text-color-highlight;
8 | text-decoration: underline;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-incomplete-ui-variables/styles/ui-variables.less:
--------------------------------------------------------------------------------
1 | // This does not contain all of the ui-variables available.
2 | @app-background-color: #00f; // Changed
3 | @input-background-color: #f00; // Changed
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *~
3 | .DS_Store
4 | Thumbs.db
5 | .project
6 | .svn
7 | .nvm-version
8 | node_modules
9 | npm-debug.log
10 | debug.log
11 | /tags
12 | /atom-shell/
13 | docs/output
14 | docs/includes
15 | spec/fixtures/evil-files/
16 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-consumed-services/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 |
4 | deactivate: ->
5 |
6 | consumeFirstServiceV3: ->
7 |
8 | consumeFirstServiceV4: ->
9 |
10 | consumeSecondService: ->
11 |
--------------------------------------------------------------------------------
/spec/fixtures/sample-with-tabs-and-initial-comment.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look, this is a comment. Don't go making assumtions that I want soft tabs
3 | * because this block comment has leading spaces, Geez.
4 | */
5 |
6 | if (beNice) {
7 | console.log('Thank you for being nice.');
8 | }
9 |
--------------------------------------------------------------------------------
/static/icons.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | .icon:before {
4 | margin-right: @component-icon-padding;
5 | }
6 |
7 | a.icon,
8 | button.icon {
9 | text-decoration: none;
10 | color: @text-color;
11 | &:hover{
12 | color: @text-color-highlight;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/apm/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "atom-bundled-apm",
3 | "description": "Atom's bundled apm",
4 | "repository": {
5 | "type": "git",
6 | "url": "https://github.com/atom/atom.git"
7 | },
8 | "dependencies": {
9 | "atom-package-manager": "0.135.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/static/markdown.less:
--------------------------------------------------------------------------------
1 | .source.gfm {
2 | .markup.heading {
3 | font-weight: bold;
4 | }
5 |
6 | .bold {
7 | font-weight: bold;
8 | }
9 |
10 | .italic {
11 | font-style: italic;
12 | }
13 |
14 | .comment.quote {
15 | font-style: italic;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-ui-variables/styles/editor.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | atom-text-editor {
4 | padding-top: @component-padding;
5 | padding-right: @component-padding;
6 | padding-bottom: @component-padding;
7 |
8 | color: @input-background-color;
9 | }
10 |
--------------------------------------------------------------------------------
/static/linux.less:
--------------------------------------------------------------------------------
1 | ::-webkit-scrollbar-corner {
2 | background-color: transparent;
3 | }
4 |
5 | ::-webkit-scrollbar {
6 | width: 8px;
7 | height: 8px;
8 | }
9 |
10 | ::-webkit-scrollbar-thumb {
11 | -webkit-border-radius: 2px;
12 | background: rgba(150, 150, 150, .33);
13 | }
14 |
--------------------------------------------------------------------------------
/static/popover-list.less:
--------------------------------------------------------------------------------
1 | .select-list.popover-list {
2 | width: 200px;
3 | min-width: 200px;
4 | margin-left: 0;
5 | position: relative;
6 | }
7 |
8 | .select-list.popover-list ol.list-group {
9 | position: relative;
10 | overflow-y: scroll;
11 | max-height: 200px;
12 | }
13 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-grammars/grammars/alot.cson:
--------------------------------------------------------------------------------
1 | 'fileTypes': ['alot', 'foobizbang']
2 | 'name': 'Alot'
3 | 'scopeName': 'source.alot'
4 |
5 | 'patterns': [
6 | {
7 | 'captures':
8 | '0':
9 | 'name': 'keyword.alot'
10 | 'match': 'alot'
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-grammars/grammars/alittle.cson:
--------------------------------------------------------------------------------
1 | 'fileTypes': ['alittle']
2 | 'name': 'Alittle'
3 | 'scopeName': 'source.alittle'
4 |
5 | 'patterns': [
6 | {
7 | 'captures':
8 | '0':
9 | 'name': 'keyword.alittle'
10 | 'match': 'alittle'
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/resources/linux/atom.desktop.in:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Atom
3 | Comment=<%= description %>
4 | GenericName=Text Editor
5 | Exec=<%= executable %> %U
6 | Icon=<%= iconName %>
7 | Type=Application
8 | StartupNotify=true
9 | Categories=GNOME;GTK;Utility;TextEditor;Development;
10 | MimeType=text/plain;
11 |
--------------------------------------------------------------------------------
/keymaps/emacs.cson:
--------------------------------------------------------------------------------
1 | 'atom-text-editor':
2 | 'alt-f': 'editor:move-to-end-of-word'
3 | 'alt-F': 'editor:select-to-end-of-word'
4 | 'alt-b': 'editor:move-to-beginning-of-word'
5 | 'alt-B': 'editor:select-to-beginning-of-word'
6 | 'alt-h': 'editor:delete-to-beginning-of-word'
7 | 'alt-d': 'editor:delete-to-end-of-word'
8 |
--------------------------------------------------------------------------------
/script/cibuild-atom-rpm:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | docker build -t atom-rpm .
6 | docker run \
7 | --rm \
8 | --env JANKY_SHA1="$JANKY_SHA1" \
9 | --env JANKY_BRANCH="$JANKY_BRANCH" \
10 | --env ATOM_ACCESS_TOKEN="$BUILD_ATOM_RPM_ACCESS_TOKEN" \
11 | atom-rpm /atom/script/rpmbuild
12 | docker rmi atom-rpm
13 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-provided-services/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activate: ->
3 |
4 | deactivate: ->
5 |
6 | provideFirstServiceV3: ->
7 | 'first-service-v3'
8 |
9 | provideFirstServiceV4: ->
10 | 'first-service-v4'
11 |
12 | provideSecondService: ->
13 | 'second-service'
14 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-config-schema/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | config:
3 | numbers:
4 | type: 'object'
5 | properties:
6 | one:
7 | type: 'integer'
8 | default: 1
9 | two:
10 | type: 'integer'
11 | default: 2
12 |
13 | activate: -> # no-op
14 |
--------------------------------------------------------------------------------
/script/copy-folder.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set USAGE=Usage: %0 source destination
4 |
5 | if [%1] == [] (
6 | echo %USAGE%
7 | exit 1
8 | )
9 | if [%2] == [] (
10 | echo %USAGE%
11 | exit 2
12 | )
13 |
14 | :: rm -rf %2
15 | if exist %2 rmdir %2 /s /q
16 |
17 | :: cp -rf %1 %2
18 | (robocopy %1 %2 /e) ^& IF %ERRORLEVEL% LEQ 1 exit 0
19 |
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/coffeelint.json:
--------------------------------------------------------------------------------
1 | {
2 | "max_line_length": {
3 | "level": "ignore"
4 | },
5 | "no_empty_param_list": {
6 | "level": "error"
7 | },
8 | "arrow_spacing": {
9 | "level": "error"
10 | },
11 | "no_interpolation_in_single_quotes": {
12 | "level": "error"
13 | },
14 | "no_debugger": {
15 | "level": "error"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/resources/linux/debian/lintian-overrides:
--------------------------------------------------------------------------------
1 | atom: arch-dependent-file-in-usr-share
2 | atom: changelog-file-missing-in-native-package
3 | atom: copyright-file-contains-full-apache-2-license
4 | atom: copyright-should-refer-to-common-license-file-for-apache-2
5 | atom: embedded-library
6 | atom: package-installs-python-bytecode
7 | atom: unstripped-binary-or-object
8 |
--------------------------------------------------------------------------------
/script/utils/fix-author:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | usage() {
4 | echo "usage: $0 sha name email"
5 | exit 1
6 | }
7 |
8 | if [ ! $3 ]; then
9 | usage
10 | fi
11 |
12 | git filter-branch -f --env-filter "
13 | export GIT_AUTHOR_NAME='$2'
14 | export GIT_AUTHOR_EMAIL='$3'
15 | export GIT_COMMITTER_NAME='$2'
16 | export GIT_COMMITTER_EMAIL='$3'
17 | " -- $1..HEAD
--------------------------------------------------------------------------------
/script/cibuild-atom-linux:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | export ATOM_ACCESS_TOKEN=$BUILD_ATOM_LINUX_ACCESS_TOKEN
6 |
7 | if [ -d /usr/local/share/nodenv ]; then
8 | export NODENV_ROOT=/usr/local/share/nodenv
9 | export PATH=/usr/local/share/nodenv/bin:/usr/local/share/nodenv/shims:$PATH
10 | export NODENV_VERSION="v0.10.21"
11 | fi
12 |
13 | script/cibuild
14 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-incomplete-ui-variables/styles/editor.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | atom-text-editor {
4 | padding-top: @component-padding;
5 | padding-right: @component-padding;
6 | padding-bottom: @component-padding;
7 |
8 | color: @input-background-color;
9 | background-color: @background-color-info; // From the fallback variables, not overridden
10 | }
11 |
--------------------------------------------------------------------------------
/resources/win/atom.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var spawn = require('child_process').spawn;
3 |
4 | var atomCommandPath = path.resolve(__dirname, '..', '..', 'atom.exe');
5 | var arguments = process.argv.slice(2);
6 | arguments.unshift('--executed-from', process.cwd());
7 | var options = {detached: true, stdio: 'ignore'};
8 | spawn(atomCommandPath, arguments, options);
9 | process.exit(0);
10 |
--------------------------------------------------------------------------------
/src/item-registry.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | class ItemRegistry
3 | constructor: ->
4 | @items = new WeakSet
5 |
6 | addItem: (item) ->
7 | if @hasItem(item)
8 | throw new Error("The workspace can only contain one instance of item #{item}")
9 | @items.add(item)
10 |
11 | removeItem: (item) ->
12 | @items.delete(item)
13 |
14 | hasItem: (item) ->
15 | @items.has(item)
16 |
--------------------------------------------------------------------------------
/script/test:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var safeExec = require('./utils/child-process-wrapper.js').safeExec;
3 | var path = require('path');
4 |
5 | process.chdir(path.dirname(__dirname));
6 |
7 | safeExec('node script/bootstrap', function() {
8 | var gruntPath = path.join('node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
9 | safeExec(gruntPath + ' ci --stack --no-color', process.exit);
10 | });
11 |
--------------------------------------------------------------------------------
/benchmark/benchmark-bootstrap.coffee:
--------------------------------------------------------------------------------
1 | require '../src/window'
2 | Atom = require '../src/atom'
3 | window.atom = Atom.loadOrCreate('spec')
4 | atom.show() unless atom.getLoadSettings().exitWhenDone
5 | window.atom = atom
6 |
7 | {runSpecSuite} = require '../spec/jasmine-helper'
8 |
9 | atom.openDevTools()
10 |
11 | document.title = "Benchmark Suite"
12 | runSpecSuite('../benchmark/benchmark-suite', atom.getLoadSettings().logFile)
13 |
--------------------------------------------------------------------------------
/dot-atom/init.coffee:
--------------------------------------------------------------------------------
1 | # Your init script
2 | #
3 | # Atom will evaluate this file each time a new window is opened. It is run
4 | # after packages are loaded/activated and after the previous editor state
5 | # has been restored.
6 | #
7 | # An example hack to log to the console when each text editor is saved.
8 | #
9 | # atom.workspace.observeTextEditors (editor) ->
10 | # editor.onDidSave ->
11 | # console.log "Saved! #{editor.getPath()}"
12 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-consumed-services/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package-with-consumed-services",
3 |
4 | "consumedServices": {
5 | "service-1": {
6 | "versions": {
7 | ">=0.2 <=0.3.6": "consumeFirstServiceV3",
8 | "^0.4.1": "consumeFirstServiceV4"
9 | }
10 | },
11 | "service-2": {
12 | "versions": {
13 | "0.2.1 || 0.2.2": "consumeSecondService"
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/static/bootstrap-overrides.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | .nav {
4 | > li > a {
5 | border-radius: @component-border-radius;
6 | }
7 | > li > a:hover {
8 | background-color: @background-color-highlight;
9 | }
10 |
11 | &.nav-pills > li.active > a {
12 | background-color: @background-color-selected;
13 | }
14 | }
15 |
16 | h1,
17 | h2,
18 | h3,
19 | h4,
20 | h5,
21 | h6 {
22 | font-family: inherit; // inherit from themes
23 | }
24 |
--------------------------------------------------------------------------------
/spec/fixtures/sample.js:
--------------------------------------------------------------------------------
1 | var quicksort = function () {
2 | var sort = function(items) {
3 | if (items.length <= 1) return items;
4 | var pivot = items.shift(), current, left = [], right = [];
5 | while(items.length > 0) {
6 | current = items.shift();
7 | current < pivot ? left.push(current) : right.push(current);
8 | }
9 | return sort(left).concat(pivot).concat(sort(right));
10 | };
11 |
12 | return sort(Array.apply(this, arguments));
13 | };
--------------------------------------------------------------------------------
/.pairs:
--------------------------------------------------------------------------------
1 | pairs:
2 | ns: Nathan Sobo; nathan
3 | cj: Corey Johnson; cj
4 | dg: David Graham; dgraham
5 | ks: Kevin Sawicki; kevin
6 | jc: Jerry Cheung; jerry
7 | bl: Brian Lopez; brian
8 | jp: Justin Palmer; justin
9 | gt: Garen Torikian; garen
10 | mc: Matt Colyer; mcolyer
11 | bo: Ben Ogle; benogle
12 | jr: Jason Rudolph; jasonrudolph
13 | jl: Jessica Lord; jlord
14 | dh: Daniel Hengeveld; danielh
15 | email:
16 | domain: github.com
17 | #global: true
18 |
--------------------------------------------------------------------------------
/resources/win/atom.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | while getopts ":fhtvw-:" opt; do
4 | case "$opt" in
5 | -)
6 | case "${OPTARG}" in
7 | foreground|help|test|version|wait)
8 | EXPECT_OUTPUT=1
9 | ;;
10 | esac
11 | ;;
12 | f|h|t|v|w)
13 | EXPECT_OUTPUT=1
14 | ;;
15 | esac
16 | done
17 |
18 | if [ $EXPECT_OUTPUT ]; then
19 | "$0/../../../atom.exe" "$@"
20 | else
21 | "$0/../../app/apm/bin/node.exe" "$0/../atom.js" "$@"
22 | fi
23 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # VERSION: 0.1
2 | # DESCRIPTION: Image to build Atom and create a .rpm file
3 |
4 | # Base docker image
5 | FROM fedora:20
6 |
7 | # Install dependencies
8 | RUN yum install -y \
9 | make \
10 | gcc \
11 | gcc-c++ \
12 | glibc-devel \
13 | git-core \
14 | libgnome-keyring-devel \
15 | rpmdevtools
16 |
17 | # Install node
18 | RUN curl -sL https://rpm.nodesource.com/setup | bash -
19 | RUN yum install -y nodejs
20 |
21 | ADD . /atom
22 | WORKDIR /atom
23 |
--------------------------------------------------------------------------------
/src/window-bootstrap.coffee:
--------------------------------------------------------------------------------
1 | # Like sands through the hourglass, so are the days of our lives.
2 | require './window'
3 |
4 | Atom = require './atom'
5 | window.atom = Atom.loadOrCreate('editor')
6 | atom.initialize()
7 | atom.startEditorWindow()
8 |
9 | # Workaround for focus getting cleared upon window creation
10 | windowFocused = ->
11 | window.removeEventListener('focus', windowFocused)
12 | setTimeout (-> document.querySelector('atom-workspace').focus()), 0
13 | window.addEventListener('focus', windowFocused)
14 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-provided-services/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package-with-provided-services",
3 |
4 | "providedServices": {
5 | "service-1": {
6 | "description": "The first service",
7 | "versions": {
8 | "0.3.1": "provideFirstServiceV3",
9 | "0.4.1": "provideFirstServiceV4"
10 | }
11 | },
12 | "service-2": {
13 | "description": "The second service",
14 | "versions": {
15 | "0.2.1": "provideSecondService"
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/spec/fixtures/coffee.coffee:
--------------------------------------------------------------------------------
1 | class quicksort
2 | sort: (items) ->
3 | return items if items.length <= 1
4 |
5 | pivot = items.shift()
6 | left = []
7 | right = []
8 |
9 | # Comment in the middle
10 |
11 | while items.length > 0
12 | current = items.shift()
13 | if current < pivot
14 | left.push(current)
15 | else
16 | right.push(current);
17 |
18 | sort(left).concat(pivot).concat(sort(right))
19 |
20 | noop: ->
21 | # just a noop
22 |
23 | exports.modules = quicksort
24 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/package-with-activation-commands/index.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | activateCallCount: 0
3 | activationCommandCallCount: 0
4 | legacyActivationCommandCallCount: 0
5 |
6 | activate: ->
7 | @activateCallCount++
8 |
9 | atom.commands.add 'atom-workspace', 'activation-command', =>
10 | @activationCommandCallCount++
11 |
12 | editorView = atom.views.getView(atom.workspace.getActiveTextEditor())?.__spacePenView
13 | editorView?.command 'activation-command', =>
14 | @legacyActivationCommandCallCount++
15 |
--------------------------------------------------------------------------------
/script/mkrpm:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | SPEC_FILE="$1"
6 | DESKTOP_FILE="$2"
7 | BUILD_DIRECTORY="$3"
8 |
9 | RPM_BUILD_ROOT=~/rpmbuild
10 | ARCH=`uname -m`
11 |
12 | rpmdev-setuptree
13 |
14 | cp -r $BUILD_DIRECTORY/Atom $RPM_BUILD_ROOT/BUILD
15 | cp -r $BUILD_DIRECTORY/icons $RPM_BUILD_ROOT/BUILD
16 | cp $SPEC_FILE $RPM_BUILD_ROOT/SPECS
17 | cp ./atom.sh $RPM_BUILD_ROOT/BUILD
18 | cp $DESKTOP_FILE $RPM_BUILD_ROOT/BUILD
19 |
20 | rpmbuild -ba $SPEC_FILE
21 | cp $RPM_BUILD_ROOT/RPMS/$ARCH/atom-*.rpm $BUILD_DIRECTORY/rpm
22 |
23 | rm -rf $RPM_BUILD_ROOT
24 |
--------------------------------------------------------------------------------
/src/replace-handler.coffee:
--------------------------------------------------------------------------------
1 | {PathReplacer} = require 'scandal'
2 |
3 | module.exports = (filePaths, regexSource, regexFlags, replacementText) ->
4 | callback = @async()
5 |
6 | replacer = new PathReplacer()
7 | regex = new RegExp(regexSource, regexFlags)
8 |
9 | replacer.on 'file-error', ({code, path, message}) ->
10 | emit('replace:file-error', {code, path, message})
11 |
12 | replacer.on 'path-replaced', (result) ->
13 | emit('replace:path-replaced', result)
14 |
15 | replacer.replacePaths(regex, replacementText, filePaths, -> callback())
16 |
--------------------------------------------------------------------------------
/resources/linux/debian/control.in:
--------------------------------------------------------------------------------
1 | Package: <%= name %>
2 | Version: <%= version %>
3 | Depends: git, gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11, libnotify4, libxtst6, libnss3, python, gvfs-bin, xdg-utils
4 | Suggests: libgnome-keyring0, gir1.2-gnomekeyring-1.0
5 | Section: <%= section %>
6 | Priority: optional
7 | Architecture: <%= arch %>
8 | Installed-Size: <%= installedSize %>
9 | Maintainer: <%= maintainer %>
10 | Description: <%= description %>
11 | Atom is a free and open source text editor that is modern, approachable, and hackable to the core.
12 |
--------------------------------------------------------------------------------
/script/build:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var cp = require('./utils/child-process-wrapper.js');
3 | var path = require('path');
4 |
5 | process.chdir(path.dirname(__dirname));
6 |
7 | cp.safeExec('node script/bootstrap', function() {
8 | // build/node_modules/.bin/grunt "$@"
9 | var gruntPath = path.join('build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
10 | var args = ['--gruntfile', path.resolve('build', 'Gruntfile.coffee')];
11 | args = args.concat(process.argv.slice(2));
12 | cp.safeSpawn(gruntPath, args, process.exit);
13 | });
14 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Specs depend on character counts, if we don't specify the line endings the
2 | # fixtures will vary depending on platform
3 | spec/fixtures/**/*.js text eol=lf
4 | spec/fixtures/**/*.coffee text eol=lf
5 | spec/fixtures/**/*.less text eol=lf
6 | spec/fixtures/**/*.css text eol=lf
7 | spec/fixtures/**/*.txt text eol=lf
8 | spec/fixtures/dir/**/* text eol=lf
9 |
10 | # Git 1.7 does not support **/* patterns
11 | spec/fixtures/css.css text eol=lf
12 | spec/fixtures/sample.js text eol=lf
13 | spec/fixtures/sample.less text eol=lf
14 | spec/fixtures/sample.txt text eol=lf
15 |
--------------------------------------------------------------------------------
/src/custom-event-mixin.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | CustomEventMixin =
3 | componentWillMount: ->
4 | @customEventListeners = {}
5 |
6 | componentWillUnmount: ->
7 | for name, listeners in @customEventListeners
8 | for listener in listeners
9 | @getDOMNode().removeEventListener(name, listener)
10 |
11 | addCustomEventListeners: (customEventListeners) ->
12 | for name, listener of customEventListeners
13 | @customEventListeners[name] ?= []
14 | @customEventListeners[name].push(listener)
15 | @getDOMNode().addEventListener(name, listener)
16 |
--------------------------------------------------------------------------------
/spec/atom-protocol-handler-spec.coffee:
--------------------------------------------------------------------------------
1 | {$} = require '../src/space-pen-extensions'
2 |
3 | describe '"atom" protocol URL', ->
4 | it 'sends the file relative in the package as response', ->
5 | called = false
6 | callback = -> called = true
7 | $.ajax
8 | url: 'atom://async/package.json'
9 | success: callback
10 | # In old versions of jQuery, ajax calls to custom protocol would always
11 | # be treated as error eventhough the browser thinks it's a success
12 | # request.
13 | error: callback
14 |
15 | waitsFor 'request to be done', -> called is true
16 |
--------------------------------------------------------------------------------
/dot-atom/styles.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Your Stylesheet
3 | *
4 | * This stylesheet is loaded when Atom starts up and is reloaded automatically
5 | * when it is changed.
6 | *
7 | * If you are unfamiliar with LESS, you can read more about it here:
8 | * http://www.lesscss.org
9 | */
10 |
11 | .tree-view {
12 |
13 | }
14 |
15 | // style the background and foreground colors on the atom-text-editor-element
16 | // itself
17 | atom-text-editor {
18 |
19 | }
20 |
21 | // To style other content in the text editor's shadow DOM, use the ::shadow
22 | // expression
23 | atom-text-editor::shadow .cursor {
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/script/create-shortcut.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set USAGE=Usage: %0 source name-on-desktop
4 |
5 | if [%1] == [] (
6 | echo %USAGE%
7 | exit 1
8 | )
9 | if [%2] == [] (
10 | echo %USAGE%
11 | exit 2
12 | )
13 |
14 | set SCRIPT="%TEMP%\%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%.vbs"
15 |
16 | echo Set oWS = WScript.CreateObject("WScript.Shell") >> %SCRIPT%
17 | echo sLinkFile = "%USERPROFILE%\Desktop\%2.lnk" >> %SCRIPT%
18 | echo Set oLink = oWS.CreateShortcut(sLinkFile) >> %SCRIPT%
19 | echo oLink.TargetPath = %1 >> %SCRIPT%
20 | echo oLink.Save >> %SCRIPT%
21 |
22 | cscript /nologo %SCRIPT%
23 | del %SCRIPT%
24 |
--------------------------------------------------------------------------------
/docs/build-instructions/freebsd.md:
--------------------------------------------------------------------------------
1 | # FreeBSD
2 |
3 | FreeBSD -RELEASE 64-bit is the recommended platform.
4 |
5 | ## Requirements
6 |
7 | * FreeBSD
8 | * `pkg install node`
9 | * `pkg install npm`
10 | * `pkg install libgnome-keyring`
11 | * `npm config set python /usr/local/bin/python2 -g` to ensure that gyp uses Python 2
12 |
13 | ## Instructions
14 |
15 | ```sh
16 | git clone https://github.com/atom/atom
17 | cd atom
18 | script/build # Creates application at $TMPDIR/atom-build/Atom
19 | sudo script/grunt install # Installs command to /usr/local/bin/atom
20 | ```
21 |
22 | ## Troubleshooting
23 |
--------------------------------------------------------------------------------
/script/set-version:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | BUILT_PRODUCTS_DIR=$1
6 | VERSION=$2
7 | PLIST_PATH="$BUILT_PRODUCTS_DIR/Atom.app/Contents/Info.plist"
8 | HELPER_PLIST_PATH="$BUILT_PRODUCTS_DIR/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/Info.plist"
9 |
10 | # Update version
11 | /usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $VERSION" "$PLIST_PATH"
12 | /usr/libexec/PlistBuddy -c "Set CFBundleVersion $VERSION" "$PLIST_PATH"
13 | /usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $VERSION" "$HELPER_PLIST_PATH"
14 | /usr/libexec/PlistBuddy -c "Set CFBundleVersion $VERSION" "$HELPER_PLIST_PATH"
15 |
--------------------------------------------------------------------------------
/dot-atom/snippets.cson:
--------------------------------------------------------------------------------
1 | # Your snippets
2 | #
3 | # Atom snippets allow you to enter a simple prefix in the editor and hit tab to
4 | # expand the prefix into a larger code block with templated values.
5 | #
6 | # You can create a new snippet in this file by typing "snip" and then hitting
7 | # tab.
8 | #
9 | # An example CoffeeScript snippet to expand log to console.log:
10 | #
11 | # '.source.coffee':
12 | # 'Console log':
13 | # 'prefix': 'log'
14 | # 'body': 'console.log $1'
15 | #
16 | # This file uses CoffeeScript Object Notation (CSON).
17 | # If you are unfamiliar with CSON, you can read more about it here:
18 | # https://github.com/bevry/cson#what-is-cson
19 |
--------------------------------------------------------------------------------
/spec/fixtures/sample-with-comments.js:
--------------------------------------------------------------------------------
1 | var quicksort = function () {
2 | /*
3 | this is a multiline comment
4 | it is, I promise
5 | */
6 | var sort = function(items) {
7 | // This is a collection of
8 | // single line comments.
9 | // Wowza
10 | if (items.length <= 1) return items;
11 | var pivot = items.shift(), current, left = [], right = [];
12 | while(items.length > 0) {
13 | current = items.shift();
14 | current < pivot ? left.push(current) : right.push(current);
15 | }
16 | return sort(left).concat(pivot).concat(sort(right));
17 | };
18 | // this is a single-line comment
19 | return sort(Array.apply(this, arguments));
20 | };
--------------------------------------------------------------------------------
/src/cursor-component.coffee:
--------------------------------------------------------------------------------
1 | React = require 'react-atom-fork'
2 | {div} = require 'reactionary-atom-fork'
3 | {isEqualForProperties} = require 'underscore-plus'
4 |
5 | module.exports =
6 | CursorComponent = React.createClass
7 | displayName: 'CursorComponent'
8 |
9 | render: ->
10 | {pixelRect, defaultCharWidth} = @props
11 | {top, left, height, width} = pixelRect
12 | width = defaultCharWidth if width is 0
13 | WebkitTransform = "translate(#{left}px, #{top}px)"
14 |
15 | div className: 'cursor', style: {height, width, WebkitTransform}
16 |
17 | shouldComponentUpdate: (newProps) ->
18 | not isEqualForProperties(newProps, @props, 'pixelRect', 'defaultCharWidth')
19 |
--------------------------------------------------------------------------------
/docs/build-instructions/os-x.md:
--------------------------------------------------------------------------------
1 | # OS X
2 |
3 | ## Requirements
4 |
5 | * OS X 10.8 or later
6 | * [node.js](http://nodejs.org/download/) v0.10.x
7 | * Command Line Tools for [Xcode](https://developer.apple.com/xcode/downloads/) (run `xcode-select --install` to install)
8 |
9 | ## Instructions
10 |
11 | ```sh
12 | git clone https://github.com/atom/atom.git
13 | cd atom
14 | script/build # Creates application at /Applications/Atom.app
15 | ```
16 |
17 | ## Troubleshooting
18 |
19 | ### OSX build error reports in atom/atom
20 | * Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Aos-x&type=Issues) to get a list of reports about build errors on OSX.
21 |
--------------------------------------------------------------------------------
/spec/clipboard-spec.coffee:
--------------------------------------------------------------------------------
1 | describe "Clipboard", ->
2 | describe "write(text, metadata) and read()", ->
3 | it "writes and reads text to/from the native clipboard", ->
4 | expect(atom.clipboard.read()).toBe 'initial clipboard content'
5 | atom.clipboard.write('next')
6 | expect(atom.clipboard.read()).toBe 'next'
7 |
8 | it "returns metadata if the item on the native clipboard matches the last written item", ->
9 | atom.clipboard.write('next', {meta: 'data'})
10 | expect(atom.clipboard.read()).toBe 'next'
11 | expect(atom.clipboard.readWithMetadata().text).toBe 'next'
12 | expect(atom.clipboard.readWithMetadata().metadata).toEqual {meta: 'data'}
13 |
--------------------------------------------------------------------------------
/script/grunt:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var cp = require('./utils/child-process-wrapper.js');
3 | var fs = require('fs');
4 | var path = require('path');
5 |
6 | // node build/node_modules/.bin/grunt "$@"
7 | var gruntPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
8 |
9 | if (!fs.existsSync(gruntPath)) {
10 | console.error('Grunt command does not exist at: ' + gruntPath);
11 | console.error('Run script/bootstrap to install Grunt');
12 | process.exit(1);
13 | }
14 |
15 | var args = ['--gruntfile', path.resolve('build', 'Gruntfile.coffee')];
16 | args = args.concat(process.argv.slice(2));
17 | cp.safeSpawn(gruntPath, args, process.exit);
18 |
--------------------------------------------------------------------------------
/static/messages.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | .info-messages,
4 | .error-messages {
5 | margin: 0;
6 | padding: 0;
7 | list-style: none;
8 | }
9 |
10 | .error-messages {
11 | color: @text-color-error;
12 | }
13 |
14 | ul.background-message {
15 | font-size: @font-size * 3;
16 |
17 | margin: 0;
18 | padding: 0;
19 |
20 | li {
21 | margin: 0;
22 | padding: 0;
23 | list-style: none;
24 | }
25 |
26 | &.centered {
27 | display: -webkit-flex;
28 | position: absolute;
29 | top: 0;
30 | left: 0;
31 | right: 0;
32 | bottom: 0;
33 |
34 | -webkit-align-items: center;
35 | text-align: center;
36 |
37 | li {
38 | width: 100%;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/static/workspace-view.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 | @import "octicon-mixins";
3 |
4 | @font-face { .octicon-font(); }
5 |
6 | html,
7 | body {
8 | width: 100%;
9 | height: 100%;
10 | overflow: hidden;
11 | font-family: @font-family;
12 | font-size: @font-size;
13 | }
14 |
15 | atom-workspace {
16 | display: block;
17 | height: 100%;
18 | overflow: hidden;
19 | position: relative;
20 | background-color: @app-background-color;
21 | font-family: @font-family;
22 |
23 | atom-workspace-axis.horizontal {
24 | display: -webkit-flex;
25 | height: 100%;
26 | }
27 |
28 | atom-workspace-axis.vertical {
29 | display: -webkit-flex;
30 | -webkit-flex: 1;
31 | -webkit-flex-flow: column;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/resources/win/atom.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | SET EXPECT_OUTPUT=
4 |
5 | FOR %%a IN (%*) DO (
6 | IF /I "%%a"=="-f" SET EXPECT_OUTPUT=YES
7 | IF /I "%%a"=="--foreground" SET EXPECT_OUTPUT=YES
8 | IF /I "%%a"=="-h" SET EXPECT_OUTPUT=YES
9 | IF /I "%%a"=="--help" SET EXPECT_OUTPUT=YES
10 | IF /I "%%a"=="-t" SET EXPECT_OUTPUT=YES
11 | IF /I "%%a"=="--test" SET EXPECT_OUTPUT=YES
12 | IF /I "%%a"=="-v" SET EXPECT_OUTPUT=YES
13 | IF /I "%%a"=="--version" SET EXPECT_OUTPUT=YES
14 | IF /I "%%a"=="-w" SET EXPECT_OUTPUT=YES
15 | IF /I "%%a"=="--wait" SET EXPECT_OUTPUT=YES
16 | )
17 |
18 | IF "%EXPECT_OUTPUT%"=="YES" (
19 | "%~dp0\..\..\atom.exe" %*
20 | ) ELSE (
21 | "%~dp0\..\app\apm\bin\node.exe" "%~dp0\atom.js" %*
22 | )
23 |
--------------------------------------------------------------------------------
/spec/panel-spec.coffee:
--------------------------------------------------------------------------------
1 | Panel = require '../src/panel'
2 |
3 | describe "Panel", ->
4 | [panel] = []
5 |
6 | class TestPanelItem
7 | constructior: ->
8 |
9 | beforeEach ->
10 | panel = new Panel(item: new TestPanelItem())
11 |
12 | describe "changing panel visibility", ->
13 | it 'emits an event when visibility changes', ->
14 | panel.onDidChangeVisible spy = jasmine.createSpy()
15 |
16 | panel.hide()
17 | expect(panel.isVisible()).toBe false
18 | expect(spy).toHaveBeenCalledWith(false)
19 | spy.reset()
20 |
21 | panel.show()
22 | expect(panel.isVisible()).toBe true
23 | expect(spy).toHaveBeenCalledWith(true)
24 |
25 | panel.destroy()
26 | expect(panel.isVisible()).toBe false
27 | expect(spy).toHaveBeenCalledWith(false)
28 |
--------------------------------------------------------------------------------
/src/scrollbar-corner-component.coffee:
--------------------------------------------------------------------------------
1 | React = require 'react-atom-fork'
2 | {div} = require 'reactionary-atom-fork'
3 | {isEqualForProperties} = require 'underscore-plus'
4 |
5 | module.exports =
6 | ScrollbarCornerComponent = React.createClass
7 | displayName: 'ScrollbarCornerComponent'
8 |
9 | render: ->
10 | {visible, measuringScrollbars, width, height} = @props
11 |
12 | if measuringScrollbars
13 | height = 25
14 | width = 25
15 |
16 | display = 'none' unless visible
17 |
18 | div className: 'scrollbar-corner', style: {display, width, height},
19 | div style:
20 | height: height + 1
21 | width: width + 1
22 |
23 | shouldComponentUpdate: (newProps) ->
24 | not isEqualForProperties(newProps, @props, 'measuringScrollbars', 'visible', 'width', 'height')
25 |
--------------------------------------------------------------------------------
/src/scoped-properties.coffee:
--------------------------------------------------------------------------------
1 | CSON = require 'season'
2 | {CompositeDisposable} = require 'event-kit'
3 |
4 | module.exports =
5 | class ScopedProperties
6 | @load: (scopedPropertiesPath, callback) ->
7 | CSON.readFile scopedPropertiesPath, (error, scopedProperties={}) ->
8 | if error?
9 | callback(error)
10 | else
11 | callback(null, new ScopedProperties(scopedPropertiesPath, scopedProperties))
12 |
13 | constructor: (@path, @scopedProperties) ->
14 |
15 | activate: ->
16 | for selector, properties of @scopedProperties
17 | atom.config.set(null, properties, scopeSelector: selector, source: @path)
18 | return
19 |
20 | deactivate: ->
21 | for selector of @scopedProperties
22 | atom.config.unset(null, scopeSelector: selector, source: @path)
23 | return
24 |
--------------------------------------------------------------------------------
/static/select-list.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 | @import "octicon-mixins";
3 |
4 | .select-list {
5 | .loading {
6 | .loading-message {
7 | .octicon(hourglass);
8 |
9 | &:before {
10 | font-size: 1.1em;
11 | width: 1.1em;
12 | height: 1.1em;
13 | margin-right: 5px;
14 | }
15 | }
16 |
17 | .badge {
18 | margin-left: 10px;
19 | }
20 | }
21 |
22 | ol.list-group {
23 | position: relative;
24 | overflow-y: auto;
25 | max-height: 312px;
26 | margin: @component-padding 0 0 0;
27 | padding: 0;
28 |
29 | li {
30 | display: block;
31 |
32 | .primary-line,
33 | .secondary-line {
34 | text-overflow: ellipsis;
35 | white-space: nowrap;
36 | overflow: hidden;
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/static/atom.less:
--------------------------------------------------------------------------------
1 | // Import from the syntax theme's variables with a fallback to ./variables/syntax-variables.less
2 | @import "./variables/syntax-variables";
3 | @import "syntax-variables";
4 |
5 | // Import from the ui theme's variables with a fallback to ./variables/ui-variables.less
6 | @import "./variables/ui-variables";
7 | @import "ui-variables";
8 |
9 | @import "octicon-utf-codes";
10 | @import "octicon-mixins";
11 |
12 | @import "workspace-view";
13 | @import "bootstrap-overrides";
14 | @import "buttons";
15 | @import "icons";
16 | @import "links";
17 | @import "panes";
18 | @import "panels";
19 | @import "sections";
20 | @import "lists";
21 | @import "popover-list";
22 | @import "messages";
23 | @import "markdown";
24 | @import "text-editor-light";
25 | @import "select-list";
26 | @import "syntax";
27 | @import "utilities";
28 | @import "octicons";
29 |
--------------------------------------------------------------------------------
/src/theme-package.coffee:
--------------------------------------------------------------------------------
1 | Q = require 'q'
2 | Package = require './package'
3 |
4 | module.exports =
5 | class ThemePackage extends Package
6 | getType: -> 'theme'
7 |
8 | getStyleSheetPriority: -> 1
9 |
10 | enable: ->
11 | atom.config.unshiftAtKeyPath('core.themes', @name)
12 |
13 | disable: ->
14 | atom.config.removeAtKeyPath('core.themes', @name)
15 |
16 | load: ->
17 | @measure 'loadTime', =>
18 | try
19 | @metadata ?= Package.loadMetadata(@path)
20 | catch error
21 | console.warn "Failed to load theme named '#{@name}'", error.stack ? error
22 | this
23 |
24 | activate: ->
25 | return @activationDeferred.promise if @activationDeferred?
26 |
27 | @activationDeferred = Q.defer()
28 | @measure 'activateTime', =>
29 | @loadStylesheets()
30 | @activateNow()
31 |
32 | @activationDeferred.promise
33 |
--------------------------------------------------------------------------------
/static/sections.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | section, .section {
4 | position: relative;
5 | margin-top: 0;
6 | &:last-child { margin-bottom: 0; }
7 |
8 | &.bordered {
9 | margin: 0;
10 | padding: @component-padding*2 0;
11 | border-top: 1px solid @background-color-highlight;
12 | border-bottom: 1px solid @tool-panel-border-color;
13 | }
14 |
15 | .section-heading:first-child {
16 | margin-top: 0;
17 | font-weight: bold;
18 | color: @text-color-highlight;
19 | }
20 | }
21 |
22 | div > section:first-child,
23 | form > section:first-child,
24 | div > .section:first-child,
25 | form > .section:first-child {
26 | border-top: none;
27 | padding-top: 0;
28 | }
29 | div > section:last-child,
30 | form > section:last-child,
31 | div > .section:last-child,
32 | form > .section:last-child {
33 | border-bottom: none;
34 | padding-bottom: 0;
35 | }
36 |
--------------------------------------------------------------------------------
/static/syntax.less:
--------------------------------------------------------------------------------
1 | @import "syntax-variables";
2 |
3 | atom-text-editor {
4 | .lines {
5 | .markup {
6 | &.git-commit {
7 | &.changed {
8 | color: @syntax-color-modified;
9 | }
10 |
11 | &.deleted {
12 | color: @syntax-color-removed;
13 | }
14 |
15 | &.inserted {
16 | color: @syntax-color-added;
17 | }
18 | }
19 | }
20 | }
21 | }
22 |
23 | .define-selection-flash-color-if-not-defined() { @syntax-selection-flash-color: rgba(100, 255, 100, 0.7); }
24 | .define-selection-flash-color-if-not-defined();
25 |
26 | @-webkit-keyframes flash {
27 | from { background-color: @syntax-selection-flash-color; }
28 | to { background-color: null; }
29 | }
30 |
31 | atom-text-editor .flash.selection .region {
32 | -webkit-animation-name: flash;
33 | -webkit-animation-duration: .5s;
34 | -webkit-animation-iteration-count: 1;
35 | }
36 |
--------------------------------------------------------------------------------
/static/variables/octicon-mixins.less:
--------------------------------------------------------------------------------
1 | .icon-size(@size) {
2 | font-size: @size;
3 | width: @size;
4 | height: @size;
5 | }
6 |
7 | .icon(@size, @display: inline-block) {
8 | font-family: 'Octicons Regular';
9 | font-weight: normal;
10 | font-style: normal;
11 | display: @display;
12 | line-height: 1;
13 | -webkit-font-smoothing: antialiased;
14 | text-decoration: none;
15 |
16 | .icon-size(@size);
17 | }
18 |
19 | .octicon(@name, @size: 16px) {
20 | @import "octicon-utf-codes.less";
21 | &:before {
22 | .icon(@size);
23 | content: @@name
24 | }
25 | }
26 |
27 | .mega-octicon(@name, @size: 32px) {
28 | @import "octicon-utf-codes.less";
29 | &:before {
30 | .icon(@size);
31 | content: @@name
32 | }
33 | }
34 |
35 | .octicon-font() {
36 | font-family: 'Octicons Regular';
37 | src: url("octicons.woff") format("woff");
38 | font-weight: normal;
39 | font-style: normal;
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/scan-handler.coffee:
--------------------------------------------------------------------------------
1 | {PathSearcher, PathScanner, search} = require 'scandal'
2 |
3 | module.exports = (rootPath, regexSource, options) ->
4 | callback = @async()
5 |
6 | PATHS_COUNTER_SEARCHED_CHUNK = 50
7 | pathsSearched = 0
8 |
9 | searcher = new PathSearcher()
10 | scanner = new PathScanner(rootPath, options)
11 |
12 | searcher.on 'file-error', ({code, path, message}) ->
13 | emit('scan:file-error', {code, path, message})
14 |
15 | searcher.on 'results-found', (result) ->
16 | emit('scan:result-found', result)
17 |
18 | scanner.on 'path-found', ->
19 | pathsSearched++
20 | if pathsSearched % PATHS_COUNTER_SEARCHED_CHUNK == 0
21 | emit('scan:paths-searched', pathsSearched)
22 |
23 | flags = "g"
24 | flags += "i" if options.ignoreCase
25 | regex = new RegExp(regexSource, flags)
26 | search regex, scanner, searcher, ->
27 | emit('scan:paths-searched', pathsSearched)
28 | callback()
29 |
--------------------------------------------------------------------------------
/src/window.coffee:
--------------------------------------------------------------------------------
1 | # Public: Measure how long a function takes to run.
2 | #
3 | # description - A {String} description that will be logged to the console when
4 | # the function completes.
5 | # fn - A {Function} to measure the duration of.
6 | #
7 | # Returns the value returned by the given function.
8 | window.measure = (description, fn) ->
9 | start = Date.now()
10 | value = fn()
11 | result = Date.now() - start
12 | console.log description, result
13 | value
14 |
15 | # Public: Create a dev tools profile for a function.
16 | #
17 | # description - A {String} description that will be available in the Profiles
18 | # tab of the dev tools.
19 | # fn - A {Function} to profile.
20 | #
21 | # Returns the value returned by the given function.
22 | window.profile = (description, fn) ->
23 | measure description, ->
24 | console.profile(description)
25 | value = fn()
26 | console.profileEnd(description)
27 | value
28 |
--------------------------------------------------------------------------------
/src/browser/context-menu.coffee:
--------------------------------------------------------------------------------
1 | Menu = require 'menu'
2 |
3 | module.exports =
4 | class ContextMenu
5 | constructor: (template, @atomWindow) ->
6 | template = @createClickHandlers(template)
7 | menu = Menu.buildFromTemplate(template)
8 | menu.popup(@atomWindow.browserWindow)
9 |
10 | # It's necessary to build the event handlers in this process, otherwise
11 | # closures are dragged across processes and failed to be garbage collected
12 | # appropriately.
13 | createClickHandlers: (template) ->
14 | for item in template
15 | if item.command
16 | item.commandDetail ?= {}
17 | item.commandDetail.contextCommand = true
18 | item.commandDetail.atomWindow = @atomWindow
19 | do (item) =>
20 | item.click = =>
21 | global.atomApplication.sendCommandToWindow(item.command, @atomWindow, item.commandDetail)
22 | else if item.submenu
23 | @createClickHandlers(item.submenu)
24 | item
25 |
--------------------------------------------------------------------------------
/dot-atom/keymap.cson:
--------------------------------------------------------------------------------
1 | # Your keymap
2 | #
3 | # Atom keymaps work similarly to style sheets. Just as style sheets use
4 | # selectors to apply styles to elements, Atom keymaps use selectors to associate
5 | # keystrokes with events in specific contexts.
6 | #
7 | # You can create a new keybinding in this file by typing "key" and then hitting
8 | # tab.
9 | #
10 | # Here's an example taken from Atom's built-in keymap:
11 | #
12 | # 'atom-text-editor':
13 | # 'enter': 'editor:newline'
14 | #
15 | # 'atom-workspace':
16 | # 'ctrl-shift-p': 'core:move-up'
17 | # 'ctrl-p': 'core:move-down'
18 | #
19 | # You can find more information about keymaps in these guides:
20 | # * https://atom.io/docs/latest/customizing-atom#customizing-key-bindings
21 | # * https://atom.io/docs/latest/advanced/keymaps
22 | #
23 | # This file uses CoffeeScript Object Notation (CSON).
24 | # If you are unfamiliar with CSON, you can read more about it here:
25 | # https://github.com/bevry/cson#what-is-cson
26 |
--------------------------------------------------------------------------------
/docs/advanced/node-modules.md:
--------------------------------------------------------------------------------
1 | ## Developing Node Modules
2 |
3 | Atom contains a number of packages that are Node modules instead of Atom packages. If you want to
4 | make changes to the Node modules, for instance `atom-keymap`, you have to link them into the
5 | development environment differently than you would a normal Atom package.
6 |
7 | ### Linking a Node Module Into Your Atom Dev Environment
8 |
9 | Here are the steps to run a local version of a node module *not an apm* within Atom. We're using
10 | `atom-keymap` as an example:
11 |
12 | ```bash
13 | $ git clone https://github.com/atom/atom-keymap.git
14 | $ cd atom-keymap
15 | $ npm install
16 | $ npm link
17 | $ apm rebuild # This is the special step, it makes the npm work with Atom's version of Node
18 | $ cd WHERE-YOU-CLONED-ATOM
19 | $ npm link atom-keymap
20 | $ atom # Should work!
21 | ```
22 |
23 | After this, you'll have to `npm install` and `apm rebuild` when you make a change to the node
24 | module's code.
25 |
--------------------------------------------------------------------------------
/static/variables/syntax-variables.less:
--------------------------------------------------------------------------------
1 | // This file has fallback variables. It specifies all syntax variables that
2 | // themes must implement if they include a syntax-variables.less file.
3 |
4 | // General colors
5 | @syntax-text-color: #333;
6 | @syntax-cursor-color: #333;
7 | @syntax-selection-color: #69c;
8 | @syntax-selection-flash-color: #00f; // Color the selection is 'flashed' when you run find next
9 | @syntax-background-color: #fff;
10 |
11 | // Guide colors
12 | @syntax-wrap-guide-color: #ccc;
13 | @syntax-indent-guide-color: #ccc;
14 | @syntax-invisible-character-color: #ccc;
15 |
16 | // For find and replace markers
17 | @syntax-result-marker-color: #444;
18 | @syntax-result-marker-color-selected: #000;
19 |
20 | // Gutter colors
21 | @syntax-gutter-text-color: #333;
22 | @syntax-gutter-text-color-selected: #000;
23 | @syntax-gutter-background-color: #ccc;
24 | @syntax-gutter-background-color-selected: #eee;
25 |
26 | // For git diff info. i.e. in the gutter
27 | @syntax-color-added: green;
28 | @syntax-color-modified: orange;
29 | @syntax-color-removed: red;
30 | @syntax-color-renamed: blue;
31 |
--------------------------------------------------------------------------------
/resources/mac/helper-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Atom Helper
9 | CFBundleExecutable
10 | Atom Helper
11 | CFBundleIdentifier
12 | com.github.atom.helper
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | Atom Helper
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | ${VERSION}
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | ${VERSION}
25 | LSMinimumSystemVersion
26 | 10.7.0
27 | LSUIElement
28 | 1
29 | NSSupportsAutomaticGraphicsSwitching
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/spec/spec-bootstrap.coffee:
--------------------------------------------------------------------------------
1 | # Start the crash reporter before anything else.
2 | require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
3 |
4 | path = require 'path'
5 |
6 | try
7 | require '../src/window'
8 | Atom = require '../src/atom'
9 | window.atom = Atom.loadOrCreate('spec')
10 |
11 | # Show window synchronously so a focusout doesn't fire on input elements
12 | # that are focused in the very first spec run.
13 | atom.getCurrentWindow().show() unless atom.getLoadSettings().exitWhenDone
14 |
15 | {runSpecSuite} = require './jasmine-helper'
16 |
17 | # Add 'exports' to module search path.
18 | exportsPath = path.join(atom.getLoadSettings().resourcePath, 'exports')
19 | require('module').globalPaths.push(exportsPath)
20 | # Still set NODE_PATH since tasks may need it.
21 | process.env.NODE_PATH = exportsPath
22 |
23 | document.title = "Spec Suite"
24 | runSpecSuite './spec-suite', atom.getLoadSettings().logFile
25 | catch error
26 | if atom?.getLoadSettings().exitWhenDone
27 | console.error(error.stack ? error)
28 | atom.exit(1)
29 | else
30 | throw error
31 |
--------------------------------------------------------------------------------
/spec/spec-helper-platform.coffee:
--------------------------------------------------------------------------------
1 | path = require 'path'
2 | fs = require 'fs-plus'
3 |
4 | ## Platform specific helpers
5 | module.exports =
6 | # Public: Returns true if being run from within Windows
7 | isWindows: ->
8 | !!process.platform.match /^win/
9 |
10 | # Public: Some files can not exist on Windows filesystems, so we have to
11 | # selectively generate our fixtures.
12 | #
13 | # Returns nothing.
14 | generateEvilFiles: ->
15 | evilFilesPath = path.join(__dirname, 'fixtures', 'evil-files')
16 | fs.removeSync(evilFilesPath) if fs.existsSync(evilFilesPath)
17 | fs.mkdirSync(evilFilesPath)
18 |
19 | if @isWindows()
20 | filenames = [
21 | "a_file_with_utf8.txt"
22 | "file with spaces.txt"
23 | "utfa\u0306.md"
24 | ]
25 | else
26 | filenames = [
27 | "a_file_with_utf8.txt"
28 | "file with spaces.txt"
29 | "goddam\nnewlines"
30 | "quote\".txt"
31 | "utfa\u0306.md"
32 | ]
33 |
34 | for filename in filenames
35 | fs.writeFileSync(path.join(evilFilesPath, filename), 'evil file!', flag: 'w')
36 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 GitHub Inc.
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 |
--------------------------------------------------------------------------------
/script/utils/clean-merged-branches:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #/ Usage: clean-merged-branches [-f]
3 | #/ Delete merged branches from the origin remote.
4 | #/
5 | #/ Options:
6 | #/ -f Really delete the branches. Without this branches are shown
7 | #/ but nothing is deleted.
8 |
9 | set -e
10 |
11 | # show usage maybe
12 | [ "$1" = "--help" ] && {
13 | grep '^#/' <"$0"| cut -c4-
14 | exit 0
15 | }
16 |
17 | # fetch and prune remote branches
18 | git fetch origin --prune
19 |
20 | # grab list of merged branches
21 | branches=$(
22 | git branch -a --merged origin/master |
23 | grep remotes/origin/ |
24 | grep -v /master |
25 | sed 's@remotes/origin/@@'
26 | )
27 |
28 | # bail out with no branches
29 | [ -z "$branches" ] && {
30 | echo "no merged branches detected" 1>&2
31 | exit 0
32 | }
33 |
34 | # delete the branches or just show what would be done without -f
35 | if [ "$1" = -f ]; then
36 | git push origin $(echo "$branches" | sed 's/^ */:/')
37 | else
38 | echo "These branches will be deleted:" 1>&2
39 | echo "$branches"
40 | echo "Run \`$0 -f' if you're sure."
41 | fi
42 |
--------------------------------------------------------------------------------
/src/less-compile-cache.coffee:
--------------------------------------------------------------------------------
1 | path = require 'path'
2 | LessCache = require 'less-cache'
3 |
4 | # {LessCache} wrapper used by {ThemeManager} to read stylesheets.
5 | module.exports =
6 | class LessCompileCache
7 | @cacheDir: path.join(process.env.ATOM_HOME, 'compile-cache', 'less')
8 |
9 | constructor: ({resourcePath, importPaths}) ->
10 | @lessSearchPaths = [
11 | path.join(resourcePath, 'static', 'variables')
12 | path.join(resourcePath, 'static')
13 | ]
14 |
15 | if importPaths?
16 | importPaths = importPaths.concat(@lessSearchPaths)
17 | else
18 | importPaths = @lessSearchPaths
19 |
20 | @cache = new LessCache
21 | cacheDir: @constructor.cacheDir
22 | importPaths: importPaths
23 | resourcePath: resourcePath
24 | fallbackDir: path.join(resourcePath, 'less-compile-cache')
25 |
26 | setImportPaths: (importPaths=[]) ->
27 | @cache.setImportPaths(importPaths.concat(@lessSearchPaths))
28 |
29 | read: (stylesheetPath) ->
30 | @cache.readFileSync(stylesheetPath)
31 |
32 | cssForFile: (stylesheetPath, lessContent) ->
33 | @cache.cssForFile(stylesheetPath, lessContent)
34 |
--------------------------------------------------------------------------------
/src/repository-status-handler.coffee:
--------------------------------------------------------------------------------
1 | Git = require 'git-utils'
2 | path = require 'path'
3 |
4 | module.exports = (repoPath) ->
5 | repo = Git.open(repoPath)
6 |
7 | upstream = {}
8 | statuses = {}
9 | submodules = {}
10 | branch = null
11 |
12 | if repo?
13 | # Statuses in main repo
14 | workingDirectoryPath = repo.getWorkingDirectory()
15 | for filePath, status of repo.getStatus()
16 | statuses[filePath] = status
17 |
18 | # Statuses in submodules
19 | for submodulePath, submoduleRepo of repo.submodules
20 | submodules[submodulePath] =
21 | branch: submoduleRepo.getHead()
22 | upstream: submoduleRepo.getAheadBehindCount()
23 |
24 | workingDirectoryPath = submoduleRepo.getWorkingDirectory()
25 | for filePath, status of submoduleRepo.getStatus()
26 | absolutePath = path.join(workingDirectoryPath, filePath)
27 | # Make path relative to parent repository
28 | relativePath = repo.relativize(absolutePath)
29 | statuses[relativePath] = status
30 |
31 | upstream = repo.getAheadBehindCount()
32 | branch = repo.getHead()
33 | repo.release()
34 |
35 | {statuses, upstream, branch, submodules}
36 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ## Guides
2 |
3 | * [Getting Started](getting-started.md)
4 | * [Customizing Atom](customizing-atom.md)
5 | * [Creating a Package](creating-a-package.md)
6 | * [Creating a Theme](creating-a-theme.md)
7 | * [Publishing a Package](publishing-a-package.md)
8 | * [Writing Specs](writing-specs.md)
9 | * [Converting a TextMate Bundle](converting-a-text-mate-bundle.md)
10 | * [Converting a TextMate Theme](converting-a-text-mate-theme.md)
11 | * [Contributing](contributing.md)
12 | * [Contributing to Core Packages](contributing-to-packages.md)
13 | * [Debugging](debugging.md)
14 | * [Your First Package](your-first-package.md)
15 |
16 | ### Advanced Topics
17 |
18 | * [Configuration](advanced/configuration.md)
19 | * [Developing Node Modules](advanced/node-modules.md)
20 | * [Keymaps](advanced/keymaps.md)
21 | * [Serialization](advanced/serialization.md)
22 | * [Scopes and Scope Descriptors](advanced/scopes-and-scope-descriptors.md)
23 | * [Theme Variables](theme-variables.md)
24 | * [apm REST API](apm-rest-api.md)
25 |
26 | ### Upgrading to 1.0 APIs
27 |
28 | * [Upgrading Your UI Theme Or Package Selectors](upgrading/upgrading-your-ui-theme.md)
29 | * [Upgrading Your Syntax Theme](upgrading/upgrading-your-syntax-theme.md)
30 |
--------------------------------------------------------------------------------
/src/panel-element.coffee:
--------------------------------------------------------------------------------
1 | {CompositeDisposable} = require 'event-kit'
2 | {callAttachHooks} = require './space-pen-extensions'
3 | Panel = require './panel'
4 |
5 | class PanelElement extends HTMLElement
6 | createdCallback: ->
7 | @subscriptions = new CompositeDisposable
8 |
9 | initialize: (@model) ->
10 | @appendChild(@getItemView())
11 |
12 | @classList.add(@model.getClassName().split(' ')...) if @model.getClassName()?
13 | @subscriptions.add @model.onDidChangeVisible(@visibleChanged.bind(this))
14 | @subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
15 | this
16 |
17 | getModel: ->
18 | @model ?= new Panel
19 |
20 | getItemView: ->
21 | atom.views.getView(@getModel().getItem())
22 |
23 | attachedCallback: ->
24 | callAttachHooks(@getItemView()) # for backward compatibility with SpacePen views
25 | @visibleChanged(@getModel().isVisible())
26 |
27 | visibleChanged: (visible) ->
28 | if visible
29 | @style.display = null
30 | else
31 | @style.display = 'none'
32 |
33 | destroyed: ->
34 | @subscriptions.dispose()
35 | @parentNode?.removeChild(this)
36 |
37 | module.exports = PanelElement = document.registerElement 'atom-panel', prototype: PanelElement.prototype
38 |
--------------------------------------------------------------------------------
/resources/mac/speakeasy.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIDOjCCAi0GByqGSM44BAEwggIgAoIBAQCEh+j0nKWTw7soK6w3uk9PzPGVBksk
3 | wDIaA+d+1CHJY9qhjp7OjAlSOl6nrUlGHzU87DRmBlwYZONAzDZnYpLi7zmPVASg
4 | Xk+AmuqzqahTKtwodJp7R/Aq/lCbB2tXTXOxVo+Jya1BQbfd0wWXJFUlD/xTvrgu
5 | zrtw6VYBvaRu8jCjHAJNZn0CO80igj1ZNxRqmmz1Rkt1tT0KBBfGBTNzXeBmGKHN
6 | bVIKW7zImgfm+UQky+WFei1dqcfWOyfrHIYa3Qn1Nes48SBdrolvfvrChlSpqgEN
7 | wxFW9aoognS1UJTu350AQb2NwOOSQRsR++y3iJp+60nBSDZu7sjNN9etAhUAvqki
8 | JOjBjooRd2odMh7imICHQ3kCggEATwa6W0s2xrolPRpwWZS8ORUNDgEI4eOIvonq
9 | O2qZgwD21zUQOsFjLMbWn0cCtrORr7iM8pFg8Yn8dSccpqs+2cM4uFZAycKXf6w3
10 | jIvV6M3IPQuUSqVFZtqUVuteGTEuAHZKIrXE05P4aJXHLjqSC9JuaXNRm9q7OW7m
11 | rwsoAFyfkKqbtl5Ch+WZ21CE4J+ByTfVwVU4XLiOtce6NABSDWNJsF9fIoFCZCDc
12 | uumLllDJysD8S6aBNhOjNMHPmeIpZBXT23zHH5du/blcEyBbVF3a2ntgudfJmyln
13 | T178CIEUSSjcbz9JyAhhK7OfNlzKhRiO1c4Y3XaZIniLGjF5DwOCAQUAAoIBABGZ
14 | mfuHBW89ub19iICE//VbB91m2f0nUvHk8vE4vvAK8AdD91GODPJr4DU0kJM6ne8r
15 | ohvZgokgDRkGAEceX/nVoG0RLq9T15Xr2qedWVwAffpU10iV9mYwbhHqUKPtG8cj
16 | GW0cDdSI+0oG6UEyn8aQ5p93YEm5N6lq4rWKpxXb/gkrIla4sJJP8VHOOKmo6l1H
17 | AKVIfofiaNAQShu72WVCCurWaoVTUEliEBhy3WlcjuKXEuoL1lpNxyqkt7mf6w71
18 | 6y2+Nh+XUTiFoTIVhk/CH0z+BQTneWEALvfTFzDae+a42rPAisKlt+Gbe7zopnVA
19 | kcQwM0lLzgwx4T1DV3s=
20 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/src/scroll-view.coffee:
--------------------------------------------------------------------------------
1 | {View} = require './space-pen-extensions'
2 |
3 | # Deprecated: Represents a view that scrolls.
4 | #
5 | # Handles several core events to update scroll position:
6 | #
7 | # * `core:move-up` Scrolls the view up
8 | # * `core:move-down` Scrolls the view down
9 | # * `core:page-up` Scrolls the view up by the height of the page
10 | # * `core:page-down` Scrolls the view down by the height of the page
11 | # * `core:move-to-top` Scrolls the editor to the top
12 | # * `core:move-to-bottom` Scroll the editor to the bottom
13 | #
14 | # Subclasses must call `super` if overriding the `initialize` method.
15 | #
16 | # ## Examples
17 | #
18 | # ```coffee
19 | # {ScrollView} = require 'atom'
20 | #
21 | # class MyView extends ScrollView
22 | # @content: ->
23 | # @div()
24 | #
25 | # initialize: ->
26 | # super
27 | # @text('super long content that will scroll')
28 | # ```
29 | #
30 | module.exports =
31 | class ScrollView extends View
32 | initialize: ->
33 | @on 'core:move-up', => @scrollUp()
34 | @on 'core:move-down', => @scrollDown()
35 | @on 'core:page-up', => @pageUp()
36 | @on 'core:page-down', => @pageDown()
37 | @on 'core:move-to-top', => @scrollToTop()
38 | @on 'core:move-to-bottom', => @scrollToBottom()
39 |
--------------------------------------------------------------------------------
/spec/buffered-node-process-spec.coffee:
--------------------------------------------------------------------------------
1 | path = require 'path'
2 | BufferedNodeProcess = require '../src/buffered-node-process'
3 |
4 | describe "BufferedNodeProcess", ->
5 | it "executes the script in a new process", ->
6 | exit = jasmine.createSpy('exitCallback')
7 | output = ''
8 | stdout = (lines) -> output += lines
9 | error = ''
10 | stderr = (lines) -> error += lines
11 | args = ['hi']
12 | command = path.join(__dirname, 'fixtures', 'script.js')
13 |
14 | new BufferedNodeProcess({command, args, stdout, stderr, exit})
15 |
16 | waitsFor ->
17 | exit.callCount is 1
18 |
19 | runs ->
20 | expect(output).toBe 'hi'
21 | expect(error).toBe ''
22 | expect(args).toEqual ['hi']
23 |
24 | it "suppresses deprecations in the new process", ->
25 | exit = jasmine.createSpy('exitCallback')
26 | output = ''
27 | stdout = (lines) -> output += lines
28 | error = ''
29 | stderr = (lines) -> error += lines
30 | command = path.join(__dirname, 'fixtures', 'script-with-deprecations.js')
31 |
32 | new BufferedNodeProcess({command, stdout, stderr, exit})
33 |
34 | waitsFor ->
35 | exit.callCount is 1
36 |
37 | runs ->
38 | expect(output).toBe 'hi'
39 | expect(error).toBe ''
40 |
--------------------------------------------------------------------------------
/static/panes.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | // Pane-items are things that go inside a pane. Like the UI-Demo, the
4 | // settings-view, the archive-view, the image-view. Etc. Basically a non-
5 | // editor resource with a tab.
6 | atom-pane-container {
7 | display: -webkit-flex;
8 | -webkit-flex: 1;
9 |
10 | atom-pane-axis.vertical {
11 | display: -webkit-flex;
12 | -webkit-flex: 1;
13 | -webkit-flex-direction: column;
14 | }
15 |
16 | atom-pane-axis.horizontal {
17 | display: -webkit-flex;
18 | -webkit-flex: 1;
19 | -webkit-flex-direction: row;
20 | }
21 |
22 | atom-pane {
23 | position: relative;
24 | display: -webkit-flex;
25 | -webkit-flex: 1;
26 | -webkit-flex-direction: column;
27 | overflow: hidden;
28 |
29 | .item-views {
30 | -webkit-flex: 1;
31 | display: -webkit-flex;
32 | min-height: 0;
33 | min-width: 0;
34 | position: relative;
35 |
36 | .pane-item {
37 | color: @text-color;
38 | background-color: @pane-item-background-color;
39 | }
40 |
41 | > *, > atom-text-editor.react > * {
42 | position: absolute;
43 | top: 0;
44 | right: 0;
45 | bottom: 0;
46 | left: 0;
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/input-component.coffee:
--------------------------------------------------------------------------------
1 | {last, isEqual} = require 'underscore-plus'
2 | React = require 'react-atom-fork'
3 | {input} = require 'reactionary-atom-fork'
4 |
5 | module.exports =
6 | InputComponent = React.createClass
7 | displayName: 'InputComponent'
8 |
9 | render: ->
10 | {className, style} = @props
11 |
12 | input {className, style, 'data-react-skip-selection-restoration': true}
13 |
14 | getInitialState: ->
15 | {lastChar: ''}
16 |
17 | componentDidMount: ->
18 | node = @getDOMNode()
19 | node.addEventListener 'paste', @onPaste
20 | node.addEventListener 'compositionupdate', @onCompositionUpdate
21 |
22 | # Don't let text accumulate in the input forever, but avoid excessive reflows
23 | componentDidUpdate: ->
24 | if @lastValueLength > 500 and not @isPressAndHoldCharacter(@state.lastChar)
25 | @getDOMNode().value = ''
26 | @lastValueLength = 0
27 |
28 | # This should actually consult the property lists in /System/Library/Input Methods/PressAndHold.app
29 | isPressAndHoldCharacter: (char) ->
30 | @state.lastChar.match /[aeiouAEIOU]/
31 |
32 | shouldComponentUpdate: (newProps) ->
33 | not isEqual(newProps.style, @props.style)
34 |
35 | onPaste: (e) ->
36 | e.preventDefault()
37 |
38 | focus: ->
39 | @getDOMNode().focus()
40 |
--------------------------------------------------------------------------------
/spec/space-pen-extensions-spec.coffee:
--------------------------------------------------------------------------------
1 | {View, $, $$} = require '../src/space-pen-extensions'
2 |
3 | describe "SpacePen extensions", ->
4 | class TestView extends View
5 | @content: -> @div()
6 |
7 | [view, parent] = []
8 |
9 | beforeEach ->
10 | view = new TestView
11 | parent = $$ -> @div()
12 | parent.append(view)
13 |
14 | describe "View.subscribe(eventEmitter, eventName, callback)", ->
15 | [emitter, eventHandler] = []
16 |
17 | beforeEach ->
18 | eventHandler = jasmine.createSpy 'eventHandler'
19 | emitter = $$ -> @div()
20 | view.subscribe emitter, 'foo', eventHandler
21 |
22 | it "subscribes to the given event emitter and unsubscribes when unsubscribe is called", ->
23 | emitter.trigger "foo"
24 | expect(eventHandler).toHaveBeenCalled()
25 |
26 | describe "tooltips", ->
27 | describe "when the window is resized", ->
28 | it "hides the tooltips", ->
29 | class TooltipView extends View
30 | @content: ->
31 | @div()
32 |
33 | view = new TooltipView()
34 | view.attachToDom()
35 | view.setTooltip('this is a tip')
36 |
37 | view.tooltip('show')
38 | expect($(document.body).find('.tooltip')).toBeVisible()
39 |
40 | $(window).trigger('resize')
41 | expect($(document.body).find('.tooltip')).not.toExist()
42 |
--------------------------------------------------------------------------------
/spec/command-installer-spec.coffee:
--------------------------------------------------------------------------------
1 | path = require 'path'
2 | fs = require 'fs-plus'
3 | temp = require 'temp'
4 | installer = require '../src/command-installer'
5 |
6 | describe "install(commandPath, callback)", ->
7 | commandFilePath = temp.openSync("atom-command").path
8 | commandName = path.basename(commandFilePath)
9 | installationPath = temp.mkdirSync("atom-bin")
10 | installationFilePath = path.join(installationPath, commandName)
11 |
12 | beforeEach ->
13 | fs.chmodSync(commandFilePath, '755')
14 | spyOn(installer, 'getInstallDirectory').andReturn installationPath
15 |
16 | describe "on #darwin", ->
17 | it "symlinks the command and makes it executable", ->
18 | expect(fs.isFileSync(commandFilePath)).toBeTruthy()
19 | expect(fs.isFileSync(installationFilePath)).toBeFalsy()
20 |
21 | installDone = false
22 | installError = null
23 | installer.createSymlink commandFilePath, false, (error) ->
24 | installDone = true
25 | installError = error
26 |
27 | waitsFor ->
28 | installDone
29 |
30 | runs ->
31 | expect(installError).toBeNull()
32 | expect(fs.isFileSync(installationFilePath)).toBeTruthy()
33 | expect(fs.realpathSync(installationFilePath)).toBe fs.realpathSync(commandFilePath)
34 | expect(fs.isExecutableSync(installationFilePath)).toBeTruthy()
35 |
--------------------------------------------------------------------------------
/src/task-bootstrap.coffee:
--------------------------------------------------------------------------------
1 | {userAgent, taskPath} = process.env
2 | handler = null
3 |
4 | setupGlobals = ->
5 | global.attachEvent = ->
6 | console =
7 | warn: -> emit 'task:warn', arguments...
8 | log: -> emit 'task:log', arguments...
9 | error: -> emit 'task:error', arguments...
10 | trace: ->
11 | global.__defineGetter__ 'console', -> console
12 |
13 | global.document =
14 | createElement: ->
15 | setAttribute: ->
16 | getElementsByTagName: -> []
17 | appendChild: ->
18 | documentElement:
19 | insertBefore: ->
20 | removeChild: ->
21 | getElementById: -> {}
22 | createComment: -> {}
23 | createDocumentFragment: -> {}
24 |
25 | global.emit = (event, args...) ->
26 | process.send({event, args})
27 | global.navigator = {userAgent}
28 | global.window = global
29 |
30 | handleEvents = ->
31 | process.on 'uncaughtException', (error) ->
32 | console.error(error.message, error.stack)
33 | process.on 'message', ({event, args}={}) ->
34 | return unless event is 'start'
35 |
36 | isAsync = false
37 | async = ->
38 | isAsync = true
39 | (result) ->
40 | emit('task:completed', result)
41 | result = handler.bind({async})(args...)
42 | emit('task:completed', result) unless isAsync
43 |
44 | setupGlobals()
45 | handleEvents()
46 | handler = require(taskPath)
47 |
--------------------------------------------------------------------------------
/src/highlights-component.coffee:
--------------------------------------------------------------------------------
1 | React = require 'react-atom-fork'
2 | {div} = require 'reactionary-atom-fork'
3 | {isEqualForProperties} = require 'underscore-plus'
4 | HighlightComponent = require './highlight-component'
5 |
6 | module.exports =
7 | HighlightsComponent = React.createClass
8 | displayName: 'HighlightsComponent'
9 |
10 | render: ->
11 | div className: 'highlights',
12 | @renderHighlights() if @props.performedInitialMeasurement
13 |
14 | renderHighlights: ->
15 | {editor, highlightDecorations, lineHeightInPixels} = @props
16 |
17 | highlightComponents = []
18 | for markerId, {startPixelPosition, endPixelPosition, decorations} of highlightDecorations
19 | for decoration in decorations
20 | highlightComponents.push(HighlightComponent({editor, key: "#{markerId}-#{decoration.id}", startPixelPosition, endPixelPosition, decoration, lineHeightInPixels}))
21 |
22 | highlightComponents
23 |
24 | componentDidMount: ->
25 | if atom.config.get('editor.useShadowDOM')
26 | insertionPoint = document.createElement('content')
27 | insertionPoint.setAttribute('select', '.underlayer')
28 | @getDOMNode().appendChild(insertionPoint)
29 |
30 | shouldComponentUpdate: (newProps) ->
31 | not isEqualForProperties(newProps, @props, 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth', 'scopedCharacterWidthsChangeCount')
32 |
--------------------------------------------------------------------------------
/static/bootstrap.less:
--------------------------------------------------------------------------------
1 | // Core variables and mixins
2 | @import "../node_modules/bootstrap/less/variables.less";
3 | @import "../node_modules/bootstrap/less/mixins.less";
4 |
5 | // Reset
6 | @import "../node_modules/bootstrap/less/normalize.less";
7 |
8 | // Core CSS
9 | @import "../node_modules/bootstrap/less/scaffolding.less";
10 | @import "../node_modules/bootstrap/less/type.less";
11 | @import "../node_modules/bootstrap/less/code.less";
12 | @import "../node_modules/bootstrap/less/grid.less";
13 | @import "../node_modules/bootstrap/less/tables.less";
14 | @import "../node_modules/bootstrap/less/forms.less";
15 | @import "../node_modules/bootstrap/less/buttons.less";
16 |
17 | // Components
18 | @import "../node_modules/bootstrap/less/button-groups.less";
19 | @import "../node_modules/bootstrap/less/input-groups.less";
20 | @import "../node_modules/bootstrap/less/navs.less";
21 | @import "../node_modules/bootstrap/less/labels.less";
22 | @import "../node_modules/bootstrap/less/badges.less";
23 | @import "../node_modules/bootstrap/less/alerts.less";
24 | @import "../node_modules/bootstrap/less/list-group.less";
25 | @import "../node_modules/bootstrap/less/thumbnails.less";
26 | @import "../node_modules/bootstrap/less/close.less";
27 |
28 | // Components w/ JavaScript
29 | @import "../node_modules/bootstrap/less/tooltip.less";
30 |
31 | // Utility classes
32 | @import "../node_modules/bootstrap/less/utilities.less";
33 |
--------------------------------------------------------------------------------
/resources/linux/redhat/atom.spec.in:
--------------------------------------------------------------------------------
1 | Name: <%= name %>
2 | Version: <%= version %>
3 | Release: 0.1%{?dist}
4 | Summary: <%= description %>
5 | License: MIT
6 | URL: https://atom.io/
7 | AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
8 | Prefix: <%= installDir %>
9 |
10 | %description
11 | <%= description %>
12 |
13 | %install
14 | mkdir -p %{buildroot}/<%= installDir %>/share/atom/
15 | cp -r Atom/* %{buildroot}/<%= installDir %>/share/atom/
16 | mkdir -p %{buildroot}/<%= installDir %>/bin/
17 | ln -sf ../share/atom/resources/app/apm/node_modules/.bin/apm %{buildroot}/<%= installDir %>/bin/apm
18 | cp atom.sh %{buildroot}/<%= installDir %>/bin/atom
19 | chmod 755 %{buildroot}/<%= installDir %>/bin/atom
20 | mkdir -p %{buildroot}/<%= installDir %>/share/applications/
21 | cp atom.desktop %{buildroot}/<%= installDir %>/share/applications/
22 |
23 | # copy over icons in sizes that most desktop environments like
24 | for i in 1024 512 256 128 64 48 32 24 16
25 | do
26 | mkdir -p %{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps
27 | cp icons/${i}.png %{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps/atom.png
28 | done
29 |
30 | %files
31 | <%= installDir %>/bin/atom
32 | <%= installDir %>/bin/apm
33 | <%= installDir %>/share/atom/
34 | <%= installDir %>/share/applications/atom.desktop
35 | <%= installDir %>/share/icons/hicolor/
36 |
--------------------------------------------------------------------------------
/static/utilities.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | :focus {
4 | outline: none;
5 | }
6 |
7 | .pull-center {
8 | margin-left: auto;
9 | margin-right: auto;
10 | }
11 |
12 | .padded {
13 | padding: @component-padding;
14 | }
15 |
16 | // Blocks
17 |
18 | // Must be div.block so as not to affect syntax highlighting.
19 | ul.block,
20 | div.block {
21 | margin-bottom: @component-padding;
22 | }
23 | div > ul.block:last-child,
24 | div > div.block:last-child {
25 | margin-bottom: 0;
26 | }
27 |
28 | // Inline Blocks
29 |
30 | .inline-block,
31 | .inline-block-tight {
32 | display: inline-block;
33 | vertical-align: middle;
34 | }
35 | .inline-block {
36 | margin-right: @component-padding;
37 | }
38 | .inline-block-tight {
39 | margin-right: @component-padding/2;
40 | }
41 | div > .inline-block:last-child,
42 | div > .inline-block-tight:last-child {
43 | margin-right: 0;
44 | }
45 |
46 | .inline-block .inline-block {
47 | vertical-align: top;
48 | }
49 |
50 | // Use left margin when it's in a float: right element.
51 | // Sets the margin correctly when inline blocks are hidden and shown.
52 | .pull-right {
53 | .inline-block {
54 | margin-right: 0;
55 | margin-left: @component-padding;
56 | }
57 | .inline-block-tight {
58 | margin-right: 0;
59 | margin-left: @component-padding/2;
60 | }
61 |
62 | > .inline-block:first-child,
63 | > .inline-block-tight:first-child {
64 | margin-left: 0;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/script/mkdeb:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # mkdeb version control-file-path deb-file-path
3 |
4 | set -e
5 |
6 | SCRIPT=`readlink -f "$0"`
7 | ROOT=`readlink -f $(dirname $SCRIPT)/..`
8 | cd $ROOT
9 |
10 | VERSION="$1"
11 | ARCH="$2"
12 | CONTROL_FILE="$3"
13 | DESKTOP_FILE="$4"
14 | ICON_FILE="$5"
15 | DEB_PATH="$6"
16 | FILE_MODE=755
17 |
18 | TARGET_ROOT="`mktemp -d`"
19 | chmod $FILE_MODE "$TARGET_ROOT"
20 | TARGET="$TARGET_ROOT/atom-$VERSION-$ARCH"
21 |
22 | mkdir -m $FILE_MODE -p "$TARGET/usr"
23 | env INSTALL_PREFIX="$TARGET/usr" script/grunt install
24 |
25 | mkdir -m $FILE_MODE -p "$TARGET/DEBIAN"
26 | cp "$CONTROL_FILE" "$TARGET/DEBIAN/control"
27 |
28 | mkdir -m $FILE_MODE -p "$TARGET/usr/share/applications"
29 | cp "$DESKTOP_FILE" "$TARGET/usr/share/applications"
30 |
31 | mkdir -m $FILE_MODE -p "$TARGET/usr/share/pixmaps"
32 | cp "$ICON_FILE" "$TARGET/usr/share/pixmaps"
33 |
34 | # Copy generated LICENSE.md to /usr/share/doc/atom/copyright
35 | mkdir -m $FILE_MODE -p "$TARGET/usr/share/doc/atom"
36 | cp "$TARGET/usr/share/atom/resources/app/LICENSE.md" "$TARGET/usr/share/doc/atom/copyright"
37 |
38 | # Add lintian overrides
39 | mkdir -m $FILE_MODE -p "$TARGET/usr/share/lintian/overrides"
40 | cp "$ROOT/resources/linux/debian/lintian-overrides" "$TARGET/usr/share/lintian/overrides/atom"
41 |
42 | # Remove executable bit from .node files
43 | find "$TARGET" -type f -name "*.node" -exec chmod a-x {} \;
44 |
45 | fakeroot dpkg-deb -b "$TARGET"
46 | mv "$TARGET_ROOT/atom-$VERSION-$ARCH.deb" "$DEB_PATH"
47 | rm -rf "$TARGET_ROOT"
48 |
--------------------------------------------------------------------------------
/src/notification.coffee:
--------------------------------------------------------------------------------
1 | {Emitter} = require 'event-kit'
2 |
3 | # Experimental: This will likely change, do not use.
4 | module.exports =
5 | class Notification
6 | constructor: (@type, @message, @options={}) ->
7 | @emitter = new Emitter
8 | @timestamp = new Date()
9 | @dismissed = true
10 | @dismissed = false if @isDismissable()
11 | @displayed = false
12 |
13 | onDidDismiss: (callback) ->
14 | @emitter.on 'did-dismiss', callback
15 |
16 | onDidDisplay: (callback) ->
17 | @emitter.on 'did-display', callback
18 |
19 | getOptions: -> @options
20 |
21 | getType: -> @type
22 |
23 | getMessage: -> @message
24 |
25 | getTimestamp: -> @timestamp
26 |
27 | getDetail: -> @options.detail
28 |
29 | isEqual: (other) ->
30 | @getMessage() == other.getMessage() \
31 | and @getType() == other.getType() \
32 | and @getDetail() == other.getDetail()
33 |
34 | dismiss: ->
35 | return unless @isDismissable() and not @isDismissed()
36 | @dismissed = true
37 | @emitter.emit 'did-dismiss', this
38 |
39 | isDismissed: -> @dismissed
40 |
41 | isDismissable: -> !!@options.dismissable
42 |
43 | wasDisplayed: -> @displayed
44 |
45 | setDisplayed: (@displayed) ->
46 | @emitter.emit 'did-display', this
47 |
48 | getIcon: ->
49 | return @options.icon if @options.icon?
50 | switch @type
51 | when 'fatal' then 'bug'
52 | when 'error' then 'flame'
53 | when 'warning' then 'alert'
54 | when 'info' then 'info'
55 | when 'success' then 'check'
56 |
--------------------------------------------------------------------------------
/script/utils/child-process-wrapper.js:
--------------------------------------------------------------------------------
1 | var childProcess = require('child_process');
2 |
3 | // Exit the process if the command failed and only call the callback if the
4 | // command succeed, output of the command would also be piped.
5 | exports.safeExec = function(command, options, callback) {
6 | if (!callback) {
7 | callback = options;
8 | options = {};
9 | }
10 | if (!options)
11 | options = {};
12 |
13 | // This needed to be increased for `apm test` runs that generate many failures
14 | // The default is 200KB.
15 | options.maxBuffer = 1024 * 1024;
16 |
17 | var child = childProcess.exec(command, options, function(error, stdout, stderr) {
18 | if (error)
19 | process.exit(error.code || 1);
20 | else
21 | callback(null);
22 | });
23 | child.stderr.pipe(process.stderr);
24 | if (!options.ignoreStdout)
25 | child.stdout.pipe(process.stdout);
26 | }
27 |
28 | // Same with safeExec but call child_process.spawn instead.
29 | exports.safeSpawn = function(command, args, options, callback) {
30 | if (!callback) {
31 | callback = options;
32 | options = {};
33 | }
34 | var child = childProcess.spawn(command, args, options);
35 | child.stderr.pipe(process.stderr);
36 | child.stdout.pipe(process.stdout);
37 | child.on('error', function(error) {
38 | console.error('Command \'' + command + '\' failed: ' + error.message);
39 | });
40 | child.on('exit', function(code) {
41 | if (code != 0)
42 | process.exit(code);
43 | else
44 | callback(null);
45 | });
46 | }
47 |
--------------------------------------------------------------------------------
/script/clean:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var cp = require('./utils/child-process-wrapper.js');
3 | var fs = require('fs');
4 | var path = require('path');
5 | var os = require('os');
6 |
7 | var removeCommand = process.platform === 'win32' ? 'rmdir /S /Q ' : 'rm -rf ';
8 | var productName = require('../package.json').productName;
9 |
10 | process.chdir(path.dirname(__dirname));
11 | var home = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
12 | var tmpdir = os.tmpdir();
13 |
14 | // Windows: Use START as a way to ignore error if Atom.exe isnt running
15 | var killatom = process.platform === 'win32' ? 'START taskkill /F /IM ' + productName + '.exe' : 'pkill -9 ' + productName + ' || true';
16 |
17 | var commands = [
18 | killatom,
19 | [__dirname, '..', 'node_modules'],
20 | [__dirname, '..', 'build', 'node_modules'],
21 | [__dirname, '..', 'apm', 'node_modules'],
22 | [__dirname, '..', 'atom-shell'],
23 | [home, '.atom', '.node-gyp'],
24 | [home, '.atom', 'storage'],
25 | [home, '.atom', '.npm'],
26 | [home, '.atom', 'compile-cache'],
27 | [home, '.atom', 'atom-shell'],
28 | [tmpdir, 'atom-build'],
29 | [tmpdir, 'atom-cached-atom-shells'],
30 | ];
31 | var run = function() {
32 | var next = commands.shift();
33 | if (!next)
34 | process.exit(0);
35 |
36 | if (Array.isArray(next)) {
37 | var pathToRemove = path.resolve.apply(path.resolve, next);
38 | if (fs.existsSync(pathToRemove))
39 | next = removeCommand + pathToRemove;
40 | else
41 | return run();
42 | }
43 |
44 | cp.safeExec(next, run);
45 | };
46 | run();
47 |
--------------------------------------------------------------------------------
/spec/task-spec.coffee:
--------------------------------------------------------------------------------
1 | Task = require '../src/task'
2 |
3 | describe "Task", ->
4 | describe "@once(taskPath, args..., callback)", ->
5 | it "terminates the process after it completes", ->
6 | handlerResult = null
7 | task = Task.once require.resolve('./fixtures/task-spec-handler'), (result) ->
8 | handlerResult = result
9 |
10 | processClosed = false
11 | processErrored = false
12 | childProcess = task.childProcess
13 | spyOn(childProcess, 'kill').andCallThrough()
14 | task.childProcess.on 'error', -> processErrored = true
15 |
16 | waitsFor ->
17 | handlerResult?
18 |
19 | runs ->
20 | expect(handlerResult).toBe 'hello'
21 | expect(childProcess.kill).toHaveBeenCalled()
22 | expect(processErrored).toBe false
23 |
24 | it "calls listeners registered with ::on when events are emitted in the task", ->
25 | task = new Task(require.resolve('./fixtures/task-spec-handler'))
26 |
27 | eventSpy = jasmine.createSpy('eventSpy')
28 | task.on("some-event", eventSpy)
29 |
30 | waitsFor (done) -> task.start(done)
31 |
32 | runs ->
33 | expect(eventSpy).toHaveBeenCalledWith(1, 2, 3)
34 |
35 | it "unregisters listeners when the Disposable returned by ::on is disposed", ->
36 | task = new Task(require.resolve('./fixtures/task-spec-handler'))
37 |
38 | eventSpy = jasmine.createSpy('eventSpy')
39 | disposable = task.on("some-event", eventSpy)
40 | disposable.dispose()
41 |
42 | waitsFor (done) -> task.start(done)
43 |
44 | runs ->
45 | expect(eventSpy).not.toHaveBeenCalled()
46 |
--------------------------------------------------------------------------------
/src/scope-descriptor.coffee:
--------------------------------------------------------------------------------
1 | # Extended: Wraps an {Array} of `String`s. The Array describes a path from the
2 | # root of the syntax tree to a token including _all_ scope names for the entire
3 | # path.
4 | #
5 | # Methods that take a `ScopeDescriptor` will also accept an {Array} of {Strings}
6 | # scope names e.g. `['.source.js']`.
7 | #
8 | # You can use `ScopeDescriptor`s to get language-specific config settings via
9 | # {Config::get}.
10 | #
11 | # You should not need to create a `ScopeDescriptor` directly.
12 | #
13 | # * {Editor::getRootScopeDescriptor} to get the language's descriptor.
14 | # * {Editor::scopeDescriptorForBufferPosition} to get the descriptor at a
15 | # specific position in the buffer.
16 | # * {Cursor::getScopeDescriptor} to get a cursor's descriptor based on position.
17 | #
18 | # See the [scopes and scope descriptor guide](https://atom.io/docs/v0.138.0/advanced/scopes-and-scope-descriptors)
19 | # for more information.
20 | module.exports =
21 | class ScopeDescriptor
22 | @fromObject: (scopes) ->
23 | if scopes instanceof ScopeDescriptor
24 | scopes
25 | else
26 | new ScopeDescriptor({scopes})
27 |
28 | ###
29 | Section: Construction and Destruction
30 | ###
31 |
32 | # Public: Create a {ScopeDescriptor} object.
33 | #
34 | # * `object` {Object}
35 | # * `scopes` {Array} of {String}s
36 | constructor: ({@scopes}) ->
37 |
38 | # Public: Returns an {Array} of {String}s
39 | getScopesArray: -> @scopes
40 |
41 | getScopeChain: ->
42 | @scopes
43 | .map (scope) ->
44 | scope = ".#{scope}" unless scope[0] is '.'
45 | scope
46 | .join(' ')
47 |
--------------------------------------------------------------------------------
/src/notification-manager.coffee:
--------------------------------------------------------------------------------
1 | {Emitter, Disposable} = require 'event-kit'
2 | Notification = require '../src/notification'
3 |
4 | # Experimental: Allows messaging the user. This will likely change, dont use
5 | # quite yet!
6 | module.exports =
7 | class NotificationManager
8 | constructor: ->
9 | @notifications = []
10 | @emitter = new Emitter
11 |
12 | ###
13 | Section: Events
14 | ###
15 |
16 | onDidAddNotification: (callback) ->
17 | @emitter.on 'did-add-notification', callback
18 |
19 | ###
20 | Section: Adding Notifications
21 | ###
22 |
23 | addSuccess: (message, options) ->
24 | @addNotification(new Notification('success', message, options))
25 |
26 | addInfo: (message, options) ->
27 | @addNotification(new Notification('info', message, options))
28 |
29 | addWarning: (message, options) ->
30 | @addNotification(new Notification('warning', message, options))
31 |
32 | addError: (message, options) ->
33 | @addNotification(new Notification('error', message, options))
34 |
35 | addFatalError: (message, options) ->
36 | @addNotification(new Notification('fatal', message, options))
37 |
38 | add: (type, message, options) ->
39 | @addNotification(new Notification(type, message, options))
40 |
41 | addNotification: (notification) ->
42 | @notifications.push(notification)
43 | @emitter.emit('did-add-notification', notification)
44 | notification
45 |
46 | ###
47 | Section: Getting Notifications
48 | ###
49 |
50 | getNotifications: -> @notifications
51 |
52 | ###
53 | Section: Managing Notifications
54 | ###
55 |
56 | clear: ->
57 | @notifications = []
58 |
--------------------------------------------------------------------------------
/src/browser/atom-protocol-handler.coffee:
--------------------------------------------------------------------------------
1 | app = require 'app'
2 | fs = require 'fs'
3 | path = require 'path'
4 | protocol = require 'protocol'
5 |
6 | # Handles requests with 'atom' protocol.
7 | #
8 | # It's created by {AtomApplication} upon instantiation and is used to create a
9 | # custom resource loader for 'atom://' URLs.
10 | #
11 | # The following directories are searched in order:
12 | # * ~/.atom/assets
13 | # * ~/.atom/dev/packages (unless in safe mode)
14 | # * ~/.atom/packages
15 | # * RESOURCE_PATH/node_modules
16 | #
17 | module.exports =
18 | class AtomProtocolHandler
19 | constructor: (resourcePath, safeMode) ->
20 | @loadPaths = []
21 | @dotAtomDirectory = path.join(app.getHomeDir(), '.atom')
22 |
23 | unless safeMode
24 | @loadPaths.push(path.join(@dotAtomDirectory, 'dev', 'packages'))
25 |
26 | @loadPaths.push(path.join(@dotAtomDirectory, 'packages'))
27 | @loadPaths.push(path.join(resourcePath, 'node_modules'))
28 |
29 | @registerAtomProtocol()
30 |
31 | # Creates the 'atom' custom protocol handler.
32 | registerAtomProtocol: ->
33 | protocol.registerProtocol 'atom', (request) =>
34 | relativePath = path.normalize(request.url.substr(7))
35 |
36 | if relativePath.indexOf('assets/') is 0
37 | assetsPath = path.join(@dotAtomDirectory, relativePath)
38 | filePath = assetsPath if fs.statSyncNoException(assetsPath).isFile?()
39 |
40 | unless filePath
41 | for loadPath in @loadPaths
42 | filePath = path.join(loadPath, relativePath)
43 | break if fs.statSyncNoException(filePath).isFile?()
44 |
45 | new protocol.RequestFileJob(filePath)
46 |
--------------------------------------------------------------------------------
/src/pane-axis-element.coffee:
--------------------------------------------------------------------------------
1 | {CompositeDisposable} = require 'event-kit'
2 | {callAttachHooks} = require './space-pen-extensions'
3 |
4 | class PaneAxisElement extends HTMLElement
5 | createdCallback: ->
6 | @subscriptions = new CompositeDisposable
7 |
8 | detachedCallback: ->
9 | @subscriptions.dispose()
10 |
11 | initialize: (@model) ->
12 | @subscriptions.add @model.onDidAddChild(@childAdded.bind(this))
13 | @subscriptions.add @model.onDidRemoveChild(@childRemoved.bind(this))
14 | @subscriptions.add @model.onDidReplaceChild(@childReplaced.bind(this))
15 |
16 | @childAdded({child, index}) for child, index in @model.getChildren()
17 |
18 | switch @model.getOrientation()
19 | when 'horizontal'
20 | @classList.add('horizontal', 'pane-row')
21 | when 'vertical'
22 | @classList.add('vertical', 'pane-column')
23 | this
24 |
25 | childAdded: ({child, index}) ->
26 | view = atom.views.getView(child)
27 | @insertBefore(view, @children[index])
28 | callAttachHooks(view) # for backward compatibility with SpacePen views
29 |
30 | childRemoved: ({child}) ->
31 | view = atom.views.getView(child)
32 | view.remove()
33 |
34 | childReplaced: ({index, oldChild, newChild}) ->
35 | focusedElement = document.activeElement if @hasFocus()
36 | @childRemoved({child: oldChild, index})
37 | @childAdded({child: newChild, index})
38 | focusedElement?.focus() if document.activeElement is document.body
39 |
40 | hasFocus: ->
41 | this is document.activeElement or @contains(document.activeElement)
42 |
43 | module.exports = PaneAxisElement = document.registerElement 'atom-pane-axis', prototype: PaneAxisElement.prototype
44 |
--------------------------------------------------------------------------------
/spec/6to5-spec.coffee:
--------------------------------------------------------------------------------
1 | to5 = require '../src/6to5'
2 | crypto = require 'crypto'
3 |
4 | describe "6to5 transpiler support", ->
5 | describe "::create6to5VersionAndOptionsDigest", ->
6 | it "returns a digest for the library version and specified options", ->
7 | defaultOptions =
8 | blacklist: [
9 | 'useStrict'
10 | ]
11 | experimental: true
12 | optional: [
13 | 'asyncToGenerator'
14 | ]
15 | reactCompat: true
16 | sourceMap: 'inline'
17 | version = '3.0.14'
18 | shasum = crypto.createHash('sha1')
19 | shasum.update('6to5-core', 'utf8')
20 | shasum.update('\0', 'utf8')
21 | shasum.update(version, 'utf8')
22 | shasum.update('\0', 'utf8')
23 | shasum.update('{"blacklist": ["useStrict",],"experimental": true,"optional": ["asyncToGenerator",],"reactCompat": true,"sourceMap": "inline",}')
24 | expectedDigest = shasum.digest('hex')
25 |
26 | observedDigest = to5.create6to5VersionAndOptionsDigest(version, defaultOptions)
27 | expect(observedDigest).toEqual expectedDigest
28 |
29 | describe "when a .js file starts with 'use 6to5';", ->
30 | it "transpiles it using 6to5", ->
31 | transpiled = require('./fixtures/6to5/single-quotes.js')
32 | expect(transpiled(3)).toBe 4
33 |
34 | describe 'when a .js file starts with "use 6to5";', ->
35 | it "transpiles it using 6to5", ->
36 | transpiled = require('./fixtures/6to5/double-quotes.js')
37 | expect(transpiled(3)).toBe 4
38 |
39 | describe "when a .js file does not start with 'use 6to6';", ->
40 | it "does not transpile it using 6to5", ->
41 | expect(-> require('./fixtures/6to5/invalid.js')).toThrow()
42 |
--------------------------------------------------------------------------------
/script/utils/translate-crash-log-addresses.coffee:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env coffee
2 | # Usage:
3 | # Copy the crash log into pasteboard and then run
4 | # pbpaste | ./script/translate-crash-log-addresses.coffee
5 |
6 | atos = (addresses, callback) ->
7 | path = require 'path'
8 | exec = require('child_process').exec
9 |
10 | cwd = path.join __dirname, '..'
11 | exec 'atos -o cef/Release/libcef.dylib -arch i386 '.concat(addresses...), cwd: cwd, (error, stdout, stderr) ->
12 | throw error if error?
13 | callback stdout.split('\n')
14 |
15 | parse_stack_trace = (raw) ->
16 | lines = {}
17 | addresses = []
18 | for line in raw
19 | columns = line.split /\ +/
20 | if columns[1] == 'libcef.dylib' and /0x[a-f0-9]+/.test columns[3]
21 | lines[columns[0]] = addresses.length
22 | addresses.push '0x' + parseInt(columns[5]).toString(16) + ' '
23 |
24 | atos addresses, (parsed) ->
25 | for line in raw
26 | columns = line.split /\ +/
27 | frame = columns[0]
28 | if lines[frame]?
29 | console.log frame, parsed[lines[frame]]
30 | else
31 | console.log line
32 |
33 | parse_log_file = (content) ->
34 | state = 'start'
35 | stack_trace = []
36 | lines = content.split /\r?\n/
37 |
38 | for line in lines
39 | if state == 'start'
40 | if /Thread \d+ Crashed::/.test line
41 | console.log line
42 | state = 'parse'
43 | else if state == 'parse'
44 | break if line == ''
45 | stack_trace.push line
46 |
47 | parse_stack_trace stack_trace
48 |
49 | input = ''
50 | process.stdin.resume()
51 | process.stdin.setEncoding 'utf8'
52 | process.stdin.on 'data', (chunk) ->
53 | input += chunk
54 | process.stdin.on 'end', ->
55 | parse_log_file input
56 |
57 |
--------------------------------------------------------------------------------
/src/clipboard.coffee:
--------------------------------------------------------------------------------
1 | clipboard = require 'clipboard'
2 | crypto = require 'crypto'
3 |
4 | # Extended: Represents the clipboard used for copying and pasting in Atom.
5 | #
6 | # An instance of this class is always available as the `atom.clipboard` global.
7 | #
8 | # ## Examples
9 | #
10 | # ```coffee
11 | # atom.clipboard.write('hello')
12 | #
13 | # console.log(atom.clipboard.read()) # 'hello'
14 | # ```
15 | module.exports =
16 | class Clipboard
17 | metadata: null
18 | signatureForMetadata: null
19 |
20 | # Creates an `md5` hash of some text.
21 | #
22 | # * `text` A {String} to hash.
23 | #
24 | # Returns a hashed {String}.
25 | md5: (text) ->
26 | crypto.createHash('md5').update(text, 'utf8').digest('hex')
27 |
28 | # Public: Write the given text to the clipboard.
29 | #
30 | # The metadata associated with the text is available by calling
31 | # {::readWithMetadata}.
32 | #
33 | # * `text` The {String} to store.
34 | # * `metadata` The additional info to associate with the text.
35 | write: (text, metadata) ->
36 | @signatureForMetadata = @md5(text)
37 | @metadata = metadata
38 | clipboard.writeText(text)
39 |
40 | # Public: Read the text from the clipboard.
41 | #
42 | # Returns a {String}.
43 | read: ->
44 | clipboard.readText()
45 |
46 | # Public: Read the text from the clipboard and return both the text and the
47 | # associated metadata.
48 | #
49 | # Returns an {Object} with the following keys:
50 | # * `text` The {String} clipboard text.
51 | # * `metadata` The metadata stored by an earlier call to {::write}.
52 | readWithMetadata: ->
53 | text = @read()
54 | if @signatureForMetadata is @md5(text)
55 | {text, @metadata}
56 | else
57 | {text}
58 |
--------------------------------------------------------------------------------
/src/panel-container-element.coffee:
--------------------------------------------------------------------------------
1 | {CompositeDisposable} = require 'event-kit'
2 |
3 | class PanelContainerElement extends HTMLElement
4 | createdCallback: ->
5 | @subscriptions = new CompositeDisposable
6 |
7 | initialize: (@model) ->
8 | @subscriptions.add @model.onDidAddPanel(@panelAdded.bind(this))
9 | @subscriptions.add @model.onDidRemovePanel(@panelRemoved.bind(this))
10 | @subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
11 | @classList.add(@model.getLocation())
12 | this
13 |
14 | getModel: -> @model
15 |
16 | panelAdded: ({panel, index}) ->
17 | panelElement = atom.views.getView(panel)
18 | panelElement.classList.add(@model.getLocation())
19 | if @model.isModal()
20 | panelElement.classList.add("overlay", "from-top")
21 | else
22 | panelElement.classList.add("tool-panel", "panel-#{@model.getLocation()}")
23 |
24 | if index >= @childNodes.length
25 | @appendChild(panelElement)
26 | else
27 | referenceItem = @childNodes[index]
28 | @insertBefore(panelElement, referenceItem)
29 |
30 | if @model.isModal()
31 | @hideAllPanelsExcept(panel)
32 | @subscriptions.add panel.onDidChangeVisible (visible) =>
33 | @hideAllPanelsExcept(panel) if visible
34 |
35 | panelRemoved: ({panel, index}) ->
36 | @removeChild(atom.views.getView(panel))
37 |
38 | destroyed: ->
39 | @subscriptions.dispose()
40 | @parentNode?.removeChild(this)
41 |
42 | hideAllPanelsExcept: (excludedPanel) ->
43 | for panel in @model.getPanels()
44 | panel.hide() unless panel is excludedPanel
45 | return
46 |
47 | module.exports = PanelContainerElement = document.registerElement 'atom-panel-container', prototype: PanelContainerElement.prototype
48 |
--------------------------------------------------------------------------------
/spec/jasmine-helper.coffee:
--------------------------------------------------------------------------------
1 | fs = require 'fs'
2 |
3 | module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
4 | {$, $$} = require '../src/space-pen-extensions'
5 |
6 | window[key] = value for key, value of require '../vendor/jasmine'
7 |
8 | {TerminalReporter} = require 'jasmine-tagged'
9 |
10 | disableFocusMethods() if process.env.JANKY_SHA1
11 |
12 | TimeReporter = require './time-reporter'
13 | timeReporter = new TimeReporter()
14 |
15 | logStream = fs.openSync(logFile, 'w') if logFile?
16 | log = (str) ->
17 | if logStream?
18 | fs.writeSync(logStream, str)
19 | else
20 | process.stderr.write(str)
21 |
22 | if atom.getLoadSettings().exitWhenDone
23 | reporter = new TerminalReporter
24 | print: (str) ->
25 | log(str)
26 | onComplete: (runner) ->
27 | fs.closeSync(logStream) if logStream?
28 | if process.env.JANKY_SHA1
29 | grim = require 'grim'
30 | grim.logDeprecations() if grim.getDeprecationsLength() > 0
31 | atom.exit(runner.results().failedCount > 0 ? 1 : 0)
32 | else
33 | AtomReporter = require './atom-reporter'
34 | reporter = new AtomReporter()
35 |
36 | require specSuite
37 |
38 | jasmineEnv = jasmine.getEnv()
39 | jasmineEnv.addReporter(reporter)
40 | jasmineEnv.addReporter(timeReporter)
41 | jasmineEnv.setIncludedTags([process.platform])
42 |
43 | $('body').append $$ -> @div id: 'jasmine-content'
44 |
45 | jasmineEnv.execute()
46 |
47 | disableFocusMethods = ->
48 | ['fdescribe', 'ffdescribe', 'fffdescribe', 'fit', 'ffit', 'fffit'].forEach (methodName) ->
49 | focusMethod = window[methodName]
50 | window[methodName] = (description) ->
51 | error = new Error('Focused spec is running on CI')
52 | focusMethod description, -> throw error
53 |
--------------------------------------------------------------------------------
/spec/tokenized-line-spec.coffee:
--------------------------------------------------------------------------------
1 | describe "TokenizedLine", ->
2 | editor = null
3 |
4 | beforeEach ->
5 | waitsForPromise -> atom.packages.activatePackage('language-coffee-script')
6 |
7 | describe "::isOnlyWhitespace()", ->
8 | beforeEach ->
9 | waitsForPromise ->
10 | atom.project.open('coffee.coffee').then (o) -> editor = o
11 |
12 | it "returns true when the line is only whitespace", ->
13 | expect(editor.tokenizedLineForScreenRow(3).isOnlyWhitespace()).toBe true
14 | expect(editor.tokenizedLineForScreenRow(7).isOnlyWhitespace()).toBe true
15 | expect(editor.tokenizedLineForScreenRow(23).isOnlyWhitespace()).toBe true
16 |
17 | it "returns false when the line is not only whitespace", ->
18 | expect(editor.tokenizedLineForScreenRow(0).isOnlyWhitespace()).toBe false
19 | expect(editor.tokenizedLineForScreenRow(2).isOnlyWhitespace()).toBe false
20 |
21 | describe "::getScopeTree()", ->
22 | it "returns a tree whose inner nodes are scopeDescriptor and whose leaf nodes are tokens in those scopeDescriptor", ->
23 | [tokens, tokenIndex] = []
24 |
25 | ensureValidScopeTree = (scopeTree, scopeDescriptor=[]) ->
26 | if scopeTree.children?
27 | for child in scopeTree.children
28 | ensureValidScopeTree(child, scopeDescriptor.concat([scopeTree.scope]))
29 | else
30 | expect(scopeTree).toBe tokens[tokenIndex++]
31 | expect(scopeDescriptor).toEqual scopeTree.scopes
32 |
33 | waitsForPromise ->
34 | atom.project.open('coffee.coffee').then (o) -> editor = o
35 |
36 | runs ->
37 | tokenIndex = 0
38 | tokens = editor.tokenizedLineForScreenRow(1).tokens
39 | scopeTree = editor.tokenizedLineForScreenRow(1).getScopeTree()
40 | ensureValidScopeTree(scopeTree)
41 |
--------------------------------------------------------------------------------
/src/overlay-manager.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | class OverlayManager
3 | constructor: (@container) ->
4 | @overlays = {}
5 |
6 | render: (props) ->
7 | {editor, overlayDecorations, lineHeightInPixels} = props
8 |
9 | existingDecorations = null
10 | for markerId, {headPixelPosition, tailPixelPosition, decorations} of overlayDecorations
11 | for decoration in decorations
12 | pixelPosition =
13 | if decoration.position is 'tail' then tailPixelPosition else headPixelPosition
14 |
15 | @renderOverlay(editor, decoration, pixelPosition, lineHeightInPixels)
16 |
17 | existingDecorations ?= {}
18 | existingDecorations[decoration.id] = true
19 |
20 | for id, overlay of @overlays
21 | unless existingDecorations? and id of existingDecorations
22 | @container.removeChild(overlay)
23 | delete @overlays[id]
24 |
25 | return
26 |
27 | renderOverlay: (editor, decoration, pixelPosition, lineHeightInPixels) ->
28 | item = atom.views.getView(decoration.item)
29 | unless overlay = @overlays[decoration.id]
30 | overlay = @overlays[decoration.id] = document.createElement('atom-overlay')
31 | overlay.appendChild(item)
32 | @container.appendChild(overlay)
33 |
34 | itemWidth = item.offsetWidth
35 | itemHeight = item.offsetHeight
36 |
37 | left = pixelPosition.left
38 | if left + itemWidth - editor.getScrollLeft() > editor.getWidth() and left - itemWidth >= editor.getScrollLeft()
39 | left -= itemWidth
40 |
41 | top = pixelPosition.top + lineHeightInPixels
42 | if top + itemHeight - editor.getScrollTop() > editor.getHeight() and top - itemHeight - lineHeightInPixels >= editor.getScrollTop()
43 | top -= itemHeight + lineHeightInPixels
44 |
45 | overlay.style.top = top + 'px'
46 | overlay.style.left = left + 'px'
47 |
--------------------------------------------------------------------------------
/benchmark/browser-process-startup.coffee:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env coffee
2 |
3 | {spawn, exec} = require 'child_process'
4 | fs = require 'fs'
5 | os = require 'os'
6 | path = require 'path'
7 | _ = require 'underscore-plus'
8 | temp = require 'temp'
9 |
10 | directoryToOpen = temp.mkdirSync('browser-process-startup-')
11 | socketPath = path.join(os.tmpdir(), 'atom.sock')
12 | numberOfRuns = 10
13 |
14 | deleteSocketFile = ->
15 | try
16 | fs.unlinkSync(socketPath) if fs.existsSync(socketPath)
17 | catch error
18 | console.error(error)
19 |
20 | launchAtom = (callback) ->
21 | deleteSocketFile()
22 |
23 | cmd = 'atom'
24 | args = ['--safe', '--new-window', '--foreground', directoryToOpen]
25 | atomProcess = spawn(cmd, args)
26 |
27 | output = ''
28 | startupTimes = []
29 | dataListener = (data) ->
30 | output += data
31 | if match = /App load time: (\d+)/.exec(output)
32 | startupTime = parseInt(match[1])
33 | atomProcess.stderr.removeListener 'data', dataListener
34 | atomProcess.kill()
35 | exec 'pkill -9 Atom', (error) ->
36 | console.error(error) if error?
37 | callback(startupTime)
38 |
39 | atomProcess.stderr.on 'data', dataListener
40 |
41 | startupTimes = []
42 | collector = (startupTime) ->
43 | startupTimes.push(startupTime)
44 | if startupTimes.length < numberOfRuns
45 | launchAtom(collector)
46 | else
47 | maxTime = _.max(startupTimes)
48 | minTime = _.min(startupTimes)
49 | totalTime = startupTimes.reduce (previousValue=0, currentValue) -> previousValue + currentValue
50 | console.log "Startup Runs: #{startupTimes.length}"
51 | console.log "First run time: #{startupTimes[0]}ms"
52 | console.log "Max time: #{maxTime}ms"
53 | console.log "Min time: #{minTime}ms"
54 | console.log "Average time: #{Math.round(totalTime/startupTimes.length)}ms"
55 |
56 | launchAtom(collector)
57 |
--------------------------------------------------------------------------------
/docs/upgrading/upgrading-your-syntax-theme.md:
--------------------------------------------------------------------------------
1 | # Upgrading Your Syntax Theme
2 |
3 | Text editor content is now rendered in the shadow DOM, which shields it from being styled by global style sheets to protect against accidental style pollution. For more background on the shadow DOM, check out the [Shadow DOM 101][shadow-dom-101] on HTML 5 Rocks.
4 |
5 | Syntax themes are specifically intended to style only text editor content, so they are automatically loaded directly into the text editor's shadow DOM when it is enabled. This happens automatically when the the theme's `package.json` contains a `theme: "syntax"` declaration, so you don't need to change anything to target the appropriate context.
6 |
7 | When theme style sheets are loaded into the text editor's shadow DOM, selectors intended to target the editor from the *outside* no longer make sense. Styles targeting the `.editor` and `.editor-colors` classes instead need to target the `:host` pseudo-element, which matches against the containing `atom-text-editor` node. Check out the [Shadow DOM 201][host-pseudo-element] article for more information about the `:host` pseudo-element.
8 |
9 | Here's an example from Atom's light syntax theme. Note that the `atom-text-editor` selector intended to target the editor from the outside has been retained to allow the theme to keep working during the transition phase when it is possible to disable the shadow DOM.
10 |
11 | ```css
12 | atom-text-editor, :host { /* :host added */
13 | background-color: @syntax-background-color;
14 | color: @syntax-text-color;
15 |
16 | .invisible-character {
17 | color: @syntax-invisible-character-color;
18 | }
19 | /* more nested selectors... */
20 | }
21 | ```
22 |
23 | [shadow-dom-101]: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom
24 | [host-pseudo-element]: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201#toc-style-host
25 |
--------------------------------------------------------------------------------
/docs/converting-a-text-mate-bundle.md:
--------------------------------------------------------------------------------
1 | ## Converting a TextMate Bundle
2 |
3 | This guide will show you how to convert a [TextMate][TextMate] bundle to an
4 | Atom package.
5 |
6 | Converting a TextMate bundle will allow you to use its editor preferences,
7 | snippets, and colorization inside Atom.
8 |
9 | ### Install apm
10 |
11 | The `apm` command line utility that ships with Atom supports converting
12 | a TextMate bundle to an Atom package.
13 |
14 | Check that you have `apm` installed by running the following command in your
15 | terminal:
16 |
17 | ```sh
18 | apm help init
19 | ```
20 |
21 | You should see a message print out with details about the `apm init` command.
22 |
23 | If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
24 | to install the `apm` and `atom` commands.
25 |
26 | ### Convert the Package
27 |
28 | Let's convert the TextMate bundle for the [R][R] programming language. You can find other existing TextMate bundles [here][TextMateOrg].
29 |
30 | You can convert the R bundle with the following command:
31 |
32 | ```sh
33 | apm init --package ~/.atom/packages/language-r --convert https://github.com/textmate/r.tmbundle
34 | ```
35 |
36 | You can now browse to `~/.atom/packages/language-r` to see the converted bundle.
37 |
38 | :tada: Your new package is now ready to use, launch Atom and open a `.r` file in
39 | the editor to see it in action!
40 |
41 | ### Further Reading
42 |
43 | * Check out [Publishing a Package](publishing-a-package.html) for more information
44 | on publishing the package you just created to [atom.io][atomio].
45 |
46 | [atomio]: https://atom.io
47 | [CSS]: https://en.wikipedia.org/wiki/Cascading_Style_Sheets
48 | [Less]: http://lesscss.org
49 | [plist]: https://en.wikipedia.org/wiki/Property_list
50 | [R]: https://en.wikipedia.org/wiki/R_(programming_language)
51 | [TextMate]: http://macromates.com
52 | [TextMateOrg]: https://github.com/textmate
53 |
--------------------------------------------------------------------------------
/src/browser/auto-updater-win32.coffee:
--------------------------------------------------------------------------------
1 | {EventEmitter} = require 'events'
2 | _ = require 'underscore-plus'
3 | SquirrelUpdate = require './squirrel-update'
4 |
5 | class AutoUpdater
6 | _.extend @prototype, EventEmitter.prototype
7 |
8 | setFeedUrl: (@updateUrl) ->
9 |
10 | quitAndInstall: ->
11 | if SquirrelUpdate.existsSync()
12 | SquirrelUpdate.restartAtom(require('app'))
13 | else
14 | require('auto-updater').quitAndInstall()
15 |
16 | downloadUpdate: (callback) ->
17 | SquirrelUpdate.spawn ['--download', @updateUrl], (error, stdout) ->
18 | return callback(error) if error?
19 |
20 | try
21 | # Last line of output is the JSON details about the releases
22 | json = stdout.trim().split('\n').pop()
23 | update = JSON.parse(json)?.releasesToApply?.pop?()
24 | catch error
25 | error.stdout = stdout
26 | return callback(error)
27 |
28 | callback(null, update)
29 |
30 | installUpdate: (callback) ->
31 | SquirrelUpdate.spawn(['--update', @updateUrl], callback)
32 |
33 | supportsUpdates: ->
34 | SquirrelUpdate.existsSync()
35 |
36 | checkForUpdates: ->
37 | throw new Error('Update URL is not set') unless @updateUrl
38 |
39 | @emit 'checking-for-update'
40 |
41 | unless SquirrelUpdate.existsSync()
42 | @emit 'update-not-available'
43 | return
44 |
45 | @downloadUpdate (error, update) =>
46 | if error?
47 | @emit 'update-not-available'
48 | return
49 |
50 | unless update?
51 | @emit 'update-not-available'
52 | return
53 |
54 | @installUpdate (error) =>
55 | if error?
56 | @emit 'update-not-available'
57 | return
58 |
59 | @emit 'update-available'
60 | @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), 'https://atom.io', => @quitAndInstall()
61 |
62 | module.exports = new AutoUpdater()
63 |
--------------------------------------------------------------------------------
/src/panel-container.coffee:
--------------------------------------------------------------------------------
1 | {Emitter, CompositeDisposable} = require 'event-kit'
2 |
3 | module.exports =
4 | class PanelContainer
5 | constructor: ({@location}={}) ->
6 | @emitter = new Emitter
7 | @subscriptions = new CompositeDisposable
8 | @panels = []
9 |
10 | destroy: ->
11 | panel.destroy() for panel in @getPanels()
12 | @subscriptions.dispose()
13 | @emitter.emit 'did-destroy', this
14 | @emitter.dispose()
15 |
16 | ###
17 | Section: Event Subscription
18 | ###
19 |
20 | onDidAddPanel: (callback) ->
21 | @emitter.on 'did-add-panel', callback
22 |
23 | onDidRemovePanel: (callback) ->
24 | @emitter.on 'did-remove-panel', callback
25 |
26 | onDidDestroy: (callback) ->
27 | @emitter.on 'did-destroy', callback
28 |
29 | ###
30 | Section: Panels
31 | ###
32 |
33 | getLocation: -> @location
34 |
35 | isModal: -> @location is 'modal'
36 |
37 | getPanels: -> @panels
38 |
39 | addPanel: (panel) ->
40 | @subscriptions.add panel.onDidDestroy(@panelDestroyed.bind(this))
41 |
42 | index = @getPanelIndex(panel)
43 | if index is @panels.length
44 | @panels.push(panel)
45 | else
46 | @panels.splice(index, 0, panel)
47 |
48 | @emitter.emit 'did-add-panel', {panel, index}
49 | panel
50 |
51 | panelForItem: (item) ->
52 | for panel in @panels
53 | return panel if panel.getItem() is item
54 | null
55 |
56 | panelDestroyed: (panel) ->
57 | index = @panels.indexOf(panel)
58 | if index > -1
59 | @panels.splice(index, 1)
60 | @emitter.emit 'did-remove-panel', {panel, index}
61 |
62 | getPanelIndex: (panel) ->
63 | priority = panel.getPriority()
64 | if @location in ['bottom', 'right']
65 | for p, i in @panels by -1
66 | return i + 1 if priority < p.getPriority()
67 | 0
68 | else
69 | for p, i in @panels
70 | return i if priority < p.getPriority()
71 | @panels.length
72 |
--------------------------------------------------------------------------------
/spec/notification-spec.coffee:
--------------------------------------------------------------------------------
1 | Notification = require '../src/notification'
2 |
3 | describe "Notification", ->
4 | [notification] = []
5 |
6 | describe "::getTimestamp()", ->
7 | it "returns a Date object", ->
8 | notification = new Notification('error', 'message!')
9 | expect(notification.getTimestamp() instanceof Date).toBe true
10 |
11 | describe "::getIcon()", ->
12 | it "returns a default when no icon specified", ->
13 | notification = new Notification('error', 'message!')
14 | expect(notification.getIcon()).toBe 'flame'
15 |
16 | it "returns the icon specified", ->
17 | notification = new Notification('error', 'message!', icon: 'my-icon')
18 | expect(notification.getIcon()).toBe 'my-icon'
19 |
20 | describe "dismissing notifications", ->
21 | describe "when the notfication is dismissable", ->
22 | it "calls a callback when the notification is dismissed", ->
23 | dismissedSpy = jasmine.createSpy()
24 | notification = new Notification('error', 'message', dismissable: true)
25 | notification.onDidDismiss dismissedSpy
26 |
27 | expect(notification.isDismissable()).toBe true
28 | expect(notification.isDismissed()).toBe false
29 |
30 | notification.dismiss()
31 |
32 | expect(dismissedSpy).toHaveBeenCalled()
33 | expect(notification.isDismissed()).toBe true
34 |
35 | describe "when the notfication is not dismissable", ->
36 | it "does nothing when ::dismiss() is called", ->
37 | dismissedSpy = jasmine.createSpy()
38 | notification = new Notification('error', 'message')
39 | notification.onDidDismiss dismissedSpy
40 |
41 | expect(notification.isDismissable()).toBe false
42 | expect(notification.isDismissed()).toBe true
43 |
44 | notification.dismiss()
45 |
46 | expect(dismissedSpy).not.toHaveBeenCalled()
47 | expect(notification.isDismissed()).toBe true
48 |
--------------------------------------------------------------------------------
/src/menu-helpers.coffee:
--------------------------------------------------------------------------------
1 | _ = require 'underscore-plus'
2 |
3 | ItemSpecificities = new WeakMap
4 |
5 | merge = (menu, item, itemSpecificity=Infinity) ->
6 | item = cloneMenuItem(item)
7 | ItemSpecificities.set(item, itemSpecificity) if itemSpecificity
8 | matchingItemIndex = findMatchingItemIndex(menu, item)
9 | matchingItem = menu[matchingItemIndex] unless matchingItemIndex is - 1
10 |
11 | if matchingItem?
12 | if item.submenu?
13 | merge(matchingItem.submenu, submenuItem, itemSpecificity) for submenuItem in item.submenu
14 | else if itemSpecificity
15 | unless itemSpecificity < ItemSpecificities.get(matchingItem)
16 | menu[matchingItemIndex] = item
17 | else unless item.type is 'separator' and _.last(menu)?.type is 'separator'
18 | menu.push(item)
19 |
20 | unmerge = (menu, item) ->
21 | matchingItemIndex = findMatchingItemIndex(menu, item)
22 | matchingItem = menu[matchingItemIndex] unless matchingItemIndex is - 1
23 |
24 | if matchingItem?
25 | if item.submenu?
26 | unmerge(matchingItem.submenu, submenuItem) for submenuItem in item.submenu
27 |
28 | unless matchingItem.submenu?.length > 0
29 | menu.splice(matchingItemIndex, 1)
30 |
31 | findMatchingItemIndex = (menu, {type, label, submenu}) ->
32 | return -1 if type is 'separator'
33 | for item, index in menu
34 | if normalizeLabel(item.label) is normalizeLabel(label) and item.submenu? is submenu?
35 | return index
36 | -1
37 |
38 | normalizeLabel = (label) ->
39 | return undefined unless label?
40 |
41 | if process.platform is 'darwin'
42 | label
43 | else
44 | label.replace(/\&/g, '')
45 |
46 | cloneMenuItem = (item) ->
47 | item = _.pick(item, 'type', 'label', 'enabled', 'visible', 'command', 'submenu', 'commandDetail')
48 | if item.submenu?
49 | item.submenu = item.submenu.map (submenuItem) -> cloneMenuItem(submenuItem)
50 | item
51 |
52 | module.exports = {merge, unmerge, normalizeLabel, cloneMenuItem}
53 |
--------------------------------------------------------------------------------
/spec/spec-suite.coffee:
--------------------------------------------------------------------------------
1 | _ = require 'underscore-plus'
2 | fs = require 'fs-plus'
3 | path = require 'path'
4 | require './spec-helper'
5 |
6 | requireSpecs = (specDirectory, specType) ->
7 | for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.(coffee|js)$/.test specFilePath
8 | require specFilePath
9 |
10 | # Set spec directory on spec for setting up the project in spec-helper
11 | setSpecDirectory(specDirectory)
12 |
13 | setSpecField = (name, value) ->
14 | specs = jasmine.getEnv().currentRunner().specs()
15 | return if specs.length is 0
16 | for index in [specs.length-1..0]
17 | break if specs[index][name]?
18 | specs[index][name] = value
19 |
20 | setSpecType = (specType) ->
21 | setSpecField('specType', specType)
22 |
23 | setSpecDirectory = (specDirectory) ->
24 | setSpecField('specDirectory', specDirectory)
25 |
26 | runAllSpecs = ->
27 | {resourcePath} = atom.getLoadSettings()
28 |
29 | requireSpecs(path.join(resourcePath, 'spec'))
30 | setSpecType('core')
31 |
32 | fixturesPackagesPath = path.join(__dirname, 'fixtures', 'packages')
33 | packagePaths = atom.packages.getAvailablePackageNames().map (packageName) ->
34 | atom.packages.resolvePackagePath(packageName)
35 | packagePaths = _.groupBy packagePaths, (packagePath) ->
36 | if packagePath.indexOf("#{fixturesPackagesPath}#{path.sep}") is 0
37 | 'fixtures'
38 | else if packagePath.indexOf("#{resourcePath}#{path.sep}") is 0
39 | 'bundled'
40 | else
41 | 'user'
42 |
43 | # Run bundled package specs
44 | requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.bundled ? []
45 | setSpecType('bundled')
46 |
47 | # Run user package specs
48 | requireSpecs(path.join(packagePath, 'spec')) for packagePath in packagePaths.user ? []
49 | setSpecType('user')
50 |
51 | if specDirectory = atom.getLoadSettings().specDirectory
52 | requireSpecs(specDirectory)
53 | setSpecType('user')
54 | else
55 | runAllSpecs()
56 |
--------------------------------------------------------------------------------
/script/cibuild:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var cp = require('./utils/child-process-wrapper.js');
3 | var fs = require('fs');
4 | var path = require('path');
5 |
6 | process.chdir(path.dirname(__dirname));
7 |
8 | var homeDir = process.platform == 'win32' ? process.env.USERPROFILE : process.env.HOME;
9 |
10 | function loadEnvironmentVariables(filePath) {
11 | try {
12 | var lines = fs.readFileSync(filePath, 'utf8').trim().split('\n');
13 | for (i in lines) {
14 | var parts = lines[i].split('=');
15 | var key = parts[0].trim();
16 | var value = parts[1].trim().substr(1, parts[1].length - 2);
17 | process.env[key] = value;
18 | }
19 | } catch(error) {
20 | console.error("Failed to load environment variables: " + filePath, error.code);
21 | }
22 | }
23 |
24 | function readEnvironmentVariables() {
25 | if (process.platform === 'win32')
26 | loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials'));
27 | else if (process.platform === 'darwin') {
28 | loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials');
29 | loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain');
30 | }
31 | }
32 |
33 | readEnvironmentVariables();
34 | cp.safeExec.bind(global, 'npm install npm', {cwd: path.resolve(__dirname, '..', 'build')}, function() {
35 | cp.safeExec.bind(global, 'node script/bootstrap', function(error) {
36 | if (error)
37 | process.exit(1);
38 | require('fs-plus').removeSync.bind(global, path.join(homeDir, '.atom'))
39 | var async = require('async');
40 | var gruntPath = path.join('build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
41 | var tasks = [
42 | cp.safeExec.bind(global, 'git clean -dff'),
43 | cp.safeExec.bind(global, gruntPath + ' ci --gruntfile build/Gruntfile.coffee --stack --no-color'),
44 | ]
45 | async.series(tasks, function(error) {
46 | process.exit(error ? 1 : 0);
47 | });
48 | })();
49 | })();
50 |
--------------------------------------------------------------------------------
/spec/deserializer-manager-spec.coffee:
--------------------------------------------------------------------------------
1 | DeserializerManager = require '../src/deserializer-manager'
2 |
3 | describe "DeserializerManager", ->
4 | manager = null
5 |
6 | class Foo
7 | @deserialize: ({name}) -> new Foo(name)
8 | constructor: (@name) ->
9 |
10 | beforeEach ->
11 | manager = new DeserializerManager
12 |
13 | describe "::add(deserializer)", ->
14 | it "returns a disposable that can be used to remove the manager", ->
15 | disposable = manager.add(Foo)
16 | expect(manager.deserialize({deserializer: 'Foo', name: 'Bar'})).toBeDefined()
17 | disposable.dispose()
18 | spyOn(console, 'warn')
19 | expect(manager.deserialize({deserializer: 'Foo', name: 'Bar'})).toBeUndefined()
20 |
21 | describe "::deserialize(state)", ->
22 | beforeEach ->
23 | manager.add(Foo)
24 |
25 | it "calls deserialize on the manager for the given state object, or returns undefined if one can't be found", ->
26 | spyOn(console, 'warn')
27 | object = manager.deserialize({deserializer: 'Foo', name: 'Bar'})
28 | expect(object.name).toBe 'Bar'
29 | expect(manager.deserialize({deserializer: 'Bogus'})).toBeUndefined()
30 |
31 | describe "when the manager has a version", ->
32 | beforeEach ->
33 | Foo.version = 2
34 |
35 | describe "when the deserialized state has a matching version", ->
36 | it "attempts to deserialize the state", ->
37 | object = manager.deserialize({deserializer: 'Foo', version: 2, name: 'Bar'})
38 | expect(object.name).toBe 'Bar'
39 |
40 | describe "when the deserialized state has a non-matching version", ->
41 | it "returns undefined", ->
42 | expect(manager.deserialize({deserializer: 'Foo', version: 3, name: 'Bar'})).toBeUndefined()
43 | expect(manager.deserialize({deserializer: 'Foo', version: 1, name: 'Bar'})).toBeUndefined()
44 | expect(manager.deserialize({deserializer: 'Foo', name: 'Bar'})).toBeUndefined()
45 |
--------------------------------------------------------------------------------
/spec/menu-manager-spec.coffee:
--------------------------------------------------------------------------------
1 | MenuManager = require '../src/menu-manager'
2 |
3 | describe "MenuManager", ->
4 | menu = null
5 |
6 | beforeEach ->
7 | menu = new MenuManager(resourcePath: atom.getLoadSettings().resourcePath)
8 |
9 | describe "::add(items)", ->
10 | it "can add new menus that can be removed with the returned disposable", ->
11 | disposable = menu.add [{label: "A", submenu: [{label: "B", command: "b"}]}]
12 | expect(menu.template).toEqual [{label: "A", submenu: [{label: "B", command: "b"}]}]
13 | disposable.dispose()
14 | expect(menu.template).toEqual []
15 |
16 | it "can add submenu items to existing menus that can be removed with the returned disposable", ->
17 | disposable1 = menu.add [{label: "A", submenu: [{label: "B", command: "b"}]}]
18 | disposable2 = menu.add [{label: "A", submenu: [{label: "C", submenu: [{label: "D", command: 'd'}]}]}]
19 | disposable3 = menu.add [{label: "A", submenu: [{label: "C", submenu: [{label: "E", command: 'e'}]}]}]
20 |
21 | expect(menu.template).toEqual [{
22 | label: "A",
23 | submenu: [
24 | {label: "B", command: "b"},
25 | {label: "C", submenu: [{label: 'D', command: 'd'}, {label: 'E', command: 'e'}]}
26 | ]
27 | }]
28 |
29 | disposable3.dispose()
30 | expect(menu.template).toEqual [{
31 | label: "A",
32 | submenu: [
33 | {label: "B", command: "b"},
34 | {label: "C", submenu: [{label: 'D', command: 'd'}]}
35 | ]
36 | }]
37 |
38 | disposable2.dispose()
39 | expect(menu.template).toEqual [{label: "A", submenu: [{label: "B", command: "b"}]}]
40 |
41 | disposable1.dispose()
42 | expect(menu.template).toEqual []
43 |
44 | it "does not add duplicate labels to the same menu", ->
45 | originalItemCount = menu.template.length
46 | menu.add [{label: "A", submenu: [{label: "B", command: "b"}]}]
47 | menu.add [{label: "A", submenu: [{label: "B", command: "b"}]}]
48 | expect(menu.template[originalItemCount]).toEqual {label: "A", submenu: [{label: "B", command: "b"}]}
49 |
--------------------------------------------------------------------------------
/docs/contributing-to-packages.md:
--------------------------------------------------------------------------------
1 | # Contributing to Official Atom Packages
2 |
3 | If you think you know which package is causing the issue you are reporting, feel
4 | free to open up the issue in that specific repository instead. When in doubt
5 | just open the issue here but be aware that it may get closed here and reopened
6 | in the proper package's repository.
7 |
8 | ## Hacking on Packages
9 |
10 | ### Cloning
11 |
12 | The first step is creating your own clone.
13 |
14 | For example, if you want to make changes to the `tree-view` package, fork the repo on your github account, then clone it:
15 |
16 | ```
17 | > git clone git@github.com:your-username/tree-view.git
18 | ```
19 |
20 | Next install all the dependencies:
21 |
22 | ```
23 | > cd tree-view
24 | > apm install
25 | Installing modules ✓
26 | ```
27 |
28 | Now you can link it to development mode so when you run an Atom window with `atom --dev`, you will use your fork instead of the built in package:
29 |
30 | ```
31 | > apm link -d
32 | ```
33 |
34 | ### Running in Development Mode
35 |
36 | Editing a package in Atom is a bit of a circular experience: you're using Atom
37 | to modify itself. What happens if you temporarily break something? You don't
38 | want the version of Atom you're using to edit to become useless in the process.
39 | For this reason, you'll only want to load packages in **development mode** while
40 | you are working on them. You'll perform your editing in **stable mode**, only
41 | switching to development mode to test your changes.
42 |
43 | To open a development mode window, use the "Application: Open Dev" command,
44 | which is normally bound to `cmd-shift-o`. You can also run dev mode from the
45 | command line with `atom --dev`.
46 |
47 | To load your package in development mode, create a symlink to it in
48 | `~/.atom/dev/packages`. This occurs automatically when you clone the package
49 | with `apm develop`. You can also run `apm link --dev` and `apm unlink --dev`
50 | from the package directory to create and remove dev-mode symlinks.
51 |
52 | ### Installing Dependencies
53 |
54 | You'll want to keep dependencies up to date by running `apm update` after pulling any upstream changes.
55 |
--------------------------------------------------------------------------------
/static/buttons.less:
--------------------------------------------------------------------------------
1 | @import "ui-variables";
2 |
3 | .btn {
4 | color: @text-color;
5 | border-radius: @component-border-radius;
6 | border: none;
7 | text-shadow: none;
8 |
9 | height: @component-line-height + 2px;
10 | line-height: @component-line-height;
11 |
12 | padding: 0 @component-padding;
13 | font-size: @font-size;
14 | z-index: 0;
15 |
16 | background-color: @button-background-color;
17 | &:hover {
18 | background-color: @button-background-color-hover;
19 | }
20 | &.selected,
21 | &.selected:hover {
22 | // we want the selected button to behave like the :hover button; it's on top of the other buttons.
23 | z-index: 1;
24 | background-color: @button-background-color-selected;
25 | }
26 | }
27 |
28 | .btn.btn-xs,
29 | .btn-group-xs > .btn {
30 | padding: @component-padding/4 @component-padding/2;
31 | font-size: @font-size - 2px;
32 | height: auto;
33 | line-height: 1.3em;
34 | }
35 | .btn.btn-sm,
36 | .btn-group-sm > .btn {
37 | padding: @component-padding/4 @component-padding/2;
38 | height: auto;
39 | line-height: 1.3em;
40 | }
41 | .btn.btn-lg,
42 | .btn-group-lg > .btn {
43 | font-size: @font-size + 2px;
44 | padding: @component-padding - 2px @component-padding + 2px;
45 | height: auto;
46 | line-height: 1.3em;
47 | }
48 |
49 | .btn-group > .btn {
50 | border-left: 1px solid @button-border-color;
51 | border-right: 1px solid @button-border-color;
52 | }
53 | .btn-group > .btn:first-child {
54 | border-left: none;
55 | border-top-left-radius: @component-border-radius;
56 | border-bottom-left-radius: @component-border-radius;
57 | }
58 | .btn-group > .btn:last-child,
59 | .btn-group > .btn.selected:last-child,
60 | .btn-group > .dropdown-toggle {
61 | border-right: none;
62 | border-top-right-radius: @component-border-radius;
63 | border-bottom-right-radius: @component-border-radius;
64 | }
65 |
66 | .btn-toolbar {
67 | > .btn-group + .btn-group, > .btn-group + .btn, > .btn + .btn {
68 | float: none;
69 | display: inline-block;
70 | margin-left: 0;
71 | }
72 | > * {
73 | margin-right: @component-padding / 2;
74 | }
75 | > *:last-child {
76 | margin-right: 0;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/keymaps/base.cson:
--------------------------------------------------------------------------------
1 | 'atom-text-editor':
2 | # Platform Bindings
3 | 'home': 'editor:move-to-first-character-of-line'
4 | 'end': 'editor:move-to-end-of-screen-line'
5 | 'shift-home': 'editor:select-to-first-character-of-line'
6 | 'shift-end': 'editor:select-to-end-of-line'
7 |
8 | 'atom-text-editor:not([mini])':
9 | # Atom Specific
10 | 'ctrl-C': 'editor:copy-path'
11 |
12 | # Sublime Parity
13 | 'tab': 'editor:indent'
14 | 'enter': 'editor:newline'
15 | 'shift-tab': 'editor:outdent-selected-rows'
16 | 'ctrl-K': 'editor:delete-line'
17 |
18 | '.select-list atom-text-editor[mini]':
19 | 'enter': 'core:confirm'
20 |
21 | '.tool-panel.panel-left, .tool-panel.panel-right':
22 | 'escape': 'tool-panel:unfocus'
23 |
24 | 'atom-text-editor !important, atom-text-editor[mini] !important':
25 | 'escape': 'editor:consolidate-selections'
26 |
27 | # allow standard input fields to work correctly
28 | 'body .native-key-bindings':
29 | 'tab': 'core:focus-next'
30 | 'shift-tab': 'core:focus-previous'
31 | 'enter': 'native!'
32 | 'backspace': 'native!'
33 | 'shift-backspace': 'native!'
34 | 'delete': 'native!'
35 | 'up': 'native!'
36 | 'down': 'native!'
37 | 'shift-up': 'native!'
38 | 'shift-down': 'native!'
39 | 'alt-up': 'native!'
40 | 'alt-down': 'native!'
41 | 'alt-shift-up': 'native!'
42 | 'alt-shift-down': 'native!'
43 | 'cmd-up': 'native!'
44 | 'cmd-down': 'native!'
45 | 'cmd-shift-up': 'native!'
46 | 'cmd-shift-down': 'native!'
47 | 'ctrl-up': 'native!'
48 | 'ctrl-down': 'native!'
49 | 'ctrl-shift-up': 'native!'
50 | 'ctrl-shift-down': 'native!'
51 | 'left': 'native!'
52 | 'right': 'native!'
53 | 'shift-left': 'native!'
54 | 'shift-right': 'native!'
55 | 'alt-left': 'native!'
56 | 'alt-right': 'native!'
57 | 'alt-shift-left': 'native!'
58 | 'alt-shift-right': 'native!'
59 | 'cmd-left': 'native!'
60 | 'cmd-right': 'native!'
61 | 'cmd-shift-left': 'native!'
62 | 'cmd-shift-right': 'native!'
63 | 'ctrl-left': 'native!'
64 | 'ctrl-right': 'native!'
65 | 'ctrl-shift-left': 'native!'
66 | 'ctrl-shift-right': 'native!'
67 | 'ctrl-b': 'native!'
68 | 'ctrl-f': 'native!'
69 | 'ctrl-F': 'native!'
70 | 'ctrl-B': 'native!'
71 | 'ctrl-h': 'native!'
72 | 'ctrl-d': 'native!'
73 |
--------------------------------------------------------------------------------
/src/cursors-component.coffee:
--------------------------------------------------------------------------------
1 | React = require 'react-atom-fork'
2 | {div} = require 'reactionary-atom-fork'
3 | {debounce, toArray, isEqualForProperties, isEqual} = require 'underscore-plus'
4 | SubscriberMixin = require './subscriber-mixin'
5 | CursorComponent = require './cursor-component'
6 |
7 | module.exports =
8 | CursorsComponent = React.createClass
9 | displayName: 'CursorsComponent'
10 | mixins: [SubscriberMixin]
11 |
12 | cursorBlinkIntervalHandle: null
13 |
14 | render: ->
15 | {performedInitialMeasurement, cursorPixelRects, defaultCharWidth} = @props
16 | {blinkOff} = @state
17 |
18 | className = 'cursors'
19 | className += ' blink-off' if blinkOff
20 |
21 | div {className},
22 | if performedInitialMeasurement
23 | for key, pixelRect of cursorPixelRects
24 | CursorComponent({key, pixelRect, defaultCharWidth})
25 |
26 | getInitialState: ->
27 | blinkOff: false
28 |
29 | componentDidMount: ->
30 | @startBlinkingCursors()
31 |
32 | componentWillUnmount: ->
33 | @stopBlinkingCursors()
34 |
35 | shouldComponentUpdate: (newProps, newState) ->
36 | not newState.blinkOff is @state.blinkOff or
37 | not isEqualForProperties(newProps, @props, 'cursorPixelRects', 'scrollTop', 'scrollLeft', 'defaultCharWidth', 'useHardwareAcceleration')
38 |
39 | componentWillUpdate: (newProps) ->
40 | cursorsMoved = @props.cursorPixelRects? and
41 | isEqualForProperties(newProps, @props, 'defaultCharWidth', 'scopedCharacterWidthsChangeCount') and
42 | not isEqual(newProps.cursorPixelRects, @props.cursorPixelRects)
43 |
44 | @pauseCursorBlinking() if cursorsMoved
45 |
46 | startBlinkingCursors: ->
47 | @toggleCursorBlinkHandle = setInterval(@toggleCursorBlink, @props.cursorBlinkPeriod / 2) if @isMounted()
48 |
49 | startBlinkingCursorsAfterDelay: null # Created lazily
50 |
51 | stopBlinkingCursors: ->
52 | clearInterval(@toggleCursorBlinkHandle)
53 |
54 | toggleCursorBlink: ->
55 | @setState(blinkOff: not @state.blinkOff)
56 |
57 | pauseCursorBlinking: ->
58 | @state.blinkOff = false
59 | @stopBlinkingCursors()
60 | @startBlinkingCursorsAfterDelay ?= debounce(@startBlinkingCursors, @props.cursorBlinkResumeDelay)
61 | @startBlinkingCursorsAfterDelay()
62 |
--------------------------------------------------------------------------------
/docs/advanced/configuration.md:
--------------------------------------------------------------------------------
1 | ## Configuration API
2 |
3 | ### Reading Config Settings
4 |
5 | If you are writing a package that you want to make configurable, you'll need to
6 | read config settings via the `atom.config` global. You can read the current
7 | value of a namespaced config key with `atom.config.get`:
8 |
9 | ```coffeescript
10 | # read a value with `config.get`
11 | @showInvisibles() if atom.config.get "editor.showInvisibles"
12 | ```
13 |
14 | Or you can subscribe via `atom.config.observe` to track changes from any view
15 | object.
16 |
17 | ```coffeescript
18 | {View} = require 'space-pen'
19 |
20 | class MyView extends View
21 | attached: ->
22 | @fontSizeObserveSubscription =
23 | atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
24 | @adjustFontSize()
25 |
26 | detached: ->
27 | @fontSizeObserveSubscription.dispose()
28 | ```
29 |
30 | The `atom.config.observe` method will call the given callback immediately with
31 | the current value for the specified key path, and it will also call it in the
32 | future whenever the value of that key path changes. If you only want to invoke
33 | the callback when the next time the value changes, use `atom.config.onDidChange`
34 | instead.
35 |
36 | Subscription methods return *disposable* subscription objects. Note in the
37 | example above how we save the subscription to the `@fontSizeObserveSubscription`
38 | instance variable and dispose of it when the view is detached. To group multiple
39 | subscriptions together, you can add them all to a
40 | [`CompositeDisposable`][composite-disposable] that you dispose when the view is
41 | detached.
42 |
43 | ### Writing Config Settings
44 |
45 | The `atom.config` database is populated on startup from `~/.atom/config.cson`,
46 | but you can programmatically write to it with `atom.config.set`:
47 |
48 | ```coffeescript
49 | # basic key update
50 | atom.config.set("core.showInvisibles", true)
51 | ```
52 |
53 | If you're exposing package configuration via specific key paths, you'll want to
54 | associate them with a schema in your package's main module. Read more about
55 | schemas in the [config API docs][config-api].
56 |
57 | [composite-disposable]: https://atom.io/docs/api/latest/CompositeDisposable
58 | [config-api]: https://atom.io/docs/api/latest/Config
59 |
--------------------------------------------------------------------------------
/spec/time-reporter.coffee:
--------------------------------------------------------------------------------
1 | _ = require 'underscore-plus'
2 |
3 | module.exports =
4 | class TimeReporter extends jasmine.Reporter
5 |
6 | constructor: ->
7 | window.timedSpecs = []
8 | window.timedSuites = {}
9 |
10 | window.logLongestSpec = => @logLongestSpecs(1)
11 | window.logLongestSpecs = (number) => @logLongestSpecs(number)
12 | window.logLongestSuite = => @logLongestSuites(1)
13 | window.logLongestSuites = (number) => @logLongestSuites(number)
14 |
15 | logLongestSuites: (number=10, log) ->
16 | return unless window.timedSuites.length > 0
17 |
18 | log ?= (line) -> console.log(line)
19 | log "Longest running suites:"
20 | suites = _.map(window.timedSuites, (key, value) -> [value, key])
21 | for suite in _.sortBy(suites, (suite) -> -suite[1])[0...number]
22 | time = Math.round(suite[1] / 100) / 10
23 | log " #{suite[0]} (#{time}s)"
24 | undefined
25 |
26 | logLongestSpecs: (number=10, log) ->
27 | return unless window.timedSpecs.length > 0
28 |
29 | log ?= (line) -> console.log(line)
30 | log "Longest running specs:"
31 | for spec in _.sortBy(window.timedSpecs, (spec) -> -spec.time)[0...number]
32 | time = Math.round(spec.time / 100) / 10
33 | log "#{spec.description} (#{time}s)"
34 | undefined
35 |
36 | reportSpecStarting: (spec) ->
37 | stack = [spec.description]
38 | suite = spec.suite
39 | while suite
40 | stack.unshift suite.description
41 | @suite = suite.description
42 | suite = suite.parentSuite
43 |
44 | reducer = (memo, description, index) ->
45 | if index is 0
46 | "#{description}"
47 | else
48 | "#{memo}\n#{_.multiplyString(' ', index)}#{description}"
49 | @description = _.reduce(stack, reducer, '')
50 | @time = Date.now()
51 |
52 | reportSpecResults: (spec) ->
53 | return unless @time? and @description?
54 |
55 | duration = Date.now() - @time
56 |
57 | if duration > 0
58 | window.timedSpecs.push
59 | description: @description
60 | time: duration
61 | fullName: spec.getFullName()
62 |
63 | if timedSuites[@suite]
64 | window.timedSuites[@suite] += duration
65 | else
66 | window.timedSuites[@suite] = duration
67 |
68 | @time = null
69 | @description = null
70 |
--------------------------------------------------------------------------------
/src/keymap-extensions.coffee:
--------------------------------------------------------------------------------
1 | fs = require 'fs-plus'
2 | path = require 'path'
3 | KeymapManager = require 'atom-keymap'
4 | CSON = require 'season'
5 | {jQuery} = require 'space-pen'
6 |
7 | KeymapManager::onDidLoadBundledKeymaps = (callback) ->
8 | @emitter.on 'did-load-bundled-keymaps', callback
9 |
10 | KeymapManager::loadBundledKeymaps = ->
11 | @loadKeymap(path.join(@resourcePath, 'keymaps'))
12 | @emit 'bundled-keymaps-loaded'
13 | @emitter.emit 'did-load-bundled-keymaps'
14 |
15 | KeymapManager::getUserKeymapPath = ->
16 | if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap'))
17 | userKeymapPath
18 | else
19 | path.join(@configDirPath, 'keymap.cson')
20 |
21 | KeymapManager::loadUserKeymap = ->
22 | userKeymapPath = @getUserKeymapPath()
23 | return unless fs.isFileSync(userKeymapPath)
24 |
25 | try
26 | @loadKeymap(userKeymapPath, watch: true, suppressErrors: true)
27 | catch error
28 | if error.message.indexOf('Unable to watch path') > -1
29 | message = """
30 | Unable to watch path: `#{path.basename(userKeymapPath)}`. Make sure you
31 | have permission to read `#{userKeymapPath}`.
32 |
33 | On linux there are currently problems with watch sizes. See
34 | [this document][watches] for more info.
35 | [watches]:https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#typeerror-unable-to-watch-path
36 | """
37 | atom.notifications.addError(message, {dismissable: true})
38 | else
39 | detail = error.path
40 | stack = error.stack
41 | atom.notifications.addFatalError(error.message, {detail, stack, dismissable: true})
42 |
43 | KeymapManager::subscribeToFileReadFailure = ->
44 | @onDidFailToReadFile (error) =>
45 | userKeymapPath = @getUserKeymapPath()
46 | message = "Failed to load `#{userKeymapPath}`"
47 |
48 | detail = if error.location?
49 | error.stack
50 | else
51 | error.message
52 |
53 | atom.notifications.addError(message, {detail: detail, dismissable: true})
54 |
55 | # This enables command handlers registered via jQuery to call
56 | # `.abortKeyBinding()` on the `jQuery.Event` object passed to the handler.
57 | jQuery.Event::abortKeyBinding = ->
58 | @originalEvent?.abortKeyBinding?()
59 |
60 | module.exports = KeymapManager
61 |
--------------------------------------------------------------------------------
/src/deserializer-manager.coffee:
--------------------------------------------------------------------------------
1 | {Disposable} = require 'event-kit'
2 | Grim = require 'grim'
3 |
4 | # Extended: Manages the deserializers used for serialized state
5 | #
6 | # An instance of this class is always available as the `atom.deserializers`
7 | # global.
8 | #
9 | # ## Examples
10 | #
11 | # ```coffee
12 | # class MyPackageView extends View
13 | # atom.deserializers.add(this)
14 | #
15 | # @deserialize: (state) ->
16 | # new MyPackageView(state)
17 | #
18 | # constructor: (@state) ->
19 | #
20 | # serialize: ->
21 | # @state
22 | # ```
23 | module.exports =
24 | class DeserializerManager
25 | constructor: ->
26 | @deserializers = {}
27 |
28 | # Public: Register the given class(es) as deserializers.
29 | #
30 | # * `deserializers` One or more deserializers to register. A deserializer can
31 | # be any object with a `.name` property and a `.deserialize()` method. A
32 | # common approach is to register a *constructor* as the deserializer for its
33 | # instances by adding a `.deserialize()` class method.
34 | add: (deserializers...) ->
35 | @deserializers[deserializer.name] = deserializer for deserializer in deserializers
36 | new Disposable =>
37 | delete @deserializers[deserializer.name] for deserializer in deserializers
38 |
39 | remove: (classes...) ->
40 | Grim.deprecate("Call .dispose() on the Disposable return from ::add instead")
41 | delete @deserializers[name] for {name} in classes
42 |
43 | # Public: Deserialize the state and params.
44 | #
45 | # * `state` The state {Object} to deserialize.
46 | # * `params` The params {Object} to pass as the second arguments to the
47 | # deserialize method of the deserializer.
48 | deserialize: (state, params) ->
49 | return unless state?
50 |
51 | if deserializer = @get(state)
52 | stateVersion = state.get?('version') ? state.version
53 | return if deserializer.version? and deserializer.version isnt stateVersion
54 | deserializer.deserialize(state, params)
55 | else
56 | console.warn "No deserializer found for", state
57 |
58 | # Get the deserializer for the state.
59 | #
60 | # * `state` The state {Object} being deserialized.
61 | get: (state) ->
62 | return unless state?
63 |
64 | name = state.get?('deserializer') ? state.deserializer
65 | @deserializers[name]
66 |
--------------------------------------------------------------------------------
/spec/notification-manager-spec.coffee:
--------------------------------------------------------------------------------
1 | NotificationManager = require '../src/notification-manager'
2 |
3 | describe "NotificationManager", ->
4 | [manager] = []
5 |
6 | beforeEach ->
7 | manager = new NotificationManager
8 |
9 | describe "the atom global", ->
10 | it "has a notifications instance", ->
11 | expect(atom.notifications instanceof NotificationManager).toBe true
12 |
13 | describe "adding events", ->
14 | addSpy = null
15 |
16 | beforeEach ->
17 | addSpy = jasmine.createSpy()
18 | manager.onDidAddNotification(addSpy)
19 |
20 | it "emits an event when a notification has been added", ->
21 | manager.add('error', 'Some error!', icon: 'someIcon')
22 | expect(addSpy).toHaveBeenCalled()
23 |
24 | notification = addSpy.mostRecentCall.args[0]
25 | expect(notification.getType()).toBe 'error'
26 | expect(notification.getMessage()).toBe 'Some error!'
27 | expect(notification.getIcon()).toBe 'someIcon'
28 |
29 | it "emits a fatal error ::addFatalError has been called", ->
30 | manager.addFatalError('Some error!', icon: 'someIcon')
31 | expect(addSpy).toHaveBeenCalled()
32 | notification = addSpy.mostRecentCall.args[0]
33 | expect(notification.getType()).toBe 'fatal'
34 |
35 | it "emits an error ::addError has been called", ->
36 | manager.addError('Some error!', icon: 'someIcon')
37 | expect(addSpy).toHaveBeenCalled()
38 | notification = addSpy.mostRecentCall.args[0]
39 | expect(notification.getType()).toBe 'error'
40 |
41 | it "emits a warning notification ::addWarning has been called", ->
42 | manager.addWarning('Something!', icon: 'someIcon')
43 | expect(addSpy).toHaveBeenCalled()
44 | notification = addSpy.mostRecentCall.args[0]
45 | expect(notification.getType()).toBe 'warning'
46 |
47 | it "emits an info notification ::addInfo has been called", ->
48 | manager.addInfo('Something!', icon: 'someIcon')
49 | expect(addSpy).toHaveBeenCalled()
50 | notification = addSpy.mostRecentCall.args[0]
51 | expect(notification.getType()).toBe 'info'
52 |
53 | it "emits a success notification ::addSuccess has been called", ->
54 | manager.addSuccess('Something!', icon: 'someIcon')
55 | expect(addSpy).toHaveBeenCalled()
56 | notification = addSpy.mostRecentCall.args[0]
57 | expect(notification.getType()).toBe 'success'
58 |
--------------------------------------------------------------------------------
/spec/panel-element-spec.coffee:
--------------------------------------------------------------------------------
1 | Panel = require '../src/panel'
2 | PanelElement = require '../src/panel-element'
3 |
4 | describe "PanelElement", ->
5 | [jasmineContent, element, panel] = []
6 |
7 | class TestPanelItem
8 | constructior: ->
9 |
10 | class TestPanelItemElement extends HTMLElement
11 | createdCallback: ->
12 | @classList.add('test-root')
13 | initialize: (@model) ->
14 | this
15 |
16 | TestPanelItemElement = document.registerElement 'atom-test-item-element', prototype: TestPanelItemElement.prototype
17 |
18 | beforeEach ->
19 | jasmineContent = document.body.querySelector('#jasmine-content')
20 |
21 | atom.views.addViewProvider Panel, (model) ->
22 | new PanelElement().initialize(model)
23 | atom.views.addViewProvider TestPanelItem, (model) ->
24 | new TestPanelItemElement().initialize(model)
25 |
26 | it 'removes the element when the panel is destroyed', ->
27 | panel = new Panel({item: new TestPanelItem})
28 | element = atom.views.getView(panel)
29 | jasmineContent.appendChild(element)
30 |
31 | expect(element.parentNode).toBe jasmineContent
32 | panel.destroy()
33 | expect(element.parentNode).not.toBe jasmineContent
34 |
35 | describe "changing panel visibility", ->
36 | it 'initially renders panel created with visibile: false', ->
37 | panel = new Panel({visible: false, item: new TestPanelItem})
38 | element = atom.views.getView(panel)
39 | jasmineContent.appendChild(element)
40 |
41 | expect(element.style.display).toBe 'none'
42 |
43 | it 'hides and shows the panel element when Panel::hide() and Panel::show() are called', ->
44 | panel = new Panel({item: new TestPanelItem})
45 | element = atom.views.getView(panel)
46 | jasmineContent.appendChild(element)
47 |
48 | expect(element.style.display).not.toBe 'none'
49 |
50 | panel.hide()
51 | expect(element.style.display).toBe 'none'
52 |
53 | panel.show()
54 | expect(element.style.display).not.toBe 'none'
55 |
56 | describe "when a class name is specified", ->
57 | it 'initially renders panel created with visibile: false', ->
58 | panel = new Panel({className: 'some classes', item: new TestPanelItem})
59 | element = atom.views.getView(panel)
60 | jasmineContent.appendChild(element)
61 |
62 | expect(element).toHaveClass 'some'
63 | expect(element).toHaveClass 'classes'
64 |
--------------------------------------------------------------------------------
/src/panel.coffee:
--------------------------------------------------------------------------------
1 | {Emitter} = require 'event-kit'
2 |
3 | # Extended: A container representing a panel on the edges of the editor window.
4 | # You should not create a `Panel` directly, instead use {Workspace::addTopPanel}
5 | # and friends to add panels.
6 | #
7 | # Examples: [tree-view](https://github.com/atom/tree-view),
8 | # [status-bar](https://github.com/atom/status-bar),
9 | # and [find-and-replace](https://github.com/atom/find-and-replace) all use
10 | # panels.
11 | module.exports =
12 | class Panel
13 | ###
14 | Section: Construction and Destruction
15 | ###
16 |
17 | constructor: ({@item, @visible, @priority, @className}={}) ->
18 | @emitter = new Emitter
19 | @visible ?= true
20 | @priority ?= 100
21 |
22 | # Public: Destroy and remove this panel from the UI.
23 | destroy: ->
24 | @hide()
25 | @emitter.emit 'did-destroy', this
26 | @emitter.dispose()
27 |
28 | ###
29 | Section: Event Subscription
30 | ###
31 |
32 | # Public: Invoke the given callback when the pane hidden or shown.
33 | #
34 | # * `callback` {Function} to be called when the pane is destroyed.
35 | # * `visible` {Boolean} true when the panel has been shown
36 | #
37 | # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
38 | onDidChangeVisible: (callback) ->
39 | @emitter.on 'did-change-visible', callback
40 |
41 | # Public: Invoke the given callback when the pane is destroyed.
42 | #
43 | # * `callback` {Function} to be called when the pane is destroyed.
44 | # * `panel` {Panel} this panel
45 | #
46 | # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
47 | onDidDestroy: (callback) ->
48 | @emitter.on 'did-destroy', callback
49 |
50 | ###
51 | Section: Panel Details
52 | ###
53 |
54 | # Public: Returns the panel's item.
55 | getItem: -> @item
56 |
57 | # Public: Returns a {Number} indicating this panel's priority.
58 | getPriority: -> @priority
59 |
60 | getClassName: -> @className
61 |
62 | # Public: Returns a {Boolean} true when the panel is visible.
63 | isVisible: -> @visible
64 |
65 | # Public: Hide this panel
66 | hide: ->
67 | wasVisible = @visible
68 | @visible = false
69 | @emitter.emit 'did-change-visible', @visible if wasVisible
70 |
71 | # Public: Show this panel
72 | show: ->
73 | wasVisible = @visible
74 | @visible = true
75 | @emitter.emit 'did-change-visible', @visible unless wasVisible
76 |
--------------------------------------------------------------------------------
/docs/converting-a-text-mate-theme.md:
--------------------------------------------------------------------------------
1 | ## Converting a TextMate Theme
2 |
3 | This guide will show you how to convert a [TextMate][TextMate] theme to an Atom
4 | theme.
5 |
6 | ### Differences
7 |
8 | TextMate themes use [plist][plist] files while Atom themes use [CSS][CSS] or
9 | [Less][Less] to style the UI and syntax in the editor.
10 |
11 | The utility that converts the theme first parses the theme's plist file and
12 | then creates comparable CSS rules and properties that will style Atom similarly.
13 |
14 | ### Install apm
15 |
16 | The `apm` command line utility that ships with Atom supports converting
17 | a TextMate theme to an Atom theme.
18 |
19 | Check that you have `apm` installed by running the following command in your
20 | terminal:
21 |
22 | ```sh
23 | apm help init
24 | ```
25 |
26 | You should see a message print out with details about the `apm init` command.
27 |
28 | If you do not, launch Atom and run the _Atom > Install Shell Commands_ menu
29 | to install the `apm` and `atom` commands.
30 |
31 | You can now run `apm help init` to see all the options for initializing new
32 | packages and themes.
33 |
34 | ### Convert the Theme
35 |
36 | Download the theme you wish to convert, you can browse existing TextMate themes
37 | [here][TextMateThemes].
38 |
39 | Now, let's say you've downloaded the theme to `~/Downloads/MyTheme.tmTheme`,
40 | you can convert the theme with the following command:
41 |
42 | ```sh
43 | apm init --theme ~/.atom/packages/my-theme --convert ~/Downloads/MyTheme.tmTheme
44 | ```
45 |
46 | You can browse to `~/.atom/packages/my-theme` to see the converted theme.
47 |
48 | ### Activate the Theme
49 |
50 | Now that your theme is installed to `~/.atom/packages` you can enable it
51 | by launching Atom and selecting the _Atom > Preferences..._ menu.
52 |
53 | Select the _Themes_ link on the left side and choose _My Theme_ from the
54 | __Syntax Theme__ dropdown menu to enable your new theme.
55 |
56 | :tada: Your theme is now enabled, open an editor to see it in action!
57 |
58 | ### Further Reading
59 |
60 | * Check out [Publishing a Package](publishing-a-package.html) for more information
61 | on publishing the theme you just created to [atom.io][atomio].
62 |
63 | [atomio]: https://atom.io
64 | [CSS]: https://en.wikipedia.org/wiki/Cascading_Style_Sheets
65 | [Less]: http://lesscss.org
66 | [plist]: https://en.wikipedia.org/wiki/Property_list
67 | [TextMate]: http://macromates.com
68 | [TextMateThemes]: http://wiki.macromates.com/Themes/UserSubmittedThemes
69 |
--------------------------------------------------------------------------------
/spec/fixtures/packages/theme-with-ui-variables/styles/ui-variables.less:
--------------------------------------------------------------------------------
1 | // Variables different from the original are marked 'Changed'
2 |
3 | @text-color: #333;
4 | @text-color-subtle: #777;
5 | @text-color-highlight: #111;
6 | @text-color-selected: @text-color-highlight;
7 |
8 | @text-color-info: #5293d8;
9 | @text-color-success: #1fe977;
10 | @text-color-warning: #f78a46;
11 | @text-color-error: #c00;
12 |
13 | @background-color-info: #0098ff;
14 | @background-color-success: #17ca65;
15 | @background-color-warning: #ff4800;
16 | @background-color-error: #c00;
17 | @background-color-highlight: rgba(255, 255, 255, 0.10);
18 | @background-color-selected: @background-color-highlight;
19 |
20 | @app-background-color: #00f; // Changed
21 |
22 | @base-background-color: #fff;
23 | @base-border-color: #eee;
24 |
25 | @pane-item-background-color: @base-background-color;
26 | @pane-item-border-color: @base-border-color;
27 |
28 | @input-background-color: #f00; // Changed
29 | @input-border-color: @base-border-color;
30 |
31 | @tool-panel-background-color: #f4f4f4;
32 | @tool-panel-border-color: @base-border-color;
33 |
34 | @inset-panel-background-color: #eee;
35 | @inset-panel-border-color: @base-border-color;
36 |
37 | @panel-heading-background-color: #ddd;
38 | @panel-heading-border-color: transparent;
39 |
40 | @overlay-background-color: #f4f4f4;
41 | @overlay-border-color: @base-border-color;
42 |
43 | @button-background-color: #ccc;
44 | @button-background-color-hover: lighten(@button-background-color, 5%);
45 | @button-background-color-selected: @button-background-color-hover;
46 | @button-border-color: #aaa;
47 |
48 | @tab-bar-background-color: #fff;
49 | @tab-bar-border-color: darken(@tab-background-color-active, 10%);
50 | @tab-background-color: #f4f4f4;
51 | @tab-background-color-active: #fff;
52 | @tab-border-color: @base-border-color;
53 |
54 | @tree-view-background-color: @tool-panel-background-color;
55 | @tree-view-border-color: @tool-panel-border-color;
56 |
57 | @ui-site-color-1: @background-color-success; // green
58 | @ui-site-color-2: @background-color-info; // blue
59 | @ui-site-color-3: @background-color-warning; // orange
60 | @ui-site-color-4: #db2ff4; // purple
61 | @ui-site-color-5: #f5e11d; // yellow
62 |
63 | @font-size: 12px;
64 |
65 | @disclosure-arrow-size: 12px;
66 |
67 | @component-padding: 150px;
68 | @component-icon-padding: 5px;
69 | @component-icon-size: 16px;
70 | @component-line-height: 25px;
71 | @component-border-radius: 2px;
72 |
73 | @tab-height: 30px;
74 |
75 | @font-family: Arial;
76 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | Atom is a hackable text editor for the 21st century, built on [atom-shell](https://github.com/atom/atom-shell), and based on everything we love about our favorite editors. We designed it to be deeply customizable, but still approachable using the default configuration.
4 |
5 | Visit [atom.io](https://atom.io) to learn more or visit the [Atom forum](https://discuss.atom.io).
6 |
7 | Visit [issue #3684](https://github.com/atom/atom/issues/3684) to learn more
8 | about the Atom 1.0 roadmap.
9 |
10 | ## Installing
11 |
12 | ### OS X
13 |
14 | Download the latest [Atom release](https://github.com/atom/atom/releases/latest).
15 |
16 | Atom will automatically update when a new release is available.
17 |
18 | ### Windows
19 |
20 | Download the latest [AtomSetup.exe installer](https://github.com/atom/atom/releases/latest).
21 |
22 | Atom will automatically update when a new release is available.
23 |
24 | You can also download an `atom-windows.zip` file from the [releases page](https://github.com/atom/atom/releases/latest).
25 | The `.zip` version will not automatically update.
26 |
27 | Using [chocolatey](https://chocolatey.org/)? Run `cinst Atom` to install
28 | the latest version of Atom.
29 |
30 | ### Debian Linux (Ubuntu)
31 |
32 | Currently only a 64-bit version is available.
33 |
34 | 1. Download `atom-amd64.deb` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
35 | 2. Run `sudo dpkg --install atom-amd64.deb` on the downloaded package.
36 | 3. Launch Atom using the installed `atom` command.
37 |
38 | The Linux version does not currently automatically update so you will need to
39 | repeat these steps to upgrade to future releases.
40 |
41 | ### Red Hat Linux (Fedora, CentOS, Red Hat)
42 |
43 | Currently only a 64-bit version is available.
44 |
45 | 1. Download `atom.x86_64.rpm` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
46 | 2. Run `sudo yum localinstall atom.x86_64.rpm` on the downloaded package.
47 | 3. Launch Atom using the installed `atom` command.
48 |
49 | The Linux version does not currently automatically update so you will need to
50 | repeat these steps to upgrade to future releases.
51 |
52 | ## Building
53 |
54 | * [Linux](docs/build-instructions/linux.md)
55 | * [OS X](docs/build-instructions/os-x.md)
56 | * [FreeBSD](docs/build-instructions/freebsd.md)
57 | * [Windows](docs/build-instructions/windows.md)
58 |
59 | ## Developing
60 |
61 | Check out the [guides](https://atom.io/docs/latest) and the [API reference](https://atom.io/docs/api).
62 |
--------------------------------------------------------------------------------
/src/buffered-node-process.coffee:
--------------------------------------------------------------------------------
1 | BufferedProcess = require './buffered-process'
2 | path = require 'path'
3 |
4 | # Extended: Like {BufferedProcess}, but accepts a Node script as the command
5 | # to run.
6 | #
7 | # This is necessary on Windows since it doesn't support shebang `#!` lines.
8 | #
9 | # ## Examples
10 | #
11 | # ```coffee
12 | # {BufferedNodeProcess} = require 'atom'
13 | # ```
14 | module.exports =
15 | class BufferedNodeProcess extends BufferedProcess
16 |
17 | # Public: Runs the given Node script by spawning a new child process.
18 | #
19 | # * `options` An {Object} with the following keys:
20 | # * `command` The {String} path to the JavaScript script to execute.
21 | # * `args` The {Array} of arguments to pass to the script (optional).
22 | # * `options` The options {Object} to pass to Node's `ChildProcess.spawn`
23 | # method (optional).
24 | # * `stdout` The callback {Function} that receives a single argument which
25 | # contains the standard output from the command. The callback is
26 | # called as data is received but it's buffered to ensure only
27 | # complete lines are passed until the source stream closes. After
28 | # the source stream has closed all remaining data is sent in a
29 | # final call (optional).
30 | # * `stderr` The callback {Function} that receives a single argument which
31 | # contains the standard error output from the command. The
32 | # callback is called as data is received but it's buffered to
33 | # ensure only complete lines are passed until the source stream
34 | # closes. After the source stream has closed all remaining data
35 | # is sent in a final call (optional).
36 | # * `exit` The callback {Function} which receives a single argument
37 | # containing the exit status (optional).
38 | constructor: ({command, args, options, stdout, stderr, exit}) ->
39 | node =
40 | if process.platform is 'darwin'
41 | # Use a helper to prevent an icon from appearing on the Dock
42 | path.resolve(process.resourcesPath, '..', 'Frameworks',
43 | 'Atom Helper.app', 'Contents', 'MacOS', 'Atom Helper')
44 | else
45 | process.execPath
46 |
47 | options ?= {}
48 | options.env ?= Object.create(process.env)
49 | options.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = 1
50 |
51 | args = args?.slice() ? []
52 | args.unshift(command)
53 | args.unshift('--no-deprecation')
54 |
55 | super({command: node, args, options, stdout, stderr, exit})
56 |
--------------------------------------------------------------------------------
/static/variables/ui-variables.less:
--------------------------------------------------------------------------------
1 | // This file has fallback variables. It specifies the variables themes
2 | // must implement.
3 |
4 | // Colors
5 |
6 | @text-color: #333;
7 | @text-color-subtle: #777;
8 | @text-color-highlight: #111;
9 | @text-color-selected: @text-color-highlight;
10 |
11 | @text-color-info: #5293d8;
12 | @text-color-success: #1fe977;
13 | @text-color-warning: #f78a46;
14 | @text-color-error: #c00;
15 |
16 | @background-color-info: #0098ff;
17 | @background-color-success: #17ca65;
18 | @background-color-warning: #ff4800;
19 | @background-color-error: #c00;
20 | @background-color-highlight: rgba(255, 255, 255, 0.10);
21 | @background-color-selected: @background-color-highlight;
22 |
23 | @app-background-color: #fff;
24 |
25 | @base-background-color: #fff;
26 | @base-border-color: #eee;
27 |
28 | @pane-item-background-color: @base-background-color;
29 | @pane-item-border-color: @base-border-color;
30 |
31 | @input-background-color: #fff;
32 | @input-border-color: @base-border-color;
33 |
34 | @tool-panel-background-color: #f4f4f4;
35 | @tool-panel-border-color: @base-border-color;
36 |
37 | @inset-panel-background-color: #eee;
38 | @inset-panel-border-color: @base-border-color;
39 |
40 | @panel-heading-background-color: #ddd;
41 | @panel-heading-border-color: transparent;
42 |
43 | @overlay-background-color: #f4f4f4;
44 | @overlay-border-color: @base-border-color;
45 |
46 | @button-background-color: #ccc;
47 | @button-background-color-hover: lighten(@button-background-color, 5%);
48 | @button-background-color-selected: @button-background-color-hover;
49 | @button-border-color: #aaa;
50 |
51 | @tab-bar-background-color: #fff;
52 | @tab-bar-border-color: darken(@tab-background-color-active, 10%);
53 | @tab-background-color: #f4f4f4;
54 | @tab-background-color-active: #fff;
55 | @tab-border-color: @base-border-color;
56 |
57 | @tree-view-background-color: @tool-panel-background-color;
58 | @tree-view-border-color: @tool-panel-border-color;
59 |
60 | @ui-site-color-1: @background-color-success; // green
61 | @ui-site-color-2: @background-color-info; // blue
62 | @ui-site-color-3: @background-color-warning; // orange
63 | @ui-site-color-4: #db2ff4; // purple
64 | @ui-site-color-5: #f5e11d; // yellow
65 |
66 |
67 | // Sizes
68 |
69 | @font-size: 13px;
70 | @input-font-size: 14px;
71 |
72 | @disclosure-arrow-size: 12px;
73 |
74 | @component-padding: 10px;
75 | @component-icon-padding: 5px;
76 | @component-icon-size: 16px;
77 | @component-line-height: 25px;
78 | @component-border-radius: 2px;
79 |
80 | @tab-height: 30px;
81 |
82 |
83 | // Other
84 |
85 | @font-family: 'Lucida Grande', 'Segoe UI', Ubuntu, Cantarell, sans-serif;
86 |
--------------------------------------------------------------------------------
/src/pane-container-view.coffee:
--------------------------------------------------------------------------------
1 | {deprecate} = require 'grim'
2 | Delegator = require 'delegato'
3 | {CompositeDisposable} = require 'event-kit'
4 | {$, View, callAttachHooks} = require './space-pen-extensions'
5 | PaneView = require './pane-view'
6 | PaneContainer = require './pane-container'
7 |
8 | # Manages the list of panes within a {WorkspaceView}
9 | module.exports =
10 | class PaneContainerView extends View
11 | Delegator.includeInto(this)
12 |
13 | @delegatesMethod 'saveAll', toProperty: 'model'
14 |
15 | @content: ->
16 | @div class: 'panes'
17 |
18 | constructor: (@element) ->
19 | super
20 | @subscriptions = new CompositeDisposable
21 |
22 | setModel: (@model) ->
23 | @subscriptions.add @model.onDidChangeActivePaneItem(@onActivePaneItemChanged)
24 |
25 | getRoot: ->
26 | view = atom.views.getView(@model.getRoot())
27 | view.__spacePenView ? view
28 |
29 | onActivePaneItemChanged: (activeItem) =>
30 | @trigger 'pane-container:active-pane-item-changed', [activeItem]
31 |
32 | confirmClose: ->
33 | @model.confirmClose()
34 |
35 | getPaneViews: ->
36 | @find('atom-pane').views()
37 |
38 | indexOfPane: (paneView) ->
39 | @getPaneViews().indexOf(paneView.view())
40 |
41 | paneAtIndex: (index) ->
42 | @getPaneViews()[index]
43 |
44 | eachPaneView: (callback) ->
45 | callback(paneView) for paneView in @getPaneViews()
46 | paneViewAttached = (e) -> callback($(e.target).view())
47 | @on 'pane:attached', paneViewAttached
48 | off: => @off 'pane:attached', paneViewAttached
49 |
50 | getFocusedPane: ->
51 | @find('atom-pane:has(:focus)').view()
52 |
53 | getActivePane: ->
54 | deprecate("Use PaneContainerView::getActivePaneView instead.")
55 | @getActivePaneView()
56 |
57 | getActivePaneView: ->
58 | atom.views.getView(@model.getActivePane()).__spacePenView
59 |
60 | getActivePaneItem: ->
61 | @model.getActivePaneItem()
62 |
63 | getActiveView: ->
64 | @getActivePaneView()?.activeView
65 |
66 | paneForUri: (uri) ->
67 | atom.views.getView(@model.paneForURI(uri)).__spacePenView
68 |
69 | focusNextPaneView: ->
70 | @model.activateNextPane()
71 |
72 | focusPreviousPaneView: ->
73 | @model.activatePreviousPane()
74 |
75 | focusPaneViewAbove: ->
76 | @element.focusPaneViewAbove()
77 |
78 | focusPaneViewBelow: ->
79 | @element.focusPaneViewBelow()
80 |
81 | focusPaneViewOnLeft: ->
82 | @element.focusPaneViewOnLeft()
83 |
84 | focusPaneViewOnRight: ->
85 | @element.focusPaneViewOnRight()
86 |
87 | getPanes: ->
88 | deprecate("Use PaneContainerView::getPaneViews() instead")
89 | @getPaneViews()
90 |
--------------------------------------------------------------------------------
/src/text-utils.coffee:
--------------------------------------------------------------------------------
1 | isHighSurrogate = (charCode) ->
2 | 0xD800 <= charCode <= 0xDBFF
3 |
4 | isLowSurrogate = (charCode) ->
5 | 0xDC00 <= charCode <= 0xDFFF
6 |
7 | isVariationSelector = (charCode) ->
8 | 0xFE00 <= charCode <= 0xFE0F
9 |
10 | isCombiningCharacter = (charCode) ->
11 | 0x0300 <= charCode <= 0x036F or
12 | 0x1AB0 <= charCode <= 0x1AFF or
13 | 0x1DC0 <= charCode <= 0x1DFF or
14 | 0x20D0 <= charCode <= 0x20FF or
15 | 0xFE20 <= charCode <= 0xFE2F
16 |
17 | # Are the given character codes a high/low surrogate pair?
18 | #
19 | # * `charCodeA` The first character code {Number}.
20 | # * `charCode2` The second character code {Number}.
21 | #
22 | # Return a {Boolean}.
23 | isSurrogatePair = (charCodeA, charCodeB) ->
24 | isHighSurrogate(charCodeA) and isLowSurrogate(charCodeB)
25 |
26 | # Are the given character codes a variation sequence?
27 | #
28 | # * `charCodeA` The first character code {Number}.
29 | # * `charCode2` The second character code {Number}.
30 | #
31 | # Return a {Boolean}.
32 | isVariationSequence = (charCodeA, charCodeB) ->
33 | not isVariationSelector(charCodeA) and isVariationSelector(charCodeB)
34 |
35 | # Are the given character codes a combined character pair?
36 | #
37 | # * `charCodeA` The first character code {Number}.
38 | # * `charCode2` The second character code {Number}.
39 | #
40 | # Return a {Boolean}.
41 | isCombinedCharacter = (charCodeA, charCodeB) ->
42 | not isCombiningCharacter(charCodeA) and isCombiningCharacter(charCodeB)
43 |
44 | # Is the character at the given index the start of high/low surrogate pair
45 | # a variation sequence, or a combined character?
46 | #
47 | # * `string` The {String} to check for a surrogate pair, variation sequence,
48 | # or combined character.
49 | # * `index` The {Number} index to look for a surrogate pair, variation
50 | # sequence, or combined character.
51 | #
52 | # Return a {Boolean}.
53 | isPairedCharacter = (string, index=0) ->
54 | charCodeA = string.charCodeAt(index)
55 | charCodeB = string.charCodeAt(index + 1)
56 | isSurrogatePair(charCodeA, charCodeB) or
57 | isVariationSequence(charCodeA, charCodeB) or
58 | isCombinedCharacter(charCodeA, charCodeB)
59 |
60 | # Does the given string contain at least surrogate pair, variation sequence,
61 | # or combined character?
62 | #
63 | # * `string` The {String} to check for the presence of paired characters.
64 | #
65 | # Returns a {Boolean}.
66 | hasPairedCharacter = (string) ->
67 | index = 0
68 | while index < string.length
69 | return true if isPairedCharacter(string, index)
70 | index++
71 | false
72 |
73 | module.exports = {isPairedCharacter, hasPairedCharacter}
74 |
--------------------------------------------------------------------------------
/src/coffee-cache.coffee:
--------------------------------------------------------------------------------
1 | crypto = require 'crypto'
2 | path = require 'path'
3 |
4 | CoffeeScript = require 'coffee-script'
5 | CSON = require 'season'
6 | fs = require 'fs-plus'
7 |
8 | cacheDir = path.join(process.env.ATOM_HOME, 'compile-cache')
9 |
10 | stats =
11 | hits: 0
12 | misses: 0
13 |
14 | # Use separate compile cache when sudo'ing as root to avoid permission issues
15 | if process.env.USER is 'root' and process.env.SUDO_USER and process.env.SUDO_USER isnt process.env.USER
16 | cacheDir = path.join(cacheDir, 'root')
17 |
18 | coffeeCacheDir = path.join(cacheDir, 'coffee')
19 | CSON.setCacheDir(path.join(cacheDir, 'cson'))
20 |
21 | getCachePath = (coffee) ->
22 | digest = crypto.createHash('sha1').update(coffee, 'utf8').digest('hex')
23 | path.join(coffeeCacheDir, "#{digest}.js")
24 |
25 | getCachedJavaScript = (cachePath) ->
26 | if fs.isFileSync(cachePath)
27 | try
28 | cachedJavaScript = fs.readFileSync(cachePath, 'utf8')
29 | stats.hits++
30 | return cachedJavaScript
31 | return
32 |
33 | convertFilePath = (filePath) ->
34 | if process.platform is 'win32'
35 | filePath = "/#{path.resolve(filePath).replace(/\\/g, '/')}"
36 | encodeURI(filePath)
37 |
38 | compileCoffeeScript = (coffee, filePath, cachePath) ->
39 | {js, v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
40 | stats.misses++
41 | # Include source map in the web page environment.
42 | if btoa? and JSON? and unescape? and encodeURIComponent?
43 | js = "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=#{convertFilePath(filePath)}"
44 | try
45 | fs.writeFileSync(cachePath, js)
46 | js
47 |
48 | requireCoffeeScript = (module, filePath) ->
49 | coffee = fs.readFileSync(filePath, 'utf8')
50 | cachePath = getCachePath(coffee)
51 | js = getCachedJavaScript(cachePath) ? compileCoffeeScript(coffee, filePath, cachePath)
52 | module._compile(js, filePath)
53 |
54 | module.exports =
55 | cacheDir: cacheDir
56 |
57 | register: ->
58 | Object.defineProperty(require.extensions, '.coffee', {
59 | writable: false
60 | value: requireCoffeeScript
61 | })
62 |
63 | addPathToCache: (filePath) ->
64 | switch path.extname(filePath)
65 | when '.coffee'
66 | content = fs.readFileSync(filePath, 'utf8')
67 | cachePath = getCachePath(coffee)
68 | compileCoffeeScript(coffee, filePath, cachePath)
69 | when '.cson'
70 | CSON.readFileSync(filePath)
71 | when '.js'
72 | require('./6to5').addPathToCache(filePath)
73 |
74 | getCacheMisses: -> stats.misses
75 |
76 | getCacheHits: -> stats.hits
77 |
--------------------------------------------------------------------------------
/src/fold.coffee:
--------------------------------------------------------------------------------
1 | {Point, Range} = require 'text-buffer'
2 |
3 | # Represents a fold that collapses multiple buffer lines into a single
4 | # line on the screen.
5 | #
6 | # Their creation is managed by the {DisplayBuffer}.
7 | module.exports =
8 | class Fold
9 | id: null
10 | displayBuffer: null
11 | marker: null
12 |
13 | constructor: (@displayBuffer, @marker) ->
14 | @id = @marker.id
15 | @displayBuffer.foldsByMarkerId[@marker.id] = this
16 | @updateDisplayBuffer()
17 | @marker.onDidDestroy => @destroyed()
18 | @marker.onDidChange ({isValid}) => @destroy() unless isValid
19 |
20 | # Returns whether this fold is contained within another fold
21 | isInsideLargerFold: ->
22 | largestContainingFoldMarker = @displayBuffer.findFoldMarker(containsRange: @getBufferRange())
23 | largestContainingFoldMarker and
24 | not largestContainingFoldMarker.getRange().isEqual(@getBufferRange())
25 |
26 | # Destroys this fold
27 | destroy: ->
28 | @marker.destroy()
29 |
30 | # Returns the fold's {Range} in buffer coordinates
31 | #
32 | # includeNewline - A {Boolean} which, if `true`, includes the trailing newline
33 | #
34 | # Returns a {Range}.
35 | getBufferRange: ({includeNewline}={}) ->
36 | range = @marker.getRange()
37 |
38 | if range.end.row > range.start.row and nextFold = @displayBuffer.largestFoldStartingAtBufferRow(range.end.row)
39 | nextRange = nextFold.getBufferRange()
40 | range = new Range(range.start, nextRange.end)
41 |
42 | if includeNewline
43 | range = range.copy()
44 | range.end.row++
45 | range.end.column = 0
46 | range
47 |
48 | getBufferRowRange: ->
49 | {start, end} = @getBufferRange()
50 | [start.row, end.row]
51 |
52 | # Returns the fold's start row as a {Number}.
53 | getStartRow: ->
54 | @getBufferRange().start.row
55 |
56 | # Returns the fold's end row as a {Number}.
57 | getEndRow: ->
58 | @getBufferRange().end.row
59 |
60 | # Returns a {String} representation of the fold.
61 | inspect: ->
62 | "Fold(#{@getStartRow()}, #{@getEndRow()})"
63 |
64 | # Retrieves the number of buffer rows spanned by the fold.
65 | #
66 | # Returns a {Number}.
67 | getBufferRowCount: ->
68 | @getEndRow() - @getStartRow() + 1
69 |
70 | # Identifies if a fold is nested within a fold.
71 | #
72 | # fold - A {Fold} to check
73 | #
74 | # Returns a {Boolean}.
75 | isContainedByFold: (fold) ->
76 | @isContainedByRange(fold.getBufferRange())
77 |
78 | updateDisplayBuffer: ->
79 | unless @isInsideLargerFold()
80 | @displayBuffer.updateScreenLines(@getStartRow(), @getEndRow() + 1, 0, updateMarkers: true)
81 |
82 | destroyed: ->
83 | delete @displayBuffer.foldsByMarkerId[@marker.id]
84 | @updateDisplayBuffer()
85 |
--------------------------------------------------------------------------------
/spec/text-utils-spec.coffee:
--------------------------------------------------------------------------------
1 | textUtils = require '../src/text-utils'
2 |
3 | describe 'text utilities', ->
4 | describe '.hasPairedCharacter(string)', ->
5 | it 'returns true when the string contains a surrogate pair, variation sequence, or combined character', ->
6 | expect(textUtils.hasPairedCharacter('abc')).toBe false
7 | expect(textUtils.hasPairedCharacter('a\uD835\uDF97b\uD835\uDF97c')).toBe true
8 | expect(textUtils.hasPairedCharacter('\uD835\uDF97')).toBe true
9 | expect(textUtils.hasPairedCharacter('\u2714\uFE0E')).toBe true
10 | expect(textUtils.hasPairedCharacter('e\u0301')).toBe true
11 |
12 | expect(textUtils.hasPairedCharacter('\uD835')).toBe false
13 | expect(textUtils.hasPairedCharacter('\uDF97')).toBe false
14 | expect(textUtils.hasPairedCharacter('\uFE0E')).toBe false
15 | expect(textUtils.hasPairedCharacter('\u0301')).toBe false
16 |
17 | expect(textUtils.hasPairedCharacter('\uFE0E\uFE0E')).toBe false
18 | expect(textUtils.hasPairedCharacter('\u0301\u0301')).toBe false
19 |
20 | describe '.isPairedCharacter(string, index)', ->
21 | it 'returns true when the index is the start of a high/low surrogate pair, variation sequence, or combined character', ->
22 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 0)).toBe false
23 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 1)).toBe true
24 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 2)).toBe false
25 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 3)).toBe false
26 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 4)).toBe true
27 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 5)).toBe false
28 | expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 6)).toBe false
29 |
30 | expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 0)).toBe false
31 | expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 1)).toBe true
32 | expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 2)).toBe false
33 | expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 3)).toBe false
34 |
35 | expect(textUtils.isPairedCharacter('\uD835')).toBe false
36 | expect(textUtils.isPairedCharacter('\uDF97')).toBe false
37 | expect(textUtils.isPairedCharacter('\uFE0E')).toBe false
38 | expect(textUtils.isPairedCharacter('\uFE0E')).toBe false
39 |
40 | expect(textUtils.isPairedCharacter('\uFE0E\uFE0E')).toBe false
41 |
42 | expect(textUtils.isPairedCharacter('ae\u0301c', 0)).toBe false
43 | expect(textUtils.isPairedCharacter('ae\u0301c', 1)).toBe true
44 | expect(textUtils.isPairedCharacter('ae\u0301c', 2)).toBe false
45 | expect(textUtils.isPairedCharacter('ae\u0301c', 3)).toBe false
46 | expect(textUtils.isPairedCharacter('ae\u0301c', 4)).toBe false
47 |
--------------------------------------------------------------------------------
/src/color.coffee:
--------------------------------------------------------------------------------
1 | _ = require 'underscore-plus'
2 | ParsedColor = null
3 |
4 | # Essential: A simple color class returned from {Config::get} when the value
5 | # at the key path is of type 'color'.
6 | module.exports =
7 | class Color
8 | # Essential: Parse a {String} or {Object} into a {Color}.
9 | #
10 | # * `value` A {String} such as `'white'`, `#ff00ff`, or
11 | # `'rgba(255, 15, 60, .75)'` or an {Object} with `red`, `green`, `blue`,
12 | # and `alpha` properties.
13 | #
14 | # Returns a {Color} or `null` if it cannot be parsed.
15 | @parse: (value) ->
16 | return null if _.isArray(value) or _.isFunction(value)
17 | return null unless _.isObject(value) or _.isString(value)
18 |
19 | ParsedColor ?= require 'color'
20 |
21 | try
22 | parsedColor = new ParsedColor(value)
23 | catch error
24 | return null
25 |
26 | new Color(parsedColor.red(), parsedColor.green(), parsedColor.blue(), parsedColor.alpha())
27 |
28 | constructor: (red, green, blue, alpha) ->
29 | Object.defineProperties this,
30 | red:
31 | set: (newRed) -> red = parseColor(newRed)
32 | get: -> red
33 | enumerable: true
34 | configurable: false
35 | green:
36 | set: (newGreen) -> green = parseColor(newGreen)
37 | get: -> green
38 | enumerable: true
39 | configurable: false
40 | blue:
41 | set: (newBlue) -> blue = parseColor(newBlue)
42 | get: -> blue
43 | enumerable: true
44 | configurable: false
45 | alpha:
46 | set: (newAlpha) -> alpha = parseAlpha(newAlpha)
47 | get: -> alpha
48 | enumerable: true
49 | configurable: false
50 |
51 | @red = red
52 | @green = green
53 | @blue = blue
54 | @alpha = alpha
55 |
56 | # Essential: Returns a {String} in the form `'#abcdef'`.
57 | toHexString: ->
58 | "##{numberToHexString(@red)}#{numberToHexString(@green)}#{numberToHexString(@blue)}"
59 |
60 | # Essential: Returns a {String} in the form `'rgba(25, 50, 75, .9)'`.
61 | toRGBAString: ->
62 | "rgba(#{@red}, #{@green}, #{@blue}, #{@alpha})"
63 |
64 | isEqual: (color) ->
65 | return true if this is color
66 | color = Color.parse(color) unless color instanceof Color
67 | return false unless color?
68 | color.red is @red and color.blue is @blue and color.green is @green and color.alpha is @alpha
69 |
70 | clone: -> new Color(@red, @green, @blue, @alpha)
71 |
72 | parseColor = (color) ->
73 | color = parseInt(color)
74 | color = 0 if isNaN(color)
75 | color = Math.max(color, 0)
76 | color = Math.min(color, 255)
77 | color
78 |
79 | parseAlpha = (alpha) ->
80 | alpha = parseFloat(alpha)
81 | alpha = 1 if isNaN(alpha)
82 | alpha = Math.max(alpha, 0)
83 | alpha = Math.min(alpha, 1)
84 | alpha
85 |
86 | numberToHexString = (number) ->
87 | hex = number.toString(16)
88 | hex = "0#{hex}" if number < 10
89 | hex
90 |
--------------------------------------------------------------------------------