Comparar commits
401 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 85df5e61e5 | |||
| 5e477ff984 | |||
| 2baf9eda61 | |||
| 7d6d8175b9 | |||
| 0fdda032cc | |||
| c82d0f8c1c | |||
| 65ff108615 | |||
| 075611eb65 | |||
| b82537b020 | |||
| 06fee4636a | |||
| 5fe1af3239 | |||
| bf6cc3d384 | |||
| b4a4ba91b0 | |||
| 271776944a | |||
| b1d5a3d75f | |||
| bd68790a10 | |||
| f0a7663447 | |||
| db627d65c7 | |||
| a9f581797a | |||
| 763291230d | |||
| 55a77a34bd | |||
| f4f975c6b7 | |||
| 2d26382510 | |||
| c5cd56a99e | |||
| 24943dd526 | |||
| 8b32e30ee7 | |||
| 72c99be0f2 | |||
| 10ac1f6ae8 | |||
| 524170534c | |||
| d542f35336 | |||
| 697ba53c6b | |||
| 148a8bad2e | |||
| 7a344b91aa | |||
| 5783350484 | |||
| 9fce23d5ac | |||
| 7c17c99b9e | |||
| ff560bc3a3 | |||
| 61f01f4713 | |||
| 2e8c0234bb | |||
| 8e62d772b3 | |||
| 532cfb5775 | |||
| f912eb805d | |||
| 6838ff8ea2 | |||
| 8aa2c40bbf | |||
| c2d603769e | |||
| 3710d85e63 | |||
| 12a72302d9 | |||
| 2c70f0dc27 | |||
| 6165c65a51 | |||
| 3ea3f64214 | |||
| 08601d32a3 | |||
| 0ae1f6858c | |||
| f2e5b480e1 | |||
| 19ab197bc1 | |||
| 8bf1464b64 | |||
| 0ee3421cbc | |||
| a18536e8a4 | |||
| cc2e1eecd3 | |||
| 87b95128f9 | |||
| 344a56b47a | |||
| da8d055817 | |||
| c07272633f | |||
| b26e0d42d5 | |||
| 8ee4e927a1 | |||
| 7eaa3cb2b6 | |||
| 696928540c | |||
| b33f36d30a | |||
| 179b392a49 | |||
| 857f19c382 | |||
| 8a333208a2 | |||
| ff23f62c3e | |||
| dcdc9d6b90 | |||
| 3d28f957c7 | |||
| 2eb2aa5bef | |||
| 371820fd59 | |||
| 596c584ef1 | |||
| 27a1577021 | |||
| 8f2745c248 | |||
| 1c964d05f8 | |||
| 2dcbf7f751 | |||
| 067f73da38 | |||
| ae324c13a6 | |||
| 9a488adbb9 | |||
| 4c0f1efec6 | |||
| 8974cb5f34 | |||
| cb303a3149 | |||
| c44628a5b1 | |||
| fb1effc654 | |||
| 5ab213b854 | |||
| bbf738635c | |||
| 705d3e9fbc | |||
| 6bd3728548 | |||
| 7d997f6d9a | |||
| e919eb3eba | |||
| c2b2096c8c | |||
| 46638d2ea1 | |||
| fdb08517d3 | |||
| f272962562 | |||
| 9e661d8a99 | |||
| 43c0b79273 | |||
| 96e96c3c7f | |||
| 15c51b4417 | |||
| 6c93ca0e42 | |||
| a3cb98a3d3 | |||
| 31ecd39f08 | |||
| 4d986b8417 | |||
| 2d14c06089 | |||
| 7746ad0b13 | |||
| 1cbaf8d1f5 | |||
| cb41e2c41a | |||
| 2fd71f2fa8 | |||
| 37d67e8a83 | |||
| 2f8e67d679 | |||
| 22dc165a25 | |||
| ebfe50aafc | |||
| de58936ed1 | |||
| eba2abd5d9 | |||
| 864ab0c095 | |||
| de3d424f51 | |||
| 68c2c18d83 | |||
| 54907455fe | |||
| ba8ab21a0d | |||
| f272d9abde | |||
| 972f194388 | |||
| adb2f31e7f | |||
| ccfd239ad1 | |||
| 6fc56b9372 | |||
| 9072a6da7a | |||
| d39547097c | |||
| 3b2f58fa22 | |||
| cbddc4eb6f | |||
| 96a0c1039a | |||
| 1390bef626 | |||
| e70a2ab3de | |||
| e0d1bdc072 | |||
| 79c60d3884 | |||
| 1e85bc66b4 | |||
| 0d633a1e27 | |||
| 0759f6a1fd | |||
| 99b5675c4e | |||
| 4f7957183c | |||
| 2de18d3c4d | |||
| fecf13e2df | |||
| 31e44d50e4 | |||
| c28aeeac4a | |||
| 5649de6cd1 | |||
| 26a649abda | |||
| 3b02ae1ce9 | |||
| 13278c3d40 | |||
| 17760a458a | |||
| 282814fe59 | |||
| 35fb02fce9 | |||
| 7286c339c8 | |||
| b956fa4d1f | |||
| 8cb66895f0 | |||
| 3a9584b840 | |||
| 5d20a518ae | |||
| bd3dc453ef | |||
| 151d22c325 | |||
| d6433a67c8 | |||
| be561f0e5e | |||
| 1f6d90319b | |||
| eca63364a6 | |||
| 38f25160d6 | |||
| 28ce023164 | |||
| 10b3d56682 | |||
| 945011f9e3 | |||
| d7c6cd68b9 | |||
| ed4c3fde2d | |||
| c5db1c33a0 | |||
| d719ea74dd | |||
| 996defaadb | |||
| 86cd7f7a01 | |||
| a79090c65a | |||
| 86c720af81 | |||
| a9becd5cc8 | |||
| 1e327699b8 | |||
| 0ba9425bb6 | |||
| 7d19b839d9 | |||
| e1a9f0a533 | |||
| f6d0051446 | |||
| 126df1fa03 | |||
| 0a72d9539f | |||
| 60ecbe054e | |||
| 5a3fa18863 | |||
| bea4f2abde | |||
| 3fc2ca3d77 | |||
| 29fcc4727a | |||
| ddb973b03a | |||
| c2b05f9956 | |||
| 7fd452102f | |||
| c80d3eea47 | |||
| 8421edbb72 | |||
| 03587f54be | |||
| dac7760018 | |||
| bd28d5d7b1 | |||
| 34df19b204 | |||
| 6e824dadf2 | |||
| c50cfc1714 | |||
| d0fcd573bd | |||
| 79089ced97 | |||
| aa6811a088 | |||
| dd27a35039 | |||
| f3b696c5ec | |||
| 8405041f64 | |||
| a372993c44 | |||
| 909e0d7312 | |||
| e8503f7ddc | |||
| 42a6caf7dc | |||
| eaffb12ffb | |||
| 105e0d3c82 | |||
| 534a36c7e1 | |||
| b5b8f757b2 | |||
| 10e3dfbfdb | |||
| bfdcbbe9f1 | |||
| 5d49839236 | |||
| e6508237e7 | |||
| 2d4797c84e | |||
| 392516e60f | |||
| d09a2d0772 | |||
| 2bd5c10f09 | |||
| 5c910113a3 | |||
| c591a2e098 | |||
| b5acc9b093 | |||
| 5b6f8ff0f6 | |||
| d530d0a4d5 | |||
| 211ce4b2d3 | |||
| 1800438a77 | |||
| 1eda9a839a | |||
| e3cc400ac2 | |||
| b9b3d021cc | |||
| 6e202e18d8 | |||
| 750b57859a | |||
| 7ba520fea1 | |||
| da85a07dae | |||
| 01851523a0 | |||
| eda744f07f | |||
| 4acfe11af1 | |||
| 85824c5df6 | |||
| 20a0c27111 | |||
| 76200884d5 | |||
| ce4ce55b29 | |||
| 66f6e38788 | |||
| d97a0a3324 | |||
| 63f5a0a324 | |||
| f0837bb98b | |||
| 0f98a72876 | |||
| 1dd59204e9 | |||
| decae725a6 | |||
| 6c92d45ff3 | |||
| 272dd4a076 | |||
| 626ebe380e | |||
| f86ce48d65 | |||
| ef92cca9db | |||
| aa71810bfb | |||
| 22c47ac648 | |||
| e592528937 | |||
| 1fdb49f314 | |||
| aff37d1ae4 | |||
| a0234d0cc6 | |||
| 8a77acb51e | |||
| 690bbbd14c | |||
| 9c9bb2f192 | |||
| 23a40fe051 | |||
| 5d9cd662fc | |||
| 6c01589d3b | |||
| 820dde8ad2 | |||
| 3de4d63f44 | |||
| e1df82e0c3 | |||
| c1985b4a10 | |||
| 1ca9ce4db3 | |||
| 636705bd70 | |||
| 153dcd8ad3 | |||
| f2c2fe11b4 | |||
| 7a2c4fa5cc | |||
| 923816ca8e | |||
| 23d0b7b89e | |||
| a6b35f3a22 | |||
| 87fb39c8a5 | |||
| 4d188a79fb | |||
| a02b807dad | |||
| e0fa9d0213 | |||
| 35ad8abf4c | |||
| 372ca374cc | |||
| 75b6e94be1 | |||
| f912d0ef88 | |||
| 1bf8a01d0b | |||
| 5e8213d45f | |||
| 8b093122ac | |||
| bc14ad5b15 | |||
| fc543fc5a6 | |||
| 2e3aec81e7 | |||
| 9b04578d3e | |||
| 6654d32229 | |||
| 7c2c9448a3 | |||
| 6531128647 | |||
| fd1b895ff9 | |||
| f4e88bbcc0 | |||
| 7993f98166 | |||
| e11b775a31 | |||
| b999494154 | |||
| 6a7ed1a948 | |||
| d0889cca31 | |||
| 8b673c7adf | |||
| f1b0390b9b | |||
| b43d767a26 | |||
| bd4f642045 | |||
| 3bdfc7d785 | |||
| 4aa73968f0 | |||
| 06bc09951d | |||
| 9d59043788 | |||
| 33f0ca3042 | |||
| e1bc62dae3 | |||
| 77dbe9ccac | |||
| 150d8c2119 | |||
| b16f6adf76 | |||
| 834dd963ef | |||
| 01e0f9c2b7 | |||
| b4c0bb1f18 | |||
| f70fc683d1 | |||
| 956d4bd5bf | |||
| 8b45f89a75 | |||
| def6b67c8f | |||
| e8136853db | |||
| 084b41e33b | |||
| 6242bd7eb7 | |||
| 5fbe298f9c | |||
| b1c2c645df | |||
| d2a6aa5462 | |||
| 71abe66b8f | |||
| 01eb6e31ba | |||
| 071e6f885f | |||
| 5fcde96f88 | |||
| a1ad10b3ee | |||
| 6d26732208 | |||
| 20a396f190 | |||
| 4b7e5ca9fc | |||
| 8522707bd2 | |||
| a1505736d7 | |||
| 5cd17028d6 | |||
| 3089dd8688 | |||
| 044c45225b | |||
| 0c1ade82b2 | |||
| 7fdf5ed7dc | |||
| 6fb956688a | |||
| 28b362f8ff | |||
| 7035ccdcd2 | |||
| ba5ac8d872 | |||
| ea16ecc81f | |||
| 0eac9d3e6f | |||
| 68a8b6d437 | |||
| e136ba9f3e | |||
| 9ee6bea772 | |||
| 79bdde4f08 | |||
| 2a5f0e3c9f | |||
| 3c42f3de47 | |||
| 7cd15d408e | |||
| 5228b778dc | |||
| 49eaf7afeb | |||
| b2f02232f2 | |||
| 2f2d7da20b | |||
| 168043d422 | |||
| 101e1f6b50 | |||
| 323b6cec9d | |||
| 019a04c488 | |||
| e566bbc5e7 | |||
| d2140672fd | |||
| 667df80d35 | |||
| 0d8ad2d8b0 | |||
| 1796ff6871 | |||
| 49c54ee69a | |||
| d8e314b0a0 | |||
| 65acfe61ce | |||
| 2f067de10a | |||
| acecb50f7e | |||
| 9b27932d2c | |||
| 4aa8c0a76a | |||
| 246e43217a | |||
| 6925a5f3a4 | |||
| 81a92a9f13 | |||
| 8440d66d33 | |||
| 63ce978afe | |||
| b4e6386496 | |||
| f524a96add | |||
| 1d0f3bb831 | |||
| 2e0ef27570 | |||
| ebbb8fcef1 | |||
| 1d89d3dbe9 | |||
| 18512f5b99 | |||
| 5d4906b4d1 | |||
| 5e83a0eea6 | |||
| 3f43856145 | |||
| bb16ca6394 | |||
| 0e0b6a4978 | |||
| 2799892f1d | |||
| 7ecd839310 | |||
| 11a2628ed2 | |||
| a24b9cf9b9 | |||
| 705f77f5ba | |||
| c71cbf2e09 | |||
| 33aba7b721 |
@@ -0,0 +1,2 @@
|
||||
ca =
|
||||
cache = ~/.atom/.npm
|
||||
+1
-1
@@ -10,7 +10,7 @@ to propose changes to this document in a pull request.
|
||||
that behavior such as Emacs, vi, Xcode, etc.
|
||||
* Check the Console app for stack traces to include if reporting a crash.
|
||||
* Check the Dev tools (`alt-cmd-i`) for errors and stack traces to include.
|
||||
|
||||
|
||||
### Package Repositories
|
||||
|
||||
This is the repository for the core Atom editor only. Atom comes bundled with
|
||||
|
||||
+56
-15
@@ -1,11 +1,13 @@
|
||||
#!/bin/sh
|
||||
ATOM_PATH=${ATOM_PATH-/Applications/Atom.app}
|
||||
ATOM_BINARY=$ATOM_PATH/Contents/MacOS/Atom
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -d $ATOM_PATH ]; then sleep 5; fi # Wait for Atom to reappear, Sparkle may be replacing it.
|
||||
|
||||
if [ ! -d $ATOM_PATH ]; then
|
||||
echo "Atom application not found at '$ATOM_PATH'" >&2
|
||||
if [ "`uname`" == 'Darwin' ]; then
|
||||
OS='Mac'
|
||||
elif [ "`expr substr $(uname -s) 1 5`" == 'Linux' ]; then
|
||||
OS='Linux'
|
||||
elif [ "`expr substr $(uname -s) 1 10`" == 'MINGW32_NT' ]; then
|
||||
OS='Cygwin'
|
||||
else
|
||||
echo "Your platform (`uname -a`) is not supported."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -16,7 +18,11 @@ while getopts ":wtfvhs-:" opt; do
|
||||
wait)
|
||||
WAIT=1
|
||||
;;
|
||||
help|version|foreground|test)
|
||||
help|version)
|
||||
REDIRECT_STDERR=1
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
foreground|test)
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
esac
|
||||
@@ -24,25 +30,60 @@ while getopts ":wtfvhs-:" opt; do
|
||||
w)
|
||||
WAIT=1
|
||||
;;
|
||||
h|v|f|t)
|
||||
h|v)
|
||||
REDIRECT_STDERR=1
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
f|t)
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
$ATOM_BINARY --executed-from="$(pwd)" --pid=$$ $@
|
||||
exit $?
|
||||
else
|
||||
open -a $ATOM_PATH -n --args --executed-from="$(pwd)" --pid=$$ $@
|
||||
if [ $REDIRECT_STDERR ]; then
|
||||
exec 2> /dev/null
|
||||
fi
|
||||
|
||||
# Used to exit process when atom is used as $EDITOR
|
||||
if [ $OS == 'Mac' ]; then
|
||||
ATOM_PATH=${ATOM_PATH:-/Applications} # Set ATOM_PATH unless it is already set
|
||||
ATOM_APP_NAME=Atom.app
|
||||
|
||||
# If ATOM_PATH isn't a executable file, use spotlight to search for Atom
|
||||
if [ ! -x "$ATOM_PATH/$ATOM_APP_NAME" ]; then
|
||||
ATOM_PATH=$(mdfind "kMDItemCFBundleIdentifier == 'com.github.atom'" | head -1 | xargs dirname)
|
||||
fi
|
||||
|
||||
# Exit if Atom can't be found
|
||||
if [ -z "$ATOM_PATH" ]; then
|
||||
echo "Cannot locate Atom.app, it is usually located in /Applications. Set the ATOM_PATH environment variable to the directory containing Atom.app."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
"$ATOM_PATH/$ATOM_APP_NAME/Contents/MacOS/Atom" --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
exit $?
|
||||
else
|
||||
open -a "$ATOM_PATH/$ATOM_APP_NAME" -n --args --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
fi
|
||||
elif [ $OS == 'Linux' ]; then
|
||||
ATOM_PATH='/opt/Atom/atom'
|
||||
[ -x "$ATOM_PATH" ] || ATOM_PATH='/tmp/atom-build/Atom/atom'
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
"$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@"
|
||||
exit $?
|
||||
else
|
||||
nohup "$ATOM_PATH" --executed-from="$(pwd)" --pid=$$ "$@" > /dev/null &
|
||||
fi
|
||||
fi
|
||||
|
||||
# Exits this process when Atom is used as $EDITOR
|
||||
on_die() {
|
||||
exit 0
|
||||
}
|
||||
trap 'on_die' SIGQUIT SIGTERM
|
||||
|
||||
# If the wait flag is set, don't exit this process until Atom tells it to.
|
||||
if [ $WAIT ]; then
|
||||
while true; do
|
||||
sleep 1
|
||||
|
||||
@@ -46,7 +46,7 @@ module.exports = (grunt) ->
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
|
||||
else
|
||||
else if process.platform is 'darwin'
|
||||
appName = 'Atom.app'
|
||||
tmpDir = '/tmp'
|
||||
installRoot = '/Applications'
|
||||
@@ -56,6 +56,16 @@ module.exports = (grunt) ->
|
||||
contentsDir = path.join(shellAppDir, 'Contents')
|
||||
appDir = path.join(contentsDir, 'Resources', 'app')
|
||||
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
|
||||
else
|
||||
appName = 'Atom'
|
||||
tmpDir = '/tmp'
|
||||
installRoot = '/opt'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
|
||||
|
||||
installDir = path.join(installRoot, appName)
|
||||
|
||||
@@ -227,4 +237,7 @@ module.exports = (grunt) ->
|
||||
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
|
||||
grunt.registerTask('ci', ['output-disk-space', 'download-atom-shell', 'build', 'dump-symbols', 'set-version', 'check-licenses', 'lint', 'test', 'codesign', 'publish-build'])
|
||||
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
|
||||
grunt.registerTask('default', ['download-atom-shell', 'build', 'set-version', 'install'])
|
||||
|
||||
defaultTasks = ['download-atom-shell', 'build', 'set-version']
|
||||
defaultTasks.push 'install' unless process.platform is 'linux'
|
||||
grunt.registerTask('default', defaultTasks)
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"grunt-cson": "0.6.0",
|
||||
"grunt-download-atom-shell": "git+https://atom-bot:467bac80a0017b96fb5be5cfc686f5e0cc607b10@github.com/atom/grunt-download-atom-shell#v0.6.0",
|
||||
"grunt-cson": "0.8.0",
|
||||
"grunt-download-atom-shell": "git+https://atom-bot:467bac80a0017b96fb5be5cfc686f5e0cc607b10@github.com/atom/grunt-download-atom-shell#v0.6.1",
|
||||
"grunt-lesslint": "0.13.0",
|
||||
"grunt-markdown": "~0.4.0",
|
||||
"grunt-peg": "~1.1.0",
|
||||
@@ -26,13 +26,14 @@
|
||||
"harmony-collections": "~0.3.8",
|
||||
"json-front-matter": "~0.1.3",
|
||||
"legal-eagle": "~0.3.0",
|
||||
"minidump": "0.4.x",
|
||||
"minidump": "0.5.x",
|
||||
"rcedit": "~0.1.2",
|
||||
"request": "~2.27.0",
|
||||
"rimraf": "~2.2.2",
|
||||
"runas": "0.5.x",
|
||||
"underscore-plus": "1.x",
|
||||
"unzip": "~0.1.9",
|
||||
"vm-compatibility-layer": "~0.1.0"
|
||||
"vm-compatibility-layer": "~0.1.0",
|
||||
"npm": "~1.4.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = (grunt) ->
|
||||
|
||||
if process.platform is 'darwin'
|
||||
cp 'atom-shell/Atom.app', shellAppDir
|
||||
else if process.platform is 'win32'
|
||||
else
|
||||
cp 'atom-shell', shellAppDir
|
||||
|
||||
mkdir appDir
|
||||
|
||||
@@ -143,6 +143,8 @@ downloadFileFromRepo = ({repo, file}, callback) ->
|
||||
|
||||
downloadIncludes = (callback) ->
|
||||
includes = [
|
||||
{repo: 'atom-keymap', file: 'src/keymap.coffee'}
|
||||
{repo: 'atom-keymap', file: 'src/key-binding.coffee'}
|
||||
{repo: 'first-mate', file: 'src/grammar.coffee'}
|
||||
{repo: 'first-mate', file: 'src/grammar-registry.coffee'}
|
||||
{repo: 'node-pathwatcher', file: 'src/directory.coffee'}
|
||||
|
||||
@@ -48,3 +48,5 @@ module.exports = (grunt) ->
|
||||
|
||||
rcedit = require('rcedit')
|
||||
rcedit(shellExePath, {'version-string': strings}, done)
|
||||
else
|
||||
done()
|
||||
|
||||
@@ -31,6 +31,7 @@ The classes available from `require 'atom'` are:
|
||||
* [SelectListView][SelectListView]
|
||||
* [View][View]
|
||||
* [WorkspaceView][WorkspaceView]
|
||||
* [Workspace][Workspace]
|
||||
|
||||
### How do I create a package?
|
||||
|
||||
@@ -54,5 +55,6 @@ Atom ships with node 0.11.10 and the comprehensive node API docs are available
|
||||
[SelectListView]: ../classes/SelectListView.html
|
||||
[View]: ../classes/View.html
|
||||
[WorkspaceView]: ../classes/WorkspaceView.html
|
||||
[Workspace]: ../classes/Workspace.html
|
||||
[creating-a-package]: https://atom.io/docs/latest/creating-a-package
|
||||
[node-docs]: http://nodejs.org/docs/v0.11.10/api
|
||||
|
||||
@@ -130,7 +130,7 @@ Ideally, you won't need much in the way of styling. We've provided a standard
|
||||
set of components which define both the colors and UI elements for any package
|
||||
that fits into Atom seamlessly. You can view all of Atom's UI components by opening
|
||||
the styleguide: open the command palette (`cmd-shift-P`) and search for _styleguide_,
|
||||
or just type `cmd-ctrl-G`.
|
||||
or just type `cmd-ctrl-shift-G`.
|
||||
|
||||
If you _do_ need special styling, try to keep only structural styles in the package
|
||||
stylesheets. If you _must_ specify colors and sizing, these should be taken from
|
||||
@@ -338,7 +338,7 @@ code depending on whether the tests passed or failed.
|
||||
|
||||
## Publishing
|
||||
|
||||
Atom bundles a command line utility called [apm] which can be used to publish
|
||||
Atom bundles a command line utility called apm which can be used to publish
|
||||
Atom packages to the public registry.
|
||||
|
||||
Once your package is written and ready for distribution you can run the
|
||||
@@ -361,7 +361,6 @@ all the other available commands.
|
||||
[cs-syntax]: https://github.com/atom/language-coffee-script
|
||||
[npm]: http://en.wikipedia.org/wiki/Npm_(software)
|
||||
[npm-keys]: https://npmjs.org/doc/json.html
|
||||
[apm]: https://github.com/atom/apm
|
||||
[git-tag]: http://git-scm.com/book/en/Git-Basics-Tagging
|
||||
[wrap-guide]: https://github.com/atom/wrap-guide/
|
||||
[keymaps]: advanced/keymaps.md
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Customizing Atom
|
||||
|
||||
To change a setting, configure a theme, or install a package just open the
|
||||
Settings view in the current window by pressing `cmd+,`.
|
||||
Settings view in the current window by pressing `cmd-,`.
|
||||
|
||||
## Changing The Theme
|
||||
|
||||
@@ -86,7 +86,7 @@ currently in use.
|
||||
## Advanced Configuration
|
||||
|
||||
Atom loads configuration settings from the `config.cson` file in your _~/.atom_
|
||||
directory, which contains CoffeeScript-style JSON:
|
||||
directory, which contains [CoffeeScript-style JSON][CSON] (CSON):
|
||||
|
||||
```coffee
|
||||
'core':
|
||||
@@ -110,7 +110,6 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu.
|
||||
- `themes`: An array of theme names to load, in cascading order
|
||||
- `editor`
|
||||
- `autoIndent`: Enable/disable basic auto-indent (defaults to `true`)
|
||||
- `autoIndentOnPaste`: Enable/disable auto-indented pasted text (defaults to `false`)
|
||||
- `nonWordCharacters`: A string of non-word characters to define word boundaries
|
||||
- `fontSize`: The editor font size
|
||||
- `fontFamily`: The editor font family
|
||||
@@ -141,13 +140,21 @@ You can open this file in an editor from the _Atom > Open Your Config_ menu.
|
||||
### init.coffee
|
||||
|
||||
When Atom finishes loading, it will evaluate _init.coffee_ in your _~/.atom_
|
||||
directory, giving you a chance to run arbitrary personal CoffeeScript code to
|
||||
directory, giving you a chance to run arbitrary personal [CoffeeScript][] code to
|
||||
make customizations. You have full access to Atom's API from code in this file.
|
||||
If customizations become extensive, consider [creating a package][creating-a-package].
|
||||
|
||||
You can open this file in an editor from the _Atom > Open Your Init Script_
|
||||
menu.
|
||||
|
||||
For example, if you have the Audio Beep configuration setting enabled, you
|
||||
could add the following code to your _~/.atom/init.coffee_ file to have Atom
|
||||
greet you with an audio beep every time it loads:
|
||||
|
||||
```coffee
|
||||
atom.beep()
|
||||
```
|
||||
|
||||
This file can also be named _init.js_ and contain JavaScript code.
|
||||
|
||||
### styles.less
|
||||
@@ -174,3 +181,5 @@ This file can also be named _styles.css_ and contain CSS.
|
||||
[creating-a-package]: creating-a-package.md
|
||||
[create-theme]: creating-a-theme.md
|
||||
[LESS]: http://www.lesscss.org
|
||||
[CSON]: https://github.com/atom/season
|
||||
[CoffeeScript]: http://coffeescript.org/
|
||||
|
||||
@@ -20,7 +20,8 @@ The final package can be viewed at
|
||||
To begin, press `cmd-shift-P` to bring up the [Command
|
||||
Palette](https://github.com/atom/command-palette). Type "generate package" and
|
||||
select the "Package Generator: Generate Package" command. Now we need to name
|
||||
the package. Let's call it _ascii-art_.
|
||||
the package. Try to avoid naming your package with the *atom-* prefix, for
|
||||
example we are going to call this package _ascii-art_.
|
||||
|
||||
Atom will open a new window with the contents of our new _ascii-art_ package
|
||||
displayed in the Tree View. Because this window is opened **after** the package
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# '.editor':
|
||||
# 'enter': 'editor:newline'
|
||||
#
|
||||
# 'body':
|
||||
# '.workspace':
|
||||
# 'ctrl-P': 'core:move-up'
|
||||
# 'ctrl-p': 'core:move-down'
|
||||
#
|
||||
|
||||
@@ -21,3 +21,4 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
module.exports.Task = require '../src/task'
|
||||
module.exports.View = View
|
||||
module.exports.WorkspaceView = require '../src/workspace-view'
|
||||
module.exports.Workspace = require '../src/workspace'
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
'.editor':
|
||||
# Apple Specific
|
||||
'cmd-backspace': 'editor:backspace-to-beginning-of-line'
|
||||
'cmd-shift-backspace': 'editor:backspace-to-beginning-of-line'
|
||||
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
||||
'ctrl-A': 'editor:select-to-first-character-of-line'
|
||||
'ctrl-E': 'editor:select-to-end-of-line'
|
||||
@@ -134,7 +135,7 @@
|
||||
'ctrl-cmd-down': 'editor:move-line-down'
|
||||
'cmd-/': 'editor:toggle-line-comments'
|
||||
'cmd-j': 'editor:join-lines'
|
||||
'cmd-D': 'editor:duplicate-line'
|
||||
'cmd-D': 'editor:duplicate-lines'
|
||||
'cmd-L': 'editor:split-selections-into-lines'
|
||||
|
||||
'cmd-alt-[': 'editor:fold-current-row'
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
'body':
|
||||
# Atom Specific
|
||||
'enter': 'core:confirm'
|
||||
'escape': 'core:cancel'
|
||||
'up': 'core:move-up'
|
||||
'down': 'core:move-down'
|
||||
'left': 'core:move-left'
|
||||
'right': 'core:move-right'
|
||||
'ctrl-alt-r': 'window:reload'
|
||||
'ctrl-alt-i': 'window:toggle-dev-tools'
|
||||
'ctrl-alt-p': 'window:run-package-specs'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-N': 'application:new-window'
|
||||
'ctrl-W': 'window:close'
|
||||
'ctrl-o': 'application:open'
|
||||
'ctrl-T': 'pane:reopen-closed-item'
|
||||
'ctrl-n': 'application:new-file'
|
||||
'ctrl-s': 'core:save'
|
||||
'ctrl-S': 'core:save-as'
|
||||
'ctrl-w': 'core:close'
|
||||
'ctrl-z': 'core:undo'
|
||||
'ctrl-y': 'core:redo'
|
||||
'ctrl-x': 'core:cut'
|
||||
'ctrl-c': 'core:copy'
|
||||
'ctrl-v': 'core:paste'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'delete': 'core:delete'
|
||||
'pageup': 'core:page-up'
|
||||
'pagedown': 'core:page-down'
|
||||
'backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
'ctrl-shift-down': 'core:move-down'
|
||||
'ctrl-=': 'window:increase-font-size'
|
||||
'ctrl-+': 'window:increase-font-size'
|
||||
'ctrl--': 'window:decrease-font-size'
|
||||
'ctrl-_': 'window:decrease-font-size'
|
||||
'ctrl-0': 'window:reset-font-size'
|
||||
|
||||
'ctrl-k up': 'pane:split-up' # Atom Specific
|
||||
'ctrl-k down': 'pane:split-down' # Atom Specific
|
||||
'ctrl-k left': 'pane:split-left' # Atom Specific
|
||||
'ctrl-k right': 'pane:split-right' # Atom Specific
|
||||
'ctrl-k ctrl-w': 'pane:close' # Atom Specific
|
||||
'ctrl-k alt-ctrl-w': 'pane:close-other-items' # Atom Specific
|
||||
'ctrl-k ctrl-p': 'window:focus-previous-pane'
|
||||
'ctrl-k ctrl-n': 'window:focus-next-pane'
|
||||
'ctrl-k ctrl-up': 'window:focus-pane-above'
|
||||
'ctrl-k ctrl-down': 'window:focus-pane-below'
|
||||
'ctrl-k ctrl-left': 'window:focus-pane-on-left'
|
||||
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
|
||||
|
||||
'.workspace .editor':
|
||||
# Windows specific
|
||||
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-a': 'core:select-all'
|
||||
'ctrl-alt-p': 'editor:log-cursor-scope'
|
||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||
|
||||
'.workspace .editor:not(.mini)':
|
||||
# Atom specific
|
||||
'alt-ctrl-z': 'editor:checkout-head-revision'
|
||||
'ctrl-<': 'editor:scroll-to-cursor'
|
||||
'alt-ctrl-f': 'editor:fold-selection'
|
||||
|
||||
# Sublime Parity
|
||||
'ctrl-enter': 'editor:newline-below'
|
||||
'ctrl-shift-enter': 'editor:newline-above'
|
||||
'ctrl-]': 'editor:indent-selected-rows'
|
||||
'ctrl-[': 'editor:outdent-selected-rows'
|
||||
'ctrl-up': 'editor:move-line-up'
|
||||
'ctrl-down': 'editor:move-line-down'
|
||||
'ctrl-/': 'editor:toggle-line-comments'
|
||||
'ctrl-j': 'editor:join-lines'
|
||||
'ctrl-D': 'editor:duplicate-lines'
|
||||
|
||||
'ctrl-alt-[': 'editor:fold-current-row'
|
||||
'ctrl-alt-]': 'editor:unfold-current-row'
|
||||
'ctrl-alt-{': 'editor:fold-all' # Atom Specific
|
||||
'ctrl-alt-}': 'editor:unfold-all' # Atom Specific
|
||||
'ctrl-k ctrl-0': 'editor:unfold-all'
|
||||
'ctrl-k ctrl-1': 'editor:fold-at-indent-level-1'
|
||||
'ctrl-k ctrl-2': 'editor:fold-at-indent-level-2'
|
||||
'ctrl-k ctrl-3': 'editor:fold-at-indent-level-3'
|
||||
'ctrl-k ctrl-4': 'editor:fold-at-indent-level-4'
|
||||
'ctrl-k ctrl-5': 'editor:fold-at-indent-level-5'
|
||||
'ctrl-k ctrl-6': 'editor:fold-at-indent-level-6'
|
||||
'ctrl-k ctrl-7': 'editor:fold-at-indent-level-7'
|
||||
'ctrl-k ctrl-8': 'editor:fold-at-indent-level-8'
|
||||
'ctrl-k ctrl-9': 'editor:fold-at-indent-level-9'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'body .native-key-bindings':
|
||||
'ctrl-z': 'native!'
|
||||
'ctrl-Z': 'native!'
|
||||
'ctrl-x': 'native!'
|
||||
'ctrl-c': 'native!'
|
||||
'ctrl-v': 'native!'
|
||||
@@ -81,7 +81,7 @@
|
||||
'ctrl-down': 'editor:move-line-down'
|
||||
'ctrl-/': 'editor:toggle-line-comments'
|
||||
'ctrl-j': 'editor:join-lines'
|
||||
'ctrl-D': 'editor:duplicate-line'
|
||||
'ctrl-D': 'editor:duplicate-lines'
|
||||
|
||||
'ctrl-alt-[': 'editor:fold-current-row'
|
||||
'ctrl-alt-]': 'editor:unfold-current-row'
|
||||
|
||||
+3
-2
@@ -7,6 +7,7 @@
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ label: "Restart and Install Update", command: 'application:install-update', visible: false}
|
||||
{ label: "Check for Update", command: 'application:check-for-update', visible: false}
|
||||
{ label: "Downloading Update", command: 'application:check-for-update', enabled: false, visible: false}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Preferences...', command: 'application:show-settings' }
|
||||
{ label: 'Open Your Config', command: 'application:open-your-config' }
|
||||
@@ -37,7 +38,7 @@
|
||||
{ label: 'Save All', command: 'window:save-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Close Buffer', command: 'core:close' }
|
||||
{ label: 'Close All Buffers', command: 'pane:close' }
|
||||
{ label: 'Close Pane', command: 'pane:close' }
|
||||
{ label: 'Close Window', command: 'window:close' }
|
||||
]
|
||||
}
|
||||
@@ -64,7 +65,7 @@
|
||||
{ type: 'separator' }
|
||||
{ label: 'Move Line Up', command: 'editor:move-line-up' }
|
||||
{ label: 'Move Line Down', command: 'editor:move-line-down' }
|
||||
{ label: 'Duplicate Line', command: 'editor:duplicate-line' }
|
||||
{ label: 'Duplicate Lines', command: 'editor:duplicate-lines' }
|
||||
{ label: 'Delete Line', command: 'editor:delete-line' }
|
||||
{ label: 'Join Lines', command: 'editor:join-lines' }
|
||||
]
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
'menu': [
|
||||
{
|
||||
label: '&File'
|
||||
submenu: [
|
||||
{ label: 'New &Window', command: 'application:new-window' }
|
||||
{ label: '&New File', command: 'application:new-file' }
|
||||
{ label: '&Open...', command: 'application:open' }
|
||||
{ label: 'Reopen Last &Item', command: 'pane:reopen-closed-item' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Preferences...', command: 'application:show-settings' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Save', command: 'core:save' }
|
||||
{ label: 'Save &As...', command: 'core:save-as' }
|
||||
{ label: 'Save A&ll', command: 'window:save-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Close Buffer', command: 'core:close' }
|
||||
{ label: 'Close All &Buffers', command: 'pane:close' }
|
||||
{ label: 'Clos&e Window', command: 'window:close' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'E&xit', command: 'application:quit' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Edit'
|
||||
submenu: [
|
||||
{ label: '&Undo', command: 'core:undo' }
|
||||
{ label: '&Redo', command: 'core:redo' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Cut', command: 'core:cut' }
|
||||
{ label: 'C&opy', command: 'core:copy' }
|
||||
{ label: 'Copy Pat&h', command: 'editor:copy-path' }
|
||||
{ label: '&Paste', command: 'core:paste' }
|
||||
{ label: 'Select &All', command: 'core:select-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Toggle Comments', command: 'editor:toggle-line-comments' }
|
||||
{
|
||||
label: 'Lines',
|
||||
submenu: [
|
||||
{ label: '&Indent', command: 'editor:indent-selected-rows' }
|
||||
{ label: '&Outdent', command: 'editor:outdent-selected-rows' }
|
||||
{ label: '&Auto Indent', command: 'editor:auto-indent' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Move Line &Up', command: 'editor:move-line-up' }
|
||||
{ label: 'Move Line &Down', command: 'editor:move-line-down' }
|
||||
{ label: 'Du&plicate Lines', command: 'editor:duplicate-lines' }
|
||||
{ label: 'D&elete Line', command: 'editor:delete-line' }
|
||||
{ label: '&Join Lines', command: 'editor:join-lines' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Text',
|
||||
submenu: [
|
||||
{ label: '&Upper Case', command: 'editor:upper-case' }
|
||||
{ label: '&Lower Case', command: 'editor:lower-case' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Delete to End of &Word', command: 'editor:delete-to-end-of-word' }
|
||||
{ label: '&Delete Line', command: 'editor:delete-line' }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Transpose', command: 'editor:transpose' }
|
||||
]
|
||||
}
|
||||
{
|
||||
label: 'Folding',
|
||||
submenu: [
|
||||
{ label: '&Fold', command: 'editor:fold-current-row' }
|
||||
{ label: '&Unfold', command: 'editor:unfold-current-row' }
|
||||
{ label: 'Unfold &All', command: 'editor:unfold-all' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Fol&d All', command: 'editor:fold-all' }
|
||||
{ label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' }
|
||||
{ label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' }
|
||||
{ label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' }
|
||||
{ label: 'Fold Level 4', command: 'editor:fold-at-indent-level-4' }
|
||||
{ label: 'Fold Level 5', command: 'editor:fold-at-indent-level-5' }
|
||||
{ label: 'Fold Level 6', command: 'editor:fold-at-indent-level-6' }
|
||||
{ label: 'Fold Level 7', command: 'editor:fold-at-indent-level-7' }
|
||||
{ label: 'Fold Level 8', command: 'editor:fold-at-indent-level-8' }
|
||||
{ label: 'Fold Level 9', command: 'editor:fold-at-indent-level-9' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&View'
|
||||
submenu: [
|
||||
{ label: '&Reload', command: 'window:reload' }
|
||||
{ label: 'Toggle &Full Screen', command: 'window:toggle-full-screen' }
|
||||
{
|
||||
label: 'Developer'
|
||||
submenu: [
|
||||
{ label: 'Open In &Dev Mode...', command: 'application:open-dev' }
|
||||
{ label: 'Run &Atom Specs', command: 'application:run-all-specs' }
|
||||
{ label: 'Run Package &Specs', command: 'window:run-package-specs' }
|
||||
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
|
||||
]
|
||||
}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Toggle Soft &Wrap', command: 'editor:toggle-soft-wrap' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Selection'
|
||||
submenu: [
|
||||
{ label: 'Add Selection &Above', command: 'editor:add-selection-above' }
|
||||
{ label: 'Add Selection &Below', command: 'editor:add-selection-below' }
|
||||
{ label: 'S&plit into Lines', command: 'editor:split-selections-into-lines'}
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select to &Top', command: 'core:select-to-top' }
|
||||
{ label: 'Select to Botto&m', command: 'core:select-to-bottom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Select &Line', command: 'editor:select-line' }
|
||||
{ label: 'Select &Word', command: 'editor:select-word' }
|
||||
{ label: 'Select to Beginning of W&ord', command: 'editor:select-to-beginning-of-word' }
|
||||
{ label: 'Select to Beginning of L&ine', command: 'editor:select-to-beginning-of-line' }
|
||||
{ label: 'Select to First &Character of Line', command: 'editor:select-to-first-character-of-line' }
|
||||
{ label: 'Select to End of Wor&d', command: 'editor:select-to-end-of-word' }
|
||||
{ label: 'Select to End of Lin&e', command: 'editor:select-to-end-of-line' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: 'F&ind'
|
||||
submenu: []
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Packages'
|
||||
submenu: []
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Window'
|
||||
submenu: [
|
||||
{ label: 'Mi&nimize', command: 'application:minimize' }
|
||||
{ label: 'Ma&ximize', command: 'application:zoom' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Bring &All to Front', command: 'application:bring-all-windows-to-front' }
|
||||
]
|
||||
}
|
||||
|
||||
{
|
||||
label: '&Help'
|
||||
submenu: [
|
||||
{ label: '&About Atom...', command: 'application:about' }
|
||||
{ label: 'View &License', command: 'application:open-license' }
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ label: "Install &update", command: 'application:install-update', visible: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
]
|
||||
+1
-1
@@ -43,7 +43,7 @@
|
||||
{ type: 'separator' }
|
||||
{ label: 'Move Line &Up', command: 'editor:move-line-up' }
|
||||
{ label: 'Move Line &Down', command: 'editor:move-line-down' }
|
||||
{ label: 'Du&plicate Line', command: 'editor:duplicate-line' }
|
||||
{ label: 'Du&plicate Lines', command: 'editor:duplicate-lines' }
|
||||
{ label: 'D&elete Line', command: 'editor:delete-line' }
|
||||
{ label: '&Join Lines', command: 'editor:join-lines' }
|
||||
]
|
||||
|
||||
+67
-66
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.64.0",
|
||||
"version": "0.75.0",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -11,118 +11,119 @@
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"license": "All Rights Reserved",
|
||||
"atomShellVersion": "0.10.3",
|
||||
"atomShellVersion": "0.11.1",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^0.9.0",
|
||||
"bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.7.0",
|
||||
"coffeestack": "0.7.0",
|
||||
"delegato": "1.x",
|
||||
"emissary": "1.x",
|
||||
"first-mate": ">=1.1.5 <2.0",
|
||||
"fs-plus": "2.x",
|
||||
"first-mate": ">=1.4.2 <2.0",
|
||||
"fs-plus": ">=2.0.4 < 3.0",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "~1.1",
|
||||
"git-utils": "1.x",
|
||||
"git-utils": "^1.0.1",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-tagged": ">=1.1.1 <2.0",
|
||||
"mkdirp": "0.3.5",
|
||||
"keytar": "0.15.1",
|
||||
"keytar": "1.x",
|
||||
"less-cache": "0.12.0",
|
||||
"mixto": "1.x",
|
||||
"nslog": "0.5.0",
|
||||
"oniguruma": "1.x",
|
||||
"oniguruma": ">=1.0.3 <2.0",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "0.16.0",
|
||||
"pegjs": "0.8.0",
|
||||
"pathwatcher": "^1.0.0",
|
||||
"property-accessors": "1.x",
|
||||
"q": "1.0.x",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
"runas": "0.5.x",
|
||||
"scandal": "0.15.0",
|
||||
"scrollbar-style": "^0.1.0",
|
||||
"season": ">=1.0.2 <2.0",
|
||||
"semver": "1.1.4",
|
||||
"serializable": "1.x",
|
||||
"space-pen": "3.1.1",
|
||||
"temp": "0.5.0",
|
||||
"text-buffer": "^1.2.0",
|
||||
"text-buffer": "^1.4.4",
|
||||
"theorist": "1.x",
|
||||
"underscore-plus": ">=1.0.2 <2.0",
|
||||
"underscore-plus": ">=1.0.5 <2.0",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.14.0",
|
||||
"atom-dark-ui": "0.23.0",
|
||||
"atom-light-syntax": "0.14.0",
|
||||
"atom-light-ui": "0.22.0",
|
||||
"base16-tomorrow-dark-theme": "0.12.0",
|
||||
"solarized-dark-syntax": "0.10.0",
|
||||
"solarized-light-syntax": "0.6.0",
|
||||
"archive-view": "0.26.0",
|
||||
"autocomplete": "0.24.0",
|
||||
"atom-dark-syntax": "0.15.0",
|
||||
"atom-dark-ui": "0.25.0",
|
||||
"atom-light-syntax": "0.16.0",
|
||||
"atom-light-ui": "0.23.0",
|
||||
"base16-tomorrow-dark-theme": "0.13.0",
|
||||
"solarized-dark-syntax": "0.14.0",
|
||||
"solarized-light-syntax": "0.7.0",
|
||||
"archive-view": "0.29.0",
|
||||
"autocomplete": "0.27.0",
|
||||
"autoflow": "0.15.0",
|
||||
"autosave": "0.12.0",
|
||||
"background-tips": "0.8.0",
|
||||
"bookmarks": "0.21.0",
|
||||
"bracket-matcher": "0.23.0",
|
||||
"command-palette": "0.18.0",
|
||||
"dev-live-reload": "0.28.0",
|
||||
"exception-reporting": "0.16.0",
|
||||
"feedback": "0.27.0",
|
||||
"find-and-replace": "0.87.0",
|
||||
"fuzzy-finder": "0.38.0",
|
||||
"autosave": "0.13.0",
|
||||
"background-tips": "0.9.0",
|
||||
"bookmarks": "0.22.0",
|
||||
"bracket-matcher": "0.26.0",
|
||||
"command-palette": "0.19.0",
|
||||
"dev-live-reload": "0.29.0",
|
||||
"exception-reporting": "0.17.0",
|
||||
"feedback": "0.28.0",
|
||||
"find-and-replace": "0.92.0",
|
||||
"fuzzy-finder": "0.42.0",
|
||||
"git-diff": "0.25.0",
|
||||
"go-to-line": "0.18.0",
|
||||
"grammar-selector": "0.22.0",
|
||||
"image-view": "0.27.0",
|
||||
"grammar-selector": "0.23.0",
|
||||
"image-view": "0.32.0",
|
||||
"keybinding-resolver": "0.11.0",
|
||||
"link": "0.19.0",
|
||||
"markdown-preview": "0.43.0",
|
||||
"metrics": "0.30.0",
|
||||
"link": "0.20.0",
|
||||
"markdown-preview": "0.49.0",
|
||||
"metrics": "0.32.0",
|
||||
"open-on-github": "0.23.0",
|
||||
"package-generator": "0.29.0",
|
||||
"release-notes": "0.25.0",
|
||||
"settings-view": "0.85.0",
|
||||
"snippets": "0.32.0",
|
||||
"spell-check": "0.26.0",
|
||||
"status-bar": "0.33.0",
|
||||
"package-generator": "0.30.0",
|
||||
"release-notes": "0.26.0",
|
||||
"settings-view": "0.97.0",
|
||||
"snippets": "0.37.0",
|
||||
"spell-check": "0.28.0",
|
||||
"status-bar": "0.36.0",
|
||||
"styleguide": "0.26.0",
|
||||
"symbols-view": "0.40.0",
|
||||
"tabs": "0.26.0",
|
||||
"timecop": "0.15.0",
|
||||
"tree-view": "0.72.0",
|
||||
"update-package-dependencies": "0.4.0",
|
||||
"symbols-view": "0.44.0",
|
||||
"tabs": "0.31.0",
|
||||
"timecop": "0.17.0",
|
||||
"tree-view": "0.83.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.11.0",
|
||||
"whitespace": "0.15.0",
|
||||
"wrap-guide": "0.16.0",
|
||||
"language-c": "0.12.0",
|
||||
"language-coffee-script": "0.14.0",
|
||||
"language-css": "0.10.0",
|
||||
"language-gfm": "0.19.0",
|
||||
"whitespace": "0.21.0",
|
||||
"wrap-guide": "0.18.0",
|
||||
"language-c": "0.13.0",
|
||||
"language-coffee-script": "0.16.0",
|
||||
"language-css": "0.13.0",
|
||||
"language-gfm": "0.22.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.6.0",
|
||||
"language-html": "0.9.0",
|
||||
"language-hyperlink": "0.8.0",
|
||||
"language-java": "0.8.0",
|
||||
"language-javascript": "0.13.0",
|
||||
"language-go": "0.7.0",
|
||||
"language-html": "0.14.0",
|
||||
"language-hyperlink": "0.9.0",
|
||||
"language-java": "0.9.0",
|
||||
"language-javascript": "0.21.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.6.0",
|
||||
"language-make": "0.9.0",
|
||||
"language-objective-c": "0.9.0",
|
||||
"language-objective-c": "0.10.0",
|
||||
"language-perl": "0.8.0",
|
||||
"language-php": "0.9.0",
|
||||
"language-php": "0.13.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.9.0",
|
||||
"language-ruby": "0.14.0",
|
||||
"language-ruby-on-rails": "0.8.0",
|
||||
"language-python": "0.12.0",
|
||||
"language-ruby": "0.16.0",
|
||||
"language-ruby-on-rails": "0.12.0",
|
||||
"language-sass": "0.8.0",
|
||||
"language-shellscript": "0.7.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.7.0",
|
||||
"language-sql": "0.7.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.6.0",
|
||||
"language-toml": "0.11.0",
|
||||
"language-todo": "0.9.0",
|
||||
"language-toml": "0.12.0",
|
||||
"language-xml": "0.8.0",
|
||||
"language-yaml": "0.6.0"
|
||||
},
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>AtomApplication</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>speakeasy.pem</string>
|
||||
<key>SUScheduledCheckInterval</key>
|
||||
|
||||
+19
-8
@@ -1,4 +1,11 @@
|
||||
#!/usr/bin/env node --harmony_collections
|
||||
|
||||
var nodeMinorVersion = process.versions.node.split('.')[1]
|
||||
if (nodeMinorVersion !== '10') {
|
||||
console.warn("You must run script/bootstrap and script/build with node v0.10.x");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var safeExec = require('./utils/child-process-wrapper.js').safeExec;
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
@@ -25,21 +32,25 @@ if (!fs.existsSync(apmInstallPath))
|
||||
if (!fs.existsSync(path.join(apmInstallPath, 'node_modules')))
|
||||
fs.mkdirSync(path.join(apmInstallPath, 'node_modules'));
|
||||
|
||||
var apmPath = 'apm/node_modules/atom-package-manager/bin/apm'
|
||||
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
|
||||
|
||||
var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm');
|
||||
var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' ';
|
||||
|
||||
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season'];
|
||||
var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo';
|
||||
|
||||
var commands = [
|
||||
'git submodule --quiet sync',
|
||||
'git submodule --quiet update --recursive --init',
|
||||
{command: 'npm --strict-ssl=false install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
|
||||
{command: 'npm --strict-ssl=false install --quiet', options: {cwd: apmVendorPath, ignoreStdout: true}},
|
||||
{command: 'npm --strict-ssl=false install --quiet ' + apmVendorPath, options: {cwd: apmInstallPath, ignoreStdout: true}},
|
||||
{command: 'npm --strict-ssl=false install --quiet ' + apmVendorPath, options: {ignoreStdout: true}},
|
||||
{command: 'node ../../apm/node_modules/atom-package-manager/bin/apm rebuild', options: {cwd: path.resolve('node_modules', 'atom-package-manager'), ignoreStdout: true}},
|
||||
{command: 'npm' + npmFlags + 'install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
|
||||
{command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmVendorPath, ignoreStdout: true}},
|
||||
{command: npmPath + npmFlags + 'install --quiet ' + apmVendorPath, options: {cwd: apmInstallPath, ignoreStdout: true}},
|
||||
echoNewLine,
|
||||
'node apm/node_modules/atom-package-manager/bin/apm clean ' + apmFlags,
|
||||
'node apm/node_modules/atom-package-manager/bin/apm install --quiet ' + apmFlags,
|
||||
'node apm/node_modules/atom-package-manager/bin/apm dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '),
|
||||
apmPath + ' clean ' + apmFlags,
|
||||
apmPath + ' install --quiet ' + apmFlags,
|
||||
apmPath + ' dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '),
|
||||
];
|
||||
|
||||
process.chdir(path.dirname(__dirname));
|
||||
|
||||
@@ -22,6 +22,7 @@ var commands = [
|
||||
[__dirname, '..', 'atom-shell'],
|
||||
[home, '.atom', '.node-gyp'],
|
||||
[home, '.atom', 'storage'],
|
||||
[home, '.atom', '.npm'],
|
||||
[tmpdir, 'atom-build'],
|
||||
[tmpdir, 'atom-cached-atom-shells'],
|
||||
[tmpdir, 'atom-compile-cache'],
|
||||
|
||||
@@ -126,6 +126,16 @@ describe "the `atom` global", ->
|
||||
expect(eventHandler.callCount).toBe 2
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
|
||||
it "activates the package immediately when the events are empty", ->
|
||||
mainModule = require './fixtures/packages/package-with-empty-activation-events/index'
|
||||
spyOn(mainModule, 'activate').andCallThrough()
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('package-with-empty-activation-events')
|
||||
|
||||
runs ->
|
||||
expect(mainModule.activate.callCount).toBe 1
|
||||
|
||||
describe "when the package has no main module", ->
|
||||
it "does not throw an exception", ->
|
||||
spyOn(console, "error")
|
||||
|
||||
@@ -525,6 +525,17 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.lineForRow(8).text).toMatch /^9-+/
|
||||
expect(displayBuffer.lineForRow(10).fold).toBeDefined()
|
||||
|
||||
describe ".outermostFoldsInBufferRowRange(startRow, endRow)", ->
|
||||
it "returns the outermost folds entirely contained in the given row range, exclusive of end row", ->
|
||||
fold1 = displayBuffer.createFold(4, 7)
|
||||
fold2 = displayBuffer.createFold(5, 6)
|
||||
fold3 = displayBuffer.createFold(11, 15)
|
||||
fold4 = displayBuffer.createFold(12, 13)
|
||||
fold5 = displayBuffer.createFold(16, 17)
|
||||
|
||||
expect(displayBuffer.outermostFoldsInBufferRowRange(3, 18)).toEqual [fold1, fold3, fold5]
|
||||
expect(displayBuffer.outermostFoldsInBufferRowRange(5, 16)).toEqual [fold3]
|
||||
|
||||
describe ".clipScreenPosition(screenPosition, wrapBeyondNewlines: false, wrapAtSoftNewlines: false, skipAtomicTokens: false)", ->
|
||||
beforeEach ->
|
||||
displayBuffer.setSoftWrap(true)
|
||||
@@ -600,6 +611,13 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.screenPositionForBufferPosition([0, 1])).toEqual [0, 2]
|
||||
expect(displayBuffer.bufferPositionForScreenPosition([0, 2])).toEqual [0, 1]
|
||||
|
||||
it "correctly translates positions on soft wrapped lines containing tabs", ->
|
||||
buffer.setText('\t\taa bb cc dd ee ff gg')
|
||||
displayBuffer.setSoftWrap(true)
|
||||
displayBuffer.setEditorWidthInChars(10)
|
||||
expect(displayBuffer.screenPositionForBufferPosition([0, 10], wrapAtSoftNewlines: true)).toEqual [1, 0]
|
||||
expect(displayBuffer.bufferPositionForScreenPosition([1, 0])).toEqual [0, 10]
|
||||
|
||||
describe ".getMaxLineLength()", ->
|
||||
it "returns the length of the longest screen line", ->
|
||||
expect(displayBuffer.getMaxLineLength()).toBe 65
|
||||
|
||||
+2523
-2420
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+67
-108
@@ -587,7 +587,7 @@ describe "EditorView", ->
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 10])
|
||||
|
||||
# moving changes selection
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27])
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27], which: 1)
|
||||
|
||||
range = editor.getSelection().getScreenRange()
|
||||
expect(range.start).toEqual({row: 4, column: 10})
|
||||
@@ -617,12 +617,12 @@ describe "EditorView", ->
|
||||
originalScrollTop = editorView.scrollTop()
|
||||
|
||||
# moving changes selection
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1)
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1, which: 1)
|
||||
expect(editorView.scrollTop()).toBe originalScrollTop - editorView.lineHeight
|
||||
|
||||
# every mouse move selects more text
|
||||
for x in [0..10]
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1)
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1, which: 1)
|
||||
|
||||
expect(editorView.scrollTop()).toBe 0
|
||||
|
||||
@@ -633,7 +633,7 @@ describe "EditorView", ->
|
||||
event = mousedownEvent(editorView: editorView, point: [4, 10])
|
||||
event.originalEvent.which = 2
|
||||
editorView.renderedLines.trigger(event)
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27])
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, point: [5, 27], which: 1)
|
||||
$(document).trigger 'mouseup'
|
||||
|
||||
range = editor.getSelection().getScreenRange()
|
||||
@@ -654,6 +654,25 @@ describe "EditorView", ->
|
||||
expect(range.start).toEqual({row: 4, column: 10})
|
||||
expect(range.end).toEqual({row: 4, column: 10})
|
||||
|
||||
describe "when the editor is hidden", ->
|
||||
it "stops scrolling the editor", ->
|
||||
editorView.vScrollMargin = 0
|
||||
editorView.attachToDom(heightInLines: 5)
|
||||
editorView.scrollToBottom()
|
||||
|
||||
spyOn(window, 'setInterval').andCallFake ->
|
||||
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [12, 0])
|
||||
originalScrollTop = editorView.scrollTop()
|
||||
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, pageX: 0, pageY: -1, which: 1)
|
||||
expect(editorView.scrollTop()).toBe originalScrollTop - editorView.lineHeight
|
||||
|
||||
editorView.hide()
|
||||
|
||||
$(document).trigger mousemoveEvent(editorView: editorView, pageX: 100000, pageY: -1, which: 1)
|
||||
expect(editorView.scrollTop()).toBe originalScrollTop - editorView.lineHeight
|
||||
|
||||
describe "double-click and drag", ->
|
||||
it "selects the word under the cursor, then continues to select by word in either direction as the mouse is dragged", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
|
||||
@@ -662,11 +681,11 @@ describe "EditorView", ->
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [0, 8], originalEvent: {detail: 2})
|
||||
expect(editor.getSelectedText()).toBe "quicksort"
|
||||
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [1, 8])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [1, 8], which: 1)
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [1, 10]]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1, 10]
|
||||
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [0, 1])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [0, 1], which: 1)
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 13]]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
|
||||
|
||||
@@ -691,12 +710,12 @@ describe "EditorView", ->
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [5, 0]]
|
||||
|
||||
# moving changes selection linewise
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [5, 27])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [5, 27], which: 1)
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[4, 0], [6, 0]]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [6, 0]
|
||||
|
||||
# moving changes selection linewise
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [2, 27])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [2, 27], which: 1)
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[2, 0], [5, 0]]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [2, 0]
|
||||
|
||||
@@ -706,11 +725,11 @@ describe "EditorView", ->
|
||||
describe "meta-click and drag", ->
|
||||
it "adds an additional selection", ->
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [4, 10])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [5, 27])
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [5, 27], which: 1)
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
|
||||
editorView.renderedLines.trigger mousedownEvent(editorView: editorView, point: [6, 10], metaKey: true)
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [8, 27], metaKey: true)
|
||||
editorView.renderedLines.trigger mousemoveEvent(editorView: editorView, point: [8, 27], metaKey: true, which: 1)
|
||||
editorView.renderedLines.trigger 'mouseup'
|
||||
|
||||
selections = editor.getSelections()
|
||||
@@ -1806,6 +1825,17 @@ describe "EditorView", ->
|
||||
runs ->
|
||||
expect(editor.getSoftWrapColumn()).toBeLessThan previousSoftWrapColumn
|
||||
|
||||
it "accounts for the width of the scrollbar if there is one", ->
|
||||
# force the scrollbar to always be visible, regardless of OS visibility setting
|
||||
$('#jasmine-content').prepend """
|
||||
<style>
|
||||
::-webkit-scrollbar { width: 15px; }
|
||||
</style>
|
||||
"""
|
||||
setEditorHeightInLines(editorView, 5)
|
||||
setEditorWidthInChars(editorView, 40)
|
||||
expect(editor.lineForScreenRow(2).text.length).toBe 34
|
||||
|
||||
describe "gutter rendering", ->
|
||||
beforeEach ->
|
||||
editorView.attachToDom(heightInLines: 5.5)
|
||||
@@ -2419,51 +2449,11 @@ describe "EditorView", ->
|
||||
editorView.underlayer.trigger event
|
||||
expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [12,2]]
|
||||
|
||||
# TODO: Move to editor-spec
|
||||
describe ".reloadGrammar()", ->
|
||||
[filePath] = []
|
||||
|
||||
beforeEach ->
|
||||
tmpdir = fs.absolute(temp.dir)
|
||||
filePath = path.join(tmpdir, "grammar-change.txt")
|
||||
fs.writeFileSync(filePath, "var i;")
|
||||
|
||||
afterEach ->
|
||||
fs.removeSync(filePath) if fs.existsSync(filePath)
|
||||
|
||||
it "updates all the rendered lines when the grammar changes", ->
|
||||
editor = atom.project.openSync(filePath)
|
||||
editorView.edit(editor)
|
||||
expect(editor.getGrammar().name).toBe 'Plain Text'
|
||||
atom.syntax.setGrammarOverrideForPath(filePath, 'source.js')
|
||||
editor.reloadGrammar()
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
|
||||
tokenizedBuffer = editorView.editor.displayBuffer.tokenizedBuffer
|
||||
line0 = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(line0.tokens.length).toBe 3
|
||||
expect(line0.tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
|
||||
it "doesn't update the rendered lines when the grammar doesn't change", ->
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
spyOn(editorView, 'updateDisplay').andCallThrough()
|
||||
editor.reloadGrammar()
|
||||
expect(editor.reloadGrammar()).toBeFalsy()
|
||||
expect(editorView.updateDisplay).not.toHaveBeenCalled()
|
||||
expect(editor.getGrammar().name).toBe 'JavaScript'
|
||||
|
||||
it "emits an editor:grammar-changed event when updated", ->
|
||||
editor = atom.project.openSync(filePath)
|
||||
editorView.edit(editor)
|
||||
|
||||
describe "when the editor's grammar is changed", ->
|
||||
it "emits an editor:grammar-changed event", ->
|
||||
eventHandler = jasmine.createSpy('eventHandler')
|
||||
editorView.on('editor:grammar-changed', eventHandler)
|
||||
editor.reloadGrammar()
|
||||
|
||||
expect(eventHandler).not.toHaveBeenCalled()
|
||||
|
||||
atom.syntax.setGrammarOverrideForPath(filePath, 'source.js')
|
||||
editor.reloadGrammar()
|
||||
editor.setGrammar(atom.syntax.selectGrammar('.coffee'))
|
||||
expect(eventHandler).toHaveBeenCalled()
|
||||
|
||||
describe ".replaceSelectedText()", ->
|
||||
@@ -2810,61 +2800,6 @@ describe "EditorView", ->
|
||||
expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(2)).toBe ' var sort = function(items) {'
|
||||
|
||||
describe "when editor:duplicate-line is triggered", ->
|
||||
describe "where there is no selection", ->
|
||||
describe "when the cursor isn't on a folded line", ->
|
||||
it "duplicates the current line below and moves the cursor down one row", ->
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
editorView.trigger 'editor:duplicate-line'
|
||||
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {'
|
||||
expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {'
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1, 5]
|
||||
|
||||
describe "when the cursor is on a folded line", ->
|
||||
it "duplicates the entire fold before and moves the cursor to the new fold", ->
|
||||
editor.setCursorBufferPosition([4])
|
||||
editor.foldCurrentRow()
|
||||
editorView.trigger 'editor:duplicate-line'
|
||||
expect(editor.getCursorScreenPosition()).toEqual [5]
|
||||
expect(editor.isFoldedAtScreenRow(4)).toBeTruthy()
|
||||
expect(editor.isFoldedAtScreenRow(5)).toBeTruthy()
|
||||
expect(buffer.lineForRow(8)).toBe ' while(items.length > 0) {'
|
||||
expect(buffer.lineForRow(9)).toBe ' current = items.shift();'
|
||||
expect(buffer.lineForRow(10)).toBe ' current < pivot ? left.push(current) : right.push(current);'
|
||||
expect(buffer.lineForRow(11)).toBe ' }'
|
||||
|
||||
describe "when the cursor is on the last line and it doesn't have a trailing newline", ->
|
||||
it "inserts a newline and the duplicated line", ->
|
||||
editor.moveCursorToBottom()
|
||||
editorView.trigger 'editor:duplicate-line'
|
||||
expect(buffer.lineForRow(12)).toBe '};'
|
||||
expect(buffer.lineForRow(13)).toBe '};'
|
||||
expect(buffer.lineForRow(14)).toBeUndefined()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [13, 2]
|
||||
|
||||
describe "when the cursor in on the last line and it is only a newline", ->
|
||||
it "duplicates the current line below and moves the cursor down one row", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.insertNewline()
|
||||
editor.moveCursorToBottom()
|
||||
editorView.trigger 'editor:duplicate-line'
|
||||
expect(buffer.lineForRow(13)).toBe ''
|
||||
expect(buffer.lineForRow(14)).toBe ''
|
||||
expect(buffer.lineForRow(15)).toBeUndefined()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [14, 0]
|
||||
|
||||
describe "when the cursor is on the second to last line and the last line only a newline", ->
|
||||
it "duplicates the current line below and moves the cursor down one row", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.insertNewline()
|
||||
editor.setCursorBufferPosition([12])
|
||||
editorView.trigger 'editor:duplicate-line'
|
||||
expect(buffer.lineForRow(12)).toBe '};'
|
||||
expect(buffer.lineForRow(13)).toBe '};'
|
||||
expect(buffer.lineForRow(14)).toBe ''
|
||||
expect(buffer.lineForRow(15)).toBeUndefined()
|
||||
expect(editor.getCursorBufferPosition()).toEqual [13, 0]
|
||||
|
||||
describe "when the escape key is pressed on the editor view", ->
|
||||
it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", ->
|
||||
atom.keymap.bindKeys 'name', '.editor', {'escape': 'test-event'}
|
||||
@@ -2987,6 +2922,30 @@ describe "EditorView", ->
|
||||
editorView.pixelPositionForScreenPosition([1, 5])
|
||||
expect(editorView.measureToColumn.callCount).toBe 0
|
||||
|
||||
describe "when stylesheets are changed", ->
|
||||
afterEach ->
|
||||
atom.themes.removeStylesheet 'line-height'
|
||||
atom.themes.removeStylesheet 'char-width'
|
||||
|
||||
it "updates the editor if the line height or character width changes due to a stylesheet change", ->
|
||||
editorView.attachToDom()
|
||||
editor.setCursorScreenPosition([1, 3])
|
||||
expect(editorView.pixelPositionForScreenPosition([1, 3])).toEqual {top: 20, left: 30}
|
||||
expect(editorView.getCursorView().position()).toEqual {top: 20, left: 30}
|
||||
|
||||
atom.themes.applyStylesheet 'line-height', """
|
||||
.editor { line-height: 2; }
|
||||
"""
|
||||
|
||||
expect(editorView.pixelPositionForScreenPosition([1, 3])).toEqual {top: 32, left: 30}
|
||||
expect(editorView.getCursorView().position()).toEqual {top: 32, left: 30}
|
||||
|
||||
atom.themes.applyStylesheet 'char-width', """
|
||||
.editor { letter-spacing: 2px; }
|
||||
"""
|
||||
expect(editorView.pixelPositionForScreenPosition([1, 3])).toEqual {top: 32, left: 36}
|
||||
expect(editorView.getCursorView().position()).toEqual {top: 32, left: 36}
|
||||
|
||||
describe "when the editor contains hard tabs", ->
|
||||
it "correctly calculates the the position left for a column", ->
|
||||
editor.setText('\ttest')
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = activate: ->
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "no events",
|
||||
"version": "0.1.0",
|
||||
"activationEvents": []
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
Keymap = require '../src/keymap'
|
||||
{$, $$, WorkspaceView} = require 'atom'
|
||||
|
||||
describe "Keymap", ->
|
||||
fragment = null
|
||||
keymap = null
|
||||
resourcePath = atom.getLoadSettings().resourcePath
|
||||
configDirPath = null
|
||||
|
||||
beforeEach ->
|
||||
configDirPath = temp.mkdirSync('atom')
|
||||
keymap = new Keymap({configDirPath, resourcePath})
|
||||
fragment = $ """
|
||||
<div class="command-mode">
|
||||
<div class="child-node">
|
||||
<div class="grandchild-node"/>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
afterEach ->
|
||||
keymap.destroy()
|
||||
|
||||
describe ".handleKeyEvent(event)", ->
|
||||
deleteCharHandler = null
|
||||
insertCharHandler = null
|
||||
commandZHandler = null
|
||||
|
||||
beforeEach ->
|
||||
keymap.bindKeys 'name', '.command-mode', 'x': 'deleteChar'
|
||||
keymap.bindKeys 'name', '.insert-mode', 'x': 'insertChar'
|
||||
keymap.bindKeys 'name', '.command-mode', 'cmd-z': 'commandZPressed'
|
||||
|
||||
deleteCharHandler = jasmine.createSpy('deleteCharHandler')
|
||||
insertCharHandler = jasmine.createSpy('insertCharHandler')
|
||||
commandZHandler = jasmine.createSpy('commandZHandler')
|
||||
fragment.on 'deleteChar', deleteCharHandler
|
||||
fragment.on 'insertChar', insertCharHandler
|
||||
fragment.on 'commandZPressed', commandZHandler
|
||||
|
||||
describe "when no binding matches the event's keystroke", ->
|
||||
it "does not return false so the event continues to propagate", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('0', target: fragment[0]))).not.toBe false
|
||||
|
||||
describe "when a non-English keyboard language is used", ->
|
||||
it "uses the physical character pressed instead of the character it maps to in the current language", ->
|
||||
event = keydownEvent('U+03B6', metaKey: true, which: 122, target: fragment[0]) # This is the 'z' key using the Greek keyboard layout
|
||||
result = keymap.handleKeyEvent(event)
|
||||
|
||||
expect(result).toBe(false)
|
||||
expect(commandZHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when at least one binding fully matches the event's keystroke", ->
|
||||
describe "when the event's target node matches a selector with a matching binding", ->
|
||||
it "triggers the command event associated with that binding on the target node and returns false", ->
|
||||
result = keymap.handleKeyEvent(keydownEvent('x', target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(deleteCharHandler).toHaveBeenCalled()
|
||||
expect(insertCharHandler).not.toHaveBeenCalled()
|
||||
|
||||
deleteCharHandler.reset()
|
||||
fragment.removeClass('command-mode').addClass('insert-mode')
|
||||
|
||||
event = keydownEvent('x', target: fragment[0])
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
expect(insertCharHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when the event's target node *descends* from a selector with a matching binding", ->
|
||||
it "triggers the command event associated with that binding on the target node and returns false", ->
|
||||
target = fragment.find('.child-node')[0]
|
||||
result = keymap.handleKeyEvent(keydownEvent('x', target: target))
|
||||
expect(result).toBe(false)
|
||||
expect(deleteCharHandler).toHaveBeenCalled()
|
||||
expect(insertCharHandler).not.toHaveBeenCalled()
|
||||
|
||||
deleteCharHandler.reset()
|
||||
fragment.removeClass('command-mode').addClass('insert-mode')
|
||||
|
||||
keymap.handleKeyEvent(keydownEvent('x', target: target))
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
expect(insertCharHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when the event's target node descends from multiple nodes that match selectors with a binding", ->
|
||||
beforeEach ->
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'foo'
|
||||
|
||||
it "only triggers bindings on selectors associated with the closest ancestor node", ->
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
fragment.on 'foo', fooHandler
|
||||
|
||||
target = fragment.find('.grandchild-node')[0]
|
||||
keymap.handleKeyEvent(keydownEvent('x', target: target))
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
expect(insertCharHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when 'abortKeyBinding' is called on the triggered event", ->
|
||||
[fooHandler1, fooHandler2] = []
|
||||
|
||||
beforeEach ->
|
||||
fooHandler1 = jasmine.createSpy('fooHandler1').andCallFake (e) ->
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
e.abortKeyBinding()
|
||||
fooHandler2 = jasmine.createSpy('fooHandler2')
|
||||
|
||||
fragment.find('.child-node').on 'foo', fooHandler1
|
||||
fragment.on 'foo', fooHandler2
|
||||
|
||||
it "aborts the current event and tries again with the next-most-specific key binding", ->
|
||||
target = fragment.find('.grandchild-node')[0]
|
||||
keymap.handleKeyEvent(keydownEvent('x', target: target))
|
||||
expect(fooHandler1).toHaveBeenCalled()
|
||||
expect(fooHandler2).not.toHaveBeenCalled()
|
||||
expect(deleteCharHandler).toHaveBeenCalled()
|
||||
|
||||
it "does not throw an exception if the event was not triggered by the keymap", ->
|
||||
fragment.find('.grandchild-node').trigger 'foo'
|
||||
|
||||
describe "when the event bubbles to a node that matches multiple selectors", ->
|
||||
describe "when the matching selectors differ in specificity", ->
|
||||
it "triggers the binding for the most specific selector", ->
|
||||
keymap.bindKeys 'name', 'div .child-node', 'x': 'foo'
|
||||
keymap.bindKeys 'name', '.command-mode .child-node !important', 'x': 'baz'
|
||||
keymap.bindKeys 'name', '.command-mode .child-node', 'x': 'quux'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'bar'
|
||||
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
barHandler = jasmine.createSpy 'barHandler'
|
||||
bazHandler = jasmine.createSpy 'bazHandler'
|
||||
fragment.on 'foo', fooHandler
|
||||
fragment.on 'bar', barHandler
|
||||
fragment.on 'baz', bazHandler
|
||||
|
||||
target = fragment.find('.grandchild-node')[0]
|
||||
keymap.handleKeyEvent(keydownEvent('x', target: target))
|
||||
|
||||
expect(fooHandler).not.toHaveBeenCalled()
|
||||
expect(barHandler).not.toHaveBeenCalled()
|
||||
expect(bazHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when the matching selectors have the same specificity", ->
|
||||
it "triggers the bindings for the most recently declared selector", ->
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'foo', 'y': 'baz'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'bar'
|
||||
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
barHandler = jasmine.createSpy 'barHandler'
|
||||
bazHandler = jasmine.createSpy 'bazHandler'
|
||||
fragment.on 'foo', fooHandler
|
||||
fragment.on 'bar', barHandler
|
||||
fragment.on 'baz', bazHandler
|
||||
|
||||
target = fragment.find('.grandchild-node')[0]
|
||||
keymap.handleKeyEvent(keydownEvent('x', target: target))
|
||||
|
||||
expect(barHandler).toHaveBeenCalled()
|
||||
expect(fooHandler).not.toHaveBeenCalled()
|
||||
|
||||
keymap.handleKeyEvent(keydownEvent('y', target: target))
|
||||
expect(bazHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when the event's target is the document body", ->
|
||||
it "triggers the mapped event on the workspaceView", ->
|
||||
atom.workspaceView = new WorkspaceView
|
||||
atom.workspaceView.attachToDom()
|
||||
keymap.bindKeys 'name', 'body', 'x': 'foo'
|
||||
fooHandler = jasmine.createSpy("fooHandler")
|
||||
atom.workspaceView.on 'foo', fooHandler
|
||||
|
||||
result = keymap.handleKeyEvent(keydownEvent('x', target: document.body))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
expect(insertCharHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when the event matches a 'native!' binding", ->
|
||||
it "returns true, allowing the browser's native key handling to process the event", ->
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'x': 'native!'
|
||||
nativeHandler = jasmine.createSpy("nativeHandler")
|
||||
fragment.on 'native!', nativeHandler
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment.find('.grandchild-node')[0]))).toBe true
|
||||
expect(nativeHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when at least one binding partially matches the event's keystroke", ->
|
||||
[quitHandler, closeOtherWindowsHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
keymap.bindKeys 'name', "*",
|
||||
'ctrl-x ctrl-c': 'quit'
|
||||
'ctrl-x 1': 'close-other-windows'
|
||||
|
||||
quitHandler = jasmine.createSpy('quitHandler')
|
||||
closeOtherWindowsHandler = jasmine.createSpy('closeOtherWindowsHandler')
|
||||
fragment.on 'quit', quitHandler
|
||||
fragment.on 'close-other-windows', closeOtherWindowsHandler
|
||||
|
||||
it "only matches entire keystroke patterns", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: fragment[0]))).not.toBe false
|
||||
|
||||
describe "when the event's target node matches a selector with a partially matching multi-stroke binding", ->
|
||||
describe "when a second keystroke added to the first to match a multi-stroke binding completely", ->
|
||||
it "triggers the event associated with the matched multi-stroke binding", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment[0], ctrlKey: true))).toBeFalsy()
|
||||
expect(keymap.handleKeyEvent(keydownEvent('ctrl', target: fragment[0]))).toBeFalsy() # This simulates actual key event behavior
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: fragment[0], ctrlKey: true))).toBeFalsy()
|
||||
|
||||
expect(quitHandler).toHaveBeenCalled()
|
||||
expect(closeOtherWindowsHandler).not.toHaveBeenCalled()
|
||||
quitHandler.reset()
|
||||
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment[0], ctrlKey: true))).toBeFalsy()
|
||||
expect(keymap.handleKeyEvent(keydownEvent('1', target: fragment[0]))).toBeFalsy()
|
||||
|
||||
expect(quitHandler).not.toHaveBeenCalled()
|
||||
expect(closeOtherWindowsHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a second keystroke added to the first doesn't match any bindings", ->
|
||||
it "clears the queued keystroke without triggering any events", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment[0], ctrlKey: true))).toBe false
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: fragment[0]))).toBe false
|
||||
expect(quitHandler).not.toHaveBeenCalled()
|
||||
expect(closeOtherWindowsHandler).not.toHaveBeenCalled()
|
||||
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: fragment[0]))).not.toBe false
|
||||
|
||||
describe "when the event's target node descends from multiple nodes that match selectors with a partial binding match", ->
|
||||
it "allows any of the bindings to be triggered upon a second keystroke, favoring the most specific selector", ->
|
||||
keymap.bindKeys 'name', ".grandchild-node", 'ctrl-x ctrl-c': 'more-specific-quit'
|
||||
grandchildNode = fragment.find('.grandchild-node')[0]
|
||||
moreSpecificQuitHandler = jasmine.createSpy('moreSpecificQuitHandler')
|
||||
fragment.on 'more-specific-quit', moreSpecificQuitHandler
|
||||
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: grandchildNode, ctrlKey: true))).toBeFalsy()
|
||||
expect(keymap.handleKeyEvent(keydownEvent('1', target: grandchildNode))).toBeFalsy()
|
||||
expect(quitHandler).not.toHaveBeenCalled()
|
||||
expect(moreSpecificQuitHandler).not.toHaveBeenCalled()
|
||||
expect(closeOtherWindowsHandler).toHaveBeenCalled()
|
||||
closeOtherWindowsHandler.reset()
|
||||
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: grandchildNode, ctrlKey: true))).toBeFalsy()
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: grandchildNode, ctrlKey: true))).toBeFalsy()
|
||||
expect(quitHandler).not.toHaveBeenCalled()
|
||||
expect(closeOtherWindowsHandler).not.toHaveBeenCalled()
|
||||
expect(moreSpecificQuitHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when there is a complete binding with a less specific selector", ->
|
||||
it "favors the more specific partial match", ->
|
||||
|
||||
describe "when there is a complete binding with a more specific selector", ->
|
||||
it "favors the more specific complete match", ->
|
||||
|
||||
describe ".bindKeys(name, selector, bindings)", ->
|
||||
it "normalizes the key patterns in the hash to put the modifiers in alphabetical order", ->
|
||||
fooHandler = jasmine.createSpy('fooHandler')
|
||||
fragment.on 'foo', fooHandler
|
||||
keymap.bindKeys 'name', '*', 'ctrl-alt-delete': 'foo'
|
||||
result = keymap.handleKeyEvent(keydownEvent('delete', ctrlKey: true, altKey: true, target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
|
||||
fooHandler.reset()
|
||||
keymap.bindKeys 'name', '*', 'ctrl-alt--': 'foo'
|
||||
result = keymap.handleKeyEvent(keydownEvent('-', ctrlKey: true, altKey: true, target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
|
||||
describe ".remove(name)", ->
|
||||
it "removes the binding set with the given selector and bindings", ->
|
||||
keymap.add 'nature',
|
||||
'.green':
|
||||
'ctrl-c': 'cultivate'
|
||||
'.brown':
|
||||
'ctrl-h': 'harvest'
|
||||
|
||||
keymap.add 'medical',
|
||||
'.green':
|
||||
'ctrl-v': 'vomit'
|
||||
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'green')).toHaveLength 2
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'brown')).toHaveLength 1
|
||||
|
||||
keymap.remove('nature')
|
||||
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'green')).toHaveLength 1
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'brown')).toEqual []
|
||||
|
||||
describe ".keystrokeStringForEvent(event)", ->
|
||||
describe "when no modifiers are pressed", ->
|
||||
it "returns a string that identifies the key pressed", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('a'))).toBe 'a'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('['))).toBe '['
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('*'))).toBe '*'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left'))).toBe 'left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('\b'))).toBe 'backspace'
|
||||
|
||||
describe "when ctrl, alt or command is pressed with a non-modifier key", ->
|
||||
it "returns a string that identifies the key pressed", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('a', altKey: true))).toBe 'alt-a'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('[', metaKey: true))).toBe 'cmd-['
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('*', ctrlKey: true))).toBe 'ctrl-*'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', ctrlKey: true, metaKey: true, altKey: true))).toBe 'alt-cmd-ctrl-left'
|
||||
|
||||
describe "when shift is pressed when a non-modifer key", ->
|
||||
it "returns a string that identifies the key pressed", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('A', shiftKey: true))).toBe 'A'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('{', shiftKey: true))).toBe '{'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', shiftKey: true))).toBe 'shift-left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('Left', shiftKey: true))).toBe 'shift-left'
|
||||
|
||||
describe ".keyBindingsMatchingElement(element)", ->
|
||||
it "returns the matching bindings for the element", ->
|
||||
keymap.bindKeys 'name', '.command-mode', 'c': 'c'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'g': 'g'
|
||||
|
||||
bindings = keymap.keyBindingsMatchingElement(fragment.find('.grandchild-node'))
|
||||
expect(bindings).toHaveLength 2
|
||||
expect(bindings[0].command).toEqual "g"
|
||||
expect(bindings[1].command).toEqual "c"
|
||||
|
||||
describe "when multiple bindings match a keystroke", ->
|
||||
it "only returns bindings that match the most specific selector", ->
|
||||
keymap.bindKeys 'name', '.command-mode', 'g': 'cmd-mode'
|
||||
keymap.bindKeys 'name', '.command-mode .grandchild-node', 'g': 'cmd-and-grandchild-node'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'g': 'grandchild-node'
|
||||
|
||||
bindings = keymap.keyBindingsMatchingElement(fragment.find('.grandchild-node'))
|
||||
expect(bindings).toHaveLength 3
|
||||
expect(bindings[0].command).toEqual "cmd-and-grandchild-node"
|
||||
|
||||
describe ".keyBindingsForCommandMatchingElement(element)", ->
|
||||
beforeEach ->
|
||||
keymap.add 'nature',
|
||||
'.green':
|
||||
'ctrl-c': 'cultivate'
|
||||
'.green-2':
|
||||
'ctrl-o': 'cultivate'
|
||||
'.brown':
|
||||
'ctrl-h': 'harvest'
|
||||
'.blue':
|
||||
'ctrl-c': 'fly'
|
||||
|
||||
it "finds a keymap for an element", ->
|
||||
el = $$ -> @div class: 'green'
|
||||
bindings = keymap.keyBindingsForCommandMatchingElement('cultivate', el)
|
||||
expect(bindings).toHaveLength 1
|
||||
expect(bindings[0].keystroke).toEqual "ctrl-c"
|
||||
|
||||
it "no keymap an element without that map", ->
|
||||
el = $$ -> @div class: 'brown'
|
||||
bindings = keymap.keyBindingsForCommandMatchingElement('cultivate', el)
|
||||
expect(bindings).toHaveLength 0
|
||||
|
||||
describe "loading platform specific keybindings", ->
|
||||
customKeymap = null
|
||||
|
||||
beforeEach ->
|
||||
resourcePath = temp.mkdirSync('atom')
|
||||
customKeymap = new Keymap({configDirPath, resourcePath})
|
||||
|
||||
afterEach ->
|
||||
customKeymap.destroy()
|
||||
|
||||
it "doesn't load keybindings from other platforms", ->
|
||||
win32FilePath = path.join(resourcePath, "keymaps", "win32.cson")
|
||||
darwinFilePath = path.join(resourcePath, "keymaps", "darwin.cson")
|
||||
fs.writeFileSync(win32FilePath, '"body": "ctrl-l": "core:win32-move-left"')
|
||||
fs.writeFileSync(darwinFilePath, '"body": "ctrl-l": "core:darwin-move-left"')
|
||||
|
||||
customKeymap.loadBundledKeymaps()
|
||||
keyBindings = customKeymap.keyBindingsForKeystroke('ctrl-l')
|
||||
expect(keyBindings).toHaveLength 1
|
||||
expect(keyBindings[0].command).toBe "core:#{process.platform}-move-left"
|
||||
|
||||
describe "when the user keymap file is changed", ->
|
||||
it "is reloaded", ->
|
||||
keymapFilePath = path.join(configDirPath, "keymap.cson")
|
||||
fs.writeFileSync(keymapFilePath, '"body": "ctrl-l": "core:move-left"')
|
||||
keymap.loadUserKeymap()
|
||||
|
||||
spyOn(keymap, 'loadUserKeymap').andCallThrough()
|
||||
fs.writeFileSync(keymapFilePath, "'body': 'ctrl-l': 'core:move-right'")
|
||||
|
||||
waitsFor ->
|
||||
keymap.loadUserKeymap.callCount > 0
|
||||
|
||||
runs ->
|
||||
keyBinding = keymap.keyBindingsForKeystroke('ctrl-l')[0]
|
||||
expect(keyBinding.command).toBe 'core:move-right'
|
||||
keymap.loadUserKeymap.reset()
|
||||
fs.removeSync(keymapFilePath)
|
||||
|
||||
waitsFor ->
|
||||
keymap.loadUserKeymap.callCount > 0
|
||||
|
||||
runs ->
|
||||
keyBinding = keymap.keyBindingsForKeystroke('ctrl-l')[0]
|
||||
expect(keyBinding).toBeUndefined()
|
||||
|
||||
it "logs a warning when it can't be parsed", ->
|
||||
keymapFilePath = path.join(configDirPath, "keymap.json")
|
||||
fs.writeFileSync(keymapFilePath, '')
|
||||
keymap.loadUserKeymap()
|
||||
|
||||
spyOn(keymap, 'loadUserKeymap').andCallThrough()
|
||||
fs.writeFileSync(keymapFilePath, '}{')
|
||||
spyOn(console, 'warn')
|
||||
|
||||
waitsFor ->
|
||||
keymap.loadUserKeymap.callCount > 0
|
||||
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
|
||||
|
||||
describe "when adding a binding with an invalid selector", ->
|
||||
it "logs a warning and does not add it", ->
|
||||
spyOn(console, 'warn')
|
||||
keybinding =
|
||||
'##selector':
|
||||
'cmd-a': 'invalid-command'
|
||||
keymap.add('test', keybinding)
|
||||
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
|
||||
expect(-> keymap.keyBindingsMatchingElement(document.body)).not.toThrow()
|
||||
expect(keymap.keyBindingsForCommand('invalid:command')).toEqual []
|
||||
@@ -208,6 +208,20 @@ describe "LanguageMode", ->
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe "// @color: #4D926F;"
|
||||
|
||||
describe "xml", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.xml', autoIndent: false)
|
||||
editor.setText("<!-- test -->")
|
||||
{buffer, languageMode} = editor
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-xml')
|
||||
|
||||
describe "when uncommenting lines", ->
|
||||
it "removes the leading whitespace from the comment end pattern match", ->
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe "test"
|
||||
|
||||
describe "folding", ->
|
||||
beforeEach ->
|
||||
editor = atom.project.openSync('sample.js', autoIndent: false)
|
||||
|
||||
@@ -292,7 +292,7 @@ describe "Pane", ->
|
||||
pane.activeItem.path = __filename
|
||||
pane.activeItem.saveAs = jasmine.createSpy("saveAs")
|
||||
pane.saveActiveItemAs()
|
||||
expect(atom.showSaveDialogSync).toHaveBeenCalledWith(__dirname)
|
||||
expect(atom.showSaveDialogSync).toHaveBeenCalledWith(__filename)
|
||||
expect(pane.activeItem.saveAs).toHaveBeenCalledWith('/selected/path')
|
||||
|
||||
describe "when the current item does not have a saveAs method", ->
|
||||
|
||||
@@ -159,14 +159,14 @@ describe "PaneView", ->
|
||||
|
||||
describe "when an unmodifed buffer's path is deleted", ->
|
||||
it "removes the pane item", ->
|
||||
jasmine.unspy(window, 'setTimeout')
|
||||
filePath = temp.openSync('atom').path
|
||||
editor = atom.project.openSync(filePath)
|
||||
pane.activateItem(editor)
|
||||
expect(pane.items).toHaveLength(5)
|
||||
|
||||
fs.removeSync(filePath)
|
||||
waitsFor 30000, ->
|
||||
pane.items.length == 4
|
||||
waitsFor -> pane.items.length == 4
|
||||
|
||||
describe "when a pane is destroyed", ->
|
||||
[pane2, pane2Model] = []
|
||||
|
||||
@@ -43,6 +43,15 @@ describe "SelectListView", ->
|
||||
expect(list.find('li:eq(0)')).toHaveClass 'A'
|
||||
expect(selectList.getSelectedItem()).toBe items[0]
|
||||
|
||||
it "allows raw HTML to be returned", ->
|
||||
selectList.viewForItem = (item) ->
|
||||
"<li>#{item}</li>"
|
||||
|
||||
selectList.setItems(['Bermuda', 'Bahama'])
|
||||
|
||||
expect(list.find('li:eq(0)')).toHaveText 'Bermuda'
|
||||
expect(selectList.getSelectedItem()).toBe 'Bermuda'
|
||||
|
||||
describe "when the text of the mini editor changes", ->
|
||||
beforeEach ->
|
||||
selectList.attachToDom()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Start the crash reporter before anything else.
|
||||
require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
|
||||
|
||||
path = require 'path'
|
||||
|
||||
try
|
||||
require '../src/window'
|
||||
Atom = require '../src/atom'
|
||||
@@ -12,6 +14,12 @@ try
|
||||
|
||||
{runSpecSuite} = require './jasmine-helper'
|
||||
|
||||
# Add 'src/exports' to module search path.
|
||||
exportsPath = path.resolve(atom.getLoadSettings().resourcePath, 'exports')
|
||||
require('module').globalPaths.push(exportsPath)
|
||||
# Still set NODE_PATH since tasks may need it.
|
||||
process.env.NODE_PATH = exportsPath
|
||||
|
||||
document.title = "Spec Suite"
|
||||
runSpecSuite './spec-suite', atom.getLoadSettings().logFile
|
||||
catch error
|
||||
|
||||
@@ -6,8 +6,8 @@ require '../vendor/jasmine-jquery'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
Keymap = require '../src/keymap-extensions'
|
||||
{$, WorkspaceView} = require 'atom'
|
||||
Keymap = require '../src/keymap'
|
||||
Config = require '../src/config'
|
||||
{Point} = require 'text-buffer'
|
||||
Project = require '../src/project'
|
||||
@@ -180,7 +180,15 @@ window.keyIdentifierForKey = (key) ->
|
||||
"U+00" + charCode.toString(16)
|
||||
|
||||
window.keydownEvent = (key, properties={}) ->
|
||||
properties = $.extend({originalEvent: { keyIdentifier: keyIdentifierForKey(key) }}, properties)
|
||||
originalEventProperties = {}
|
||||
originalEventProperties.ctrl = properties.ctrlKey
|
||||
originalEventProperties.alt = properties.altKey
|
||||
originalEventProperties.shift = properties.shiftKey
|
||||
originalEventProperties.cmd = properties.metaKey
|
||||
originalEventProperties.target = properties.target?[0] ? properties.target
|
||||
originalEventProperties.which = properties.which
|
||||
originalEvent = Keymap.keydownEvent(key, originalEventProperties)
|
||||
properties = $.extend({originalEvent}, properties)
|
||||
$.Event("keydown", properties)
|
||||
|
||||
window.mouseEvent = (type, properties) ->
|
||||
|
||||
@@ -5,7 +5,7 @@ path = require 'path'
|
||||
require './spec-helper'
|
||||
|
||||
requireSpecs = (specDirectory, specType) ->
|
||||
for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.coffee$/.test specFilePath
|
||||
for specFilePath in fs.listTreeSync(specDirectory) when /-spec\.(coffee|js)$/.test specFilePath
|
||||
require specFilePath
|
||||
|
||||
# Set spec directory on spec for setting up the project in spec-helper
|
||||
@@ -26,6 +26,7 @@ setSpecDirectory = (specDirectory) ->
|
||||
|
||||
runAllSpecs = ->
|
||||
{resourcePath} = atom.getLoadSettings()
|
||||
|
||||
# Only run core specs when resource path is the Atom repository
|
||||
if Git.exists(resourcePath)
|
||||
requireSpecs(path.join(resourcePath, 'spec'))
|
||||
|
||||
@@ -170,8 +170,11 @@ describe "ThemeManager", ->
|
||||
expect($(document.body).css('font-weight')).not.toBe("bold")
|
||||
themeManager.requireStylesheet(cssPath)
|
||||
expect($(document.body).css('font-weight')).toBe("bold")
|
||||
|
||||
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
|
||||
themeManager.removeStylesheet(cssPath)
|
||||
expect($(document.body).css('font-weight')).not.toBe("bold")
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
beforeEach ->
|
||||
@@ -204,12 +207,15 @@ describe "ThemeManager", ->
|
||||
fs.writeFileSync(userStylesheetPath, 'body {border-style: dotted !important;}')
|
||||
|
||||
spyOn(themeManager, 'getUserStylesheetPath').andReturn userStylesheetPath
|
||||
themeManager.on 'stylesheets-changed', stylesheetsChangedHandler = jasmine.createSpy("stylesheetsChangedHandler")
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
expect($(document.body).css('border-style')).toBe 'dotted'
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
stylesheetsChangedHandler.reset()
|
||||
spyOn(themeManager, 'loadUserStylesheet').andCallThrough()
|
||||
fs.writeFileSync(userStylesheetPath, 'body {border-style: dashed}')
|
||||
|
||||
@@ -218,6 +224,8 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
expect($(document.body).css('border-style')).toBe 'dashed'
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
stylesheetsChangedHandler.reset()
|
||||
fs.removeSync(userStylesheetPath)
|
||||
|
||||
waitsFor ->
|
||||
@@ -225,6 +233,7 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
expect($(document.body).css('border-style')).toBe 'none'
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a non-existent theme is present in the config", ->
|
||||
it "logs a warning but does not throw an exception (regression)", ->
|
||||
|
||||
@@ -452,3 +452,14 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenForPosition([0,0]).value).toBe ' '
|
||||
atom.config.set('editor.tabLength', 6)
|
||||
expect(tokenizedBuffer.tokenForPosition([0,0]).value).toBe ' '
|
||||
|
||||
it "does not allow the tab length to be less than 1", ->
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
buffer.setText('\ttest')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
expect(tokenizedBuffer.tokenForPosition([0,0]).value).toBe ' '
|
||||
atom.config.set('editor.tabLength', 1)
|
||||
expect(tokenizedBuffer.tokenForPosition([0,0]).value).toBe ' '
|
||||
atom.config.set('editor.tabLength', 0)
|
||||
expect(tokenizedBuffer.tokenForPosition([0,0]).value).toBe ' '
|
||||
|
||||
@@ -90,11 +90,13 @@ describe "Window", ->
|
||||
it "saves the serialized state of the window so it can be deserialized after reload", ->
|
||||
workspaceState = atom.workspace.serialize()
|
||||
syntaxState = atom.syntax.serialize()
|
||||
projectState = atom.project.serialize()
|
||||
|
||||
atom.unloadEditorWindow()
|
||||
|
||||
expect(atom.state.workspace).toEqual workspaceState
|
||||
expect(atom.state.syntax).toEqual syntaxState
|
||||
expect(atom.state.project).toEqual projectState
|
||||
expect(atom.saveSync).toHaveBeenCalled()
|
||||
|
||||
it "unsubscribes from all buffers", ->
|
||||
|
||||
@@ -241,3 +241,11 @@ describe "WorkspaceView", ->
|
||||
expect(atom.workspaceView.getActivePane().getItems()).toHaveLength 1
|
||||
atom.workspaceView.trigger('core:close')
|
||||
expect(atom.workspaceView.getActivePane().getItems()).toHaveLength 0
|
||||
|
||||
describe "the scrollbar visibility class", ->
|
||||
it "has a class based on the style of the scrollbar", ->
|
||||
scrollbarStyle = require 'scrollbar-style'
|
||||
scrollbarStyle.emitValue 'legacy'
|
||||
expect(atom.workspaceView).toHaveClass 'scrollbars-visible-always'
|
||||
scrollbarStyle.emitValue 'overlay'
|
||||
expect(atom.workspaceView).toHaveClass 'scrollbars-visible-when-scrolling'
|
||||
|
||||
+10
-2
@@ -138,7 +138,7 @@ class Atom extends Model
|
||||
@loadTime = null
|
||||
|
||||
Config = require './config'
|
||||
Keymap = require './keymap'
|
||||
Keymap = require './keymap-extensions'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
Syntax = require './syntax'
|
||||
@@ -148,6 +148,12 @@ class Atom extends Model
|
||||
{devMode, resourcePath} = @getLoadSettings()
|
||||
configDirPath = @getConfigDirPath()
|
||||
|
||||
# Add 'src/exports' to module search path.
|
||||
exportsPath = path.resolve(resourcePath, 'exports')
|
||||
require('module').globalPaths.push(exportsPath)
|
||||
# Still set NODE_PATH since tasks may need it.
|
||||
process.env.NODE_PATH = exportsPath
|
||||
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymap = new Keymap({configDirPath, resourcePath})
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath})
|
||||
@@ -229,13 +235,14 @@ class Atom extends Model
|
||||
|
||||
deserializeProject: ->
|
||||
Project = require './project'
|
||||
@project ?= @deserializers.deserialize(@project) ? new Project(path: @getLoadSettings().initialPath)
|
||||
@project ?= @deserializers.deserialize(@state.project) ? new Project(path: @getLoadSettings().initialPath)
|
||||
|
||||
deserializeWorkspaceView: ->
|
||||
Workspace = require './workspace'
|
||||
WorkspaceView = require './workspace-view'
|
||||
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
|
||||
@workspaceView = new WorkspaceView(@workspace)
|
||||
@keymap.defaultTarget = @workspaceView[0]
|
||||
$(@workspaceViewParentSelector).append(@workspaceView)
|
||||
|
||||
deserializePackageStates: ->
|
||||
@@ -280,6 +287,7 @@ class Atom extends Model
|
||||
return if not @project and not @workspaceView
|
||||
|
||||
@state.syntax = @syntax.serialize()
|
||||
@state.project = @project.serialize()
|
||||
@state.workspace = @workspace.serialize()
|
||||
@packages.deactivatePackages()
|
||||
@state.packageStates = @packages.packageStates
|
||||
|
||||
@@ -71,11 +71,28 @@ class ApplicationMenu
|
||||
|
||||
# Toggles Install Update Item
|
||||
showInstallUpdateItem: (visible=true) ->
|
||||
if visible
|
||||
@showDownloadingUpdateItem(false)
|
||||
@showCheckForUpdateItem(false)
|
||||
|
||||
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Restart and Install Update'))
|
||||
item.visible = visible
|
||||
|
||||
# Toggles Downloading Update Item
|
||||
showDownloadingUpdateItem: (visible=true) ->
|
||||
if visible
|
||||
@showInstallUpdateItem(false)
|
||||
@showCheckForUpdateItem(false)
|
||||
|
||||
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Downloading Update'))
|
||||
item.visible = visible
|
||||
|
||||
# Toggles Check For Update Item
|
||||
showCheckForUpdateItem: (visible=true) ->
|
||||
if visible
|
||||
@showDownloadingUpdateItem(false)
|
||||
@showInstallUpdateItem(false)
|
||||
|
||||
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Check for Update'))
|
||||
item.visible = visible
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ socketPath =
|
||||
module.exports =
|
||||
class AtomApplication
|
||||
_.extend @prototype, EventEmitter.prototype
|
||||
updateVersion: null
|
||||
|
||||
# Public: The entry point into the Atom application.
|
||||
@open: (options) ->
|
||||
@@ -130,51 +129,42 @@ class AtomApplication
|
||||
|
||||
# Enable updates unless running from a local build of Atom.
|
||||
setupAutoUpdater: ->
|
||||
return if /\w{7}/.test(@version) # Only released versions should check for updates.
|
||||
|
||||
autoUpdater.setFeedUrl "https://atom.io/api/updates?version=#{@version}"
|
||||
|
||||
autoUpdater.on 'checking-for-update', =>
|
||||
@applicationMenu.showDownloadingUpdateItem(false)
|
||||
@applicationMenu.showInstallUpdateItem(false)
|
||||
@applicationMenu.showCheckForUpdateItem(false)
|
||||
|
||||
autoUpdater.on 'update-not-available', =>
|
||||
@applicationMenu.showInstallUpdateItem(false)
|
||||
@applicationMenu.showCheckForUpdateItem(true)
|
||||
|
||||
autoUpdater.on 'update-downloaded', (event, releaseNotes, releaseName, releaseDate, releaseURL) =>
|
||||
atomWindow.sendCommand('window:update-available', [releaseName, releaseNotes]) for atomWindow in @windows
|
||||
autoUpdater.on 'update-available', =>
|
||||
@applicationMenu.showDownloadingUpdateItem(true)
|
||||
|
||||
autoUpdater.on 'update-downloaded', (event, releaseNotes, releaseVersion, releaseDate, releaseURL) =>
|
||||
atomWindow.sendCommand('window:update-available', [releaseVersion, releaseNotes]) for atomWindow in @windows
|
||||
@applicationMenu.showInstallUpdateItem(true)
|
||||
@applicationMenu.showCheckForUpdateItem(false)
|
||||
@updateVersion = releaseName
|
||||
|
||||
autoUpdater.on 'error', (event, message) =>
|
||||
@applicationMenu.showInstallUpdateItem(false)
|
||||
@applicationMenu.showCheckForUpdateItem(true)
|
||||
|
||||
# Check for update after Atom has fully started and the menus are created
|
||||
setTimeout((-> autoUpdater.checkForUpdates()), 5000)
|
||||
|
||||
checkForUpdate: ->
|
||||
autoUpdater.once 'update-available', ->
|
||||
dialog.showMessageBox
|
||||
type: 'info'
|
||||
buttons: ['OK']
|
||||
message: 'Update available.'
|
||||
detail: 'A new update is being downloaded.'
|
||||
@onUpdateNotAvailable ?= =>
|
||||
autoUpdater.removeListener 'error', @onUpdateError
|
||||
dialog.showMessageBox type: 'info', buttons: ['OK'], message: 'No update available.', detail: "Version #{@version} is the latest version."
|
||||
|
||||
autoUpdater.once 'update-not-available', =>
|
||||
dialog.showMessageBox
|
||||
type: 'info'
|
||||
buttons: ['OK']
|
||||
message: 'No update available.'
|
||||
detail: "Version #{@version} is the latest version."
|
||||
|
||||
autoUpdater.once 'error', (event, message)->
|
||||
dialog.showMessageBox
|
||||
type: 'warning'
|
||||
buttons: ['OK']
|
||||
message: 'There was an error checking for updates.'
|
||||
detail: message
|
||||
@onUpdateError ?= (event, message) =>
|
||||
autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable
|
||||
dialog.showMessageBox type: 'warning', buttons: ['OK'], message: 'There was an error checking for updates.', detail: message
|
||||
|
||||
autoUpdater.once 'update-not-available', @onUpdateNotAvailable
|
||||
autoUpdater.once 'error', @onUpdateError
|
||||
autoUpdater.checkForUpdates()
|
||||
|
||||
# Registers basic application commands, non-idempotent.
|
||||
@@ -206,10 +196,15 @@ class AtomApplication
|
||||
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
|
||||
|
||||
app.on 'window-all-closed', ->
|
||||
app.quit() if process.platform is 'win32'
|
||||
app.quit() if process.platform in ['win32', 'linux']
|
||||
|
||||
app.on 'will-quit', => @deleteSocketFile()
|
||||
app.on 'will-exit', => @deleteSocketFile()
|
||||
app.on 'will-quit', =>
|
||||
@killAllProcesses()
|
||||
@deleteSocketFile()
|
||||
|
||||
app.on 'will-exit', =>
|
||||
@killAllProcesses()
|
||||
@deleteSocketFile()
|
||||
|
||||
app.on 'open-file', (event, pathToOpen) =>
|
||||
event.preventDefault()
|
||||
@@ -256,7 +251,26 @@ class AtomApplication
|
||||
# The optional arguments to pass along.
|
||||
sendCommand: (command, args...) ->
|
||||
unless @emit(command, args...)
|
||||
@focusedWindow()?.sendCommand(command, args...)
|
||||
focusedWindow = @focusedWindow()
|
||||
if focusedWindow?
|
||||
focusedWindow.sendCommand(command, args...)
|
||||
else
|
||||
@sendCommandToFirstResponder(command)
|
||||
|
||||
# Translates the command into OS X action and sends it to application's first
|
||||
# responder.
|
||||
sendCommandToFirstResponder: (command) ->
|
||||
return false unless process.platform is 'darwin'
|
||||
|
||||
switch command
|
||||
when 'core:undo' then Menu.sendActionToFirstResponder('undo:')
|
||||
when 'core:redo' then Menu.sendActionToFirstResponder('redo:')
|
||||
when 'core:copy' then Menu.sendActionToFirstResponder('copy:')
|
||||
when 'core:cut' then Menu.sendActionToFirstResponder('cut:')
|
||||
when 'core:paste' then Menu.sendActionToFirstResponder('paste:')
|
||||
when 'core:select-all' then Menu.sendActionToFirstResponder('selectAll:')
|
||||
else return false
|
||||
true
|
||||
|
||||
# Public: Open the given path in the focused window when the event is
|
||||
# triggered.
|
||||
@@ -345,13 +359,25 @@ class AtomApplication
|
||||
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
|
||||
|
||||
openedWindow.browserWindow.on 'destroyed', =>
|
||||
for pid, trackedWindow of @pidsToOpenWindows when trackedWindow is openedWindow
|
||||
try
|
||||
process.kill(pid)
|
||||
catch error
|
||||
if error.code isnt 'ESRCH'
|
||||
console.log("Killing process #{pid} failed: #{error.code}")
|
||||
delete @pidsToOpenWindows[pid]
|
||||
@killProcessForWindow(openedWindow)
|
||||
|
||||
# Kill all processes associated with opened windows.
|
||||
killAllProcesses: ->
|
||||
@killProcess(pid) for pid of @pidsToOpenWindows
|
||||
|
||||
# Kill process associated with the given opened window.
|
||||
killProcessForWindow: (openedWindow) ->
|
||||
for pid, trackedWindow of @pidsToOpenWindows
|
||||
@killProcess(pid) if trackedWindow is openedWindow
|
||||
|
||||
# Kill the process with the given pid.
|
||||
killProcess: (pid) ->
|
||||
try
|
||||
process.kill(pid)
|
||||
catch error
|
||||
if error.code isnt 'ESRCH'
|
||||
console.log("Killing process #{pid} failed: #{error.code}")
|
||||
delete @pidsToOpenWindows[pid]
|
||||
|
||||
# Open an atom:// url.
|
||||
#
|
||||
@@ -427,8 +453,3 @@ class AtomApplication
|
||||
promptForPath: ({devMode}={}) ->
|
||||
dialog.showOpenDialog title: 'Open', properties: ['openFile', 'openDirectory', 'multiSelections', 'createDirectory'], (pathsToOpen) =>
|
||||
@openPaths({pathsToOpen, devMode})
|
||||
|
||||
# Public: If an update is available, it returns the new version string
|
||||
# otherwise it returns null.
|
||||
getUpdateVersion: ->
|
||||
@updateVersion
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
BrowserWindow = require 'browser-window'
|
||||
Menu = require 'menu'
|
||||
ContextMenu = require './context-menu'
|
||||
app = require 'app'
|
||||
dialog = require 'dialog'
|
||||
@@ -22,12 +21,7 @@ class AtomWindow
|
||||
{@resourcePath, pathToOpen, initialLine, @isSpec, @exitWhenDone} = settings
|
||||
global.atomApplication.addWindow(this)
|
||||
|
||||
@setupNodePath(@resourcePath)
|
||||
@browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath
|
||||
@browserWindow.restart = _.wrap _.bind(@browserWindow.restart, @browserWindow), (restart) =>
|
||||
@setupNodePath(@resourcePath)
|
||||
restart()
|
||||
|
||||
@handleEvents()
|
||||
|
||||
loadSettings = _.extend({}, settings)
|
||||
@@ -50,9 +44,6 @@ class AtomWindow
|
||||
|
||||
@openPath(pathToOpen, initialLine)
|
||||
|
||||
setupNodePath: (resourcePath) ->
|
||||
process.env['NODE_PATH'] = path.resolve(resourcePath, 'exports')
|
||||
|
||||
getUrl: (loadSettingsObj) ->
|
||||
# Ignore the windowState when passing loadSettings via URL, since it could
|
||||
# be quite large.
|
||||
@@ -121,13 +112,12 @@ class AtomWindow
|
||||
if @loaded
|
||||
@focus()
|
||||
@sendCommand('window:open-path', {pathToOpen, initialLine})
|
||||
@sendCommand('window:update-available', global.atomApplication.getUpdateVersion()) if global.atomApplication.getUpdateVersion()
|
||||
else
|
||||
@browserWindow.once 'window:loaded', => @openPath(pathToOpen, initialLine)
|
||||
|
||||
sendCommand: (command, args...) ->
|
||||
if @isSpecWindow()
|
||||
unless @sendCommandToFirstResponder(command)
|
||||
unless global.atomApplication.sendCommandToFirstResponder(command)
|
||||
switch command
|
||||
when 'window:reload' then @reload()
|
||||
when 'window:toggle-dev-tools' then @toggleDevTools()
|
||||
@@ -135,24 +125,13 @@ class AtomWindow
|
||||
else if @isWebViewFocused()
|
||||
@sendCommandToBrowserWindow(command, args...)
|
||||
else
|
||||
unless @sendCommandToFirstResponder(command)
|
||||
unless global.atomApplication.sendCommandToFirstResponder(command)
|
||||
@sendCommandToBrowserWindow(command, args...)
|
||||
|
||||
sendCommandToBrowserWindow: (command, args...) ->
|
||||
action = if args[0]?.contextCommand then 'context-command' else 'command'
|
||||
ipc.sendChannel @browserWindow.getProcessId(), @browserWindow.getRoutingId(), action, command, args...
|
||||
|
||||
sendCommandToFirstResponder: (command) ->
|
||||
switch command
|
||||
when 'core:undo' then Menu.sendActionToFirstResponder('undo:')
|
||||
when 'core:redo' then Menu.sendActionToFirstResponder('redo:')
|
||||
when 'core:copy' then Menu.sendActionToFirstResponder('copy:')
|
||||
when 'core:cut' then Menu.sendActionToFirstResponder('cut:')
|
||||
when 'core:paste' then Menu.sendActionToFirstResponder('paste:')
|
||||
when 'core:select-all' then Menu.sendActionToFirstResponder('selectAll:')
|
||||
else return false
|
||||
true
|
||||
|
||||
close: -> @browserWindow.close()
|
||||
|
||||
focus: -> @browserWindow.focus()
|
||||
|
||||
@@ -77,7 +77,7 @@ parseCommandLine = ->
|
||||
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
|
||||
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
|
||||
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
|
||||
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the directory from which specs are loaded (default: Atom\'s spec directory).')
|
||||
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the spec directory (default: Atom\'s spec directory).')
|
||||
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
|
||||
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
|
||||
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
|
||||
|
||||
@@ -146,7 +146,7 @@ class DisplayBufferMarker
|
||||
@bufferMarker.setAttributes(attributes)
|
||||
|
||||
matchesAttributes: (attributes) ->
|
||||
attributes = @displayBuffer.translateToBufferMarkerAttributes(attributes)
|
||||
attributes = @displayBuffer.translateToBufferMarkerParams(attributes)
|
||||
@bufferMarker.matchesAttributes(attributes)
|
||||
|
||||
# Destroys the marker
|
||||
|
||||
+34
-15
@@ -215,6 +215,13 @@ class DisplayBuffer extends Model
|
||||
largestFoldContainingBufferRow: (bufferRow) ->
|
||||
@foldsContainingBufferRow(bufferRow)[0]
|
||||
|
||||
# Returns the folds in the given row range (exclusive of end row) that are
|
||||
# not contained by any other folds.
|
||||
outermostFoldsInBufferRowRange: (startRow, endRow) ->
|
||||
@findFoldMarkers(containedInRange: [[startRow, 0], [endRow, 0]])
|
||||
.map (marker) => @foldForMarker(marker)
|
||||
.filter (fold) -> not fold.isInsideLargerFold()
|
||||
|
||||
# Public: Given a buffer row, this returns folds that include it.
|
||||
#
|
||||
#
|
||||
@@ -519,24 +526,34 @@ class DisplayBuffer extends Model
|
||||
# Refer to {DisplayBuffer::findMarkers} for details.
|
||||
#
|
||||
# Returns a {DisplayBufferMarker} or null
|
||||
findMarker: (attributes) ->
|
||||
@findMarkers(attributes)[0]
|
||||
findMarker: (params) ->
|
||||
@findMarkers(params)[0]
|
||||
|
||||
# Finds all valid markers satisfying the given attributes
|
||||
# Public: Find all markers satisfying a set of parameters.
|
||||
#
|
||||
# attributes - The attributes against which to compare the markers' attributes
|
||||
# There are some reserved keys that match against derived marker properties:
|
||||
# startBufferRow - The buffer row at which the marker starts
|
||||
# endBufferRow - The buffer row at which the marker ends
|
||||
# params - An {Object} containing parameters that all returned markers must
|
||||
# satisfy. Unreserved keys will be compared against the markers' custom
|
||||
# properties. There are also the following reserved keys with special
|
||||
# meaning for the query:
|
||||
# :startBufferRow - A {Number}. Only returns markers starting at this row in
|
||||
# buffer coordinates.
|
||||
# :endBufferRow - A {Number}. Only returns markers ending at this row in
|
||||
# buffer coordinates.
|
||||
# :containsBufferRange - A {Range} or range-compatible {Array}. Only returns
|
||||
# markers containing this range in buffer coordinates.
|
||||
# :containsBufferPosition - A {Point} or point-compatible {Array}. Only
|
||||
# returns markers containing this position in buffer coordinates.
|
||||
# :containedInBufferRange - A {Range} or range-compatible {Array}. Only
|
||||
# returns markers contained within this range.
|
||||
#
|
||||
# Returns an {Array} of {DisplayBufferMarker}s
|
||||
findMarkers: (attributes) ->
|
||||
attributes = @translateToBufferMarkerAttributes(attributes)
|
||||
@buffer.findMarkers(attributes).map (stringMarker) => @getMarker(stringMarker.id)
|
||||
findMarkers: (params) ->
|
||||
params = @translateToBufferMarkerParams(params)
|
||||
@buffer.findMarkers(params).map (stringMarker) => @getMarker(stringMarker.id)
|
||||
|
||||
translateToBufferMarkerAttributes: (attributes) ->
|
||||
stringMarkerAttributes = {}
|
||||
for key, value of attributes
|
||||
translateToBufferMarkerParams: (params) ->
|
||||
bufferMarkerParams = {}
|
||||
for key, value of params
|
||||
switch key
|
||||
when 'startBufferRow'
|
||||
key = 'startRow'
|
||||
@@ -546,8 +563,10 @@ class DisplayBuffer extends Model
|
||||
key = 'containsRange'
|
||||
when 'containsBufferPosition'
|
||||
key = 'containsPosition'
|
||||
stringMarkerAttributes[key] = value
|
||||
stringMarkerAttributes
|
||||
when 'containedInBufferRange'
|
||||
key = 'containedInRange'
|
||||
bufferMarkerParams[key] = value
|
||||
bufferMarkerParams
|
||||
|
||||
findFoldMarker: (attributes) ->
|
||||
@findFoldMarkers(attributes)[0]
|
||||
|
||||
+55
-13
@@ -20,7 +20,23 @@ LongLineLength = 1000
|
||||
# ## Requiring in packages
|
||||
#
|
||||
# ```coffee
|
||||
# {EditorView} = require 'atom'
|
||||
# {EditorView} = require 'atom'
|
||||
#
|
||||
# miniEditorView = new EditorView(mini: true)
|
||||
# ```
|
||||
#
|
||||
# ## Iterating over the open editor views
|
||||
#
|
||||
# ```coffee
|
||||
# for editorView in atom.workspace.getEditorViews()
|
||||
# console.log(editorView.getEditor().getPath())
|
||||
# ```
|
||||
#
|
||||
# ## Subscribing to every current and future editor
|
||||
#
|
||||
# ```coffee
|
||||
# atom.workspace.eachEditorView (editorView) ->
|
||||
# console.log(editorView.getEditor().getPath())
|
||||
# ```
|
||||
module.exports =
|
||||
class EditorView extends View
|
||||
@@ -209,7 +225,7 @@ class EditorView extends View
|
||||
'editor:copy-path': => @copyPathToClipboard()
|
||||
'editor:move-line-up': => @editor.moveLineUp()
|
||||
'editor:move-line-down': => @editor.moveLineDown()
|
||||
'editor:duplicate-line': => @editor.duplicateLine()
|
||||
'editor:duplicate-lines': => @editor.duplicateLines()
|
||||
'editor:join-lines': => @editor.joinLines()
|
||||
'editor:toggle-indent-guide': => atom.config.toggle('editor.showIndentGuide')
|
||||
'editor:toggle-line-numbers': => atom.config.toggle('editor.showLineNumbers')
|
||||
@@ -403,6 +419,8 @@ class EditorView extends View
|
||||
@scrollView.on 'overflowchanged', =>
|
||||
updateWidthInChars() if @[0].classList.contains('soft-wrap')
|
||||
|
||||
@subscribe atom.themes, 'stylesheets-changed', => @recalculateDimensions()
|
||||
|
||||
handleInputEvents: ->
|
||||
@on 'cursor:moved', =>
|
||||
return unless @isFocused
|
||||
@@ -445,20 +463,29 @@ class EditorView extends View
|
||||
|
||||
selectOnMousemoveUntilMouseup: ->
|
||||
lastMoveEvent = null
|
||||
|
||||
finalizeSelections = =>
|
||||
clearInterval(interval)
|
||||
$(document).off 'mousemove', moveHandler
|
||||
$(document).off 'mouseup', finalizeSelections
|
||||
|
||||
unless @editor.isDestroyed()
|
||||
@editor.mergeIntersectingSelections(isReversed: @editor.getLastSelection().isReversed())
|
||||
@editor.finalizeSelections()
|
||||
@syncCursorAnimations()
|
||||
|
||||
moveHandler = (event = lastMoveEvent) =>
|
||||
if event
|
||||
return unless event?
|
||||
|
||||
if event.which is 1 and @[0].style.display isnt 'none'
|
||||
@editor.selectToScreenPosition(@screenPositionFromMouseEvent(event))
|
||||
lastMoveEvent = event
|
||||
else
|
||||
finalizeSelections()
|
||||
|
||||
$(document).on "mousemove.editor-#{@id}", moveHandler
|
||||
interval = setInterval(moveHandler, 20)
|
||||
|
||||
$(document).one "mouseup.editor-#{@id}", =>
|
||||
clearInterval(interval)
|
||||
$(document).off 'mousemove', moveHandler
|
||||
@editor.mergeIntersectingSelections(isReversed: @editor.getLastSelection().isReversed())
|
||||
@editor.finalizeSelections()
|
||||
@syncCursorAnimations()
|
||||
$(document).one "mouseup.editor-#{@id}", finalizeSelections
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
return unless onDom
|
||||
@@ -667,11 +694,15 @@ class EditorView extends View
|
||||
@editor.setSoftWrap(not @editor.getSoftWrap())
|
||||
|
||||
calculateWidthInChars: ->
|
||||
Math.floor(@scrollView.width() / @charWidth)
|
||||
Math.floor((@scrollView.width() - @getScrollbarWidth()) / @charWidth)
|
||||
|
||||
calculateHeightInLines: ->
|
||||
Math.ceil($(window).height() / @lineHeight)
|
||||
|
||||
getScrollbarWidth: ->
|
||||
scrollbarElement = @verticalScrollbar[0]
|
||||
scrollbarElement.offsetWidth - scrollbarElement.clientWidth
|
||||
|
||||
# Public: Enables/disables soft wrap on the editor.
|
||||
#
|
||||
# softWrap - A {Boolean} which, if `true`, enables soft wrap
|
||||
@@ -853,6 +884,18 @@ class EditorView extends View
|
||||
fragment.remove()
|
||||
@setHeightInLines()
|
||||
|
||||
recalculateDimensions: ->
|
||||
return unless @attached
|
||||
|
||||
oldCharWidth = @charWidth
|
||||
oldLineHeight = @lineHeight
|
||||
|
||||
@calculateDimensions()
|
||||
|
||||
unless @charWidth is oldCharWidth and @lineHeight is oldLineHeight
|
||||
@clearCharacterWidthCache()
|
||||
@requestDisplayUpdate()
|
||||
|
||||
updateLayerDimensions: ->
|
||||
height = @lineHeight * @editor.getScreenLineCount()
|
||||
unless @layerHeight == height
|
||||
@@ -960,8 +1003,7 @@ class EditorView extends View
|
||||
(startRow <= @firstRenderedScreenRow and endRow >= @lastRenderedScreenRow) # selection surrounds the rendered items
|
||||
|
||||
syncCursorAnimations: ->
|
||||
for cursorView in @getCursorViews()
|
||||
do (cursorView) -> cursorView.resetBlinking()
|
||||
cursorView.resetBlinking() for cursorView in @getCursorViews()
|
||||
|
||||
autoscroll: (options={}) ->
|
||||
for cursorView in @getCursorViews()
|
||||
|
||||
+54
-28
@@ -373,10 +373,16 @@ class Editor extends Model
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row.
|
||||
# newLevel - A {Number} indicating the new indentation level.
|
||||
setIndentationForBufferRow: (bufferRow, newLevel) ->
|
||||
currentIndentLength = @lineForBufferRow(bufferRow).match(/^\s*/)[0].length
|
||||
# options - An {Object} with the following keys:
|
||||
# :preserveLeadingWhitespace - true to preserve any whitespace already at
|
||||
# the beginning of the line (default: false).
|
||||
setIndentationForBufferRow: (bufferRow, newLevel, {preserveLeadingWhitespace}={}) ->
|
||||
if preserveLeadingWhitespace
|
||||
endColumn = 0
|
||||
else
|
||||
endColumn = @lineForBufferRow(bufferRow).match(/^\s*/)[0].length
|
||||
newIndentString = @buildIndentString(newLevel)
|
||||
@buffer.change([[bufferRow, 0], [bufferRow, currentIndentLength]], newIndentString)
|
||||
@buffer.change([[bufferRow, 0], [bufferRow, endColumn]], newIndentString)
|
||||
|
||||
# Public: Get the indentation level of the given line of text.
|
||||
#
|
||||
@@ -400,17 +406,23 @@ class Editor extends Model
|
||||
# Constructs the string used for tabs.
|
||||
buildIndentString: (number) ->
|
||||
if @getSoftTabs()
|
||||
_.multiplyString(" ", number * @getTabLength())
|
||||
_.multiplyString(" ", Math.floor(number * @getTabLength()))
|
||||
else
|
||||
_.multiplyString("\t", Math.floor(number))
|
||||
|
||||
# {Delegates to: TextBuffer.save}
|
||||
# Public: Saves the editor's text buffer.
|
||||
#
|
||||
# See {TextBuffer::save} for more details.
|
||||
save: -> @buffer.save()
|
||||
|
||||
# {Delegates to: TextBuffer.saveAs}
|
||||
saveAs: (path) -> @buffer.saveAs(path)
|
||||
# Public: Saves the editor's text buffer as the given path.
|
||||
#
|
||||
# See {TextBuffer::saveAs} for more details.
|
||||
#
|
||||
# filePath - A {String} path.
|
||||
saveAs: (filePath) -> @buffer.saveAs(filePath)
|
||||
|
||||
# {Delegates to: TextBuffer.getPath}
|
||||
# Public: Returns the {String} path of this editor's text buffer.
|
||||
getPath: -> @buffer.getPath()
|
||||
|
||||
# Public: Returns a {String} representing the entire contents of the editor.
|
||||
@@ -679,7 +691,7 @@ class Editor extends Model
|
||||
# {Range}.
|
||||
normalizeTabsInBufferRange: (bufferRange) ->
|
||||
return unless @getSoftTabs()
|
||||
@scanInBufferRange /\t/, bufferRange, ({replace}) => replace(@getTabText())
|
||||
@scanInBufferRange /\t/g, bufferRange, ({replace}) => replace(@getTabText())
|
||||
|
||||
# Public: For each selection, if the selection is empty, cut all characters
|
||||
# of the containing line following the cursor. Otherwise cut the selected
|
||||
@@ -838,6 +850,10 @@ class Editor extends Model
|
||||
largestFoldStartingAtScreenRow: (screenRow) ->
|
||||
@displayBuffer.largestFoldStartingAtScreenRow(screenRow)
|
||||
|
||||
# {Delegates to: DisplayBuffer.outermostFoldsForBufferRowRange}
|
||||
outermostFoldsInBufferRowRange: (startRow, endRow) ->
|
||||
@displayBuffer.outermostFoldsInBufferRowRange(startRow, endRow)
|
||||
|
||||
# Move lines intersection the most recent selection up by one row in screen
|
||||
# coordinates.
|
||||
moveLineUp: ->
|
||||
@@ -948,28 +964,34 @@ class Editor extends Model
|
||||
@setSelectedBufferRange(selection.translate([insertDelta]), preserveFolds: true)
|
||||
|
||||
# Duplicate the most recent cursor's current line.
|
||||
duplicateLine: ->
|
||||
return unless @getSelection().isEmpty()
|
||||
|
||||
duplicateLines: ->
|
||||
@transact =>
|
||||
cursorPosition = @getCursorBufferPosition()
|
||||
cursorRowFolded = @isFoldedAtCursorRow()
|
||||
if cursorRowFolded
|
||||
screenRow = @screenPositionForBufferPosition(cursorPosition).row
|
||||
bufferRange = @bufferRangeForScreenRange([[screenRow], [screenRow + 1]])
|
||||
else
|
||||
bufferRange = new Range([cursorPosition.row], [cursorPosition.row + 1])
|
||||
for selection in @getSelectionsOrderedByBufferPosition().reverse()
|
||||
selectedBufferRange = selection.getBufferRange()
|
||||
if selection.isEmpty()
|
||||
{start} = selection.getScreenRange()
|
||||
selection.selectToScreenPosition([start.row + 1, 0])
|
||||
|
||||
insertPosition = new Point(bufferRange.end.row)
|
||||
if insertPosition.row > @buffer.getLastRow()
|
||||
@unfoldCurrentRow() if cursorRowFolded
|
||||
@buffer.append("\n#{@getTextInBufferRange(bufferRange)}")
|
||||
@foldCurrentRow() if cursorRowFolded
|
||||
else
|
||||
@buffer.insert(insertPosition, @getTextInBufferRange(bufferRange))
|
||||
[startRow, endRow] = selection.getBufferRowRange()
|
||||
endRow++
|
||||
|
||||
@setCursorScreenPosition(@getCursorScreenPosition().translate([1]))
|
||||
@foldCurrentRow() if cursorRowFolded
|
||||
foldedRowRanges =
|
||||
@outermostFoldsInBufferRowRange(startRow, endRow)
|
||||
.map (fold) -> fold.getBufferRowRange()
|
||||
|
||||
rangeToDuplicate = [[startRow, 0], [endRow, 0]]
|
||||
textToDuplicate = @getTextInBufferRange(rangeToDuplicate)
|
||||
textToDuplicate = '\n' + textToDuplicate if endRow > @getLastBufferRow()
|
||||
@buffer.insert([endRow, 0], textToDuplicate)
|
||||
|
||||
delta = endRow - startRow
|
||||
selection.setBufferRange(selectedBufferRange.translate([delta, 0]))
|
||||
for [foldStartRow, foldEndRow] in foldedRowRanges
|
||||
@createFold(foldStartRow + delta, foldEndRow + delta)
|
||||
|
||||
# Deprecated: Use {::duplicateLines} instead.
|
||||
duplicateLine: ->
|
||||
@duplicateLines()
|
||||
|
||||
mutateSelectedText: (fn) ->
|
||||
@transact => fn(selection) for selection in @getSelections()
|
||||
@@ -1733,3 +1755,7 @@ class Editor extends Model
|
||||
|
||||
getSelectionMarkerAttributes: ->
|
||||
type: 'selection', editorId: @id, invalidate: 'never'
|
||||
|
||||
# Deprecated: Call {::joinLines} instead.
|
||||
joinLine: ->
|
||||
@joinLines()
|
||||
|
||||
@@ -41,6 +41,10 @@ class Fold
|
||||
range.end.column = 0
|
||||
range
|
||||
|
||||
getBufferRowRange: ->
|
||||
{start, end} = @getBufferRange()
|
||||
[start.row, end.row]
|
||||
|
||||
# Returns the fold's start row as a {Number}.
|
||||
getStartRow: ->
|
||||
@getBufferRange().start.row
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
{specificity} = require 'clear-cut'
|
||||
|
||||
module.exports =
|
||||
class KeyBinding
|
||||
@parser: null
|
||||
@currentIndex: 1
|
||||
@specificities: null
|
||||
|
||||
@calculateSpecificity: (selector) ->
|
||||
@specificities ?= {}
|
||||
value = @specificities[selector]
|
||||
unless value?
|
||||
value = specificity(selector)
|
||||
@specificities[selector] = value
|
||||
value
|
||||
|
||||
@normalizeKeystroke: (keystroke) ->
|
||||
normalizedKeystroke = keystroke.split(/\s+/).map (keystroke) =>
|
||||
keys = @parseKeystroke(keystroke)
|
||||
modifiers = keys[0...-1]
|
||||
modifiers.sort()
|
||||
[modifiers..., _.last(keys)].join('-')
|
||||
normalizedKeystroke.join(' ')
|
||||
|
||||
@parseKeystroke: (keystroke) ->
|
||||
unless @parser?
|
||||
try
|
||||
@parser = require './keystroke-pattern'
|
||||
catch
|
||||
keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8')
|
||||
PEG = require 'pegjs'
|
||||
@parser = PEG.buildParser(keystrokePattern)
|
||||
|
||||
@parser.parse(keystroke)
|
||||
|
||||
constructor: (source, command, keystroke, selector) ->
|
||||
@source = source
|
||||
@command = command
|
||||
@keystroke = KeyBinding.normalizeKeystroke(keystroke)
|
||||
@selector = selector.replace(/!important/g, '')
|
||||
@specificity = KeyBinding.calculateSpecificity(selector)
|
||||
@index = KeyBinding.currentIndex++
|
||||
|
||||
matches: (keystroke) ->
|
||||
multiKeystroke = /\s/.test keystroke
|
||||
if multiKeystroke
|
||||
keystroke == @keystroke
|
||||
else
|
||||
keystroke.split(' ')[0] == @keystroke.split(' ')[0]
|
||||
|
||||
compare: (keyBinding) ->
|
||||
if keyBinding.specificity == @specificity
|
||||
keyBinding.index - @index
|
||||
else
|
||||
keyBinding.specificity - @specificity
|
||||
@@ -0,0 +1,27 @@
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
Keymap = require 'atom-keymap'
|
||||
CSON = require 'season'
|
||||
{jQuery} = require 'space-pen'
|
||||
|
||||
Keymap::loadBundledKeymaps = ->
|
||||
@loadKeyBindings(path.join(@resourcePath, 'keymaps'))
|
||||
@emit('bundled-keymaps-loaded')
|
||||
|
||||
Keymap::getUserKeymapPath = ->
|
||||
if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap'))
|
||||
userKeymapPath
|
||||
else
|
||||
path.join(@configDirPath, 'keymap.cson')
|
||||
|
||||
Keymap::loadUserKeymap = ->
|
||||
userKeymapPath = @getUserKeymapPath()
|
||||
if fs.isFileSync(userKeymapPath)
|
||||
@loadKeyBindings(userKeymapPath, watch: true, suppressErrors: true)
|
||||
|
||||
# This enables command handlers registered via jQuery to call
|
||||
# `.abortKeyBinding()` on the `jQuery.Event` object passed to the handler.
|
||||
jQuery.Event::abortKeyBinding = ->
|
||||
@originalEvent?.abortKeyBinding?()
|
||||
|
||||
module.exports = Keymap
|
||||
@@ -1,221 +0,0 @@
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
CSON = require 'season'
|
||||
KeyBinding = require './key-binding'
|
||||
{File} = require 'pathwatcher'
|
||||
{Emitter} = require 'emissary'
|
||||
|
||||
Modifiers = ['alt', 'control', 'ctrl', 'shift', 'cmd']
|
||||
|
||||
# Public: Associates keybindings with commands.
|
||||
#
|
||||
# An instance of this class is always available as the `atom.keymap` global.
|
||||
#
|
||||
# Keymaps are defined in a CSON/JSON format. A typical keymap looks something
|
||||
# like this:
|
||||
#
|
||||
# ```cson
|
||||
# 'body':
|
||||
# 'ctrl-l': 'package:do-something'
|
||||
# '.someClass':
|
||||
# 'enter': 'package:confirm'
|
||||
# ```
|
||||
#
|
||||
# As a key, you define the DOM element you want to work on, using CSS notation.
|
||||
# For that key, you define one or more key:value pairs, associating keystrokes
|
||||
# with a command to execute.
|
||||
module.exports =
|
||||
class Keymap
|
||||
Emitter.includeInto(this)
|
||||
|
||||
constructor: ({@resourcePath, @configDirPath})->
|
||||
@keyBindings = []
|
||||
|
||||
destroy: ->
|
||||
@unwatchUserKeymap()
|
||||
|
||||
# Public: Returns an array of all {KeyBinding}s.
|
||||
getKeyBindings: ->
|
||||
_.clone(@keyBindings)
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# that match a keystroke and element.
|
||||
#
|
||||
# keystroke - The {String} representing the keys pressed (e.g. ctrl-P).
|
||||
# element - The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsForKeystrokeMatchingElement: (keystroke, element) ->
|
||||
keyBindings = @keyBindingsForKeystroke(keystroke)
|
||||
@keyBindingsMatchingElement(element, keyBindings)
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# that match a command.
|
||||
#
|
||||
# command - The {String} representing the command (tree-view:toggle).
|
||||
# element - The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsForCommandMatchingElement: (command, element) ->
|
||||
keyBindings = @keyBindingsForCommand(command)
|
||||
@keyBindingsMatchingElement(element, keyBindings)
|
||||
|
||||
# Public: Returns an array of {KeyBinding}s that match a keystroke
|
||||
#
|
||||
# keystroke: The {String} representing the keys pressed (e.g. ctrl-P)
|
||||
keyBindingsForKeystroke: (keystroke) ->
|
||||
keystroke = KeyBinding.normalizeKeystroke(keystroke)
|
||||
@keyBindings.filter (keyBinding) -> keyBinding.matches(keystroke)
|
||||
|
||||
# Public: Returns an array of {KeyBinding}s that match a command
|
||||
#
|
||||
# keystroke - The {String} representing the keys pressed (e.g. ctrl-P)
|
||||
keyBindingsForCommand: (command) ->
|
||||
@keyBindings.filter (keyBinding) -> keyBinding.command == command
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# whos selector matches the element.
|
||||
#
|
||||
# element - The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsMatchingElement: (element, keyBindings=@keyBindings) ->
|
||||
keyBindings = keyBindings.filter ({selector}) -> $(element).closest(selector).length > 0
|
||||
keyBindings.sort (a, b) -> a.compare(b)
|
||||
|
||||
# Public: Returns a keystroke string derived from an event.
|
||||
#
|
||||
# event - A DOM or jQuery event.
|
||||
# previousKeystroke - An optional string used for multiKeystrokes.
|
||||
keystrokeStringForEvent: (event, previousKeystroke) ->
|
||||
if event.originalEvent.keyIdentifier.indexOf('U+') == 0
|
||||
hexCharCode = event.originalEvent.keyIdentifier[2..]
|
||||
charCode = parseInt(hexCharCode, 16)
|
||||
charCode = event.which if !@isAscii(charCode) and @isAscii(event.which)
|
||||
key = @keyFromCharCode(charCode)
|
||||
else
|
||||
key = event.originalEvent.keyIdentifier.toLowerCase()
|
||||
|
||||
modifiers = []
|
||||
if event.altKey and key not in Modifiers
|
||||
modifiers.push 'alt'
|
||||
if event.metaKey and key not in Modifiers
|
||||
modifiers.push 'cmd'
|
||||
if event.ctrlKey and key not in Modifiers
|
||||
modifiers.push 'ctrl'
|
||||
|
||||
if event.shiftKey and key not in Modifiers
|
||||
isNamedKey = key.length > 1
|
||||
modifiers.push 'shift' if isNamedKey
|
||||
else
|
||||
key = key.toLowerCase()
|
||||
|
||||
keystroke = [modifiers..., key].join('-')
|
||||
|
||||
if previousKeystroke
|
||||
if keystroke in Modifiers
|
||||
previousKeystroke
|
||||
else
|
||||
"#{previousKeystroke} #{keystroke}"
|
||||
else
|
||||
keystroke
|
||||
|
||||
loadBundledKeymaps: ->
|
||||
@loadDirectory(path.join(@resourcePath, 'keymaps'))
|
||||
@emit('bundled-keymaps-loaded')
|
||||
|
||||
getUserKeymapPath: ->
|
||||
if userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap'))
|
||||
userKeymapPath
|
||||
else
|
||||
path.join(@configDirPath, 'keymap.cson')
|
||||
|
||||
unwatchUserKeymap: ->
|
||||
@userKeymapFile?.off()
|
||||
@remove(@userKeymapPath) if @userKeymapPath?
|
||||
|
||||
loadUserKeymap: ->
|
||||
@unwatchUserKeymap()
|
||||
userKeymapPath = @getUserKeymapPath()
|
||||
if fs.isFileSync(userKeymapPath)
|
||||
@userKeymapPath = userKeymapPath
|
||||
@userKeymapFile = new File(userKeymapPath)
|
||||
@userKeymapFile.on 'contents-changed moved removed', => @loadUserKeymap()
|
||||
@add(@userKeymapPath, @readUserKeymap())
|
||||
|
||||
readUserKeymap: ->
|
||||
try
|
||||
CSON.readFileSync(@userKeymapPath) ? {}
|
||||
catch error
|
||||
console.warn("Failed to load your keymap file: #{@userKeymapPath}", error.stack ? error)
|
||||
{}
|
||||
|
||||
loadDirectory: (directoryPath) ->
|
||||
platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32']
|
||||
otherPlatforms = platforms.filter (name) -> name != process.platform
|
||||
|
||||
for filePath in fs.listSync(directoryPath, ['.cson', '.json'])
|
||||
continue if path.basename(filePath, path.extname(filePath)) in otherPlatforms
|
||||
@load(filePath)
|
||||
|
||||
load: (path) ->
|
||||
@add(path, CSON.readFileSync(path))
|
||||
|
||||
add: (source, keyMappingsBySelector) ->
|
||||
for selector, keyMappings of keyMappingsBySelector
|
||||
@bindKeys(source, selector, keyMappings)
|
||||
|
||||
remove: (source) ->
|
||||
@keyBindings = @keyBindings.filter (keyBinding) -> keyBinding.source isnt source
|
||||
|
||||
bindKeys: (source, selector, keyMappings) ->
|
||||
for keystroke, command of keyMappings
|
||||
keyBinding = new KeyBinding(source, command, keystroke, selector)
|
||||
try
|
||||
$(keyBinding.selector) # Verify selector is valid before registering
|
||||
@keyBindings.push(keyBinding)
|
||||
catch
|
||||
console.warn("Keybinding '#{keystroke}': '#{command}' in #{source} has an invalid selector: '#{selector}'")
|
||||
|
||||
handleKeyEvent: (event) ->
|
||||
element = event.target
|
||||
element = atom.workspaceView if element == document.body
|
||||
keystroke = @keystrokeStringForEvent(event, @queuedKeystroke)
|
||||
keyBindings = @keyBindingsForKeystrokeMatchingElement(keystroke, element)
|
||||
|
||||
if keyBindings.length == 0 and @queuedKeystroke
|
||||
@queuedKeystroke = null
|
||||
return false
|
||||
else
|
||||
@queuedKeystroke = null
|
||||
|
||||
for keyBinding in keyBindings
|
||||
partialMatch = keyBinding.keystroke isnt keystroke
|
||||
if partialMatch
|
||||
@queuedKeystroke = keystroke
|
||||
shouldBubble = false
|
||||
else
|
||||
if keyBinding.command is 'native!'
|
||||
shouldBubble = true
|
||||
else if @triggerCommandEvent(element, keyBinding.command, event)
|
||||
shouldBubble = false
|
||||
|
||||
break if shouldBubble?
|
||||
|
||||
shouldBubble ? true
|
||||
|
||||
triggerCommandEvent: (element, commandName, event) ->
|
||||
commandEvent = $.Event(commandName)
|
||||
commandEvent.originalEvent = event
|
||||
commandEvent.abortKeyBinding = -> commandEvent.stopImmediatePropagation()
|
||||
$(element).trigger(commandEvent)
|
||||
not commandEvent.isImmediatePropagationStopped()
|
||||
|
||||
isAscii: (charCode) ->
|
||||
0 <= charCode <= 127
|
||||
|
||||
keyFromCharCode: (charCode) ->
|
||||
switch charCode
|
||||
when 8 then 'backspace'
|
||||
when 9 then 'tab'
|
||||
when 13 then 'enter'
|
||||
when 27 then 'escape'
|
||||
when 32 then 'space'
|
||||
when 127 then 'delete'
|
||||
else String.fromCharCode(charCode)
|
||||
@@ -1,3 +0,0 @@
|
||||
keystrokePattern = key:key additionalKeys:additionalKey* { return [key].concat(additionalKeys); }
|
||||
additionalKey = '-' key:key { return key; }
|
||||
key = '-' / chars:[^-]+ { return chars.join('') }
|
||||
@@ -39,13 +39,13 @@ class LanguageMode
|
||||
return unless commentStartString
|
||||
|
||||
buffer = @editor.buffer
|
||||
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?')
|
||||
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '(?:$1)?')
|
||||
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
|
||||
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
|
||||
|
||||
if commentEndString
|
||||
if shouldUncomment
|
||||
commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '($1)?')
|
||||
commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '(?:$1)?')
|
||||
commentEndRegex = new OnigRegExp("(#{commentEndRegexString})(\\s*)$")
|
||||
startMatch = commentStartRegex.search(buffer.lineForRow(start))
|
||||
endMatch = commentEndRegex.search(buffer.lineForRow(end))
|
||||
@@ -265,10 +265,11 @@ class LanguageMode
|
||||
|
||||
# Given a buffer row, this indents it.
|
||||
#
|
||||
# bufferRow - The row {Number}
|
||||
autoIndentBufferRow: (bufferRow) ->
|
||||
# bufferRow - The row {Number}.
|
||||
# options - An options {Object} to pass through to {Editor::setIndentationForBufferRow}.
|
||||
autoIndentBufferRow: (bufferRow, options) ->
|
||||
indentLevel = @suggestedIndentForBufferRow(bufferRow)
|
||||
@editor.setIndentationForBufferRow(bufferRow, indentLevel)
|
||||
@editor.setIndentationForBufferRow(bufferRow, indentLevel, options)
|
||||
|
||||
# Given a buffer row, this decreases the indentation.
|
||||
#
|
||||
|
||||
@@ -41,7 +41,7 @@ class PackageManager
|
||||
|
||||
# Public: Get the path to the apm command
|
||||
getApmPath: ->
|
||||
@apmPath ?= require.resolve('atom-package-manager/bin/apm')
|
||||
@apmPath ?= path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm')
|
||||
|
||||
# Public: Get the paths being used to look for packages.
|
||||
#
|
||||
|
||||
+14
-2
@@ -69,7 +69,7 @@ class Package
|
||||
@loadStylesheets()
|
||||
@grammarsPromise = @loadGrammars()
|
||||
@scopedPropertiesPromise = @loadScopedProperties()
|
||||
@requireMainModule() unless @metadata.activationEvents?
|
||||
@requireMainModule() unless @hasActivationEvents()
|
||||
|
||||
catch error
|
||||
console.warn "Failed to load package named '#{@name}'", error.stack ? error
|
||||
@@ -87,7 +87,7 @@ class Package
|
||||
@activationDeferred = Q.defer()
|
||||
@measure 'activateTime', =>
|
||||
@activateResources()
|
||||
if @metadata.activationEvents?
|
||||
if @hasActivationEvents()
|
||||
@subscribeToActivationEvents()
|
||||
else
|
||||
@activateNow()
|
||||
@@ -262,6 +262,18 @@ class Package
|
||||
path.join(@path, 'index')
|
||||
@mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...])
|
||||
|
||||
hasActivationEvents: ->
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
return @metadata.activationEvents.some (activationEvent) ->
|
||||
activationEvent?.length > 0
|
||||
else if _.isString(@metadata.activationEvents)
|
||||
return @metadata.activationEvents.length > 0
|
||||
else if _.isObject(@metadata.activationEvents)
|
||||
for event, selector of @metadata.activationEvents
|
||||
return true if event.length > 0 and selector.length > 0
|
||||
|
||||
false
|
||||
|
||||
subscribeToActivationEvents: ->
|
||||
return unless @metadata.activationEvents?
|
||||
if _.isArray(@metadata.activationEvents)
|
||||
|
||||
@@ -75,7 +75,9 @@ class PaneView extends View
|
||||
@command 'pane:split-right', => @splitRight(@copyActiveItem())
|
||||
@command 'pane:split-up', => @splitUp(@copyActiveItem())
|
||||
@command 'pane:split-down', => @splitDown(@copyActiveItem())
|
||||
@command 'pane:close', => @model.destroy()
|
||||
@command 'pane:close', =>
|
||||
@model.destroyItems()
|
||||
@model.destroy()
|
||||
@command 'pane:close-other-items', => @destroyInactiveItems()
|
||||
|
||||
# Deprecated: Use ::destroyItem
|
||||
|
||||
+3
-5
@@ -1,5 +1,4 @@
|
||||
{find, compact, extend, last} = require 'underscore-plus'
|
||||
{dirname} = require 'path'
|
||||
{Model, Sequence} = require 'theorist'
|
||||
Serializable = require 'serializable'
|
||||
PaneAxis = require './pane-axis'
|
||||
@@ -265,10 +264,9 @@ class Pane extends Model
|
||||
return unless item?.saveAs?
|
||||
|
||||
itemPath = item.getPath?()
|
||||
itemPath = dirname(itemPath) if itemPath
|
||||
path = atom.showSaveDialogSync(itemPath)
|
||||
if path
|
||||
item.saveAs(path)
|
||||
newItemPath = atom.showSaveDialogSync(itemPath)
|
||||
if newItemPath
|
||||
item.saveAs(newItemPath)
|
||||
nextAction?()
|
||||
|
||||
# Public: Saves all items.
|
||||
|
||||
@@ -56,6 +56,11 @@ class SelectListView extends View
|
||||
@filterEditorView.hiddenInput.on 'focusout', =>
|
||||
@cancel() unless @cancelling
|
||||
|
||||
# This prevents the focusout event from firing on the filter editor view
|
||||
# when the list is scrolled by clicking the scrollbar and dragging.
|
||||
@list.on 'mousedown', ({target}) =>
|
||||
false if target is @list[0]
|
||||
|
||||
@on 'core:move-up', =>
|
||||
@selectPreviousItemView()
|
||||
@on 'core:move-down', =>
|
||||
@@ -148,8 +153,8 @@ class SelectListView extends View
|
||||
|
||||
for i in [0...Math.min(filteredItems.length, @maxItems)]
|
||||
item = filteredItems[i]
|
||||
itemView = @viewForItem(item)
|
||||
$(itemView).data('select-list-item', item)
|
||||
itemView = $(@viewForItem(item))
|
||||
itemView.data('select-list-item', item)
|
||||
@list.append(itemView)
|
||||
|
||||
@selectItemView(@list.find('li:first'))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{Range} = require 'text-buffer'
|
||||
{Point, Range} = require 'text-buffer'
|
||||
{Emitter} = require 'emissary'
|
||||
{pick} = require 'underscore-plus'
|
||||
|
||||
@@ -141,6 +141,8 @@ class Selection
|
||||
#
|
||||
# position - An instance of {Point}, with a given `row` and `column`.
|
||||
selectToScreenPosition: (position) ->
|
||||
position = Point.fromObject(position)
|
||||
|
||||
@modifySelection =>
|
||||
if @initialScreenRange
|
||||
if position.isLessThan(@initialScreenRange.start)
|
||||
@@ -299,7 +301,7 @@ class Selection
|
||||
if options.autoIndent
|
||||
@editor.autoIndentBufferRow(row) for row in newBufferRange.getRows()
|
||||
else if options.autoIndentNewline and text == '\n'
|
||||
@editor.autoIndentBufferRow(newBufferRange.end.row)
|
||||
@editor.autoIndentBufferRow(newBufferRange.end.row, preserveLeadingWhitespace: true)
|
||||
else if options.autoDecreaseIndent and /\S/.test text
|
||||
@editor.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
|
||||
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ class Task
|
||||
if _.isFunction(callback)
|
||||
@callback = callback
|
||||
else
|
||||
args = arguments
|
||||
args.push(callback)
|
||||
@send({event: 'start', args})
|
||||
|
||||
# Public: Send message to the task.
|
||||
|
||||
@@ -191,6 +191,7 @@ class ThemeManager
|
||||
removeStylesheet: (stylesheetPath) ->
|
||||
fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath
|
||||
@stylesheetElementForId(@stringToId(fullPath)).remove()
|
||||
@emit 'stylesheets-changed'
|
||||
|
||||
applyStylesheet: (path, text, ttype = 'bundled', htmlElement=$('html')) ->
|
||||
styleElement = @stylesheetElementForId(@stringToId(path), htmlElement)
|
||||
@@ -201,3 +202,4 @@ class ThemeManager
|
||||
htmlElement.find("head style.#{ttype}:last").after "<style class='#{ttype}' id='#{@stringToId(path)}'>#{text}</style>"
|
||||
else
|
||||
htmlElement.find("head").append "<style class='#{ttype}' id='#{@stringToId(path)}'>#{text}</style>"
|
||||
@emit 'stylesheets-changed'
|
||||
|
||||
@@ -20,7 +20,7 @@ class TokenizedBuffer extends Model
|
||||
visible: false
|
||||
|
||||
constructor: ({@buffer, @tabLength}) ->
|
||||
@tabLength ?= atom.config.get('editor.tabLength') ? 2
|
||||
@tabLength ?= atom.config.getPositiveInt('editor.tabLength', 2)
|
||||
|
||||
@subscribe atom.syntax, 'grammar-added grammar-updated', (grammar) =>
|
||||
if grammar.injectionSelector?
|
||||
@@ -40,7 +40,7 @@ class TokenizedBuffer extends Model
|
||||
@emit "changed", { start: 0, end: lastRow, delta: 0 }
|
||||
|
||||
@subscribe atom.config.observe 'editor.tabLength', callNow: false, =>
|
||||
@setTabLength(atom.config.getPositiveInt('editor.tabLength'))
|
||||
@setTabLength(atom.config.getPositiveInt('editor.tabLength', 2))
|
||||
|
||||
@reloadGrammar()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ class TokenizedLine
|
||||
@tokens = @breakOutAtomicTokens(tokens, tabLength)
|
||||
@startBufferColumn ?= 0
|
||||
@text = _.pluck(@tokens, 'value').join('')
|
||||
@bufferDelta = _.sum(_.pluck(@tokens, 'bufferDelta'))
|
||||
|
||||
copy: ->
|
||||
new TokenizedLine({@tokens, @lineEnding, @ruleStack, @startBufferColumn, @fold})
|
||||
@@ -55,7 +56,7 @@ class TokenizedLine
|
||||
@text.length
|
||||
|
||||
getMaxBufferColumn: ->
|
||||
@startBufferColumn + @getMaxScreenColumn()
|
||||
@startBufferColumn + @bufferDelta
|
||||
|
||||
softWrapAt: (column) ->
|
||||
return [new TokenizedLine([], '', [0, 0], [0, 0]), this] if column == 0
|
||||
@@ -78,7 +79,7 @@ class TokenizedLine
|
||||
)
|
||||
rightFragment = new TokenizedLine(
|
||||
tokens: rightTokens
|
||||
startBufferColumn: @startBufferColumn + column
|
||||
startBufferColumn: @bufferColumnForScreenColumn(column)
|
||||
ruleStack: @ruleStack
|
||||
lineEnding: @lineEnding
|
||||
)
|
||||
|
||||
+106
-49
@@ -3,6 +3,7 @@ path = require 'path'
|
||||
Q = require 'q'
|
||||
_ = require 'underscore-plus'
|
||||
Delegator = require 'delegato'
|
||||
scrollbarStyle = require 'scrollbar-style'
|
||||
{$, $$, View} = require './space-pen-extensions'
|
||||
fs = require 'fs-plus'
|
||||
Workspace = require './workspace'
|
||||
@@ -14,38 +15,42 @@ PaneRowView = require './pane-row-view'
|
||||
PaneContainerView = require './pane-container-view'
|
||||
Editor = require './editor'
|
||||
|
||||
# Public: The container for the entire Atom application.
|
||||
# Public: The top-level view for the entire window. An instance of this class is
|
||||
# available via the `atom.workspaceView` global.
|
||||
#
|
||||
# An instance of this class is always available as the `atom.workspaceView`
|
||||
# global.
|
||||
# It is backed by a model object, an instance of {Workspace}, which is available
|
||||
# via the `atom.workspace` global or {::getModel}. You should prefer to interact
|
||||
# with the model object when possible, but it won't always be possible with the
|
||||
# current API.
|
||||
#
|
||||
# ## Commands
|
||||
# ## Adding Perimiter Panels
|
||||
#
|
||||
# * `application:about` - Opens the about dialog.
|
||||
# * `application:show-settings` - Opens the preference pane in the currently
|
||||
# focused editor.
|
||||
# * `application:quit` - Quits the entire application.
|
||||
# * `application:hide` - Hides the entire application.
|
||||
# * `application:hide-other-applications` - Hides other applications
|
||||
# running on the system.
|
||||
# * `application:unhide-other-applications` - Shows other applications
|
||||
# that were previously hidden.
|
||||
# * `application:new-window` - Opens a new {AtomWindow} with no {Project}
|
||||
# path.
|
||||
# * `application:new-file` - Creates a new file within the focused window.
|
||||
# Note: only one new file may exist within an {AtomWindow} at a time.
|
||||
# * `application:open` - Prompts the user for a path to open in a new {AtomWindow}
|
||||
# * `application:minimize` - Minimizes the currently focused {AtomWindow}
|
||||
# * `application:zoom` - Expands the window to fill the screen or returns it to
|
||||
# it's original unzoomed size.
|
||||
# * `application:bring-all-windows-to-front` - Brings all {AtomWindow}s to the
|
||||
# the front.
|
||||
# Use the following methods if possible to attach panels to the perimiter of the
|
||||
# workspace rather than manipulating the DOM directly to better insulate you to
|
||||
# changes in the workspace markup:
|
||||
#
|
||||
# * {::prependToTop}
|
||||
# * {::appendToTop}
|
||||
# * {::prependToBottom}
|
||||
# * {::appendToBottom}
|
||||
# * {::prependToLeft}
|
||||
# * {::appendToLeft}
|
||||
# * {::prependToRight}
|
||||
# * {::appendToRight}
|
||||
#
|
||||
# ## Requiring in package specs
|
||||
#
|
||||
# If you need a `WorkspaceView` instance to test your package, require it via
|
||||
# the built-in `atom` module.
|
||||
#
|
||||
# ```coffee
|
||||
# {WorkspaceView} = require 'atom'
|
||||
# ```
|
||||
#
|
||||
# You can assign it to the `atom.workspaceView` global in the spec or just use
|
||||
# it as a local, depending on what you're trying to accomplish. Building the
|
||||
# `WorkspaceView` is currently expensive, so you should try build a {Workspace}
|
||||
# instead if possible.
|
||||
module.exports =
|
||||
class WorkspaceView extends View
|
||||
Delegator.includeInto(this)
|
||||
@@ -81,6 +86,14 @@ class WorkspaceView extends View
|
||||
|
||||
@subscribe @model, 'uri-opened', => @trigger 'uri-opened'
|
||||
|
||||
@subscribe scrollbarStyle, (style) =>
|
||||
@removeClass('scrollbars-visible-always scrollbars-visible-when-scrolling')
|
||||
switch style
|
||||
when 'legacy'
|
||||
@addClass("scrollbars-visible-always")
|
||||
when 'overlay'
|
||||
@addClass("scrollbars-visible-when-scrolling")
|
||||
|
||||
@updateTitle()
|
||||
|
||||
@on 'focus', (e) => @handleFocus(e)
|
||||
@@ -139,6 +152,12 @@ class WorkspaceView extends View
|
||||
@command 'core:save', => @saveActivePaneItem()
|
||||
@command 'core:save-as', => @saveActivePaneItemAs()
|
||||
|
||||
# Public: Get the underlying model object.
|
||||
#
|
||||
# Returns a {Workspace}.
|
||||
getModel: -> @model
|
||||
|
||||
# Public: Install the Atom shell commands on the user's system.
|
||||
installShellCommands: ->
|
||||
showErrorDialog = (error) ->
|
||||
installDirectory = CommandInstaller.getInstallDirectory()
|
||||
@@ -176,11 +195,11 @@ class WorkspaceView extends View
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if onDom
|
||||
|
||||
# Public: Shows a dialog asking if the pane was _really_ meant to be closed.
|
||||
# Prompts to save all unsaved items
|
||||
confirmClose: ->
|
||||
@panes.confirmClose()
|
||||
|
||||
# Public: Updates the application's title, based on whichever file is open.
|
||||
# Updates the application's title, based on whichever file is open.
|
||||
updateTitle: ->
|
||||
if projectPath = atom.project.getPath()
|
||||
if item = @getActivePaneItem()
|
||||
@@ -190,85 +209,119 @@ class WorkspaceView extends View
|
||||
else
|
||||
@setTitle('untitled')
|
||||
|
||||
# Public: Sets the application's title.
|
||||
# Sets the application's title.
|
||||
setTitle: (title) ->
|
||||
document.title = title
|
||||
|
||||
# Returns an Array of all of the application's {EditorView}s.
|
||||
# Get all editor views.
|
||||
#
|
||||
# You should prefer {Workspace::getEditors} unless you absolutely need access
|
||||
# to the view objects. Also consider using {::eachEditorView}, which will call
|
||||
# a callback for all current and *future* editor views.
|
||||
#
|
||||
# Returns an {Array} of {EditorView}s.
|
||||
getEditorViews: ->
|
||||
@panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray()
|
||||
|
||||
# Public: Prepends the element to the top of the window.
|
||||
# Public: Prepend an element or view to the panels at the top of the
|
||||
# workspace.
|
||||
prependToTop: (element) ->
|
||||
@vertical.prepend(element)
|
||||
|
||||
# Public: Appends the element to the top of the window.
|
||||
# Public: Append an element or view to the panels at the top of the workspace.
|
||||
appendToTop: (element) ->
|
||||
@panes.before(element)
|
||||
|
||||
# Public: Prepends the element to the bottom of the window.
|
||||
# Public: Prepend an element or view to the panels at the bottom of the
|
||||
# workspace.
|
||||
prependToBottom: (element) ->
|
||||
@panes.after(element)
|
||||
|
||||
# Public: Appends the element to bottom of the window.
|
||||
# Public: Append an element or view to the panels at the bottom of the
|
||||
# workspace.
|
||||
appendToBottom: (element) ->
|
||||
@vertical.append(element)
|
||||
|
||||
# Public: Prepends the element to the left side of the window.
|
||||
# Public: Prepend an element or view to the panels at the left of the
|
||||
# workspace.
|
||||
prependToLeft: (element) ->
|
||||
@horizontal.prepend(element)
|
||||
|
||||
# Public: Appends the element to the left side of the window.
|
||||
# Public: Append an element or view to the panels at the left of the
|
||||
# workspace.
|
||||
appendToLeft: (element) ->
|
||||
@vertical.before(element)
|
||||
|
||||
# Public: Prepends the element to the right side of the window.
|
||||
# Public: Prepend an element or view to the panels at the right of the
|
||||
# workspace.
|
||||
prependToRight: (element) ->
|
||||
@vertical.after(element)
|
||||
|
||||
# Public: Appends the element to the right side of the window.
|
||||
# Public: Append an element or view to the panels at the right of the
|
||||
# workspace.
|
||||
appendToRight: (element) ->
|
||||
@horizontal.append(element)
|
||||
|
||||
# Public: Returns the currently focused {PaneView}.
|
||||
# Public: Get the active pane view.
|
||||
#
|
||||
# Prefer {Workspace::getActivePane} if you don't actually need access to the
|
||||
# view.
|
||||
#
|
||||
# Returns a {PaneView}.
|
||||
getActivePaneView: ->
|
||||
@panes.getActivePane()
|
||||
|
||||
# Public: Returns the currently focused item from within the focused {PaneView}
|
||||
getActivePaneItem: ->
|
||||
@model.activePaneItem
|
||||
|
||||
# Public: Returns the view of the currently focused item.
|
||||
# Public: Get the view associated with the active pane item.
|
||||
#
|
||||
# Returns a view.
|
||||
getActiveView: ->
|
||||
@panes.getActiveView()
|
||||
|
||||
# Public: Focuses the previous pane by id.
|
||||
# Focus the previous pane by id.
|
||||
focusPreviousPaneView: -> @model.activatePreviousPane()
|
||||
|
||||
# Public: Focuses the next pane by id.
|
||||
# Focus the next pane by id.
|
||||
focusNextPaneView: -> @model.activateNextPane()
|
||||
|
||||
# Public: Focuses the pane directly above the active pane.
|
||||
# Public: Focus the pane directly above the active pane.
|
||||
focusPaneViewAbove: -> @panes.focusPaneViewAbove()
|
||||
|
||||
# Public: Focuses the pane directly below the active pane.
|
||||
# Public: Focus the pane directly below the active pane.
|
||||
focusPaneViewBelow: -> @panes.focusPaneViewBelow()
|
||||
|
||||
# Public: Focuses the pane directly to the left of the active pane.
|
||||
# Public: Focus the pane directly to the left of the active pane.
|
||||
focusPaneViewOnLeft: -> @panes.focusPaneViewOnLeft()
|
||||
|
||||
# Public: Focuses the pane directly to the right of the active pane.
|
||||
# Public: Focus the pane directly to the right of the active pane.
|
||||
focusPaneViewOnRight: -> @panes.focusPaneViewOnRight()
|
||||
|
||||
# Public: Fires a callback on each open {PaneView}.
|
||||
# Public: Register a function to be called for every current and future
|
||||
# pane view in the workspace.
|
||||
#
|
||||
# callback - A {Function} with a {PaneView} as its only argument.
|
||||
#
|
||||
# Returns a subscription object with an `.off` method that you can call to
|
||||
# unregister the callback.
|
||||
eachPaneView: (callback) ->
|
||||
@panes.eachPaneView(callback)
|
||||
|
||||
# Public: Get all existing pane views.
|
||||
#
|
||||
# Prefer {Workspace::getPanes} if you don't need access to the view objects.
|
||||
# Also consider using {::eachPaneView} if you want to register a callback for
|
||||
# all current and *future* pane views.
|
||||
#
|
||||
# Returns an Array of all open {PaneView}s.
|
||||
getPaneViews: ->
|
||||
@panes.getPanes()
|
||||
|
||||
# Public: Fires a callback on each open {EditorView}.
|
||||
# Public: Register a function to be called for every current and future
|
||||
# editor view in the workspace.
|
||||
#
|
||||
# callback - A {Function} with an {EditorView} as its only argument.
|
||||
#
|
||||
# Returns a subscription object with an `.off` method that you can call to
|
||||
# unregister the callback.
|
||||
eachEditorView: (callback) ->
|
||||
callback(editor) for editor in @getEditorViews()
|
||||
attachedCallback = (e, editor) -> callback(editor)
|
||||
@@ -290,3 +343,7 @@ class WorkspaceView extends View
|
||||
# Deprecated
|
||||
getActivePane: ->
|
||||
@getActivePaneView()
|
||||
|
||||
# Deprecated: Call {Workspace::getActivePaneItem} instead.
|
||||
getActivePaneItem: ->
|
||||
@model.activePaneItem
|
||||
|
||||
+90
-31
@@ -7,18 +7,18 @@ Delegator = require 'delegato'
|
||||
PaneContainer = require './pane-container'
|
||||
Pane = require './pane'
|
||||
|
||||
# Public: Represents the view state of the entire window, including the panes at
|
||||
# the center and panels around the periphery.
|
||||
# Public: Represents the state of the user interface for the entire window.
|
||||
# An instance of this class is available via the `atom.workspace` global.
|
||||
#
|
||||
# An instance of this class is always available as the `atom.workspace` global.
|
||||
# Interact with this object to open files, be notified of current and future
|
||||
# editors, and manipulate panes. To add panels, you'll need to use the
|
||||
# {WorkspaceView} class for now until we establish APIs at the model layer.
|
||||
module.exports =
|
||||
class Workspace extends Model
|
||||
atom.deserializers.add(this)
|
||||
Serializable.includeInto(this)
|
||||
|
||||
@delegatesProperty 'activePane', 'activePaneItem', toProperty: 'paneContainer'
|
||||
@delegatesMethod 'getPanes', 'saveAll', 'activateNextPane', 'activatePreviousPane',
|
||||
toProperty: 'paneContainer'
|
||||
|
||||
@properties
|
||||
paneContainer: -> new PaneContainer
|
||||
@@ -49,28 +49,38 @@ class Workspace extends Model
|
||||
paneContainer: @paneContainer.serialize()
|
||||
fullScreen: atom.isFullScreen()
|
||||
|
||||
# Public: Calls callback for every existing {Editor} and for all new {Editor}s.
|
||||
# that are created.
|
||||
# Public: Register a function to be called for every current and future
|
||||
# {Editor} in the workspace.
|
||||
#
|
||||
# callback - A {Function} with an {Editor} as its only argument
|
||||
# callback - A {Function} with an {Editor} as its only argument.
|
||||
#
|
||||
# Returns a subscription object with an `.off` method that you can call to
|
||||
# unregister the callback.
|
||||
eachEditor: (callback) ->
|
||||
atom.project.eachEditor(callback)
|
||||
|
||||
# Public: Returns an {Array} of all open {Editor}s.
|
||||
# Public: Get all current editors in the workspace.
|
||||
#
|
||||
# Returns an {Array} of {Editor}s.
|
||||
getEditors: ->
|
||||
atom.project.getEditors()
|
||||
|
||||
# Public: Asynchronously opens a given a filepath in Atom.
|
||||
# Public: Open a given a URI in Atom asynchronously.
|
||||
#
|
||||
# uri - A {String} uri.
|
||||
# options - An options {Object} (default: {}).
|
||||
# :initialLine - A {Number} indicating which line number to open to.
|
||||
# :split - A {String} ('left' or 'right') that opens the filePath in a new
|
||||
# pane or an existing one if it exists.
|
||||
# :changeFocus - A {Boolean} that allows the filePath to be opened without
|
||||
# changing focus.
|
||||
# :searchAllPanes - A {Boolean} that will open existing editors from any pane
|
||||
# if the uri is already open (default: false)
|
||||
# uri - A {String} containing a URI.
|
||||
# options - An optional options {Object}
|
||||
# :initialLine - A {Number} indicating which row to move the cursor to
|
||||
# initially. Defaults to `0`.
|
||||
# :split - Either 'left' or 'right'. If 'left', the item will be opened in
|
||||
# leftmost pane of the current active pane's row. If 'right', the
|
||||
# item will be opened in the rightmost pane of the current active
|
||||
# pane's row.
|
||||
# :activatePane - A {Boolean} indicating whether to call {Pane::activate} on
|
||||
# the containing pane. Defaults to `true`.
|
||||
# :searchAllPanes - A {Boolean}. If `true`, the workspace will attempt to
|
||||
# activate an existing item for the given URI on any pane.
|
||||
# If `false`, only the active pane will be searched for
|
||||
# an existing item for the same URI. Defaults to `false`.
|
||||
#
|
||||
# Returns a promise that resolves to the {Editor} for the file URI.
|
||||
open: (uri, options={}) ->
|
||||
@@ -89,10 +99,20 @@ class Workspace extends Model
|
||||
|
||||
@openUriInPane(uri, pane, options)
|
||||
|
||||
# Public: Open Atom's license in the active pane.
|
||||
openLicense: ->
|
||||
@open(join(atom.getLoadSettings().resourcePath, 'LICENSE'))
|
||||
|
||||
# Only used in specs
|
||||
# Synchronously open the given URI in the active pane. **Only use this method
|
||||
# in specs. Calling this in production code will block the UI thread and
|
||||
# everyone will be mad at you.**
|
||||
#
|
||||
# uri - A {String} containing a URI.
|
||||
# options - An optional options {Object}
|
||||
# :initialLine - A {Number} indicating which row to move the cursor to
|
||||
# initially. Defaults to `0`.
|
||||
# :activatePane - A {Boolean} indicating whether to call {Pane::activate} on
|
||||
# the containing pane. Defaults to `true`.
|
||||
openSync: (uri='', options={}) ->
|
||||
{initialLine} = options
|
||||
# TODO: Remove deprecated changeFocus option
|
||||
@@ -130,7 +150,8 @@ class Workspace extends Model
|
||||
.catch (error) ->
|
||||
console.error(error.stack ? error)
|
||||
|
||||
# Public: Reopens the last-closed item uri if it hasn't already been reopened.
|
||||
# Public: Reopen the last-closed item's URI if it hasn't already been
|
||||
# reopened.
|
||||
reopenItemSync: ->
|
||||
if uri = @destroyedItemUris.pop()
|
||||
@openSync(uri)
|
||||
@@ -150,50 +171,88 @@ class Workspace extends Model
|
||||
registerOpener: (opener) ->
|
||||
atom.project.registerOpener(opener)
|
||||
|
||||
# Public: Remove a registered opener.
|
||||
# Public: Unregister an opener registered with {::registerOpener}.
|
||||
unregisterOpener: (opener) ->
|
||||
atom.project.unregisterOpener(opener)
|
||||
|
||||
getOpeners: ->
|
||||
atom.project.openers
|
||||
|
||||
# Public: Returns the active {Pane}.
|
||||
# Public: Get the active {Pane}.
|
||||
#
|
||||
# Returns a {Pane}.
|
||||
getActivePane: ->
|
||||
@paneContainer.activePane
|
||||
|
||||
# Public: Returns the first pane {Pane} with an item for the given uri or
|
||||
# undefined if none exists.
|
||||
# Public: Get all {Pane}s.
|
||||
#
|
||||
# Returns an {Array} of {Pane}s.
|
||||
getPanes: ->
|
||||
@paneContainer.getPanes()
|
||||
|
||||
# Public: Save all pane items.
|
||||
saveAll: ->
|
||||
@paneContainer.saveAll()
|
||||
|
||||
# Public: Make the next pane active.
|
||||
activateNextPane: ->
|
||||
@paneContainer.activateNextPane()
|
||||
|
||||
# Public: Make the previous pane active.
|
||||
activatePreviousPane: ->
|
||||
@paneContainer.activatePreviousPane()
|
||||
|
||||
# Public: Get the first pane {Pane} with an item for the given URI.
|
||||
#
|
||||
# Returns a {Pane} or `undefined` if no pane exists for the given URI.
|
||||
paneForUri: (uri) ->
|
||||
@paneContainer.paneForUri(uri)
|
||||
|
||||
# Public: save the active item.
|
||||
# Public: Save the active pane item.
|
||||
#
|
||||
# If the active pane item currently has a URI according to the item's
|
||||
# `.getUri` method, calls `.save` on the item. Otherwise
|
||||
# {::saveActivePaneItemAs} # will be called instead. This method does nothing
|
||||
# if the active item does not implement a `.save` method.
|
||||
saveActivePaneItem: ->
|
||||
@activePane?.saveActiveItem()
|
||||
|
||||
# Public: save the active item as.
|
||||
# Public: Prompt the user for a path and save the active pane item to it.
|
||||
#
|
||||
# Opens a native dialog where the user selects a path on disk, then calls
|
||||
# `.saveAs` on the item with the selected path. This method does nothing if
|
||||
# the active item does not implement a `.saveAs` method.
|
||||
saveActivePaneItemAs: ->
|
||||
@activePane?.saveActiveItemAs()
|
||||
|
||||
# Public: destroy/close the active item.
|
||||
# Public: Destroy (close) the active pane item.
|
||||
#
|
||||
# Removes the active pane item and calls the `.destroy` method on it if one is
|
||||
# defined.
|
||||
destroyActivePaneItem: ->
|
||||
@activePane?.destroyActiveItem()
|
||||
|
||||
# Public: destroy/close the active pane.
|
||||
# Public: Destroy (close) the active pane.
|
||||
destroyActivePane: ->
|
||||
@activePane?.destroy()
|
||||
|
||||
# Public: Returns an {Editor} if the active pane item is an {Editor},
|
||||
# or null otherwise.
|
||||
# Public: Get the active item if it is an {Editor}.
|
||||
#
|
||||
# Returns an {Editor} or `undefined` if the current active item is not an
|
||||
# {Editor}.
|
||||
getActiveEditor: ->
|
||||
@activePane?.getActiveEditor()
|
||||
|
||||
# Public: Increase the editor font size by 1px.
|
||||
increaseFontSize: ->
|
||||
atom.config.set("editor.fontSize", atom.config.get("editor.fontSize") + 1)
|
||||
|
||||
# Public: Decrease the editor font size by 1px.
|
||||
decreaseFontSize: ->
|
||||
fontSize = atom.config.get("editor.fontSize")
|
||||
atom.config.set("editor.fontSize", fontSize - 1) if fontSize > 1
|
||||
|
||||
# Public: Restore to a default editor font size.
|
||||
resetFontSize: ->
|
||||
atom.config.restoreDefault("editor.fontSize")
|
||||
|
||||
|
||||
+2
-32
@@ -3,39 +3,9 @@
|
||||
<head>
|
||||
<title></title>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
var path = require('path');
|
||||
var ipc = require('ipc');
|
||||
try {
|
||||
// Skip "?loadSettings=".
|
||||
var loadSettings = JSON.parse(decodeURIComponent(location.search.substr(14)));
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src *; script-src 'self'; style-src 'self' 'unsafe-inline';">
|
||||
|
||||
// Start the crash reporter before anything else.
|
||||
require('crash-reporter').start({
|
||||
productName: 'Atom',
|
||||
companyName: 'GitHub',
|
||||
// By explicitly passing the app version here, we could save the call
|
||||
// of "require('remote').require('app').getVersion()".
|
||||
extra: {_version: loadSettings.appVersion}
|
||||
});
|
||||
|
||||
require('vm-compatibility-layer');
|
||||
require('coffee-script').register();
|
||||
require(path.resolve(__dirname, '..', 'src', 'coffee-cache')).register();
|
||||
require(loadSettings.bootstrapScript);
|
||||
ipc.sendChannel('window-command', 'window:loaded')
|
||||
}
|
||||
catch (error) {
|
||||
var currentWindow = require('remote').getCurrentWindow();
|
||||
currentWindow.setSize(800, 600);
|
||||
currentWindow.center();
|
||||
currentWindow.show();
|
||||
currentWindow.openDevTools();
|
||||
console.error(error.stack || error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body tabindex="-1">
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
window.onload = function() {
|
||||
var path = require('path');
|
||||
var ipc = require('ipc');
|
||||
try {
|
||||
// Skip "?loadSettings=".
|
||||
var loadSettings = JSON.parse(decodeURIComponent(location.search.substr(14)));
|
||||
|
||||
// Start the crash reporter before anything else.
|
||||
require('crash-reporter').start({
|
||||
productName: 'Atom',
|
||||
companyName: 'GitHub',
|
||||
// By explicitly passing the app version here, we could save the call
|
||||
// of "require('remote').require('app').getVersion()".
|
||||
extra: {_version: loadSettings.appVersion}
|
||||
});
|
||||
|
||||
require('vm-compatibility-layer');
|
||||
require('coffee-script').register();
|
||||
require(path.resolve(__dirname, '..', 'src', 'coffee-cache')).register();
|
||||
require(loadSettings.bootstrapScript);
|
||||
ipc.sendChannel('window-command', 'window:loaded')
|
||||
}
|
||||
catch (error) {
|
||||
var currentWindow = require('remote').getCurrentWindow();
|
||||
currentWindow.setSize(800, 600);
|
||||
currentWindow.center();
|
||||
currentWindow.show();
|
||||
currentWindow.openDevTools();
|
||||
console.error(error.stack || error);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,29 @@
|
||||
// This file has fallback variables. It specifies the syntax variables that
|
||||
// themes must implement.
|
||||
// This file has fallback variables. It specifies all syntax variables that
|
||||
// themes must implement if they include a syntax-variables.less file.
|
||||
|
||||
// Colors
|
||||
// General colors
|
||||
@syntax-text-color: #333;
|
||||
@syntax-cursor-color: #333;
|
||||
@syntax-selection-color: #69c;
|
||||
@syntax-background-color: #fff;
|
||||
|
||||
@syntax-color-added: #5293d8;
|
||||
@syntax-color-modified: #f78a46;
|
||||
@syntax-color-removed: #c00;
|
||||
// Guide colors
|
||||
@syntax-wrap-guide-color: #ccc;
|
||||
@syntax-indent-guide-color: #ccc;
|
||||
@syntax-invisible-character-color: #ccc;
|
||||
|
||||
// For find and replace markers
|
||||
@syntax-result-marker-color: #444;
|
||||
@syntax-result-marker-color-selected: #000;
|
||||
|
||||
// Gutter colors
|
||||
@syntax-gutter-text-color: #333;
|
||||
@syntax-gutter-text-color-selected: #000;
|
||||
@syntax-gutter-background-color: #ccc;
|
||||
@syntax-gutter-background-color-selected: #eee;
|
||||
|
||||
// For git diff info. i.e. in the gutter
|
||||
@syntax-color-added: green;
|
||||
@syntax-color-modified: orange;
|
||||
@syntax-color-removed: red;
|
||||
@syntax-color-renamed: blue;
|
||||
|
||||
externo
+1
-1
Submodule vendor/apm updated: 90cd546860...b85d052154
Referência em uma Nova Issue
Bloquear um usuário