mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
Merge branch 'dev' into editor-stats
This commit is contained in:
8
.atom/user.css
Normal file
8
.atom/user.css
Normal file
@@ -0,0 +1,8 @@
|
||||
// User styles
|
||||
.tree-view {
|
||||
|
||||
}
|
||||
|
||||
.editor {
|
||||
|
||||
}
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -43,3 +43,6 @@
|
||||
[submodule "vendor/packages/property-list.tmbundle"]
|
||||
path = vendor/packages/property-list.tmbundle
|
||||
url = https://github.com/textmate/property-list.tmbundle.git
|
||||
[submodule "vendor/packages/python.tmbundle"]
|
||||
path = vendor/packages/python.tmbundle
|
||||
url = https://github.com/textmate/python.tmbundle
|
||||
|
||||
20
CONTRIBUTING.md
Normal file
20
CONTRIBUTING.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# :rotating_light: Contributing to Atom :rotating_light:
|
||||
|
||||
## Issues
|
||||
* Include screenshots and animated GIFs whenever possible, they are immensely
|
||||
helpful
|
||||
* Include the behavior you expected to happen and other places you've seen
|
||||
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
|
||||
|
||||
## Code
|
||||
* Follow the [JavaScript](https://github.com/styleguide/javascript),
|
||||
[CSS](https://github.com/styleguide/css),
|
||||
and [Objective-C](https://github.com/github/objective-c-conventions)
|
||||
styleguides
|
||||
* Include thoughtfully worded [Jasmine](http://pivotal.github.com/jasmine/)
|
||||
specs
|
||||
* New packages go in `src/packages/`
|
||||
* Add 3rd-party packages by submoduling in `vendor/packages/`
|
||||
* Commit messages are in the present tense
|
||||
@@ -21,7 +21,7 @@ Requirements
|
||||
Atom is installed! Type `atom [path]` from the commmand line or find it in `/Applications/Atom.app`
|
||||
|
||||
## Your ~/.atom Directory
|
||||
A basic ~/.atom directory is installed when you run `rake install`. Take a look at ~/.atom/atom.coffee for more information.
|
||||
A basic ~/.atom directory is installed when you run `rake install`. Take a look at ~/.atom/user.coffee for more information.
|
||||
|
||||
## Basic Keyboard shortcuts
|
||||
Atom doesn't have much in the way of menus yet. Use these keyboard shortcuts to
|
||||
@@ -53,7 +53,7 @@ Most default OS X keybindings also work.
|
||||
|
||||
## Init Script
|
||||
|
||||
Atom will require `~/.atom/atom.coffee` whenever a window is opened or reloaded if it is present in your
|
||||
Atom will require `~/.atom/user.coffee` whenever a window is opened or reloaded if it is present in your
|
||||
home directory. This is a rudimentary jumping off point for your own customizations.
|
||||
|
||||
## Command Panel
|
||||
|
||||
19
Rakefile
19
Rakefile
@@ -76,12 +76,25 @@ task "create-dot-atom" do
|
||||
|
||||
dot_atom_template_path = ATOM_SRC_PATH + "/.atom"
|
||||
replace_dot_atom = false
|
||||
next if File.exists?(DOT_ATOM_PATH)
|
||||
|
||||
if File.exists?(DOT_ATOM_PATH)
|
||||
user_config = "#{DOT_ATOM_PATH}/user.coffee"
|
||||
old_user_config = "#{DOT_ATOM_PATH}/atom.coffee"
|
||||
|
||||
if File.exists?(old_user_config)
|
||||
`mv #{old_user_config} #{user_config}`
|
||||
puts "\033[32mRenamed #{old_user_config} to #{user_config}\033[0m"
|
||||
end
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
`rm -rf "#{DOT_ATOM_PATH}"`
|
||||
`mkdir "#{DOT_ATOM_PATH}"`
|
||||
`cp "#{dot_atom_template_path}/atom.coffee" "#{DOT_ATOM_PATH}"`
|
||||
`cp "#{dot_atom_template_path}/packages" "#{DOT_ATOM_PATH}"`
|
||||
|
||||
`cp "#{dot_atom_template_path}/user.coffee" "#{DOT_ATOM_PATH}"`
|
||||
`cp "#{dot_atom_template_path}/user.css" "#{DOT_ATOM_PATH}"`
|
||||
`cp -r "#{dot_atom_template_path}/packages" "#{DOT_ATOM_PATH}"`
|
||||
`cp -r "#{ATOM_SRC_PATH}/themes" "#{DOT_ATOM_PATH}"`
|
||||
`cp "#{ATOM_SRC_PATH}/vendor/themes/IR_Black.tmTheme" "#{DOT_ATOM_PATH}/themes"`
|
||||
end
|
||||
|
||||
@@ -55,8 +55,8 @@ Or you can use `observeConfig` to track changes from a view object.
|
||||
```coffeescript
|
||||
class MyView extends View
|
||||
initialize: ->
|
||||
@observeConfig 'editor.lineHeight', (lineHeight) =>
|
||||
@adjustLineHeight(lineHeight)
|
||||
@observeConfig 'editor.fontSize', () =>
|
||||
@adjustFontSize()
|
||||
```
|
||||
|
||||
The `observeConfig` method will call the given callback immediately with the
|
||||
|
||||
@@ -18,9 +18,9 @@ my-package/
|
||||
index.coffee
|
||||
```
|
||||
|
||||
**NOTE: NPM behavior is partially implemented until we get a working Node.js
|
||||
**NOTE:** NPM behavior is partially implemented until we get a working Node.js
|
||||
API built into Atom. The goal is to make Atom packages be a superset of NPM
|
||||
packages**
|
||||
packages
|
||||
|
||||
#### package.json
|
||||
|
||||
|
||||
@@ -141,6 +141,8 @@ bool AtomCefClient::OnKeyEvent(CefRefPtr<CefBrowser> browser,
|
||||
ToggleDevTools(browser);
|
||||
} else if (event.modifiers == EVENTFLAG_COMMAND_DOWN && event.unmodified_character == '`') {
|
||||
FocusNextWindow();
|
||||
} else if (event.modifiers == (EVENTFLAG_COMMAND_DOWN | EVENTFLAG_SHIFT_DOWN) && event.unmodified_character == '~') {
|
||||
FocusPreviousWindow();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
||||
@@ -105,6 +105,7 @@ class AtomCefClient : public CefClient,
|
||||
bool m_HandlePasteboardCommands = false;
|
||||
|
||||
void FocusNextWindow();
|
||||
void FocusPreviousWindow();
|
||||
void Open(std::string path);
|
||||
void Open();
|
||||
void OpenUnstable(std::string path);
|
||||
|
||||
@@ -23,6 +23,24 @@ void AtomCefClient::FocusNextWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
void AtomCefClient::FocusPreviousWindow() {
|
||||
NSArray *windows = [NSApp windows];
|
||||
int count = [windows count];
|
||||
int start = [windows indexOfObject:[NSApp keyWindow]];
|
||||
|
||||
int i = start;
|
||||
while (true) {
|
||||
i = i - 1;
|
||||
if (i == 0) i = count -1;
|
||||
if (i == start) break;
|
||||
NSWindow *window = [windows objectAtIndex:i];
|
||||
if ([window isVisible] && ![window isExcludedFromWindowsMenu]) {
|
||||
[window makeKeyAndOrderFront:nil];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AtomCefClient::Open(std::string path) {
|
||||
NSString *pathString = [NSString stringWithCString:path.c_str() encoding:NSUTF8StringEncoding];
|
||||
[(AtomApplication *)[AtomApplication sharedApplication] open:pathString];
|
||||
|
||||
17
script/fix-author
Executable file
17
script/fix-author
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
usage() {
|
||||
echo "usage: $0 sha name email"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ ! $3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
git filter-branch -f --env-filter "
|
||||
export GIT_AUTHOR_NAME='$2'
|
||||
export GIT_AUTHOR_EMAIL='$3'
|
||||
export GIT_COMMITTER_NAME='$2'
|
||||
export GIT_COMMITTER_EMAIL='$3'
|
||||
" -- $1..HEAD
|
||||
@@ -26,17 +26,20 @@ describe "the `atom` global", ->
|
||||
|
||||
describe "keymap loading", ->
|
||||
describe "when package.json does not contain a 'keymaps' manifest", ->
|
||||
it "loads all keymaps in the directory", ->
|
||||
it "loads all the .cson/.json files in the keymaps directory", ->
|
||||
element1 = $$ -> @div class: 'test-1'
|
||||
element2 = $$ -> @div class: 'test-2'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
|
||||
expect(keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined()
|
||||
expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
|
||||
|
||||
atom.loadPackage("package-with-module")
|
||||
|
||||
expect(keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1"
|
||||
expect(keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2"
|
||||
expect(keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
|
||||
|
||||
describe "when package.json contains a 'keymaps' manifest", ->
|
||||
it "loads only the keymaps specified by the manifest, in the specified order", ->
|
||||
|
||||
@@ -465,6 +465,14 @@ describe 'Buffer', ->
|
||||
range = [[2,10], [4,10]]
|
||||
expect(buffer.getTextInRange(range)).toBe "ems.length <= 1) return items;\n var pivot = items.shift(), current, left = [], right = [];\n while("
|
||||
|
||||
describe "when the range starts before the start of the buffer", ->
|
||||
it "clips the range to the start of the buffer", ->
|
||||
expect(buffer.getTextInRange([[-Infinity, -Infinity], [0, Infinity]])).toBe buffer.lineForRow(0)
|
||||
|
||||
describe "when the range ends after the end of the buffer", ->
|
||||
it "clips the range to the end of the buffer", ->
|
||||
expect(buffer.getTextInRange([[12], [13, Infinity]])).toBe buffer.lineForRow(12)
|
||||
|
||||
describe ".scanInRange(range, regex, fn)", ->
|
||||
describe "when given a regex with a ignore case flag", ->
|
||||
it "does a case-insensitive search", ->
|
||||
|
||||
@@ -495,6 +495,20 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.lineForRow(8).text).toMatch /^9-+/
|
||||
expect(displayBuffer.lineForRow(10).fold).toBeDefined()
|
||||
|
||||
describe "when the line being deleted preceeds a fold", ->
|
||||
describe "when the command is undone", ->
|
||||
it "restores the line and preserves the fold", ->
|
||||
editSession.setCursorBufferPosition([4])
|
||||
editSession.foldCurrentRow()
|
||||
expect(editSession.isFoldedAtScreenRow(4)).toBeTruthy()
|
||||
editSession.setCursorBufferPosition([3])
|
||||
editSession.deleteLine()
|
||||
expect(editSession.isFoldedAtScreenRow(3)).toBeTruthy()
|
||||
expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {'
|
||||
editSession.undo()
|
||||
expect(editSession.isFoldedAtScreenRow(4)).toBeTruthy()
|
||||
expect(buffer.lineForRow(3)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
|
||||
describe ".clipScreenPosition(screenPosition, wrapBeyondNewlines: false, wrapAtSoftNewlines: false, skipAtomicTokens: false)", ->
|
||||
beforeEach ->
|
||||
displayBuffer.setSoftWrapColumn(50)
|
||||
|
||||
@@ -276,17 +276,22 @@ describe "EditSession", ->
|
||||
editSession.moveCursorToBeginningOfWord()
|
||||
|
||||
expect(cursor1.getBufferPosition()).toEqual [0, 4]
|
||||
expect(cursor2.getBufferPosition()).toEqual [1, 10]
|
||||
expect(cursor2.getBufferPosition()).toEqual [1, 11]
|
||||
expect(cursor3.getBufferPosition()).toEqual [2, 39]
|
||||
|
||||
it "does not fail at position [0, 0]", ->
|
||||
editSession.setCursorBufferPosition([0, 0])
|
||||
editSession.moveCursorToBeginningOfWord()
|
||||
|
||||
it "works when the preceding line is blank", ->
|
||||
it "treats lines with only whitespace as a word", ->
|
||||
editSession.setCursorBufferPosition([11, 0])
|
||||
editSession.moveCursorToBeginningOfWord()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [10, 0]
|
||||
|
||||
it "works when the current line is blank", ->
|
||||
editSession.setCursorBufferPosition([10, 0])
|
||||
editSession.moveCursorToBeginningOfWord()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [9, 0]
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [9, 2]
|
||||
|
||||
describe ".moveCursorToEndOfWord()", ->
|
||||
it "moves the cursor to the end of the word", ->
|
||||
@@ -298,8 +303,8 @@ describe "EditSession", ->
|
||||
editSession.moveCursorToEndOfWord()
|
||||
|
||||
expect(cursor1.getBufferPosition()).toEqual [0, 13]
|
||||
expect(cursor2.getBufferPosition()).toEqual [1, 13]
|
||||
expect(cursor3.getBufferPosition()).toEqual [3, 4]
|
||||
expect(cursor2.getBufferPosition()).toEqual [1, 12]
|
||||
expect(cursor3.getBufferPosition()).toEqual [3, 7]
|
||||
|
||||
it "does not blow up when there is no next word", ->
|
||||
editSession.setCursorBufferPosition [Infinity, Infinity]
|
||||
@@ -307,6 +312,17 @@ describe "EditSession", ->
|
||||
editSession.moveCursorToEndOfWord()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual endPosition
|
||||
|
||||
it "treats lines with only whitespace as a word", ->
|
||||
editSession.setCursorBufferPosition([9, 4])
|
||||
editSession.moveCursorToEndOfWord()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [10, 0]
|
||||
|
||||
it "works when the current line is blank", ->
|
||||
editSession.setCursorBufferPosition([10, 0])
|
||||
editSession.moveCursorToEndOfWord()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual [11, 8]
|
||||
|
||||
|
||||
describe ".getCurrentParagraphBufferRange()", ->
|
||||
it "returns the buffer range of the current paragraph, delimited by blank lines or the beginning / end of the file", ->
|
||||
buffer.setText """
|
||||
@@ -518,13 +534,13 @@ describe "EditSession", ->
|
||||
expect(editSession.getCursors().length).toBe 2
|
||||
[cursor1, cursor2] = editSession.getCursors()
|
||||
expect(cursor1.getBufferPosition()).toEqual [0,4]
|
||||
expect(cursor2.getBufferPosition()).toEqual [3,44]
|
||||
expect(cursor2.getBufferPosition()).toEqual [3,47]
|
||||
|
||||
expect(editSession.getSelections().length).toBe 2
|
||||
[selection1, selection2] = editSession.getSelections()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,4], [0,13]]
|
||||
expect(selection1.isReversed()).toBeTruthy()
|
||||
expect(selection2.getBufferRange()).toEqual [[3,44], [3,49]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,47], [3,49]]
|
||||
expect(selection2.isReversed()).toBeTruthy()
|
||||
|
||||
describe ".selectToEndOfWord()", ->
|
||||
@@ -537,40 +553,49 @@ describe "EditSession", ->
|
||||
expect(editSession.getCursors().length).toBe 2
|
||||
[cursor1, cursor2] = editSession.getCursors()
|
||||
expect(cursor1.getBufferPosition()).toEqual [0,13]
|
||||
expect(cursor2.getBufferPosition()).toEqual [3,51]
|
||||
expect(cursor2.getBufferPosition()).toEqual [3,50]
|
||||
|
||||
expect(editSession.getSelections().length).toBe 2
|
||||
[selection1, selection2] = editSession.getSelections()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,4], [0,13]]
|
||||
expect(selection1.isReversed()).toBeFalsy()
|
||||
expect(selection2.getBufferRange()).toEqual [[3,48], [3,51]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,48], [3,50]]
|
||||
expect(selection2.isReversed()).toBeFalsy()
|
||||
|
||||
describe ".selectWord()", ->
|
||||
describe "when the cursor is inside a word", ->
|
||||
it "selects the entire word", ->
|
||||
editSession.setCursorScreenPosition([0, 8])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedText()).toBe 'quicksort'
|
||||
describe "when the cursor is inside a word", ->
|
||||
it "selects the entire word", ->
|
||||
editSession.setCursorScreenPosition([0, 8])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedText()).toBe 'quicksort'
|
||||
|
||||
describe "when the cursor is between two words", ->
|
||||
it "selects both words", ->
|
||||
editSession.setCursorScreenPosition([0, 4])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedText()).toBe ' quicksort'
|
||||
describe "when the cursor is between two words", ->
|
||||
it "selects the word the cursor is on", ->
|
||||
editSession.setCursorScreenPosition([0, 4])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedText()).toBe 'quicksort'
|
||||
|
||||
describe "when the cursor is inside a region of whitespace", ->
|
||||
it "selects the whitespace region", ->
|
||||
editSession.setCursorScreenPosition([5, 2])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]]
|
||||
editSession.setCursorScreenPosition([0, 3])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedText()).toBe 'var'
|
||||
|
||||
describe "when the cursor is at the end of the text", ->
|
||||
it "select the previous word", ->
|
||||
editSession.buffer.append 'word'
|
||||
editSession.moveCursorToBottom()
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]]
|
||||
|
||||
describe "when the cursor is inside a region of whitespace", ->
|
||||
it "selects the whitespace region", ->
|
||||
editSession.setCursorScreenPosition([5, 2])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]]
|
||||
|
||||
editSession.setCursorScreenPosition([5, 0])
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[5, 0], [5, 6]]
|
||||
|
||||
describe "when the cursor is at the end of the text", ->
|
||||
it "select the previous word", ->
|
||||
editSession.buffer.append 'word'
|
||||
editSession.moveCursorToBottom()
|
||||
editSession.selectWord()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]]
|
||||
|
||||
describe ".setSelectedBufferRanges(ranges)", ->
|
||||
it "clears existing selections and creates selections for each of the given ranges", ->
|
||||
@@ -1110,25 +1135,26 @@ describe "EditSession", ->
|
||||
describe "when no text is selected", ->
|
||||
it "deletes all text between the cursor and the beginning of the word", ->
|
||||
editSession.setCursorBufferPosition([1, 24])
|
||||
editSession.addCursorAtBufferPosition([2, 5])
|
||||
editSession.addCursorAtBufferPosition([3, 5])
|
||||
[cursor1, cursor2] = editSession.getCursors()
|
||||
|
||||
editSession.backspaceToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(ems) {'
|
||||
expect(buffer.lineForRow(2)).toBe ' f (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(3)).toBe ' ar pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 22]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 4]
|
||||
expect(cursor2.getBufferPosition()).toEqual [3, 4]
|
||||
|
||||
editSession.backspaceToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = functionems) {'
|
||||
expect(buffer.lineForRow(2)).toBe 'f (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return itemsar pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 21]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 0]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 39]
|
||||
|
||||
editSession.backspaceToBeginningOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = emsf (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = ems) {'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return ar pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 13]
|
||||
expect(cursor2.getBufferPosition()).toEqual [1, 16]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 34]
|
||||
|
||||
describe "when text is selected", ->
|
||||
it "deletes only selected text", ->
|
||||
@@ -1296,7 +1322,7 @@ describe "EditSession", ->
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 5]
|
||||
|
||||
editSession.deleteToEndOfWord()
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(it'
|
||||
expect(buffer.lineForRow(1)).toBe ' var sort = function(it {'
|
||||
expect(buffer.lineForRow(2)).toBe ' iitems.length <= 1) return items;'
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 24]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 5]
|
||||
|
||||
@@ -516,14 +516,61 @@ describe "Editor", ->
|
||||
editor.getBuffer().saveAs(path)
|
||||
expect(editor.getGrammar().name).toBe 'Plain Text'
|
||||
|
||||
describe "font size", ->
|
||||
it "sets the initial font size based on the value from config", ->
|
||||
config.set("editor.fontSize", 20)
|
||||
newEditor = editor.splitRight()
|
||||
expect(editor.css('font-size')).toBe '20px'
|
||||
expect(newEditor.css('font-size')).toBe '20px'
|
||||
describe "font family", ->
|
||||
beforeEach ->
|
||||
expect(editor.css('font-family')).not.toBe 'Courier'
|
||||
|
||||
it "when there is no config in fontFamily don't set it", ->
|
||||
expect($("head style.font-family")).not.toExist()
|
||||
|
||||
describe "when the font family changes", ->
|
||||
it "updates the font family on new and existing editors", ->
|
||||
rootView.attachToDom()
|
||||
rootView.height(200)
|
||||
rootView.width(200)
|
||||
|
||||
config.set("editor.fontFamily", "Courier")
|
||||
newEditor = editor.splitRight()
|
||||
|
||||
expect($("head style.font-family").text()).toMatch "{font-family: Courier}"
|
||||
expect(editor.css('font-family')).toBe 'Courier'
|
||||
expect(newEditor.css('font-family')).toBe 'Courier'
|
||||
|
||||
it "updates the font family of editors and recalculates dimensions critical to cursor positioning", ->
|
||||
rootView.attachToDom()
|
||||
rootView.height(200)
|
||||
rootView.width(200)
|
||||
|
||||
lineHeightBefore = editor.lineHeight
|
||||
charWidthBefore = editor.charWidth
|
||||
config.set("editor.fontFamily", "Inconsolata")
|
||||
editor.setCursorScreenPosition [5, 6]
|
||||
expect(editor.charWidth).not.toBe charWidthBefore
|
||||
expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 6 * editor.charWidth }
|
||||
expect(editor.verticalScrollbarContent.height()).toBe buffer.getLineCount() * editor.lineHeight
|
||||
|
||||
describe "font size", ->
|
||||
beforeEach ->
|
||||
expect(editor.css('font-size')).not.toBe "20px"
|
||||
expect(editor.css('font-size')).not.toBe "10px"
|
||||
|
||||
it "sets the initial font size based on the value from config", ->
|
||||
expect($("head style.font-size")).toExist()
|
||||
expect($("head style.font-size").text()).toMatch "{font-size: #{config.get('editor.fontSize')}px}"
|
||||
|
||||
describe "when the font size changes", ->
|
||||
it "updates the font family on new and existing editors", ->
|
||||
rootView.attachToDom()
|
||||
rootView.height(200)
|
||||
rootView.width(200)
|
||||
|
||||
config.set("editor.fontSize", 20)
|
||||
newEditor = editor.splitRight()
|
||||
|
||||
expect($("head style.font-size").text()).toMatch "{font-size: 20px}"
|
||||
expect(editor.css('font-size')).toBe '20px'
|
||||
expect(newEditor.css('font-size')).toBe '20px'
|
||||
|
||||
describe "when the font size changes on the view", ->
|
||||
it "updates the font sizes of editors and recalculates dimensions critical to cursor positioning", ->
|
||||
rootView.attachToDom()
|
||||
rootView.height(200)
|
||||
@@ -568,6 +615,23 @@ describe "Editor", ->
|
||||
config.set("editor.fontSize", 10)
|
||||
expect(editor.renderedLines.find(".line").length).toBeGreaterThan originalLineCount
|
||||
|
||||
describe "when the editor is detached", ->
|
||||
it "updates the font-size correctly and recalculates the dimensions by placing the rendered lines on the DOM", ->
|
||||
rootView.attachToDom()
|
||||
rootView.height(200)
|
||||
rootView.width(200)
|
||||
|
||||
newEditor = editor.splitRight()
|
||||
newEditorParent = newEditor.parent()
|
||||
newEditor.detach()
|
||||
config.set("editor.fontSize", 10)
|
||||
newEditorParent.append(newEditor)
|
||||
|
||||
expect(newEditor.lineHeight).toBe editor.lineHeight
|
||||
expect(newEditor.charWidth).toBe editor.charWidth
|
||||
expect(newEditor.getCursorView().position()).toEqual editor.getCursorView().position()
|
||||
expect(newEditor.verticalScrollbarContent.height()).toBe editor.verticalScrollbarContent.height()
|
||||
|
||||
describe "mouse events", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom()
|
||||
@@ -1730,6 +1794,11 @@ describe "Editor", ->
|
||||
fold.destroy()
|
||||
expect(editor.gutter.find('.line-number').length).toBe 13
|
||||
|
||||
it "styles folded line numbers", ->
|
||||
editor.createFold(3, 5)
|
||||
expect(editor.gutter.find('.line-number.fold').length).toBe 1
|
||||
expect(editor.gutter.find('.line-number.fold:eq(0)').text()).toBe '4'
|
||||
|
||||
describe "when the scrollView is scrolled to the right", ->
|
||||
it "adds a drop shadow to the gutter", ->
|
||||
editor.attachToDom()
|
||||
@@ -1898,16 +1967,18 @@ describe "Editor", ->
|
||||
editor.attachToDom()
|
||||
|
||||
describe "when a fold-selection event is triggered", ->
|
||||
it "folds the lines covered by the selection into a single line with a fold class", ->
|
||||
it "folds the lines covered by the selection into a single line with a fold class and marker", ->
|
||||
editor.getSelection().setBufferRange(new Range([4, 29], [7, 4]))
|
||||
editor.trigger 'editor:fold-selection'
|
||||
|
||||
expect(editor.renderedLines.find('.line:eq(4)')).toHaveClass('fold')
|
||||
expect(editor.renderedLines.find('.line:eq(4) > .fold-marker')).toExist()
|
||||
expect(editor.renderedLines.find('.line:eq(5)').text()).toBe '8'
|
||||
|
||||
expect(editor.getSelection().isEmpty()).toBeTruthy()
|
||||
expect(editor.getCursorScreenPosition()).toEqual [5, 0]
|
||||
|
||||
|
||||
describe "when a fold placeholder line is clicked", ->
|
||||
it "removes the associated fold and places the cursor at its beginning", ->
|
||||
editor.setCursorBufferPosition([3,0])
|
||||
@@ -1916,6 +1987,7 @@ describe "Editor", ->
|
||||
editor.find('.fold.line').mousedown()
|
||||
|
||||
expect(editor.find('.fold')).not.toExist()
|
||||
expect(editor.find('.fold-marker')).not.toExist()
|
||||
expect(editor.renderedLines.find('.line:eq(4)').text()).toMatch /4-+/
|
||||
expect(editor.renderedLines.find('.line:eq(5)').text()).toMatch /5/
|
||||
|
||||
@@ -2260,3 +2332,196 @@ describe "Editor", ->
|
||||
it "copies the absolute path to the editor's file to the pasteboard", ->
|
||||
editor.trigger 'editor:copy-path'
|
||||
expect(pasteboard.read()[0]).toBe editor.getPath()
|
||||
|
||||
describe "when editor:move-line-up is triggered", ->
|
||||
describe "when there is no selection", ->
|
||||
it "moves the line where the cursor is up", ->
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {'
|
||||
expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {'
|
||||
|
||||
it "moves the cursor to the new row and the same column", ->
|
||||
editor.setCursorBufferPosition([1,2])
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0,2]
|
||||
|
||||
describe "where there is a selection", ->
|
||||
describe "when the selection falls inside the line", ->
|
||||
it "maintains the selection", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [1, 5]])
|
||||
expect(editor.getSelectedText()).toBe 'var'
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[0, 2], [0, 5]]
|
||||
expect(editor.getSelectedText()).toBe 'var'
|
||||
|
||||
describe "where there are multiple lines selected", ->
|
||||
it "moves the selected lines up", ->
|
||||
editor.setSelectedBufferRange([[2, 0], [3, Infinity]])
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {'
|
||||
expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(2)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(buffer.lineForRow(3)).toBe ' var sort = function(items) {'
|
||||
|
||||
it "maintains the selection", ->
|
||||
editor.setSelectedBufferRange([[2, 0], [3, 62]])
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[1, 0], [2, 62]]
|
||||
|
||||
describe "when the last line is selected", ->
|
||||
it "moves the selected line up", ->
|
||||
editor.setSelectedBufferRange([[12, 0], [12, Infinity]])
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(11)).toBe '};'
|
||||
expect(buffer.lineForRow(12)).toBe ' return sort(Array.apply(this, arguments));'
|
||||
|
||||
describe "when the last two lines are selected", ->
|
||||
it "moves the selected lines up", ->
|
||||
editor.setSelectedBufferRange([[11, 0], [12, Infinity]])
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(10)).toBe ' return sort(Array.apply(this, arguments));'
|
||||
expect(buffer.lineForRow(11)).toBe '};'
|
||||
expect(buffer.lineForRow(12)).toBe ''
|
||||
|
||||
describe "when the cursor is on the first line", ->
|
||||
it "does not move the line", ->
|
||||
editor.setCursorBufferPosition([0,0])
|
||||
originalText = editor.getText()
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(editor.getText()).toBe originalText
|
||||
|
||||
describe "when the cursor is on the trailing newline", ->
|
||||
it "does not move the line", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.insertNewline()
|
||||
editor.moveCursorToBottom()
|
||||
originalText = editor.getText()
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(editor.getText()).toBe originalText
|
||||
|
||||
describe "when the cursor is on a folded line", ->
|
||||
it "moves all lines in the fold up and preserves the fold", ->
|
||||
editor.setCursorBufferPosition([4, 0])
|
||||
editor.foldCurrentRow()
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {'
|
||||
expect(buffer.lineForRow(7)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[3, 0], [3, 0]]
|
||||
expect(editor.isFoldedAtScreenRow(3)).toBeTruthy()
|
||||
|
||||
describe "when the selection contains a folded and unfolded line", ->
|
||||
it "moves the selected lines up and preserves the fold", ->
|
||||
editor.setCursorBufferPosition([4, 0])
|
||||
editor.foldCurrentRow()
|
||||
editor.setCursorBufferPosition([3, 4])
|
||||
editor.selectDown()
|
||||
expect(editor.isFoldedAtScreenRow(4)).toBeTruthy()
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(2)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(buffer.lineForRow(3)).toBe ' while(items.length > 0) {'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[2, 4], [3, 0]]
|
||||
expect(editor.isFoldedAtScreenRow(3)).toBeTruthy()
|
||||
|
||||
describe "when an entire line is selected including the newline", ->
|
||||
it "moves the selected line up", ->
|
||||
editor.setCursorBufferPosition([1])
|
||||
editor.selectToEndOfLine()
|
||||
editor.selectRight()
|
||||
editor.trigger 'editor:move-line-up'
|
||||
expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {'
|
||||
expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {'
|
||||
|
||||
describe "when editor:move-line-down is triggered", ->
|
||||
describe "when there is no selection", ->
|
||||
it "moves the line where the cursor is down", ->
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {'
|
||||
expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {'
|
||||
|
||||
it "moves the cursor to the new row and the same column", ->
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(editor.getCursorBufferPosition()).toEqual [1, 2]
|
||||
|
||||
describe "when the cursor is on the last line", ->
|
||||
it "does not move the line", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(12)).toBe '};'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]]
|
||||
|
||||
describe "when the cursor is on the second to last line", ->
|
||||
it "moves the line down", ->
|
||||
editor.setCursorBufferPosition([11, 0])
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(11)).toBe '};'
|
||||
expect(buffer.lineForRow(12)).toBe ' return sort(Array.apply(this, arguments));'
|
||||
expect(buffer.lineForRow(13)).toBeUndefined()
|
||||
|
||||
describe "when the cursor is on the second to last line and the last line is empty", ->
|
||||
it "does not move the line", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.insertNewline()
|
||||
editor.setCursorBufferPosition([12, 2])
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(12)).toBe '};'
|
||||
expect(buffer.lineForRow(13)).toBe ''
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 2]]
|
||||
|
||||
describe "where there is a selection", ->
|
||||
describe "when the selection falls inside the line", ->
|
||||
it "maintains the selection", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [1, 5]])
|
||||
expect(editor.getSelectedText()).toBe 'var'
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[2, 2], [2, 5]]
|
||||
expect(editor.getSelectedText()).toBe 'var'
|
||||
|
||||
describe "where there are multiple lines selected", ->
|
||||
it "moves the selected lines down", ->
|
||||
editor.setSelectedBufferRange([[2, 0], [3, Infinity]])
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(2)).toBe ' while(items.length > 0) {'
|
||||
expect(buffer.lineForRow(3)).toBe ' if (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(buffer.lineForRow(5)).toBe ' current = items.shift();'
|
||||
|
||||
it "maintains the selection", ->
|
||||
editor.setSelectedBufferRange([[2, 0], [3, 62]])
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[3, 0], [4, 62]]
|
||||
|
||||
describe "when the cursor is on a folded line", ->
|
||||
it "moves all lines in the fold down and preserves the fold", ->
|
||||
editor.setCursorBufferPosition([4, 0])
|
||||
editor.foldCurrentRow()
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(4)).toBe ' return sort(left).concat(pivot).concat(sort(right));'
|
||||
expect(buffer.lineForRow(5)).toBe ' while(items.length > 0) {'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[5, 0], [5, 0]]
|
||||
expect(editor.isFoldedAtScreenRow(5)).toBeTruthy()
|
||||
|
||||
describe "when the selection contains a folded and unfolded line", ->
|
||||
it "moves the selected lines down and preserves the fold", ->
|
||||
editor.setCursorBufferPosition([4, 0])
|
||||
editor.foldCurrentRow()
|
||||
editor.setCursorBufferPosition([3, 4])
|
||||
editor.selectDown()
|
||||
expect(editor.isFoldedAtScreenRow(4)).toBeTruthy()
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(3)).toBe ' return sort(left).concat(pivot).concat(sort(right));'
|
||||
expect(buffer.lineForRow(4)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(buffer.lineForRow(5)).toBe ' while(items.length > 0) {'
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[4, 4], [5, 0]]
|
||||
expect(editor.isFoldedAtScreenRow(5)).toBeTruthy()
|
||||
|
||||
describe "when an entire line is selected including the newline", ->
|
||||
it "moves the selected line down", ->
|
||||
editor.setCursorBufferPosition([1])
|
||||
editor.selectToEndOfLine()
|
||||
editor.selectRight()
|
||||
editor.trigger 'editor:move-line-down'
|
||||
expect(buffer.lineForRow(1)).toBe ' if (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(2)).toBe ' var sort = function(items) {'
|
||||
|
||||
@@ -25,3 +25,9 @@ describe "Point", ->
|
||||
expect(new Point(5, 0).compare(new Point(6, 1))).toBe -1
|
||||
expect(new Point(5, 5).compare(new Point(4, 1))).toBe 1
|
||||
expect(new Point(5, 5).compare(new Point(5, 3))).toBe 1
|
||||
|
||||
describe ".translate(other)", ->
|
||||
it "returns a translated point", ->
|
||||
expect(new Point(1,2).translate([2,4])).toEqual [3,6]
|
||||
expect(new Point(1,2).translate([-1])).toEqual [0,2]
|
||||
expect(new Point(1,2).translate([0,-2])).toEqual [1,0]
|
||||
|
||||
@@ -32,3 +32,8 @@ describe "Range", ->
|
||||
expect(new Range([2, 1], [3, 10]).union(new Range([1, 1], [2, 10]))).toEqual [[1, 1], [3, 10]]
|
||||
expect(new Range([2, 1], [3, 10]).union(new Range([2, 5], [3, 1]))).toEqual [[2, 1], [3, 10]]
|
||||
expect(new Range([2, 5], [3, 1]).union(new Range([2, 1], [3, 10]))).toEqual [[2, 1], [3, 10]]
|
||||
|
||||
describe ".translate(startPoint, endPoint)", ->
|
||||
it "returns a range translates by the specified start and end points", ->
|
||||
expect(new Range([1, 1], [2, 10]).translate([1])).toEqual [[2, 1], [3, 10]]
|
||||
expect(new Range([1, 1], [2, 10]).translate([1,2], [3,4])).toEqual [[2, 3], [5, 14]]
|
||||
|
||||
@@ -567,9 +567,9 @@ describe "RootView", ->
|
||||
editor = null
|
||||
beforeEach ->
|
||||
editor = rootView.getActiveEditor()
|
||||
editor.attachToDom()
|
||||
|
||||
it "increases/decreases font size when increase/decrease-font-size events are triggered", ->
|
||||
editor = rootView.getActiveEditor()
|
||||
fontSizeBefore = editor.getFontSize()
|
||||
rootView.trigger 'window:increase-font-size'
|
||||
expect(editor.getFontSize()).toBe fontSizeBefore + 1
|
||||
|
||||
@@ -23,8 +23,7 @@ describe "the `syntax` global", ->
|
||||
expect(syntax.grammarForFilePath("/tmp/.git/config").name).toBe "Git Config"
|
||||
|
||||
it "uses plain text if no grammar can be found", ->
|
||||
filePath = require.resolve("this-is-not-a-real-file")
|
||||
expect(syntax.grammarForFilePath(filePath).name).toBe "Plain Text"
|
||||
expect(syntax.grammarForFilePath("this-is-not-a-real-file").name).toBe "Plain Text"
|
||||
|
||||
describe ".getProperty(scopeDescriptor)", ->
|
||||
it "returns the property with the most specific scope selector", ->
|
||||
|
||||
2
spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson
vendored
Normal file
2
spec/fixtures/packages/package-with-module/keymaps/keymap-3.cjson
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
".test-3":
|
||||
"ctrl-z": "test-3"
|
||||
@@ -85,7 +85,7 @@ jasmine.unspy = (object, methodName) ->
|
||||
throw new Error("Not a spy") unless object[methodName].originalValue?
|
||||
object[methodName] = object[methodName].originalValue
|
||||
|
||||
jasmine.getEnv().defaultTimeoutInterval = 500
|
||||
jasmine.getEnv().defaultTimeoutInterval = 1000
|
||||
|
||||
window.keyIdentifierForKey = (key) ->
|
||||
if key.length > 1 # named key
|
||||
|
||||
@@ -128,3 +128,8 @@ describe "fs", ->
|
||||
describe ".md5ForPath(path)", ->
|
||||
it "returns the MD5 hash of the file at the given path", ->
|
||||
expect(fs.md5ForPath(require.resolve('fixtures/sample.js'))).toBe 'dd38087d0d7e3e4802a6d3f9b9745f2b'
|
||||
|
||||
describe ".list(path, extensions)", ->
|
||||
it "returns the paths with the specified extensions", ->
|
||||
path = require.resolve('fixtures/css.css')
|
||||
expect(fs.list(require.resolve('fixtures'), ['.css'])).toEqual [path]
|
||||
|
||||
@@ -26,15 +26,12 @@ class AtomPackage extends Package
|
||||
@metadata = fs.readObject(metadataPath)
|
||||
|
||||
loadKeymaps: ->
|
||||
for keymapPath in @getKeymapPaths()
|
||||
keymap.load(keymapPath)
|
||||
|
||||
getKeymapPaths: ->
|
||||
if keymaps = @metadata?.keymaps
|
||||
keymaps.map (relativePath) =>
|
||||
keymaps = keymaps.map (relativePath) =>
|
||||
fs.resolve(@keymapsDirPath, relativePath, ['cson', 'json', ''])
|
||||
keymap.load(keymapPath) for keymapPath in keymaps
|
||||
else
|
||||
fs.list(@keymapsDirPath)
|
||||
keymap.loadDirectory(@keymapsDirPath)
|
||||
|
||||
loadStylesheets: ->
|
||||
for stylesheetPath in @getStylesheetPaths()
|
||||
|
||||
@@ -53,10 +53,16 @@ _.extend atom,
|
||||
themeNames = config.get("core.themes") ? ['Atom - Dark', 'IR_Black']
|
||||
themeNames = [themeNames] unless _.isArray(themeNames)
|
||||
@loadTheme(themeName) for themeName in themeNames
|
||||
@loadUserStylesheet()
|
||||
|
||||
loadTheme: (name) ->
|
||||
@loadedThemes.push Theme.load(name)
|
||||
|
||||
loadUserStylesheet: ->
|
||||
userStylesheetPath = fs.join(config.configDirPath, 'user.css')
|
||||
if fs.isFile(userStylesheetPath)
|
||||
applyStylesheet(userStylesheetPath, fs.read(userStylesheetPath), 'userTheme')
|
||||
|
||||
getAtomThemeStylesheets: ->
|
||||
themeNames = config.get("core.themes") ? ['Atom - Dark', 'IR_Black']
|
||||
themeNames = [themeNames] unless _.isArray(themeNames)
|
||||
|
||||
@@ -115,9 +115,9 @@ class Buffer
|
||||
new Range([0, 0], [@getLastRow(), @getLastLine().length])
|
||||
|
||||
getTextInRange: (range) ->
|
||||
range = Range.fromObject(range)
|
||||
range = @clipRange(range)
|
||||
if range.start.row == range.end.row
|
||||
return @lines[range.start.row][range.start.column...range.end.column]
|
||||
return @lineForRow(range.start.row)[range.start.column...range.end.column]
|
||||
|
||||
multipleLines = []
|
||||
multipleLines.push @lineForRow(range.start.row)[range.start.column..] # first line
|
||||
@@ -194,7 +194,7 @@ class Buffer
|
||||
startPoint = [start, 0]
|
||||
endPoint = [end + 1, 0]
|
||||
|
||||
@change(new Range(startPoint, endPoint), '')
|
||||
@delete(new Range(startPoint, endPoint))
|
||||
|
||||
append: (text) ->
|
||||
@insert(@getEofPosition(), text)
|
||||
@@ -220,6 +220,10 @@ class Buffer
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
clipRange: (range) ->
|
||||
range = Range.fromObject(range)
|
||||
new Range(@clipPosition(range.start), @clipPosition(range.end))
|
||||
|
||||
prefixAndSuffixForRange: (range) ->
|
||||
prefix: @lines[range.start.row][0...range.start.column]
|
||||
suffix: @lines[range.end.row][range.end.column..]
|
||||
|
||||
@@ -4,7 +4,7 @@ EventEmitter = require 'event-emitter'
|
||||
|
||||
configDirPath = fs.absolute("~/.atom")
|
||||
configJsonPath = fs.join(configDirPath, "config.json")
|
||||
userInitScriptPath = fs.join(configDirPath, "atom.coffee")
|
||||
userInitScriptPath = fs.join(configDirPath, "user.coffee")
|
||||
bundledPackagesDirPath = fs.join(resourcePath, "src/packages")
|
||||
bundledThemesDirPath = fs.join(resourcePath, "themes")
|
||||
vendoredPackagesDirPath = fs.join(resourcePath, "vendor/packages")
|
||||
|
||||
@@ -9,7 +9,6 @@ class Cursor
|
||||
screenPosition: null
|
||||
bufferPosition: null
|
||||
goalColumn: null
|
||||
wordRegex: /(\w+)|([^\w\n]+)/g
|
||||
visible: true
|
||||
needsAutoscroll: false
|
||||
|
||||
@@ -56,9 +55,18 @@ class Cursor
|
||||
|
||||
isVisible: -> @visible
|
||||
|
||||
wordRegExp: ->
|
||||
nonWordCharacters = config.get("editor.nonWordCharacters")
|
||||
new RegExp("^[\t ]*$|[^\\s#{_.escapeRegExp(nonWordCharacters)}]+|[#{_.escapeRegExp(nonWordCharacters)}]+", "g")
|
||||
|
||||
isLastCursor: ->
|
||||
this == @editSession.getCursor()
|
||||
|
||||
isSurroundedByWhitespace: ->
|
||||
{row, column} = @getBufferPosition()
|
||||
range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]]
|
||||
/^\s+$/.test @editSession.getTextInBufferRange(range)
|
||||
|
||||
autoscrolled: ->
|
||||
@needsAutoscroll = false
|
||||
|
||||
@@ -147,14 +155,16 @@ class Cursor
|
||||
allowPrevious = options.allowPrevious ? true
|
||||
currentBufferPosition = @getBufferPosition()
|
||||
previousNonBlankRow = @editSession.buffer.previousNonBlankRow(currentBufferPosition.row)
|
||||
previousLinesRange = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
range = [[previousNonBlankRow, 0], currentBufferPosition]
|
||||
|
||||
beginningOfWordPosition = currentBufferPosition
|
||||
@editSession.backwardsScanInRange (options.wordRegex || @wordRegex), previousLinesRange, (match, matchRange, { stop }) =>
|
||||
beginningOfWordPosition = null
|
||||
@editSession.backwardsScanInRange (options.wordRegex ? @wordRegExp()), range, (match, matchRange, { stop }) =>
|
||||
if matchRange.end.isGreaterThanOrEqual(currentBufferPosition) or allowPrevious
|
||||
beginningOfWordPosition = matchRange.start
|
||||
stop()
|
||||
beginningOfWordPosition
|
||||
if not beginningOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
beginningOfWordPosition or currentBufferPosition
|
||||
|
||||
getEndOfCurrentWordBufferPosition: (options = {}) ->
|
||||
allowNext = options.allowNext ? true
|
||||
@@ -162,11 +172,12 @@ class Cursor
|
||||
range = [currentBufferPosition, @editSession.getEofBufferPosition()]
|
||||
|
||||
endOfWordPosition = null
|
||||
@editSession.scanInRange (options.wordRegex || @wordRegex), range, (match, matchRange, { stop }) =>
|
||||
endOfWordPosition = matchRange.end
|
||||
if not allowNext and matchRange.start.isGreaterThan(currentBufferPosition)
|
||||
endOfWordPosition = currentBufferPosition
|
||||
stop()
|
||||
@editSession.scanInRange (options.wordRegex ? @wordRegExp()), range, (match, matchRange, { stop }) =>
|
||||
if matchRange.start.isLessThanOrEqual(currentBufferPosition) or allowNext
|
||||
endOfWordPosition = matchRange.end
|
||||
if not endOfWordPosition?.isEqual(currentBufferPosition)
|
||||
stop()
|
||||
|
||||
endOfWordPosition or currentBufferPosition
|
||||
|
||||
getCurrentWordBufferRange: (options={}) ->
|
||||
|
||||
@@ -18,7 +18,7 @@ class EditSession
|
||||
if fs.exists(state.buffer)
|
||||
session = project.buildEditSessionForPath(state.buffer)
|
||||
else
|
||||
console.warn "Could not build edit session for path '#{state.buffer}' because that file no longer exists"
|
||||
console.warn "Could not build edit session for path '#{state.buffer}' because that file no longer exists" if state.buffer
|
||||
session = project.buildEditSessionForPath(null)
|
||||
session.setScrollTop(state.scrollTop)
|
||||
session.setScrollLeft(state.scrollLeft)
|
||||
@@ -307,6 +307,10 @@ class EditSession
|
||||
fold.destroy()
|
||||
@setCursorBufferPosition([fold.startRow, 0])
|
||||
|
||||
isFoldedAtBufferRow: (bufferRow) ->
|
||||
screenRow = @screenPositionForBufferPosition([bufferRow]).row
|
||||
@isFoldedAtScreenRow(screenRow)
|
||||
|
||||
isFoldedAtScreenRow: (screenRow) ->
|
||||
@lineForScreenRow(screenRow)?.fold?
|
||||
|
||||
@@ -334,6 +338,77 @@ class EditSession
|
||||
toggleLineCommentsForBufferRows: (start, end) ->
|
||||
@languageMode.toggleLineCommentsForBufferRows(start, end)
|
||||
|
||||
moveLineUp: ->
|
||||
selection = @getSelectedBufferRange()
|
||||
return if selection.start.row is 0
|
||||
lastRow = @buffer.getLastRow()
|
||||
return if selection.isEmpty() and selection.start.row is lastRow and @buffer.getLastLine() is ''
|
||||
|
||||
@transact =>
|
||||
foldedRows = []
|
||||
rows = [selection.start.row..selection.end.row]
|
||||
if selection.start.row isnt selection.end.row and selection.end.column is 0
|
||||
rows.pop() unless @isFoldedAtBufferRow(selection.end.row)
|
||||
for row in rows
|
||||
screenRow = @screenPositionForBufferPosition([row]).row
|
||||
if @isFoldedAtScreenRow(screenRow)
|
||||
bufferRange = @bufferRangeForScreenRange([[screenRow], [screenRow + 1]])
|
||||
startRow = bufferRange.start.row
|
||||
endRow = bufferRange.end.row - 1
|
||||
foldedRows.push(endRow - 1)
|
||||
else
|
||||
startRow = row
|
||||
endRow = row
|
||||
|
||||
endPosition = Point.min([endRow + 1], @buffer.getEofPosition())
|
||||
lines = @buffer.getTextInRange([[startRow], endPosition])
|
||||
if endPosition.row is lastRow and endPosition.column > 0 and not @buffer.lineEndingForRow(endPosition.row)
|
||||
lines = "#{lines}\n"
|
||||
@buffer.deleteRows(startRow, endRow)
|
||||
@buffer.insert([startRow - 1], lines)
|
||||
|
||||
@foldBufferRow(foldedRow) for foldedRow in foldedRows
|
||||
|
||||
@setSelectedBufferRange(selection.translate([-1]), preserveFolds: true)
|
||||
|
||||
moveLineDown: ->
|
||||
selection = @getSelectedBufferRange()
|
||||
lastRow = @buffer.getLastRow()
|
||||
return if selection.end.row is lastRow
|
||||
return if selection.end.row is lastRow - 1 and @buffer.getLastLine() is ''
|
||||
|
||||
@transact =>
|
||||
foldedRows = []
|
||||
rows = [selection.end.row..selection.start.row]
|
||||
if selection.start.row isnt selection.end.row and selection.end.column is 0
|
||||
rows.shift() unless @isFoldedAtBufferRow(selection.end.row)
|
||||
for row in rows
|
||||
screenRow = @screenPositionForBufferPosition([row]).row
|
||||
if @isFoldedAtScreenRow(screenRow)
|
||||
bufferRange = @bufferRangeForScreenRange([[screenRow], [screenRow + 1]])
|
||||
startRow = bufferRange.start.row
|
||||
endRow = bufferRange.end.row - 1
|
||||
foldedRows.push(endRow + 1)
|
||||
else
|
||||
startRow = row
|
||||
endRow = row
|
||||
|
||||
if endRow + 1 is lastRow
|
||||
endPosition = [endRow, @buffer.lineLengthForRow(endRow)]
|
||||
else
|
||||
endPosition = [endRow + 1]
|
||||
lines = @buffer.getTextInRange([[startRow], endPosition])
|
||||
@buffer.deleteRows(startRow, endRow)
|
||||
insertPosition = Point.min([startRow + 1], @buffer.getEofPosition())
|
||||
if insertPosition.row is @buffer.getLastRow() and insertPosition.column > 0
|
||||
lines = "\n#{lines}"
|
||||
@buffer.insert(insertPosition, lines)
|
||||
|
||||
@foldBufferRow(foldedRow) for foldedRow in foldedRows
|
||||
|
||||
@setSelectedBufferRange(selection.translate([1]), preserveFolds: true)
|
||||
|
||||
|
||||
mutateSelectedText: (fn) ->
|
||||
@transact => fn(selection) for selection in @getSelections()
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ class Editor extends View
|
||||
autosave: false
|
||||
autoIndent: true
|
||||
autoIndentOnPaste: false
|
||||
nonWordCharacters: "./\\()\"'-_:,.;<>~!@#$%^&*|+=[]{}`~?"
|
||||
|
||||
@content: (params) ->
|
||||
@div class: @classes(params), tabindex: -1, =>
|
||||
@@ -183,6 +184,8 @@ class Editor extends View
|
||||
'editor:close-all-edit-sessions': @destroyAllEditSessions
|
||||
'editor:select-grammar': @selectGrammar
|
||||
'editor:copy-path': @copyPathToPasteboard
|
||||
'editor:move-line-up': @moveLineUp
|
||||
'editor:move-line-down': @moveLineDown
|
||||
|
||||
documentation = {}
|
||||
for name, method of editorBindings
|
||||
@@ -204,6 +207,8 @@ class Editor extends View
|
||||
moveCursorToBeginningOfLine: -> @activeEditSession.moveCursorToBeginningOfLine()
|
||||
moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine()
|
||||
moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine()
|
||||
moveLineUp: -> @activeEditSession.moveLineUp()
|
||||
moveLineDown: -> @activeEditSession.moveLineDown()
|
||||
setCursorScreenPosition: (position) -> @activeEditSession.setCursorScreenPosition(position)
|
||||
getCursorScreenPosition: -> @activeEditSession.getCursorScreenPosition()
|
||||
getCursorScreenRow: -> @activeEditSession.getCursorScreenRow()
|
||||
@@ -271,6 +276,7 @@ class Editor extends View
|
||||
destroyFold: (foldId) -> @activeEditSession.destroyFold(foldId)
|
||||
destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow)
|
||||
isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow)
|
||||
isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow)
|
||||
|
||||
lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow)
|
||||
linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end)
|
||||
@@ -312,7 +318,7 @@ class Editor extends View
|
||||
setInvisibles: (@invisibles={}) ->
|
||||
_.defaults @invisibles,
|
||||
eol: '\u00ac'
|
||||
space: '\u2022'
|
||||
space: '\u00b7'
|
||||
tab: '\u00bb'
|
||||
cr: '\u00a4'
|
||||
@resetDisplay()
|
||||
@@ -335,6 +341,7 @@ class Editor extends View
|
||||
@observeConfig 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles)
|
||||
@observeConfig 'editor.invisibles', (invisibles) => @setInvisibles(invisibles)
|
||||
@observeConfig 'editor.fontSize', (fontSize) => @setFontSize(fontSize)
|
||||
@observeConfig 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily)
|
||||
|
||||
handleEvents: ->
|
||||
@on 'focus', =>
|
||||
@@ -675,16 +682,38 @@ class Editor extends View
|
||||
autosave: ->
|
||||
@save() if @getPath()?
|
||||
|
||||
setFontSize: (@fontSize) ->
|
||||
if fontSize?
|
||||
@css('font-size', fontSize + 'px')
|
||||
return unless @attached
|
||||
@calculateDimensions()
|
||||
@updatePaddingOfRenderedLines()
|
||||
@updateLayerDimensions()
|
||||
@requestDisplayUpdate()
|
||||
setFontSize: (fontSize) ->
|
||||
headTag = $("head")
|
||||
styleTag = headTag.find("style.font-size")
|
||||
if styleTag.length == 0
|
||||
styleTag = $$ -> @style class: 'font-size'
|
||||
headTag.append styleTag
|
||||
|
||||
getFontSize: -> @fontSize
|
||||
styleTag.text(".editor {font-size: #{fontSize}px}")
|
||||
@redraw()
|
||||
|
||||
getFontSize: ->
|
||||
parseInt(@css("font-size"))
|
||||
|
||||
setFontFamily: (fontFamily) ->
|
||||
return if fontFamily == undefined
|
||||
headTag = $("head")
|
||||
styleTag = headTag.find("style.font-family")
|
||||
if styleTag.length == 0
|
||||
styleTag = $$ -> @style class: 'font-family'
|
||||
headTag.append styleTag
|
||||
|
||||
styleTag.text(".editor {font-family: #{fontFamily}}")
|
||||
@redraw()
|
||||
|
||||
getFontFamily: -> @css("font-family")
|
||||
|
||||
redraw: ->
|
||||
return unless @attached
|
||||
@calculateDimensions()
|
||||
@updatePaddingOfRenderedLines()
|
||||
@updateLayerDimensions()
|
||||
@requestDisplayUpdate()
|
||||
|
||||
newSplitEditor: (editSession) ->
|
||||
new Editor { editSession: editSession ? @activeEditSession.copy() }
|
||||
@@ -775,6 +804,10 @@ class Editor extends View
|
||||
@overlayer.append(view)
|
||||
|
||||
calculateDimensions: ->
|
||||
if not @isOnDom()
|
||||
detachedEditorParent = _.last(@parents()) ? this
|
||||
$(document.body).append(detachedEditorParent)
|
||||
|
||||
fragment = $('<pre class="line" style="position: absolute; visibility: hidden;"><span>x</span></div>')
|
||||
@renderedLines.append(fragment)
|
||||
|
||||
@@ -786,6 +819,8 @@ class Editor extends View
|
||||
@height(@lineHeight) if @mini
|
||||
fragment.remove()
|
||||
|
||||
$(detachedEditorParent).detach()
|
||||
|
||||
updateLayerDimensions: ->
|
||||
@gutter.calculateWidth()
|
||||
|
||||
@@ -1053,8 +1088,6 @@ class Editor extends View
|
||||
|
||||
if fold = screenLine.fold
|
||||
lineAttributes = { class: 'fold line', 'fold-id': fold.id }
|
||||
if @activeEditSession.selectionIntersectsBufferRange(fold.getBufferRange())
|
||||
lineAttributes.class += ' selected'
|
||||
else
|
||||
lineAttributes = { class: 'line' }
|
||||
|
||||
@@ -1087,6 +1120,8 @@ class Editor extends View
|
||||
if invisibles.eol
|
||||
line.push("<span class='invisible'>#{invisibles.eol}</span>")
|
||||
|
||||
line.push("<span class='fold-marker'/>") if fold
|
||||
|
||||
line.push('</pre>')
|
||||
line.join('')
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ class Fold
|
||||
@displayBuffer.unregisterFold(@startRow, this)
|
||||
return
|
||||
|
||||
@updateStartRow(event)
|
||||
@updateEndRow(event)
|
||||
@startRow += @getRowDelta(event, @startRow)
|
||||
@endRow += @getRowDelta(event, @endRow)
|
||||
|
||||
if @startRow != oldStartRow
|
||||
@displayBuffer.unregisterFold(oldStartRow, this)
|
||||
@@ -49,26 +49,12 @@ class Fold
|
||||
isContainedByFold: (fold) ->
|
||||
@isContainedByRange(fold.getBufferRange())
|
||||
|
||||
updateStartRow: (event) ->
|
||||
getRowDelta: (event, row) ->
|
||||
{ newRange, oldRange } = event
|
||||
|
||||
if oldRange.end.row < @startRow
|
||||
delta = newRange.end.row - oldRange.end.row
|
||||
else if newRange.end.row < @startRow
|
||||
delta = newRange.end.row - @startRow
|
||||
if oldRange.end.row <= row
|
||||
newRange.end.row - oldRange.end.row
|
||||
else if newRange.end.row < row
|
||||
newRange.end.row - row
|
||||
else
|
||||
delta = 0
|
||||
|
||||
@startRow += delta
|
||||
|
||||
updateEndRow: (event) ->
|
||||
{ newRange, oldRange } = event
|
||||
|
||||
if oldRange.end.row <= @endRow
|
||||
delta = newRange.end.row - oldRange.end.row
|
||||
else if newRange.end.row <= @endRow
|
||||
delta = newRange.end.row - @endRow
|
||||
else
|
||||
delta = 0
|
||||
|
||||
@endRow += delta
|
||||
0
|
||||
|
||||
@@ -58,16 +58,19 @@ class Gutter extends View
|
||||
@renderLineNumbers(renderFrom, renderTo) if performUpdate
|
||||
|
||||
renderLineNumbers: (startScreenRow, endScreenRow) ->
|
||||
rows = @editor().bufferRowsForScreenRows(startScreenRow, endScreenRow)
|
||||
editor = @editor()
|
||||
rows = editor.bufferRowsForScreenRows(startScreenRow, endScreenRow)
|
||||
|
||||
cursorScreenRow = @editor().getCursorScreenPosition().row
|
||||
cursorScreenRow = editor.getCursorScreenPosition().row
|
||||
@lineNumbers[0].innerHTML = $$$ ->
|
||||
for row in rows
|
||||
if row == lastScreenRow
|
||||
rowValue = '•'
|
||||
else
|
||||
rowValue = row + 1
|
||||
@div {class: 'line-number'}, rowValue
|
||||
classes = ['line-number']
|
||||
classes.push('fold') if editor.isFoldedAtBufferRow(row)
|
||||
@div rowValue, class: classes.join(' ')
|
||||
lastScreenRow = row
|
||||
|
||||
@calculateWidth()
|
||||
|
||||
@@ -35,7 +35,7 @@ class Keymap
|
||||
@loadDirectory(fs.join(config.configDirPath, 'keymaps'))
|
||||
|
||||
loadDirectory: (directoryPath) ->
|
||||
@load(filePath) for filePath in fs.list(directoryPath)
|
||||
@load(filePath) for filePath in fs.list(directoryPath, ['.cson', '.json'])
|
||||
|
||||
load: (path) ->
|
||||
@add(fs.readObject(path))
|
||||
|
||||
@@ -38,3 +38,5 @@
|
||||
'meta-P': 'editor:close-all-edit-sessions'
|
||||
'meta-L': 'editor:select-grammar'
|
||||
'ctrl-C': 'editor:copy-path'
|
||||
'ctrl-meta-up': 'editor:move-line-up'
|
||||
'ctrl-meta-down': 'editor:move-line-down'
|
||||
|
||||
@@ -133,6 +133,7 @@ class LineMap
|
||||
new Range(start, end)
|
||||
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
screenRange = Range.fromObject(screenRange)
|
||||
start = @bufferPositionForScreenPosition(screenRange.start)
|
||||
end = @bufferPositionForScreenPosition(screenRange.end)
|
||||
new Range(start, end)
|
||||
@@ -141,4 +142,3 @@ class LineMap
|
||||
for row in [start..end]
|
||||
line = @lineForScreenRow(row).text
|
||||
console.log row, line, line.length
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Task = require 'Task'
|
||||
Task = require 'task'
|
||||
|
||||
module.exports =
|
||||
class LoadTextMatePackagesTask extends Task
|
||||
|
||||
@@ -11,6 +11,14 @@ class Point
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
@min: (point1, point2) ->
|
||||
point1 = @fromObject(point1)
|
||||
point2 = @fromObject(point2)
|
||||
if point1.isLessThanOrEqual(point2)
|
||||
point1
|
||||
else
|
||||
point2
|
||||
|
||||
constructor: (@row=0, @column=0) ->
|
||||
|
||||
copy: ->
|
||||
@@ -26,6 +34,10 @@ class Point
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
translate: (other) ->
|
||||
other = Point.fromObject(other)
|
||||
new Point(@row + other.row, @column + other.column)
|
||||
|
||||
splitAt: (column) ->
|
||||
if @row == 0
|
||||
rightColumn = @column - column
|
||||
|
||||
@@ -48,6 +48,9 @@ class Range
|
||||
add: (point) ->
|
||||
new Range(@start.add(point), @end.add(point))
|
||||
|
||||
translate: (startPoint, endPoint=startPoint) ->
|
||||
new Range(@start.translate(startPoint), @end.translate(endPoint))
|
||||
|
||||
intersectsWith: (otherRange) ->
|
||||
if @start.isLessThanOrEqual(otherRange.start)
|
||||
@end.isGreaterThanOrEqual(otherRange.start)
|
||||
|
||||
@@ -96,7 +96,10 @@ class Selection
|
||||
@screenRangeChanged()
|
||||
|
||||
selectWord: ->
|
||||
@setBufferRange(@cursor.getCurrentWordBufferRange())
|
||||
options = {}
|
||||
options.wordRegex = /[\t ]*/ if @cursor.isSurroundedByWhitespace()
|
||||
|
||||
@setBufferRange(@cursor.getCurrentWordBufferRange(options))
|
||||
@wordwise = true
|
||||
@initialScreenRange = @getScreenRange()
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
DeferredAtomPackage = require 'deferred-atom-package'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class CommandLogger extends DeferredAtomPackage
|
||||
@@ -7,4 +8,25 @@ class CommandLogger extends DeferredAtomPackage
|
||||
|
||||
instanceClass: 'command-logger/src/command-logger-view'
|
||||
|
||||
onLoadEvent: (event, instance) -> instance.toggle()
|
||||
activate: (rootView, state={})->
|
||||
super
|
||||
|
||||
@eventLog = state.eventLog ? {}
|
||||
rootView.command 'command-logger:clear-data', => @eventLog = {}
|
||||
|
||||
registerTriggeredEvent = (eventName) =>
|
||||
eventNameLog = @eventLog[eventName]
|
||||
unless eventNameLog
|
||||
eventNameLog =
|
||||
count: 0
|
||||
name: eventName
|
||||
@eventLog[eventName] = eventNameLog
|
||||
eventNameLog.count++
|
||||
eventNameLog.lastRun = new Date().getTime()
|
||||
originalTrigger = $.fn.trigger
|
||||
$.fn.trigger = (eventName) ->
|
||||
eventName = eventName.type if eventName.type
|
||||
registerTriggeredEvent(eventName) if $(this).events()[eventName]
|
||||
originalTrigger.apply(this, arguments)
|
||||
|
||||
onLoadEvent: (event, instance) -> instance.toggle(@eventLog)
|
||||
|
||||
@@ -6,9 +6,8 @@ describe "CommandLogger", ->
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
atom.loadPackage('command-logger').getInstance()
|
||||
commandLogger = atom.loadPackage('command-logger')
|
||||
editor = rootView.getActiveEditor()
|
||||
commandLogger = CommandLogger.instance
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
@@ -44,9 +43,11 @@ describe "CommandLogger", ->
|
||||
|
||||
describe "when an event is ignored", ->
|
||||
it "does not create a node for that event", ->
|
||||
commandLogger.ignoredEvents.push 'editor:delete-line'
|
||||
commandLoggerView = commandLogger.getInstance()
|
||||
commandLoggerView.ignoredEvents.push 'editor:delete-line'
|
||||
editor.trigger 'editor:delete-line'
|
||||
nodes = commandLogger.createNodes()
|
||||
commandLoggerView.eventLog = commandLogger.eventLog
|
||||
nodes = commandLoggerView.createNodes()
|
||||
for node in nodes
|
||||
continue unless node.name is 'Editor'
|
||||
for child in node.children
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{$$$} = require 'space-pen'
|
||||
ScrollView = require 'scroll-view'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class CommandLoggerView extends ScrollView
|
||||
@activate: (rootView, state) ->
|
||||
@instance = new CommandLoggerView(rootView, state?.eventLog)
|
||||
@instance = new CommandLoggerView(rootView)
|
||||
|
||||
@content: (rootView) ->
|
||||
@div class: 'command-logger', tabindex: -1, =>
|
||||
@@ -31,29 +30,13 @@ class CommandLoggerView extends ScrollView
|
||||
'tree-view:directory-modified'
|
||||
]
|
||||
|
||||
initialize: (@rootView, @eventLog={}) ->
|
||||
initialize: (@rootView) ->
|
||||
super
|
||||
|
||||
@rootView.command 'command-logger:clear-data', => @eventLog = {}
|
||||
@command 'core:cancel', => @detach()
|
||||
@on 'blur', => @detach() unless document.activeElement is this[0]
|
||||
|
||||
registerEvent = (eventName) =>
|
||||
eventNameLog = @eventLog[eventName]
|
||||
unless eventNameLog
|
||||
eventNameLog =
|
||||
count: 0
|
||||
name: eventName
|
||||
@eventLog[eventName] = eventNameLog
|
||||
eventNameLog.count++
|
||||
eventNameLog.lastRun = new Date().getTime()
|
||||
|
||||
originalTrigger = $.fn.trigger
|
||||
$.fn.trigger = (eventName) ->
|
||||
eventName = eventName.type if eventName.type
|
||||
registerEvent(eventName) if $(this).events()[eventName]
|
||||
originalTrigger.apply(this, arguments)
|
||||
|
||||
toggle: ->
|
||||
toggle: (@eventLog={}) ->
|
||||
if @hasParent()
|
||||
@detach()
|
||||
else
|
||||
@@ -198,8 +181,11 @@ class CommandLoggerView extends ScrollView
|
||||
@focus()
|
||||
|
||||
detach: ->
|
||||
super()
|
||||
return if @detaching
|
||||
@detaching = true
|
||||
super
|
||||
@rootView.focus()
|
||||
@detaching = false
|
||||
|
||||
serialize: ->
|
||||
eventLog: @eventLog
|
||||
|
||||
@@ -438,13 +438,13 @@ describe "CommandPanel", ->
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
|
||||
|
||||
describe "when core:confirm is triggered on the preview list", ->
|
||||
it "opens the operation's buffer, selects and scrolls to the search result, and focuses the active editor", ->
|
||||
it "opens the operation's buffer, selects and scrolls to the search result, and refocuses the preview list", ->
|
||||
rootView.height(200)
|
||||
rootView.attachToDom()
|
||||
|
||||
waitsForPromise -> commandPanel.execute('X x/apply/') # use apply because it is at the end of the file
|
||||
runs ->
|
||||
spyOn(rootView, 'focus')
|
||||
spyOn(previewList, 'focus')
|
||||
executeHandler = jasmine.createSpy('executeHandler')
|
||||
commandPanel.on 'core:confirm', executeHandler
|
||||
|
||||
@@ -458,13 +458,13 @@ describe "CommandPanel", ->
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(editor.isScreenRowVisible(editor.getCursorScreenRow())).toBeTruthy()
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
expect(previewList.focus).toHaveBeenCalled()
|
||||
|
||||
expect(executeHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when an operation in the preview list is clicked", ->
|
||||
it "opens the operation's buffer, selects the search result, and focuses the active editor", ->
|
||||
spyOn(rootView, 'focus')
|
||||
it "opens the operation's buffer, selects the search result, and refocuses the preview list", ->
|
||||
spyOn(previewList, 'focus')
|
||||
operation = previewList.getOperations()[4]
|
||||
|
||||
previewList.find('li.operation:eq(4) span').mousedown()
|
||||
@@ -473,4 +473,4 @@ describe "CommandPanel", ->
|
||||
editSession = rootView.getActiveEditSession()
|
||||
expect(editSession.buffer.getPath()).toBe project.resolve(operation.getPath())
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
expect(previewList.focus).toHaveBeenCalled()
|
||||
|
||||
@@ -51,7 +51,7 @@ class CommandPanelView extends View
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
@errorMessages.hide()
|
||||
@prompt.iconSize(@miniEditor.fontSize)
|
||||
@prompt.iconSize(@miniEditor.getFontSize())
|
||||
|
||||
serialize: ->
|
||||
text: @miniEditor.getText()
|
||||
|
||||
@@ -83,7 +83,7 @@ class PreviewList extends ScrollView
|
||||
editSession = @rootView.open(operation.getPath())
|
||||
bufferRange = operation.execute(editSession)
|
||||
editSession.setSelectedBufferRange(bufferRange, autoscroll: true) if bufferRange
|
||||
@rootView.focus()
|
||||
@focus()
|
||||
false
|
||||
|
||||
getPathCount: ->
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
window.keymap.bindKeys '.editor'
|
||||
'.editor':
|
||||
'tab': 'snippets:expand'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# it's critical that these bindings be loaded after those snippets-1 so they
|
||||
# are later in the cascade, hence breaking the keymap into 2 files
|
||||
|
||||
window.keymap.bindKeys '.editor'
|
||||
'.editor':
|
||||
'tab': 'snippets:next-tab-stop'
|
||||
'shift-tab': 'snippets:previous-tab-stop'
|
||||
|
||||
@@ -277,6 +277,7 @@ describe "Snippets extension", ->
|
||||
|
||||
it "terminates the worker when loading completes", ->
|
||||
jasmine.unspy(LoadSnippetsTask.prototype, 'loadAtomSnippets')
|
||||
spyOn(console, "warn")
|
||||
spyOn(Worker.prototype, 'terminate').andCallThrough()
|
||||
snippets.loaded = false
|
||||
snippets.loadAll()
|
||||
@@ -284,6 +285,8 @@ describe "Snippets extension", ->
|
||||
waitsFor "all snippets to load", 5000, -> snippets.loaded
|
||||
|
||||
runs ->
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
expect(console.warn.argsForCall[0]).toMatch /Error reading snippets file '.*?\/spec\/fixtures\/packages\/package-with-snippets\/snippets\/junk-file'/
|
||||
expect(Worker.prototype.terminate).toHaveBeenCalled()
|
||||
expect(Worker.prototype.terminate.calls.length).toBe 1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Task = require 'Task'
|
||||
Task = require 'task'
|
||||
TextMatePackage = require 'text-mate-package'
|
||||
|
||||
module.exports =
|
||||
|
||||
@@ -5,7 +5,7 @@ Tabs = require 'tabs'
|
||||
fs = require 'fs'
|
||||
|
||||
describe "Tabs", ->
|
||||
[rootView, editor, statusBar, buffer, tabs] = []
|
||||
[rootView, editor, buffer, tabs] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
@@ -118,3 +118,21 @@ describe "Tabs", ->
|
||||
tabs.find('.tab .close-icon:eq(1)').click()
|
||||
expect(editor.getActiveEditSessionIndex()).toBe 0
|
||||
expect(editor.activeEditSession).toBe firstSession
|
||||
|
||||
describe "when two tabs have the same file name", ->
|
||||
[tempPath] = []
|
||||
|
||||
beforeEach ->
|
||||
tempPath = '/tmp/sample.js'
|
||||
fs.write(tempPath, 'sample')
|
||||
|
||||
afterEach ->
|
||||
fs.remove(tempPath) if fs.exists(tempPath)
|
||||
|
||||
it "displays the parent folder name after the file name", ->
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe 'sample.js'
|
||||
rootView.open(tempPath)
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe 'sample.js - fixtures'
|
||||
expect(tabs.find('.tab:last .file-name').text()).toBe 'sample.js - tmp'
|
||||
editor.destroyActiveEditSession()
|
||||
expect(tabs.find('.tab:eq(0) .file-name').text()).toBe 'sample.js'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
|
||||
module.exports =
|
||||
class Tab extends View
|
||||
@@ -7,12 +8,14 @@ class Tab extends View
|
||||
@span class: 'file-name', outlet: 'fileName'
|
||||
@span class: 'close-icon'
|
||||
|
||||
initialize: (@editSession) ->
|
||||
initialize: (@editSession, @editor) ->
|
||||
@buffer = @editSession.buffer
|
||||
@subscribe @buffer, 'path-changed', => @updateFileName()
|
||||
@subscribe @buffer, 'contents-modified', => @updateModifiedStatus()
|
||||
@subscribe @buffer, 'saved', => @updateModifiedStatus()
|
||||
@subscribe @buffer, 'git-status-changed', => @updateModifiedStatus()
|
||||
@subscribe @editor, 'editor:edit-session-added', => @updateFileName()
|
||||
@subscribe @editor, 'editor:edit-session-removed', => @updateFileName()
|
||||
@updateFileName()
|
||||
@updateModifiedStatus()
|
||||
|
||||
@@ -25,4 +28,14 @@ class Tab extends View
|
||||
@isModified = false
|
||||
|
||||
updateFileName: ->
|
||||
@fileName.text(@editSession.buffer.getBaseName() ? 'untitled')
|
||||
fileNameText = @editSession.buffer.getBaseName()
|
||||
if fileNameText?
|
||||
duplicates = @editor.getEditSessions().filter (session) -> fileNameText is session.buffer.getBaseName()
|
||||
if duplicates.length > 1
|
||||
directory = fs.base(fs.directory(@editSession.getPath()))
|
||||
fileNameText = "#{fileNameText} - #{directory}" if directory
|
||||
else
|
||||
fileNameText = 'untitled'
|
||||
|
||||
@fileName.text(fileNameText)
|
||||
@fileName.attr('title', @editSession.getPath())
|
||||
|
||||
@@ -34,7 +34,7 @@ class Tabs extends View
|
||||
false
|
||||
|
||||
addTabForEditSession: (editSession) ->
|
||||
@append(new Tab(editSession))
|
||||
@append(new Tab(editSession, @editor))
|
||||
|
||||
setActiveTab: (index) ->
|
||||
@find(".tab.active").removeClass('active')
|
||||
|
||||
@@ -761,7 +761,7 @@ describe "TreeView", ->
|
||||
|
||||
expect(addDialog.miniEditor.getText().length).toBe 0
|
||||
|
||||
describe "tree-view:move", ->
|
||||
fdescribe "tree-view:move", ->
|
||||
describe "when a file is selected", ->
|
||||
moveDialog = null
|
||||
|
||||
@@ -770,6 +770,9 @@ describe "TreeView", ->
|
||||
treeView.trigger "tree-view:move"
|
||||
moveDialog = rootView.find(".tree-view-dialog").view()
|
||||
|
||||
afterEach ->
|
||||
waits 50 # The move specs cause too many false positives because of their async nature, so wait a little bit before we cleanup
|
||||
|
||||
it "opens a move dialog with the file's current path (excluding extension) populated", ->
|
||||
extension = fs.extension(filePath)
|
||||
fileNameWithoutExtension = fs.base(filePath, extension)
|
||||
|
||||
@@ -59,11 +59,16 @@ module.exports =
|
||||
|
||||
# Returns an array with all the names of files contained
|
||||
# in the directory path.
|
||||
list: (rootPath) ->
|
||||
list: (rootPath, extensions) ->
|
||||
paths = []
|
||||
onPath = (path) =>
|
||||
paths.push(@join(rootPath, path))
|
||||
false
|
||||
if extensions
|
||||
onPath = (path) =>
|
||||
paths.push(@join(rootPath, path)) if _.contains(extensions, @extension(path))
|
||||
false
|
||||
else
|
||||
onPath = (path) =>
|
||||
paths.push(@join(rootPath, path))
|
||||
false
|
||||
@traverseTree(rootPath, onPath, onPath)
|
||||
paths
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@ $.fn.pageUp = ->
|
||||
$.fn.pageDown = ->
|
||||
@scrollTop(@scrollTop() + @height())
|
||||
|
||||
$.fn.isOnDom = ->
|
||||
@closest(document.body).length is 1
|
||||
|
||||
$.fn.containsElement = (element) ->
|
||||
(element[0].compareDocumentPosition(this[0]) & 8) == 8
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
|
||||
.editor .underlayer, .editor .lines, .editor .overlayer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -103,4 +102,4 @@
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.editor {
|
||||
font-family: Inconsolata, Monaco, Courier;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.editor.mini {
|
||||
@@ -17,7 +18,7 @@
|
||||
}
|
||||
|
||||
.editor .gutter .line-number {
|
||||
padding-right: 1.3em;
|
||||
padding-right: .5em;
|
||||
min-width: 35px;
|
||||
box-sizing: border-box;
|
||||
text-align: right;
|
||||
@@ -43,12 +44,37 @@
|
||||
-webkit-animation-iteration-count: 1;
|
||||
}
|
||||
|
||||
.editor .fold {
|
||||
background-color: #444;
|
||||
.editor .gutter .line-number.fold {
|
||||
color: #fba0e3;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.editor .fold.selected {
|
||||
background-color: #244;
|
||||
.editor .gutter .line-number.fold.cursor-line {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.editor .gutter .line-number:after {
|
||||
font-size: 0.8em;
|
||||
content: '\f078';
|
||||
font-family: 'Octicons Regular';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #fba0e3;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.editor .gutter .line-number.fold:after {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.editor .fold-marker:after {
|
||||
content: '\2026';
|
||||
opacity: .8;
|
||||
color: #fba0e3;
|
||||
padding-left: .2em;
|
||||
}
|
||||
|
||||
.editor .line.cursor-line .fold-marker {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.editor .invisible {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.editor {
|
||||
font-family: Inconsolata, Monaco, Courier;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.editor.mini {
|
||||
@@ -20,7 +21,7 @@
|
||||
}
|
||||
|
||||
.editor .gutter .line-number {
|
||||
padding-right: 1.3em;
|
||||
padding-right: .5em;
|
||||
min-width: 35px;
|
||||
box-sizing: border-box;
|
||||
text-align: right;
|
||||
@@ -46,12 +47,37 @@
|
||||
-webkit-animation-iteration-count: 1;
|
||||
}
|
||||
|
||||
.editor .fold {
|
||||
background-color: #444;
|
||||
.editor .gutter .line-number.fold {
|
||||
color: #fba0e3;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.editor .fold.selected {
|
||||
background-color: #244;
|
||||
.editor .gutter .line-number.fold.cursor-line {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.editor .gutter .line-number:after {
|
||||
font-size: 0.8em;
|
||||
content: '\f078';
|
||||
font-family: 'Octicons Regular';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #fba0e3;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.editor .gutter .line-number.fold:after {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.editor .fold-marker:after {
|
||||
content: '\2026';
|
||||
opacity: .8;
|
||||
color: #fba0e3;
|
||||
padding-left: .2em;
|
||||
}
|
||||
|
||||
.editor .line.cursor-line .fold-marker {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.editor .invisible {
|
||||
|
||||
4
vendor/jasmine-console-reporter.js
vendored
4
vendor/jasmine-console-reporter.js
vendored
@@ -31,7 +31,9 @@ jasmine.ConsoleReporter.prototype.reportSpecResults = function(spec) {
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
if (this.logErrors && result.type == 'expect' && result.passed && !result.passed()) {
|
||||
console.log("ERROR: " + spec.getFullName())
|
||||
message = spec.getFullName()
|
||||
console.log("\n\n" + message)
|
||||
console.log((new Array(message.length + 1)).join('-'))
|
||||
if (result.trace.stack) {
|
||||
console.log(result.trace.stack)
|
||||
}
|
||||
|
||||
1
vendor/packages/python.tmbundle
vendored
Submodule
1
vendor/packages/python.tmbundle
vendored
Submodule
Submodule vendor/packages/python.tmbundle added at 3675c22ae8
Reference in New Issue
Block a user