├── spec ├── fixtures │ ├── dir │ │ ├── file1 │ │ ├── b │ │ ├── a-dir │ │ │ └── oh-git │ │ └── a │ ├── cson.cson │ ├── 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 │ │ ├── theme-with-invalid-styles │ │ │ ├── index.less │ │ │ └── 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-invalid-grammar │ │ │ ├── grammars │ │ │ │ └── grammar.json │ │ │ └── package.json │ │ ├── package-with-invalid-settings │ │ │ ├── settings │ │ │ │ └── settings.json │ │ │ └── package.json │ │ ├── package-with-no-activate │ │ │ ├── index.js │ │ │ └── package.json │ │ ├── package-without-module │ │ │ └── package.cson │ │ ├── package-with-main │ │ │ ├── package.cson │ │ │ └── main-module.coffee │ │ ├── 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-empty-activation-hooks │ │ │ ├── index.coffee │ │ │ └── package.json │ │ ├── package-with-keymaps │ │ │ └── keymaps │ │ │ │ ├── keymap-1.cson │ │ │ │ ├── keymap-2.cson │ │ │ │ └── keymap-3.cjson │ │ ├── wordcount │ │ │ └── package.json │ │ ├── sublime-tabs │ │ │ └── package.json │ │ ├── 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 │ │ ├── package-with-missing-consumed-services │ │ │ ├── index.coffee │ │ │ └── package.json │ │ ├── package-with-missing-provided-services │ │ │ ├── index.coffee │ │ │ └── package.json │ │ ├── package-with-rb-filetype │ │ │ ├── package.json │ │ │ └── grammars │ │ │ │ └── rb.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 │ │ ├── package-with-invalid-context-menu │ │ │ ├── package.json │ │ │ └── menus │ │ │ │ └── menu.json │ │ ├── theme-with-package-file │ │ │ ├── package.json │ │ │ └── styles │ │ │ │ ├── last.css │ │ │ │ ├── first.css │ │ │ │ └── second.less │ │ ├── package-with-activation-hooks │ │ │ ├── index.coffee │ │ │ └── package.cson │ │ ├── package-with-different-directory-name │ │ │ └── package.json │ │ ├── package-with-invalid-url-package-json │ │ │ └── package.json │ │ ├── package-with-short-url-package-json │ │ │ └── package.json │ │ ├── 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-invalid-activation-commands │ │ │ └── package.json │ │ ├── package-with-grammars │ │ │ └── grammars │ │ │ │ ├── alot.cson │ │ │ │ └── alittle.cson │ │ ├── package-with-config-schema │ │ │ └── index.coffee │ │ └── package-with-provided-services │ │ │ ├── index.coffee │ │ │ └── package.json │ ├── module-cache │ │ └── file.json │ ├── script.js │ ├── shebang │ ├── typescript │ │ ├── invalid.ts │ │ └── valid.ts │ ├── babel │ │ ├── invalid.js │ │ ├── babel-comment.js │ │ ├── babel-double-quotes.js │ │ └── babel-single-quotes.js │ ├── task-handler-with-deprecations.coffee │ ├── 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 ├── integration │ ├── fixtures │ │ └── atom-home │ │ │ └── config.cson │ └── helpers │ │ └── atom-launcher.sh ├── typescript-spec.coffee ├── atom-protocol-handler-spec.coffee ├── clipboard-spec.coffee ├── panel-spec.coffee ├── babel-spec.coffee ├── tokenized-line-spec.coffee ├── default-directory-searcher-spec.coffee ├── spec-bootstrap.coffee ├── spec-helper-platform.coffee ├── buffered-node-process-spec.coffee ├── space-pen-extensions-spec.coffee ├── command-installer-spec.coffee ├── jasmine-helper.coffee ├── spec-suite.coffee ├── deserializer-manager-spec.coffee ├── default-directory-provider-spec.coffee ├── workspace-element-spec.coffee ├── time-reporter.coffee ├── notification-manager-spec.coffee ├── panel-element-spec.coffee └── gutter-spec.coffee ├── .node-version ├── .python-version ├── docs ├── contributing.md ├── README.md ├── build-instructions │ ├── freebsd.md │ └── os-x.md └── contributing-to-packages.md ├── CHANGELOG.md ├── .coffeelintignore ├── dot-atom ├── .gitignore ├── packages │ └── README.md ├── init.coffee ├── snippets.cson ├── styles.less └── 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 ├── babelrc.json ├── links.less ├── icons.less ├── index.html ├── markdown.less ├── linux.less ├── popover-list.less ├── messages.less ├── text.less ├── workspace-view.less ├── select-list.less ├── sections.less ├── atom.less ├── bootstrap-overrides.less ├── syntax.less ├── variables │ ├── octicon-mixins.less │ └── syntax-variables.less ├── bootstrap.less ├── utilities.less ├── badges.less ├── panes.less └── buttons.less ├── apm ├── README.md └── package.json ├── script ├── build.cmd ├── clean.cmd ├── grunt.cmd ├── utils │ ├── compile-main-to-app │ ├── clean-open-with-menu │ ├── fix-author │ ├── run-grunt.js │ ├── clean-merged-branches │ ├── child-process-wrapper.js │ └── translate-crash-log-addresses.coffee ├── rpmbuild ├── bootstrap.cmd ├── grunt ├── cibuild-atom-rpm ├── copy-folder.cmd ├── test ├── cibuild-atom-linux ├── build ├── mkrpm ├── create-shortcut.cmd ├── set-version ├── mkdeb └── clean ├── src ├── subscriber-mixin.coffee ├── special-token-symbols.coffee ├── safe-clipboard.coffee ├── marker-observation-window.coffee ├── item-registry.coffee ├── window-bootstrap.coffee ├── replace-handler.coffee ├── custom-event-mixin.coffee ├── model.coffee ├── theme-package.coffee ├── scoped-properties.coffee ├── storage-folder.coffee ├── window.coffee ├── browser │ ├── context-menu.coffee │ ├── atom-protocol-handler.coffee │ └── auto-updater-win32.coffee ├── input-component.coffee ├── less-compile-cache.coffee ├── repository-status-handler.coffee ├── panel-element.coffee ├── scroll-view.coffee ├── coffee-script.js ├── gutter-component-helpers.coffee ├── scrollbar-corner-component.coffee ├── deprecated-packages.coffee ├── typescript.js ├── tiled-component.coffee ├── task-bootstrap.coffee ├── scope-descriptor.coffee ├── token.coffee ├── panel-container-element.coffee ├── clipboard.coffee ├── default-directory-provider.coffee ├── babel.js ├── scan-handler.coffee ├── panel-container.coffee ├── menu-helpers.coffee ├── overlay-manager.coffee ├── cursors-component.coffee ├── token-iterator.coffee ├── deserializer-manager.coffee ├── panel.coffee ├── keymap-extensions.coffee └── gutter.coffee ├── .gitignore ├── benchmark ├── benchmark-bootstrap.coffee └── browser-process-startup.coffee ├── .pairs ├── Dockerfile ├── .gitattributes ├── keymaps ├── emacs.cson └── base.cson ├── coffeelint.json ├── .travis.yml └── LICENSE.md /spec/fixtures/dir/file1: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v0.12.0 2 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 2.7.6 2 | -------------------------------------------------------------------------------- /spec/fixtures/cson.cson: -------------------------------------------------------------------------------- 1 | a: 4 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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | See https://atom.io/releases 2 | -------------------------------------------------------------------------------- /spec/fixtures/git/ignore.git/info/exclude: -------------------------------------------------------------------------------- 1 | a.txt 2 | -------------------------------------------------------------------------------- /.coffeelintignore: -------------------------------------------------------------------------------- 1 | spec/fixtures 2 | benchmark/fixtures 3 | -------------------------------------------------------------------------------- /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/packages/theme-with-invalid-styles/index.less: -------------------------------------------------------------------------------- 1 | <> 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /spec/fixtures/typescript/invalid.ts: -------------------------------------------------------------------------------- 1 | var foo = 123 123; // Syntax error 2 | -------------------------------------------------------------------------------- /spec/fixtures/typescript/valid.ts: -------------------------------------------------------------------------------- 1 | var inc = v => v + 1 2 | export = inc 3 | -------------------------------------------------------------------------------- /dot-atom/.gitignore: -------------------------------------------------------------------------------- 1 | storage 2 | compile-cache 3 | dev 4 | .npm 5 | .node-gyp 6 | -------------------------------------------------------------------------------- /spec/fixtures/babel/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-invalid-grammar/grammars/grammar.json: -------------------------------------------------------------------------------- 1 | >< 2 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-invalid-settings/settings/settings.json: -------------------------------------------------------------------------------- 1 | >< 2 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-no-activate/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-without-module/package.cson: -------------------------------------------------------------------------------- 1 | "name": "perfect" 2 | -------------------------------------------------------------------------------- /resources/atom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/atom.png -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-main/package.cson: -------------------------------------------------------------------------------- 1 | 'main': 'main-module.coffee' 2 | -------------------------------------------------------------------------------- /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/babel/babel-comment.js: -------------------------------------------------------------------------------- 1 | /** @babel */ 2 | 3 | module.exports = v => v + 1 4 | -------------------------------------------------------------------------------- /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/functions/atom/master/static/octicons.woff -------------------------------------------------------------------------------- /resources/mac/atom.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/mac/atom.icns -------------------------------------------------------------------------------- /resources/mac/file.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/mac/file.icns -------------------------------------------------------------------------------- /resources/win/atom.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/win/atom.ico -------------------------------------------------------------------------------- /spec/fixtures/babel/babel-double-quotes.js: -------------------------------------------------------------------------------- 1 | "use babel"; 2 | 3 | module.exports = v => v + 1 4 | -------------------------------------------------------------------------------- /spec/fixtures/babel/babel-single-quotes.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | module.exports = v => v + 1 4 | -------------------------------------------------------------------------------- /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/functions/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/functions/atom/master/resources/linux/icons/16.png -------------------------------------------------------------------------------- /resources/linux/icons/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/24.png -------------------------------------------------------------------------------- /resources/linux/icons/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/32.png -------------------------------------------------------------------------------- /resources/linux/icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/48.png -------------------------------------------------------------------------------- /resources/linux/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/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-empty-activation-hooks/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 | -------------------------------------------------------------------------------- /spec/fixtures/task-handler-with-deprecations.coffee: -------------------------------------------------------------------------------- 1 | {Git} = require 'atom' 2 | 3 | module.exports = -> 4 | -------------------------------------------------------------------------------- /resources/linux/icons/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/1024.png -------------------------------------------------------------------------------- /resources/linux/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/128.png -------------------------------------------------------------------------------- /resources/linux/icons/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/256.png -------------------------------------------------------------------------------- /resources/linux/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/resources/linux/icons/512.png -------------------------------------------------------------------------------- /spec/fixtures/packages/theme-with-index-css/index.css: -------------------------------------------------------------------------------- 1 | atom-text-editor { 2 | padding-top: 1234px; 3 | } 4 | -------------------------------------------------------------------------------- /spec/fixtures/packages/wordcount/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wordcount", 3 | "version": "2.0.9" 4 | } 5 | -------------------------------------------------------------------------------- /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/packages/sublime-tabs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sublime-tabs", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /spec/fixtures/git/ignore.git/index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/spec/fixtures/git/ignore.git/index -------------------------------------------------------------------------------- /spec/fixtures/git/master.git/index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/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/functions/atom/master/static/images/octocat-spinner-128.gif -------------------------------------------------------------------------------- /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/functions/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/functions/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-invalid-styles/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "theme-with-invalid-styles", 3 | "theme": "ui" 4 | } 5 | -------------------------------------------------------------------------------- /spec/fixtures/packages/theme-with-syntax-variables/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": "syntax", 3 | "styleSheets": ["editor.less"] 4 | } 5 | -------------------------------------------------------------------------------- /script/rpmbuild: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | script/build 6 | script/grunt mkrpm publish-build --stack --no-color --install-dir /usr 7 | -------------------------------------------------------------------------------- /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/package-with-missing-consumed-services/index.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | activate: -> 3 | 4 | deactivate: -> 5 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-missing-provided-services/index.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | activate: -> 3 | 4 | deactivate: -> 5 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-no-activate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-no-activate", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-rb-filetype/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-rb-filetype", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /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-grammar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-invalid-grammar", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /resources/win/apm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | directory=$(dirname "$0") 4 | "$directory/../app/apm/bin/node.exe" "$directory/../app/apm/lib/cli.js" "$@" 5 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-invalid-settings/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-invalid-settings", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /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/package-with-invalid-context-menu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-invalid-context-menu", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /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-activation-hooks/index.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | activateCallCount: 0 3 | 4 | activate: -> 5 | @activateCallCount++ 6 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-different-directory-name/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-a-totally-different-name", 3 | "version": "1.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-invalid-url-package-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-invalid-url-package-json", 3 | "repository": "foo" 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/package-with-short-url-package-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-short-url-package-json", 3 | "repository": "example/repo" 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/integration/fixtures/atom-home/config.cson: -------------------------------------------------------------------------------- 1 | "*": 2 | welcome: 3 | showOnStartup: false 4 | "exception-reporting": 5 | userId: "7c0a3c52-795c-5e20-5323-64efcf91f212" 6 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-empty-activation-hooks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-empty-activation-hooks", 3 | "version": "0.1.0", 4 | "activationHooks": [] 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 | } -------------------------------------------------------------------------------- /static/babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "breakConfig": true, 3 | "sourceMap": "inline", 4 | "blacklist": ["es6.forOf", "useStrict"], 5 | "optional": ["asyncToGenerator"], 6 | "stage": 0 7 | } 8 | -------------------------------------------------------------------------------- /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.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 | -------------------------------------------------------------------------------- /script/grunt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var runGrunt = require('./utils/run-grunt.js'); 3 | 4 | // build/node_modules/.bin/grunt "$@" 5 | var args = process.argv.slice(2); 6 | runGrunt(args, process.exit); 7 | -------------------------------------------------------------------------------- /spec/fixtures/git/ignore.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/spec/fixtures/git/ignore.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7 -------------------------------------------------------------------------------- /spec/fixtures/git/ignore.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/spec/fixtures/git/ignore.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 -------------------------------------------------------------------------------- /spec/fixtures/git/ignore.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/spec/fixtures/git/ignore.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1 -------------------------------------------------------------------------------- /spec/fixtures/git/master.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/spec/fixtures/git/master.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7 -------------------------------------------------------------------------------- /spec/fixtures/git/master.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/atom/master/spec/fixtures/git/master.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 -------------------------------------------------------------------------------- /spec/fixtures/git/master.git/objects/ef/046e9eecaa5255ea5e9817132d4001724d6ae1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/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-activation-hooks/package.cson: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-activation-hooks", 3 | "version": "0.1.0", 4 | "activationHooks": ['language-fictitious:grammar-used'] 5 | } 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-empty-activation-commands/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-empty-activation-commands", 3 | "version": "0.1.0", 4 | "activationCommands": {"atom-workspace": []} 5 | } 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/special-token-symbols.coffee: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SoftTab: Symbol('SoftTab') 3 | HardTab: Symbol('HardTab') 4 | PairedCharacter: Symbol('PairedCharacter') 5 | SoftWrapIndent: Symbol('SoftWrapIndent') 6 | } 7 | -------------------------------------------------------------------------------- /spec/fixtures/git/working-dir/git.git/objects/06/15f9a45968b3515e0a202530ef9f61aba26b6c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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/functions/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 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-invalid-context-menu/menus/menu.json: -------------------------------------------------------------------------------- 1 | { 2 | "context-menu": { 3 | "<>": [ 4 | { 5 | "label": "Hello", 6 | "command:": "world" 7 | } 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.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/packages/package-with-rb-filetype/grammars/rb.cson: -------------------------------------------------------------------------------- 1 | 'name': 'Test Ruby' 2 | 'scopeName': 'test.rb' 3 | 'fileTypes': [ 4 | 'rb' 5 | ] 6 | 'patterns': [ 7 | { 8 | 'match': 'ruby' 9 | 'name': 'meta.class.ruby' 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-invalid-activation-commands/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-invalid-activation-commands", 3 | "version": "1.0.0", 4 | "activationCommands": { 5 | "<>": [ 6 | "foo:bar" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/safe-clipboard.coffee: -------------------------------------------------------------------------------- 1 | # Using clipboard in renderer process is not safe on Linux. 2 | module.exports = 3 | if process.platform is 'linux' and process.type is 'renderer' 4 | require('remote').require('clipboard') 5 | else 6 | require('clipboard') 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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": "1.0.2" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-missing-consumed-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-missing-consumed-services", 3 | 4 | "consumedServices": { 5 | "service-1": { 6 | "versions": { 7 | ">=0.1": "consumeMissingService" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /spec/fixtures/packages/package-with-missing-provided-services/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-with-missing-provided-services", 3 | 4 | "providedServices": { 5 | "service-1": { 6 | "description": "The first service", 7 | "versions": { 8 | "0.2.9": "provideMissingService" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /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/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var safeExec = require('./utils/child-process-wrapper.js').safeExec; 3 | var runGrunt = require('./utils/run-grunt.js'); 4 | var path = require('path'); 5 | 6 | process.chdir(path.dirname(__dirname)); 7 | 8 | safeExec('node script/bootstrap', function() { 9 | runGrunt(["ci", "--stack", "--no-color"], process.exit); 10 | }); 11 | -------------------------------------------------------------------------------- /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/package-with-provided-services/index.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | activate: -> 3 | 4 | deactivate: -> 5 | 6 | provideFirstServiceV2: -> 7 | 'first-service-v2' 8 | 9 | provideFirstServiceV3: -> 10 | 'first-service-v3' 11 | 12 | provideFirstServiceV4: -> 13 | 'first-service-v4' 14 | 15 | provideSecondService: -> 16 | 'second-service' 17 | -------------------------------------------------------------------------------- /src/marker-observation-window.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class MarkerObservationWindow 3 | constructor: (@displayBuffer, @bufferWindow) -> 4 | 5 | setScreenRange: (range) -> 6 | @bufferWindow.setRange(@displayBuffer.bufferRangeForScreenRange(range)) 7 | 8 | setBufferRange: (range) -> 9 | @bufferWindow.setRange(range) 10 | 11 | destroy: -> 12 | @bufferWindow.destroy() 13 | -------------------------------------------------------------------------------- /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/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var cp = require('./utils/child-process-wrapper.js'); 3 | var runGrunt = require('./utils/run-grunt.js'); 4 | var path = require('path'); 5 | 6 | process.chdir(path.dirname(__dirname)); 7 | 8 | cp.safeExec('node script/bootstrap', function() { 9 | // build/node_modules/.bin/grunt "$@" 10 | var args = process.argv.slice(2); 11 | runGrunt(args, process.exit); 12 | }); 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /spec/typescript-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "TypeScript transpiler support", -> 2 | describe "when there is a .ts file", -> 3 | it "transpiles it using typescript", -> 4 | transpiled = require('./fixtures/typescript/valid.ts') 5 | expect(transpiled(3)).toBe 4 6 | 7 | describe "when the .ts file is invalid", -> 8 | it "does not transpile", -> 9 | expect(-> require('./fixtures/typescript/invalid.ts')).toThrow() 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # VERSION: 0.1 2 | # DESCRIPTION: Image to build Atom and create a .rpm file 3 | 4 | # Base docker image 5 | FROM fedora:21 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 | nodejs \ 17 | npm 18 | 19 | RUN npm install -g npm@1.4.28 --loglevel error 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 | -------------------------------------------------------------------------------- /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 | directory=$(dirname "$0") 19 | 20 | if [ $EXPECT_OUTPUT ]; then 21 | "$directory/../../atom.exe" "$@" 22 | else 23 | "$directory/../app/apm/bin/node.exe" "$directory/atom.js" "$@" 24 | fi 25 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.2.9": "provideFirstServiceV2", 9 | "0.3.1": "provideFirstServiceV3", 10 | "0.4.1": "provideFirstServiceV4" 11 | } 12 | }, 13 | "service-2": { 14 | "description": "The second service", 15 | "versions": { 16 | "0.2.1": "provideSecondService" 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | return 11 | 12 | addCustomEventListeners: (customEventListeners) -> 13 | for name, listener of customEventListeners 14 | @customEventListeners[name] ?= [] 15 | @customEventListeners[name].push(listener) 16 | @getDOMNode().addEventListener(name, listener) 17 | return 18 | -------------------------------------------------------------------------------- /resources/linux/debian/control.in: -------------------------------------------------------------------------------- 1 | Package: <%= name %> 2 | Version: <%= version %> 3 | Depends: git, gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11 | libgcrypt20, libnotify4, libxtst6, libnss3, python, gvfs-bin, xdg-utils, libcap2 4 | Recommends: lsb-release 5 | Suggests: libgnome-keyring0, gir1.2-gnomekeyring-1.0 6 | Section: <%= section %> 7 | Priority: optional 8 | Architecture: <%= arch %> 9 | Installed-Size: <%= installedSize %> 10 | Maintainer: <%= maintainer %> 11 | Description: <%= description %> 12 | Atom is a free and open source text editor that is modern, approachable, and hackable to the core. 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /keymaps/emacs.cson: -------------------------------------------------------------------------------- 1 | 'atom-text-editor': 2 | 'alt-f': 'editor:move-to-end-of-word' 3 | 'alt-ctrl-f': 'editor:move-to-next-subword-boundary' 4 | 'alt-F': 'editor:select-to-end-of-word' 5 | 'alt-ctrl-F': 'editor:select-to-next-subword-boundary' 6 | 'alt-b': 'editor:move-to-beginning-of-word' 7 | 'alt-ctrl-b': 'editor:move-to-previous-subword-boundary' 8 | 'alt-B': 'editor:select-to-beginning-of-word' 9 | 'alt-ctrl-B': 'editor:select-to-previous-subword-boundary' 10 | 'alt-h': 'editor:delete-to-beginning-of-word' 11 | 'alt-ctrl-h': 'editor:delete-to-beginning-of-subword' 12 | 'alt-d': 'editor:delete-to-end-of-word' 13 | 'alt-ctrl-d': 'editor:delete-to-end-of-subword' 14 | -------------------------------------------------------------------------------- /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 | }; -------------------------------------------------------------------------------- /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/utils/run-grunt.js: -------------------------------------------------------------------------------- 1 | var cp = require('./child-process-wrapper.js'); 2 | var fs = require('fs'); 3 | var path = require('path'); 4 | 5 | module.exports = function(additionalArgs, callback) { 6 | var gruntPath = path.join('build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : ''); 7 | 8 | if (!fs.existsSync(gruntPath)) { 9 | console.error('Grunt command does not exist at: ' + gruntPath); 10 | console.error('Run script/bootstrap to install Grunt'); 11 | process.exit(1); 12 | } 13 | 14 | var args = ['--gruntfile', path.resolve('build', 'Gruntfile.coffee')]; 15 | args = args.concat(additionalArgs); 16 | cp.safeSpawn(gruntPath, args, callback); 17 | }; 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/text.less: -------------------------------------------------------------------------------- 1 | @import "ui-variables"; 2 | 3 | .text-bits (@type) { 4 | @text-color-name: "text-color-@{type}"; 5 | @bg-color-name: "background-color-@{type}"; 6 | 7 | @text-color: @@text-color-name; 8 | @bg-color: @@bg-color-name; 9 | 10 | code { 11 | color: @text-color; 12 | background: fadeout(@bg-color, 80%); 13 | } 14 | 15 | a, a code { 16 | text-decoration: underline; 17 | color: darken(@text-color, 10%); 18 | 19 | &:hover { 20 | color: darken(@text-color, 15%); 21 | } 22 | } 23 | } 24 | 25 | .text-info { 26 | .text-bits(info); 27 | } 28 | 29 | .text-success { 30 | .text-bits(success); 31 | } 32 | 33 | .text-warning { 34 | .text-bits(warning); 35 | } 36 | 37 | .text-error { 38 | .text-bits(error); 39 | } 40 | -------------------------------------------------------------------------------- /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 | "prefer_english_operator": { 18 | "level": "error" 19 | }, 20 | "colon_assignment_spacing": { 21 | "spacing": { 22 | "left": 0, 23 | "right": 1 24 | }, 25 | "level": "error" 26 | }, 27 | "braces_spacing": { 28 | "spaces": 0, 29 | "level": "error" 30 | }, 31 | "spacing_after_comma": { 32 | "level": "error" 33 | }, 34 | "no_stand_alone_at": { 35 | "level": "error" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /static/workspace-view.less: -------------------------------------------------------------------------------- 1 | @import "ui-variables"; 2 | @import "octicon-mixins"; 3 | 4 | @font-face { .octicon-font(); } 5 | 6 | html { 7 | font-family: @font-family; 8 | font-size: @font-size; 9 | } 10 | 11 | html, 12 | body { 13 | width: 100%; 14 | height: 100%; 15 | overflow: hidden; 16 | } 17 | 18 | atom-workspace { 19 | display: block; 20 | height: 100%; 21 | overflow: hidden; 22 | position: relative; 23 | color: @text-color; 24 | background-color: @app-background-color; 25 | font-family: @font-family; 26 | 27 | atom-workspace-axis.horizontal { 28 | display: -webkit-flex; 29 | height: 100%; 30 | } 31 | 32 | atom-workspace-axis.vertical { 33 | display: -webkit-flex; 34 | -webkit-flex: 1; 35 | -webkit-flex-flow: column; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /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 | # Each scope (e.g. '.source.coffee' above) can only be declared once. 17 | # 18 | # This file uses CoffeeScript Object Notation (CSON). 19 | # If you are unfamiliar with CSON, you can read more about it in the 20 | # Atom Flight Manual: 21 | # https://atom.io/docs/latest/using-atom-basic-customization#cson 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/model.coffee: -------------------------------------------------------------------------------- 1 | Grim = require 'grim' 2 | if Grim.includeDeprecatedAPIs 3 | module.exports = require('theorist').Model 4 | return 5 | 6 | PropertyAccessors = require 'property-accessors' 7 | 8 | nextInstanceId = 1 9 | 10 | module.exports = 11 | class Model 12 | PropertyAccessors.includeInto(this) 13 | 14 | @resetNextInstanceId: -> nextInstanceId = 1 15 | 16 | alive: true 17 | 18 | constructor: (params) -> 19 | @assignId(params?.id) 20 | 21 | assignId: (id) -> 22 | @id ?= id ? nextInstanceId++ 23 | 24 | @::advisedAccessor 'id', 25 | set: (id) -> nextInstanceId = id + 1 if id >= nextInstanceId 26 | 27 | destroy: -> 28 | return unless @isAlive() 29 | @alive = false 30 | @destroyed?() 31 | 32 | isAlive: -> @alive 33 | 34 | isDestroyed: -> not @isAlive() 35 | -------------------------------------------------------------------------------- /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/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 | @loadTime = 0 18 | this 19 | 20 | activate: -> 21 | return @activationDeferred.promise if @activationDeferred? 22 | 23 | @activationDeferred = Q.defer() 24 | @measure 'activateTime', => 25 | try 26 | @loadStylesheets() 27 | @activateNow() 28 | catch error 29 | @handleError("Failed to activate the #{@name} theme", error) 30 | 31 | @activationDeferred.promise 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | git: 2 | depth: 10 3 | 4 | branches: 5 | only: 6 | - master 7 | 8 | env: 9 | global: 10 | - ATOM_ACCESS_TOKEN=da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4 11 | - NODE_VERSION=0.12 12 | 13 | matrix: 14 | include: 15 | - os: linux 16 | - os: osx 17 | env: ATOM_SPECS_TASK=core 18 | - os: osx 19 | env: ATOM_SPECS_TASK=packages 20 | 21 | sudo: false 22 | 23 | install: 24 | - git clone https://github.com/creationix/nvm.git /tmp/.nvm 25 | - source /tmp/.nvm/nvm.sh 26 | - nvm install $NODE_VERSION 27 | - nvm use $NODE_VERSION 28 | 29 | script: script/cibuild 30 | 31 | notifications: 32 | email: 33 | on_success: never 34 | on_failure: change 35 | 36 | addons: 37 | apt: 38 | packages: 39 | - build-essential 40 | - git 41 | - libgnome-keyring-dev 42 | - fakeroot 43 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Atom Docs 2 | 3 | ![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png) 4 | 5 | Most of the Atom user and developer documentation is contained in the [Atom Docs](https://github.com/atom/docs) repository. 6 | 7 | In this directory you can only find very specific build and API level documentation. Some of this may eventually move to the docs repository as well. 8 | 9 | ## Build documentation 10 | 11 | Instructions for building Atom on various platforms from source. 12 | 13 | * [OS X](build-instructions/os-x.md) 14 | * [Windows](build-instructions/windows.md) 15 | * [Linux](build-instructions/linux.md) 16 | * [FreeBSD](build-instructions/freebsd.md) 17 | 18 | ## Other documentation here 19 | 20 | * [apm REST API](apm-rest-api.md) 21 | * [Tips for contributing to packages](contributing-to-packages.md) 22 | -------------------------------------------------------------------------------- /src/storage-folder.coffee: -------------------------------------------------------------------------------- 1 | path = require "path" 2 | fs = require "fs-plus" 3 | 4 | module.exports = 5 | class StorageFolder 6 | constructor: (containingPath) -> 7 | @path = path.join(containingPath, "storage") 8 | 9 | store: (name, object) -> 10 | fs.writeFileSync(@pathForKey(name), JSON.stringify(object), 'utf8') 11 | 12 | load: (name) -> 13 | statePath = @pathForKey(name) 14 | try 15 | stateString = fs.readFileSync(statePath, 'utf8') 16 | catch error 17 | unless error.code is 'ENOENT' 18 | console.warn "Error reading state file: #{statePath}", error.stack, error 19 | return undefined 20 | 21 | try 22 | JSON.parse(stateString) 23 | catch error 24 | console.warn "Error parsing state file: #{statePath}", error.stack, error 25 | 26 | pathForKey: (name) -> path.join(@getPath(), name) 27 | getPath: -> @path 28 | -------------------------------------------------------------------------------- /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 | ## Advanced Options 23 | 24 | ### Custom install directory 25 | 26 | ```sh 27 | sudo script/grunt install --install-dir /install/atom/here 28 | ``` 29 | 30 | ### Custom build directory 31 | 32 | ```sh 33 | script/build --build-dir /build/atom/here 34 | ``` 35 | 36 | ## Troubleshooting 37 | -------------------------------------------------------------------------------- /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/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 "badges"; 15 | @import "buttons"; 16 | @import "icons"; 17 | @import "links"; 18 | @import "panes"; 19 | @import "panels"; 20 | @import "sections"; 21 | @import "lists"; 22 | @import "popover-list"; 23 | @import "messages"; 24 | @import "markdown"; 25 | @import "text-editor-light"; 26 | @import "select-list"; 27 | @import "syntax"; 28 | @import "text"; 29 | @import "utilities"; 30 | @import "octicons"; 31 | -------------------------------------------------------------------------------- /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 and saved. 6 | * 7 | * Add your own CSS or Less to fully customize Atom. 8 | * If you are unfamiliar with Less, you can read more about it here: 9 | * http://lesscss.org 10 | */ 11 | 12 | 13 | /* 14 | * Examples 15 | * (To see them, uncomment and save) 16 | */ 17 | 18 | // style the background color of the tree view 19 | .tree-view { 20 | // background-color: whitesmoke; 21 | } 22 | 23 | // style the background and foreground colors on the atom-text-editor-element itself 24 | atom-text-editor { 25 | // color: white; 26 | // background-color: hsl(180, 24%, 12%); 27 | } 28 | 29 | // To style other content in the text editor's shadow DOM, use the ::shadow expression 30 | atom-text-editor::shadow .cursor { 31 | // border-color: red; 32 | } 33 | -------------------------------------------------------------------------------- /spec/babel-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "Babel transpiler support", -> 2 | describe 'when a .js file starts with /** @babel */;', -> 3 | it "transpiles it using babel", -> 4 | transpiled = require('./fixtures/babel/babel-comment.js') 5 | expect(transpiled(3)).toBe 4 6 | 7 | describe "when a .js file starts with 'use babel';", -> 8 | it "transpiles it using babel", -> 9 | transpiled = require('./fixtures/babel/babel-single-quotes.js') 10 | expect(transpiled(3)).toBe 4 11 | 12 | describe 'when a .js file starts with "use babel";', -> 13 | it "transpiles it using babel", -> 14 | transpiled = require('./fixtures/babel/babel-double-quotes.js') 15 | expect(transpiled(3)).toBe 4 16 | 17 | describe "when a .js file does not start with 'use babel';", -> 18 | it "does not transpile it using babel", -> 19 | expect(-> require('./fixtures/babel/invalid.js')).toThrow() 20 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 25 | body { 26 | font-family: inherit; // inherit from html 27 | font-size: inherit; // inherit from html 28 | } 29 | 30 | // Latest Bootstrap specifies the font properties again instead of inheriting 31 | .tooltip { 32 | font-family: @font-family; 33 | font-size: @font-size; 34 | } 35 | 36 | // disable some styling, will be styled in themes 37 | kbd { 38 | color: inherit; 39 | background-color: none; 40 | box-shadow: none; 41 | } 42 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /spec/default-directory-searcher-spec.coffee: -------------------------------------------------------------------------------- 1 | DefaultDirectorySearcher = require "../src/default-directory-searcher" 2 | Task = require "../src/task" 3 | path = require "path" 4 | 5 | describe "DefaultDirectorySearcher", -> 6 | [searcher, dirPath] = [] 7 | 8 | beforeEach -> 9 | dirPath = path.resolve(__dirname, 'fixtures', 'dir') 10 | searcher = new DefaultDirectorySearcher 11 | 12 | it "terminates the task after running a search", -> 13 | options = 14 | ignoreCase: false 15 | includeHidden: false 16 | excludeVcsIgnores: true 17 | inclusions: [] 18 | globalExclusions: ['a-dir'] 19 | didMatch: -> 20 | didError: -> 21 | didSearchPaths: -> 22 | searchPromise = searcher.search([{getPath: -> dirPath}], /abcdefg/, options) 23 | spyOn(Task::, 'terminate').andCallThrough() 24 | 25 | waitsForPromise -> searchPromise 26 | 27 | runs -> 28 | expect(Task::terminate).toHaveBeenCalled() 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 | -------------------------------------------------------------------------------- /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/) (0.10.x or 0.12.x) or [io.js](https://iojs.org) (1.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 | ### `script/build` Options 18 | * `--install-dir` - The full path to the final built application (must include `.app` in the path), e.g. `script/build --install-dir /Users/username/full/path/to/Atom.app` 19 | * `--build-dir` - Build the application in this directory. 20 | * `--verbose` - Verbose mode. A lot more information output. 21 | 22 | ## Troubleshooting 23 | 24 | ### OSX build error reports in atom/atom 25 | * 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. 26 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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. Unlike style sheets however, 6 | # each selector can only be declared once. 7 | # 8 | # You can create a new keybinding in this file by typing "key" and then hitting 9 | # tab. 10 | # 11 | # Here's an example taken from Atom's built-in keymap: 12 | # 13 | # 'atom-text-editor': 14 | # 'enter': 'editor:newline' 15 | # 16 | # 'atom-workspace': 17 | # 'ctrl-shift-p': 'core:move-up' 18 | # 'ctrl-p': 'core:move-down' 19 | # 20 | # You can find more information about keymaps in these guides: 21 | # * https://atom.io/docs/latest/using-atom-basic-customization#customizing-key-bindings 22 | # * https://atom.io/docs/latest/behind-atom-keymaps-in-depth 23 | # 24 | # This file uses CoffeeScript Object Notation (CSON). 25 | # If you are unfamiliar with CSON, you can read more about it in the 26 | # Atom Flight Manual: 27 | # https://atom.io/docs/latest/using-atom-basic-customization#cson 28 | -------------------------------------------------------------------------------- /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) 2015 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/input-component.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class InputComponent 3 | constructor: -> 4 | @domNode = document.createElement('input') 5 | @domNode.classList.add('hidden-input') 6 | @domNode.setAttribute('data-react-skip-selection-restoration', true) 7 | @domNode.style['-webkit-transform'] = 'translateZ(0)' 8 | @domNode.addEventListener 'paste', (event) -> event.preventDefault() 9 | 10 | getDomNode: -> 11 | @domNode 12 | 13 | updateSync: (state) -> 14 | @oldState ?= {} 15 | newState = state.hiddenInput 16 | 17 | if newState.top isnt @oldState.top 18 | @domNode.style.top = newState.top + 'px' 19 | @oldState.top = newState.top 20 | 21 | if newState.left isnt @oldState.left 22 | @domNode.style.left = newState.left + 'px' 23 | @oldState.left = newState.left 24 | 25 | if newState.width isnt @oldState.width 26 | @domNode.style.width = newState.width + 'px' 27 | @oldState.width = newState.width 28 | 29 | if newState.height isnt @oldState.height 30 | @domNode.style.height = newState.height + 'px' 31 | @oldState.height = newState.height 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/coffee-script.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var crypto = require('crypto') 4 | var path = require('path') 5 | var CoffeeScript = null 6 | 7 | exports.shouldCompile = function () { 8 | return true 9 | } 10 | 11 | exports.getCachePath = function (sourceCode) { 12 | return path.join( 13 | 'coffee', 14 | crypto 15 | .createHash('sha1') 16 | .update(sourceCode, 'utf8') 17 | .digest('hex') + '.js' 18 | ) 19 | } 20 | 21 | exports.compile = function (sourceCode, filePath) { 22 | if (!CoffeeScript) { 23 | var previousPrepareStackTrace = Error.prepareStackTrace 24 | CoffeeScript = require('coffee-script') 25 | 26 | // When it loads, coffee-script reassigns Error.prepareStackTrace. We have 27 | // already reassigned it via the 'source-map-support' module, so we need 28 | // to set it back. 29 | Error.prepareStackTrace = previousPrepareStackTrace 30 | } 31 | 32 | var output = CoffeeScript.compile(sourceCode, { 33 | filename: filePath, 34 | sourceFiles: [filePath], 35 | sourceMap: true 36 | }) 37 | 38 | var js = output.js 39 | js += '\n' 40 | js += '//# sourceMappingURL=data:application/json;base64,' 41 | js += new Buffer(output.v3SourceMap).toString('base64') 42 | js += '\n' 43 | return js 44 | } 45 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/gutter-component-helpers.coffee: -------------------------------------------------------------------------------- 1 | # Helper methods shared among GutterComponent classes. 2 | 3 | module.exports = 4 | createGutterView: (gutterModel) -> 5 | domNode = document.createElement('div') 6 | domNode.classList.add('gutter') 7 | domNode.setAttribute('gutter-name', gutterModel.name) 8 | childNode = document.createElement('div') 9 | if gutterModel.name is 'line-number' 10 | childNode.classList.add('line-numbers') 11 | else 12 | childNode.classList.add('custom-decorations') 13 | domNode.appendChild(childNode) 14 | domNode 15 | 16 | # Sets scrollHeight, scrollTop, and backgroundColor on the given domNode. 17 | setDimensionsAndBackground: (oldState, newState, domNode) -> 18 | if newState.scrollHeight isnt oldState.scrollHeight 19 | domNode.style.height = newState.scrollHeight + 'px' 20 | oldState.scrollHeight = newState.scrollHeight 21 | 22 | if newState.scrollTop isnt oldState.scrollTop 23 | domNode.style['-webkit-transform'] = "translate3d(0px, #{-newState.scrollTop}px, 0px)" 24 | oldState.scrollTop = newState.scrollTop 25 | 26 | if newState.backgroundColor isnt oldState.backgroundColor 27 | domNode.style.backgroundColor = newState.backgroundColor 28 | oldState.backgroundColor = newState.backgroundColor 29 | -------------------------------------------------------------------------------- /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/alerts.less"; 23 | @import "../node_modules/bootstrap/less/list-group.less"; 24 | @import "../node_modules/bootstrap/less/thumbnails.less"; 25 | @import "../node_modules/bootstrap/less/close.less"; 26 | 27 | // Components w/ JavaScript 28 | @import "../node_modules/bootstrap/less/tooltip.less"; 29 | 30 | // Utility classes 31 | @import "../node_modules/bootstrap/less/utilities.less"; 32 | -------------------------------------------------------------------------------- /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/scrollbar-corner-component.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class ScrollbarCornerComponent 3 | constructor: -> 4 | @domNode = document.createElement('div') 5 | @domNode.classList.add('scrollbar-corner') 6 | 7 | @contentNode = document.createElement('div') 8 | @domNode.appendChild(@contentNode) 9 | 10 | getDomNode: -> 11 | @domNode 12 | 13 | updateSync: (state) -> 14 | @oldState ?= {} 15 | @newState ?= {} 16 | 17 | newHorizontalState = state.horizontalScrollbar 18 | newVerticalState = state.verticalScrollbar 19 | @newState.visible = newHorizontalState.visible and newVerticalState.visible 20 | @newState.height = newHorizontalState.height 21 | @newState.width = newVerticalState.width 22 | 23 | if @newState.visible isnt @oldState.visible 24 | if @newState.visible 25 | @domNode.style.display = '' 26 | else 27 | @domNode.style.display = 'none' 28 | @oldState.visible = @newState.visible 29 | 30 | if @newState.height isnt @oldState.height 31 | @domNode.style.height = @newState.height + 'px' 32 | @contentNode.style.height = @newState.height + 1 + 'px' 33 | @oldState.height = @newState.height 34 | 35 | if @newState.width isnt @oldState.width 36 | @domNode.style.width = @newState.width + 'px' 37 | @contentNode.style.width = @newState.width + 1 + 'px' 38 | @oldState.width = @newState.width 39 | -------------------------------------------------------------------------------- /src/deprecated-packages.coffee: -------------------------------------------------------------------------------- 1 | semver = require 'semver' 2 | 3 | deprecatedPackages = require('../package.json')?._deprecatedPackages ? {} 4 | ranges = {} 5 | 6 | exports.getDeprecatedPackageMetadata = (name) -> 7 | metadata = null 8 | if deprecatedPackages.hasOwnProperty(name) 9 | metadata = deprecatedPackages[name] 10 | Object.freeze(metadata) if metadata 11 | metadata 12 | 13 | exports.isDeprecatedPackage = (name, version) -> 14 | return false unless deprecatedPackages.hasOwnProperty(name) 15 | 16 | deprecatedVersionRange = deprecatedPackages[name].version 17 | return true unless deprecatedVersionRange 18 | 19 | semver.valid(version) and satisfies(version, deprecatedVersionRange) 20 | 21 | satisfies = (version, rawRange) -> 22 | unless parsedRange = ranges[rawRange] 23 | parsedRange = new Range(rawRange) 24 | ranges[rawRange] = parsedRange 25 | parsedRange.test(version) 26 | 27 | # Extend semver.Range to memoize matched versions for speed 28 | class Range extends semver.Range 29 | constructor: -> 30 | super 31 | @matchedVersions = new Set() 32 | @unmatchedVersions = new Set() 33 | 34 | test: (version) -> 35 | return true if @matchedVersions.has(version) 36 | return false if @unmatchedVersions.has(version) 37 | 38 | matches = super 39 | if matches 40 | @matchedVersions.add(version) 41 | else 42 | @unmatchedVersions.add(version) 43 | matches 44 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | Requires: lsb-core-noarch 11 | 12 | %description 13 | <%= description %> 14 | 15 | %install 16 | mkdir -p %{buildroot}/<%= installDir %>/share/atom/ 17 | cp -r Atom/* %{buildroot}/<%= installDir %>/share/atom/ 18 | mkdir -p %{buildroot}/<%= installDir %>/bin/ 19 | ln -sf ../share/atom/resources/app/apm/node_modules/.bin/apm %{buildroot}/<%= installDir %>/bin/apm 20 | cp atom.sh %{buildroot}/<%= installDir %>/bin/atom 21 | chmod 755 %{buildroot}/<%= installDir %>/bin/atom 22 | mkdir -p %{buildroot}/<%= installDir %>/share/applications/ 23 | cp atom.desktop %{buildroot}/<%= installDir %>/share/applications/ 24 | 25 | # copy over icons in sizes that most desktop environments like 26 | for i in 1024 512 256 128 64 48 32 24 16 27 | do 28 | mkdir -p %{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps 29 | cp icons/${i}.png %{buildroot}/<%= installDir %>/share/icons/hicolor/${i}x${i}/apps/atom.png 30 | done 31 | 32 | %files 33 | <%= installDir %>/bin/atom 34 | <%= installDir %>/bin/apm 35 | <%= installDir %>/share/atom/ 36 | <%= installDir %>/share/applications/atom.desktop 37 | <%= installDir %>/share/icons/hicolor/ 38 | -------------------------------------------------------------------------------- /spec/integration/helpers/atom-launcher.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script wraps the `Atom` binary, allowing the `chromedriver` server to 4 | # execute it with positional arguments and environment variables. `chromedriver` 5 | # only allows 'switches' to be specified when starting a browser, not positional 6 | # arguments, so this script accepts the following special switches: 7 | # 8 | # * `atom-path`: The path to the `Atom` binary. 9 | # * `atom-args`: A space-separated list of positional arguments to pass to Atom. 10 | # * `atom-env`: A space-separated list of key=value pairs representing environment 11 | # variables to set for Atom. 12 | # 13 | # Any other switches will be passed through to `Atom`. 14 | 15 | atom_path="" 16 | atom_switches=() 17 | atom_args=() 18 | 19 | for arg in "$@"; do 20 | case $arg in 21 | --atom-path=*) 22 | atom_path="${arg#*=}" 23 | ;; 24 | 25 | --atom-args=*) 26 | atom_arg_string="${arg#*=}" 27 | for atom_arg in $atom_arg_string; do 28 | atom_args+=($atom_arg) 29 | done 30 | ;; 31 | 32 | --atom-env=*) 33 | atom_env_string="${arg#*=}" 34 | for atom_env_pair in $atom_env_string; do 35 | export $atom_env_pair 36 | done 37 | ;; 38 | 39 | *) 40 | atom_switches+=($arg) 41 | ;; 42 | esac 43 | done 44 | 45 | echo "Launching Atom" >&2 46 | echo ${atom_path} ${atom_args[@]} ${atom_switches[@]} >&2 47 | 48 | exec ${atom_path} ${atom_args[@]} ${atom_switches[@]} 49 | -------------------------------------------------------------------------------- /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/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/typescript.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var _ = require('underscore-plus') 4 | var crypto = require('crypto') 5 | var path = require('path') 6 | 7 | var defaultOptions = { 8 | target: 1, 9 | module: 'commonjs', 10 | sourceMap: true 11 | } 12 | 13 | var TypeScriptSimple = null 14 | var typescriptVersionDir = null 15 | 16 | exports.shouldCompile = function () { 17 | return true 18 | } 19 | 20 | exports.getCachePath = function (sourceCode) { 21 | if (typescriptVersionDir == null) { 22 | var version = require('typescript-simple/package.json').version 23 | typescriptVersionDir = path.join('ts', createVersionAndOptionsDigest(version, defaultOptions)) 24 | } 25 | 26 | return path.join( 27 | typescriptVersionDir, 28 | crypto 29 | .createHash('sha1') 30 | .update(sourceCode, 'utf8') 31 | .digest('hex') + '.js' 32 | ) 33 | } 34 | 35 | exports.compile = function (sourceCode, filePath) { 36 | if (!TypeScriptSimple) { 37 | TypeScriptSimple = require('typescript-simple').TypeScriptSimple 38 | } 39 | 40 | var options = _.defaults({filename: filePath}, defaultOptions) 41 | return new TypeScriptSimple(options, false).compile(sourceCode, filePath) 42 | } 43 | 44 | function createVersionAndOptionsDigest (version, options) { 45 | return crypto 46 | .createHash('sha1') 47 | .update('typescript', 'utf8') 48 | .update('\0', 'utf8') 49 | .update(version, 'utf8') 50 | .update('\0', 'utf8') 51 | .update(JSON.stringify(options), 'utf8') 52 | .digest('hex') 53 | } 54 | -------------------------------------------------------------------------------- /src/tiled-component.coffee: -------------------------------------------------------------------------------- 1 | cloneObject = (object) -> 2 | clone = {} 3 | clone[key] = value for key, value of object 4 | clone 5 | 6 | module.exports = 7 | class TiledComponent 8 | updateSync: (state) -> 9 | @newState = @getNewState(state) 10 | @oldState ?= @buildEmptyState() 11 | 12 | @beforeUpdateSync?(state) 13 | 14 | @removeTileNodes() if @shouldRecreateAllTilesOnUpdate?() 15 | @updateTileNodes() 16 | 17 | @afterUpdateSync?(state) 18 | 19 | removeTileNodes: -> 20 | @removeTileNode(tileRow) for tileRow of @oldState.tiles 21 | return 22 | 23 | removeTileNode: (tileRow) -> 24 | node = @componentsByTileId[tileRow].getDomNode() 25 | 26 | node.remove() 27 | delete @componentsByTileId[tileRow] 28 | delete @oldState.tiles[tileRow] 29 | 30 | updateTileNodes: -> 31 | @componentsByTileId ?= {} 32 | 33 | for tileRow of @oldState.tiles 34 | unless @newState.tiles.hasOwnProperty(tileRow) 35 | @removeTileNode(tileRow) 36 | 37 | for tileRow, tileState of @newState.tiles 38 | if @oldState.tiles.hasOwnProperty(tileRow) 39 | component = @componentsByTileId[tileRow] 40 | else 41 | component = @componentsByTileId[tileRow] = @buildComponentForTile(tileRow) 42 | 43 | @getTilesNode().appendChild(component.getDomNode()) 44 | @oldState.tiles[tileRow] = cloneObject(tileState) 45 | 46 | component.updateSync(@newState) 47 | 48 | return 49 | 50 | getComponentForTile: (tileRow) -> 51 | @componentsByTileId[tileRow] 52 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 32 | // For language entity colors 33 | @syntax-color-variable: #DF6A73; 34 | @syntax-color-constant: #DF6A73; 35 | @syntax-color-property: #DF6A73; 36 | @syntax-color-value: #D29B67; 37 | @syntax-color-function: #61AEEF; 38 | @syntax-color-method: @syntax-color-function; 39 | @syntax-color-class: #E5C17C; 40 | @syntax-color-keyword: #a431c4; 41 | @syntax-color-tag: #b72424; 42 | @syntax-color-attribute: #87400d; 43 | @syntax-color-import: #97C378; 44 | @syntax-color-snippet: #97C378; 45 | -------------------------------------------------------------------------------- /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 | 22 | unless safeMode 23 | @loadPaths.push(path.join(process.env.ATOM_HOME, 'dev', 'packages')) 24 | 25 | @loadPaths.push(path.join(process.env.ATOM_HOME, 'packages')) 26 | @loadPaths.push(path.join(resourcePath, 'node_modules')) 27 | 28 | @registerAtomProtocol() 29 | 30 | # Creates the 'atom' custom protocol handler. 31 | registerAtomProtocol: -> 32 | protocol.registerProtocol 'atom', (request) => 33 | relativePath = path.normalize(request.url.substr(7)) 34 | 35 | if relativePath.indexOf('assets/') is 0 36 | assetsPath = path.join(process.env.ATOM_HOME, relativePath) 37 | filePath = assetsPath if fs.statSyncNoException(assetsPath).isFile?() 38 | 39 | unless filePath 40 | for loadPath in @loadPaths 41 | filePath = path.join(loadPath, relativePath) 42 | break if fs.statSyncNoException(filePath).isFile?() 43 | 44 | new protocol.RequestFileJob(filePath) 45 | -------------------------------------------------------------------------------- /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', '.apm'], 26 | [home, '.atom', '.npm'], 27 | [home, '.atom', 'compile-cache'], 28 | [home, '.atom', 'atom-shell'], 29 | [tmpdir, 'atom-build'], 30 | [tmpdir, 'atom-cached-atom-shells'], 31 | ]; 32 | var run = function() { 33 | var next = commands.shift(); 34 | if (!next) 35 | process.exit(0); 36 | 37 | if (Array.isArray(next)) { 38 | var pathToRemove = path.resolve.apply(path.resolve, next); 39 | if (fs.existsSync(pathToRemove)) 40 | next = removeCommand + pathToRemove; 41 | else 42 | return run(); 43 | } 44 | 45 | cp.safeExec(next, run); 46 | }; 47 | run(); 48 | -------------------------------------------------------------------------------- /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 | setupDeprecations = -> 45 | Grim = require 'grim' 46 | Grim.on 'updated', -> 47 | deprecations = Grim.getDeprecations().map (deprecation) -> deprecation.serialize() 48 | Grim.clearDeprecations() 49 | emit('task:deprecations', deprecations) 50 | 51 | setupGlobals() 52 | handleEvents() 53 | setupDeprecations() 54 | handler = require(taskPath) 55 | -------------------------------------------------------------------------------- /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/latest/behind-atom-scoped-settings-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 | 48 | toString: -> 49 | @getScopeChain() 50 | -------------------------------------------------------------------------------- /src/token.coffee: -------------------------------------------------------------------------------- 1 | _ = require 'underscore-plus' 2 | 3 | StartDotRegex = /^\.?/ 4 | WhitespaceRegex = /\S/ 5 | 6 | # Represents a single unit of text as selected by a grammar. 7 | module.exports = 8 | class Token 9 | value: null 10 | hasPairedCharacter: false 11 | scopes: null 12 | isAtomic: null 13 | isHardTab: null 14 | firstNonWhitespaceIndex: null 15 | firstTrailingWhitespaceIndex: null 16 | hasInvisibleCharacters: false 17 | 18 | constructor: (properties) -> 19 | {@value, @scopes, @isAtomic, @isHardTab, @bufferDelta} = properties 20 | {@hasInvisibleCharacters, @hasPairedCharacter, @isSoftWrapIndentation} = properties 21 | @firstNonWhitespaceIndex = properties.firstNonWhitespaceIndex ? null 22 | @firstTrailingWhitespaceIndex = properties.firstTrailingWhitespaceIndex ? null 23 | 24 | @screenDelta = @value.length 25 | @bufferDelta ?= @screenDelta 26 | 27 | isEqual: (other) -> 28 | # TODO: scopes is deprecated. This is here for the sake of lang package tests 29 | @value is other.value and _.isEqual(@scopes, other.scopes) and !!@isAtomic is !!other.isAtomic 30 | 31 | isBracket: -> 32 | /^meta\.brace\b/.test(_.last(@scopes)) 33 | 34 | isOnlyWhitespace: -> 35 | not WhitespaceRegex.test(@value) 36 | 37 | matchesScopeSelector: (selector) -> 38 | targetClasses = selector.replace(StartDotRegex, '').split('.') 39 | _.any @scopes, (scope) -> 40 | scopeClasses = scope.split('.') 41 | _.isSubset(targetClasses, scopeClasses) 42 | 43 | hasLeadingWhitespace: -> 44 | @firstNonWhitespaceIndex? and @firstNonWhitespaceIndex > 0 45 | 46 | hasTrailingWhitespace: -> 47 | @firstTrailingWhitespaceIndex? and @firstTrailingWhitespaceIndex < @value.length 48 | -------------------------------------------------------------------------------- /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] is '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 is 'start' 40 | if /Thread \d+ Crashed::/.test line 41 | console.log line 42 | state = 'parse' 43 | else if state is 'parse' 44 | break if line is '' 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/clipboard.coffee: -------------------------------------------------------------------------------- 1 | crypto = require 'crypto' 2 | clipboard = require './safe-clipboard' 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` (optional) 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/default-directory-provider.coffee: -------------------------------------------------------------------------------- 1 | {Directory} = require 'pathwatcher' 2 | fs = require 'fs-plus' 3 | path = require 'path' 4 | url = require 'url' 5 | 6 | module.exports = 7 | class DefaultDirectoryProvider 8 | 9 | # Public: Create a Directory that corresponds to the specified URI. 10 | # 11 | # * `uri` {String} The path to the directory to add. This is guaranteed not to 12 | # be contained by a {Directory} in `atom.project`. 13 | # 14 | # Returns: 15 | # * {Directory} if the given URI is compatible with this provider. 16 | # * `null` if the given URI is not compatibile with this provider. 17 | directoryForURISync: (uri) -> 18 | normalizedPath = path.normalize(uri) 19 | {protocol} = url.parse(uri) 20 | directoryPath = if protocol? 21 | uri 22 | else if not fs.isDirectorySync(normalizedPath) and fs.isDirectorySync(path.dirname(normalizedPath)) 23 | path.dirname(normalizedPath) 24 | else 25 | normalizedPath 26 | 27 | # TODO: Stop normalizing the path in pathwatcher's Directory. 28 | directory = new Directory(directoryPath) 29 | if protocol? 30 | directory.path = directoryPath 31 | if fs.isCaseInsensitive() 32 | directory.lowerCasePath = directoryPath.toLowerCase() 33 | directory 34 | 35 | # Public: Create a Directory that corresponds to the specified URI. 36 | # 37 | # * `uri` {String} The path to the directory to add. This is guaranteed not to 38 | # be contained by a {Directory} in `atom.project`. 39 | # 40 | # Returns a Promise that resolves to: 41 | # * {Directory} if the given URI is compatible with this provider. 42 | # * `null` if the given URI is not compatibile with this provider. 43 | directoryForURI: (uri) -> 44 | Promise.resolve(@directoryForURISync(uri)) 45 | -------------------------------------------------------------------------------- /src/babel.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var crypto = require('crypto') 4 | var path = require('path') 5 | var defaultOptions = require('../static/babelrc.json') 6 | 7 | var babel = null 8 | var babelVersionDirectory = null 9 | 10 | var PREFIXES = [ 11 | '/** @babel */', 12 | '"use babel"', 13 | '\'use babel\'' 14 | ] 15 | 16 | var PREFIX_LENGTH = Math.max.apply(Math, PREFIXES.map(function (prefix) { 17 | return prefix.length 18 | })) 19 | 20 | exports.shouldCompile = function (sourceCode) { 21 | var start = sourceCode.substr(0, PREFIX_LENGTH) 22 | return PREFIXES.some(function (prefix) { 23 | return start.indexOf(prefix) === 0 24 | }) 25 | } 26 | 27 | exports.getCachePath = function (sourceCode) { 28 | if (babelVersionDirectory == null) { 29 | var babelVersion = require('babel-core/package.json').version 30 | babelVersionDirectory = path.join('js', 'babel', createVersionAndOptionsDigest(babelVersion, defaultOptions)) 31 | } 32 | 33 | return path.join( 34 | babelVersionDirectory, 35 | crypto 36 | .createHash('sha1') 37 | .update(sourceCode, 'utf8') 38 | .digest('hex') + '.js' 39 | ) 40 | } 41 | 42 | exports.compile = function (sourceCode, filePath) { 43 | if (!babel) { 44 | babel = require('babel-core') 45 | } 46 | 47 | var options = {filename: filePath} 48 | for (var key in defaultOptions) { 49 | options[key] = defaultOptions[key] 50 | } 51 | return babel.transform(sourceCode, options).code 52 | } 53 | 54 | function createVersionAndOptionsDigest (version, options) { 55 | return crypto 56 | .createHash('sha1') 57 | .update('babel-core', 'utf8') 58 | .update('\0', 'utf8') 59 | .update(version, 'utf8') 60 | .update('\0', 'utf8') 61 | .update(JSON.stringify(options), 'utf8') 62 | .digest('hex') 63 | } 64 | -------------------------------------------------------------------------------- /static/badges.less: -------------------------------------------------------------------------------- 1 | @import "ui-variables"; 2 | 3 | .badge { 4 | display: inline-block; 5 | line-height: 1; 6 | vertical-align: middle; 7 | font-weight: normal; 8 | text-align: center; 9 | white-space: nowrap; 10 | border-radius: 1em; 11 | 12 | &:empty { 13 | display: none; // Hide when un-used 14 | } 15 | 16 | 17 | // Color ---------------------- 18 | 19 | .badge-color( @fg: @text-color-selected; 20 | @bg: @background-color-selected; ) { 21 | color: @fg; 22 | background-color: @bg; 23 | } 24 | .badge-color(); 25 | &.badge-info { .badge-color(white, @background-color-info); } 26 | &.badge-success { .badge-color(white, @background-color-success); } 27 | &.badge-warning { .badge-color(white, @background-color-warning); } 28 | &.badge-error { .badge-color(white, @background-color-error); } 29 | 30 | 31 | // Size ---------------------- 32 | 33 | .badge-size( @size: @font-size; ) { 34 | @padding: round(@size/4); 35 | font-size: @size; 36 | min-width: @size + @padding*2; 37 | padding: @padding round(@padding*1.5); 38 | } 39 | .badge-size(); // default 40 | 41 | // Fixed size 42 | &.badge-large { .badge-size(18px); } 43 | &.badge-medium { .badge-size(14px); } 44 | &.badge-small { .badge-size(10px); } 45 | 46 | // Flexible size 47 | // The size changes depending on the parent element 48 | // Best used for larger sizes, since em's can cause rounding errors 49 | &.badge-flexible { 50 | @size: .8em; 51 | @padding: @size/2; 52 | font-size: @size; 53 | min-width: @size + @padding*2; 54 | padding: @padding @padding*1.5; 55 | } 56 | 57 | 58 | // Icon ---------------------- 59 | 60 | &.icon { 61 | font-size: round(@component-icon-size*0.8); 62 | padding: @component-icon-padding @component-icon-padding*2; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/scan-handler.coffee: -------------------------------------------------------------------------------- 1 | _ = require "underscore-plus" 2 | path = require "path" 3 | async = require "async" 4 | {PathSearcher, PathScanner, search} = require 'scandal' 5 | 6 | module.exports = (rootPaths, regexSource, options) -> 7 | callback = @async() 8 | 9 | rootPath = rootPaths[0] 10 | 11 | PATHS_COUNTER_SEARCHED_CHUNK = 50 12 | pathsSearched = 0 13 | 14 | searcher = new PathSearcher() 15 | 16 | searcher.on 'file-error', ({code, path, message}) -> 17 | emit('scan:file-error', {code, path, message}) 18 | 19 | searcher.on 'results-found', (result) -> 20 | emit('scan:result-found', result) 21 | 22 | flags = "g" 23 | flags += "i" if options.ignoreCase 24 | regex = new RegExp(regexSource, flags) 25 | 26 | async.each( 27 | rootPaths, 28 | (rootPath, next) -> 29 | options2 = _.extend {}, options, 30 | inclusions: processPaths(rootPath, options.inclusions) 31 | globalExclusions: processPaths(rootPath, options.globalExclusions) 32 | 33 | scanner = new PathScanner(rootPath, options2) 34 | 35 | scanner.on 'path-found', -> 36 | pathsSearched++ 37 | if pathsSearched % PATHS_COUNTER_SEARCHED_CHUNK is 0 38 | emit('scan:paths-searched', pathsSearched) 39 | 40 | search regex, scanner, searcher, -> 41 | emit('scan:paths-searched', pathsSearched) 42 | next() 43 | callback 44 | ) 45 | 46 | processPaths = (rootPath, paths) -> 47 | return paths unless paths?.length > 0 48 | rootPathBase = path.basename(rootPath) 49 | results = [] 50 | for givenPath in paths 51 | segments = givenPath.split(path.sep) 52 | firstSegment = segments.shift() 53 | results.push(givenPath) 54 | if firstSegment is rootPathBase 55 | if segments.length is 0 56 | results.push(path.join("**", "*")) 57 | else 58 | results.push(path.join(segments...)) 59 | results 60 | -------------------------------------------------------------------------------- /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-#{process.env.USER}.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 | -------------------------------------------------------------------------------- /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 | @emit 'update-available' 55 | 56 | @installUpdate (error) => 57 | if error? 58 | @emit 'update-not-available' 59 | return 60 | 61 | @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), 'https://atom.io', => @quitAndInstall() 62 | 63 | module.exports = new AutoUpdater() 64 | -------------------------------------------------------------------------------- /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/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 or process.env.CI 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 | 31 | if grim.getDeprecationsLength() > 0 32 | grim.logDeprecations() 33 | return atom.exit(1) 34 | 35 | if runner.results().failedCount > 0 36 | atom.exit(1) 37 | else 38 | atom.exit(0) 39 | else 40 | AtomReporter = require './atom-reporter' 41 | reporter = new AtomReporter() 42 | 43 | require specSuite 44 | 45 | jasmineEnv = jasmine.getEnv() 46 | jasmineEnv.addReporter(reporter) 47 | jasmineEnv.addReporter(timeReporter) 48 | jasmineEnv.setIncludedTags([process.platform]) 49 | 50 | $('body').append $$ -> @div id: 'jasmine-content' 51 | 52 | jasmineEnv.execute() 53 | 54 | disableFocusMethods = -> 55 | ['fdescribe', 'ffdescribe', 'fffdescribe', 'fit', 'ffit', 'fffit'].forEach (methodName) -> 56 | focusMethod = window[methodName] 57 | window[methodName] = (description) -> 58 | error = new Error('Focused spec is running on CI') 59 | focusMethod description, -> throw error 60 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | return 21 | 22 | unmerge = (menu, item) -> 23 | matchingItemIndex = findMatchingItemIndex(menu, item) 24 | matchingItem = menu[matchingItemIndex] unless matchingItemIndex is - 1 25 | 26 | if matchingItem? 27 | if item.submenu? 28 | unmerge(matchingItem.submenu, submenuItem) for submenuItem in item.submenu 29 | 30 | unless matchingItem.submenu?.length > 0 31 | menu.splice(matchingItemIndex, 1) 32 | 33 | findMatchingItemIndex = (menu, {type, label, submenu}) -> 34 | return -1 if type is 'separator' 35 | for item, index in menu 36 | if normalizeLabel(item.label) is normalizeLabel(label) and item.submenu? is submenu? 37 | return index 38 | -1 39 | 40 | normalizeLabel = (label) -> 41 | return undefined unless label? 42 | 43 | if process.platform is 'darwin' 44 | label 45 | else 46 | label.replace(/\&/g, '') 47 | 48 | cloneMenuItem = (item) -> 49 | item = _.pick(item, 'type', 'label', 'enabled', 'visible', 'command', 'submenu', 'commandDetail') 50 | if item.submenu? 51 | item.submenu = item.submenu.map (submenuItem) -> cloneMenuItem(submenuItem) 52 | item 53 | 54 | module.exports = {merge, unmerge, normalizeLabel, cloneMenuItem} 55 | -------------------------------------------------------------------------------- /spec/default-directory-provider-spec.coffee: -------------------------------------------------------------------------------- 1 | DefaultDirectoryProvider = require "../src/default-directory-provider" 2 | path = require "path" 3 | fs = require 'fs-plus' 4 | temp = require "temp" 5 | 6 | describe "DefaultDirectoryProvider", -> 7 | describe ".directoryForURISync(uri)", -> 8 | it "returns a Directory with a path that matches the uri", -> 9 | provider = new DefaultDirectoryProvider() 10 | tmp = temp.mkdirSync() 11 | 12 | directory = provider.directoryForURISync(tmp) 13 | expect(directory.getPath()).toEqual tmp 14 | 15 | it "normalizes its input before creating a Directory for it", -> 16 | provider = new DefaultDirectoryProvider() 17 | tmp = temp.mkdirSync() 18 | nonNormalizedPath = tmp + path.sep + ".." + path.sep + path.basename(tmp) 19 | expect(tmp.includes("..")).toBe false 20 | expect(nonNormalizedPath.includes("..")).toBe true 21 | 22 | directory = provider.directoryForURISync(nonNormalizedPath) 23 | expect(directory.getPath()).toEqual tmp 24 | 25 | it "creates a Directory for its parent dir when passed a file", -> 26 | provider = new DefaultDirectoryProvider() 27 | tmp = temp.mkdirSync() 28 | file = path.join(tmp, "example.txt") 29 | fs.writeFileSync(file, "data") 30 | 31 | directory = provider.directoryForURISync(file) 32 | expect(directory.getPath()).toEqual tmp 33 | 34 | it "creates a Directory with a path as a uri when passed a uri", -> 35 | provider = new DefaultDirectoryProvider() 36 | uri = 'remote://server:6792/path/to/a/dir' 37 | directory = provider.directoryForURISync(uri) 38 | expect(directory.getPath()).toEqual uri 39 | 40 | describe ".directoryForURI(uri)", -> 41 | it "returns a Promise that resolves to a Directory with a path that matches the uri", -> 42 | provider = new DefaultDirectoryProvider() 43 | tmp = temp.mkdirSync() 44 | 45 | waitsForPromise -> 46 | provider.directoryForURI(tmp).then (directory) -> 47 | expect(directory.getPath()).toEqual tmp 48 | -------------------------------------------------------------------------------- /src/overlay-manager.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class OverlayManager 3 | constructor: (@presenter, @container) -> 4 | @overlaysById = {} 5 | 6 | render: (state) -> 7 | for decorationId, overlay of state.content.overlays 8 | if @shouldUpdateOverlay(decorationId, overlay) 9 | @renderOverlay(state, decorationId, overlay) 10 | 11 | for id, {overlayNode} of @overlaysById 12 | unless state.content.overlays.hasOwnProperty(id) 13 | delete @overlaysById[id] 14 | overlayNode.remove() 15 | 16 | shouldUpdateOverlay: (decorationId, overlay) -> 17 | cachedOverlay = @overlaysById[decorationId] 18 | return true unless cachedOverlay? 19 | cachedOverlay.pixelPosition?.top isnt overlay.pixelPosition?.top or 20 | cachedOverlay.pixelPosition?.left isnt overlay.pixelPosition?.left 21 | 22 | measureOverlays: -> 23 | for decorationId, {itemView} of @overlaysById 24 | @measureOverlay(decorationId, itemView) 25 | 26 | measureOverlay: (decorationId, itemView) -> 27 | contentMargin = parseInt(getComputedStyle(itemView)['margin-left']) ? 0 28 | @presenter.setOverlayDimensions(decorationId, itemView.offsetWidth, itemView.offsetHeight, contentMargin) 29 | 30 | renderOverlay: (state, decorationId, {item, pixelPosition, class: klass}) -> 31 | itemView = atom.views.getView(item) 32 | cachedOverlay = @overlaysById[decorationId] 33 | unless overlayNode = cachedOverlay?.overlayNode 34 | overlayNode = document.createElement('atom-overlay') 35 | overlayNode.classList.add(klass) if klass? 36 | @container.appendChild(overlayNode) 37 | @overlaysById[decorationId] = cachedOverlay = {overlayNode, itemView} 38 | 39 | # The same node may be used in more than one overlay. This steals the node 40 | # back if it has been displayed in another overlay. 41 | overlayNode.appendChild(itemView) if overlayNode.childNodes.length is 0 42 | 43 | cachedOverlay.pixelPosition = pixelPosition 44 | overlayNode.style.top = pixelPosition.top + 'px' 45 | overlayNode.style.left = pixelPosition.left + 'px' 46 | -------------------------------------------------------------------------------- /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 | You can also run dev mode from the command line with `atom --dev`. 45 | 46 | To load your package in development mode, create a symlink to it in 47 | `~/.atom/dev/packages`. This occurs automatically when you clone the package 48 | with `apm develop`. You can also run `apm link --dev` and `apm unlink --dev` 49 | from the package directory to create and remove dev-mode symlinks. 50 | 51 | ### Installing Dependencies 52 | 53 | You'll want to keep dependencies up to date by running `apm update` after pulling any upstream changes. 54 | -------------------------------------------------------------------------------- /spec/workspace-element-spec.coffee: -------------------------------------------------------------------------------- 1 | ipc = require 'ipc' 2 | path = require 'path' 3 | temp = require('temp').track() 4 | 5 | describe "WorkspaceElement", -> 6 | workspaceElement = null 7 | 8 | beforeEach -> 9 | workspaceElement = atom.views.getView(atom.workspace) 10 | 11 | describe "the 'window:run-package-specs' command", -> 12 | it "runs the package specs for the active item's project path, or the first project path", -> 13 | spyOn(ipc, 'send') 14 | 15 | # No project paths. Don't try to run specs. 16 | atom.commands.dispatch(workspaceElement, "window:run-package-specs") 17 | expect(ipc.send).not.toHaveBeenCalledWith("run-package-specs") 18 | 19 | projectPaths = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")] 20 | atom.project.setPaths(projectPaths) 21 | 22 | # No active item. Use first project directory. 23 | atom.commands.dispatch(workspaceElement, "window:run-package-specs") 24 | expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec")) 25 | ipc.send.reset() 26 | 27 | # Active item doesn't implement ::getPath(). Use first project directory. 28 | item = document.createElement("div") 29 | atom.workspace.getActivePane().activateItem(item) 30 | atom.commands.dispatch(workspaceElement, "window:run-package-specs") 31 | expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec")) 32 | ipc.send.reset() 33 | 34 | # Active item has no path. Use first project directory. 35 | item.getPath = -> null 36 | atom.commands.dispatch(workspaceElement, "window:run-package-specs") 37 | expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec")) 38 | ipc.send.reset() 39 | 40 | # Active item has path. Use project path for item path. 41 | item.getPath = -> path.join(projectPaths[1], "a-file.txt") 42 | atom.commands.dispatch(workspaceElement, "window:run-package-specs") 43 | expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[1], "spec")) 44 | ipc.send.reset() 45 | -------------------------------------------------------------------------------- /src/cursors-component.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | class CursorsComponent 3 | oldState: null 4 | 5 | constructor: -> 6 | @cursorNodesById = {} 7 | @domNode = document.createElement('div') 8 | @domNode.classList.add('cursors') 9 | 10 | getDomNode: -> 11 | @domNode 12 | 13 | updateSync: (state) -> 14 | newState = state.content 15 | @oldState ?= {cursors: {}} 16 | 17 | # update blink class 18 | if newState.cursorsVisible isnt @oldState.cursorsVisible 19 | if newState.cursorsVisible 20 | @domNode.classList.remove 'blink-off' 21 | else 22 | @domNode.classList.add 'blink-off' 23 | @oldState.cursorsVisible = newState.cursorsVisible 24 | 25 | # remove cursors 26 | for id of @oldState.cursors 27 | unless newState.cursors[id]? 28 | @cursorNodesById[id].remove() 29 | delete @cursorNodesById[id] 30 | delete @oldState.cursors[id] 31 | 32 | # add or update cursors 33 | for id, cursorState of newState.cursors 34 | unless @oldState.cursors[id]? 35 | cursorNode = document.createElement('div') 36 | cursorNode.classList.add('cursor') 37 | @cursorNodesById[id] = cursorNode 38 | @domNode.appendChild(cursorNode) 39 | @updateCursorNode(id, cursorState) 40 | 41 | return 42 | 43 | updateCursorNode: (id, newCursorState) -> 44 | cursorNode = @cursorNodesById[id] 45 | oldCursorState = (@oldState.cursors[id] ?= {}) 46 | 47 | if newCursorState.top isnt oldCursorState.top or newCursorState.left isnt oldCursorState.left 48 | cursorNode.style['-webkit-transform'] = "translate(#{newCursorState.left}px, #{newCursorState.top}px)" 49 | oldCursorState.top = newCursorState.top 50 | oldCursorState.left = newCursorState.left 51 | 52 | if newCursorState.height isnt oldCursorState.height 53 | cursorNode.style.height = newCursorState.height + 'px' 54 | oldCursorState.height = newCursorState.height 55 | 56 | if newCursorState.width isnt oldCursorState.width 57 | cursorNode.style.width = newCursorState.width + 'px' 58 | oldCursorState.width = newCursorState.width 59 | -------------------------------------------------------------------------------- /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 | position: relative; 8 | display: -webkit-flex; 9 | -webkit-flex: 1; 10 | 11 | atom-pane-axis { 12 | display: -webkit-flex; 13 | -webkit-flex: 1; 14 | 15 | & > atom-pane-resize-handle { 16 | position: absolute; 17 | z-index: 3; 18 | } 19 | } 20 | 21 | atom-pane-axis.vertical { 22 | -webkit-flex-direction: column; 23 | 24 | & > atom-pane-resize-handle { 25 | width: 100%; 26 | height: 8px; 27 | margin-top: -4px; 28 | cursor: row-resize; 29 | border-bottom: none; 30 | } 31 | } 32 | 33 | atom-pane-axis.horizontal { 34 | -webkit-flex-direction: row; 35 | 36 | & > atom-pane-resize-handle { 37 | width: 8px; 38 | height: 100%; 39 | margin-left: -4px; 40 | cursor: col-resize; 41 | border-right: none; 42 | } 43 | } 44 | 45 | atom-pane { 46 | position: relative; 47 | display: -webkit-flex; 48 | -webkit-flex: 1; 49 | -webkit-flex-direction: column; 50 | overflow: visible; 51 | 52 | .item-views { 53 | -webkit-flex: 1; 54 | display: -webkit-flex; 55 | min-height: 0; 56 | min-width: 0; 57 | position: relative; 58 | 59 | .pane-item { 60 | color: @text-color; 61 | background-color: @pane-item-background-color; 62 | } 63 | 64 | > *, > atom-text-editor.react > * { 65 | position: absolute; 66 | top: 0; 67 | right: 0; 68 | bottom: 0; 69 | left: 0; 70 | } 71 | } 72 | } 73 | } 74 | 75 | // Windows doesn't have row- and col-resize cursors 76 | .platform-win32 { 77 | atom-pane-container { 78 | atom-pane-axis.vertical { 79 | & > atom-pane-resize-handle { 80 | cursor: ns-resize; 81 | } 82 | } 83 | 84 | atom-pane-axis.horizontal { 85 | & > atom-pane-resize-handle { 86 | cursor: ew-resize; 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/token-iterator.coffee: -------------------------------------------------------------------------------- 1 | {SoftTab, HardTab, PairedCharacter, SoftWrapIndent} = require './special-token-symbols' 2 | 3 | module.exports = 4 | class TokenIterator 5 | constructor: (line) -> 6 | @reset(line) if line? 7 | 8 | reset: (@line) -> 9 | @index = null 10 | @bufferStart = @line.startBufferColumn 11 | @bufferEnd = @bufferStart 12 | @screenStart = 0 13 | @screenEnd = 0 14 | @scopes = @line.openScopes.map (id) -> atom.grammars.scopeForId(id) 15 | @scopeStarts = @scopes.slice() 16 | @scopeEnds = [] 17 | this 18 | 19 | next: -> 20 | {tags} = @line 21 | 22 | if @index? 23 | @index++ 24 | @scopeEnds.length = 0 25 | @scopeStarts.length = 0 26 | @bufferStart = @bufferEnd 27 | @screenStart = @screenEnd 28 | else 29 | @index = 0 30 | 31 | while @index < tags.length 32 | tag = tags[@index] 33 | if tag < 0 34 | if tag % 2 is 0 35 | @scopeEnds.push(atom.grammars.scopeForId(tag + 1)) 36 | @scopes.pop() 37 | else 38 | scope = atom.grammars.scopeForId(tag) 39 | @scopeStarts.push(scope) 40 | @scopes.push(scope) 41 | @index++ 42 | else 43 | if @isHardTab() 44 | @screenEnd = @screenStart + tag 45 | @bufferEnd = @bufferStart + 1 46 | else if @isSoftWrapIndentation() 47 | @screenEnd = @screenStart + tag 48 | @bufferEnd = @bufferStart + 0 49 | else 50 | @screenEnd = @screenStart + tag 51 | @bufferEnd = @bufferStart + tag 52 | return true 53 | 54 | false 55 | 56 | getBufferStart: -> @bufferStart 57 | getBufferEnd: -> @bufferEnd 58 | 59 | getScreenStart: -> @screenStart 60 | getScreenEnd: -> @screenEnd 61 | 62 | getScopeStarts: -> @scopeStarts 63 | getScopeEnds: -> @scopeEnds 64 | 65 | getScopes: -> @scopes 66 | 67 | getText: -> 68 | @line.text.substring(@screenStart, @screenEnd) 69 | 70 | isSoftTab: -> 71 | @line.specialTokens[@index] is SoftTab 72 | 73 | isHardTab: -> 74 | @line.specialTokens[@index] is HardTab 75 | 76 | isSoftWrapIndentation: -> 77 | @line.specialTokens[@index] is SoftWrapIndent 78 | 79 | isPairedCharacter: -> 80 | @line.specialTokens[@index] is PairedCharacter 81 | 82 | isAtomic: -> 83 | @isSoftTab() or @isHardTab() or @isSoftWrapIndentation() or @isPairedCharacter() 84 | -------------------------------------------------------------------------------- /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/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 | return 39 | 40 | # Public: Deserialize the state and params. 41 | # 42 | # * `state` The state {Object} to deserialize. 43 | # * `params` The params {Object} to pass as the second arguments to the 44 | # deserialize method of the deserializer. 45 | deserialize: (state, params) -> 46 | return unless state? 47 | 48 | if deserializer = @get(state) 49 | stateVersion = state.get?('version') ? state.version 50 | return if deserializer.version? and deserializer.version isnt stateVersion 51 | deserializer.deserialize(state, params) 52 | else 53 | console.warn "No deserializer found for", state 54 | 55 | # Get the deserializer for the state. 56 | # 57 | # * `state` The state {Object} being deserialized. 58 | get: (state) -> 59 | return unless state? 60 | 61 | name = state.get?('deserializer') ? state.deserializer 62 | @deserializers[name] 63 | 64 | if Grim.includeDeprecatedAPIs 65 | DeserializerManager::remove = (classes...) -> 66 | Grim.deprecate("Call .dispose() on the Disposable return from ::add instead") 67 | delete @deserializers[name] for {name} in classes 68 | return 69 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /spec/gutter-spec.coffee: -------------------------------------------------------------------------------- 1 | Gutter = require '../src/gutter' 2 | 3 | describe 'Gutter', -> 4 | fakeGutterContainer = {} 5 | name = 'name' 6 | 7 | describe '::hide', -> 8 | it 'hides the gutter if it is visible.', -> 9 | options = 10 | name: name 11 | visible: true 12 | gutter = new Gutter fakeGutterContainer, options 13 | events = [] 14 | gutter.onDidChangeVisible (gutter) -> 15 | events.push gutter.isVisible() 16 | 17 | expect(gutter.isVisible()).toBe true 18 | gutter.hide() 19 | expect(gutter.isVisible()).toBe false 20 | expect(events).toEqual [false] 21 | gutter.hide() 22 | expect(gutter.isVisible()).toBe false 23 | # An event should only be emitted when the visibility changes. 24 | expect(events.length).toBe 1 25 | 26 | describe '::show', -> 27 | it 'shows the gutter if it is hidden.', -> 28 | options = 29 | name: name 30 | visible: false 31 | gutter = new Gutter fakeGutterContainer, options 32 | events = [] 33 | gutter.onDidChangeVisible (gutter) -> 34 | events.push gutter.isVisible() 35 | 36 | expect(gutter.isVisible()).toBe false 37 | gutter.show() 38 | expect(gutter.isVisible()).toBe true 39 | expect(events).toEqual [true] 40 | gutter.show() 41 | expect(gutter.isVisible()).toBe true 42 | # An event should only be emitted when the visibility changes. 43 | expect(events.length).toBe 1 44 | 45 | describe '::destroy', -> 46 | [mockGutterContainer, mockGutterContainerRemovedGutters] = [] 47 | 48 | beforeEach -> 49 | mockGutterContainerRemovedGutters = [] 50 | mockGutterContainer = removeGutter: (destroyedGutter) -> 51 | mockGutterContainerRemovedGutters.push destroyedGutter 52 | 53 | it 'removes the gutter from its container.', -> 54 | gutter = new Gutter mockGutterContainer, {name} 55 | gutter.destroy() 56 | expect(mockGutterContainerRemovedGutters).toEqual([gutter]) 57 | 58 | it 'calls all callbacks registered on ::onDidDestroy.', -> 59 | gutter = new Gutter mockGutterContainer, {name} 60 | didDestroy = false 61 | gutter.onDidDestroy -> 62 | didDestroy = true 63 | gutter.destroy() 64 | expect(didDestroy).toBe true 65 | 66 | it 'does not allow destroying the line-number gutter', -> 67 | gutter = new Gutter mockGutterContainer, {name: 'line-number'} 68 | expect(gutter.destroy).toThrow() 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 | -------------------------------------------------------------------------------- /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 | Grim = require 'grim' 7 | 8 | bundledKeymaps = require('../package.json')?._atomKeymaps 9 | 10 | KeymapManager::onDidLoadBundledKeymaps = (callback) -> 11 | @emitter.on 'did-load-bundled-keymaps', callback 12 | 13 | KeymapManager::loadBundledKeymaps = -> 14 | keymapsPath = path.join(@resourcePath, 'keymaps') 15 | if bundledKeymaps? 16 | for keymapName, keymap of bundledKeymaps 17 | keymapPath = path.join(keymapsPath, keymapName) 18 | @add(keymapPath, keymap) 19 | else 20 | @loadKeymap(keymapsPath) 21 | 22 | @emitter.emit 'did-load-bundled-keymaps' 23 | 24 | KeymapManager::getUserKeymapPath = -> 25 | if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap')) 26 | userKeymapPath 27 | else 28 | path.join(@configDirPath, 'keymap.cson') 29 | 30 | KeymapManager::loadUserKeymap = -> 31 | userKeymapPath = @getUserKeymapPath() 32 | return unless fs.isFileSync(userKeymapPath) 33 | 34 | try 35 | @loadKeymap(userKeymapPath, watch: true, suppressErrors: true) 36 | catch error 37 | if error.message.indexOf('Unable to watch path') > -1 38 | message = """ 39 | Unable to watch path: `#{path.basename(userKeymapPath)}`. Make sure you 40 | have permission to read `#{userKeymapPath}`. 41 | 42 | On linux there are currently problems with watch sizes. See 43 | [this document][watches] for more info. 44 | [watches]:https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#typeerror-unable-to-watch-path 45 | """ 46 | atom.notifications.addError(message, {dismissable: true}) 47 | else 48 | detail = error.path 49 | stack = error.stack 50 | atom.notifications.addFatalError(error.message, {detail, stack, dismissable: true}) 51 | 52 | KeymapManager::subscribeToFileReadFailure = -> 53 | @onDidFailToReadFile (error) => 54 | userKeymapPath = @getUserKeymapPath() 55 | message = "Failed to load `#{userKeymapPath}`" 56 | 57 | detail = if error.location? 58 | error.stack 59 | else 60 | error.message 61 | 62 | atom.notifications.addError(message, {detail, dismissable: true}) 63 | 64 | # This enables command handlers registered via jQuery to call 65 | # `.abortKeyBinding()` on the `jQuery.Event` object passed to the handler. 66 | jQuery.Event::abortKeyBinding = -> 67 | @originalEvent?.abortKeyBinding?() 68 | 69 | module.exports = KeymapManager 70 | -------------------------------------------------------------------------------- /src/gutter.coffee: -------------------------------------------------------------------------------- 1 | {Emitter} = require 'event-kit' 2 | 3 | # Public: This class represents a gutter within a TextEditor. 4 | 5 | DefaultPriority = -100 6 | 7 | module.exports = 8 | class Gutter 9 | # * `gutterContainer` The {GutterContainer} object to which this gutter belongs. 10 | # * `options` An {Object} with the following fields: 11 | # * `name` (required) A unique {String} to identify this gutter. 12 | # * `priority` (optional) A {Number} that determines stacking order between 13 | # gutters. Lower priority items are forced closer to the edges of the 14 | # window. (default: -100) 15 | # * `visible` (optional) {Boolean} specifying whether the gutter is visible 16 | # initially after being created. (default: true) 17 | constructor: (gutterContainer, options) -> 18 | @gutterContainer = gutterContainer 19 | @name = options?.name 20 | @priority = options?.priority ? DefaultPriority 21 | @visible = options?.visible ? true 22 | 23 | @emitter = new Emitter 24 | 25 | destroy: -> 26 | if @name is 'line-number' 27 | throw new Error('The line-number gutter cannot be destroyed.') 28 | else 29 | @gutterContainer.removeGutter(this) 30 | @emitter.emit 'did-destroy' 31 | @emitter.dispose() 32 | 33 | hide: -> 34 | if @visible 35 | @visible = false 36 | @emitter.emit 'did-change-visible', this 37 | 38 | show: -> 39 | if not @visible 40 | @visible = true 41 | @emitter.emit 'did-change-visible', this 42 | 43 | isVisible: -> 44 | @visible 45 | 46 | # * `marker` (required) A Marker object. 47 | # * `options` (optional) An object with the following fields: 48 | # * `class` (optional) 49 | # * `item` (optional) A model {Object} with a corresponding view registered, 50 | # or an {HTMLElement}. 51 | # 52 | # Returns a {Decoration} object. 53 | decorateMarker: (marker, options) -> 54 | @gutterContainer.addGutterDecoration(this, marker, options) 55 | 56 | # Calls your `callback` when the {Gutter}'s' visibility changes. 57 | # 58 | # * `callback` {Function} 59 | # * `gutter` The {Gutter} whose visibility changed. 60 | # 61 | # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. 62 | onDidChangeVisible: (callback) -> 63 | @emitter.on 'did-change-visible', callback 64 | 65 | # Calls your `callback` when the {Gutter} is destroyed 66 | # 67 | # * `callback` {Function} 68 | # 69 | # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. 70 | onDidDestroy: (callback) -> 71 | @emitter.on 'did-destroy', callback 72 | --------------------------------------------------------------------------------