Comparar commits
117 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| f0d3a06655 | |||
| 0ce67b307c | |||
| 598cdea22a | |||
| 32d23d6303 | |||
| 3279a575f6 | |||
| 16ffbd1920 | |||
| 9180060920 | |||
| fdae5fd89c | |||
| 8e218de3e7 | |||
| a6c89b75fc | |||
| 15cf475d04 | |||
| b56f4a129f | |||
| 0d8a6782b3 | |||
| fe219ed159 | |||
| 6ee24cc50e | |||
| 5a84814e27 | |||
| 994138c7a6 | |||
| df6809e705 | |||
| 71aa9802d5 | |||
| 8b98a7793d | |||
| b4cbffd978 | |||
| 53dde09523 | |||
| 8af73449fe | |||
| d2b513bd5e | |||
| c54766a08a | |||
| 8a7aa8083c | |||
| d1a26b9f81 | |||
| 655fec2f18 | |||
| 2d5bb8bd8b | |||
| bd7542cb0a | |||
| f06c9a5bc8 | |||
| 9f85ba4f7d | |||
| b878be27a0 | |||
| 1b98bf706e | |||
| c923b561e2 | |||
| e72e1c9c56 | |||
| ecad6bc2a8 | |||
| cedea831f7 | |||
| 1b4fbdb065 | |||
| c5cd39308d | |||
| 083e6f26bd | |||
| 15f95cb2a3 | |||
| b6d1f37249 | |||
| 232978ea9d | |||
| 5afe0a758c | |||
| d3fa5b0f85 | |||
| ad0bcc3851 | |||
| b110f430ee | |||
| 7993e3ab39 | |||
| 540c543984 | |||
| af02d9f0fd | |||
| 36d0b2c735 | |||
| 7518864938 | |||
| 2d00d3e07e | |||
| 0d520e9930 | |||
| b70ff1b164 | |||
| ba6d3a1124 | |||
| ac65e288df | |||
| c5e34c60f8 | |||
| 5a291e8188 | |||
| ab5156c5e3 | |||
| 360a3076a8 | |||
| 0af9564d1a | |||
| 21f83ea938 | |||
| 81c1769770 | |||
| 0620d19f26 | |||
| 46acb6da2c | |||
| e8a66ded01 | |||
| c90579956f | |||
| d857cc7d77 | |||
| 495230435f | |||
| 707ed3c51a | |||
| 027bada7d5 | |||
| 58add85f09 | |||
| 7359101bac | |||
| 4e787ceb43 | |||
| ff76911e4c | |||
| f0cddf9f32 | |||
| c32c894d23 | |||
| 422d89a7ed | |||
| 5e0dd80366 | |||
| bfbdfb46a8 | |||
| 91e3fbd2d8 | |||
| 6c640133f1 | |||
| bb287cb465 | |||
| 252159afcf | |||
| 6c43fd5c9d | |||
| 2f60ffcfce | |||
| 8980a97895 | |||
| 160b80b47f | |||
| df064ddd21 | |||
| 9d2d3d5c00 | |||
| f62e81bca8 | |||
| ab1b90804e | |||
| 9fe264ded4 | |||
| 0e3f9297fb | |||
| 7fdfd71382 | |||
| bb40ad6177 | |||
| e3295059a0 | |||
| 4940439f4b | |||
| dccd5ec8ba | |||
| 0ca1204b89 | |||
| c8d76edea1 | |||
| 1d9aa7c5e1 | |||
| 3a05731f2d | |||
| 9c7ff78fc8 | |||
| 89fe8e1628 | |||
| 7e0ac1db9c | |||
| 20073c9d34 | |||
| 4fdc9fba63 | |||
| 0d78098dbf | |||
| ee31114b32 | |||
| 0f623b3d08 | |||
| 1ac55413d9 | |||
| 60f945aafd | |||
| ca3b0c97da | |||
| c50b7fd99e |
@@ -1,3 +1,13 @@
|
||||
* Fixed: Atom always running in dev mode
|
||||
* Fixed: Crash when running in dev mode without a path to the Atom source
|
||||
|
||||
* Fixed: Freeze when editing a RoR class
|
||||
* Added: meta-N to open a new untitled editor in the current window
|
||||
|
||||
* Fixed: Styling in command logger
|
||||
* Added: XML and Ruby syntax highlighting in Markdown files
|
||||
* Fixed: Error when editing files in a HEAD-less Git repository
|
||||
|
||||
* Fixed: Invisible characters not being visible when enabled
|
||||
* Added: Editor gutter now displays Git status for lines
|
||||
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ ATOM_PATH=/Applications/Atom.app
|
||||
|
||||
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 [ ! -d $ATOM_PATH ]; then
|
||||
echo "Atom application not found at '$ATOM_PATH'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ keymap.bindKeys '*',
|
||||
'meta-w': 'close'
|
||||
'alt-meta-i': 'show-console'
|
||||
$(document).on 'close', -> window.close()
|
||||
$(document).on 'show-console', -> atom.toggleDevTools()
|
||||
|
||||
defaultCount = 100
|
||||
window.pbenchmark = (args...) -> window.benchmark(args..., profile: true)
|
||||
|
||||
@@ -154,7 +154,7 @@ its own namespace.
|
||||
### Glossary of Config Keys
|
||||
|
||||
- core
|
||||
- disablePackages: An array of package names to disable
|
||||
- disabledPackages: An array of package names to disable
|
||||
- hideGitIgnoredFiles: Whether files in the .gitignore should be hidden
|
||||
- ignoredNames: File names to ignore across all of atom (not fully implemented)
|
||||
- themes: An array of theme names to load, in cascading order
|
||||
|
||||
@@ -20,6 +20,7 @@ class AtomCefClient;
|
||||
- (void)open:(NSString *)path;
|
||||
- (void)openDev:(NSString *)path;
|
||||
- (void)open:(NSString *)path pidToKillWhenWindowCloses:(NSNumber *)pid;
|
||||
- (void)openConfig;
|
||||
- (IBAction)runSpecs:(id)sender;
|
||||
- (IBAction)runBenchmarks:(id)sender;
|
||||
- (void)runSpecsThenExit:(BOOL)exitWhenDone;
|
||||
|
||||
@@ -191,6 +191,16 @@
|
||||
[[AtomWindowController alloc] initDevWithPath:path];
|
||||
}
|
||||
|
||||
- (void)openConfig {
|
||||
for (NSWindow *window in [self windows]) {
|
||||
if ([[window windowController] isConfig]) {
|
||||
[window makeKeyAndOrderFront:nil];
|
||||
return;
|
||||
}
|
||||
}
|
||||
[[AtomWindowController alloc] initConfig];
|
||||
}
|
||||
|
||||
- (IBAction)runSpecs:(id)sender {
|
||||
[self runSpecsThenExit:NO];
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ bool AtomCefClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
else if (name == "newWindow") {
|
||||
NewWindow();
|
||||
}
|
||||
else if (name == "openConfig") {
|
||||
OpenConfig();
|
||||
}
|
||||
else if (name == "toggleDevTools") {
|
||||
ToggleDevTools(browser);
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ class AtomCefClient : public CefClient,
|
||||
void OpenDev(std::string path);
|
||||
void OpenDev();
|
||||
void NewWindow();
|
||||
void OpenConfig();
|
||||
void ToggleDevTools(CefRefPtr<CefBrowser> browser);
|
||||
void ShowDevTools(CefRefPtr<CefBrowser> browser);
|
||||
void Confirm(int replyId,
|
||||
|
||||
@@ -74,6 +74,10 @@ void AtomCefClient::NewWindow() {
|
||||
[(AtomApplication *)[AtomApplication sharedApplication] open:nil];
|
||||
}
|
||||
|
||||
void AtomCefClient::OpenConfig() {
|
||||
[(AtomApplication *)[AtomApplication sharedApplication] openConfig];
|
||||
}
|
||||
|
||||
void AtomCefClient::Confirm(int replyId,
|
||||
std::string message,
|
||||
std::string detailedMessage,
|
||||
|
||||
@@ -18,19 +18,24 @@ class AtomCefClient;
|
||||
|
||||
BOOL _runningSpecs;
|
||||
BOOL _exitWhenDone;
|
||||
BOOL _isConfig;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) IBOutlet NSSplitView *splitView;
|
||||
@property (nonatomic, retain) IBOutlet NSView *webView;
|
||||
@property (nonatomic, retain) IBOutlet NSView *devToolsView;
|
||||
@property (nonatomic, retain) NSString *pathToOpen;
|
||||
@property (nonatomic) BOOL isConfig;
|
||||
|
||||
- (id)initWithPath:(NSString *)path;
|
||||
- (id)initDevWithPath:(NSString *)path;
|
||||
- (id)initInBackground;
|
||||
- (id)initConfig;
|
||||
- (id)initSpecsThenExit:(BOOL)exitWhenDone;
|
||||
- (id)initBenchmarksThenExit:(BOOL)exitWhenDone;
|
||||
- (void)setPidToKillOnClose:(NSNumber *)pid;
|
||||
- (BOOL)isDevMode;
|
||||
- (BOOL)isDevFlagSpecified;
|
||||
|
||||
- (void)toggleDevTools;
|
||||
- (void)showDevTools;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
@synthesize webView=_webView;
|
||||
@synthesize devToolsView=_devToolsView;
|
||||
@synthesize pathToOpen=_pathToOpen;
|
||||
@synthesize isConfig=_isConfig;
|
||||
|
||||
- (void)dealloc {
|
||||
[_splitView release];
|
||||
@@ -33,10 +34,7 @@
|
||||
|
||||
AtomApplication *atomApplication = (AtomApplication *)[AtomApplication sharedApplication];
|
||||
|
||||
if (useBundleResourcePath) {
|
||||
_resourcePath = [[NSBundle bundleForClass:self.class] resourcePath];
|
||||
}
|
||||
else {
|
||||
if (!useBundleResourcePath) {
|
||||
_resourcePath = [[atomApplication.arguments objectForKey:@"resource-path"] stringByStandardizingPath];
|
||||
if (!_resourcePath) {
|
||||
NSString *defaultRepositoryPath = [@"~/github/atom" stringByStandardizingPath];
|
||||
@@ -52,6 +50,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_resourcePath) {
|
||||
_resourcePath = [[NSBundle bundleForClass:self.class] resourcePath];
|
||||
}
|
||||
|
||||
if ([self isDevMode]) {
|
||||
[self displayDevIcon];
|
||||
@@ -95,6 +96,12 @@
|
||||
[self setWindowFrameAutosaveName:@"AtomWindow"];
|
||||
NSColor *background = [NSColor colorWithDeviceRed:(51.0/255.0) green:(51.0/255.0f) blue:(51.0/255.0f) alpha:1.0];
|
||||
[self.window setBackgroundColor:background];
|
||||
if (self.isConfig) {
|
||||
NSRect frame = self.window.frame;
|
||||
frame.size.width = 800;
|
||||
frame.size.height = 600;
|
||||
[self.window setFrame:frame display: YES];
|
||||
}
|
||||
[self showWindow:self];
|
||||
}
|
||||
|
||||
@@ -103,9 +110,7 @@
|
||||
|
||||
- (id)initWithPath:(NSString *)path {
|
||||
_pathToOpen = [path retain];
|
||||
AtomApplication *atomApplication = (AtomApplication *)[AtomApplication sharedApplication];
|
||||
BOOL useBundleResourcePath = [atomApplication.arguments objectForKey:@"dev"] == nil;
|
||||
return [self initWithBootstrapScript:@"window-bootstrap" background:NO useBundleResourcePath:useBundleResourcePath];
|
||||
return [self initWithBootstrapScript:@"window-bootstrap" background:NO useBundleResourcePath:![self isDevFlagSpecified]];
|
||||
}
|
||||
|
||||
- (id)initDevWithPath:(NSString *)path {
|
||||
@@ -114,10 +119,7 @@
|
||||
}
|
||||
|
||||
- (id)initInBackground {
|
||||
AtomApplication *atomApplication = (AtomApplication *)[AtomApplication sharedApplication];
|
||||
BOOL useBundleResourcePath = [atomApplication.arguments objectForKey:@"dev"] == nil;
|
||||
|
||||
[self initWithBootstrapScript:@"window-bootstrap" background:YES useBundleResourcePath:useBundleResourcePath];
|
||||
[self initWithBootstrapScript:@"window-bootstrap" background:YES useBundleResourcePath:![self isDevFlagSpecified]];
|
||||
[self.window setFrame:NSMakeRect(0, 0, 0, 0) display:NO];
|
||||
[self.window setExcludedFromWindowsMenu:YES];
|
||||
[self.window setCollectionBehavior:NSWindowCollectionBehaviorStationary];
|
||||
@@ -136,6 +138,11 @@
|
||||
return [self initWithBootstrapScript:@"benchmark-bootstrap" background:NO useBundleResourcePath:NO];
|
||||
}
|
||||
|
||||
- (id)initConfig {
|
||||
_isConfig = true;
|
||||
return [self initWithBootstrapScript:@"config-bootstrap" background:NO useBundleResourcePath:![self isDevMode]];
|
||||
}
|
||||
|
||||
- (void)addBrowserToView:(NSView *)view url:(const char *)url cefHandler:(CefRefPtr<AtomCefClient>)cefClient {
|
||||
CefBrowserSettings settings;
|
||||
[self populateBrowserSettings:settings];
|
||||
@@ -271,11 +278,16 @@
|
||||
[_devButton setHidden:NO];
|
||||
}
|
||||
|
||||
- (bool)isDevMode {
|
||||
- (BOOL)isDevMode {
|
||||
NSString *bundleResourcePath = [[NSBundle bundleForClass:self.class] resourcePath];
|
||||
return ![_resourcePath isEqualToString:bundleResourcePath];
|
||||
}
|
||||
|
||||
- (BOOL)isDevFlagSpecified {
|
||||
AtomApplication *atomApplication = (AtomApplication *)[AtomApplication sharedApplication];
|
||||
return [atomApplication.arguments objectForKey:@"dev"] != nil;
|
||||
}
|
||||
|
||||
- (void)displayDevIcon {
|
||||
NSView *themeFrame = [self.window.contentView superview];
|
||||
NSButton *fullScreenButton = nil;
|
||||
|
||||
+3
-2
@@ -7,7 +7,7 @@
|
||||
"ctags": "0.3.0",
|
||||
"oniguruma": "0.11.0",
|
||||
"mkdirp": "0.3.5",
|
||||
"git-utils": "0.14.0",
|
||||
"git-utils": "0.15.0",
|
||||
"underscore": "1.4.4",
|
||||
"d3": "3.0.8",
|
||||
"coffee-cache": "0.1.0",
|
||||
@@ -18,7 +18,8 @@
|
||||
"pathwatcher": "0.3.0",
|
||||
"plist": "git://github.com/nathansobo/node-plist.git",
|
||||
"space-pen": "git://github.com/nathansobo/space-pen.git",
|
||||
"less": "git://github.com/nathansobo/less.js.git"
|
||||
"less": "git://github.com/nathansobo/less.js.git",
|
||||
"jqueryui-browser": "1.10.2-1"
|
||||
},
|
||||
|
||||
"devDependencies" : {
|
||||
|
||||
@@ -181,6 +181,18 @@ describe "the `atom` global", ->
|
||||
atom.activatePackage('ruby.tmbundle', sync: true)
|
||||
expect(syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBe '# '
|
||||
|
||||
describe ".activatePackageConfig(id)", ->
|
||||
it "calls the optional .activateConfigMenu method on the package's main module", ->
|
||||
pack = atom.activatePackageConfig('package-with-activate-config')
|
||||
expect(pack.mainModule.activateCalled).toBeFalsy()
|
||||
expect(pack.mainModule.activateConfigCalled).toBeTruthy()
|
||||
|
||||
it "loads the package's config defaults", ->
|
||||
expect(config.get('package-with-config-defaults.numbers.one')).toBeUndefined()
|
||||
atom.activatePackageConfig('package-with-config-defaults')
|
||||
expect(config.get('package-with-config-defaults.numbers.one')).toBe 1
|
||||
expect(config.get('package-with-config-defaults.numbers.two')).toBe 2
|
||||
|
||||
describe ".deactivatePackage(id)", ->
|
||||
describe "atom packages", ->
|
||||
it "calls `deactivate` on the package's main module", ->
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
ConfigPanel = require 'config-panel'
|
||||
Editor = require 'editor'
|
||||
|
||||
describe "ConfigPanel", ->
|
||||
it "automatically binds named input fields to their corresponding config keys", ->
|
||||
class TestPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@div =>
|
||||
@input outlet: 'intInput', id: 'foo.int', type: 'int'
|
||||
@input outlet: 'floatInput', id: 'foo.float', type: 'float'
|
||||
@input outlet: 'stringInput', id: 'foo.string', type: 'string'
|
||||
@input outlet: 'booleanInput', id: 'foo.boolean', type: 'checkbox'
|
||||
|
||||
config.set('foo.int', 22)
|
||||
config.set('foo.boolean', true)
|
||||
|
||||
panel = new TestPanel
|
||||
expect(panel.intInput.val()).toBe '22'
|
||||
expect(panel.floatInput.val()).toBe ''
|
||||
expect(panel.stringInput.val()).toBe ''
|
||||
expect(panel.booleanInput.attr('checked')).toBeTruthy()
|
||||
|
||||
config.set('foo.int', 10)
|
||||
expect(panel.intInput.val()).toBe '10'
|
||||
expect(panel.floatInput.val()).toBe ''
|
||||
expect(panel.stringInput.val()).toBe ''
|
||||
|
||||
config.set('foo.string', 'hey')
|
||||
expect(panel.intInput.val()).toBe '10'
|
||||
expect(panel.floatInput.val()).toBe ''
|
||||
expect(panel.stringInput.val()).toBe 'hey'
|
||||
|
||||
config.set('foo.boolean', false)
|
||||
expect(panel.booleanInput.attr('checked')).toBeFalsy()
|
||||
|
||||
panel.intInput.val('90.2').change()
|
||||
expect(config.get('foo.int')).toBe 90
|
||||
|
||||
panel.floatInput.val('90.2').change()
|
||||
expect(config.get('foo.float')).toBe 90.2
|
||||
|
||||
panel.stringInput.val('moo').change()
|
||||
expect(config.get('foo.string')).toBe 'moo'
|
||||
|
||||
it "automatically binds named editors to their corresponding config keys", ->
|
||||
class TestPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@div =>
|
||||
@subview 'intEditor', new Editor(mini: true, attributes: { id: 'foo.int', type: 'int' })
|
||||
@subview 'floatEditor', new Editor(mini: true, attributes: { id: 'foo.float', type: 'float' })
|
||||
@subview 'stringEditor', new Editor(mini: true, attributes: { id: 'foo.string', type: 'string' })
|
||||
|
||||
config.set('foo.int', 1)
|
||||
config.set('foo.float', 1.1)
|
||||
config.set('foo.string', 'I think therefore I am.')
|
||||
panel = new TestPanel
|
||||
expect(panel.intEditor.getText()).toBe '1'
|
||||
expect(panel.floatEditor.getText()).toBe '1.1'
|
||||
expect(panel.stringEditor.getText()).toBe 'I think therefore I am.'
|
||||
|
||||
config.set('foo.int', 2)
|
||||
config.set('foo.float', 2.2)
|
||||
config.set('foo.string', 'We are what we think.')
|
||||
expect(panel.intEditor.getText()).toBe '2'
|
||||
expect(panel.floatEditor.getText()).toBe '2.2'
|
||||
expect(panel.stringEditor.getText()).toBe 'We are what we think.'
|
||||
|
||||
panel.intEditor.setText('3')
|
||||
panel.floatEditor.setText('3.3')
|
||||
panel.stringEditor.setText('All limitations are self imposed.')
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(config.get('foo.int')).toBe 3
|
||||
expect(config.get('foo.float')).toBe 3.3
|
||||
expect(config.get('foo.string')).toBe 'All limitations are self imposed.'
|
||||
|
||||
panel.intEditor.setText('not an int')
|
||||
panel.floatEditor.setText('not a float')
|
||||
panel.stringEditor.setText('')
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(config.get('foo.int')).toBe 0
|
||||
expect(config.get('foo.float')).toBe 0
|
||||
expect(config.get('foo.string')).toBe undefined
|
||||
@@ -100,6 +100,11 @@ describe "Config", ->
|
||||
config.set('foo.bar.baz', "value 1")
|
||||
expect(observeHandler).toHaveBeenCalledWith("value 1")
|
||||
|
||||
it "fires the callback when the observed value is deleted", ->
|
||||
observeHandler.reset() # clear the initial call
|
||||
config.set('foo.bar.baz', undefined)
|
||||
expect(observeHandler).toHaveBeenCalledWith(undefined)
|
||||
|
||||
it "fires the callback when the full key path goes into and out of existence", ->
|
||||
observeHandler.reset() # clear the initial call
|
||||
config.set("foo.bar", undefined)
|
||||
@@ -110,7 +115,7 @@ describe "Config", ->
|
||||
config.set("foo.bar.baz", "i'm back")
|
||||
expect(observeHandler).toHaveBeenCalledWith("i'm back")
|
||||
|
||||
describe "initializeConfigDirectory()", ->
|
||||
describe ".initializeConfigDirectory()", ->
|
||||
beforeEach ->
|
||||
config.configDirPath = '/tmp/dot-atom-dir'
|
||||
expect(fsUtils.exists(config.configDirPath)).toBeFalsy()
|
||||
@@ -148,20 +153,76 @@ describe "Config", ->
|
||||
expect(fsUtils.isFile(fsUtils.join(config.configDirPath, 'themes/atom-dark-syntax.css'))).toBeTruthy()
|
||||
expect(fsUtils.isFile(fsUtils.join(config.configDirPath, 'themes/atom-light-syntax.css'))).toBeTruthy()
|
||||
|
||||
describe "when the config file is not parseable", ->
|
||||
describe ".loadUserConfig()", ->
|
||||
beforeEach ->
|
||||
config.configDirPath = '/tmp/dot-atom-dir'
|
||||
config.configFilePath = fsUtils.join(config.configDirPath, "config.cson")
|
||||
expect(fsUtils.exists(config.configDirPath)).toBeFalsy()
|
||||
config.configDirPath = '/tmp/dot-atom-dir'
|
||||
config.configFilePath = fsUtils.join(config.configDirPath, "config.cson")
|
||||
expect(fsUtils.exists(config.configDirPath)).toBeFalsy()
|
||||
|
||||
afterEach ->
|
||||
fsUtils.remove('/tmp/dot-atom-dir') if fsUtils.exists('/tmp/dot-atom-dir')
|
||||
|
||||
it "logs an error to the console and does not overwrite the config file", ->
|
||||
config.save.reset()
|
||||
spyOn(console, 'error')
|
||||
fsUtils.write(config.configFilePath, "{{{{{")
|
||||
describe "when the config file contains valid cson", ->
|
||||
beforeEach ->
|
||||
fsUtils.write(config.configFilePath, "foo: bar: 'baz'")
|
||||
config.loadUserConfig()
|
||||
|
||||
it "updates the config data based on the file contents", ->
|
||||
expect(config.get("foo.bar")).toBe 'baz'
|
||||
|
||||
describe "when the config file contains invalid cson", ->
|
||||
beforeEach ->
|
||||
spyOn(console, 'error')
|
||||
fsUtils.write(config.configFilePath, "{{{{{")
|
||||
|
||||
it "logs an error to the console and does not overwrite the config file on a subsequent save", ->
|
||||
config.loadUserConfig()
|
||||
expect(console.error).toHaveBeenCalled()
|
||||
config.set("hair", "blonde") # trigger a save
|
||||
expect(config.save).not.toHaveBeenCalled()
|
||||
|
||||
describe ".observeUserConfig()", ->
|
||||
updatedHandler = null
|
||||
|
||||
beforeEach ->
|
||||
config.configDirPath = '/tmp/dot-atom-dir'
|
||||
config.configFilePath = fsUtils.join(config.configDirPath, "config.cson")
|
||||
expect(fsUtils.exists(config.configDirPath)).toBeFalsy()
|
||||
fsUtils.write(config.configFilePath, "foo: bar: 'baz'")
|
||||
config.loadUserConfig()
|
||||
config.set("hair", "blonde") # trigger a save
|
||||
expect(console.error).toHaveBeenCalled()
|
||||
expect(config.save).not.toHaveBeenCalled()
|
||||
config.observeUserConfig()
|
||||
updatedHandler = jasmine.createSpy("updatedHandler")
|
||||
config.on 'updated', updatedHandler
|
||||
|
||||
afterEach ->
|
||||
config.unobserveUserConfig()
|
||||
fsUtils.remove('/tmp/dot-atom-dir') if fsUtils.exists('/tmp/dot-atom-dir')
|
||||
|
||||
describe "when the config file changes to contain valid cson", ->
|
||||
it "updates the config data", ->
|
||||
fsUtils.write(config.configFilePath, "foo: { bar: 'quux', baz: 'bar'}")
|
||||
waitsFor 'update event', -> updatedHandler.callCount > 0
|
||||
runs ->
|
||||
expect(config.get('foo.bar')).toBe 'quux'
|
||||
expect(config.get('foo.baz')).toBe 'bar'
|
||||
|
||||
describe "when the config file changes to contain invalid cson", ->
|
||||
beforeEach ->
|
||||
spyOn(console, 'error')
|
||||
fsUtils.write(config.configFilePath, "}}}")
|
||||
waitsFor "error to be logged", -> console.error.callCount > 0
|
||||
|
||||
it "logs a warning and does not update config data", ->
|
||||
expect(updatedHandler.callCount).toBe 0
|
||||
expect(config.get('foo.bar')).toBe 'baz'
|
||||
config.set("hair", "blonde") # trigger a save
|
||||
expect(config.save).not.toHaveBeenCalled()
|
||||
|
||||
describe "when the config file subsequently changes again to contain valid cson", ->
|
||||
beforeEach ->
|
||||
fsUtils.write(config.configFilePath, "foo: bar: 'baz'")
|
||||
waitsFor 'update event', -> updatedHandler.callCount > 0
|
||||
|
||||
it "updates the config data and resumes saving", ->
|
||||
config.set("hair", "blonde")
|
||||
expect(config.save).toHaveBeenCalled()
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
ConfigView = require 'config-view'
|
||||
{$$} = require 'space-pen'
|
||||
|
||||
describe "ConfigView", ->
|
||||
configView = null
|
||||
|
||||
beforeEach ->
|
||||
configView = new ConfigView
|
||||
|
||||
describe "serialization", ->
|
||||
it "remembers which panel was visible", ->
|
||||
configView.showPanel('Editor')
|
||||
newConfigView = deserialize(configView.serialize())
|
||||
configView.remove()
|
||||
newConfigView.attachToDom()
|
||||
expect(newConfigView.activePanelName).toBe 'Editor'
|
||||
|
||||
it "shows the previously active panel if it is added after deserialization", ->
|
||||
configView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
|
||||
configView.showPanel('Panel 1')
|
||||
newConfigView = deserialize(configView.serialize())
|
||||
configView.remove()
|
||||
newConfigView.attachToDom()
|
||||
newConfigView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
|
||||
expect(newConfigView.activePanelName).toBe 'Panel 1'
|
||||
|
||||
describe ".addPanel(name, view)", ->
|
||||
it "adds a menu entry to the left and a panel that can be activated by clicking it", ->
|
||||
configView.addPanel('Panel 1', $$ -> @div id: 'panel-1')
|
||||
configView.addPanel('Panel 2', $$ -> @div id: 'panel-2')
|
||||
|
||||
expect(configView.panelMenu.find('li a:contains(Panel 1)')).toExist()
|
||||
expect(configView.panelMenu.find('li a:contains(Panel 2)')).toExist()
|
||||
expect(configView.panelMenu.children(':first')).toHaveClass 'active'
|
||||
|
||||
configView.attachToDom()
|
||||
configView.panelMenu.find('li a:contains(Panel 1)').click()
|
||||
expect(configView.panelMenu.children('.active').length).toBe 1
|
||||
expect(configView.panelMenu.find('li:contains(Panel 1)')).toHaveClass('active')
|
||||
expect(configView.panels.find('#panel-1')).toBeVisible()
|
||||
expect(configView.panels.find('#panel-2')).toBeHidden()
|
||||
configView.panelMenu.find('li a:contains(Panel 2)').click()
|
||||
expect(configView.panelMenu.children('.active').length).toBe 1
|
||||
expect(configView.panelMenu.find('li:contains(Panel 2)')).toHaveClass('active')
|
||||
expect(configView.panels.find('#panel-1')).toBeHidden()
|
||||
expect(configView.panels.find('#panel-2')).toBeVisible()
|
||||
@@ -3,24 +3,24 @@ Buffer = require 'text-buffer'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "DisplayBuffer", ->
|
||||
[editSession, displayBuffer, buffer, changeHandler, tabLength] = []
|
||||
[displayBuffer, buffer, changeHandler, tabLength] = []
|
||||
beforeEach ->
|
||||
tabLength = 2
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
editSession = project.buildEditSession('sample.js', { tabLength })
|
||||
{ buffer, displayBuffer } = editSession
|
||||
changeHandler = jasmine.createSpy 'changeHandler'
|
||||
displayBuffer.on 'changed', changeHandler
|
||||
buffer = project.bufferForPath('sample.js')
|
||||
displayBuffer = new DisplayBuffer(buffer, { tabLength })
|
||||
displayBuffer.on 'changed', changeHandler = jasmine.createSpy 'changeHandler'
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
displayBuffer.destroy()
|
||||
buffer.release()
|
||||
|
||||
describe "when the buffer changes", ->
|
||||
it "renders line numbers correctly", ->
|
||||
originalLineCount = displayBuffer.lineCount()
|
||||
originalLineCount = displayBuffer.getLineCount()
|
||||
oneHundredLines = [0..100].join("\n")
|
||||
buffer.insert([0,0], oneHundredLines)
|
||||
expect(displayBuffer.lineCount()).toBe 100 + originalLineCount
|
||||
expect(displayBuffer.getLineCount()).toBe 100 + originalLineCount
|
||||
|
||||
describe "soft wrapping", ->
|
||||
beforeEach ->
|
||||
@@ -60,9 +60,8 @@ describe "DisplayBuffer", ->
|
||||
describe "when whitespace is added after the max line length", ->
|
||||
it "adds whitespace to the end of the current line and wraps an empty line", ->
|
||||
fiftyCharacters = _.multiplyString("x", 50)
|
||||
editSession.buffer.setText(fiftyCharacters)
|
||||
editSession.setCursorBufferPosition([0, 51])
|
||||
editSession.insertText(" ")
|
||||
buffer.setText(fiftyCharacters)
|
||||
buffer.insert([0, 51], " ")
|
||||
|
||||
describe "when the update makes a soft-wrapped line shorter than the max line length", ->
|
||||
it "rewraps the line and emits a change event", ->
|
||||
@@ -142,100 +141,14 @@ describe "DisplayBuffer", ->
|
||||
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 0, end: 15, screenDelta: 3, bufferDelta: 0)
|
||||
|
||||
describe "structural folding", ->
|
||||
describe ".unfoldAll()", ->
|
||||
it "unfolds every folded line", ->
|
||||
displayBuffer.foldBufferRow(0)
|
||||
displayBuffer.foldBufferRow(1)
|
||||
|
||||
displayBuffer.unfoldAll()
|
||||
expect(Object.keys(displayBuffer.activeFolds).length).toBe 0
|
||||
|
||||
describe ".foldAll()", ->
|
||||
it "folds every foldable line", ->
|
||||
displayBuffer.foldAll()
|
||||
fold = displayBuffer.lineForRow(0).fold
|
||||
expect(fold).toBeDefined()
|
||||
expect([fold.startRow, fold.endRow]).toEqual [0,12]
|
||||
|
||||
expect(Object.keys(displayBuffer.activeFolds).length).toBe(3)
|
||||
expect(displayBuffer.activeFolds[1].length).toBe(1)
|
||||
expect(displayBuffer.activeFolds[4].length).toBe(1)
|
||||
|
||||
it "doesn't fold lines that are already folded", ->
|
||||
displayBuffer.foldBufferRow(4)
|
||||
displayBuffer.foldAll()
|
||||
expect(Object.keys(displayBuffer.activeFolds).length).toBe(3)
|
||||
expect(displayBuffer.activeFolds[0].length).toBe(1)
|
||||
expect(displayBuffer.activeFolds[1].length).toBe(1)
|
||||
expect(displayBuffer.activeFolds[4].length).toBe(1)
|
||||
|
||||
describe ".foldBufferRow(bufferRow)", ->
|
||||
describe "when bufferRow can be folded", ->
|
||||
it "creates a fold based on the syntactic region starting at the given row", ->
|
||||
displayBuffer.foldBufferRow(1)
|
||||
fold = displayBuffer.lineForRow(1).fold
|
||||
expect(fold.startRow).toBe 1
|
||||
expect(fold.endRow).toBe 9
|
||||
|
||||
describe "when bufferRow can't be folded", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", ->
|
||||
displayBuffer.foldBufferRow(8)
|
||||
fold = displayBuffer.lineForRow(1).fold
|
||||
expect(fold.startRow).toBe 1
|
||||
expect(fold.endRow).toBe 9
|
||||
|
||||
describe "when the bufferRow is already folded", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
|
||||
displayBuffer.foldBufferRow(2)
|
||||
expect(displayBuffer.lineForRow(1).fold).toBeDefined()
|
||||
expect(displayBuffer.lineForRow(0).fold).not.toBeDefined()
|
||||
|
||||
displayBuffer.foldBufferRow(1)
|
||||
expect(displayBuffer.lineForRow(0).fold).toBeDefined()
|
||||
|
||||
describe "when the bufferRow is in a multi-line comment", ->
|
||||
it "searches upward and downward for surrounding comment lines and folds them as a single fold", ->
|
||||
buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment")
|
||||
displayBuffer.foldBufferRow(1)
|
||||
fold = displayBuffer.lineForRow(1).fold
|
||||
expect(fold.startRow).toBe 1
|
||||
expect(fold.endRow).toBe 3
|
||||
|
||||
describe "when the bufferRow is a single-line comment", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
|
||||
buffer.insert([1,0], " //this is a single line comment\n")
|
||||
displayBuffer.foldBufferRow(1)
|
||||
fold = displayBuffer.lineForRow(0).fold
|
||||
expect(fold.startRow).toBe 0
|
||||
expect(fold.endRow).toBe 13
|
||||
|
||||
describe ".unfoldBufferRow(bufferRow)", ->
|
||||
describe "when bufferRow can be unfolded", ->
|
||||
it "destroys a fold based on the syntactic region starting at the given row", ->
|
||||
displayBuffer.foldBufferRow(1)
|
||||
expect(displayBuffer.lineForRow(1).fold).toBeDefined()
|
||||
|
||||
displayBuffer.unfoldBufferRow(1)
|
||||
expect(displayBuffer.lineForRow(1).fold).toBeUndefined()
|
||||
|
||||
describe "when bufferRow can't be unfolded", ->
|
||||
it "does not throw an error", ->
|
||||
expect(displayBuffer.lineForRow(1).fold).toBeUndefined()
|
||||
displayBuffer.unfoldBufferRow(1)
|
||||
expect(displayBuffer.lineForRow(1).fold).toBeUndefined()
|
||||
|
||||
describe "primitive folding", ->
|
||||
editSession2 = null
|
||||
|
||||
beforeEach ->
|
||||
editSession2 = project.buildEditSession('two-hundred.txt')
|
||||
{ buffer, displayBuffer } = editSession2
|
||||
displayBuffer.destroy()
|
||||
buffer.release()
|
||||
buffer = project.bufferForPath('two-hundred.txt')
|
||||
displayBuffer = new DisplayBuffer(buffer, { tabLength })
|
||||
displayBuffer.on 'changed', changeHandler
|
||||
|
||||
afterEach ->
|
||||
editSession2.destroy()
|
||||
|
||||
describe "when folds are created and destroyed", ->
|
||||
describe "when a fold spans multiple lines", ->
|
||||
it "replaces the lines spanned by the fold with a placeholder that references the fold object", ->
|
||||
@@ -530,20 +443,6 @@ 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)
|
||||
@@ -617,7 +516,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
describe "markers", ->
|
||||
beforeEach ->
|
||||
displayBuffer.foldBufferRow(4)
|
||||
displayBuffer.createFold(4, 7)
|
||||
|
||||
describe "marker creation and manipulation", ->
|
||||
it "allows markers to be created in terms of both screen and buffer coordinates", ->
|
||||
@@ -690,7 +589,7 @@ describe "DisplayBuffer", ->
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
displayBuffer.unfoldBufferRow(4)
|
||||
displayBuffer.destroyFoldsContainingBufferRow(4)
|
||||
expect(observeHandler).toHaveBeenCalled()
|
||||
expect(observeHandler.argsForCall[0][0]).toEqual {
|
||||
oldHeadScreenPosition: [8, 23]
|
||||
@@ -706,7 +605,7 @@ describe "DisplayBuffer", ->
|
||||
}
|
||||
observeHandler.reset()
|
||||
|
||||
displayBuffer.foldBufferRow(4)
|
||||
displayBuffer.createFold(4, 7)
|
||||
expect(observeHandler).toHaveBeenCalled()
|
||||
expect(observeHandler.argsForCall[0][0]).toEqual {
|
||||
oldHeadScreenPosition: [11, 23]
|
||||
@@ -793,7 +692,7 @@ describe "DisplayBuffer", ->
|
||||
it "allows observation subscriptions to be cancelled", ->
|
||||
subscription.cancel()
|
||||
displayBuffer.setMarkerHeadScreenPosition(marker, [8, 20])
|
||||
displayBuffer.unfoldBufferRow(4)
|
||||
displayBuffer.destroyFoldsContainingBufferRow(4)
|
||||
expect(observeHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "updates the position of markers before emitting buffer change events, but does not notify their observers until the change event", ->
|
||||
@@ -822,7 +721,7 @@ describe "DisplayBuffer", ->
|
||||
expect(displayBuffer.getMarkerTailScreenPosition(marker)).toEqual [8, 4]
|
||||
displayBuffer.on 'changed', changeHandler
|
||||
|
||||
displayBuffer.unfoldBufferRow(4)
|
||||
displayBuffer.destroyFoldsContainingBufferRow(4)
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
expect(observeHandler).toHaveBeenCalled()
|
||||
|
||||
@@ -2111,11 +2111,89 @@ describe "EditSession", ->
|
||||
expect(cursor3.getBufferPosition()).toEqual [1,2]
|
||||
|
||||
describe "folding", ->
|
||||
describe "structural folding", ->
|
||||
it "maintains cursor buffer position when a fold is created/destroyed", ->
|
||||
editSession.setCursorBufferPosition([5,5])
|
||||
describe ".unfoldAll()", ->
|
||||
it "unfolds every folded line", ->
|
||||
initialScreenLineCount = editSession.getScreenLineCount()
|
||||
editSession.foldBufferRow(0)
|
||||
editSession.foldBufferRow(1)
|
||||
expect(editSession.getScreenLineCount()).toBeLessThan initialScreenLineCount
|
||||
editSession.unfoldAll()
|
||||
expect(editSession.getScreenLineCount()).toBe initialScreenLineCount
|
||||
|
||||
describe ".foldAll()", ->
|
||||
it "folds every foldable line", ->
|
||||
editSession.foldAll()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([5,5])
|
||||
|
||||
fold1 = editSession.lineForScreenRow(0).fold
|
||||
expect([fold1.startRow, fold1.endRow]).toEqual [0, 12]
|
||||
fold1.destroy()
|
||||
|
||||
fold2 = editSession.lineForScreenRow(1).fold
|
||||
expect([fold2.startRow, fold2.endRow]).toEqual [1, 9]
|
||||
fold2.destroy()
|
||||
|
||||
fold3 = editSession.lineForScreenRow(4).fold
|
||||
expect([fold3.startRow, fold3.endRow]).toEqual [4, 7]
|
||||
|
||||
describe ".foldBufferRow(bufferRow)", ->
|
||||
describe "when bufferRow can be folded", ->
|
||||
it "creates a fold based on the syntactic region starting at the given row", ->
|
||||
editSession.foldBufferRow(1)
|
||||
fold = editSession.lineForScreenRow(1).fold
|
||||
expect(fold.startRow).toBe 1
|
||||
expect(fold.endRow).toBe 9
|
||||
|
||||
describe "when bufferRow can't be folded", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the given buffer row (and folds it)", ->
|
||||
editSession.foldBufferRow(8)
|
||||
fold = editSession.lineForScreenRow(1).fold
|
||||
expect(fold.startRow).toBe 1
|
||||
expect(fold.endRow).toBe 9
|
||||
|
||||
describe "when the bufferRow is already folded", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
|
||||
editSession.foldBufferRow(2)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
|
||||
expect(editSession.lineForScreenRow(0).fold).not.toBeDefined()
|
||||
|
||||
editSession.foldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(0).fold).toBeDefined()
|
||||
|
||||
describe "when the bufferRow is in a multi-line comment", ->
|
||||
it "searches upward and downward for surrounding comment lines and folds them as a single fold", ->
|
||||
buffer.insert([1,0], " //this is a comment\n // and\n //more docs\n\n//second comment")
|
||||
editSession.foldBufferRow(1)
|
||||
fold = editSession.lineForScreenRow(1).fold
|
||||
expect(fold.startRow).toBe 1
|
||||
expect(fold.endRow).toBe 3
|
||||
|
||||
describe "when the bufferRow is a single-line comment", ->
|
||||
it "searches upward for the first row that begins a syntatic region containing the folded row (and folds it)", ->
|
||||
buffer.insert([1,0], " //this is a single line comment\n")
|
||||
editSession.foldBufferRow(1)
|
||||
fold = editSession.lineForScreenRow(0).fold
|
||||
expect(fold.startRow).toBe 0
|
||||
expect(fold.endRow).toBe 13
|
||||
|
||||
describe ".unfoldBufferRow(bufferRow)", ->
|
||||
describe "when bufferRow can be unfolded", ->
|
||||
it "destroys a fold based on the syntactic region starting at the given row", ->
|
||||
editSession.foldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeDefined()
|
||||
|
||||
editSession.unfoldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
|
||||
|
||||
describe "when bufferRow can't be unfolded", ->
|
||||
it "does not throw an error", ->
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
|
||||
editSession.unfoldBufferRow(1)
|
||||
expect(editSession.lineForScreenRow(1).fold).toBeUndefined()
|
||||
|
||||
it "maintains cursor buffer position when a folding/unfolding", ->
|
||||
editSession.setCursorBufferPosition([5,5])
|
||||
editSession.foldAll()
|
||||
expect(editSession.getCursorBufferPosition()).toEqual([5,5])
|
||||
|
||||
describe ".deleteLine()", ->
|
||||
it "deletes the first line when the cursor is there", ->
|
||||
@@ -2194,6 +2272,19 @@ describe "EditSession", ->
|
||||
expect(buffer.lineForRow(6)).toBe(line7)
|
||||
expect(buffer.getLineCount()).toBe(count - 1)
|
||||
|
||||
describe "when the line being deleted preceeds a fold, and 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 ".transpose()", ->
|
||||
it "swaps two characters", ->
|
||||
editSession.buffer.setText("abc")
|
||||
|
||||
@@ -371,7 +371,6 @@ describe "Editor", ->
|
||||
describe "single-click", ->
|
||||
it "re-positions the cursor to the clicked row / column", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
|
||||
|
||||
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [3, 10])
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 3, column: 10)
|
||||
|
||||
@@ -1760,6 +1759,14 @@ describe "Editor", ->
|
||||
miniEditor.setText(" a line with tabs\tand spaces ")
|
||||
expect(miniEditor.renderedLines.find('.line').text()).toBe "#{space}a line with tabs#{tab} and spaces#{space}"
|
||||
|
||||
it "doesn't show the indent guide", ->
|
||||
config.set "editor.showIndentGuide", true
|
||||
miniEditor = new Editor(mini: true)
|
||||
miniEditor.attachToDom()
|
||||
miniEditor.setText(" and indented line")
|
||||
expect(miniEditor.renderedLines.find('.indent-guide').length).toBe 0
|
||||
|
||||
|
||||
it "lets you set the grammar", ->
|
||||
miniEditor = new Editor(mini: true)
|
||||
miniEditor.setText("var something")
|
||||
|
||||
@@ -165,6 +165,14 @@ describe "Keymap", ->
|
||||
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 '.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] = []
|
||||
|
||||
|
||||
@@ -8,18 +8,6 @@ describe "LanguageMode", ->
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
|
||||
describe "common behavior", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
editSession = project.buildEditSession('sample.js', autoIndent: false)
|
||||
{ buffer, languageMode } = editSession
|
||||
|
||||
describe "language detection", ->
|
||||
it "uses the file name as the file type if it has no extension", ->
|
||||
jsEditSession = project.buildEditSession('js', autoIndent: false)
|
||||
expect(jsEditSession.languageMode.grammar.name).toBe "JavaScript"
|
||||
jsEditSession.destroy()
|
||||
|
||||
describe "javascript", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
PackageConfigPanel = require 'package-config-panel'
|
||||
|
||||
describe "PackageConfigPanel", ->
|
||||
[panel, configObserver] = []
|
||||
|
||||
beforeEach ->
|
||||
configObserver = jasmine.createSpy("configObserver")
|
||||
observeSubscription = config.observe('core.disabledPackages', configObserver)
|
||||
config.set('core.disabledPackages', ['toml', 'wrap-guide'])
|
||||
configObserver.reset()
|
||||
panel = new PackageConfigPanel
|
||||
|
||||
it "lists all available packages, with an unchecked checkbox next to packages in the core.disabledPackages array", ->
|
||||
treeViewTr = panel.packageTableBody.find("tr[name='tree-view']")
|
||||
expect(treeViewTr).toExist()
|
||||
expect(treeViewTr.find("input[type='checkbox']").attr('checked')).toBeTruthy()
|
||||
|
||||
tomlTr = panel.packageTableBody.find("tr[name='toml']")
|
||||
expect(tomlTr).toExist()
|
||||
expect(tomlTr.find("input[type='checkbox']").attr('checked')).toBeFalsy()
|
||||
|
||||
wrapGuideTr = panel.packageTableBody.find("tr[name='wrap-guide']")
|
||||
expect(wrapGuideTr).toExist()
|
||||
expect(wrapGuideTr.find("input[type='checkbox']").attr('checked')).toBeFalsy()
|
||||
|
||||
describe "when the core.disabledPackages array changes", ->
|
||||
it "updates the checkboxes for newly disabled / enabled packages", ->
|
||||
config.set('core.disabledPackages', ['wrap-guide', 'tree-view'])
|
||||
expect(panel.find("tr[name='tree-view'] input[type='checkbox']").attr('checked')).toBeFalsy()
|
||||
expect(panel.find("tr[name='toml'] input[type='checkbox']").attr('checked')).toBeTruthy()
|
||||
expect(panel.find("tr[name='wrap-guide'] input[type='checkbox']").attr('checked')).toBeFalsy()
|
||||
|
||||
describe "when a checkbox is unchecked", ->
|
||||
it "adds the package name to the disabled packages array", ->
|
||||
panel.find("tr[name='tree-view'] input[type='checkbox']").attr('checked', false).change()
|
||||
expect(configObserver).toHaveBeenCalledWith(['toml', 'wrap-guide', 'tree-view'])
|
||||
|
||||
describe "when a checkbox is checked", ->
|
||||
it "removes the package name from the disabled packages array", ->
|
||||
panel.find("tr[name='toml'] input[type='checkbox']").attr('checked', true).change()
|
||||
expect(configObserver).toHaveBeenCalledWith(['wrap-guide'])
|
||||
@@ -354,3 +354,11 @@ describe "RootView", ->
|
||||
rootView.open(require.resolve('fixtures/sample.txt'))
|
||||
expect(count).toBe 1
|
||||
expect(callbackBuffer).toBe rootView.getActiveView().getBuffer()
|
||||
|
||||
describe "when a 'new-editor' event is triggered", ->
|
||||
it "opens a new untitled editor", ->
|
||||
itemCount = rootView.getActivePane().getItems().length
|
||||
rootView.trigger 'new-editor'
|
||||
expect(rootView.getActivePaneItem().getPath()).toBeUndefined()
|
||||
expect(rootView.getActivePaneItem().getBuffer().fileExists()).toBeFalsy()
|
||||
expect(rootView.getActivePane().getItems().length).toBe itemCount + 1
|
||||
|
||||
@@ -487,3 +487,113 @@ describe "TextMateGrammar", ->
|
||||
{tokens} = editSession.lineForScreenRow(0)
|
||||
expect(tokens[2].value).toBe "SELECT"
|
||||
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]
|
||||
|
||||
describe "when the position doesn't advance and rule includes $self and matches itself", ->
|
||||
it "token the entire line using the rule", ->
|
||||
grammar = new TextMateGrammar
|
||||
name: "test"
|
||||
scopeName: "source"
|
||||
repository: {}
|
||||
patterns: [
|
||||
{
|
||||
name: "text"
|
||||
begin: "(?=forever)"
|
||||
end: "whatevs"
|
||||
patterns: [
|
||||
include: "$self"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("forever and ever")
|
||||
|
||||
expect(tokens.length).toBe 1
|
||||
expect(tokens[0].value).toBe "forever and ever"
|
||||
expect(tokens[0].scopes).toEqual ["source", "text"]
|
||||
|
||||
describe "language-specific integration tests", ->
|
||||
lines = null
|
||||
|
||||
describe "Git commit messages", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('git.tmbundle', sync: true)
|
||||
grammar = syntax.selectGrammar('COMMIT_EDITMSG')
|
||||
lines = grammar.tokenizeLines """
|
||||
longggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
# Please enter the commit message for your changes. Lines starting
|
||||
"""
|
||||
|
||||
it "correctly parses a long line", ->
|
||||
tokens = lines[0]
|
||||
expect(tokens[0].value).toBe "longggggggggggggggggggggggggggggggggggggggggggggggg"
|
||||
expect(tokens[0].scopes).toEqual ["text.git-commit", "meta.scope.message.git-commit", "invalid.deprecated.line-too-long.git-commit"]
|
||||
|
||||
it "correctly parses the number sign of the first comment line", ->
|
||||
tokens = lines[1]
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[0].scopes).toEqual ["text.git-commit", "meta.scope.metadata.git-commit", "comment.line.number-sign.git-commit", "punctuation.definition.comment.git-commit"]
|
||||
|
||||
describe "C++", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('c.tmbundle', sync: true)
|
||||
grammar = syntax.selectGrammar('includes.cc')
|
||||
lines = grammar.tokenizeLines """
|
||||
#include "a.h"
|
||||
#include "b.h"
|
||||
"""
|
||||
|
||||
it "correctly parses the first include line", ->
|
||||
tokens = lines[0]
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[0].scopes).toEqual ["source.c++", "meta.preprocessor.c.include"]
|
||||
expect(tokens[1].value).toBe 'include'
|
||||
expect(tokens[1].scopes).toEqual ["source.c++", "meta.preprocessor.c.include", "keyword.control.import.include.c"]
|
||||
|
||||
it "correctly parses the second include line", ->
|
||||
tokens = lines[1]
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[0].scopes).toEqual ["source.c++", "meta.preprocessor.c.include"]
|
||||
expect(tokens[1].value).toBe 'include'
|
||||
expect(tokens[1].scopes).toEqual ["source.c++", "meta.preprocessor.c.include", "keyword.control.import.include.c"]
|
||||
|
||||
describe "Ruby", ->
|
||||
beforeEach ->
|
||||
grammar = syntax.selectGrammar('hello.rb')
|
||||
lines = grammar.tokenizeLines """
|
||||
a = {
|
||||
"b" => "c",
|
||||
}
|
||||
"""
|
||||
|
||||
it "doesn't loop infinitely (regression)", ->
|
||||
expect(_.pluck(lines[0], 'value').join('')).toBe 'a = {'
|
||||
expect(_.pluck(lines[1], 'value').join('')).toBe ' "b" => "c",'
|
||||
expect(_.pluck(lines[2], 'value').join('')).toBe '}'
|
||||
expect(_.pluck(lines[3], 'value').join('')).toBe ''
|
||||
|
||||
describe "Objective-C", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('c.tmbundle', sync: true)
|
||||
atom.activatePackage('objective-c.tmbundle', sync: true)
|
||||
grammar = syntax.selectGrammar('function.mm')
|
||||
lines = grammar.tokenizeLines """
|
||||
void test() {
|
||||
NSString *a = @"a\\nb";
|
||||
}
|
||||
"""
|
||||
|
||||
it "correctly parses variable type when it is a built-in Cocoa class", ->
|
||||
tokens = lines[1]
|
||||
expect(tokens[0].value).toBe "NSString"
|
||||
expect(tokens[0].scopes).toEqual ["source.objc++", "meta.function.c", "meta.block.c", "support.class.cocoa"]
|
||||
|
||||
it "correctly parses the semicolon at the end of the line", ->
|
||||
tokens = lines[1]
|
||||
lastToken = _.last(tokens)
|
||||
expect(lastToken.value).toBe ";"
|
||||
expect(lastToken.scopes).toEqual ["source.objc++", "meta.function.c", "meta.block.c"]
|
||||
|
||||
it "correctly parses the string characters before the escaped character", ->
|
||||
tokens = lines[1]
|
||||
expect(tokens[2].value).toBe '@"'
|
||||
expect(tokens[2].scopes).toEqual ["source.objc++", "meta.function.c", "meta.block.c", "string.quoted.double.objc", "punctuation.definition.string.begin.objc"]
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
$ = require 'jquery'
|
||||
ThemeConfigPanel = require 'theme-config-panel'
|
||||
|
||||
describe "ThemeConfigPanel", ->
|
||||
panel = null
|
||||
|
||||
beforeEach ->
|
||||
config.set('core.themes', ['atom-dark-ui', 'atom-dark-syntax'])
|
||||
panel = new ThemeConfigPanel
|
||||
|
||||
describe "when an enabled theme is reloced in the themes list", ->
|
||||
it "updates the 'core.themes' config key to reflect the new order", ->
|
||||
li = panel.enabledThemes.children(':first').detach()
|
||||
panel.enabledThemes.append(li)
|
||||
panel.enabledThemes.sortable('option', 'update')()
|
||||
expect(config.get('core.themes')).toEqual ['atom-dark-syntax', 'atom-dark-ui']
|
||||
|
||||
describe "when a theme is dragged into the enabled themes list", ->
|
||||
it "updates the 'core.themes' config key to reflect the themes in the enabled list", ->
|
||||
dragHelper = panel.availableThemes.find("li[name='atom-light-ui']").clone()
|
||||
panel.enabledThemes.prepend(dragHelper)
|
||||
panel.enabledThemes.sortable('option', 'receive')(null, helper: dragHelper[0])
|
||||
panel.enabledThemes.sortable('option', 'update')()
|
||||
expect(config.get('core.themes')).toEqual ['atom-light-ui', 'atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
describe "when the theme is already present in the enabled list", ->
|
||||
it "removes the previous instance of the theme, updating the order based on the location of drag", ->
|
||||
dragHelper = panel.availableThemes.find("li[name='atom-dark-ui']").clone()
|
||||
panel.enabledThemes.append(dragHelper)
|
||||
panel.enabledThemes.sortable('option', 'receive')(null, helper: dragHelper[0])
|
||||
panel.enabledThemes.sortable('option', 'update')()
|
||||
expect(config.get('core.themes')).toEqual ['atom-dark-syntax', 'atom-dark-ui']
|
||||
|
||||
dragHelper = panel.availableThemes.find("li[name='atom-dark-ui']").clone()
|
||||
panel.enabledThemes.prepend(dragHelper)
|
||||
panel.enabledThemes.sortable('option', 'receive')(null, helper: dragHelper[0])
|
||||
panel.enabledThemes.sortable('option', 'update')()
|
||||
expect(config.get('core.themes')).toEqual ['atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
describe "when the disable icon is clicked on a theme li", ->
|
||||
it "removes the theme from the list and the 'core.themes' array", ->
|
||||
panel.enabledThemes.find('li:first .disable-theme').click()
|
||||
expect(panel.getEnabledThemeNames()).toEqual ['atom-dark-syntax']
|
||||
expect(config.get('core.themes')).toEqual ['atom-dark-syntax']
|
||||
|
||||
describe "when the 'core.config' key is updated", ->
|
||||
it "refreshes the enabled themes list", ->
|
||||
config.set('core.themes', ['atom-light-ui', 'atom-light-syntax'])
|
||||
expect(panel.getEnabledThemeNames()).toEqual ['atom-light-ui', 'atom-light-syntax']
|
||||
@@ -1,11 +1,10 @@
|
||||
TokenizedBuffer = require 'tokenized-buffer'
|
||||
LanguageMode = require 'language-mode'
|
||||
Buffer = require 'text-buffer'
|
||||
Range = require 'range'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "TokenizedBuffer", ->
|
||||
[editSession, tokenizedBuffer, buffer, changeHandler] = []
|
||||
[tokenizedBuffer, buffer, changeHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
atom.activatePackage('javascript.tmbundle', sync: true)
|
||||
@@ -19,15 +18,14 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
describe "when the buffer contains soft-tabs", ->
|
||||
beforeEach ->
|
||||
editSession = project.buildEditSession('sample.js', autoIndent: false)
|
||||
buffer = editSession.buffer
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
editSession.setVisible(true)
|
||||
changeHandler = jasmine.createSpy('changeHandler')
|
||||
tokenizedBuffer.on "changed", changeHandler
|
||||
buffer = project.bufferForPath('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer(buffer)
|
||||
tokenizedBuffer.setVisible(true)
|
||||
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
tokenizedBuffer.destroy()
|
||||
buffer.release()
|
||||
|
||||
describe "on construction", ->
|
||||
it "initially creates un-tokenized screen lines, then tokenizes lines chunk at a time in the background", ->
|
||||
@@ -300,21 +298,20 @@ describe "TokenizedBuffer", ->
|
||||
describe "when the buffer contains hard-tabs", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('coffee-script-tmbundle', sync: true)
|
||||
tabLength = 2
|
||||
editSession = project.buildEditSession('sample-with-tabs.coffee', { tabLength })
|
||||
buffer = editSession.buffer
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
editSession.setVisible(true)
|
||||
buffer = project.bufferForPath('sample-with-tabs.coffee')
|
||||
tokenizedBuffer = new TokenizedBuffer(buffer)
|
||||
tokenizedBuffer.setVisible(true)
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
tokenizedBuffer.destroy()
|
||||
buffer.release()
|
||||
|
||||
describe "when the buffer is fully tokenized", ->
|
||||
beforeEach ->
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
it "renders each tab as its own atomic token with a value of size tabLength", ->
|
||||
tabAsSpaces = _.multiplyString(' ', editSession.getTabLength())
|
||||
tabAsSpaces = _.multiplyString(' ', tokenizedBuffer.tabLength)
|
||||
screenLine0 = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}"
|
||||
{ tokens } = screenLine0
|
||||
@@ -328,16 +325,15 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "#{tabAsSpaces} buy()#{tabAsSpaces}while supply > demand"
|
||||
|
||||
describe "when the language mode emits a 'grammar-updated' event based on an included grammar being activated", ->
|
||||
describe "when the grammar is updated because a grammar it includes is activated", ->
|
||||
it "retokenizes the buffer", ->
|
||||
atom.activatePackage('ruby.tmbundle', sync: true)
|
||||
atom.activatePackage('ruby-on-rails-tmbundle', sync: true)
|
||||
|
||||
editSession = project.buildEditSession()
|
||||
editSession.setVisible(true)
|
||||
editSession.setGrammar(syntax.selectGrammar('test.erb'))
|
||||
editSession.buffer.setText("<div class='name'><%= User.find(2).full_name %></div>")
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
buffer = project.bufferForPath(null, "<div class='name'><%= User.find(2).full_name %></div>")
|
||||
tokenizedBuffer = new TokenizedBuffer(buffer)
|
||||
tokenizedBuffer.setGrammar(syntax.selectGrammar('test.erb'))
|
||||
tokenizedBuffer.setVisible(true)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
{tokens} = tokenizedBuffer.lineForScreenRow(0)
|
||||
@@ -347,119 +343,3 @@ describe "TokenizedBuffer", ->
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
{tokens} = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
|
||||
|
||||
describe "when a Git commit message file is tokenized", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('git.tmbundle', sync: true)
|
||||
editSession = project.buildEditSession('COMMIT_EDITMSG', autoIndent: false)
|
||||
buffer = editSession.buffer
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
editSession.setVisible(true)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
|
||||
it "correctly parses a long line", ->
|
||||
longLine = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(longLine.text).toBe "longggggggggggggggggggggggggggggggggggggggggggggggg"
|
||||
{ tokens } = longLine
|
||||
|
||||
expect(tokens[0].value).toBe "longggggggggggggggggggggggggggggggggggggggggggggggg"
|
||||
expect(tokens[0].scopes).toEqual ["text.git-commit", "meta.scope.message.git-commit", "invalid.deprecated.line-too-long.git-commit"]
|
||||
|
||||
it "correctly parses the number sign of the first comment line", ->
|
||||
commentLine = tokenizedBuffer.lineForScreenRow(1)
|
||||
expect(commentLine.text).toBe "# Please enter the commit message for your changes. Lines starting"
|
||||
{ tokens } = commentLine
|
||||
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[0].scopes).toEqual ["text.git-commit", "meta.scope.metadata.git-commit", "comment.line.number-sign.git-commit", "punctuation.definition.comment.git-commit"]
|
||||
|
||||
describe "when a C++ source file is tokenized", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('c.tmbundle', sync: true)
|
||||
editSession = project.buildEditSession('includes.cc', autoIndent: false)
|
||||
buffer = editSession.buffer
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
editSession.setVisible(true)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
|
||||
it "correctly parses the first include line", ->
|
||||
longLine = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(longLine.text).toBe '#include "a.h"'
|
||||
{ tokens } = longLine
|
||||
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[0].scopes).toEqual ["source.c++", "meta.preprocessor.c.include"]
|
||||
expect(tokens[1].value).toBe 'include'
|
||||
expect(tokens[1].scopes).toEqual ["source.c++", "meta.preprocessor.c.include", "keyword.control.import.include.c"]
|
||||
|
||||
it "correctly parses the second include line", ->
|
||||
commentLine = tokenizedBuffer.lineForScreenRow(1)
|
||||
expect(commentLine.text).toBe '#include "b.h"'
|
||||
{ tokens } = commentLine
|
||||
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[0].scopes).toEqual ["source.c++", "meta.preprocessor.c.include"]
|
||||
expect(tokens[1].value).toBe 'include'
|
||||
expect(tokens[1].scopes).toEqual ["source.c++", "meta.preprocessor.c.include", "keyword.control.import.include.c"]
|
||||
|
||||
describe "when a Ruby source file is tokenized", ->
|
||||
beforeEach ->
|
||||
editSession = project.buildEditSession('hello.rb', autoIndent: false)
|
||||
buffer = editSession.buffer
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
editSession.setVisible(true)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
|
||||
it "doesn't loop infinitely (regression)", ->
|
||||
expect(tokenizedBuffer.lineForScreenRow(0).text).toBe 'a = {'
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).text).toBe ' "b" => "c",'
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).text).toBe '}'
|
||||
expect(tokenizedBuffer.lineForScreenRow(3).text).toBe ''
|
||||
|
||||
describe "when an Objective-C source file is tokenized", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('c.tmbundle', sync: true)
|
||||
atom.activatePackage('objective-c.tmbundle', sync: true)
|
||||
editSession = project.buildEditSession('function.mm', autoIndent: false)
|
||||
buffer = editSession.buffer
|
||||
tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
|
||||
editSession.setVisible(true)
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
afterEach ->
|
||||
editSession.destroy()
|
||||
|
||||
it "correctly parses variable type when it is a built-in Cocoa class", ->
|
||||
commentLine = tokenizedBuffer.lineForScreenRow(1)
|
||||
expect(commentLine.text).toBe 'NSString *a = @"a\\nb";'
|
||||
{ tokens } = commentLine
|
||||
|
||||
expect(tokens[0].value).toBe "NSString"
|
||||
expect(tokens[0].scopes).toEqual ["source.objc++", "meta.function.c", "meta.block.c", "support.class.cocoa"]
|
||||
|
||||
it "correctly parses the semicolon at the end of the line", ->
|
||||
commentLine = tokenizedBuffer.lineForScreenRow(1)
|
||||
expect(commentLine.text).toBe 'NSString *a = @"a\\nb";'
|
||||
{ tokens } = commentLine
|
||||
|
||||
lastToken = tokens.length - 1
|
||||
expect(lastToken).toBeGreaterThan 0
|
||||
expect(tokens[lastToken].value).toBe ";"
|
||||
expect(tokens[lastToken].scopes).toEqual ["source.objc++", "meta.function.c", "meta.block.c"]
|
||||
|
||||
it "correctly parses the string characters before the escaped character", ->
|
||||
commentLine = tokenizedBuffer.lineForScreenRow(1)
|
||||
expect(commentLine.text).toBe 'NSString *a = @"a\\nb";'
|
||||
{ tokens } = commentLine
|
||||
|
||||
expect(tokens[2].value).toBe '@"'
|
||||
expect(tokens[2].scopes).toEqual ["source.objc++", "meta.function.c", "meta.block.c", "string.quoted.double.objc", "punctuation.definition.string.begin.objc"]
|
||||
|
||||
@@ -8,11 +8,11 @@ describe "Window", ->
|
||||
beforeEach ->
|
||||
spyOn(atom, 'getPathToOpen').andReturn(project.getPath())
|
||||
window.handleWindowEvents()
|
||||
window.deserializeWindowState()
|
||||
window.deserializeEditorWindow()
|
||||
projectPath = project.getPath()
|
||||
|
||||
afterEach ->
|
||||
window.shutdown()
|
||||
window.unloadEditorWindow()
|
||||
$(window).off 'beforeunload'
|
||||
|
||||
describe "when the window is loaded", ->
|
||||
@@ -120,7 +120,7 @@ describe "Window", ->
|
||||
removeStylesheet(cssPath)
|
||||
expect($(document.body).css('font-weight')).not.toBe("bold")
|
||||
|
||||
describe ".shutdown()", ->
|
||||
describe ".unloadEditorWindow()", ->
|
||||
it "saves the serialized state of the window so it can be deserialized after reload", ->
|
||||
projectPath = project.getPath()
|
||||
expect(atom.getWindowState()).toEqual {}
|
||||
@@ -130,7 +130,7 @@ describe "Window", ->
|
||||
projectState = JSON.parse(JSON.stringify(project.serialize()))
|
||||
syntaxState = JSON.parse(JSON.stringify(syntax.serialize()))
|
||||
|
||||
window.shutdown()
|
||||
window.unloadEditorWindow()
|
||||
|
||||
windowState = atom.getWindowState()
|
||||
expect(windowState.rootView).toEqual rootViewState
|
||||
@@ -145,14 +145,14 @@ describe "Window", ->
|
||||
rootView.getActivePane().splitRight()
|
||||
expect(window.rootView.find('.editor').length).toBe 2
|
||||
|
||||
window.shutdown()
|
||||
window.unloadEditorWindow()
|
||||
|
||||
expect(buffer.subscriptionCount()).toBe 0
|
||||
|
||||
it "only serializes window state the first time it is called", ->
|
||||
|
||||
window.shutdown()
|
||||
window.shutdown()
|
||||
window.unloadEditorWindow()
|
||||
window.unloadEditorWindow()
|
||||
expect(atom.saveWindowState.callCount).toBe 1
|
||||
|
||||
describe ".installAtomCommand(commandPath)", ->
|
||||
|
||||
externo
-2
@@ -1,2 +0,0 @@
|
||||
longggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
# Please enter the commit message for your changes. Lines starting
|
||||
externo
-3
@@ -1,3 +0,0 @@
|
||||
void test() {
|
||||
NSString *a = @"a\nb";
|
||||
}
|
||||
externo
-3
@@ -1,3 +0,0 @@
|
||||
a = {
|
||||
"b" => "c",
|
||||
}
|
||||
externo
-2
@@ -1,2 +0,0 @@
|
||||
#include "a.h"
|
||||
#include "b.h"
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports =
|
||||
activate: -> @activateCalled = true
|
||||
activateConfig: -> @activateConfigCalled = true
|
||||
@@ -2,7 +2,7 @@ require 'window'
|
||||
window.setUpEnvironment()
|
||||
|
||||
nakedLoad 'jasmine-jquery'
|
||||
$ = require 'jquery'
|
||||
$ = jQuery = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
Keymap = require 'keymap'
|
||||
Config = require 'config'
|
||||
@@ -23,7 +23,6 @@ keymap.loadBundledKeymaps()
|
||||
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
|
||||
|
||||
$(window).on 'core:close', -> window.close()
|
||||
$(window).on 'toggle-dev-tools', (e) -> atom.toggleDevTools()
|
||||
$('html,body').css('overflow', 'auto')
|
||||
|
||||
jasmine.getEnv().addEqualityTester(_.isEqual) # Use underscore's definition of equality for toEqual assertions
|
||||
@@ -57,6 +56,7 @@ beforeEach ->
|
||||
config.set "editor.fontSize", 16
|
||||
config.set "editor.autoIndent", false
|
||||
config.set "core.disabledPackages", ["package-that-throws-an-exception"]
|
||||
config.save.reset()
|
||||
|
||||
# make editor display updates synchronous
|
||||
spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()
|
||||
|
||||
@@ -31,7 +31,7 @@ describe "underscore extensions", ->
|
||||
expect(_.endsWith("test.txt", ".tx")).toBeFalsy()
|
||||
expect(_.endsWith("test.txt", "test")).toBeFalsy()
|
||||
|
||||
describe "camelize(string)", ->
|
||||
describe "_.camelize(string)", ->
|
||||
it "converts `string` to camel case", ->
|
||||
expect(_.camelize("corey_dale_johnson")).toBe "coreyDaleJohnson"
|
||||
expect(_.camelize("corey-dale-johnson")).toBe "coreyDaleJohnson"
|
||||
@@ -39,14 +39,14 @@ describe "underscore extensions", ->
|
||||
expect(_.camelize("coreyDaleJohnson")).toBe "coreyDaleJohnson"
|
||||
expect(_.camelize("CoreyDaleJohnson")).toBe "CoreyDaleJohnson"
|
||||
|
||||
describe "dasherize(string)", ->
|
||||
describe "_.dasherize(string)", ->
|
||||
it "converts `string` to use dashes", ->
|
||||
expect(_.dasherize("corey_dale_johnson")).toBe "corey-dale-johnson"
|
||||
expect(_.dasherize("coreyDaleJohnson")).toBe "corey-dale-johnson"
|
||||
expect(_.dasherize("CoreyDaleJohnson")).toBe "corey-dale-johnson"
|
||||
expect(_.dasherize("corey-dale-johnson")).toBe "corey-dale-johnson"
|
||||
|
||||
describe "underscore(string)", ->
|
||||
describe "_.underscore(string)", ->
|
||||
it "converts `string` to use underscores", ->
|
||||
expect(_.underscore("corey-dale-johnson")).toBe "corey_dale_johnson"
|
||||
expect(_.underscore("coreyDaleJohnson")).toBe "corey_dale_johnson"
|
||||
@@ -65,3 +65,14 @@ describe "underscore extensions", ->
|
||||
array = ['a', 'b', 'c']
|
||||
_.spliceWithArray(array, 1, 1, ['v', 'w', 'x', 'y', 'z'], 2)
|
||||
expect(array).toEqual ['a', 'v', 'w', 'x', 'y', 'z', 'c']
|
||||
|
||||
describe "_.humanizeEventName(eventName)", ->
|
||||
describe "when no namespace exists", ->
|
||||
it "undasherizes and capitalizes the event name", ->
|
||||
expect(_.humanizeEventName('nonamespace')).toBe 'Nonamespace'
|
||||
expect(_.humanizeEventName('no-name-space')).toBe 'No Name Space'
|
||||
|
||||
describe "when a namespaces exists", ->
|
||||
it "space separates the undasherized/capitalized versions of the namespace and event name", ->
|
||||
expect(_.humanizeEventName('space:final-frontier')).toBe 'Space: Final Frontier'
|
||||
expect(_.humanizeEventName('star-trek:the-next-generation')).toBe 'Star Trek: The Next Generation'
|
||||
|
||||
@@ -37,11 +37,7 @@ class AtomPackage extends Package
|
||||
this
|
||||
|
||||
activate: ({immediate}={}) ->
|
||||
keymap.add(path, map) for [path, map] in @keymaps
|
||||
applyStylesheet(path, content) for [path, content] in @stylesheets
|
||||
syntax.addGrammar(grammar) for grammar in @grammars
|
||||
syntax.addProperties(path, selector, properties) for [path, selector, properties] in @scopedProperties
|
||||
|
||||
@activateResources()
|
||||
if @metadata.activationEvents? and not immediate
|
||||
@subscribeToActivationEvents()
|
||||
else
|
||||
@@ -55,6 +51,18 @@ class AtomPackage extends Package
|
||||
catch e
|
||||
console.warn "Failed to activate package named '#{@name}'", e.stack
|
||||
|
||||
activateConfig: ->
|
||||
@activateResources()
|
||||
if @requireMainModule()
|
||||
config.setDefaults(@name, @mainModule.configDefaults)
|
||||
@mainModule?.activateConfig?()
|
||||
|
||||
activateResources: ->
|
||||
keymap.add(path, map) for [path, map] in @keymaps
|
||||
applyStylesheet(path, content) for [path, content] in @stylesheets
|
||||
syntax.addGrammar(grammar) for grammar in @grammars
|
||||
syntax.addProperties(path, selector, properties) for [path, selector, properties] in @scopedProperties
|
||||
|
||||
loadMetadata: ->
|
||||
if metadataPath = fsUtils.resolveExtension(fsUtils.join(@path, 'package'), ['json', 'cson'])
|
||||
@metadata = CSON.readObject(metadataPath)
|
||||
@@ -101,11 +109,18 @@ class AtomPackage extends Package
|
||||
|
||||
deactivate: ->
|
||||
@unsubscribeFromActivationEvents()
|
||||
@deactivateResources()
|
||||
@mainModule?.deactivate?()
|
||||
|
||||
deactivateConfig: ->
|
||||
@deactivateResources()
|
||||
@mainModule?.deactivateConfig?()
|
||||
|
||||
deactivateResources: ->
|
||||
syntax.removeGrammar(grammar) for grammar in @grammars
|
||||
syntax.removeProperties(path) for [path] in @scopedProperties
|
||||
keymap.remove(path) for [path] in @keymaps
|
||||
removeStylesheet(path) for [path] in @stylesheets
|
||||
@mainModule?.deactivate?()
|
||||
|
||||
requireMainModule: ->
|
||||
return @mainModule if @mainModule
|
||||
|
||||
+35
-7
@@ -57,8 +57,17 @@ _.extend atom,
|
||||
getActivePackages: ->
|
||||
_.clone(@activePackages)
|
||||
|
||||
activatePackageConfigs: ->
|
||||
@activatePackageConfig(pack.path) for pack in @getLoadedPackages()
|
||||
|
||||
activatePackageConfig: (id, options) ->
|
||||
if pack = @loadPackage(id, options)
|
||||
@activePackages.push(pack)
|
||||
pack.activateConfig()
|
||||
pack
|
||||
|
||||
loadPackages: ->
|
||||
@loadPackage(path) for path in @getPackagePaths() when not @isPackageDisabled(path)
|
||||
@loadPackage(path) for path in @getAvailablePackagePaths() when not @isPackageDisabled(path)
|
||||
|
||||
loadPackage: (id, options) ->
|
||||
if @isPackageDisabled(id)
|
||||
@@ -91,19 +100,31 @@ _.extend atom,
|
||||
if path = @resolvePackagePath(id)
|
||||
_.include(config.get('core.disabledPackages') ? [], fsUtils.base(path))
|
||||
|
||||
getPackagePaths: ->
|
||||
getAvailablePackagePaths: ->
|
||||
packagePaths = []
|
||||
for packageDirPath in config.packageDirPaths
|
||||
for packagePath in fsUtils.list(packageDirPath)
|
||||
packagePaths.push(packagePath) if fsUtils.isDirectory(packagePath)
|
||||
_.uniq(packagePaths)
|
||||
|
||||
getAvailablePackageNames: ->
|
||||
fsUtils.base(path) for path in @getAvailablePackagePaths()
|
||||
|
||||
loadThemes: ->
|
||||
themeNames = config.get("core.themes") ? ['atom-dark-ui', 'atom-dark-syntax']
|
||||
themeNames = config.get("core.themes")
|
||||
themeNames = [themeNames] unless _.isArray(themeNames)
|
||||
@loadTheme(themeName) for themeName in themeNames
|
||||
@loadUserStylesheet()
|
||||
|
||||
getAvailableThemePaths: ->
|
||||
themePaths = []
|
||||
for themeDirPath in config.themeDirPaths
|
||||
themePaths.push(fsUtils.list(themeDirPath, ['', '.tmTheme', '.css', 'less'])...)
|
||||
_.uniq(themePaths)
|
||||
|
||||
getAvailableThemeNames: ->
|
||||
fsUtils.base(path).split('.')[0] for path in @getAvailableThemePaths()
|
||||
|
||||
loadTheme: (name) ->
|
||||
@loadedThemes.push Theme.load(name)
|
||||
|
||||
@@ -126,6 +147,9 @@ _.extend atom,
|
||||
newWindow: (args...) ->
|
||||
@sendMessageToBrowserProcess('newWindow', args)
|
||||
|
||||
openConfig: ->
|
||||
@sendMessageToBrowserProcess('openConfig')
|
||||
|
||||
restartRendererProcess: ->
|
||||
@sendMessageToBrowserProcess('restartRendererProcess')
|
||||
|
||||
@@ -239,12 +263,16 @@ _.extend atom,
|
||||
null
|
||||
|
||||
getSavedWindowState: ->
|
||||
if pathToOpen = window.location.params.pathToOpen
|
||||
localStorage[pathToOpen]
|
||||
storageKey = switch @windowMode
|
||||
when 'editor' then window.location.params.pathToOpen
|
||||
when 'config' then 'config'
|
||||
localStorage[storageKey] if storageKey
|
||||
|
||||
saveWindowState: ->
|
||||
if pathToOpen = @getPathToOpen()
|
||||
localStorage[pathToOpen] = JSON.stringify(@getWindowState())
|
||||
storageKey = switch @windowMode
|
||||
when 'editor' then @getPathToOpen()
|
||||
when 'config' then 'config'
|
||||
localStorage[storageKey] = JSON.stringify(@getWindowState())
|
||||
|
||||
update: ->
|
||||
@sendMessageToBrowserProcess('update')
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
$ = require 'jquery'
|
||||
{View} = require 'space-pen'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
module.exports =
|
||||
class ConfigPanel extends View
|
||||
initialize: ->
|
||||
@bindFormFields()
|
||||
@bindEditors()
|
||||
|
||||
bindFormFields: ->
|
||||
for input in @find('input[id]').toArray()
|
||||
do (input) =>
|
||||
input = $(input)
|
||||
name = input.attr('id')
|
||||
type = input.attr('type')
|
||||
@observeConfig name, (value) ->
|
||||
if type is 'checkbox'
|
||||
input.attr('checked', value)
|
||||
else
|
||||
input.val(value) if value
|
||||
input.on 'change', ->
|
||||
value = input.val()
|
||||
config.set name, switch type
|
||||
when 'int'
|
||||
parseInt(value)
|
||||
when 'float'
|
||||
parseFloat(value)
|
||||
when 'checkbox'
|
||||
!!input.attr('checked')
|
||||
else
|
||||
value
|
||||
|
||||
bindEditors: ->
|
||||
for editor in @find('.editor[id]').views()
|
||||
do (editor) =>
|
||||
name = editor.attr('id')
|
||||
type = editor.attr('type')
|
||||
|
||||
@observeConfig name, (value) ->
|
||||
return if value?.toString() == editor.getText()
|
||||
value ?= ""
|
||||
editor.setText(value.toString())
|
||||
|
||||
editor.getBuffer().on 'contents-modified', ->
|
||||
value = editor.getText()
|
||||
if type == 'int' then value = parseInt(value) or 0
|
||||
if type == 'float' then value = parseFloat(value) or 0
|
||||
if value == "" then value = undefined
|
||||
config.set name, value
|
||||
@@ -0,0 +1,69 @@
|
||||
{View, $$} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
GeneralConfigPanel = require 'general-config-panel'
|
||||
EditorConfigPanel = require 'editor-config-panel'
|
||||
ThemeConfigPanel = require 'theme-config-panel'
|
||||
PackageConfigPanel = require 'package-config-panel'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
module.exports =
|
||||
class ConfigView extends View
|
||||
registerDeserializer(this)
|
||||
|
||||
@deserialize: ({activePanelName}) ->
|
||||
view = new ConfigView()
|
||||
view.showPanel(activePanelName)
|
||||
view
|
||||
|
||||
@content: ->
|
||||
@div id: 'config-view', =>
|
||||
@div id: 'config-menu', =>
|
||||
@ul id: 'panels-menu', class: 'nav nav-pills nav-stacked', outlet: 'panelMenu'
|
||||
@button "open .atom", id: 'open-dot-atom', class: 'btn btn-default btn-small'
|
||||
@div id: 'panels', outlet: 'panels'
|
||||
|
||||
initialize: ->
|
||||
@panelsByName = {}
|
||||
document.title = "Atom Configuration"
|
||||
@on 'click', '#panels-menu li a', (e) =>
|
||||
@showPanel($(e.target).closest('li').attr('name'))
|
||||
|
||||
@on 'click', '#open-dot-atom', ->
|
||||
atom.open(config.configDirPath)
|
||||
|
||||
@addPanel('General', new GeneralConfigPanel)
|
||||
@addPanel('Editor', new EditorConfigPanel)
|
||||
@addPanel('Themes', new ThemeConfigPanel)
|
||||
@addPanel('Installed Packages', new PackageConfigPanel)
|
||||
|
||||
addPanel: (name, panel) ->
|
||||
panelItem = $$ -> @li name: name, => @a name
|
||||
@panelMenu.append(panelItem)
|
||||
panel.hide()
|
||||
@panelsByName[name] = panel
|
||||
@panels.append(panel)
|
||||
@showPanel(name) if @getPanelCount() is 1 or @panelToShow is name
|
||||
|
||||
getPanelCount: ->
|
||||
_.values(@panelsByName).length
|
||||
|
||||
showPanel: (name) ->
|
||||
if @panelsByName[name]
|
||||
@panels.children().hide()
|
||||
@panelMenu.children('.active').removeClass('active')
|
||||
@panelsByName[name].show()
|
||||
for editorElement in @panelsByName[name].find(".editor")
|
||||
$(editorElement).view().redraw()
|
||||
@panelMenu.children("[name='#{name}']").addClass('active')
|
||||
@activePanelName = name
|
||||
@panelToShow = null
|
||||
else
|
||||
@panelToShow = name
|
||||
|
||||
serialize: ->
|
||||
deserializer: @constructor.name
|
||||
activePanelName: @activePanelName
|
||||
@@ -4,6 +4,7 @@ EventEmitter = require 'event-emitter'
|
||||
CSON = require 'cson'
|
||||
fs = require 'fs'
|
||||
async = require 'async'
|
||||
pathWatcher = require 'pathwatcher'
|
||||
|
||||
configDirPath = fsUtils.absolute("~/.atom")
|
||||
bundledPackagesDirPath = fsUtils.join(resourcePath, "src/packages")
|
||||
@@ -67,17 +68,28 @@ class Config
|
||||
load: ->
|
||||
@initializeConfigDirectory()
|
||||
@loadUserConfig()
|
||||
@observeUserConfig()
|
||||
|
||||
loadUserConfig: ->
|
||||
if fsUtils.exists(@configFilePath)
|
||||
try
|
||||
userConfig = CSON.readObject(@configFilePath)
|
||||
_.extend(@settings, userConfig)
|
||||
@configFileHasErrors = false
|
||||
@trigger 'updated'
|
||||
catch e
|
||||
@configFileHasErrors = true
|
||||
console.error "Failed to load user config '#{@configFilePath}'", e.message
|
||||
console.error e.stack
|
||||
|
||||
observeUserConfig: ->
|
||||
@watchSubscription ?= pathWatcher.watch @configFilePath, (eventType) =>
|
||||
@loadUserConfig() if eventType is 'change' and @watchSubscription?
|
||||
|
||||
unobserveUserConfig: ->
|
||||
@watchSubscription?.close()
|
||||
@watchSubscription = null
|
||||
|
||||
# Public: Retrieves the setting for the given key.
|
||||
#
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
|
||||
@@ -17,6 +17,7 @@ class Cursor
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
constructor: ({@editSession, @marker}) ->
|
||||
@updateVisibility()
|
||||
@editSession.observeMarker @marker, (e) =>
|
||||
|
||||
@@ -13,7 +13,6 @@ module.exports =
|
||||
class DisplayBuffer
|
||||
@idCounter: 1
|
||||
lineMap: null
|
||||
languageMode: null
|
||||
tokenizedBuffer: null
|
||||
activeFolds: null
|
||||
foldsById: null
|
||||
@@ -25,13 +24,13 @@ class DisplayBuffer
|
||||
|
||||
constructor: (@buffer, options={}) ->
|
||||
@id = @constructor.idCounter++
|
||||
@languageMode = options.languageMode
|
||||
@tokenizedBuffer = new TokenizedBuffer(@buffer, options)
|
||||
@softWrapColumn = options.softWrapColumn ? Infinity
|
||||
@activeFolds = {}
|
||||
@foldsById = {}
|
||||
@markers = {}
|
||||
@buildLineMap()
|
||||
@tokenizedBuffer.on 'grammar-changed', (grammar) => @trigger 'grammar-changed', grammar
|
||||
@tokenizedBuffer.on 'changed', @handleTokenizedBufferChange
|
||||
@buffer.on 'markers-updated', @handleMarkersUpdated
|
||||
|
||||
@@ -97,56 +96,6 @@ class DisplayBuffer
|
||||
bufferRowsForScreenRows: (startRow, endRow) ->
|
||||
@lineMap.bufferRowsForScreenRows(startRow, endRow)
|
||||
|
||||
# Public: Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
for currentRow in [0..@buffer.getLastRow()]
|
||||
[startRow, endRow] = @languageMode.rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
continue unless startRow?
|
||||
|
||||
@createFold(startRow, endRow)
|
||||
|
||||
# Public: Unfolds all the foldable lines in the buffer.
|
||||
unfoldAll: ->
|
||||
for row in [@buffer.getLastRow()..0]
|
||||
@activeFolds[row]?.forEach (fold) => @destroyFold(fold)
|
||||
|
||||
rowRangeForCommentAtBufferRow: (row) ->
|
||||
return unless @tokenizedBuffer.lineForScreenRow(row).isComment()
|
||||
|
||||
startRow = row
|
||||
for currentRow in [row-1..0]
|
||||
break if @buffer.isRowBlank(currentRow)
|
||||
break unless @tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
startRow = currentRow
|
||||
endRow = row
|
||||
for currentRow in [row+1..@buffer.getLastRow()]
|
||||
break if @buffer.isRowBlank(currentRow)
|
||||
break unless @tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
endRow = currentRow
|
||||
return [startRow, endRow] if startRow isnt endRow
|
||||
|
||||
# Public: Given a buffer row, this folds it.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
foldBufferRow: (bufferRow) ->
|
||||
for currentRow in [bufferRow..0]
|
||||
rowRange = @rowRangeForCommentAtBufferRow(currentRow)
|
||||
rowRange ?= @languageMode.rowRangeForFoldAtBufferRow(currentRow)
|
||||
[startRow, endRow] = rowRange ? []
|
||||
continue unless startRow? and startRow <= bufferRow <= endRow
|
||||
fold = @largestFoldStartingAtBufferRow(startRow)
|
||||
continue if fold
|
||||
|
||||
@createFold(startRow, endRow)
|
||||
|
||||
return
|
||||
|
||||
# Public: Given a buffer row, this unfolds it.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
unfoldBufferRow: (bufferRow) ->
|
||||
@largestFoldContainingBufferRow(bufferRow)?.destroy()
|
||||
|
||||
# Public: Creates a new fold between two row numbers.
|
||||
#
|
||||
# startRow - The row {Number} to start folding at
|
||||
@@ -202,6 +151,9 @@ class DisplayBuffer
|
||||
for fold in new Array(folds...)
|
||||
fold.destroy() if fold.getBufferRange().containsRow(bufferRow)
|
||||
|
||||
foldsStartingAtBufferRow: (bufferRow) ->
|
||||
new Array((@activeFolds[bufferRow] ? [])...)
|
||||
|
||||
# Public: Given a buffer row, this returns the largest fold that starts there.
|
||||
#
|
||||
# Largest is defined as the fold whose difference between its start and end points
|
||||
@@ -288,14 +240,14 @@ class DisplayBuffer
|
||||
# Public: Gets the number of lines in the buffer.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
lineCount: ->
|
||||
@lineMap.screenLineCount()
|
||||
getLineCount: ->
|
||||
@lineMap.getScreenLineCount()
|
||||
|
||||
# Public: Gets the number of the last row in the buffer.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastRow: ->
|
||||
@lineCount() - 1
|
||||
@getLineCount() - 1
|
||||
|
||||
# Public: Gets the length of the longest screen line.
|
||||
#
|
||||
@@ -355,6 +307,15 @@ class DisplayBuffer
|
||||
setTabLength: (tabLength) ->
|
||||
@tokenizedBuffer.setTabLength(tabLength)
|
||||
|
||||
getGrammar: ->
|
||||
@tokenizedBuffer.grammar
|
||||
|
||||
setGrammar: (grammar) ->
|
||||
@tokenizedBuffer.setGrammar(grammar)
|
||||
|
||||
reloadGrammar: ->
|
||||
@tokenizedBuffer.reloadGrammar()
|
||||
|
||||
# Public: Given a position, this clips it to a real position.
|
||||
#
|
||||
# For example, if `position`'s row exceeds the row count of the buffer,
|
||||
|
||||
@@ -62,7 +62,7 @@ class EditSession
|
||||
@subscribe @displayBuffer, "changed", (e) =>
|
||||
@trigger 'screen-lines-changed', e
|
||||
|
||||
@languageMode.on 'grammar-changed', => @handleGrammarChange()
|
||||
@displayBuffer.on 'grammar-changed', => @handleGrammarChange()
|
||||
|
||||
getViewClass: ->
|
||||
require 'editor'
|
||||
@@ -162,14 +162,17 @@ class EditSession
|
||||
#
|
||||
# softWrapColumn - A {Number} defining the soft wrap limit
|
||||
setSoftWrapColumn: (@softWrapColumn) -> @displayBuffer.setSoftWrapColumn(@softWrapColumn)
|
||||
|
||||
# Public: Defines whether to use soft tabs.
|
||||
#
|
||||
# softTabs - A {Boolean} which, if `true`, indicates that you want soft tabs.
|
||||
setSoftTabs: (@softTabs) ->
|
||||
|
||||
# Public: Retrieves whether soft tabs are enabled.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
getSoftWrap: -> @softWrap
|
||||
|
||||
# Public: Defines whether to use soft wrapping of text.
|
||||
#
|
||||
# softTabs - A {Boolean} which, if `true`, indicates that you want soft wraps.
|
||||
@@ -256,14 +259,17 @@ class EditSession
|
||||
|
||||
# Public: Saves the buffer.
|
||||
save: -> @buffer.save()
|
||||
|
||||
# Public: Saves the buffer at a specific path.
|
||||
#
|
||||
# path - The path to save at.
|
||||
saveAs: (path) -> @buffer.saveAs(path)
|
||||
|
||||
# Public: Retrieves the current buffer's file extension.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getFileExtension: -> @buffer.getExtension()
|
||||
|
||||
# Public: Retrieves the current buffer's file path.
|
||||
#
|
||||
# Returns a {String}.
|
||||
@@ -283,30 +289,36 @@ class EditSession
|
||||
#
|
||||
# Returns a {String}.
|
||||
getBuffer: -> @buffer
|
||||
|
||||
# Public: Retrieves the current buffer's URI.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getUri: -> @getPath()
|
||||
|
||||
# Public: Given a buffer row, identifies if it is blank.
|
||||
#
|
||||
# bufferRow - A buffer row {Number} to check
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isBufferRowBlank: (bufferRow) -> @buffer.isRowBlank(bufferRow)
|
||||
|
||||
# Public: Given a buffer row, this finds the next row that's blank.
|
||||
#
|
||||
# bufferRow - A buffer row {Number} to check
|
||||
#
|
||||
# Returns a {Number}, or `null` if there's no other blank row.
|
||||
nextNonBlankBufferRow: (bufferRow) -> @buffer.nextNonBlankRow(bufferRow)
|
||||
|
||||
# Public: Finds the last point in the current buffer.
|
||||
#
|
||||
# Returns a {Point} representing the last position.
|
||||
getEofBufferPosition: -> @buffer.getEofPosition()
|
||||
|
||||
# Public: Finds the last line in the current buffer.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastBufferRow: -> @buffer.getLastRow()
|
||||
|
||||
# Public: Given a buffer row, this retrieves the range for that line.
|
||||
#
|
||||
# row - A {Number} identifying the row
|
||||
@@ -315,34 +327,40 @@ class EditSession
|
||||
#
|
||||
# Returns a {Range}.
|
||||
bufferRangeForBufferRow: (row, options) -> @buffer.rangeForRow(row, options)
|
||||
|
||||
# Public: Given a buffer row, this retrieves that line.
|
||||
#
|
||||
# row - A {Number} identifying the row
|
||||
#
|
||||
# Returns a {String}.
|
||||
lineForBufferRow: (row) -> @buffer.lineForRow(row)
|
||||
|
||||
# Public: Given a buffer row, this retrieves that line's length.
|
||||
#
|
||||
# row - A {Number} identifying the row
|
||||
#
|
||||
# Returns a {Number}.
|
||||
lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row)
|
||||
|
||||
# Public: Scans for text in the buffer, calling a function on each match.
|
||||
#
|
||||
# regex - A {RegExp} representing the text to find
|
||||
# range - A {Range} in the buffer to search within
|
||||
# iterator - A {Function} that's called on each match
|
||||
scanInBufferRange: (args...) -> @buffer.scanInRange(args...)
|
||||
|
||||
# Public: Scans for text in the buffer _backwards_, calling a function on each match.
|
||||
#
|
||||
# regex - A {RegExp} representing the text to find
|
||||
# range - A {Range} in the buffer to search within
|
||||
# iterator - A {Function} that's called on each match
|
||||
backwardsScanInBufferRange: (args...) -> @buffer.backwardsScanInRange(args...)
|
||||
|
||||
# Public: Identifies if the {Buffer} is modified (and not saved).
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isModified: -> @buffer.isModified()
|
||||
|
||||
# Public: Identifies if the modified buffer should let you know if it's closing
|
||||
# without being saved.
|
||||
#
|
||||
@@ -394,12 +412,14 @@ class EditSession
|
||||
#
|
||||
# Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed.
|
||||
clipScreenPosition: (screenPosition, options) -> @displayBuffer.clipScreenPosition(screenPosition, options)
|
||||
|
||||
# Public: Gets the line for the given screen row.
|
||||
#
|
||||
# screenRow - A {Number} indicating the screen row.
|
||||
#
|
||||
# Returns a {String}.
|
||||
lineForScreenRow: (row) -> @displayBuffer.lineForRow(row)
|
||||
|
||||
# Public: Gets the lines for the given screen row boundaries.
|
||||
#
|
||||
# start - A {Number} indicating the beginning screen row.
|
||||
@@ -407,18 +427,22 @@ class EditSession
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
linesForScreenRows: (start, end) -> @displayBuffer.linesForRows(start, end)
|
||||
|
||||
# Public: Gets the number of screen rows.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
screenLineCount: -> @displayBuffer.lineCount()
|
||||
getScreenLineCount: -> @displayBuffer.getLineCount()
|
||||
|
||||
# Public: Gets the length of the longest screen line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
maxScreenLineLength: -> @displayBuffer.maxLineLength()
|
||||
|
||||
# Public: Gets the number of the last row in the buffer.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastScreenRow: -> @displayBuffer.getLastRow()
|
||||
|
||||
# Public: Given a starting and ending row, this converts every row into a buffer position.
|
||||
#
|
||||
# startRow - The row {Number} to start at
|
||||
@@ -426,22 +450,26 @@ class EditSession
|
||||
#
|
||||
# Returns an {Array} of {Range}s.
|
||||
bufferRowsForScreenRows: (startRow, endRow) -> @displayBuffer.bufferRowsForScreenRows(startRow, endRow)
|
||||
|
||||
# Public: Retrieves the grammar's token scopes for a buffer position.
|
||||
#
|
||||
# bufferPosition - A {Point} in the {Buffer}
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
scopesForBufferPosition: (bufferPosition) -> @displayBuffer.scopesForBufferPosition(bufferPosition)
|
||||
|
||||
# Public: Retrieves the grammar's token for a buffer position.
|
||||
#
|
||||
# bufferPosition - A {Point} in the {Buffer}
|
||||
#
|
||||
# Returns a {Token}.
|
||||
tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition)
|
||||
|
||||
# Public: Retrieves the grammar's token scopes for the line with the most recently added cursor.
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
getCursorScopes: -> @getCursor().getScopes()
|
||||
|
||||
# Internal:
|
||||
logScreenLines: (start, end) -> @displayBuffer.logLines(start, end)
|
||||
|
||||
@@ -617,11 +645,11 @@ class EditSession
|
||||
|
||||
# Public: Folds all the rows.
|
||||
foldAll: ->
|
||||
@displayBuffer.foldAll()
|
||||
@languageMode.foldAll()
|
||||
|
||||
# Public: Unfolds all the rows.
|
||||
unfoldAll: ->
|
||||
@displayBuffer.unfoldAll()
|
||||
@languageMode.unfoldAll()
|
||||
|
||||
# Public: Folds the current row.
|
||||
foldCurrentRow: ->
|
||||
@@ -632,7 +660,7 @@ class EditSession
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
foldBufferRow: (bufferRow) ->
|
||||
@displayBuffer.foldBufferRow(bufferRow)
|
||||
@languageMode.foldBufferRow(bufferRow)
|
||||
|
||||
# Public: Unfolds the current row.
|
||||
unfoldCurrentRow: ->
|
||||
@@ -643,7 +671,7 @@ class EditSession
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
unfoldBufferRow: (bufferRow) ->
|
||||
@displayBuffer.unfoldBufferRow(bufferRow)
|
||||
@languageMode.unfoldBufferRow(bufferRow)
|
||||
|
||||
# Public: Folds all selections.
|
||||
foldSelection: ->
|
||||
@@ -1576,17 +1604,18 @@ class EditSession
|
||||
# Public: Retrieves the current {EditSession}'s grammar.
|
||||
#
|
||||
# Returns a {String} indicating the language's grammar rules.
|
||||
getGrammar: -> @languageMode.grammar
|
||||
getGrammar: ->
|
||||
@displayBuffer.getGrammar()
|
||||
|
||||
# Public: Sets the current {EditSession}'s grammar.
|
||||
#
|
||||
# grammar - A {String} indicating the language's grammar rules.
|
||||
setGrammar: (grammar) ->
|
||||
@languageMode.setGrammar(grammar)
|
||||
@displayBuffer.setGrammar(grammar)
|
||||
|
||||
# Public: Reloads the current grammar.
|
||||
reloadGrammar: ->
|
||||
@languageMode.reloadGrammar()
|
||||
@displayBuffer.reloadGrammar()
|
||||
|
||||
# Internal:
|
||||
handleGrammarChange: ->
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
ConfigPanel = require 'config-panel'
|
||||
Editor = require 'editor'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
module.exports =
|
||||
class EditorConfigPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@form class: 'form-horizontal', =>
|
||||
@fieldset =>
|
||||
@legend "Editor Settings"
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', "Font Size:"
|
||||
@div class: 'controls', =>
|
||||
@subview "fontSizeEditor", new Editor(mini: true, attributes: {id: 'editor.fontSize', type: 'int', style: 'width: 40px'})
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', "Font Family:"
|
||||
@div class: 'controls', =>
|
||||
@subview "fontFamilyEditor", new Editor(mini: true, attributes: {id: 'editor.fontFamily', type: 'string'})
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@div class: 'controls', =>
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'editor.autoIndent', =>
|
||||
@input id: 'editor.autoIndent', type: 'checkbox'
|
||||
@text 'Auto-Indent'
|
||||
|
||||
@div class: 'controls', =>
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'editor.autoIndentOnPaste', =>
|
||||
@input id: 'editor.autoIndentOnPaste', type: 'checkbox'
|
||||
@text 'Auto-Indent on Paste'
|
||||
|
||||
@div class: 'controls', =>
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'editor.showLineNumbers', =>
|
||||
@input id: 'editor.showLineNumbers', type: 'checkbox'
|
||||
@text 'Show Line Numbers'
|
||||
|
||||
@div class: 'controls', =>
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'editor.showInvisibles', =>
|
||||
@input id: 'editor.showInvisibles', type: 'checkbox'
|
||||
@text 'Show Invisible Characters'
|
||||
|
||||
@div class: 'controls', =>
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'editor.showIndentGuide', =>
|
||||
@input id: 'editor.showIndentGuide', type: 'checkbox'
|
||||
@text 'Show Indent Guide'
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', for: 'editor.preferredLineLength', "Preferred Line Length:"
|
||||
@div class: 'controls', =>
|
||||
@subview "preferredLineLengthEditor", new Editor(mini: true, attributes: {id: 'editor.preferredLineLength', type: 'int', style: 'width: 40px'})
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', for: 'editor.nonWordCharacters', "Non-Word Characters:"
|
||||
@div class: 'controls', =>
|
||||
@subview "nonWordCharactersEditor", new Editor(mini: true, attributes: {id: 'editor.nonWordCharacters', type: 'string'})
|
||||
+127
-11
@@ -31,7 +31,9 @@ class Editor extends View
|
||||
###
|
||||
|
||||
@content: (params) ->
|
||||
@div class: @classes(params), tabindex: -1, =>
|
||||
attributes = { class: @classes(params), tabindex: -1 }
|
||||
_.extend(attributes, params.attributes) if params.attributes
|
||||
@div attributes, =>
|
||||
@subview 'gutter', new Gutter
|
||||
@input class: 'hidden-input', outlet: 'hiddenInput'
|
||||
@div class: 'scroll-view', outlet: 'scrollView', =>
|
||||
@@ -196,137 +198,173 @@ class Editor extends View
|
||||
#
|
||||
# Returns a {Cursor}.
|
||||
getCursor: -> @activeEditSession.getCursor()
|
||||
|
||||
# Public: Retrieves an array of all the cursors.
|
||||
#
|
||||
# Returns a {[Cursor]}.
|
||||
getCursors: -> @activeEditSession.getCursors()
|
||||
|
||||
# Public: Adds a cursor at the provided `screenPosition`.
|
||||
#
|
||||
# screenPosition - An {Array} of two numbers: the screen row, and the screen column.
|
||||
#
|
||||
# Returns the new {Cursor}.
|
||||
addCursorAtScreenPosition: (screenPosition) -> @activeEditSession.addCursorAtScreenPosition(screenPosition)
|
||||
|
||||
# Public: Adds a cursor at the provided `bufferPosition`.
|
||||
#
|
||||
# bufferPosition - An {Array} of two numbers: the buffer row, and the buffer column.
|
||||
#
|
||||
# Returns the new {Cursor}.
|
||||
addCursorAtBufferPosition: (bufferPosition) -> @activeEditSession.addCursorAtBufferPosition(bufferPosition)
|
||||
|
||||
# Public: Moves every cursor up one row.
|
||||
moveCursorUp: -> @activeEditSession.moveCursorUp()
|
||||
|
||||
# Public: Moves every cursor down one row.
|
||||
moveCursorDown: -> @activeEditSession.moveCursorDown()
|
||||
|
||||
# Public: Moves every cursor left one column.
|
||||
moveCursorLeft: -> @activeEditSession.moveCursorLeft()
|
||||
|
||||
# Public: Moves every cursor right one column.
|
||||
moveCursorRight: -> @activeEditSession.moveCursorRight()
|
||||
|
||||
# Public: Moves every cursor to the beginning of the current word.
|
||||
moveCursorToBeginningOfWord: -> @activeEditSession.moveCursorToBeginningOfWord()
|
||||
|
||||
# Public: Moves every cursor to the end of the current word.
|
||||
moveCursorToEndOfWord: -> @activeEditSession.moveCursorToEndOfWord()
|
||||
|
||||
# Public: Moves the cursor to the beginning of the next word.
|
||||
moveCursorToBeginningOfNextWord: -> @activeEditSession.moveCursorToBeginningOfNextWord()
|
||||
|
||||
# Public: Moves every cursor to the top of the buffer.
|
||||
moveCursorToTop: -> @activeEditSession.moveCursorToTop()
|
||||
|
||||
# Public: Moves every cursor to the bottom of the buffer.
|
||||
moveCursorToBottom: -> @activeEditSession.moveCursorToBottom()
|
||||
|
||||
# Public: Moves every cursor to the beginning of the line.
|
||||
moveCursorToBeginningOfLine: -> @activeEditSession.moveCursorToBeginningOfLine()
|
||||
|
||||
# Public: Moves every cursor to the first non-whitespace character of the line.
|
||||
moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine()
|
||||
|
||||
# Public: Moves every cursor to the end of the line.
|
||||
moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine()
|
||||
|
||||
# Public: Moves the selected line up one row.
|
||||
moveLineUp: -> @activeEditSession.moveLineUp()
|
||||
|
||||
# Public: Moves the selected line down one row.
|
||||
moveLineDown: -> @activeEditSession.moveLineDown()
|
||||
|
||||
# Public: Sets the cursor based on a given screen position.
|
||||
#
|
||||
# position - An {Array} of two numbers: the screen row, and the screen column.
|
||||
# options - An object with properties based on {Cursor.setScreenPosition}.
|
||||
#
|
||||
setCursorScreenPosition: (position, options) -> @activeEditSession.setCursorScreenPosition(position, options)
|
||||
|
||||
# Public: Duplicates the current line.
|
||||
#
|
||||
# If more than one cursor is present, only the most recently added one is considered.
|
||||
duplicateLine: -> @activeEditSession.duplicateLine()
|
||||
|
||||
# Public: Joins the current line with the one below it.
|
||||
#
|
||||
# Multiple cursors are considered equally. If there's a selection in the editor,
|
||||
# all the lines are joined together.
|
||||
joinLine: -> @activeEditSession.joinLine()
|
||||
|
||||
# Public: Gets the current screen position.
|
||||
#
|
||||
# Returns an {Array} of two numbers: the screen row, and the screen column.
|
||||
getCursorScreenPosition: -> @activeEditSession.getCursorScreenPosition()
|
||||
|
||||
# Public: Gets the current screen row.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getCursorScreenRow: -> @activeEditSession.getCursorScreenRow()
|
||||
|
||||
# Public: Sets the cursor based on a given buffer position.
|
||||
#
|
||||
# position - An {Array} of two numbers: the buffer row, and the buffer column.
|
||||
# options - An object with properties based on {Cursor.setBufferPosition}.
|
||||
#
|
||||
setCursorBufferPosition: (position, options) -> @activeEditSession.setCursorBufferPosition(position, options)
|
||||
|
||||
# Public: Gets the current buffer position of the cursor.
|
||||
#
|
||||
# Returns an {Array} of two numbers: the buffer row, and the buffer column.
|
||||
getCursorBufferPosition: -> @activeEditSession.getCursorBufferPosition()
|
||||
|
||||
# Public: Retrieves the range for the current paragraph.
|
||||
#
|
||||
# A paragraph is defined as a block of text surrounded by empty lines.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getCurrentParagraphBufferRange: -> @activeEditSession.getCurrentParagraphBufferRange()
|
||||
|
||||
# Public: Gets the word located under the cursor.
|
||||
#
|
||||
# options - An object with properties based on {Cursor.getBeginningOfCurrentWordBufferPosition}.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getWordUnderCursor: (options) -> @activeEditSession.getWordUnderCursor(options)
|
||||
|
||||
# Public: Gets the selection at the specified index.
|
||||
#
|
||||
# index - The id {Number} of the selection
|
||||
#
|
||||
# Returns a {Selection}.
|
||||
getSelection: (index) -> @activeEditSession.getSelection(index)
|
||||
|
||||
# Public: Gets the last selection, _i.e._ the most recently added.
|
||||
#
|
||||
# Returns a {Selection}.
|
||||
getSelections: -> @activeEditSession.getSelections()
|
||||
|
||||
# Public: Gets all selections, ordered by their position in the buffer.
|
||||
#
|
||||
# Returns an {Array} of {Selection}s.
|
||||
getSelectionsOrderedByBufferPosition: -> @activeEditSession.getSelectionsOrderedByBufferPosition()
|
||||
|
||||
# Public: Gets the very last selection, as it's ordered in the buffer.
|
||||
#
|
||||
# Returns a {Selection}.
|
||||
getLastSelectionInBuffer: -> @activeEditSession.getLastSelectionInBuffer()
|
||||
|
||||
# Public: Gets the currently selected text.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getSelectedText: -> @activeEditSession.getSelectedText()
|
||||
|
||||
# Public: Gets the buffer ranges of all the {Selection}s.
|
||||
#
|
||||
# This is ordered by their buffer position.
|
||||
#
|
||||
# Returns an {Array} of {Range}s.
|
||||
getSelectedBufferRanges: -> @activeEditSession.getSelectedBufferRanges()
|
||||
|
||||
# Public: Gets the buffer range of the most recently added {Selection}.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getSelectedBufferRange: -> @activeEditSession.getSelectedBufferRange()
|
||||
|
||||
# Public: Given a buffer range, this removes all previous selections and creates a new selection for it.
|
||||
#
|
||||
# bufferRange - A {Range} in the buffer
|
||||
# options - A hash of options
|
||||
setSelectedBufferRange: (bufferRange, options) -> @activeEditSession.setSelectedBufferRange(bufferRange, options)
|
||||
|
||||
# Public: Given an array of buffer ranges, this removes all previous selections and creates new selections for them.
|
||||
#
|
||||
# bufferRanges - An {Array} of {Range}s in the buffer
|
||||
# options - A hash of options
|
||||
setSelectedBufferRanges: (bufferRanges, options) -> @activeEditSession.setSelectedBufferRanges(bufferRanges, options)
|
||||
|
||||
# Public: Given a buffer range, this adds a new selection for it.
|
||||
#
|
||||
# bufferRange - A {Range} in the buffer
|
||||
@@ -334,38 +372,55 @@ class Editor extends View
|
||||
#
|
||||
# Returns the new {Selection}.
|
||||
addSelectionForBufferRange: (bufferRange, options) -> @activeEditSession.addSelectionForBufferRange(bufferRange, options)
|
||||
|
||||
# Public: Selects the text one position right of the cursor.
|
||||
selectRight: -> @activeEditSession.selectRight()
|
||||
|
||||
# Public: Selects the text one position left of the cursor.
|
||||
selectLeft: -> @activeEditSession.selectLeft()
|
||||
|
||||
# Public: Selects all the text one position above the cursor.
|
||||
selectUp: -> @activeEditSession.selectUp()
|
||||
|
||||
# Public: Selects all the text one position below the cursor.
|
||||
selectDown: -> @activeEditSession.selectDown()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the top of the buffer.
|
||||
selectToTop: -> @activeEditSession.selectToTop()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the bottom of the buffer.
|
||||
selectToBottom: -> @activeEditSession.selectToBottom()
|
||||
|
||||
# Public: Selects all the text in the buffer.
|
||||
selectAll: -> @activeEditSession.selectAll()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the beginning of the line.
|
||||
selectToBeginningOfLine: -> @activeEditSession.selectToBeginningOfLine()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the end of the line.
|
||||
selectToEndOfLine: -> @activeEditSession.selectToEndOfLine()
|
||||
|
||||
# Public: Moves the current selection down one row.
|
||||
addSelectionBelow: -> @activeEditSession.addSelectionBelow()
|
||||
|
||||
# Public: Moves the current selection up one row.
|
||||
addSelectionAbove: -> @activeEditSession.addSelectionAbove()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the beginning of the word.
|
||||
selectToBeginningOfWord: -> @activeEditSession.selectToBeginningOfWord()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the end of the word.
|
||||
selectToEndOfWord: -> @activeEditSession.selectToEndOfWord()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the beginning of the next word.
|
||||
selectToBeginningOfNextWord: -> @activeEditSession.selectToBeginningOfNextWord()
|
||||
|
||||
# Public: Selects the current word.
|
||||
selectWord: -> @activeEditSession.selectWord()
|
||||
|
||||
# Public: Selects the current line.
|
||||
selectLine: -> @activeEditSession.selectLine()
|
||||
|
||||
# Public: Selects the text from the current cursor position to a given position.
|
||||
#
|
||||
# position - An instance of {Point}, with a given `row` and `column`.
|
||||
@@ -376,64 +431,89 @@ class Editor extends View
|
||||
# to the position of the selection after it. The last selection is transferred to the
|
||||
# position of the first.
|
||||
transpose: -> @activeEditSession.transpose()
|
||||
|
||||
# Public: Turns the current selection into upper case.
|
||||
upperCase: -> @activeEditSession.upperCase()
|
||||
|
||||
# Public: Turns the current selection into lower case.
|
||||
lowerCase: -> @activeEditSession.lowerCase()
|
||||
|
||||
# Public: Clears every selection. TODO
|
||||
clearSelections: -> @activeEditSession.clearSelections()
|
||||
|
||||
# Public: Performs a backspace, removing the character found behind the cursor position.
|
||||
backspace: -> @activeEditSession.backspace()
|
||||
|
||||
# Public: Performs a backspace to the beginning of the current word, removing characters found there.
|
||||
backspaceToBeginningOfWord: -> @activeEditSession.backspaceToBeginningOfWord()
|
||||
|
||||
# Public: Performs a backspace to the beginning of the current line, removing characters found there.
|
||||
backspaceToBeginningOfLine: -> @activeEditSession.backspaceToBeginningOfLine()
|
||||
|
||||
# Public: Performs a delete, removing the character found ahead the cursor position.
|
||||
delete: -> @activeEditSession.delete()
|
||||
|
||||
# Public: Performs a delete to the end of the current word, removing characters found there.
|
||||
deleteToEndOfWord: -> @activeEditSession.deleteToEndOfWord()
|
||||
|
||||
# Public: Performs a delete to the end of the current line, removing characters found there.
|
||||
deleteLine: -> @activeEditSession.deleteLine()
|
||||
|
||||
# Public: Performs a cut to the end of the current line.
|
||||
#
|
||||
# Characters are removed, but the text remains in the clipboard.
|
||||
cutToEndOfLine: -> @activeEditSession.cutToEndOfLine()
|
||||
|
||||
# Public: Inserts text at the current cursor positions.
|
||||
#
|
||||
# text - A {String} representing the text to insert.
|
||||
# options - A set of options equivalent to {Selection.insertText}.
|
||||
insertText: (text, options) -> @activeEditSession.insertText(text, options)
|
||||
|
||||
# Public: Inserts a new line at the current cursor positions.
|
||||
insertNewline: -> @activeEditSession.insertNewline()
|
||||
|
||||
# Internal:
|
||||
|
||||
consolidateSelections: (e) -> e.abortKeyBinding() unless @activeEditSession.consolidateSelections()
|
||||
|
||||
# Public: Inserts a new line below the current cursor positions.
|
||||
insertNewlineBelow: -> @activeEditSession.insertNewlineBelow()
|
||||
|
||||
# Public: Inserts a new line above the current cursor positions.
|
||||
insertNewlineAbove: -> @activeEditSession.insertNewlineAbove()
|
||||
|
||||
# Public: Indents the current line.
|
||||
#
|
||||
# options - A set of options equivalent to {Selection.indent}.
|
||||
indent: (options) -> @activeEditSession.indent(options)
|
||||
|
||||
# Public: TODO
|
||||
autoIndent: (options) -> @activeEditSession.autoIndentSelectedRows()
|
||||
|
||||
# Public: Indents the selected rows.
|
||||
indentSelectedRows: -> @activeEditSession.indentSelectedRows()
|
||||
|
||||
# Public: Outdents the selected rows.
|
||||
outdentSelectedRows: -> @activeEditSession.outdentSelectedRows()
|
||||
|
||||
# Public: Cuts the selected text.
|
||||
cutSelection: -> @activeEditSession.cutSelectedText()
|
||||
|
||||
# Public: Copies the selected text.
|
||||
copySelection: -> @activeEditSession.copySelectedText()
|
||||
|
||||
# Public: Pastes the text in the clipboard.
|
||||
#
|
||||
# options - A set of options equivalent to {Selection.insertText}.
|
||||
paste: (options) -> @activeEditSession.pasteText(options)
|
||||
|
||||
# Public: Undos the last {Buffer} change.
|
||||
undo: -> @activeEditSession.undo()
|
||||
|
||||
# Public: Redos the last {Buffer} change.
|
||||
redo: -> @activeEditSession.redo()
|
||||
|
||||
# Public: Creates a new fold between two row numbers.
|
||||
#
|
||||
# startRow - The row {Number} to start folding at
|
||||
@@ -441,36 +521,46 @@ class Editor extends View
|
||||
#
|
||||
# Returns the new {Fold}.
|
||||
createFold: (startRow, endRow) -> @activeEditSession.createFold(startRow, endRow)
|
||||
|
||||
# Public: Folds the current row.
|
||||
foldCurrentRow: -> @activeEditSession.foldCurrentRow()
|
||||
|
||||
# Public: Unfolds the current row.
|
||||
unfoldCurrentRow: -> @activeEditSession.unfoldCurrentRow()
|
||||
|
||||
# Public: Folds all the rows.
|
||||
foldAll: -> @activeEditSession.foldAll()
|
||||
|
||||
# Public: Unfolds all the rows.
|
||||
unfoldAll: -> @activeEditSession.unfoldAll()
|
||||
|
||||
# Public: Folds the most recent selection.
|
||||
foldSelection: -> @activeEditSession.foldSelection()
|
||||
|
||||
# Public: Given the id of a {Fold}, this removes it.
|
||||
#
|
||||
# foldId - The fold id {Number} to remove
|
||||
destroyFold: (foldId) -> @activeEditSession.destroyFold(foldId)
|
||||
|
||||
# Public: Removes any {Fold}s found that contain the given buffer row.
|
||||
#
|
||||
# bufferRow - The buffer row {Number} to check against
|
||||
destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow)
|
||||
|
||||
# Public: Determines if the given screen row is folded.
|
||||
#
|
||||
# screenRow - A {Number} indicating the screen row.
|
||||
#
|
||||
# Returns `true` if the screen row is folded, `false` otherwise.
|
||||
isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow)
|
||||
|
||||
# Public: Determines if the given buffer row is folded.
|
||||
#
|
||||
# screenRow - A {Number} indicating the buffer row.
|
||||
#
|
||||
# Returns `true` if the buffer row is folded, `false` otherwise.
|
||||
isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow)
|
||||
|
||||
# Public: Determines if the given row that the cursor is at is folded.
|
||||
#
|
||||
# Returns `true` if the row is folded, `false` otherwise.
|
||||
@@ -482,6 +572,7 @@ class Editor extends View
|
||||
#
|
||||
# Returns a {String}.
|
||||
lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow)
|
||||
|
||||
# Public: Gets the lines for the given screen row boundaries.
|
||||
#
|
||||
# start - A {Number} indicating the beginning screen row.
|
||||
@@ -489,24 +580,29 @@ class Editor extends View
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end)
|
||||
|
||||
# Public: Gets the number of screen rows.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
screenLineCount: -> @activeEditSession.screenLineCount()
|
||||
getScreenLineCount: -> @activeEditSession.getScreenLineCount()
|
||||
|
||||
# Public: Defines the limit at which the buffer begins to soft wrap text.
|
||||
#
|
||||
# softWrapColumn - A {Number} defining the soft wrap limit
|
||||
setSoftWrapColumn: (softWrapColumn) ->
|
||||
softWrapColumn ?= @calcSoftWrapColumn()
|
||||
@activeEditSession.setSoftWrapColumn(softWrapColumn) if softWrapColumn
|
||||
|
||||
# Public: Gets the length of the longest screen line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
maxScreenLineLength: -> @activeEditSession.maxScreenLineLength()
|
||||
|
||||
# Public: Gets the text in the last screen row.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getLastScreenRow: -> @activeEditSession.getLastScreenRow()
|
||||
|
||||
# Public: Given a position, this clips it to a real position.
|
||||
#
|
||||
# For example, if `position`'s row exceeds the row count of the buffer,
|
||||
@@ -553,6 +649,7 @@ class Editor extends View
|
||||
#
|
||||
# Returns a {Range}.
|
||||
bufferRangeForScreenRange: (range) -> @activeEditSession.bufferRangeForScreenRange(range)
|
||||
|
||||
# Public: Given a starting and ending row, this converts every row into a buffer position.
|
||||
#
|
||||
# startRow - The row {Number} to start at
|
||||
@@ -560,13 +657,17 @@ class Editor extends View
|
||||
#
|
||||
# Returns an {Array} of {Range}s.
|
||||
bufferRowsForScreenRows: (startRow, endRow) -> @activeEditSession.bufferRowsForScreenRows(startRow, endRow)
|
||||
|
||||
# Public: Gets the number of the last row in the buffer.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastScreenRow: -> @activeEditSession.getLastScreenRow()
|
||||
|
||||
# Internal:
|
||||
|
||||
logCursorScope: ->
|
||||
console.log @activeEditSession.getCursorScopes()
|
||||
|
||||
# Public: Emulates the "page down" key, where the last row of a buffer scrolls to become the first.
|
||||
pageDown: ->
|
||||
newScrollTop = @scrollTop() + @scrollView[0].clientHeight
|
||||
@@ -618,48 +719,58 @@ class Editor extends View
|
||||
|
||||
# Public: Checks out the current HEAD revision of the file.
|
||||
checkoutHead: -> @getBuffer().checkoutHead()
|
||||
|
||||
# Public: Replaces the current buffer contents.
|
||||
#
|
||||
# text - A {String} containing the new buffer contents.
|
||||
setText: (text) -> @activeEditSession.setText(text)
|
||||
|
||||
# Public: Retrieves the current buffer contents.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getText: -> @activeEditSession.getText()
|
||||
|
||||
# Public: Retrieves the current buffer's file path.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getPath: -> @activeEditSession?.getPath()
|
||||
|
||||
# Public: Gets the number of lines in a file.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLineCount: -> @getBuffer().getLineCount()
|
||||
|
||||
# Public: Gets the row number of the last line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastBufferRow: -> @getBuffer().getLastRow()
|
||||
|
||||
# Public: Given a range, returns the lines of text within it.
|
||||
#
|
||||
# range - A {Range} object specifying your points of interest
|
||||
#
|
||||
# Returns a {String} of the combined lines.
|
||||
getTextInRange: (range) -> @getBuffer().getTextInRange(range)
|
||||
|
||||
# Public: Finds the last point in the current buffer.
|
||||
#
|
||||
# Returns a {Point} representing the last position.
|
||||
getEofPosition: -> @getBuffer().getEofPosition()
|
||||
|
||||
# Public: Given a row, returns the line of text.
|
||||
#
|
||||
# row - A {Number} indicating the row.
|
||||
#
|
||||
# Returns a {String}.
|
||||
lineForBufferRow: (row) -> @getBuffer().lineForRow(row)
|
||||
|
||||
# Public: Given a row, returns the length of the line of text.
|
||||
#
|
||||
# row - A {Number} indicating the row
|
||||
#
|
||||
# Returns a {Number}.
|
||||
lineLengthForBufferRow: (row) -> @getBuffer().lineLengthForRow(row)
|
||||
|
||||
# Public: Given a buffer row, this retrieves the range for that line.
|
||||
#
|
||||
# row - A {Number} identifying the row
|
||||
@@ -668,12 +779,14 @@ class Editor extends View
|
||||
#
|
||||
# Returns a {Range}.
|
||||
rangeForBufferRow: (row) -> @getBuffer().rangeForRow(row)
|
||||
|
||||
# Public: Scans for text in the buffer, calling a function on each match.
|
||||
#
|
||||
# regex - A {RegExp} representing the text to find
|
||||
# range - A {Range} in the buffer to search within
|
||||
# iterator - A {Function} that's called on each match
|
||||
scanInBufferRange: (args...) -> @getBuffer().scanInRange(args...)
|
||||
|
||||
# Public: Scans for text in the buffer _backwards_, calling a function on each match.
|
||||
#
|
||||
# regex - A {RegExp} representing the text to find
|
||||
@@ -887,7 +1000,7 @@ class Editor extends View
|
||||
|
||||
# Public: Scrolls the editor to the bottom.
|
||||
scrollToBottom: ->
|
||||
@scrollBottom(@screenLineCount() * @lineHeight)
|
||||
@scrollBottom(@getScreenLineCount() * @lineHeight)
|
||||
|
||||
# Public: Scrolls the editor to the position of the most recently added cursor.
|
||||
#
|
||||
@@ -1042,14 +1155,17 @@ class Editor extends View
|
||||
#
|
||||
# fontFamily - A {String} identifying the CSS `font-family`,
|
||||
setFontFamily: (fontFamily) ->
|
||||
return if fontFamily == undefined
|
||||
headTag = $("head")
|
||||
styleTag = headTag.find("style.editor-font-family")
|
||||
if styleTag.length == 0
|
||||
styleTag = $$ -> @style class: 'editor-font-family'
|
||||
headTag.append styleTag
|
||||
|
||||
styleTag.text(".editor {font-family: #{fontFamily}}")
|
||||
if fontFamily?
|
||||
if styleTag.length == 0
|
||||
styleTag = $$ -> @style class: 'editor-font-family'
|
||||
headTag.append styleTag
|
||||
styleTag.text(".editor {font-family: #{fontFamily}}")
|
||||
else
|
||||
styleTag.remove()
|
||||
|
||||
@redraw()
|
||||
|
||||
# Public: Gets the font family for the editor.
|
||||
@@ -1156,7 +1272,7 @@ class Editor extends View
|
||||
fragment.remove()
|
||||
|
||||
updateLayerDimensions: ->
|
||||
height = @lineHeight * @screenLineCount()
|
||||
height = @lineHeight * @getScreenLineCount()
|
||||
unless @layerHeight == height
|
||||
@renderedLines.height(height)
|
||||
@underlayer.css('min-height', height)
|
||||
@@ -1281,7 +1397,7 @@ class Editor extends View
|
||||
|
||||
intactRanges = [{start: @firstRenderedScreenRow, end: @lastRenderedScreenRow, domStart: 0}]
|
||||
|
||||
if @showIndentGuide
|
||||
if not @mini and @showIndentGuide
|
||||
trailingEmptyLineChanges = []
|
||||
for change in @pendingChanges
|
||||
continue unless change.bufferDelta?
|
||||
@@ -1497,7 +1613,7 @@ class Editor extends View
|
||||
updateScopeStack(token.scopes)
|
||||
hasLeadingWhitespace = position < firstNonWhitespacePosition
|
||||
hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition
|
||||
hasIndentGuide = @showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly)
|
||||
hasIndentGuide = not @mini and @showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly)
|
||||
line.push(token.getValueAsHtml({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide}))
|
||||
position += token.value.length
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
ConfigPanel = require 'config-panel'
|
||||
{$$} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
module.exports =
|
||||
class GeneralConfigPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@form id: 'general-config-panel', class: 'form-horizontal', =>
|
||||
@fieldset =>
|
||||
@legend "General Settings"
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'editor.hideGitIgnoredFiles', =>
|
||||
@input id: 'editor.hideGitIgnoredFiles', type: 'checkbox'
|
||||
@text 'Hide Git-Ignored Files'
|
||||
|
||||
@div class: 'checkbox', =>
|
||||
@label for: 'core.autosave', =>
|
||||
@input id: 'core.autosave', type: 'checkbox'
|
||||
@text 'Auto-Save on Focus Change'
|
||||
@@ -10,6 +10,7 @@ GitUtils = require 'git-utils'
|
||||
# Ultimately, this is an overlay to the native [git-utils](https://github.com/atom/node-git) model.
|
||||
module.exports =
|
||||
class Git
|
||||
|
||||
# Public: Creates a new `Git` instance.
|
||||
#
|
||||
# path - The git repository to open
|
||||
@@ -98,7 +99,7 @@ class Git
|
||||
getWorkingDirectory: ->
|
||||
@getRepo().getWorkingDirectory()
|
||||
|
||||
# Public: Retrieves the reference or SHA-1 that `HEAD` points to.
|
||||
# Public: Retrieves the reference or SHA-1 that `HEAD` points to.
|
||||
#
|
||||
# This can be `refs/heads/master`, or a full SHA-1 if the repository is in a detached `HEAD` state.
|
||||
#
|
||||
@@ -170,7 +171,7 @@ class Git
|
||||
relativize: (path) ->
|
||||
@getRepo().relativize(path)
|
||||
|
||||
# Public: Retrieves a shortened version of {.getHead}.
|
||||
# Public: Retrieves a shortened version of {.getHead}.
|
||||
#
|
||||
# This removes the leading segments of `refs/heads`, `refs/tags`, or `refs/remotes`.
|
||||
# It also shortenes the SHA-1 of a detached `HEAD` to 7 characters.
|
||||
@@ -179,7 +180,7 @@ class Git
|
||||
getShortHead: ->
|
||||
@getRepo().getShortHead()
|
||||
|
||||
# Public: Restore the contents of a path in the working directory and index to the version at `HEAD`.
|
||||
# Public: Restore the contents of a path in the working directory and index to the version at `HEAD`.
|
||||
#
|
||||
# This is essentially the same as running:
|
||||
# ```
|
||||
@@ -239,7 +240,7 @@ class Git
|
||||
#
|
||||
# path - The {String} path (relative to the repository)
|
||||
# text - The {String} to compare against the `HEAD` contents
|
||||
#
|
||||
#
|
||||
# Returns an object with two keys, `ahead` and `behind`. These will always be greater than zero.
|
||||
getLineDiffs: (path, text) ->
|
||||
@getRepo().getLineDiffs(@relativize(path), text)
|
||||
@@ -259,6 +260,6 @@ class Git
|
||||
@statusTask.one 'task-completed', =>
|
||||
@statusTask = null
|
||||
@statusTask.start()
|
||||
|
||||
|
||||
_.extend Git.prototype, Subscriber
|
||||
_.extend Git.prototype, EventEmitter
|
||||
|
||||
+11
-17
@@ -30,19 +30,11 @@ class Keymap
|
||||
@bindingSetsByFirstKeystroke = {}
|
||||
|
||||
bindDefaultKeys: ->
|
||||
@add
|
||||
'body':
|
||||
'meta-n': 'new-window'
|
||||
'meta-,': 'open-user-configuration'
|
||||
'meta-o': 'open'
|
||||
'meta-O': 'open-dev'
|
||||
'meta-w': 'core:close'
|
||||
'alt-meta-i': 'toggle-dev-tools'
|
||||
|
||||
$(document).command 'new-window', => atom.newWindow()
|
||||
$(document).command 'open-user-configuration', => atom.open(config.configDirPath)
|
||||
$(document).command 'open-user-configuration', => atom.openConfig()
|
||||
$(document).command 'open', => atom.open()
|
||||
$(document).command 'open-dev', => atom.openDev()
|
||||
$(document).command 'toggle-dev-tools', => atom.toggleDevTools()
|
||||
|
||||
loadBundledKeymaps: ->
|
||||
@loadDirectory(fsUtils.resolveOnLoadPath('keymaps'))
|
||||
@@ -52,23 +44,23 @@ class Keymap
|
||||
|
||||
loadDirectory: (directoryPath) ->
|
||||
@load(filePath) for filePath in fsUtils.list(directoryPath, ['.cson', '.json'])
|
||||
|
||||
|
||||
load: (path) ->
|
||||
@add(path, CSON.readObject(path))
|
||||
|
||||
|
||||
add: (args...) ->
|
||||
name = args.shift() if args.length > 1
|
||||
keymap = args.shift()
|
||||
for selector, bindings of keymap
|
||||
@bindKeys(name, selector, bindings)
|
||||
|
||||
|
||||
remove: (name) ->
|
||||
for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name)
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0]
|
||||
_.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet)
|
||||
|
||||
|
||||
bindKeys: (args...) ->
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, bindings] = args
|
||||
@@ -78,7 +70,7 @@ class Keymap
|
||||
keystroke = keystrokes.split(' ')[0] # only index by first keystroke
|
||||
@bindingSetsByFirstKeystroke[keystroke] ?= []
|
||||
@bindingSetsByFirstKeystroke[keystroke].push(bindingSet)
|
||||
|
||||
|
||||
unbindKeys: (selector, bindings) ->
|
||||
bindingSet = _.detect @bindingSets, (bindingSet) ->
|
||||
bindingSet.selector is selector and bindingSet.bindings is bindings
|
||||
@@ -86,7 +78,7 @@ class Keymap
|
||||
if bindingSet
|
||||
console.log "binding set", bindingSet
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
|
||||
|
||||
bindingsForElement: (element) ->
|
||||
keystrokeMap = {}
|
||||
currentNode = $(element)
|
||||
@@ -112,7 +104,9 @@ class Keymap
|
||||
candidateBindingSets = @bindingSetsForNode(currentNode, bindingSetsForFirstKeystroke)
|
||||
for bindingSet in candidateBindingSets
|
||||
command = bindingSet.commandForEvent(event)
|
||||
if command
|
||||
if command is 'native!'
|
||||
return true
|
||||
else if command
|
||||
continue if @triggerCommandEvent(event, command)
|
||||
return false
|
||||
else if command == false
|
||||
|
||||
@@ -52,7 +52,32 @@
|
||||
'meta-9': 'pane:show-item-9'
|
||||
'meta-T': 'pane:reopen-closed-item'
|
||||
|
||||
'meta-n': 'new-window'
|
||||
'meta-N': 'new-editor'
|
||||
'meta-,': 'open-user-configuration'
|
||||
'meta-o': 'open'
|
||||
'meta-O': 'open-dev'
|
||||
'meta-w': 'core:close'
|
||||
'alt-meta-i': 'toggle-dev-tools'
|
||||
|
||||
'.tool-panel':
|
||||
'meta-escape': 'tool-panel:unfocus'
|
||||
'escape': 'core:close'
|
||||
'meta-w': 'noop'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'input:not(.hidden-input)':
|
||||
'left': 'native!'
|
||||
'right': 'native!'
|
||||
'tab': 'native!'
|
||||
'shift-tab': 'native!'
|
||||
'shift-left': 'native!'
|
||||
'shift-right': 'native!'
|
||||
'backspace': 'native!'
|
||||
'shift-backspace': 'native!'
|
||||
'delete': 'native!'
|
||||
'meta-z': 'native!'
|
||||
'meta-Z': 'native!'
|
||||
'meta-x': 'native!'
|
||||
'meta-c': 'native!'
|
||||
'meta-v': 'native!'
|
||||
|
||||
@@ -41,4 +41,5 @@
|
||||
'meta-+': 'image-view:zoom-in'
|
||||
'meta-=': 'image-view:zoom-in'
|
||||
'meta--': 'image-view:zoom-out'
|
||||
'meta-_': 'image-view:zoom-out'
|
||||
'meta-0': 'image-view:reset-zoom'
|
||||
|
||||
@@ -22,3 +22,12 @@
|
||||
'alt-h': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-d': 'editor:delete-to-end-of-word'
|
||||
'ctrl-k': 'editor:cut-to-end-of-line'
|
||||
|
||||
# allow standard input fields to work correctly
|
||||
'input:not(.hidden-input)':
|
||||
'ctrl-b': 'native!'
|
||||
'ctrl-f': 'native!'
|
||||
'ctrl-F': 'native!'
|
||||
'ctrl-B': 'native!'
|
||||
'ctrl-h': 'native!'
|
||||
'ctrl-d': 'native!'
|
||||
|
||||
@@ -11,9 +11,9 @@ Subscriber = require 'subscriber'
|
||||
|
||||
module.exports =
|
||||
class LanguageMode
|
||||
buffer = null
|
||||
grammar = null
|
||||
editSession = null
|
||||
buffer: null
|
||||
grammar: null
|
||||
editSession: null
|
||||
currentGrammarScore: null
|
||||
|
||||
# Public: Sets up a `LanguageMode` for the given {EditSession}.
|
||||
@@ -21,28 +21,11 @@ class LanguageMode
|
||||
# editSession - The {EditSession} to associate with
|
||||
constructor: (@editSession) ->
|
||||
@buffer = @editSession.buffer
|
||||
@reloadGrammar()
|
||||
@subscribe syntax, 'grammar-added', (grammar) =>
|
||||
newScore = grammar.getScore(@buffer.getPath(), @buffer.getText())
|
||||
@setGrammar(grammar, newScore) if newScore > @currentGrammarScore
|
||||
|
||||
|
||||
# Internal:
|
||||
destroy: ->
|
||||
@unsubscribe()
|
||||
|
||||
setGrammar: (grammar, score) ->
|
||||
return if grammar is @grammar
|
||||
@unsubscribe(@grammar) if @grammar
|
||||
@grammar = grammar
|
||||
@currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText())
|
||||
@subscribe @grammar, 'grammar-updated', => @trigger 'grammar-updated'
|
||||
@trigger 'grammar-changed', grammar
|
||||
|
||||
reloadGrammar: ->
|
||||
if grammar = syntax.selectGrammar(@buffer.getPath(), @buffer.getText())
|
||||
@setGrammar(grammar)
|
||||
else
|
||||
throw new Error("No grammar found for path: #{path}")
|
||||
|
||||
# Public: Wraps the lines between two rows in comments.
|
||||
#
|
||||
@@ -91,6 +74,34 @@ class LanguageMode
|
||||
for row in [start..end]
|
||||
buffer.insert([row, 0], commentStartString)
|
||||
|
||||
# Public: Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
for currentRow in [0..@buffer.getLastRow()]
|
||||
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
continue unless startRow?
|
||||
|
||||
@editSession.createFold(startRow, endRow)
|
||||
|
||||
# Public: Unfolds all the foldable lines in the buffer.
|
||||
unfoldAll: ->
|
||||
for row in [@buffer.getLastRow()..0]
|
||||
fold.destroy() for fold in @editSession.displayBuffer.foldsStartingAtBufferRow(row)
|
||||
|
||||
foldBufferRow: (bufferRow) ->
|
||||
for currentRow in [bufferRow..0]
|
||||
rowRange = @rowRangeForCommentAtBufferRow(currentRow)
|
||||
rowRange ?= @rowRangeForFoldAtBufferRow(currentRow)
|
||||
[startRow, endRow] = rowRange ? []
|
||||
continue unless startRow? and startRow <= bufferRow <= endRow
|
||||
fold = @editSession.displayBuffer.largestFoldStartingAtBufferRow(startRow)
|
||||
return @editSession.createFold(startRow, endRow) unless fold
|
||||
|
||||
# Public: Given a buffer row, this unfolds it.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
unfoldBufferRow: (bufferRow) ->
|
||||
@editSession.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy()
|
||||
|
||||
doesBufferRowStartFold: (bufferRow) ->
|
||||
return false if @editSession.isBufferRowBlank(bufferRow)
|
||||
nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow)
|
||||
@@ -114,9 +125,24 @@ class LanguageMode
|
||||
|
||||
[bufferRow, foldEndRow]
|
||||
|
||||
rowRangeForCommentAtBufferRow: (row) ->
|
||||
return unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
|
||||
|
||||
startRow = row
|
||||
for currentRow in [row-1..0]
|
||||
break if @buffer.isRowBlank(currentRow)
|
||||
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
startRow = currentRow
|
||||
endRow = row
|
||||
for currentRow in [row+1..@buffer.getLastRow()]
|
||||
break if @buffer.isRowBlank(currentRow)
|
||||
break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
|
||||
endRow = currentRow
|
||||
return [startRow, endRow] if startRow isnt endRow
|
||||
|
||||
# Public: Given a buffer row, this returns a suggested indentation level.
|
||||
#
|
||||
# The indentation level provided is based on the current {LanguageMode}.
|
||||
# The indentation level provided is based on the current {LanguageMode}.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
#
|
||||
|
||||
@@ -62,14 +62,14 @@ class LineMap
|
||||
|
||||
bufferRows
|
||||
|
||||
screenLineCount: ->
|
||||
getScreenLineCount: ->
|
||||
@screenLines.length
|
||||
|
||||
# Retrieves the last screen row in the buffer.
|
||||
#
|
||||
# Returns an {Integer}.
|
||||
lastScreenRow: ->
|
||||
@screenLineCount() - 1
|
||||
@getScreenLineCount() - 1
|
||||
|
||||
clipScreenPosition: (screenPosition, options={}) ->
|
||||
{ wrapBeyondNewlines, wrapAtSoftNewlines } = options
|
||||
@@ -139,6 +139,7 @@ class LineMap
|
||||
currentBufferRow = nextBufferRow
|
||||
|
||||
[screenRow, screenLines]
|
||||
|
||||
# Public: Given a buffer range, this converts it into a screen position.
|
||||
#
|
||||
# screenPosition - An object that represents a buffer position. It can be either
|
||||
@@ -172,6 +173,7 @@ class LineMap
|
||||
start = @screenPositionForBufferPosition(bufferRange.start)
|
||||
end = @screenPositionForBufferPosition(bufferRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
# Public: Given a screen range, this converts it into a buffer position.
|
||||
#
|
||||
# screenRange - The {Range} to convert
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
ConfigPanel = require 'config-panel'
|
||||
{$$} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
module.exports =
|
||||
class PackageConfigPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@div =>
|
||||
@legend "Installed Packages"
|
||||
|
||||
@table id: 'packages', class: "table table-striped", =>
|
||||
@thead =>
|
||||
@tr =>
|
||||
@th "Package Name"
|
||||
@th class: 'package-enabled', "Enable"
|
||||
|
||||
@tbody outlet: 'packageTableBody', =>
|
||||
for name in atom.getAvailablePackageNames().sort()
|
||||
@tr name: name, =>
|
||||
@td name
|
||||
@td class: 'package-enabled', => @input type: 'checkbox'
|
||||
|
||||
initialize: ->
|
||||
@on 'change', '#packages input[type=checkbox]', (e) ->
|
||||
checkbox = $(e.target)
|
||||
name = checkbox.closest('tr').attr('name')
|
||||
if checkbox.attr('checked')
|
||||
_.remove(config.get('core.disabledPackages'), name)
|
||||
else
|
||||
config.get('core.disabledPackages').push(name)
|
||||
config.update()
|
||||
|
||||
@observeConfig 'core.disabledPackages', (disabledPackages) =>
|
||||
@packageTableBody.find("input[type='checkbox']").attr('checked', true)
|
||||
for name in disabledPackages
|
||||
@packageTableBody.find("tr[name='#{name}'] input[type='checkbox']").attr('checked', false)
|
||||
@@ -1,15 +1,16 @@
|
||||
Point = require 'point'
|
||||
_ = require 'underscore'
|
||||
|
||||
# Public: Indicates a region within the editor.
|
||||
# Public: Indicates a region within the editor.
|
||||
#
|
||||
# To better visualize how this works, imagine a rectangle.
|
||||
# Each quadrant of the rectangle is analogus to a range, as ranges contain a
|
||||
# Each quadrant of the rectangle is analogus to a range, as ranges contain a
|
||||
# starting row and a starting column, as well as an ending row, and an ending column.
|
||||
#
|
||||
# Each `Range` is actually constructed of two `Point` objects, labelled `start` and `end`.
|
||||
module.exports =
|
||||
class Range
|
||||
|
||||
# Public: Constructs a `Range` from a given object.
|
||||
#
|
||||
# object - This can be an {Array} (`[startRow, startColumn, endRow, endColumn]`) or an object `{start: Point, end: Point}`
|
||||
@@ -58,7 +59,7 @@ class Range
|
||||
|
||||
# Public: Identifies if two `Range`s are equal.
|
||||
#
|
||||
# All four points (`start.row`, `start.column`, `end.row`, `end.column`) must be
|
||||
# All four points (`start.row`, `start.column`, `end.row`, `end.column`) must be
|
||||
# equal for this method to return `true`.
|
||||
#
|
||||
# other - A different {Range} to check against
|
||||
|
||||
@@ -23,6 +23,7 @@ class RootView extends View
|
||||
@configDefaults:
|
||||
ignoredNames: [".git", ".svn", ".DS_Store"]
|
||||
disabledPackages: []
|
||||
themes: ['atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
###
|
||||
# Internal:
|
||||
@@ -33,13 +34,12 @@ class RootView extends View
|
||||
@div id: 'horizontal', outlet: 'horizontal', =>
|
||||
@div id: 'vertical', outlet: 'vertical', =>
|
||||
@subview 'panes', panes ? new PaneContainer
|
||||
|
||||
|
||||
@deserialize: ({ panes }) ->
|
||||
panes = deserialize(panes) if panes?.deserializer is 'PaneContainer'
|
||||
new RootView({panes})
|
||||
|
||||
initialize: ->
|
||||
@command 'toggle-dev-tools', => atom.toggleDevTools()
|
||||
@on 'focus', (e) => @handleFocus(e)
|
||||
@subscribe $(window), 'focus', (e) =>
|
||||
@handleFocus(e) if document.activeElement is document.body
|
||||
@@ -74,6 +74,9 @@ class RootView extends View
|
||||
@command 'pane:reopen-closed-item', =>
|
||||
@panes.reopenItem()
|
||||
|
||||
@command 'new-editor', =>
|
||||
@open()
|
||||
|
||||
serialize: ->
|
||||
version: RootView.version
|
||||
deserializer: 'RootView'
|
||||
|
||||
@@ -117,6 +117,7 @@ class TextMateGrammar
|
||||
ruleStack = new Array(ruleStack...) # clone ruleStack
|
||||
tokens = []
|
||||
position = 0
|
||||
|
||||
loop
|
||||
scopes = scopesFromStack(ruleStack)
|
||||
previousRuleStackLength = ruleStack.length
|
||||
@@ -154,13 +155,30 @@ class TextMateGrammar
|
||||
))
|
||||
break
|
||||
|
||||
if position == previousPosition and ruleStack.length == previousRuleStackLength
|
||||
console.error("Popping rule because it loops at column #{position} of line '#{line}'", _.clone(ruleStack))
|
||||
ruleStack.pop()
|
||||
if position == previousPosition
|
||||
if ruleStack.length == previousRuleStackLength
|
||||
console.error("Popping rule because it loops at column #{position} of line '#{line}'", _.clone(ruleStack))
|
||||
ruleStack.pop()
|
||||
|
||||
[penultimateRule, lastRule] = ruleStack[-2..]
|
||||
if lastRule? and penultimateRule.scopeName == lastRule.scopeName
|
||||
ruleStack.pop()
|
||||
tokens.push(new Token(
|
||||
value: line[position...line.length]
|
||||
scopes: scopes
|
||||
))
|
||||
break
|
||||
|
||||
ruleStack.forEach (rule) -> rule.clearAnchorPosition()
|
||||
{ tokens, ruleStack }
|
||||
|
||||
tokenizeLines: (text) ->
|
||||
lines = text.split('\n')
|
||||
ruleStack = null
|
||||
for line, i in lines
|
||||
{ tokens, ruleStack } = @tokenizeLine(line, ruleStack, i is 0)
|
||||
tokens
|
||||
|
||||
getMaxTokensPerLine: ->
|
||||
@maxTokensPerLine
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ class TextMatePackage extends Package
|
||||
for { selector, properties } in @scopedProperties
|
||||
syntax.addProperties(@path, selector, properties)
|
||||
|
||||
activateConfig: -> # noop
|
||||
|
||||
deactivate: ->
|
||||
syntax.removeGrammar(grammar) for grammar in @grammars
|
||||
syntax.removeProperties(@path)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
ConfigPanel = require 'config-panel'
|
||||
{$$} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
window.jQuery = $
|
||||
require 'jqueryui-browser/ui/jquery.ui.core'
|
||||
require 'jqueryui-browser/ui/jquery.ui.widget'
|
||||
require 'jqueryui-browser/ui/jquery.ui.mouse'
|
||||
require 'jqueryui-browser/ui/jquery.ui.sortable'
|
||||
require 'jqueryui-browser/ui/jquery.ui.draggable'
|
||||
delete window.jQuery
|
||||
|
||||
module.exports =
|
||||
class ThemeConfigPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@div id: 'themes-config', =>
|
||||
@legend "Themes"
|
||||
@div id: 'theme-picker', =>
|
||||
@div class: 'panel', =>
|
||||
@div class: 'panel-heading', "Enabled Themes"
|
||||
@ol id: 'enabled-themes', class: 'list-group list-group-flush', outlet: 'enabledThemes'
|
||||
@div class: 'panel', =>
|
||||
@div class: 'panel-heading', "Available Themes"
|
||||
@ol id: 'available-themes', class: 'list-group list-group-flush', outlet: 'availableThemes'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
for name in atom.getAvailableThemeNames()
|
||||
@availableThemes.append(@buildThemeLi(name, draggable: true))
|
||||
|
||||
@observeConfig "core.themes", (enabledThemes) =>
|
||||
@enabledThemes.empty()
|
||||
for name in enabledThemes ? []
|
||||
@enabledThemes.append(@buildThemeLi(name))
|
||||
|
||||
@enabledThemes.sortable
|
||||
receive: (e, ui) => @enabledThemeReceived($(ui.helper))
|
||||
update: => @enabledThemesUpdated()
|
||||
|
||||
@on "click", "#enabled-themes .disable-theme", (e) =>
|
||||
$(e.target).closest('li').remove()
|
||||
@enabledThemesUpdated()
|
||||
|
||||
buildThemeLi: (name, {draggable} = {}) ->
|
||||
li = $$ ->
|
||||
@li class: 'list-group-item', name: name, =>
|
||||
@div class: 'disable-theme pull-right'
|
||||
@text name
|
||||
if draggable
|
||||
li.draggable
|
||||
connectToSortable: '#enabled-themes'
|
||||
appendTo: '#themes-config'
|
||||
helper: (e) ->
|
||||
target = $(e.target)
|
||||
target.clone().width(target.width())
|
||||
else
|
||||
li
|
||||
|
||||
enabledThemeReceived: (helper) ->
|
||||
name = helper.attr('name')
|
||||
@enabledThemes.find("[name='#{name}']:not('.ui-draggable')").remove()
|
||||
@enabledThemes.find(".ui-draggable").removeClass('ui-draggable')
|
||||
|
||||
enabledThemesUpdated: ->
|
||||
config.set('core.themes', @getEnabledThemeNames())
|
||||
|
||||
getEnabledThemeNames: ->
|
||||
$(li).attr('name') for li in @enabledThemes.children().toArray()
|
||||
@@ -14,7 +14,8 @@ module.exports =
|
||||
class TokenizedBuffer
|
||||
@idCounter: 1
|
||||
|
||||
languageMode: null
|
||||
grammar: null
|
||||
currentGrammarScore: null
|
||||
tabLength: null
|
||||
buffer: null
|
||||
aceAdaptor: null
|
||||
@@ -23,15 +24,36 @@ class TokenizedBuffer
|
||||
invalidRows: null
|
||||
visible: false
|
||||
|
||||
constructor: (@buffer, { @languageMode, @tabLength }) ->
|
||||
constructor: (@buffer, { @tabLength } = {}) ->
|
||||
@tabLength ?= 2
|
||||
@id = @constructor.idCounter++
|
||||
|
||||
@subscribe syntax, 'grammar-added grammar-updated', (grammar) =>
|
||||
if grammar.injectionSelector?
|
||||
@resetScreenLines() if @hasTokenForSelector(grammar.injectionSelector)
|
||||
else
|
||||
newScore = grammar.getScore(@buffer.getPath(), @buffer.getText())
|
||||
@setGrammar(grammar, newScore) if newScore > @currentGrammarScore
|
||||
|
||||
@on 'grammar-changed grammar-updated', => @resetScreenLines()
|
||||
@subscribe @buffer, "changed.tokenized-buffer#{@id}", (e) => @handleBufferChange(e)
|
||||
|
||||
@reloadGrammar()
|
||||
|
||||
setGrammar: (grammar, score) ->
|
||||
return if grammar is @grammar
|
||||
@unsubscribe(@grammar) if @grammar
|
||||
@grammar = grammar
|
||||
@currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText())
|
||||
@subscribe @grammar, 'grammar-updated', => @resetScreenLines()
|
||||
@resetScreenLines()
|
||||
@buffer.on "changed.tokenized-buffer#{@id}", (e) => @handleBufferChange(e)
|
||||
@languageMode.on 'grammar-changed grammar-updated', => @resetScreenLines()
|
||||
@subscribe syntax, 'grammar-updated grammar-added', (grammar) =>
|
||||
if grammar.injectionSelector? and @hasTokenForSelector(grammar.injectionSelector)
|
||||
@resetScreenLines()
|
||||
@trigger 'grammar-changed', grammar
|
||||
|
||||
reloadGrammar: ->
|
||||
if grammar = syntax.selectGrammar(@buffer.getPath(), @buffer.getText())
|
||||
@setGrammar(grammar)
|
||||
else
|
||||
throw new Error("No grammar found for path: #{path}")
|
||||
|
||||
hasTokenForSelector: (selector) ->
|
||||
for {tokens} in @screenLines
|
||||
@@ -154,13 +176,13 @@ class TokenizedBuffer
|
||||
|
||||
buildPlaceholderScreenLineForRow: (row) ->
|
||||
line = @buffer.lineForRow(row)
|
||||
tokens = [new Token(value: line, scopes: [@languageMode.grammar.scopeName])]
|
||||
tokens = [new Token(value: line, scopes: [@grammar.scopeName])]
|
||||
new ScreenLine({tokens, @tabLength})
|
||||
|
||||
buildTokenizedScreenLineForRow: (row, ruleStack) ->
|
||||
line = @buffer.lineForRow(row)
|
||||
lineEnding = @buffer.lineEndingForRow(row)
|
||||
{ tokens, ruleStack } = @languageMode.tokenizeLine(line, ruleStack, row is 0)
|
||||
{ tokens, ruleStack } = @grammar.tokenizeLine(line, ruleStack, row is 0)
|
||||
new ScreenLine({tokens, ruleStack, @tabLength, lineEnding})
|
||||
|
||||
lineForScreenRow: (row) ->
|
||||
@@ -180,6 +202,7 @@ class TokenizedBuffer
|
||||
@screenLines[position.row].tokenAtBufferColumn(position.column)
|
||||
|
||||
destroy: ->
|
||||
@unsubscribe()
|
||||
@buffer.off ".tokenized-buffer#{@id}"
|
||||
|
||||
iterateTokensInBufferRange: (bufferRange, iterator) ->
|
||||
|
||||
+34
-6
@@ -35,27 +35,41 @@ window.setUpEnvironment = ->
|
||||
requireStylesheet(nativeStylesheetPath)
|
||||
|
||||
# This method is only called when opening a real application window
|
||||
window.startup = ->
|
||||
window.startEditorWindow = ->
|
||||
directory = _.find ['/opt/boxen', '/opt/github', '/usr/local'], (dir) -> fsUtils.isDirectory(dir)
|
||||
if directory
|
||||
installAtomCommand(fsUtils.join(directory, 'bin/atom'))
|
||||
else
|
||||
console.warn "Failed to install `atom` binary"
|
||||
|
||||
atom.windowMode = 'editor'
|
||||
handleWindowEvents()
|
||||
handleDragDrop()
|
||||
config.load()
|
||||
keymap.loadBundledKeymaps()
|
||||
atom.loadThemes()
|
||||
atom.loadPackages()
|
||||
deserializeWindowState()
|
||||
deserializeEditorWindow()
|
||||
atom.activatePackages()
|
||||
keymap.loadUserKeymaps()
|
||||
atom.requireUserInitScript()
|
||||
$(window).on 'beforeunload', -> shutdown(); false
|
||||
$(window).on 'beforeunload', -> unloadEditorWindow(); false
|
||||
$(window).focus()
|
||||
|
||||
window.shutdown = ->
|
||||
window.startConfigWindow = ->
|
||||
atom.windowMode = 'config'
|
||||
handleWindowEvents()
|
||||
config.load()
|
||||
keymap.loadBundledKeymaps()
|
||||
atom.loadThemes()
|
||||
atom.loadPackages()
|
||||
deserializeConfigWindow()
|
||||
atom.activatePackageConfigs()
|
||||
keymap.loadUserKeymaps()
|
||||
$(window).on 'beforeunload', -> unloadConfigWindow(); false
|
||||
$(window).focus()
|
||||
|
||||
window.unloadEditorWindow = ->
|
||||
return if not project and not rootView
|
||||
atom.setWindowState('pathToOpen', project.getPath())
|
||||
atom.setWindowState('project', project.serialize())
|
||||
@@ -88,6 +102,14 @@ window.installAtomCommand = (commandPath, done) ->
|
||||
else
|
||||
fs.chmod(commandPath, 0o755, commandPath)
|
||||
|
||||
window.unloadConfigWindow = ->
|
||||
return if not configView
|
||||
atom.setWindowState('configView', configView.serialize())
|
||||
atom.saveWindowState()
|
||||
configView.remove()
|
||||
window.configView = null
|
||||
$(window).off('focus blur before')
|
||||
|
||||
window.handleWindowEvents = ->
|
||||
$(window).command 'window:toggle-full-screen', => atom.toggleFullScreen()
|
||||
$(window).on 'focus', -> $("body").removeClass('is-blurred')
|
||||
@@ -107,7 +129,7 @@ window.onDrop = (e) ->
|
||||
for file in e.originalEvent.dataTransfer.files
|
||||
atom.open(file.path)
|
||||
|
||||
window.deserializeWindowState = ->
|
||||
window.deserializeEditorWindow = ->
|
||||
RootView = require 'root-view'
|
||||
Project = require 'project'
|
||||
Git = require 'git'
|
||||
@@ -130,8 +152,14 @@ window.deserializeWindowState = ->
|
||||
window.git?.destroy()
|
||||
window.git = Git.open(project.getPath())
|
||||
|
||||
window.deserializeConfigWindow = ->
|
||||
ConfigView = require 'config-view'
|
||||
windowState = atom.getWindowState()
|
||||
window.configView = deserialize(windowState.configView) ? new ConfigView()
|
||||
$(rootViewParentSelector).append(configView)
|
||||
|
||||
window.stylesheetElementForId = (id) ->
|
||||
$("head style[id='#{id}']")
|
||||
$("""head style[id="#{id}"]""")
|
||||
|
||||
window.resolveStylesheet = (path) ->
|
||||
if fsUtils.extension(path).length > 0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
date = new Date().getTime()
|
||||
require 'atom'
|
||||
require 'window'
|
||||
|
||||
window.setUpEnvironment()
|
||||
window.startConfigWindow()
|
||||
atom.show()
|
||||
console.log "Load time: #{new Date().getTime() - date}"
|
||||
@@ -6,8 +6,8 @@ module.exports =
|
||||
class CommandLoggerView extends ScrollView
|
||||
@content: (rootView) ->
|
||||
@div class: 'command-logger', tabindex: -1, =>
|
||||
@h1 class: 'category-header', outlet: 'categoryHeader'
|
||||
@h1 class: 'category-summary', outlet: 'categorySummary'
|
||||
@h4 class: 'category-header', outlet: 'categoryHeader'
|
||||
@h5 class: 'category-summary', outlet: 'categorySummary'
|
||||
@div class: 'tree-map', outlet: 'treeMap'
|
||||
|
||||
eventLog: null
|
||||
|
||||
@@ -35,6 +35,7 @@ module.exports =
|
||||
{@eventLog}
|
||||
|
||||
createView: ->
|
||||
unless @commandLoggerView
|
||||
CommandLoggerView = require 'command-logger/lib/command-logger-view'
|
||||
unless @commandLoggerView?
|
||||
CommandLoggerView = require './command-logger-view'
|
||||
@commandLoggerView = new CommandLoggerView
|
||||
@commandLoggerView
|
||||
|
||||
@@ -4,6 +4,7 @@ RegexAddress = require './commands/regex-address'
|
||||
CompositeCommand = require './commands/composite-command'
|
||||
PreviewList = require './preview-list'
|
||||
Editor = require 'editor'
|
||||
EditSession = require 'edit-session'
|
||||
{SyntaxError} = require('pegjs').parser
|
||||
_ = require 'underscore'
|
||||
|
||||
@@ -11,7 +12,8 @@ module.exports =
|
||||
class CommandPanelView extends View
|
||||
@content: ->
|
||||
@div class: 'command-panel tool-panel', =>
|
||||
@div class: 'loading is-loading', outlet: 'loadingMessage', 'Searching...'
|
||||
@div class: 'loading is-loading', outlet: 'loadingMessage', =>
|
||||
@span 'Searching...'
|
||||
@div class: 'header', outlet: 'previewHeader', =>
|
||||
@button outlet: 'collapseAll', class: 'btn btn-mini pull-right', 'Collapse All'
|
||||
@button outlet: 'expandAll', class: 'btn btn-mini pull-right', 'Expand All'
|
||||
@@ -40,8 +42,8 @@ class CommandPanelView extends View
|
||||
|
||||
@subscribeToCommand rootView, 'command-panel:toggle', => @toggle()
|
||||
@subscribeToCommand rootView, 'command-panel:toggle-preview', => @togglePreview()
|
||||
@subscribeToCommand rootView, 'command-panel:find-in-file', => @attach('/')
|
||||
@subscribeToCommand rootView, 'command-panel:find-in-project', => @attach('Xx/')
|
||||
@subscribeToCommand rootView, 'command-panel:find-in-file', => @findInFile()
|
||||
@subscribeToCommand rootView, 'command-panel:find-in-project', => @findInProject()
|
||||
@subscribeToCommand rootView, 'command-panel:repeat-relative-address', => @repeatRelativeAddress()
|
||||
@subscribeToCommand rootView, 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddress(reverse: true)
|
||||
@subscribeToCommand rootView, 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
@@ -96,22 +98,38 @@ class CommandPanelView extends View
|
||||
@previewList.collapseAllPaths()
|
||||
@previewList.focus()
|
||||
|
||||
attach: (text='', options={}) ->
|
||||
attach: (text, options={}) ->
|
||||
@errorMessages.hide()
|
||||
|
||||
focus = options.focus ? true
|
||||
rootView.vertical.append(this)
|
||||
@miniEditor.focus() if focus
|
||||
@miniEditor.setText(text)
|
||||
@miniEditor.setCursorBufferPosition([0, Infinity])
|
||||
if text?
|
||||
@miniEditor.setText(text)
|
||||
@miniEditor.setCursorBufferPosition([0, Infinity])
|
||||
else
|
||||
@miniEditor.selectAll()
|
||||
|
||||
detach: ->
|
||||
@miniEditor.setText('')
|
||||
rootView.focus()
|
||||
@previewList.hide()
|
||||
@previewHeader.hide()
|
||||
super
|
||||
|
||||
findInFile: ->
|
||||
if @miniEditor.getText()[0] is '/'
|
||||
@attach()
|
||||
@miniEditor.setSelectedBufferRange([[0, 1], [0, Infinity]])
|
||||
else
|
||||
@attach('/')
|
||||
|
||||
findInProject: ->
|
||||
if @miniEditor.getText().indexOf('Xx/') is 0
|
||||
@attach()
|
||||
@miniEditor.setSelectedBufferRange([[0, 3], [0, Infinity]])
|
||||
else
|
||||
@attach('Xx/')
|
||||
|
||||
escapedCommand: ->
|
||||
@miniEditor.getText()
|
||||
|
||||
@@ -122,7 +140,9 @@ class CommandPanelView extends View
|
||||
@errorMessages.empty()
|
||||
|
||||
try
|
||||
@commandInterpreter.eval(command, rootView.getActivePaneItem()).done ({operationsToPreview, errorMessages}) =>
|
||||
activePaneItem = rootView.getActivePaneItem()
|
||||
editSession = activePaneItem if activePaneItem instanceof EditSession
|
||||
@commandInterpreter.eval(command, editSession).done ({operationsToPreview, errorMessages}) =>
|
||||
@loadingMessage.hide()
|
||||
@history.push(command)
|
||||
@historyIndex = @history.length
|
||||
|
||||
@@ -76,7 +76,7 @@ describe "CommandPanel", ->
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
expect(rootViewCloseHandler).not.toHaveBeenCalled()
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
expect(commandPanel.miniEditor.getText()).toBe ''
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
|
||||
describe "when core:cancel is triggered on the command panel's mini editor", ->
|
||||
it "detaches the command panel, focuses the RootView and does not bubble the core:cancel event", ->
|
||||
@@ -91,7 +91,7 @@ describe "CommandPanel", ->
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
expect(rootViewCancelHandler).not.toHaveBeenCalled()
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
expect(commandPanel.miniEditor.getText()).toBe ''
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
|
||||
describe "when command-panel:toggle is triggered on the root view", ->
|
||||
beforeEach ->
|
||||
@@ -115,6 +115,16 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
expect(commandPanel.miniEditor.hiddenInput).toMatchSelector ':focus'
|
||||
|
||||
describe "when the command panel is opened a second time", ->
|
||||
it "displays and selects the previously entered text", ->
|
||||
commandPanel.miniEditor.setText('command1')
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command1'
|
||||
expect(commandPanel.miniEditor.getSelectedText()).toBe 'command1'
|
||||
|
||||
describe "when the command panel is not visible", ->
|
||||
it "shows and focuses the command panel", ->
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
@@ -289,28 +299,54 @@ describe "CommandPanel", ->
|
||||
expect(commandInterpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/\\(items\\)/i"
|
||||
|
||||
describe "when command-panel:find-in-file is triggered on an editor", ->
|
||||
it "pre-populates the command panel's editor with / and moves the cursor to the last column", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
describe "when the command panel's editor does not begin with /", ->
|
||||
it "pre-populates the command panel's editor with / and moves the cursor to the last column", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
|
||||
rootView.getActiveView().trigger "command-panel:find-in-file"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "/"
|
||||
expect(commandPanel.miniEditor.getCursorBufferPosition()).toEqual [0, 1]
|
||||
rootView.getActiveView().trigger "command-panel:find-in-file"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "/"
|
||||
expect(commandPanel.miniEditor.getCursorBufferPosition()).toEqual [0, 1]
|
||||
|
||||
describe "when the command panel's editor begins with /", ->
|
||||
it "selects text after the /", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("/foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
|
||||
rootView.getActiveView().trigger "command-panel:find-in-file"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "/foo"
|
||||
expect(commandPanel.miniEditor.getSelectedText()).toBe "foo"
|
||||
|
||||
describe "when command-panel:find-in-project is triggered on the root view", ->
|
||||
it "pre-populates the command panel's editor with Xx/ and moves the cursor to the last column", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
describe "when the command panel's editor does not begin with Xx/", ->
|
||||
it "pre-populates the command panel's editor with Xx/ and moves the cursor to the last column", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
|
||||
rootView.trigger "command-panel:find-in-project"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "Xx/"
|
||||
expect(commandPanel.miniEditor.getCursorBufferPosition()).toEqual [0, 3]
|
||||
rootView.trigger "command-panel:find-in-project"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "Xx/"
|
||||
expect(commandPanel.miniEditor.getCursorBufferPosition()).toEqual [0, 3]
|
||||
|
||||
describe "when the command panel's editor begins with Xx/", ->
|
||||
it "selects text after the Xx/", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("Xx/foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
|
||||
rootView.getActiveView().trigger "command-panel:find-in-project"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "Xx/foo"
|
||||
expect(commandPanel.miniEditor.getSelectedText()).toBe "foo"
|
||||
|
||||
describe "when return is pressed on the panel's editor", ->
|
||||
describe "if the command has an immediate effect", ->
|
||||
@@ -548,3 +584,13 @@ describe "CommandPanel", ->
|
||||
previewList.trigger 'command-panel:expand-result'
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeVisible()
|
||||
expect(previewList.find('li.path:first-child')).toHaveClass 'selected'
|
||||
|
||||
describe "when the active pane item is not an EditSession", ->
|
||||
it "doesn't throw an error (regression)", ->
|
||||
rootView.open('binary-file.png')
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
executePromise = null
|
||||
expect(-> executePromise = commandPanel.execute('Xx/sort/')).not.toThrow()
|
||||
|
||||
waitsForPromise -> executePromise
|
||||
|
||||
@@ -3,17 +3,28 @@
|
||||
padding: 0;
|
||||
|
||||
.is-loading {
|
||||
display: block;
|
||||
margin: 0 auto 10px auto;
|
||||
width: 100px;
|
||||
background-color: #111111;
|
||||
background-size: auto;
|
||||
background-position: 5px 5px;
|
||||
padding: 5px 5px 10px 30px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
border-top: 1px solid rgba(0,0,0,1);
|
||||
border-left: 1px solid rgba(0,0,0,1);
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
padding: 5px 10px 5px 10px;
|
||||
background-color: #111111;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
border-top: 1px solid rgba(0,0,0,1);
|
||||
border-left: 1px solid rgba(0,0,0,1);
|
||||
|
||||
&:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 14px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-right: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
content: '\f09e';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-count {
|
||||
|
||||
@@ -79,6 +79,36 @@
|
||||
'name': 'markup.code.css.gfm'
|
||||
'patterns': ['include': 'source.css']
|
||||
}
|
||||
{
|
||||
'begin': '^```xml$'
|
||||
'beginCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'end': '^```$'
|
||||
'endCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'name': 'markup.code.xml.gfm'
|
||||
'patterns': ['include': 'text.xml']
|
||||
}
|
||||
{
|
||||
'begin': '^```(ruby|rb)$'
|
||||
'beginCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'end': '^```$'
|
||||
'endCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'name': 'markup.code.ruby.gfm'
|
||||
'patterns': ['include': 'source.ruby']
|
||||
}
|
||||
{
|
||||
'begin': '^```java$'
|
||||
'beginCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'end': '^```$'
|
||||
'endCaptures':
|
||||
'0': 'name': 'support.gfm'
|
||||
'name': 'markup.code.java.gfm'
|
||||
'patterns': ['include': 'source.java']
|
||||
}
|
||||
{
|
||||
'begin': '^```.*$'
|
||||
'beginCaptures':
|
||||
|
||||
@@ -192,8 +192,7 @@ describe "StatusBar", ->
|
||||
|
||||
it "hides the label when the current grammar is the null grammar", ->
|
||||
rootView.attachToDom()
|
||||
editor.activeEditSession.languageMode.grammar = syntax.nullGrammar
|
||||
editor.activeEditSession.trigger 'grammar-changed'
|
||||
editor.activeEditSession.setGrammar(syntax.nullGrammar)
|
||||
expect(statusBar.find('.grammar-name')).toBeHidden()
|
||||
editor.reloadGrammar()
|
||||
expect(statusBar.find('.grammar-name')).toBeVisible()
|
||||
|
||||
@@ -106,8 +106,13 @@ module.exports =
|
||||
done(null, paths)
|
||||
|
||||
filterExtensions: (paths, extensions) ->
|
||||
extensions = extensions.map (ext) -> '.' + ext.replace(/^\./, '')
|
||||
paths.filter (path) => _.include(extensions, @extension(path))
|
||||
extensions = extensions.map (ext) ->
|
||||
if ext is ''
|
||||
ext
|
||||
else
|
||||
'.' + ext.replace(/^\./, '')
|
||||
paths.filter (path) =>
|
||||
_.include(extensions, @extension(path))
|
||||
|
||||
listTree: (rootPath) ->
|
||||
paths = []
|
||||
|
||||
@@ -62,7 +62,7 @@ _.mixin
|
||||
|
||||
humanizeEventName: (eventName, eventDoc) ->
|
||||
[namespace, event] = eventName.split(':')
|
||||
return _.capitalize(namespace) unless event?
|
||||
return _.undasherize(namespace) unless event?
|
||||
|
||||
namespaceDoc = _.undasherize(namespace)
|
||||
eventDoc ?= _.undasherize(event)
|
||||
@@ -139,7 +139,10 @@ _.mixin
|
||||
key = keys.shift()
|
||||
object[key] ?= {}
|
||||
object = object[key]
|
||||
object[keys.shift()] = value
|
||||
if value?
|
||||
object[keys.shift()] = value
|
||||
else
|
||||
delete object[keys.shift()]
|
||||
|
||||
compactObject: (object) ->
|
||||
newObject = {}
|
||||
|
||||
@@ -4,6 +4,6 @@ require 'atom'
|
||||
require 'window'
|
||||
|
||||
window.setUpEnvironment()
|
||||
window.startup()
|
||||
window.startEditorWindow()
|
||||
setTimeout((-> atom.show()), 0)
|
||||
console.log "Load time: #{new Date().getTime() - date}"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@import "bootstrap/less/bootstrap.less";
|
||||
@import "root-view.less";
|
||||
@import "config.less";
|
||||
@import "overlay.less";
|
||||
@import "popover-list.less";
|
||||
@import "notification.less";
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
@import "bootstrap/less/variables.less";
|
||||
@import "octicon-mixins.less";
|
||||
|
||||
#config-view {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: white;
|
||||
display: -webkit-flex;
|
||||
|
||||
#config-menu {
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: column;
|
||||
|
||||
#panels-menu {
|
||||
width: 150px;
|
||||
margin-left: @line-height-base;
|
||||
margin-top: @line-height-base;
|
||||
-webkit-flex-grow: 1;
|
||||
|
||||
li a {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
#open-dot-atom {
|
||||
width: 150px;
|
||||
margin-left: @line-height-base;
|
||||
margin-bottom: @line-height-base;
|
||||
}
|
||||
}
|
||||
|
||||
#panels {
|
||||
-webkit-flex: 1;
|
||||
-webkit-flex-flow: column;
|
||||
display: -webkit-flex;
|
||||
padding: @line-height-base;
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
|
||||
> div {
|
||||
-webkit-flex: 1;
|
||||
}
|
||||
|
||||
.editor {
|
||||
padding-left: 0.25em;
|
||||
border: 1px solid #aaa;
|
||||
box-shadow: 1px 1px 1px 0 #888 inset;
|
||||
}
|
||||
}
|
||||
|
||||
#themes-config {
|
||||
height: 100%;
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-flow: column;
|
||||
|
||||
#theme-picker {
|
||||
-webkit-flex: 1;
|
||||
display: -webkit-flex;
|
||||
min-height: 0;
|
||||
|
||||
.panel {
|
||||
-webkit-flex: 1;
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-flow: column;
|
||||
min-height: 0;
|
||||
&:first-child { margin-right: @line-height-base / 2; }
|
||||
&:last-child { margin-left: @line-height-base / 2; }
|
||||
|
||||
.panel-heading {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
ol {
|
||||
margin-top: 0;
|
||||
-webkit-flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
|
||||
li {
|
||||
-webkit-user-select: none;
|
||||
cursor: default;
|
||||
padding-right: 15px;
|
||||
&:first-child { border-top: 0; }
|
||||
}
|
||||
}
|
||||
|
||||
#enabled-themes {
|
||||
li:hover .disable-theme {
|
||||
.mini-icon(x);
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
&:hover { color: #000; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li.ui-draggable-dragging, li.ui-sortable-helper {
|
||||
border: 0;
|
||||
box-sizing: content-box;
|
||||
background: white;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
/* li.ui-draggable-dragging, li.ui-sortable-helper {
|
||||
width: 300px;
|
||||
background: white;
|
||||
border: 1px solid #eee;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
ol {
|
||||
box-sizing: border-box;
|
||||
height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
border-top-width: 0;
|
||||
background: #fafafa;
|
||||
|
||||
li {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
background: white;
|
||||
|
||||
input[type='checkbox'] {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
#packages {
|
||||
white-space: nowrap;
|
||||
.package-enabled {
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,6 @@
|
||||
border: 2px solid;
|
||||
background-image: url(images/transparent-background.gif);
|
||||
position: relative;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version='1.0' standalone='no'?>
|
||||
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='20px' height='20px'>
|
||||
<g>
|
||||
<circle cx='10' cy='2' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0s' />
|
||||
</circle>
|
||||
<circle cx='15.6569' cy='4.3431' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.1s' />
|
||||
</circle>
|
||||
<circle cx='18' cy='10' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.2s' />
|
||||
</circle>
|
||||
<circle cx='15.6569' cy='15.6569' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.3s' />
|
||||
</circle>
|
||||
<circle cx='10' cy='18' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.4s' />
|
||||
</circle>
|
||||
<circle cx='4.3431' cy='15.6569' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.5s' />
|
||||
</circle>
|
||||
<circle cx='2' cy='10' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.6s' />
|
||||
</circle>
|
||||
<circle cx='4.3431' cy='4.3431' r='2' style='opacity:0;fill:#fff'>
|
||||
<animate attributeType='CSS' attributeName='opacity' from='1' to='0' dur='0.8s' repeatCount='indefinite' begin='0.7s' />
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
||||
|
Antes Largura: | Altura: | Tamanho: 1.8 KiB |
@@ -72,15 +72,3 @@ html, body {
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.is-loading {
|
||||
background-image: url(images/spinner.svg);
|
||||
background-repeat: no-repeat;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
opacity: 0.5;
|
||||
background-size: contain;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding-left: 19px;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,10 @@
|
||||
|
||||
.command-logger .category-header {
|
||||
text-align: center;
|
||||
padding-bottom: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.command-logger .category-summary {
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.command-logger .tree-map {
|
||||
|
||||
externo
+3
-2
@@ -1,4 +1,5 @@
|
||||
jQuery = require('jquery');
|
||||
(function(jQuery) {
|
||||
|
||||
jasmine.JQuery = function() {};
|
||||
|
||||
jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
|
||||
@@ -174,4 +175,4 @@ beforeEach(function() {
|
||||
afterEach(function() {
|
||||
jasmine.JQuery.events.cleanUp();
|
||||
});
|
||||
|
||||
})(require('jquery'));
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário