diff --git a/Rakefile b/Rakefile index 2c5375001..e6adbba94 100644 --- a/Rakefile +++ b/Rakefile @@ -6,7 +6,7 @@ require 'erb' desc "Build Atom via `xcodebuild`" task :build => "create-project" do - command = "xcodebuild -target Atom configuration=Release SYMROOT=#{BUILD_DIR}" + command = "xcodebuild -target Atom -configuration Release SYMROOT=#{BUILD_DIR}" output = `#{command}` if $?.exitstatus != 0 $stderr.puts "Error #{$?.exitstatus}:\n#{output}" @@ -82,7 +82,8 @@ task "create-dot-atom" do `mkdir "#{DOT_ATOM_PATH}"` `cp "#{dot_atom_template_path}/atom.coffee" "#{DOT_ATOM_PATH}"` `cp "#{dot_atom_template_path}/packages" "#{DOT_ATOM_PATH}"` - `cp -r "#{dot_atom_template_path}/themes" "#{DOT_ATOM_PATH}"` + `cp -r "#{ATOM_SRC_PATH}/themes" "#{DOT_ATOM_PATH}"` + `cp "#{ATOM_SRC_PATH}/vendor/themes/IR_Black.tmTheme" "#{DOT_ATOM_PATH}/themes"` end desc "Clone default bundles into vendor/bundles directory" @@ -112,7 +113,7 @@ end desc "Run the specs" task :test => ["clean", "clone-default-bundles"] do `pkill Atom` - Rake::Task["run"].invoke("--test") + Rake::Task["run"].invoke("--test --resource-path=#{ATOM_SRC_PATH}") end desc "Run the benchmarks" diff --git a/atom.gyp b/atom.gyp index ff4abbcc3..b52c5b3ac 100644 --- a/atom.gyp +++ b/atom.gyp @@ -52,7 +52,7 @@ ], 'include_dirs': [ '.', 'cef', 'git2' ], 'mac_framework_dirs': [ 'native/frameworks' ], - 'libraries': [ 'native/frameworks/CocoaOniguruma.framework' ], + 'libraries': [ 'native/frameworks/CocoaOniguruma.framework', 'native/frameworks/Sparkle.framework'], 'sources': [ '<@(includes_common)', '<@(includes_wrapper)', @@ -71,6 +71,7 @@ 'mac_bundle_resources': [ 'native/mac/atom.icns', 'native/mac/file.icns', + 'native/mac/speakeasy.pem', 'native/mac/English.lproj/MainMenu.xib', 'native/mac/English.lproj/AtomWindow.xib', ], @@ -139,6 +140,7 @@ 'destination': '<(PRODUCT_DIR)/Atom.app/Contents/Frameworks', 'files': [ 'native/frameworks/CocoaOniguruma.framework', + 'native/frameworks/Sparkle.framework', ], }, { diff --git a/cef/Resources/cef.pak b/cef/Resources/cef.pak index f74178cd5..37fa7fb5e 100644 Binary files a/cef/Resources/cef.pak and b/cef/Resources/cef.pak differ diff --git a/cef/Resources/devtools_resources.pak b/cef/Resources/devtools_resources.pak index 4afa9320c..d56217fb7 100644 Binary files a/cef/Resources/devtools_resources.pak and b/cef/Resources/devtools_resources.pak differ diff --git a/cef/frameworks/ffmpegsumo.so b/cef/frameworks/ffmpegsumo.so index 77a27dc6a..1b77e36ea 100755 Binary files a/cef/frameworks/ffmpegsumo.so and b/cef/frameworks/ffmpegsumo.so differ diff --git a/cef/frameworks/libcef.dylib b/cef/frameworks/libcef.dylib index 772bb935c..edae81a14 100755 Binary files a/cef/frameworks/libcef.dylib and b/cef/frameworks/libcef.dylib differ diff --git a/cef/include/cef_version.h b/cef/include/cef_version.h index 8776f303f..d747de2f3 100644 --- a/cef/include/cef_version.h +++ b/cef/include/cef_version.h @@ -36,13 +36,13 @@ #define CEF_INCLUDE_CEF_VERSION_H_ #define CEF_VERSION_MAJOR 3 -#define CEF_REVISION 1050 +#define CEF_REVISION 1065 #define COPYRIGHT_YEAR 2013 #define CHROME_VERSION_MAJOR 25 #define CHROME_VERSION_MINOR 0 #define CHROME_VERSION_BUILD 1364 -#define CHROME_VERSION_PATCH 29 +#define CHROME_VERSION_PATCH 45 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) diff --git a/docs/configuring-and-extending.md b/docs/configuring-and-extending.md index f978f117d..7ecd60a04 100644 --- a/docs/configuring-and-extending.md +++ b/docs/configuring-and-extending.md @@ -79,16 +79,30 @@ ConfigObserver = require 'config-observer' _.extend MyClass.prototype, ConfigObserver ``` -# Themes (Not Yet Implemented) +# Themes ## Selecting A Theme +Atom comes bundles with two themes "Atom - Dark" and "Atom - Light". You can +select a theme in your core preferences pane. + Because Atom themes are based on CSS, it's possible to have multiple themes active at the same time. For example, you might select a theme for the UI, and another theme for syntax highlighting. You select your theme(s) in the core preferences pane, by selecting themes from the available list and dragging them in your preferred order. You can also edit the selected themes manually with the -`config.core.themes` array. +`config.core.themes` array. For example. + +```js +{ + "core": { + "themes": ["Atom - Light", "Mac Classic"] + }, + "editor": { + "fontSize": 15 + } +} +``` ## Installing A Theme @@ -140,15 +154,16 @@ matches the name of the original with an additional filename extension: ```text ~/.atom/themes/ - midnight.less - midnight.terminal.less - midnight.tree-view.less + midnight/midnight.less + midnight/packages/terminal.less + midnight/packages/tree-view.less ``` In the example above, when the `midnight` theme is loaded, its `terminal` and `tree-view` extensions will be loaded with it. If you author a theme extension, consider sending its author a pull request to have it included in the theme's -core. +core. Package theme extensions, do not need to be in `package.json` because they +will be loaded when needed by the package. ## TextMate Compatibility diff --git a/git2/frameworks/libgit2.0.17.0.dylib b/git2/frameworks/libgit2.0.17.0.dylib index 6cee2cf63..f76d63a47 100755 Binary files a/git2/frameworks/libgit2.0.17.0.dylib and b/git2/frameworks/libgit2.0.17.0.dylib differ diff --git a/native/atom_application.mm b/native/atom_application.mm index 8eab6bfc5..1e36ce37d 100644 --- a/native/atom_application.mm +++ b/native/atom_application.mm @@ -4,6 +4,7 @@ #import "native/atom_window_controller.h" #import "native/atom_cef_app.h" #import +#import @implementation AtomApplication @@ -87,9 +88,13 @@ NSString *path = [NSString stringWithUTF8String:cleanArgv[0]]; path = [self standardizePathToOpen:path withArguments:arguments]; [arguments setObject:path forKey:@"path"]; + } else { + NSString *executedFromPath = [arguments objectForKey:@"executed-from"]; + if (executedFromPath) { + [arguments setObject:executedFromPath forKey:@"path"]; + } } - return arguments; } @@ -217,6 +222,11 @@ } - (void)applicationWillFinishLaunching:(NSNotification *)notification { + SUUpdater.sharedUpdater.delegate = self; + SUUpdater.sharedUpdater.automaticallyChecksForUpdates = YES; + SUUpdater.sharedUpdater.automaticallyDownloadsUpdates = YES; + [SUUpdater.sharedUpdater checkForUpdatesInBackground]; + _backgroundWindowController = [[AtomWindowController alloc] initInBackground]; if ([self.arguments objectForKey:@"benchmark"]) { [self runBenchmarksThenExit:true]; @@ -256,4 +266,26 @@ } } +#pragma mark SUUpdaterDelegate + +- (void)updaterDidNotFindUpdate:(SUUpdater *)update { + NSLog(@"No update found"); +} + +- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update { + NSLog(@"Found Update"); +} + +- (void)updater:(SUUpdater *)updater willExtractUpdate:(SUAppcastItem *)update { + NSLog(@"Extract update"); +} + +- (void)updater:(SUUpdater *)updater willInstallUpdateOnQuit:(SUAppcastItem *)update immediateInstallationInvocation:(NSInvocation *)invocation { + NSLog(@"Install Update"); +} + +- (void)updater:(SUUpdater *)updater didCancelInstallUpdateOnQuit:(SUAppcastItem *)update { + NSLog(@"Cancel Update Install"); +} + @end diff --git a/native/atom_cef_render_process_handler.h b/native/atom_cef_render_process_handler.h index c6d979e8b..973086245 100644 --- a/native/atom_cef_render_process_handler.h +++ b/native/atom_cef_render_process_handler.h @@ -16,10 +16,22 @@ class AtomCefRenderProcessHandler : public CefRenderProcessHandler { virtual bool OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) OVERRIDE; - + virtual void OnWorkerContextCreated(int worker_id, + const CefString& url, + CefRefPtr context) OVERRIDE; + virtual void OnWorkerContextReleased(int worker_id, + const CefString& url, + CefRefPtr context) OVERRIDE; + virtual void OnWorkerUncaughtException(int worker_id, + const CefString& url, + CefRefPtr context, + CefRefPtr exception, + CefRefPtr stackTrace) OVERRIDE; + void Reload(CefRefPtr browser); void Shutdown(CefRefPtr browser); bool CallMessageReceivedHandler(CefRefPtr context, CefRefPtr message); + void InjectExtensionsIntoV8Context(CefRefPtr context); IMPLEMENT_REFCOUNTING(AtomCefRenderProcessHandler); }; diff --git a/native/atom_cef_render_process_handler.mm b/native/atom_cef_render_process_handler.mm index 2c6196906..3f74f92aa 100644 --- a/native/atom_cef_render_process_handler.mm +++ b/native/atom_cef_render_process_handler.mm @@ -9,26 +9,44 @@ #import "path_watcher.h" #include + void AtomCefRenderProcessHandler::OnWebKitInitialized() { - new v8_extensions::Atom(); - new v8_extensions::Native(); - new v8_extensions::OnigRegExp(); - new v8_extensions::OnigScanner(); - new v8_extensions::Git(); - new v8_extensions::Tags(); } void AtomCefRenderProcessHandler::OnContextCreated(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) { + CefRefPtr frame, + CefRefPtr context) { + InjectExtensionsIntoV8Context(context); } void AtomCefRenderProcessHandler::OnContextReleased(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) { + CefRefPtr frame, + CefRefPtr context) { [PathWatcher removePathWatcherForContext:context]; } +void AtomCefRenderProcessHandler::OnWorkerContextCreated(int worker_id, + const CefString& url, + CefRefPtr context) { + InjectExtensionsIntoV8Context(context); +} + +void AtomCefRenderProcessHandler::OnWorkerContextReleased(int worker_id, + const CefString& url, + CefRefPtr context) { + NSLog(@"Web worker context released"); +} + +void AtomCefRenderProcessHandler::OnWorkerUncaughtException(int worker_id, + const CefString& url, + CefRefPtr context, + CefRefPtr exception, + CefRefPtr stackTrace) { + + std::string message = exception->GetMessage().ToString(); + NSLog(@"Exception throw in worker thread %s", message.c_str()); +} + bool AtomCefRenderProcessHandler::OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) { @@ -100,3 +118,13 @@ bool AtomCefRenderProcessHandler::CallMessageReceivedHandler(CefRefPtr context) { + // these objects are deleted when the context removes all references to them + (new v8_extensions::Atom())->CreateContextBinding(context); + (new v8_extensions::Native())->CreateContextBinding(context); + (new v8_extensions::Git())->CreateContextBinding(context); + (new v8_extensions::OnigRegExp())->CreateContextBinding(context); + (new v8_extensions::OnigScanner())->CreateContextBinding(context); + (new v8_extensions::Tags())->CreateContextBinding(context); +} diff --git a/native/atom_window_controller.mm b/native/atom_window_controller.mm index 29dca8447..d61e46063 100644 --- a/native/atom_window_controller.mm +++ b/native/atom_window_controller.mm @@ -41,7 +41,7 @@ if (!background) { [self setShouldCascadeWindows:NO]; [self setWindowFrameAutosaveName:@"AtomWindow"]; - NSColor *background = [NSColor colorWithCalibratedRed:(51.0/255.0) green:(51.0/255.0f) blue:(51.0/255.0f) alpha:1.0]; + 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]; [self showWindow:self]; } diff --git a/native/frameworks/Sparkle.framework/Headers b/native/frameworks/Sparkle.framework/Headers new file mode 120000 index 000000000..a177d2a6b --- /dev/null +++ b/native/frameworks/Sparkle.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/native/frameworks/Sparkle.framework/Resources b/native/frameworks/Sparkle.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/native/frameworks/Sparkle.framework/Sparkle b/native/frameworks/Sparkle.framework/Sparkle new file mode 120000 index 000000000..b2c52731e --- /dev/null +++ b/native/frameworks/Sparkle.framework/Sparkle @@ -0,0 +1 @@ +Versions/Current/Sparkle \ No newline at end of file diff --git a/native/frameworks/Sparkle.framework/Versions/A/Headers/SUAppcast.h b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUAppcast.h new file mode 100644 index 000000000..5a60d2fda --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUAppcast.h @@ -0,0 +1,36 @@ +// +// SUAppcast.h +// Sparkle +// +// Created by Andy Matuschak on 3/12/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUAPPCAST_H +#define SUAPPCAST_H + +@class SUAppcastItem; +@interface SUAppcast : NSObject +{ +@private + NSArray *items; + NSString *userAgentString; + id delegate; + NSString *downloadFilename; + NSURLDownload *download; +} + +- (void)fetchAppcastFromURL:(NSURL *)url; +- (void)setDelegate:delegate; +- (void)setUserAgentString:(NSString *)userAgentString; + +- (NSArray *)items; + +@end + +@interface NSObject (SUAppcastDelegate) +- (void)appcastDidFinishLoading:(SUAppcast *)appcast; +- (void)appcast:(SUAppcast *)appcast failedToLoadWithError:(NSError *)error; +@end + +#endif diff --git a/native/frameworks/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h new file mode 100644 index 000000000..9f9539e1c --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h @@ -0,0 +1,61 @@ +// +// SUAppcastItem.h +// Sparkle +// +// Created by Andy Matuschak on 3/12/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUAPPCASTITEM_H +#define SUAPPCASTITEM_H + +@interface SUAppcastItem : NSObject +{ +@private + NSString *title; + NSDate *date; + NSString *itemDescription; + + NSURL *releaseNotesURL; + + NSString *DSASignature; + NSString *minimumSystemVersion; + NSString *maximumSystemVersion; + + NSURL *fileURL; + NSString *versionString; + NSString *displayVersionString; + + NSDictionary *deltaUpdates; + + NSDictionary *propertiesDictionary; + + NSURL *infoURL; // UK 2007-08-31 +} + +// Initializes with data from a dictionary provided by the RSS class. +- initWithDictionary:(NSDictionary *)dict; +- initWithDictionary:(NSDictionary *)dict failureReason:(NSString**)error; + +- (NSString *)title; +- (NSString *)versionString; +- (NSString *)displayVersionString; +- (NSDate *)date; +- (NSString *)itemDescription; +- (NSURL *)releaseNotesURL; +- (NSURL *)fileURL; +- (NSString *)DSASignature; +- (NSString *)minimumSystemVersion; +- (NSString *)maximumSystemVersion; +- (NSDictionary *)deltaUpdates; +- (BOOL)isDeltaUpdate; +- (BOOL)isCriticalUpdate; + +// Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. +- (NSDictionary *)propertiesDictionary; + +- (NSURL *)infoURL; // UK 2007-08-31 + +@end + +#endif diff --git a/native/frameworks/Sparkle.framework/Versions/A/Headers/SUUpdater.h b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUUpdater.h new file mode 100644 index 000000000..67b116e83 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUUpdater.h @@ -0,0 +1,169 @@ +// +// SUUpdater.h +// Sparkle +// +// Created by Andy Matuschak on 1/4/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUUPDATER_H +#define SUUPDATER_H + +#import "SUVersionComparisonProtocol.h" +#import "SUVersionDisplayProtocol.h" + +@class SUUpdateDriver, SUAppcastItem, SUHost, SUAppcast; + +@interface SUUpdater : NSObject +{ +@private + NSTimer *checkTimer; + SUUpdateDriver *driver; + + NSString *customUserAgentString; + SUHost *host; + IBOutlet id delegate; +} + ++ (SUUpdater *)sharedUpdater; ++ (SUUpdater *)updaterForBundle:(NSBundle *)bundle; +- initForBundle:(NSBundle *)bundle; + +- (NSBundle *)hostBundle; + +- (void)setDelegate:(id)delegate; +- delegate; + +- (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyChecks; +- (BOOL)automaticallyChecksForUpdates; + +- (void)setUpdateCheckInterval:(NSTimeInterval)interval; +- (NSTimeInterval)updateCheckInterval; + +- (void)setFeedURL:(NSURL *)feedURL; +- (NSURL *)feedURL; // *** MUST BE CALLED ON MAIN THREAD *** + +- (void)setUserAgentString:(NSString *)userAgent; +- (NSString *)userAgentString; + +- (void)setSendsSystemProfile:(BOOL)sendsSystemProfile; +- (BOOL)sendsSystemProfile; + +- (void)setAutomaticallyDownloadsUpdates:(BOOL)automaticallyDownloadsUpdates; +- (BOOL)automaticallyDownloadsUpdates; + +// This IBAction is meant for a main menu item. Hook up any menu item to this action, +// and Sparkle will check for updates and report back its findings verbosely. +- (IBAction)checkForUpdates:(id)sender; + +// This kicks off an update meant to be programmatically initiated. That is, it will display no UI unless it actually finds an update, +// in which case it proceeds as usual. If the fully automated updating is turned on, however, this will invoke that behavior, and if an +// update is found, it will be downloaded and prepped for installation. +- (void)checkForUpdatesInBackground; + +// Date of last update check. Returns nil if no check has been performed. +- (NSDate*)lastUpdateCheckDate; + +// This begins a "probing" check for updates which will not actually offer to update to that version. The delegate methods, though, +// (up to updater:didFindValidUpdate: and updaterDidNotFindUpdate:), are called, so you can use that information in your UI. +- (void)checkForUpdateInformation; + +// Call this to appropriately schedule or cancel the update checking timer according to the preferences for time interval and automatic checks. This call does not change the date of the next check, but only the internal NSTimer. +- (void)resetUpdateCycle; + +- (BOOL)updateInProgress; + +@end + + +// ----------------------------------------------------------------------------- +// SUUpdater Delegate: +// ----------------------------------------------------------------------------- + +@interface NSObject (SUUpdaterDelegateInformalProtocol) + +// Use this to keep Sparkle from popping up e.g. while your setup assistant is showing: +- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)bundle; + +// This method allows you to add extra parameters to the appcast URL, potentially based on whether or not Sparkle will also be sending along the system profile. This method should return an array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user. +- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile; + +// Override this to dynamically specify the entire URL. +- (NSString*)feedURLStringForUpdater:(SUUpdater*)updater; + +// Use this to override the default behavior for Sparkle prompting the user about automatic update checks. +- (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)bundle; + +// Implement this if you want to do some special handling with the appcast once it finishes loading. +- (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast; + +// If you're using special logic or extensions in your appcast, implement this to use your own logic for finding +// a valid update, if any, in the given appcast. +- (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast forUpdater:(SUUpdater *)bundle; + +// Sent when a valid update is found by the update driver. +- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update; + +// Sent when a valid update is not found. +- (void)updaterDidNotFindUpdate:(SUUpdater *)update; + +// Sent immediately before extracting the specified update. +- (void)updater:(SUUpdater *)updater willExtractUpdate:(SUAppcastItem *)update; + +// Sent immediately before installing the specified update. +- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update; + +// Return YES to delay the relaunch until you do some processing; invoke the given NSInvocation to continue. +// This is not called if the user didn't relaunch on the previous update, in that case it will immediately +// restart. +- (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update untilInvoking:(NSInvocation *)invocation; + +// Some apps *can not* be relaunched in certain circumstances. They can use this method +// to prevent a relaunch "hard": +- (BOOL)updaterShouldRelaunchApplication:(SUUpdater *)updater; + +// Called immediately before relaunching. +- (void)updaterWillRelaunchApplication:(SUUpdater *)updater; + +// This method allows you to provide a custom version comparator. +// If you don't implement this method or return nil, the standard version comparator will be used. +- (id )versionComparatorForUpdater:(SUUpdater *)updater; + +// This method allows you to provide a custom version comparator. +// If you don't implement this method or return nil, the standard version displayer will be used. +- (id )versionDisplayerForUpdater:(SUUpdater *)updater; + +// Returns the path which is used to relaunch the client after the update is installed. By default, the path of the host bundle. +- (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater; + +// Called before and after, respectively, an updater shows a modal alert window, to give the host +// the opportunity to hide attached windows etc. that may get in the way: +-(void) updaterWillShowModalAlert:(SUUpdater *)updater; +-(void) updaterDidShowModalAlert:(SUUpdater *)updater; + +// Called when an update is scheduled to be silently installed on quit. +// The invocation can be used to trigger an immediate silent install and relaunch. +- (void)updater:(SUUpdater *)updater willInstallUpdateOnQuit:(SUAppcastItem *)update immediateInstallationInvocation:(NSInvocation *)invocation; +- (void)updater:(SUUpdater *)updater didCancelInstallUpdateOnQuit:(SUAppcastItem *)update; + +@end + + +// ----------------------------------------------------------------------------- +// Constants: +// ----------------------------------------------------------------------------- + +// Define some minimum intervals to avoid DOS-like checking attacks. These are in seconds. +#if defined(DEBUG) && DEBUG && 0 +#define SU_MIN_CHECK_INTERVAL 60 +#else +#define SU_MIN_CHECK_INTERVAL 60*60 +#endif + +#if defined(DEBUG) && DEBUG && 0 +#define SU_DEFAULT_CHECK_INTERVAL 60 +#else +#define SU_DEFAULT_CHECK_INTERVAL 60*60*24 +#endif + +#endif diff --git a/native/frameworks/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h new file mode 100644 index 000000000..6c65ea45a --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h @@ -0,0 +1,29 @@ +// +// SUVersionComparisonProtocol.h +// Sparkle +// +// Created by Andy Matuschak on 12/21/07. +// Copyright 2007 Andy Matuschak. All rights reserved. +// + +#ifndef SUVERSIONCOMPARISONPROTOCOL_H +#define SUVERSIONCOMPARISONPROTOCOL_H + +#import + +/*! + @protocol + @abstract Implement this protocol to provide version comparison facilities for Sparkle. +*/ +@protocol SUVersionComparison + +/*! + @method + @abstract An abstract method to compare two version strings. + @discussion Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, and NSOrderedSame if they are equivalent. +*/ +- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; // *** MAY BE CALLED ON NON-MAIN THREAD! + +@end + +#endif diff --git a/native/frameworks/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h new file mode 100644 index 000000000..368b9c9f4 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h @@ -0,0 +1,27 @@ +// +// SUVersionDisplayProtocol.h +// EyeTV +// +// Created by Uli Kusterer on 08.12.09. +// Copyright 2009 Elgato Systems GmbH. All rights reserved. +// + +#import + + +/*! + @protocol + @abstract Implement this protocol to apply special formatting to the two + version numbers. +*/ +@protocol SUVersionDisplay + +/*! + @method + @abstract An abstract method to format two version strings. + @discussion You get both so you can display important distinguishing + information, but leave out unnecessary/confusing parts. +*/ +-(void) formatVersion: (NSString**)inOutVersionA andVersion: (NSString**)inOutVersionB; + +@end diff --git a/native/frameworks/Sparkle.framework/Versions/A/Headers/Sparkle.h b/native/frameworks/Sparkle.framework/Versions/A/Headers/Sparkle.h new file mode 100644 index 000000000..08dd57775 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Headers/Sparkle.h @@ -0,0 +1,21 @@ +// +// Sparkle.h +// Sparkle +// +// Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07) +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SPARKLE_H +#define SPARKLE_H + +// This list should include the shared headers. It doesn't matter if some of them aren't shared (unless +// there are name-space collisions) so we can list all of them to start with: + +#import + +#import +#import +#import + +#endif diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/Info.plist b/native/frameworks/Sparkle.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..26bc4f522 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,40 @@ + + + + + BuildMachineOSBuild + 12C60 + CFBundleDevelopmentRegion + en + CFBundleExecutable + Sparkle + CFBundleIdentifier + org.andymatuschak.Sparkle + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Sparkle + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.5 Beta (git) + CFBundleSignature + ???? + CFBundleVersion + 4abc126 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4G2008a + DTPlatformVersion + GM + DTSDKBuild + 11E52 + DTSDKName + macosx10.7 + DTXcode + 0452 + DTXcodeBuild + 4G2008a + + diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/License.txt b/native/frameworks/Sparkle.framework/Versions/A/Resources/License.txt new file mode 100644 index 000000000..08364c631 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/License.txt @@ -0,0 +1,38 @@ +Copyright (c) 2006 Andy Matuschak + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +================= +EXTERNAL LICENSES +================= + +License for bspatch.c and bsdiff.c, from bsdiff 4.3 (: +/*- + * Copyright 2003-2005 Colin Percival + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist b/native/frameworks/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist new file mode 100644 index 000000000..63644f088 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist @@ -0,0 +1,182 @@ + + + + + ADP2,1 + Developer Transition Kit + iMac1,1 + iMac G3 (Rev A-D) + iMac4,1 + iMac (Core Duo) + iMac4,2 + iMac for Education (17-inch, Core Duo) + iMac5,1 + iMac (Core 2 Duo, 17 or 20 inch, SuperDrive) + iMac5,2 + iMac (Core 2 Duo, 17 inch, Combo Drive) + iMac6,1 + iMac (Core 2 Duo, 24 inch, SuperDrive) + iMac8,1 + iMac (April 2008) + MacBook1,1 + MacBook (Core Duo) + MacBook2,1 + MacBook (Core 2 Duo) + MacBook4,1 + MacBook (Core 2 Duo Feb 2008) + MacBookAir1,1 + MacBook Air (January 2008) + MacBookAir2,1 + MacBook Air (June 2009) + MacBookAir3,1 + MacBook Air (October 2010) + MacBookPro1,1 + MacBook Pro Core Duo (15-inch) + MacBookPro1,2 + MacBook Pro Core Duo (17-inch) + MacBookPro2,1 + MacBook Pro Core 2 Duo (17-inch) + MacBookPro2,2 + MacBook Pro Core 2 Duo (15-inch) + MacBookPro3,1 + MacBook Pro Core 2 Duo (15-inch LED, Core 2 Duo) + MacBookPro3,2 + MacBook Pro Core 2 Duo (17-inch HD, Core 2 Duo) + MacBookPro4,1 + MacBook Pro (Core 2 Duo Feb 2008) + Macmini1,1 + Mac Mini (Core Solo/Duo) + MacPro1,1 + Mac Pro (four-core) + MacPro2,1 + Mac Pro (eight-core) + MacPro3,1 + Mac Pro (January 2008 4- or 8- core "Harpertown") + MacPro4,1 + Mac Pro (March 2009) + MacPro5,1 + Mac Pro (August 2010) + PowerBook1,1 + PowerBook G3 + PowerBook2,1 + iBook G3 + PowerBook2,2 + iBook G3 (FireWire) + PowerBook2,3 + iBook G3 + PowerBook2,4 + iBook G3 + PowerBook3,1 + PowerBook G3 (FireWire) + PowerBook3,2 + PowerBook G4 + PowerBook3,3 + PowerBook G4 (Gigabit Ethernet) + PowerBook3,4 + PowerBook G4 (DVI) + PowerBook3,5 + PowerBook G4 (1GHz / 867MHz) + PowerBook4,1 + iBook G3 (Dual USB, Late 2001) + PowerBook4,2 + iBook G3 (16MB VRAM) + PowerBook4,3 + iBook G3 Opaque 16MB VRAM, 32MB VRAM, Early 2003) + PowerBook5,1 + PowerBook G4 (17 inch) + PowerBook5,2 + PowerBook G4 (15 inch FW 800) + PowerBook5,3 + PowerBook G4 (17-inch 1.33GHz) + PowerBook5,4 + PowerBook G4 (15 inch 1.5/1.33GHz) + PowerBook5,5 + PowerBook G4 (17-inch 1.5GHz) + PowerBook5,6 + PowerBook G4 (15 inch 1.67GHz/1.5GHz) + PowerBook5,7 + PowerBook G4 (17-inch 1.67GHz) + PowerBook5,8 + PowerBook G4 (Double layer SD, 15 inch) + PowerBook5,9 + PowerBook G4 (Double layer SD, 17 inch) + PowerBook6,1 + PowerBook G4 (12 inch) + PowerBook6,2 + PowerBook G4 (12 inch, DVI) + PowerBook6,3 + iBook G4 + PowerBook6,4 + PowerBook G4 (12 inch 1.33GHz) + PowerBook6,5 + iBook G4 (Early-Late 2004) + PowerBook6,7 + iBook G4 (Mid 2005) + PowerBook6,8 + PowerBook G4 (12 inch 1.5GHz) + PowerMac1,1 + Power Macintosh G3 (Blue & White) + PowerMac1,2 + Power Macintosh G4 (PCI Graphics) + PowerMac10,1 + Mac Mini G4 + PowerMac10,2 + Mac Mini (Late 2005) + PowerMac11,2 + Power Macintosh G5 (Late 2005) + PowerMac12,1 + iMac G5 (iSight) + PowerMac2,1 + iMac G3 (Slot-loading CD-ROM) + PowerMac2,2 + iMac G3 (Summer 2000) + PowerMac3,1 + Power Macintosh G4 (AGP Graphics) + PowerMac3,2 + Power Macintosh G4 (AGP Graphics) + PowerMac3,3 + Power Macintosh G4 (Gigabit Ethernet) + PowerMac3,4 + Power Macintosh G4 (Digital Audio) + PowerMac3,5 + Power Macintosh G4 (Quick Silver) + PowerMac3,6 + Power Macintosh G4 (Mirrored Drive Door) + PowerMac4,1 + iMac G3 (Early/Summer 2001) + PowerMac4,2 + iMac G4 (Flat Panel) + PowerMac4,4 + eMac + PowerMac4,5 + iMac G4 (17-inch Flat Panel) + PowerMac5,1 + Power Macintosh G4 Cube + PowerMac6,1 + iMac G4 (USB 2.0) + PowerMac6,3 + iMac G4 (20-inch Flat Panel) + PowerMac6,4 + eMac (USB 2.0, 2005) + PowerMac7,2 + Power Macintosh G5 + PowerMac7,3 + Power Macintosh G5 + PowerMac8,1 + iMac G5 + PowerMac8,2 + iMac G5 (Ambient Light Sensor) + PowerMac9,1 + Power Macintosh G5 (Late 2005) + RackMac1,1 + Xserve G4 + RackMac1,2 + Xserve G4 (slot-loading, cluster node) + RackMac3,1 + Xserve G5 + Xserve1,1 + Xserve (Intel Xeon) + Xserve2,1 + Xserve (January 2008 quad-core) + + diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib new file mode 100644 index 000000000..5ddc9d216 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..5e5199c7c Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUPasswordPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUPasswordPrompt.nib new file mode 100644 index 000000000..1c35eef14 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUPasswordPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..f80f6c760 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..e11c18462 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings new file mode 100644 index 000000000..858a71fae Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ar.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..6960c92a2 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..ac0456f55 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..2d72e4e50 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings new file mode 100644 index 000000000..9bbb99686 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/cs.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..278635608 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..51225f88c Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..d9d19c17a Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings new file mode 100644 index 000000000..2984afdf6 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/da.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..9c9c941b7 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..300f99c84 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..829526ee7 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings new file mode 100644 index 000000000..664946d41 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..4924731bd Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUPasswordPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUPasswordPrompt.nib new file mode 100644 index 000000000..16cd6171c Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUPasswordPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..504ab4904 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..a8dc39dfe Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings new file mode 100644 index 000000000..a9c7f851d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..e895c2668 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..e1412ac95 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..d5f250406 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings new file mode 100644 index 000000000..8e4ab943b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Info.plist b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Info.plist new file mode 100644 index 000000000..2c7893dea --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Info.plist @@ -0,0 +1,50 @@ + + + + + BuildMachineOSBuild + 12C60 + CFBundleDevelopmentRegion + English + CFBundleExecutable + finish_installation + CFBundleIconFile + Sparkle + CFBundleIdentifier + org.andymatuschak.sparkle.finish-installation + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4G2008a + DTPlatformVersion + GM + DTSDKBuild + 11E52 + DTSDKName + macosx10.7 + DTXcode + 0452 + DTXcodeBuild + 4G2008a + LSBackgroundOnly + 1 + LSMinimumSystemVersion + 10.4 + LSUIElement + 1 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/MacOS/finish_installation b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/MacOS/finish_installation new file mode 100755 index 000000000..67aaa1908 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/MacOS/finish_installation differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/PkgInfo b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/PkgInfo new file mode 100644 index 000000000..bd04210fb --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/SUStatus.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/SUStatus.nib new file mode 100644 index 000000000..5ddc9d216 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/SUStatus.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/Sparkle.icns b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/Sparkle.icns new file mode 100644 index 000000000..8e56d45c0 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/Sparkle.icns differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ar.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ar.lproj/Sparkle.strings new file mode 100644 index 000000000..858a71fae Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ar.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/cs.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/cs.lproj/Sparkle.strings new file mode 100644 index 000000000..9bbb99686 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/cs.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/da.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/da.lproj/Sparkle.strings new file mode 100644 index 000000000..2984afdf6 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/da.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/de.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/de.lproj/Sparkle.strings new file mode 100644 index 000000000..664946d41 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/de.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/en.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/en.lproj/Sparkle.strings new file mode 100644 index 000000000..a9c7f851d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/en.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/es.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/es.lproj/Sparkle.strings new file mode 100644 index 000000000..8e4ab943b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/es.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/fr.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/fr.lproj/Sparkle.strings new file mode 100644 index 000000000..236f807a7 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/fr.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/is.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/is.lproj/Sparkle.strings new file mode 100644 index 000000000..665e273e4 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/is.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/it.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/it.lproj/Sparkle.strings new file mode 100644 index 000000000..4ccd7affb Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/it.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ja.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ja.lproj/Sparkle.strings new file mode 100644 index 000000000..b21ea044d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ja.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/nl.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/nl.lproj/Sparkle.strings new file mode 100644 index 000000000..023c473b2 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/nl.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pl.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pl.lproj/Sparkle.strings new file mode 100644 index 000000000..9a0bc8b9f Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pl.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pt_BR.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pt_BR.lproj/Sparkle.strings new file mode 100644 index 000000000..7a11a9ebd Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pt_BR.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pt_PT.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pt_PT.lproj/Sparkle.strings new file mode 100644 index 000000000..497cd8303 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/pt_PT.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ro.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ro.lproj/Sparkle.strings new file mode 100644 index 000000000..e90bdf598 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ro.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ru.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ru.lproj/Sparkle.strings new file mode 100644 index 000000000..7afef95f4 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/ru.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/sl.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/sl.lproj/Sparkle.strings new file mode 100644 index 000000000..7ec0bc27b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/sl.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/sv.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/sv.lproj/Sparkle.strings new file mode 100644 index 000000000..16c3fb842 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/sv.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/th.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/th.lproj/Sparkle.strings new file mode 100644 index 000000000..0468c97f1 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/th.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/tr.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/tr.lproj/Sparkle.strings new file mode 100644 index 000000000..69184c75b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/tr.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/uk.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/uk.lproj/Sparkle.strings new file mode 100644 index 000000000..6f0e4db95 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/uk.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/zh_CN.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/zh_CN.lproj/Sparkle.strings new file mode 100644 index 000000000..b741758fd Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/zh_CN.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/zh_TW.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/zh_TW.lproj/Sparkle.strings new file mode 100644 index 000000000..c1f7e85ed Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/finish_installation.app/Contents/Resources/zh_TW.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..6f99d8514 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..347f12a98 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..9d1adfa73 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings new file mode 100644 index 000000000..236f807a7 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/fr_CA.lproj b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr_CA.lproj new file mode 120000 index 000000000..f9834a395 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/fr_CA.lproj @@ -0,0 +1 @@ +fr.lproj \ No newline at end of file diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..a8bbb1d57 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..e371d758b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..55c5891d2 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings new file mode 100644 index 000000000..665e273e4 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/is.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..c3d4c8f1d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..b12608a4c Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..3d7a8e675 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings new file mode 100644 index 000000000..4ccd7affb Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..cc6a7d842 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..86aa88c23 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..62a4e0195 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings new file mode 100644 index 000000000..b21ea044d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ja.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..e74a88b91 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..08e91dd77 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..763ed3727 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ko.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..2ce3543b0 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..a47c77410 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..5d115e14a Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings new file mode 100644 index 000000000..023c473b2 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..6b3bb832d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..e55aabf6e Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..f936c00e5 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings new file mode 100644 index 000000000..9a0bc8b9f Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pl.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt.lproj b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt.lproj new file mode 120000 index 000000000..3c1c9f6dc --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt.lproj @@ -0,0 +1 @@ +pt_BR.lproj \ No newline at end of file diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..cfde618d8 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUPasswordPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUPasswordPrompt.nib new file mode 100644 index 000000000..185c1c08e Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUPasswordPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..0507aae05 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..192910175 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings new file mode 100644 index 000000000..7a11a9ebd Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_BR.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..1677728af Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..487f7556d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..01a6c38a3 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings new file mode 100644 index 000000000..497cd8303 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/pt_PT.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..52e0e5d22 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..650114b57 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..f556aae5d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings new file mode 100644 index 000000000..e90bdf598 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ro.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..50e99525f Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..259cc9b5b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..bbbc71e9e Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings new file mode 100644 index 000000000..7afef95f4 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..1599b26a0 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..0b8688cdf Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..eceddf2de Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sk.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..ccf680cc6 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..d2db5af34 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..df467541b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings new file mode 100644 index 000000000..7ec0bc27b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sl.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..ccb719614 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..cf7b20365 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..60343ea62 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings new file mode 100644 index 000000000..16c3fb842 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..de3bceed9 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUPasswordPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUPasswordPrompt.nib new file mode 100644 index 000000000..08c9dc44d Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUPasswordPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..e21e467e8 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..7610fc98e Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings new file mode 100644 index 000000000..0468c97f1 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/th.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..193b60c8e Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..80923a410 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..6fe09c2b1 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings new file mode 100644 index 000000000..69184c75b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/tr.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..309cda699 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..ef1b92f0b Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..41b5a3974 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings new file mode 100644 index 000000000..6f0e4db95 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/uk.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..a06881312 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..ec7965e50 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..c2ff59c40 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings new file mode 100644 index 000000000..b741758fd Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_CN.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib new file mode 100644 index 000000000..966d90063 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUAutomaticUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib new file mode 100644 index 000000000..530b67ab5 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdateAlert.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib new file mode 100644 index 000000000..f6849fe84 Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.nib differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings new file mode 100644 index 000000000..c1f7e85ed Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Resources/zh_TW.lproj/Sparkle.strings differ diff --git a/native/frameworks/Sparkle.framework/Versions/A/Sparkle b/native/frameworks/Sparkle.framework/Versions/A/Sparkle new file mode 100755 index 000000000..bfc12fdcf Binary files /dev/null and b/native/frameworks/Sparkle.framework/Versions/A/Sparkle differ diff --git a/native/frameworks/Sparkle.framework/Versions/Current b/native/frameworks/Sparkle.framework/Versions/Current new file mode 120000 index 000000000..8c7e5a667 --- /dev/null +++ b/native/frameworks/Sparkle.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/native/mac/info.plist b/native/mac/info.plist index 8ca1026b6..c85f69221 100644 --- a/native/mac/info.plist +++ b/native/mac/info.plist @@ -4,22 +4,6 @@ CFBundleDevelopmentRegion English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - atom.icns - CFBundleIdentifier - com.github.atom - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 CFBundleDocumentTypes @@ -32,9 +16,35 @@ + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + atom.icns + CFBundleIdentifier + com.github.atom + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.0.1 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1 + LSApplicationCategoryType + public.app-category.developer-tools NSMainNibFile MainMenu NSPrincipalClass AtomApp + SUFeedURL + https://speakeasy.githubapp.com/apps/27/appcast.xml + SUPublicDSAKeyFile + speakeasy.pem + SUScheduledCheckInterval + 3600 diff --git a/native/mac/speakeasy.pem b/native/mac/speakeasy.pem new file mode 100644 index 000000000..791182f81 --- /dev/null +++ b/native/mac/speakeasy.pem @@ -0,0 +1,20 @@ +-----BEGIN PUBLIC KEY----- +MIIDOjCCAi0GByqGSM44BAEwggIgAoIBAQCEh+j0nKWTw7soK6w3uk9PzPGVBksk +wDIaA+d+1CHJY9qhjp7OjAlSOl6nrUlGHzU87DRmBlwYZONAzDZnYpLi7zmPVASg +Xk+AmuqzqahTKtwodJp7R/Aq/lCbB2tXTXOxVo+Jya1BQbfd0wWXJFUlD/xTvrgu +zrtw6VYBvaRu8jCjHAJNZn0CO80igj1ZNxRqmmz1Rkt1tT0KBBfGBTNzXeBmGKHN +bVIKW7zImgfm+UQky+WFei1dqcfWOyfrHIYa3Qn1Nes48SBdrolvfvrChlSpqgEN +wxFW9aoognS1UJTu350AQb2NwOOSQRsR++y3iJp+60nBSDZu7sjNN9etAhUAvqki +JOjBjooRd2odMh7imICHQ3kCggEATwa6W0s2xrolPRpwWZS8ORUNDgEI4eOIvonq +O2qZgwD21zUQOsFjLMbWn0cCtrORr7iM8pFg8Yn8dSccpqs+2cM4uFZAycKXf6w3 +jIvV6M3IPQuUSqVFZtqUVuteGTEuAHZKIrXE05P4aJXHLjqSC9JuaXNRm9q7OW7m +rwsoAFyfkKqbtl5Ch+WZ21CE4J+ByTfVwVU4XLiOtce6NABSDWNJsF9fIoFCZCDc +uumLllDJysD8S6aBNhOjNMHPmeIpZBXT23zHH5du/blcEyBbVF3a2ntgudfJmyln +T178CIEUSSjcbz9JyAhhK7OfNlzKhRiO1c4Y3XaZIniLGjF5DwOCAQUAAoIBABGZ +mfuHBW89ub19iICE//VbB91m2f0nUvHk8vE4vvAK8AdD91GODPJr4DU0kJM6ne8r +ohvZgokgDRkGAEceX/nVoG0RLq9T15Xr2qedWVwAffpU10iV9mYwbhHqUKPtG8cj +GW0cDdSI+0oG6UEyn8aQ5p93YEm5N6lq4rWKpxXb/gkrIla4sJJP8VHOOKmo6l1H +AKVIfofiaNAQShu72WVCCurWaoVTUEliEBhy3WlcjuKXEuoL1lpNxyqkt7mf6w71 +6y2+Nh+XUTiFoTIVhk/CH0z+BQTneWEALvfTFzDae+a42rPAisKlt+Gbe7zopnVA +kcQwM0lLzgwx4T1DV3s= +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/native/v8_extensions/atom.h b/native/v8_extensions/atom.h index 9aae075c0..05c2e0825 100644 --- a/native/v8_extensions/atom.h +++ b/native/v8_extensions/atom.h @@ -5,7 +5,7 @@ namespace v8_extensions { class Atom : public CefV8Handler { public: Atom(); - + void CreateContextBinding(CefRefPtr context); virtual bool Execute(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, @@ -14,5 +14,9 @@ namespace v8_extensions { // Provide the reference counting implementation for this class. IMPLEMENT_REFCOUNTING(Atom); + + private: + Atom(Atom const&); + void operator=(Atom const&); }; } diff --git a/native/v8_extensions/atom.js b/native/v8_extensions/atom.js deleted file mode 100644 index 5ec3a5922..000000000 --- a/native/v8_extensions/atom.js +++ /dev/null @@ -1,9 +0,0 @@ -(function () { - -native function sendMessageToBrowserProcess(name, array); - -this.atom = { - sendMessageToBrowserProcess: sendMessageToBrowserProcess -}; - -})(); diff --git a/native/v8_extensions/atom.mm b/native/v8_extensions/atom.mm index de6c7abe1..403cac409 100644 --- a/native/v8_extensions/atom.mm +++ b/native/v8_extensions/atom.mm @@ -7,9 +7,14 @@ namespace v8_extensions { Atom::Atom() : CefV8Handler() { - NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/atom.js"]; - NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - CefRegisterExtension("v8/atom", [extensionCode UTF8String], this); + } + + void Atom::CreateContextBinding(CefRefPtr context) { + CefRefPtr function = CefV8Value::CreateFunction("sendMessageToBrowserProcess", this); + CefRefPtr atomObject = CefV8Value::CreateObject(NULL); + atomObject->SetValue("sendMessageToBrowserProcess", function, V8_PROPERTY_ATTRIBUTE_NONE); + CefRefPtr global = context->GetGlobal(); + global->SetValue("atom", atomObject, V8_PROPERTY_ATTRIBUTE_NONE); } bool Atom::Execute(const CefString& name, diff --git a/native/v8_extensions/git.h b/native/v8_extensions/git.h index e7c0b1dce..74876fe11 100644 --- a/native/v8_extensions/git.h +++ b/native/v8_extensions/git.h @@ -2,19 +2,21 @@ #include "include/cef_v8.h" namespace v8_extensions { + class Git : public CefV8Handler { + public: + Git(); + void CreateContextBinding(CefRefPtr context); + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE; -class Git : public CefV8Handler { -public: - Git(); - - virtual bool Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) OVERRIDE; - - // Provide the reference counting implementation for this class. - IMPLEMENT_REFCOUNTING(Git); -}; + // Provide the reference counting implementation for this class. + IMPLEMENT_REFCOUNTING(Git); + private: + Git(Git const&); + void operator=(Git const&); + }; } diff --git a/native/v8_extensions/git.js b/native/v8_extensions/git.js deleted file mode 100644 index fa4b1b49c..000000000 --- a/native/v8_extensions/git.js +++ /dev/null @@ -1,35 +0,0 @@ -var $git = {}; -(function() { - - native function getRepository(pathInRepo); - native function getHead(); - native function getPath(); - native function getStatus(path); - native function isIgnored(path); - native function checkoutHead(path); - native function getDiffStats(path); - native function isSubmodule(path); - native function refreshIndex(); - native function destroy(); - - function GitRepository(path) { - var repo = getRepository(path); - if (!repo) - throw new Error("No Git repository found searching path: " + path); - - repo.constructor = GitRepository; - repo.__proto__ = GitRepository.prototype; - return repo; - } - - GitRepository.prototype.getHead = getHead; - GitRepository.prototype.getPath = getPath; - GitRepository.prototype.getStatus = getStatus; - GitRepository.prototype.isIgnored = isIgnored; - GitRepository.prototype.checkoutHead = checkoutHead; - GitRepository.prototype.getDiffStats = getDiffStats; - GitRepository.prototype.isSubmodule = isSubmodule; - GitRepository.prototype.refreshIndex = refreshIndex; - GitRepository.prototype.destroy = destroy; - this.GitRepository = GitRepository; -})(); diff --git a/native/v8_extensions/git.mm b/native/v8_extensions/git.mm index b0d8cebe9..d2cda0a29 100644 --- a/native/v8_extensions/git.mm +++ b/native/v8_extensions/git.mm @@ -4,264 +4,278 @@ namespace v8_extensions { -class GitRepository : public CefBase { -private: - git_repository *repo; + class GitRepository : public CefBase { + private: + git_repository *repo; -public: - GitRepository(const char *pathInRepo) { - if (git_repository_open_ext(&repo, pathInRepo, 0, NULL) != GIT_OK) { - repo = NULL; + public: + GitRepository(const char *pathInRepo) { + if (git_repository_open_ext(&repo, pathInRepo, 0, NULL) != GIT_OK) { + repo = NULL; + } } - } - ~GitRepository() { - Destroy(); - } - - void Destroy() { - if (Exists()) { - git_repository_free(repo); - repo = NULL; + ~GitRepository() { + Destroy(); } - } - BOOL Exists() { - return repo != NULL; - } + void Destroy() { + if (Exists()) { + git_repository_free(repo); + repo = NULL; + } + } - CefRefPtr GetPath() { - return CefV8Value::CreateString(git_repository_path(repo)); - } + BOOL Exists() { + return repo != NULL; + } - CefRefPtr GetHead() { - git_reference *head; - if (git_repository_head(&head, repo) == GIT_OK) { - if (git_repository_head_detached(repo) == 1) { - const git_oid* sha = git_reference_target(head); - if (sha) { - char oid[GIT_OID_HEXSZ + 1]; - git_oid_tostr(oid, GIT_OID_HEXSZ + 1, sha); - git_reference_free(head); - return CefV8Value::CreateString(oid); + CefRefPtr GetPath() { + return CefV8Value::CreateString(git_repository_path(repo)); + } + + CefRefPtr GetHead() { + git_reference *head; + if (git_repository_head(&head, repo) == GIT_OK) { + if (git_repository_head_detached(repo) == 1) { + const git_oid* sha = git_reference_target(head); + if (sha) { + char oid[GIT_OID_HEXSZ + 1]; + git_oid_tostr(oid, GIT_OID_HEXSZ + 1, sha); + git_reference_free(head); + return CefV8Value::CreateString(oid); + } } + + CefRefPtr result = CefV8Value::CreateString(git_reference_name(head)); + git_reference_free(head); + return result; } - CefRefPtr result = CefV8Value::CreateString(git_reference_name(head)); + return CefV8Value::CreateNull(); + } + + CefRefPtr IsIgnored(const char *path) { + int ignored; + if (git_ignore_path_is_ignored(&ignored, repo, path) == GIT_OK) { + return CefV8Value::CreateBool(ignored == 1); + } + else { + return CefV8Value::CreateBool(false); + } + } + + CefRefPtr GetStatus(const char *path) { + unsigned int status = 0; + if (git_status_file(&status, repo, path) == GIT_OK) { + return CefV8Value::CreateInt(status); + } + else { + return CefV8Value::CreateInt(0); + } + } + + CefRefPtr CheckoutHead(const char *path) { + char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); + strcpy(copiedPath, path); + git_checkout_opts options = GIT_CHECKOUT_OPTS_INIT; + options.checkout_strategy = GIT_CHECKOUT_FORCE; + git_strarray paths; + paths.count = 1; + paths.strings = &copiedPath; + options.paths = paths; + + int result = git_checkout_head(repo, &options); + free(copiedPath); + return CefV8Value::CreateBool(result == GIT_OK); + } + + CefRefPtr GetDiffStats(const char *path) { + git_reference *head; + if (git_repository_head(&head, repo) != GIT_OK) { + return CefV8Value::CreateNull(); + } + + const git_oid* sha = git_reference_target(head); + git_commit *commit; + int commitStatus = git_commit_lookup(&commit, repo, sha); git_reference_free(head); - return result; - } + if (commitStatus != GIT_OK) { + return CefV8Value::CreateNull(); + } - return CefV8Value::CreateNull(); - } + git_tree *tree; + int treeStatus = git_commit_tree(&tree, commit); + git_commit_free(commit); + if (treeStatus != GIT_OK) { + return CefV8Value::CreateNull(); + } - CefRefPtr IsIgnored(const char *path) { - int ignored; - if (git_ignore_path_is_ignored(&ignored, repo, path) == GIT_OK) { - return CefV8Value::CreateBool(ignored == 1); - } - else { - return CefV8Value::CreateBool(false); - } - } + char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); + strcpy(copiedPath, path); + git_diff_options options = GIT_DIFF_OPTIONS_INIT; + git_strarray paths; + paths.count = 1; + paths.strings = &copiedPath; + options.pathspec = paths; + options.context_lines = 1; + options.flags = GIT_DIFF_DISABLE_PATHSPEC_MATCH; - CefRefPtr GetStatus(const char *path) { - unsigned int status = 0; - if (git_status_file(&status, repo, path) == GIT_OK) { - return CefV8Value::CreateInt(status); - } - else { - return CefV8Value::CreateInt(0); - } - } + git_diff_list *diffs; + int diffStatus = git_diff_tree_to_workdir(&diffs, repo, tree, &options); + free(copiedPath); + if (diffStatus != GIT_OK || git_diff_num_deltas(diffs) != 1) { + return CefV8Value::CreateNull(); + } - CefRefPtr CheckoutHead(const char *path) { - char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); - strcpy(copiedPath, path); - git_checkout_opts options = GIT_CHECKOUT_OPTS_INIT; - options.checkout_strategy = GIT_CHECKOUT_FORCE; - git_strarray paths; - paths.count = 1; - paths.strings = &copiedPath; - options.paths = paths; + git_diff_patch *patch; + int patchStatus = git_diff_get_patch(&patch, NULL, diffs, 0); + git_diff_list_free(diffs); + if (patchStatus != GIT_OK) { + return CefV8Value::CreateNull(); + } - int result = git_checkout_head(repo, &options); - free(copiedPath); - return CefV8Value::CreateBool(result == GIT_OK); - } - - CefRefPtr GetDiffStats(const char *path) { - git_reference *head; - if (git_repository_head(&head, repo) != GIT_OK) { - return CefV8Value::CreateNull(); - } - - const git_oid* sha = git_reference_target(head); - git_commit *commit; - int commitStatus = git_commit_lookup(&commit, repo, sha); - git_reference_free(head); - if (commitStatus != GIT_OK) { - return CefV8Value::CreateNull(); - } - - git_tree *tree; - int treeStatus = git_commit_tree(&tree, commit); - git_commit_free(commit); - if (treeStatus != GIT_OK) { - return CefV8Value::CreateNull(); - } - - char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); - strcpy(copiedPath, path); - git_diff_options options = GIT_DIFF_OPTIONS_INIT; - git_strarray paths; - paths.count = 1; - paths.strings = &copiedPath; - options.pathspec = paths; - options.context_lines = 1; - options.flags = GIT_DIFF_DISABLE_PATHSPEC_MATCH; - - git_diff_list *diffs; - int diffStatus = git_diff_tree_to_workdir(&diffs, repo, tree, &options); - free(copiedPath); - if (diffStatus != GIT_OK || git_diff_num_deltas(diffs) != 1) { - return CefV8Value::CreateNull(); - } - - git_diff_patch *patch; - int patchStatus = git_diff_get_patch(&patch, NULL, diffs, 0); - git_diff_list_free(diffs); - if (patchStatus != GIT_OK) { - return CefV8Value::CreateNull(); - } - - int added = 0; - int deleted = 0; - int hunks = git_diff_patch_num_hunks(patch); - for (int i = 0; i < hunks; i++) { - int lines = git_diff_patch_num_lines_in_hunk(patch, i); - for (int j = 0; j < lines; j++) { - char lineType; - if (git_diff_patch_get_line_in_hunk(&lineType, NULL, NULL, NULL, NULL, patch, i, j) == GIT_OK) { - switch (lineType) { - case GIT_DIFF_LINE_ADDITION: - added++; - break; - case GIT_DIFF_LINE_DELETION: - deleted++; - break; + int added = 0; + int deleted = 0; + int hunks = git_diff_patch_num_hunks(patch); + for (int i = 0; i < hunks; i++) { + int lines = git_diff_patch_num_lines_in_hunk(patch, i); + for (int j = 0; j < lines; j++) { + char lineType; + if (git_diff_patch_get_line_in_hunk(&lineType, NULL, NULL, NULL, NULL, patch, i, j) == GIT_OK) { + switch (lineType) { + case GIT_DIFF_LINE_ADDITION: + added++; + break; + case GIT_DIFF_LINE_DELETION: + deleted++; + break; + } } } } - } - git_diff_patch_free(patch); + git_diff_patch_free(patch); - CefRefPtr result = CefV8Value::CreateObject(NULL); - result->SetValue("added", CefV8Value::CreateInt(added), V8_PROPERTY_ATTRIBUTE_NONE); - result->SetValue("deleted", CefV8Value::CreateInt(deleted), V8_PROPERTY_ATTRIBUTE_NONE); - return result; + CefRefPtr result = CefV8Value::CreateObject(NULL); + result->SetValue("added", CefV8Value::CreateInt(added), V8_PROPERTY_ATTRIBUTE_NONE); + result->SetValue("deleted", CefV8Value::CreateInt(deleted), V8_PROPERTY_ATTRIBUTE_NONE); + return result; + } + + CefRefPtr IsSubmodule(const char *path) { + BOOL isSubmodule = false; + git_index* index; + if (git_repository_index(&index, repo) == GIT_OK) { + const git_index_entry *entry = git_index_get_bypath(index, path, 0); + isSubmodule = entry != NULL && (entry->mode & S_IFMT) == GIT_FILEMODE_COMMIT; + git_index_free(index); + } + return CefV8Value::CreateBool(isSubmodule); + } + + void RefreshIndex() { + git_index* index; + if (git_repository_index(&index, repo) == GIT_OK) { + git_index_read(index); + git_index_free(index); + } + } + + IMPLEMENT_REFCOUNTING(GitRepository); + }; + + Git::Git() : CefV8Handler() { } - CefRefPtr IsSubmodule(const char *path) { - BOOL isSubmodule = false; - git_index* index; - if (git_repository_index(&index, repo) == GIT_OK) { - const git_index_entry *entry = git_index_get_bypath(index, path, 0); - isSubmodule = entry != NULL && (entry->mode & S_IFMT) == GIT_FILEMODE_COMMIT; - git_index_free(index); + void Git::CreateContextBinding(CefRefPtr context) { + const char* methodNames[] = { + "getRepository", "getHead", "getPath", "isIgnored", "getStatus", "checkoutHead", + "getDiffStats", "isSubmodule", "refreshIndex", "destroy" + }; + + CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); + int arrayLength = sizeof(methodNames) / sizeof(const char *); + for (int i = 0; i < arrayLength; i++) { + const char *functionName = methodNames[i]; + CefRefPtr function = CefV8Value::CreateFunction(functionName, this); + nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE); } - return CefV8Value::CreateBool(isSubmodule); + + CefRefPtr global = context->GetGlobal(); + global->SetValue("$git", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE); } - void RefreshIndex() { - git_index* index; - if (git_repository_index(&index, repo) == GIT_OK) { - git_index_read(index); - git_index_free(index); + bool Git::Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) { + if (name == "getRepository") { + GitRepository *repository = new GitRepository(arguments[0]->GetStringValue().ToString().c_str()); + if (repository->Exists()) { + CefRefPtr userData = repository; + retval = CefV8Value::CreateObject(NULL); + retval->SetUserData(userData); + } else { + retval = CefV8Value::CreateNull(); + } + return true; } + + if (name == "getHead") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->GetHead(); + return true; + } + + if (name == "getPath") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->GetPath(); + return true; + } + + if (name == "isIgnored") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->IsIgnored(arguments[0]->GetStringValue().ToString().c_str()); + return true; + } + + if (name == "getStatus") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->GetStatus(arguments[0]->GetStringValue().ToString().c_str()); + return true; + } + + if (name == "checkoutHead") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->CheckoutHead(arguments[0]->GetStringValue().ToString().c_str()); + return true; + } + + if (name == "getDiffStats") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->GetDiffStats(arguments[0]->GetStringValue().ToString().c_str()); + return true; + } + + if (name == "isSubmodule") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->IsSubmodule(arguments[0]->GetStringValue().ToString().c_str()); + return true; + } + + if (name == "refreshIndex") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + userData->RefreshIndex(); + return true; + } + + if (name == "destroy") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + userData->Destroy(); + return true; + } + + return false; } - - IMPLEMENT_REFCOUNTING(GitRepository); -}; - -Git::Git() : CefV8Handler() { - NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/git.js"]; - NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - CefRegisterExtension("v8/git", [extensionCode UTF8String], this); -} - -bool Git::Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) { - if (name == "getRepository") { - GitRepository *repository = new GitRepository(arguments[0]->GetStringValue().ToString().c_str()); - if (repository->Exists()) { - CefRefPtr userData = repository; - retval = CefV8Value::CreateObject(NULL); - retval->SetUserData(userData); - } else { - retval = CefV8Value::CreateNull(); - } - return true; - } - - if (name == "getHead") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->GetHead(); - return true; - } - - if (name == "getPath") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->GetPath(); - return true; - } - - if (name == "isIgnored") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->IsIgnored(arguments[0]->GetStringValue().ToString().c_str()); - return true; - } - - if (name == "getStatus") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->GetStatus(arguments[0]->GetStringValue().ToString().c_str()); - return true; - } - - if (name == "checkoutHead") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->CheckoutHead(arguments[0]->GetStringValue().ToString().c_str()); - return true; - } - - if (name == "getDiffStats") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->GetDiffStats(arguments[0]->GetStringValue().ToString().c_str()); - return true; - } - - if (name == "isSubmodule") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - retval = userData->IsSubmodule(arguments[0]->GetStringValue().ToString().c_str()); - return true; - } - - if (name == "refreshIndex") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - userData->RefreshIndex(); - return true; - } - - if (name == "destroy") { - GitRepository *userData = (GitRepository *)object->GetUserData().get(); - userData->Destroy(); - return true; - } - - return false; -} - } diff --git a/native/v8_extensions/native.h b/native/v8_extensions/native.h index e7a200493..24064429f 100644 --- a/native/v8_extensions/native.h +++ b/native/v8_extensions/native.h @@ -1,24 +1,23 @@ #include "include/cef_base.h" #include "include/cef_v8.h" - namespace v8_extensions { -class Native : public CefV8Handler { -public: - Native(); + class Native : public CefV8Handler { + public: + Native(); + void CreateContextBinding(CefRefPtr context); + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE; - virtual bool Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) OVERRIDE; - - // Provide the reference counting implementation for this class. - IMPLEMENT_REFCOUNTING(Native); - -private: - std::string windowState; -}; + // Provide the reference counting implementation for this class. + IMPLEMENT_REFCOUNTING(Native); + private: + Native(Native const&); + void operator=(Native const&); + }; } diff --git a/native/v8_extensions/native.js b/native/v8_extensions/native.js deleted file mode 100644 index 9124d89fc..000000000 --- a/native/v8_extensions/native.js +++ /dev/null @@ -1,85 +0,0 @@ -var $native = {}; -(function() { - - native function exists(path); - $native.exists = exists; - - native function read(path); - $native.read = read; - - native function write(path, content); - $native.write = write; - - native function absolute(path); - $native.absolute = absolute; - - native function traverseTree(path, onFile, onDirectory); - $native.traverseTree = traverseTree; - - native function getAllFilePathsAsync(path, callback); - $native.getAllFilePathsAsync = getAllFilePathsAsync; - - native function isFile(path); - $native.isFile = isFile; - - native function isDirectory(path); - $native.isDirectory = isDirectory; - - native function remove(path); - $native.remove = remove; - - native function open(path); - $native.open = open; - - native function quit(); - $native.quit = quit; - - native function writeToPasteboard(text); - $native.writeToPasteboard = writeToPasteboard; - - native function readFromPasteboard(); - $native.readFromPasteboard = readFromPasteboard; - - native function watchPath(path); - $native.watchPath = watchPath; - - native function unwatchPath(path, callbackId); - $native.unwatchPath = unwatchPath; - - native function getWatchedPaths(); - $native.getWatchedPaths = getWatchedPaths; - - native function unwatchAllPaths(); - $native.unwatchAllPaths = unwatchAllPaths; - - native function makeDirectory(path); - $native.makeDirectory = makeDirectory; - - native function move(sourcePath, targetPath); - $native.move = move; - - native function moveToTrash(path); - $native.moveToTrash = moveToTrash; - - native function reload(); - $native.reload = reload; - - native function lastModified(path); - $native.lastModified = lastModified; - - native function md5ForPath(path); - $native.md5ForPath = md5ForPath; - - native function exec(command, options, callback); - $native.exec = exec; - - native function getPlatform(); - $native.getPlatform = getPlatform; - - native function setWindowState(state); - $native.setWindowState = setWindowState; - - native function getWindowState(); - $native.getWindowState = getWindowState; - -})(); diff --git a/native/v8_extensions/native.mm b/native/v8_extensions/native.mm index 0a66591ca..9ce5b4ee6 100644 --- a/native/v8_extensions/native.mm +++ b/native/v8_extensions/native.mm @@ -8,496 +8,522 @@ #import "path_watcher.h" #import - #include +static std::string windowState = "{}"; +static NSLock *windowStateLock = [[NSLock alloc] init]; + namespace v8_extensions { + using namespace std; -NSString *stringFromCefV8Value(const CefRefPtr& value) { - std::string cc_value = value->GetStringValue().ToString(); - return [NSString stringWithUTF8String:cc_value.c_str()]; -} + NSString *stringFromCefV8Value(const CefRefPtr& value); + void throwException(const CefRefPtr& global, CefRefPtr exception, NSString *message); -void throwException(const CefRefPtr& global, CefRefPtr exception, NSString *message) { - CefV8ValueList arguments; - - message = [message stringByAppendingFormat:@"\n%s", exception->GetMessage().ToString().c_str()]; - arguments.push_back(CefV8Value::CreateString(std::string([message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - - CefRefPtr console = global->GetValue("console"); - console->GetValue("error")->ExecuteFunction(console, arguments); -} - -Native::Native() : CefV8Handler() { - NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/native.js"]; - NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - windowState = "{}"; - CefRegisterExtension("v8/native", [extensionCode UTF8String], this); -} - -bool Native::Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) { - if (name == "exists") { - std::string cc_value = arguments[0]->GetStringValue().ToString(); - const char *path = cc_value.c_str(); - retval = CefV8Value::CreateBool(access(path, F_OK) == 0); - - return true; + Native::Native() : CefV8Handler() { } - else if (name == "read") { - NSString *path = stringFromCefV8Value(arguments[0]); - NSError *error = nil; - NSStringEncoding *encoding = nil; - NSString *contents = [NSString stringWithContentsOfFile:path usedEncoding:encoding error:&error]; + void Native::CreateContextBinding(CefRefPtr context) { + const char* methodNames[] = { + "exists", "read", "write", "absolute", "getAllFilePathsAsync", "traverseTree", "isDirectory", + "isFile", "remove", "writeToPasteboard", "readFromPasteboard", "quit", "watchPath", "unwatchPath", + "getWatchedPaths", "unwatchAllPaths", "makeDirectory", "move", "moveToTrash", "reload", "lastModified", + "md5ForPath", "exec", "getPlatform", "setWindowState", "getWindowState" + }; - NSError *binaryFileError = nil; - if (error) { - contents = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:&binaryFileError]; + CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); + int arrayLength = sizeof(methodNames) / sizeof(const char *); + for (int i = 0; i < arrayLength; i++) { + const char *functionName = methodNames[i]; + CefRefPtr function = CefV8Value::CreateFunction(functionName, this); + nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE); } - if (binaryFileError) { - exception = [[binaryFileError localizedDescription] UTF8String]; - } - else { - retval = CefV8Value::CreateString([contents UTF8String]); - } - - return true; + CefRefPtr global = context->GetGlobal(); + global->SetValue("$native", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE); } - else if (name == "write") { - NSString *path = stringFromCefV8Value(arguments[0]); - NSString *content = stringFromCefV8Value(arguments[1]); - NSFileManager *fm = [NSFileManager defaultManager]; + bool Native::Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) { + if (name == "exists") { + std::string cc_value = arguments[0]->GetStringValue().ToString(); + const char *path = cc_value.c_str(); + retval = CefV8Value::CreateBool(access(path, F_OK) == 0); - // Create parent directories if they don't exist - BOOL exists = [fm fileExistsAtPath:[path stringByDeletingLastPathComponent] isDirectory:nil]; - if (!exists) { - [fm createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; + return true; } + else if (name == "read") { + NSString *path = stringFromCefV8Value(arguments[0]); - NSError *error = nil; - BOOL success = [content writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error]; + NSError *error = nil; + NSStringEncoding *encoding = nil; + NSString *contents = [NSString stringWithContentsOfFile:path usedEncoding:encoding error:&error]; - if (error) { - exception = [[error localizedDescription] UTF8String]; + NSError *binaryFileError = nil; + if (error) { + contents = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:&binaryFileError]; + } + + if (binaryFileError) { + exception = [[binaryFileError localizedDescription] UTF8String]; + } + else { + retval = CefV8Value::CreateString([contents UTF8String]); + } + + return true; } - else if (!success) { - std::string exception = "Cannot write to '"; - exception += [path UTF8String]; - exception += "'"; + else if (name == "write") { + NSString *path = stringFromCefV8Value(arguments[0]); + NSString *content = stringFromCefV8Value(arguments[1]); + + NSFileManager *fm = [NSFileManager defaultManager]; + + // Create parent directories if they don't exist + BOOL exists = [fm fileExistsAtPath:[path stringByDeletingLastPathComponent] isDirectory:nil]; + if (!exists) { + [fm createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; + } + + NSError *error = nil; + BOOL success = [content writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error]; + + if (error) { + exception = [[error localizedDescription] UTF8String]; + } + else if (!success) { + std::string exception = "Cannot write to '"; + exception += [path UTF8String]; + exception += "'"; + } + + return true; } + else if (name == "absolute") { + NSString *path = stringFromCefV8Value(arguments[0]); - return true; - } - else if (name == "absolute") { - NSString *path = stringFromCefV8Value(arguments[0]); + path = [path stringByStandardizingPath]; + if ([path characterAtIndex:0] == '/') { + retval = CefV8Value::CreateString([path UTF8String]); + } - path = [path stringByStandardizingPath]; - if ([path characterAtIndex:0] == '/') { - retval = CefV8Value::CreateString([path UTF8String]); + return true; } + else if (name == "getAllFilePathsAsync") { + std::string argument = arguments[0]->GetStringValue().ToString(); + CefRefPtr callback = arguments[1]; + CefRefPtr context = CefV8Context::GetCurrentContext(); - return true; - } - else if (name == "getAllFilePathsAsync") { - std::string argument = arguments[0]->GetStringValue().ToString(); - CefRefPtr callback = arguments[1]; - CefRefPtr context = CefV8Context::GetCurrentContext(); + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_async(queue, ^{ + int rootPathLength = argument.size() + 1; + char rootPath[rootPathLength]; + strcpy(rootPath, argument.c_str()); + char * const treePaths[] = {rootPath, NULL}; - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_async(queue, ^{ + FTS *tree = fts_open(treePaths, FTS_COMFOLLOW | FTS_PHYSICAL| FTS_NOCHDIR | FTS_NOSTAT, NULL); + std::vector paths; + + if (tree != NULL) { + FTSENT *entry; + int arrayIndex = 0; + while ((entry = fts_read(tree)) != NULL) { + if (entry->fts_level == 0) { + continue; + } + + bool isFile = entry->fts_info == FTS_NSOK; + if (!isFile) { + continue; + } + + int pathLength = entry->fts_pathlen - rootPathLength; + char relative[pathLength + 1]; + relative[pathLength] = '\0'; + strncpy(relative, entry->fts_path + rootPathLength, pathLength); + paths.push_back(relative); + } + } + + dispatch_queue_t mainQueue = dispatch_get_main_queue(); + dispatch_async(mainQueue, ^{ + context->Enter(); + CefRefPtr v8Paths = CefV8Value::CreateArray(paths.size()); + for (int i = 0; i < paths.size(); i++) { + v8Paths->SetValue(i, CefV8Value::CreateString(paths[i])); + } + CefV8ValueList callbackArgs; + callbackArgs.push_back(v8Paths); + callback->ExecuteFunction(callback, callbackArgs); + context->Exit(); + }); + }); + return true; + } + else if (name == "traverseTree") { + std::string argument = arguments[0]->GetStringValue().ToString(); int rootPathLength = argument.size() + 1; char rootPath[rootPathLength]; strcpy(rootPath, argument.c_str()); - char * const treePaths[] = {rootPath, NULL}; + char * const paths[] = {rootPath, NULL}; - FTS *tree = fts_open(treePaths, FTS_COMFOLLOW | FTS_PHYSICAL| FTS_NOCHDIR | FTS_NOSTAT, NULL); - std::vector paths; + FTS *tree = fts_open(paths, FTS_COMFOLLOW | FTS_PHYSICAL| FTS_NOCHDIR | FTS_NOSTAT, NULL); + if (tree == NULL) { + return true; + } - if (tree != NULL) { - FTSENT *entry; - int arrayIndex = 0; - while ((entry = fts_read(tree)) != NULL) { - if (entry->fts_level == 0) { - continue; + CefRefPtr onFile = arguments[1]; + CefRefPtr onDir = arguments[2]; + CefV8ValueList args; + FTSENT *entry; + while ((entry = fts_read(tree)) != NULL) { + if (entry->fts_level == 0) { + continue; + } + + bool isFile = entry->fts_info == FTS_NSOK; + bool isDir = entry->fts_info == FTS_D; + if (!isFile && !isDir) { + continue; + } + + int pathLength = entry->fts_pathlen - rootPathLength; + char relative[pathLength + 1]; + relative[pathLength] = '\0'; + strncpy(relative, entry->fts_path + rootPathLength, pathLength); + args.clear(); + args.push_back(CefV8Value::CreateString(relative)); + if (isFile) { + onFile->ExecuteFunction(onFile, args); + } + else { + CefRefPtr enterDir = onDir->ExecuteFunction(onDir, args); + if(enterDir != NULL && !enterDir->GetBoolValue()) { + fts_set(tree, entry, FTS_SKIP); } - - bool isFile = entry->fts_info == FTS_NSOK; - if (!isFile) { - continue; - } - - int pathLength = entry->fts_pathlen - rootPathLength; - char relative[pathLength + 1]; - relative[pathLength] = '\0'; - strncpy(relative, entry->fts_path + rootPathLength, pathLength); - paths.push_back(relative); } } - dispatch_queue_t mainQueue = dispatch_get_main_queue(); - dispatch_async(mainQueue, ^{ - context->Enter(); - CefRefPtr v8Paths = CefV8Value::CreateArray(paths.size()); - for (int i = 0; i < paths.size(); i++) { - v8Paths->SetValue(i, CefV8Value::CreateString(paths[i])); - } - CefV8ValueList callbackArgs; - callbackArgs.push_back(v8Paths); - callback->ExecuteFunction(callback, callbackArgs); - context->Exit(); - }); - }); - return true; - } - else if (name == "traverseTree") { - std::string argument = arguments[0]->GetStringValue().ToString(); - int rootPathLength = argument.size() + 1; - char rootPath[rootPathLength]; - strcpy(rootPath, argument.c_str()); - char * const paths[] = {rootPath, NULL}; + return true; + } + else if (name == "isDirectory") { + NSString *path = stringFromCefV8Value(arguments[0]); - FTS *tree = fts_open(paths, FTS_COMFOLLOW | FTS_PHYSICAL| FTS_NOCHDIR | FTS_NOSTAT, NULL); - if (tree == NULL) { + BOOL isDir = false; + BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; + retval = CefV8Value::CreateBool(exists && isDir); + + return true; + } + else if (name == "isFile") { + NSString *path = stringFromCefV8Value(arguments[0]); + + BOOL isDir = false; + BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; + retval = CefV8Value::CreateBool(exists && !isDir); + + return true; + } + else if (name == "remove") { + NSString *path = stringFromCefV8Value(arguments[0]); + + NSError *error = nil; + [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; + + if (error) { + exception = [[error localizedDescription] UTF8String]; + } + + return true; + } + else if (name == "writeToPasteboard") { + NSString *text = stringFromCefV8Value(arguments[0]); + + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + [pb declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; + [pb setString:text forType:NSStringPboardType]; + + return true; + } + else if (name == "readFromPasteboard") { + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSArray *results = [pb readObjectsForClasses:[NSArray arrayWithObjects:[NSString class], nil] options:nil]; + if (results) { + retval = CefV8Value::CreateString([[results objectAtIndex:0] UTF8String]); + } + + return true; + } + else if (name == "quit") { + [NSApp terminate:nil]; + return true; + } + else if (name == "watchPath") { + NSString *path = stringFromCefV8Value(arguments[0]); + CefRefPtr function = arguments[1]; + + CefRefPtr context = CefV8Context::GetCurrentContext(); + + WatchCallback callback = ^(NSString *eventType, NSString *path) { + context->Enter(); + + CefV8ValueList args; + + args.push_back(CefV8Value::CreateString(std::string([eventType UTF8String], [eventType lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); + args.push_back(CefV8Value::CreateString(std::string([path UTF8String], [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); + function->ExecuteFunction(function, args); + + context->Exit(); + }; + + PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; + NSString *watchId = [pathWatcher watchPath:path callback:[[callback copy] autorelease]]; + if (watchId) { + retval = CefV8Value::CreateString([watchId UTF8String]); + } + else { + exception = std::string("Failed to watch path '") + std::string([path UTF8String]) + std::string("' (it may not exist)"); + } + + return true; + } + else if (name == "unwatchPath") { + NSString *path = stringFromCefV8Value(arguments[0]); + NSString *callbackId = stringFromCefV8Value(arguments[1]); + NSError *error = nil; + PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; + [pathWatcher unwatchPath:path callbackId:callbackId error:&error]; + + if (error) { + exception = [[error localizedDescription] UTF8String]; + } + + return true; + } + else if (name == "getWatchedPaths") { + PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; + NSArray *paths = [pathWatcher watchedPaths]; + + CefRefPtr pathsArray = CefV8Value::CreateArray([paths count]); + + for (int i = 0; i < [paths count]; i++) { + CefRefPtr path = CefV8Value::CreateString([[paths objectAtIndex:i] UTF8String]); + pathsArray->SetValue(i, path); + } + retval = pathsArray; + + return true; + } + else if (name == "unwatchAllPaths") { + PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; + [pathWatcher unwatchAllPaths]; + return true; + } + else if (name == "makeDirectory") { + NSString *path = stringFromCefV8Value(arguments[0]); + NSFileManager *fm = [NSFileManager defaultManager]; + NSError *error = nil; + [fm createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error]; + + if (error) { + exception = [[error localizedDescription] UTF8String]; + } + + return true; + } + else if (name == "move") { + NSString *sourcePath = stringFromCefV8Value(arguments[0]); + NSString *targetPath = stringFromCefV8Value(arguments[1]); + NSFileManager *fm = [NSFileManager defaultManager]; + + NSError *error = nil; + [fm moveItemAtPath:sourcePath toPath:targetPath error:&error]; + + if (error) { + exception = [[error localizedDescription] UTF8String]; + } + + return true; + } + else if (name == "moveToTrash") { + NSString *sourcePath = stringFromCefV8Value(arguments[0]); + bool success = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation + source:[sourcePath stringByDeletingLastPathComponent] + destination:@"" + files:[NSArray arrayWithObject:[sourcePath lastPathComponent]] + tag:nil]; + + if (!success) { + std::string exception = "Can not move "; + exception += [sourcePath UTF8String]; + exception += " to trash."; + } + + return true; + } + else if (name == "reload") { + CefV8Context::GetCurrentContext()->GetBrowser()->ReloadIgnoreCache(); + } + else if (name == "lastModified") { + NSString *path = stringFromCefV8Value(arguments[0]); + NSFileManager *fm = [NSFileManager defaultManager]; + + NSError *error = nil; + NSDictionary *attributes = [fm attributesOfItemAtPath:path error:&error]; + + if (error) { + exception = [[error localizedDescription] UTF8String]; + } + + NSDate *lastModified = [attributes objectForKey:NSFileModificationDate]; + retval = CefV8Value::CreateDate(CefTime([lastModified timeIntervalSince1970])); + return true; + } + else if (name == "md5ForPath") { + NSString *path = stringFromCefV8Value(arguments[0]); + unsigned char outputData[CC_MD5_DIGEST_LENGTH]; + + NSData *inputData = [[NSData alloc] initWithContentsOfFile:path]; + CC_MD5([inputData bytes], [inputData length], outputData); + [inputData release]; + + NSMutableString *hash = [[NSMutableString alloc] init]; + + for (NSUInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { + [hash appendFormat:@"%02x", outputData[i]]; + } + + retval = CefV8Value::CreateString([hash UTF8String]); + return true; + } + else if (name == "exec") { + NSString *command = stringFromCefV8Value(arguments[0]); + CefRefPtr options = arguments[1]; + CefRefPtr callback = arguments[2]; + + NSTask *task = [[NSTask alloc] init]; + [task setLaunchPath:@"/bin/sh"]; + [task setStandardInput:[NSFileHandle fileHandleWithNullDevice]]; + [task setArguments:[NSArray arrayWithObjects:@"-l", @"-c", command, nil]]; + + NSPipe *stdout = [NSPipe pipe]; + NSPipe *stderr = [NSPipe pipe]; + [task setStandardOutput:stdout]; + [task setStandardError:stderr]; + + CefRefPtr context = CefV8Context::GetCurrentContext(); + void (^outputHandle)(NSString *contents, CefRefPtr function) = nil; + void (^taskTerminatedHandle)(NSString *output, NSString *errorOutput) = nil; + + outputHandle = ^(NSString *contents, CefRefPtr function) { + context->Enter(); + + CefV8ValueList args; + args.push_back(CefV8Value::CreateString(std::string([contents UTF8String], [contents lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); + CefRefPtr retval = function->ExecuteFunction(function, args); + + if (function->HasException()) { + throwException(context->GetGlobal(), function->GetException(), @"Error thrown in OutputHandle"); + } + + context->Exit(); + }; + + taskTerminatedHandle = ^(NSString *output, NSString *errorOutput) { + context->Enter(); + + CefV8ValueList args; + args.push_back(CefV8Value::CreateInt([task terminationStatus])); + args.push_back(CefV8Value::CreateString([output UTF8String])); + args.push_back(CefV8Value::CreateString([errorOutput UTF8String])); + + callback->ExecuteFunction(callback, args); + + if (callback->HasException()) { + throwException(context->GetGlobal(), callback->GetException(), @"Error thrown in TaskTerminatedHandle"); + } + + context->Exit(); + + stdout.fileHandleForReading.writeabilityHandler = nil; + stderr.fileHandleForReading.writeabilityHandler = nil; + }; + + task.terminationHandler = ^(NSTask *) { + NSString *output = [[NSString alloc] initWithData:[[stdout fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding]; + NSString *errorOutput = [[NSString alloc] initWithData:[[stderr fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding]; + dispatch_sync(dispatch_get_main_queue(), ^() { + taskTerminatedHandle(output, errorOutput); + }); + [output release]; + [errorOutput release]; + }; + + CefRefPtr stdoutFunction = options->GetValue("stdout"); + if (stdoutFunction->IsFunction()) { + stdout.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) { + NSData *data = [fileHandle availableData]; + NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + dispatch_sync(dispatch_get_main_queue(), ^() { + outputHandle(contents, stdoutFunction); + }); + [contents release]; + }; + } + + CefRefPtr stderrFunction = options->GetValue("stderr"); + if (stderrFunction->IsFunction()) { + stderr.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) { + NSData *data = [fileHandle availableData]; + NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + dispatch_sync(dispatch_get_main_queue(), ^() { + outputHandle(contents, stderrFunction); + }); + [contents release]; + }; + } + + [task launch]; + + return true; + } + else if (name == "getPlatform") { + retval = CefV8Value::CreateString("mac"); return true; } - CefRefPtr onFile = arguments[1]; - CefRefPtr onDir = arguments[2]; - CefV8ValueList args; - FTSENT *entry; - while ((entry = fts_read(tree)) != NULL) { - if (entry->fts_level == 0) { - continue; - } - - bool isFile = entry->fts_info == FTS_NSOK; - bool isDir = entry->fts_info == FTS_D; - if (!isFile && !isDir) { - continue; - } - - int pathLength = entry->fts_pathlen - rootPathLength; - char relative[pathLength + 1]; - relative[pathLength] = '\0'; - strncpy(relative, entry->fts_path + rootPathLength, pathLength); - args.clear(); - args.push_back(CefV8Value::CreateString(relative)); - if (isFile) { - onFile->ExecuteFunction(onFile, args); - } - else { - CefRefPtr enterDir = onDir->ExecuteFunction(onDir, args); - if(enterDir != NULL && !enterDir->GetBoolValue()) { - fts_set(tree, entry, FTS_SKIP); - } - } + else if (name == "setWindowState") { + [windowStateLock lock]; + windowState = arguments[0]->GetStringValue().ToString(); + [windowStateLock unlock]; + return true; } - return true; - } - else if (name == "isDirectory") { - NSString *path = stringFromCefV8Value(arguments[0]); - - BOOL isDir = false; - BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; - retval = CefV8Value::CreateBool(exists && isDir); - - return true; - } - else if (name == "isFile") { - NSString *path = stringFromCefV8Value(arguments[0]); - - BOOL isDir = false; - BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir]; - retval = CefV8Value::CreateBool(exists && !isDir); - - return true; - } - else if (name == "remove") { - NSString *path = stringFromCefV8Value(arguments[0]); - - NSError *error = nil; - [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; - - if (error) { - exception = [[error localizedDescription] UTF8String]; + else if (name == "getWindowState") { + [windowStateLock lock]; + retval = CefV8Value::CreateString(windowState); + [windowStateLock unlock]; + return true; } - return true; - } - else if (name == "writeToPasteboard") { - NSString *text = stringFromCefV8Value(arguments[0]); + return false; + }; - NSPasteboard *pb = [NSPasteboard generalPasteboard]; - [pb declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; - [pb setString:text forType:NSStringPboardType]; - - return true; - } - else if (name == "readFromPasteboard") { - NSPasteboard *pb = [NSPasteboard generalPasteboard]; - NSArray *results = [pb readObjectsForClasses:[NSArray arrayWithObjects:[NSString class], nil] options:nil]; - if (results) { - retval = CefV8Value::CreateString([[results objectAtIndex:0] UTF8String]); - } - - return true; - } - else if (name == "quit") { - [NSApp terminate:nil]; - return true; - } - else if (name == "watchPath") { - NSString *path = stringFromCefV8Value(arguments[0]); - CefRefPtr function = arguments[1]; - - CefRefPtr context = CefV8Context::GetCurrentContext(); - - WatchCallback callback = ^(NSString *eventType, NSString *path) { - context->Enter(); - - CefV8ValueList args; - - args.push_back(CefV8Value::CreateString(std::string([eventType UTF8String], [eventType lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - args.push_back(CefV8Value::CreateString(std::string([path UTF8String], [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - function->ExecuteFunction(function, args); - - context->Exit(); - }; - - PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; - NSString *watchId = [pathWatcher watchPath:path callback:[[callback copy] autorelease]]; - if (watchId) { - retval = CefV8Value::CreateString([watchId UTF8String]); - } - else { - exception = std::string("Failed to watch path '") + std::string([path UTF8String]) + std::string("' (it may not exist)"); - } - - return true; - } - else if (name == "unwatchPath") { - NSString *path = stringFromCefV8Value(arguments[0]); - NSString *callbackId = stringFromCefV8Value(arguments[1]); - NSError *error = nil; - PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; - [pathWatcher unwatchPath:path callbackId:callbackId error:&error]; - - if (error) { - exception = [[error localizedDescription] UTF8String]; - } - - return true; - } - else if (name == "getWatchedPaths") { - PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; - NSArray *paths = [pathWatcher watchedPaths]; - - CefRefPtr pathsArray = CefV8Value::CreateArray([paths count]); - - for (int i = 0; i < [paths count]; i++) { - CefRefPtr path = CefV8Value::CreateString([[paths objectAtIndex:i] UTF8String]); - pathsArray->SetValue(i, path); - } - retval = pathsArray; - - return true; - } - else if (name == "unwatchAllPaths") { - PathWatcher *pathWatcher = [PathWatcher pathWatcherForContext:CefV8Context::GetCurrentContext()]; - [pathWatcher unwatchAllPaths]; - return true; - } - else if (name == "makeDirectory") { - NSString *path = stringFromCefV8Value(arguments[0]); - NSFileManager *fm = [NSFileManager defaultManager]; - NSError *error = nil; - [fm createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error]; - - if (error) { - exception = [[error localizedDescription] UTF8String]; - } - - return true; - } - else if (name == "move") { - NSString *sourcePath = stringFromCefV8Value(arguments[0]); - NSString *targetPath = stringFromCefV8Value(arguments[1]); - NSFileManager *fm = [NSFileManager defaultManager]; - - NSError *error = nil; - [fm moveItemAtPath:sourcePath toPath:targetPath error:&error]; - - if (error) { - exception = [[error localizedDescription] UTF8String]; - } - - return true; - } - else if (name == "moveToTrash") { - NSString *sourcePath = stringFromCefV8Value(arguments[0]); - bool success = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation - source:[sourcePath stringByDeletingLastPathComponent] - destination:@"" - files:[NSArray arrayWithObject:[sourcePath lastPathComponent]] - tag:nil]; - - if (!success) { - std::string exception = "Can not move "; - exception += [sourcePath UTF8String]; - exception += " to trash."; - } - - return true; - } - else if (name == "reload") { - CefV8Context::GetCurrentContext()->GetBrowser()->ReloadIgnoreCache(); - } - else if (name == "lastModified") { - NSString *path = stringFromCefV8Value(arguments[0]); - NSFileManager *fm = [NSFileManager defaultManager]; - - NSError *error = nil; - NSDictionary *attributes = [fm attributesOfItemAtPath:path error:&error]; - - if (error) { - exception = [[error localizedDescription] UTF8String]; - } - - NSDate *lastModified = [attributes objectForKey:NSFileModificationDate]; - retval = CefV8Value::CreateDate(CefTime([lastModified timeIntervalSince1970])); - return true; - } - else if (name == "md5ForPath") { - NSString *path = stringFromCefV8Value(arguments[0]); - unsigned char outputData[CC_MD5_DIGEST_LENGTH]; - - NSData *inputData = [[NSData alloc] initWithContentsOfFile:path]; - CC_MD5([inputData bytes], [inputData length], outputData); - [inputData release]; - - NSMutableString *hash = [[NSMutableString alloc] init]; - - for (NSUInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { - [hash appendFormat:@"%02x", outputData[i]]; - } - - retval = CefV8Value::CreateString([hash UTF8String]); - return true; - } - else if (name == "exec") { - NSString *command = stringFromCefV8Value(arguments[0]); - CefRefPtr options = arguments[1]; - CefRefPtr callback = arguments[2]; - - NSTask *task = [[NSTask alloc] init]; - [task setLaunchPath:@"/bin/sh"]; - [task setStandardInput:[NSFileHandle fileHandleWithNullDevice]]; - [task setArguments:[NSArray arrayWithObjects:@"-l", @"-c", command, nil]]; - - NSPipe *stdout = [NSPipe pipe]; - NSPipe *stderr = [NSPipe pipe]; - [task setStandardOutput:stdout]; - [task setStandardError:stderr]; - - CefRefPtr context = CefV8Context::GetCurrentContext(); - void (^outputHandle)(NSString *contents, CefRefPtr function) = nil; - void (^taskTerminatedHandle)(NSString *output, NSString *errorOutput) = nil; - - outputHandle = ^(NSString *contents, CefRefPtr function) { - context->Enter(); - - CefV8ValueList args; - args.push_back(CefV8Value::CreateString(std::string([contents UTF8String], [contents lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - CefRefPtr retval = function->ExecuteFunction(function, args); - - if (function->HasException()) { - throwException(context->GetGlobal(), function->GetException(), @"Error thrown in OutputHandle"); - } - - context->Exit(); - }; - - taskTerminatedHandle = ^(NSString *output, NSString *errorOutput) { - context->Enter(); - - CefV8ValueList args; - args.push_back(CefV8Value::CreateInt([task terminationStatus])); - args.push_back(CefV8Value::CreateString([output UTF8String])); - args.push_back(CefV8Value::CreateString([errorOutput UTF8String])); - - callback->ExecuteFunction(callback, args); - - if (callback->HasException()) { - throwException(context->GetGlobal(), callback->GetException(), @"Error thrown in TaskTerminatedHandle"); - } - - context->Exit(); - - stdout.fileHandleForReading.writeabilityHandler = nil; - stderr.fileHandleForReading.writeabilityHandler = nil; - }; - - task.terminationHandler = ^(NSTask *) { - NSString *output = [[NSString alloc] initWithData:[[stdout fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding]; - NSString *errorOutput = [[NSString alloc] initWithData:[[stderr fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding]; - dispatch_sync(dispatch_get_main_queue(), ^() { - taskTerminatedHandle(output, errorOutput); - }); - [output release]; - [errorOutput release]; - }; - - CefRefPtr stdoutFunction = options->GetValue("stdout"); - if (stdoutFunction->IsFunction()) { - stdout.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) { - NSData *data = [fileHandle availableData]; - NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - dispatch_sync(dispatch_get_main_queue(), ^() { - outputHandle(contents, stdoutFunction); - }); - [contents release]; - }; - } - - CefRefPtr stderrFunction = options->GetValue("stderr"); - if (stderrFunction->IsFunction()) { - stderr.fileHandleForReading.writeabilityHandler = ^(NSFileHandle *fileHandle) { - NSData *data = [fileHandle availableData]; - NSString *contents = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - dispatch_sync(dispatch_get_main_queue(), ^() { - outputHandle(contents, stderrFunction); - }); - [contents release]; - }; - } - - [task launch]; - - return true; - } - else if (name == "getPlatform") { - retval = CefV8Value::CreateString("mac"); - return true; + NSString *stringFromCefV8Value(const CefRefPtr& value) { + std::string cc_value = value->GetStringValue().ToString(); + return [NSString stringWithUTF8String:cc_value.c_str()]; } - else if (name == "setWindowState") { - windowState = arguments[0]->GetStringValue().ToString(); - return true; - } + void throwException(const CefRefPtr& global, CefRefPtr exception, NSString *message) { + CefV8ValueList arguments; - else if (name == "getWindowState") { - retval = CefV8Value::CreateString(windowState); - return true; - } + message = [message stringByAppendingFormat:@"\n%s", exception->GetMessage().ToString().c_str()]; + arguments.push_back(CefV8Value::CreateString(std::string([message UTF8String], [message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]))); - return false; -}; + CefRefPtr console = global->GetValue("console"); + console->GetValue("error")->ExecuteFunction(console, arguments); + } } // namespace v8_extensions diff --git a/native/v8_extensions/onig_reg_exp.h b/native/v8_extensions/onig_reg_exp.h index 4a1725c48..4db0d0e32 100644 --- a/native/v8_extensions/onig_reg_exp.h +++ b/native/v8_extensions/onig_reg_exp.h @@ -3,18 +3,22 @@ namespace v8_extensions { -class OnigRegExp : public CefV8Handler { -public: - OnigRegExp(); - - virtual bool Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) OVERRIDE; - - // Provide the reference counting implementation for this class. - IMPLEMENT_REFCOUNTING(OnigRegExp); -}; + class OnigRegExp : public CefV8Handler { + public: + OnigRegExp(); + void CreateContextBinding(CefRefPtr context); + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE; + + // Provide the reference counting implementation for this class. + IMPLEMENT_REFCOUNTING(OnigRegExp); + + private: + OnigRegExp(OnigRegExp const&); + void operator=(OnigRegExp const&); + }; } \ No newline at end of file diff --git a/native/v8_extensions/onig_reg_exp.js b/native/v8_extensions/onig_reg_exp.js deleted file mode 100644 index ae06d5e36..000000000 --- a/native/v8_extensions/onig_reg_exp.js +++ /dev/null @@ -1,19 +0,0 @@ -(function() { - native function buildOnigRegExp(source); - native function search(string, index); - native function test(string); - - function OnigRegExp(source) { - var regexp = buildOnigRegExp(source); - regexp.constructor = OnigRegExp; - regexp.__proto__ = OnigRegExp.prototype; - regexp.source = source; - return regexp; - } - - OnigRegExp.prototype.search = search; - OnigRegExp.prototype.test = test; - - this.OnigRegExp = OnigRegExp; -})(); - diff --git a/native/v8_extensions/onig_reg_exp.mm b/native/v8_extensions/onig_reg_exp.mm index ba1657b1f..6f8b5edcd 100644 --- a/native/v8_extensions/onig_reg_exp.mm +++ b/native/v8_extensions/onig_reg_exp.mm @@ -38,21 +38,33 @@ public: return resultArray; } - + CefRefPtr Test(CefRefPtr string, CefRefPtr index) { OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()]; return CefV8Value::CreateBool(result); } - + OnigRegexp *m_regex; IMPLEMENT_REFCOUNTING(OnigRegexpUserData); }; OnigRegExp::OnigRegExp() : CefV8Handler() { - NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/onig_reg_exp.js"]; - NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - CefRegisterExtension("v8/onig-reg-exp", [extensionCode UTF8String], this); +} + +void OnigRegExp::CreateContextBinding(CefRefPtr context) { + const char* methodNames[] = { "search", "test", "buildOnigRegExp" }; + + CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); + int arrayLength = sizeof(methodNames) / sizeof(const char *); + for (int i = 0; i < arrayLength; i++) { + const char *functionName = methodNames[i]; + CefRefPtr function = CefV8Value::CreateFunction(functionName, this); + nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE); + } + + CefRefPtr global = context->GetGlobal(); + global->SetValue("$onigRegExp", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE); } bool OnigRegExp::Execute(const CefString& name, @@ -73,7 +85,7 @@ bool OnigRegExp::Execute(const CefString& name, CefRefPtr index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0); OnigRegExpUserData *userData = (OnigRegExpUserData *)object->GetUserData().get(); retval = userData->Test(string, index); - return true; + return true; } else if (name == "buildOnigRegExp") { CefRefPtr pattern = arguments[0]; diff --git a/native/v8_extensions/onig_scanner.h b/native/v8_extensions/onig_scanner.h index 462462dd1..33a2bb1af 100644 --- a/native/v8_extensions/onig_scanner.h +++ b/native/v8_extensions/onig_scanner.h @@ -2,19 +2,23 @@ #include "include/cef_v8.h" namespace v8_extensions { - + class OnigScanner : public CefV8Handler { public: OnigScanner(); - + void CreateContextBinding(CefRefPtr context); virtual bool Execute(const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception) OVERRIDE; - + // Provide the reference counting implementation for this class. IMPLEMENT_REFCOUNTING(OnigRegExp); + + private: + OnigScanner(OnigScanner const&); + void operator=(OnigScanner const&); }; - + } \ No newline at end of file diff --git a/native/v8_extensions/onig_scanner.js b/native/v8_extensions/onig_scanner.js deleted file mode 100644 index 9348ad48c..000000000 --- a/native/v8_extensions/onig_scanner.js +++ /dev/null @@ -1,17 +0,0 @@ -(function() { - native function buildScanner(sources); - native function findNextMatch(string, startPosition); - - function OnigScanner(sources) { - var scanner = buildScanner(sources); - scanner.constructor = OnigScanner; - scanner.__proto__ = OnigScanner.prototype; - scanner.sources = sources; - return scanner; - } - - OnigScanner.prototype.buildScanner = buildScanner; - OnigScanner.prototype.findNextMatch = findNextMatch; - - this.OnigScanner = OnigScanner; -})(); diff --git a/native/v8_extensions/onig_scanner.mm b/native/v8_extensions/onig_scanner.mm index b357ffeca..9d429de97 100644 --- a/native/v8_extensions/onig_scanner.mm +++ b/native/v8_extensions/onig_scanner.mm @@ -130,11 +130,22 @@ class OnigScannerUserData : public CefBase { }; OnigScanner::OnigScanner() : CefV8Handler() { - NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/onig_scanner.js"]; - NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - CefRegisterExtension("v8/onig-scanner", [extensionCode UTF8String], this); } +void OnigScanner::CreateContextBinding(CefRefPtr context) { + const char* methodNames[] = { "findNextMatch", "buildScanner" }; + + CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); + int arrayLength = sizeof(methodNames) / sizeof(const char *); + for (int i = 0; i < arrayLength; i++) { + const char *functionName = methodNames[i]; + CefRefPtr function = CefV8Value::CreateFunction(functionName, this); + nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE); + } + + CefRefPtr global = context->GetGlobal(); + global->SetValue("$onigScanner", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE); +} bool OnigScanner::Execute(const CefString& name, CefRefPtr object, diff --git a/native/v8_extensions/tags.h b/native/v8_extensions/tags.h index 48cbcd34e..e8c6627bf 100644 --- a/native/v8_extensions/tags.h +++ b/native/v8_extensions/tags.h @@ -4,21 +4,23 @@ namespace v8_extensions { -class Tags : public CefV8Handler { -public: - Tags(); + class Tags : public CefV8Handler { + public: + Tags(); + void CreateContextBinding(CefRefPtr context); + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE; - virtual bool Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) OVERRIDE; + // Provide the reference counting implementation for this class. + IMPLEMENT_REFCOUNTING(Tags); - // Provide the reference counting implementation for this class. - IMPLEMENT_REFCOUNTING(Tags); - -private: - CefRefPtr ParseEntry(tagEntry entry); -}; + private: + Tags(Tags const&); + void operator=(Tags const&); + CefRefPtr ParseEntry(tagEntry entry); + }; } diff --git a/native/v8_extensions/tags.js b/native/v8_extensions/tags.js deleted file mode 100644 index cdef853d0..000000000 --- a/native/v8_extensions/tags.js +++ /dev/null @@ -1,10 +0,0 @@ -var $tags = {}; -(function() { - - native function find(path, tag); - $tags.find = find; - - native function getAllTagsAsync(path, callback); - $tags.getAllTagsAsync = getAllTagsAsync; - -})(); diff --git a/native/v8_extensions/tags.mm b/native/v8_extensions/tags.mm index 000bbdc12..74e46f275 100644 --- a/native/v8_extensions/tags.mm +++ b/native/v8_extensions/tags.mm @@ -3,100 +3,112 @@ namespace v8_extensions { -Tags::Tags() : CefV8Handler() { - NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"v8_extensions/tags.js"]; - NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - CefRegisterExtension("v8/tags", [extensionCode UTF8String], this); -} - -CefRefPtr Tags::ParseEntry(tagEntry entry) { - CefRefPtr tagEntry = CefV8Value::CreateObject(NULL); - tagEntry->SetValue("name", CefV8Value::CreateString(entry.name), V8_PROPERTY_ATTRIBUTE_NONE); - tagEntry->SetValue("file", CefV8Value::CreateString(entry.file), V8_PROPERTY_ATTRIBUTE_NONE); - if (entry.address.pattern) { - tagEntry->SetValue("pattern", CefV8Value::CreateString(entry.address.pattern), V8_PROPERTY_ATTRIBUTE_NONE); + Tags::Tags() : CefV8Handler() { } - return tagEntry; -} -bool Tags::Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) { + void Tags::CreateContextBinding(CefRefPtr context) { + const char* methodNames[] = { "find", "getAllTagsAsync" }; - if (name == "find") { - std::string path = arguments[0]->GetStringValue().ToString(); - std::string tag = arguments[1]->GetStringValue().ToString(); - tagFileInfo info; - tagFile* tagFile; - tagFile = tagsOpen(path.c_str(), &info); - if (info.status.opened) { - tagEntry entry; - std::vector> entries; - if (tagsFind(tagFile, &entry, tag.c_str(), TAG_FULLMATCH | TAG_OBSERVECASE) == TagSuccess) { - entries.push_back(ParseEntry(entry)); - while (tagsFindNext(tagFile, &entry) == TagSuccess) { - entries.push_back(ParseEntry(entry)); - } - } - - retval = CefV8Value::CreateArray(entries.size()); - for (int i = 0; i < entries.size(); i++) { - retval->SetValue(i, entries[i]); - } - tagsClose(tagFile); + CefRefPtr nativeObject = CefV8Value::CreateObject(NULL); + int arrayLength = sizeof(methodNames) / sizeof(const char *); + for (int i = 0; i < arrayLength; i++) { + const char *functionName = methodNames[i]; + CefRefPtr function = CefV8Value::CreateFunction(functionName, this); + nativeObject->SetValue(functionName, function, V8_PROPERTY_ATTRIBUTE_NONE); } - return true; + + CefRefPtr global = context->GetGlobal(); + global->SetValue("$tags", nativeObject, V8_PROPERTY_ATTRIBUTE_NONE); } - if (name == "getAllTagsAsync") { - std::string path = arguments[0]->GetStringValue().ToString(); - CefRefPtr callback = arguments[1]; - CefRefPtr context = CefV8Context::GetCurrentContext(); + CefRefPtr Tags::ParseEntry(tagEntry entry) { + CefRefPtr tagEntry = CefV8Value::CreateObject(NULL); + tagEntry->SetValue("name", CefV8Value::CreateString(entry.name), V8_PROPERTY_ATTRIBUTE_NONE); + tagEntry->SetValue("file", CefV8Value::CreateString(entry.file), V8_PROPERTY_ATTRIBUTE_NONE); + if (entry.address.pattern) { + tagEntry->SetValue("pattern", CefV8Value::CreateString(entry.address.pattern), V8_PROPERTY_ATTRIBUTE_NONE); + } + return tagEntry; + } - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_async(queue, ^{ + bool Tags::Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) { + + if (name == "find") { + std::string path = arguments[0]->GetStringValue().ToString(); + std::string tag = arguments[1]->GetStringValue().ToString(); tagFileInfo info; tagFile* tagFile; tagFile = tagsOpen(path.c_str(), &info); - std::vector entries; - if (info.status.opened) { tagEntry entry; - while (tagsNext(tagFile, &entry) == TagSuccess) { - entry.name = strdup(entry.name); - entry.file = strdup(entry.file); - if (entry.address.pattern) { - entry.address.pattern = strdup(entry.address.pattern); + std::vector> entries; + if (tagsFind(tagFile, &entry, tag.c_str(), TAG_FULLMATCH | TAG_OBSERVECASE) == TagSuccess) { + entries.push_back(ParseEntry(entry)); + while (tagsFindNext(tagFile, &entry) == TagSuccess) { + entries.push_back(ParseEntry(entry)); } - entries.push_back(entry); + } + + retval = CefV8Value::CreateArray(entries.size()); + for (int i = 0; i < entries.size(); i++) { + retval->SetValue(i, entries[i]); } tagsClose(tagFile); } + return true; + } - dispatch_queue_t mainQueue = dispatch_get_main_queue(); - dispatch_async(mainQueue, ^{ - context->Enter(); - CefRefPtr v8Tags = CefV8Value::CreateArray(entries.size()); - for (int i = 0; i < entries.size(); i++) { - v8Tags->SetValue(i, ParseEntry(entries[i])); - free((void*)entries[i].name); - free((void*)entries[i].file); - if (entries[i].address.pattern) { - free((void*)entries[i].address.pattern); + if (name == "getAllTagsAsync") { + std::string path = arguments[0]->GetStringValue().ToString(); + CefRefPtr callback = arguments[1]; + CefRefPtr context = CefV8Context::GetCurrentContext(); + + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_async(queue, ^{ + tagFileInfo info; + tagFile* tagFile; + tagFile = tagsOpen(path.c_str(), &info); + std::vector entries; + + if (info.status.opened) { + tagEntry entry; + while (tagsNext(tagFile, &entry) == TagSuccess) { + entry.name = strdup(entry.name); + entry.file = strdup(entry.file); + if (entry.address.pattern) { + entry.address.pattern = strdup(entry.address.pattern); + } + entries.push_back(entry); } + tagsClose(tagFile); } - CefV8ValueList callbackArgs; - callbackArgs.push_back(v8Tags); - callback->ExecuteFunction(callback, callbackArgs); - context->Exit(); + + dispatch_queue_t mainQueue = dispatch_get_main_queue(); + dispatch_async(mainQueue, ^{ + context->Enter(); + CefRefPtr v8Tags = CefV8Value::CreateArray(entries.size()); + for (int i = 0; i < entries.size(); i++) { + v8Tags->SetValue(i, ParseEntry(entries[i])); + free((void*)entries[i].name); + free((void*)entries[i].file); + if (entries[i].address.pattern) { + free((void*)entries[i].address.pattern); + } + } + CefV8ValueList callbackArgs; + callbackArgs.push_back(v8Tags); + callback->ExecuteFunction(callback, callbackArgs); + context->Exit(); + }); }); - }); - return true; + return true; + } + + return false; } - return false; -} - } diff --git a/script/update-cef b/script/update-cef index d58b03a0b..817c65575 100755 --- a/script/update-cef +++ b/script/update-cef @@ -1,7 +1,7 @@ #!/bin/sh usage() { - echo 'usage: `basename $0` 'chromium-dir' [cef-release-branch] 1>&2' + echo 'usage: update-cef chromium-dir [cef-release-branch] 1>&2' echo echo 'chromium-dir is the root of the chromium directory (i.e. ~/code/chromium)' echo 'CEF release branches can be found at http://code.google.com/p/chromiumembedded/wiki/BranchesAndBuilding' @@ -14,9 +14,13 @@ fi ATOM_ROOT=$(cd $(dirname $0); pwd -P)/.. CHROMIUM_DIR=$1 -CEF_DIR=$CHROMIUM_DIR/src/cef/ +CEF_DIR=$CHROMIUM_DIR/src/cef CEF_RELEASE_BRANCH=${2:-1271} -CEF_BINARY_PATH=$(echo "$CEF_DIR"/binary_distrib/cef_binary_*_macosx/) # Expand the path +CEF_REVISION=$(svnversion $CEF_DIR) +CEF_BINARY_PATH=$(echo ${CEF_DIR}/binary_distrib/cef_binary_3.${CEF_RELEASE_BRANCH}.${CEF_REVISION}_macosx/) # Expand the path + +echo "CEF_RELEASE_BRANCH=$CEF_RELEASE_BRANCH" +echo "CEF_BINARY_PATH=$CEF_BINARY_PATH" # Update and compile CEF CEF_AUTOMATE_SCRIPT_PATH=/tmp/cef-update diff --git a/script/update-libgit2 b/script/update-libgit2 index 7f6face0c..301b1f24c 100755 --- a/script/update-libgit2 +++ b/script/update-libgit2 @@ -1,4 +1,18 @@ #!/bin/sh +# From root of libgit2 repo: +# mkdir build +# cd build +# cmake .. -DCMAKE_INSTALL_PREFIX=~/repos/atom/git2 -DCMAKE_OSX_ARCHITECTURES="i386;x86_64" -DCMAKE_BUILD_TYPE=Release +# cmake --build . --target install +# +# From root of atom repo: +# mv git2/lib/libgit2.0.17.0.dylib git2/frameworks/libgit2.0.17.0.dylib +# rm -fr git2/lib +# script/update-libgit2 + # update the id of the dylib install_name_tool -id @executable_path/libgit2.0.17.0.dylib git2/frameworks/libgit2.0.17.0.dylib + +# Verify @executable_path is in the output of: +otool -L git2/frameworks/libgit2.0.17.0.dylib diff --git a/spec/app/atom-spec.coffee b/spec/app/atom-spec.coffee index a117d48b8..a02c84d97 100644 --- a/spec/app/atom-spec.coffee +++ b/spec/app/atom-spec.coffee @@ -16,9 +16,10 @@ describe "the `atom` global", -> it "requires and activates the package's main module if it exists", -> spyOn(rootView, 'activatePackage').andCallThrough() atom.loadPackage("package-with-module") - expect(rootView.activatePackage).toHaveBeenCalledWith('package-with-module', extension) + expect(rootView.activatePackage).toHaveBeenCalled() it "logs warning instead of throwing an exception if a package fails to load", -> + config.set("core.disabledPackages", []) spyOn(console, "warn") expect(-> atom.loadPackage("package-that-throws-an-exception")).not.toThrow() expect(console.warn).toHaveBeenCalled() @@ -55,3 +56,22 @@ describe "the `atom` global", -> expect(stylesheetElementForId(stylesheetPath).length).toBe 0 atom.loadPackage("package-with-module") expect(stylesheetElementForId(stylesheetPath).length).toBe 1 + + describe ".loadPackages()", -> + beforeEach -> + spyOn(syntax, 'addGrammar') + + it "terminates the worker when all packages have been loaded", -> + spyOn(Worker.prototype, 'terminate').andCallThrough() + eventHandler = jasmine.createSpy('eventHandler') + syntax.on 'grammars-loaded', eventHandler + disabledPackages = config.get("core.disabledPackages") + disabledPackages.push('textmate-package.tmbundle') + config.set "core.disabledPackages", disabledPackages + atom.loadPackages() + + waitsFor "all packages to load", 5000, -> eventHandler.callCount > 0 + + runs -> + expect(Worker.prototype.terminate).toHaveBeenCalled() + expect(Worker.prototype.terminate.calls.length).toBe 1 diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index a4a1fea71..ea10907cf 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -128,6 +128,22 @@ describe 'Buffer', -> runs -> expect(buffer.isModified()).toBeTruthy() + it "fires a single contents-conflicted event", -> + buffer.insert([0, 0], "a change") + buffer.save() + buffer.insert([0, 0], "a second change") + + handler = jasmine.createSpy('fileChange') + fs.write(path, "second") + buffer.on 'contents-conflicted', handler + + expect(handler.callCount).toBe 0 + waitsFor -> + handler.callCount > 0 + + runs -> + expect(handler.callCount).toBe 1 + describe "when the buffer's file is deleted (via another process)", -> [path, bufferToDelete] = [] @@ -625,7 +641,7 @@ describe 'Buffer', -> expect(ranges[1]).toEqual [[6,6], [6,13]] describe ".characterIndexForPosition(position)", -> - it "returns the total number of charachters that precede the given position", -> + it "returns the total number of characters that precede the given position", -> expect(buffer.characterIndexForPosition([0, 0])).toBe 0 expect(buffer.characterIndexForPosition([0, 1])).toBe 1 expect(buffer.characterIndexForPosition([0, 29])).toBe 29 @@ -634,7 +650,7 @@ describe 'Buffer', -> expect(buffer.characterIndexForPosition([12, 2])).toBe 408 describe ".positionForCharacterIndex(position)", -> - it "returns the position based on charachter index", -> + it "returns the position based on character index", -> expect(buffer.positionForCharacterIndex(0)).toEqual [0, 0] expect(buffer.positionForCharacterIndex(1)).toEqual [0, 1] expect(buffer.positionForCharacterIndex(29)).toEqual [0, 29] @@ -817,3 +833,51 @@ describe 'Buffer', -> expect(buffer.getText()).toBe "a" buffer.append("b\nc"); expect(buffer.getText()).toBe "ab\nc" + + describe "line ending support", -> + describe ".lineEndingForRow(line)", -> + it "return the line ending for each buffer line", -> + buffer.setText("a\r\nb\nc") + expect(buffer.lineEndingForRow(0)).toBe '\r\n' + expect(buffer.lineEndingForRow(1)).toBe '\n' + expect(buffer.lineEndingForRow(2)).toBeUndefined() + + describe ".lineForRow(line)", -> + it "returns the line text without the line ending for both lf and crlf lines", -> + buffer.setText("a\r\nb\nc") + expect(buffer.lineForRow(0)).toBe 'a' + expect(buffer.lineForRow(1)).toBe 'b' + expect(buffer.lineForRow(2)).toBe 'c' + + describe ".getText()", -> + it "returns the text with the corrent line endings for each row", -> + buffer.setText("a\r\nb\nc") + expect(buffer.getText()).toBe "a\r\nb\nc" + buffer.setText("a\r\nb\nc\n") + expect(buffer.getText()).toBe "a\r\nb\nc\n" + + describe "when editing a line", -> + it "preserves the existing line ending", -> + buffer.setText("a\r\nb\nc") + buffer.insert([0, 1], "1") + expect(buffer.getText()).toBe "a1\r\nb\nc" + + describe "when inserting text with multiple lines", -> + describe "when the current line has a line ending", -> + it "uses the same line ending as the line where the text is inserted", -> + buffer.setText("a\r\n") + buffer.insert([0,1], "hello\n1\n\n2") + expect(buffer.getText()).toBe "ahello\r\n1\r\n\r\n2\r\n" + + describe "when the current line has no line ending (because it's the last line of the buffer)", -> + describe "when the buffer contains only a single line", -> + it "honors the line endings in the inserted text", -> + buffer.setText("initialtext") + buffer.append("hello\n1\r\n2\n") + expect(buffer.getText()).toBe "initialtexthello\n1\r\n2\n" + + describe "when the buffer contains a preceding line", -> + it "uses the line ending of the preceding line", -> + buffer.setText("\ninitialtext") + buffer.append("hello\n1\r\n2\n") + expect(buffer.getText()).toBe "\ninitialtexthello\n1\n2\n" diff --git a/spec/app/edit-session-spec.coffee b/spec/app/edit-session-spec.coffee index c74a6605e..6f72cd8bc 100644 --- a/spec/app/edit-session-spec.coffee +++ b/spec/app/edit-session-spec.coffee @@ -2007,3 +2007,16 @@ describe "EditSession", -> expect(editSession.lineForBufferRow(2)).toBe " 0" expect(editSession.lineForBufferRow(3)).toBe " 2" expect(editSession.lineForBufferRow(4)).toBe " 4" + + describe ".autoDecreaseIndentForRow()", -> + it "doesn't outdent the first and only row", -> + editSession.selectAll() + editSession.insertText("}") + editSession.autoDecreaseIndentForRow(0) + expect(editSession.lineForBufferRow(0)).toBe "}" + + it "doesn't outdent a row that is already fully outdented", -> + editSession.selectAll() + editSession.insertText("var i;\n}") + editSession.autoDecreaseIndentForRow(1) + expect(editSession.lineForBufferRow(1)).toBe "}" diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 777e7b7b3..25dc557dc 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -558,7 +558,7 @@ describe "Editor", -> rootView.attachToDom() config.set("editor.fontSize", 16 * 4) expect(editor.gutter.css('font-size')).toBe "#{16 * 4}px" - expect(editor.gutter.width()).toBe(141) + expect(editor.gutter.width()).toBe(64) it "updates lines if there are unrendered lines", -> editor.attachToDom(heightInLines: 5) @@ -744,7 +744,7 @@ describe "Editor", -> editor.renderedLines.trigger mousedownEvent(editor: editor, point: [12, 0]) # moving changes selection - $(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -10) + $(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -15) expect(editor.scrollTop()).toBe 4 * editor.lineHeight # if cursor stays off screen, we keep moving / scrolling up @@ -1604,6 +1604,49 @@ describe "Editor", -> expect(rightEditor.find(".line:first").text()).toBe "_tab _;" expect(leftEditor.find(".line:first").text()).toBe "_tab _;" + it "displays trailing carriage return using a visible non-empty value", -> + editor.setText "a line that ends with a carriage return\r\n" + editor.attachToDom() + + expect(config.get("editor.showInvisibles")).toBeFalsy() + expect(editor.renderedLines.find('.line:first').text()).toBe "a line that ends with a carriage return" + + config.set("editor.showInvisibles", true) + cr = editor.invisibles?.cr + expect(cr).toBeTruthy() + eol = editor.invisibles?.eol + expect(eol).toBeTruthy() + expect(editor.renderedLines.find('.line:first').text()).toBe "a line that ends with a carriage return#{cr}#{eol}" + + + describe "when wrapping is on", -> + it "doesn't show the end of line invisible at the end of lines broken due to wrapping", -> + editor.setSoftWrapColumn(6) + editor.setText "a line that wraps" + editor.attachToDom() + config.set "editor.showInvisibles", true + space = editor.invisibles?.space + expect(space).toBeTruthy() + eol = editor.invisibles?.eol + expect(eol).toBeTruthy() + expect(editor.renderedLines.find('.line:first').text()).toBe "a line#{space}" + expect(editor.renderedLines.find('.line:last').text()).toBe "wraps#{eol}" + + it "displays trailing carriage return using a visible non-empty value", -> + editor.setSoftWrapColumn(6) + editor.setText "a line that\r\n" + editor.attachToDom() + config.set "editor.showInvisibles", true + space = editor.invisibles?.space + expect(space).toBeTruthy() + cr = editor.invisibles?.cr + expect(cr).toBeTruthy() + eol = editor.invisibles?.eol + expect(eol).toBeTruthy() + expect(editor.renderedLines.find('.line:first').text()).toBe "a line#{space}" + expect(editor.renderedLines.find('.line:eq(1)').text()).toBe "that#{cr}#{eol}" + expect(editor.renderedLines.find('.line:last').text()).toBe "#{eol}" + describe "gutter rendering", -> beforeEach -> editor.attachToDom(heightInLines: 5.5) @@ -2212,3 +2255,8 @@ describe "Editor", -> edited = editor.replaceSelectedText(replacer) expect(replaced).toBe true expect(edited).toBe false + + describe "when editor:copy-path is triggered", -> + it "copies the absolute path to the editor's file to the pasteboard", -> + editor.trigger 'editor:copy-path' + expect(pasteboard.read()[0]).toBe editor.getPath() diff --git a/spec/app/language-mode-spec.coffee b/spec/app/language-mode-spec.coffee index 340f4865c..775baefa1 100644 --- a/spec/app/language-mode-spec.coffee +++ b/spec/app/language-mode-spec.coffee @@ -23,12 +23,12 @@ describe "LanguageMode", -> beforeEach -> editSession.buffer.setText("") - describe "when more than one charachter is inserted", -> + describe "when more than one character is inserted", -> it "does not insert a matching bracket", -> editSession.insertText("woah(") expect(editSession.buffer.getText()).toBe "woah(" - describe "when there is a word charachter after the cursor", -> + describe "when there is a word character after the cursor", -> it "does not insert a matching bracket", -> editSession.buffer.setText("ab") editSession.setCursorBufferPosition([0, 1]) @@ -47,7 +47,7 @@ describe "LanguageMode", -> expect(editSession.buffer.getText()).toBe "())\na)b\n[)]\n1)2" - describe "when there is a non-word characher after the cursor", -> + describe "when there is a non-word character after the cursor", -> it "inserts a closing bracket after an opening bracket is inserted", -> editSession.buffer.setText("}") editSession.setCursorBufferPosition([0, 0]) @@ -145,8 +145,30 @@ describe "LanguageMode", -> expect(buffer.lineForRow(0)).toBe '"ok"' expect(editSession.getCursorBufferPosition()).toEqual [0, 4] + describe "when there is text selected on a single line", -> + it "wraps the selection with brackets", -> + editSession.insertText 'text' + editSession.moveCursorToBottom() + editSession.selectToTop() + editSession.selectAll() + editSession.insertText '(' + expect('(text)').toBe buffer.getText() + expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [0, 5]] + expect(editSession.getSelection().isReversed()).toBeTruthy() + + describe "when there is text selected on multiple lines", -> + it "wraps the selection with brackets", -> + editSession.insertText 'text\nabcd' + editSession.moveCursorToBottom() + editSession.selectToTop() + editSession.selectAll() + editSession.insertText '(' + expect('(text\nabcd)').toBe buffer.getText() + expect(editSession.getSelectedBufferRange()).toEqual [[0, 1], [1, 4]] + expect(editSession.getSelection().isReversed()).toBeTruthy() + describe "when inserting a quote", -> - describe "when a word charachter is before the cursor", -> + describe "when a word character is before the cursor", -> it "does not automatically insert closing quote", -> editSession.buffer.setText("abc") editSession.setCursorBufferPosition([0, 3]) @@ -158,7 +180,7 @@ describe "LanguageMode", -> editSession.insertText '\'' expect(buffer.lineForRow(0)).toBe "abc\'" - describe "when a non word charachter is before the cursor", -> + describe "when a non word character is before the cursor", -> it "automatically insert closing quote", -> editSession.buffer.setText("ab@") editSession.setCursorBufferPosition([0, 3]) @@ -174,6 +196,15 @@ describe "LanguageMode", -> expect(buffer.lineForRow(0)).toBe "\"\"" expect(editSession.getCursorBufferPosition()).toEqual [0, 1] + describe "bracket deletion", -> + it "deletes the end bracket when it directly proceeds a begin bracket that is being backspaced", -> + buffer.setText("") + editSession.setCursorBufferPosition([0, 0]) + editSession.insertText '{' + expect(buffer.lineForRow(0)).toBe "{}" + editSession.backspace() + expect(buffer.lineForRow(0)).toBe "" + describe "javascript", -> beforeEach -> editSession = fixturesProject.buildEditSessionForPath('sample.js', autoIndent: false) @@ -277,16 +308,16 @@ describe "LanguageMode", -> expect(buffer.lineForRow(3)).toBe " font-weight: bold !important;" it "uncomments lines with leading whitespace", -> - buffer.replaceLines(2, 2, " /*width: 110%;*/") + buffer.change([[2, 0], [2, Infinity]], " /*width: 110%;*/") languageMode.toggleLineCommentsForBufferRows(2, 2) expect(buffer.lineForRow(2)).toBe " width: 110%;" it "uncomments lines with trailing whitespace", -> - buffer.replaceLines(2, 2, "/*width: 110%;*/ ") + buffer.change([[2, 0], [2, Infinity]], "/*width: 110%;*/ ") languageMode.toggleLineCommentsForBufferRows(2, 2) expect(buffer.lineForRow(2)).toBe "width: 110%; " it "uncomments lines with leading and trailing whitespace", -> - buffer.replaceLines(2, 2, " /*width: 110%;*/ ") + buffer.change([[2, 0], [2, Infinity]], " /*width: 110%;*/ ") languageMode.toggleLineCommentsForBufferRows(2, 2) expect(buffer.lineForRow(2)).toBe " width: 110%; " diff --git a/spec/app/select-list-spec.coffee b/spec/app/select-list-spec.coffee index 01ffeb445..a39c4a128 100644 --- a/spec/app/select-list-spec.coffee +++ b/spec/app/select-list-spec.coffee @@ -59,6 +59,17 @@ describe "SelectList", -> expect(selectList.error).not.toBeVisible() expect(selectList).not.toHaveClass("error") + it "displays no elements until the array has been set on the list", -> + selectList.array = null + selectList.list.empty() + miniEditor.insertText('la') + window.advanceClock(selectList.inputThrottle) + + expect(list.find('li').length).toBe 0 + expect(selectList).not.toHaveClass("error") + selectList.setArray(array) + expect(list.find('li').length).toBe 2 + describe "when core:move-up / core:move-down are triggered on the miniEditor", -> it "selects the previous / next item in the list, or wraps around to the other side", -> expect(list.find('li:first')).toHaveClass 'selected' @@ -153,3 +164,16 @@ describe "SelectList", -> miniEditor.trigger 'focusout' expect(selectList.cancelled).toHaveBeenCalled() expect(selectList.detach).toHaveBeenCalled() + + describe "the core:move-to-top event", -> + it "scrolls to the top and selects the first element", -> + selectList.trigger 'core:move-down' + expect(list.find('li:eq(1)')).toHaveClass 'selected' + selectList.trigger 'core:move-to-top' + expect(list.find('li:first')).toHaveClass 'selected' + + describe "the core:move-to-bottom event", -> + it "scrolls to the bottom and selects the last element", -> + expect(list.find('li:first')).toHaveClass 'selected' + selectList.trigger 'core:move-to-bottom' + expect(list.find('li:last')).toHaveClass 'selected' diff --git a/spec/app/text-mate-theme-spec.coffee b/spec/app/text-mate-theme-spec.coffee index 381d3297e..5191ced55 100644 --- a/spec/app/text-mate-theme-spec.coffee +++ b/spec/app/text-mate-theme-spec.coffee @@ -21,7 +21,7 @@ describe "TextMateTheme", -> it "returns rulesets representing the theme's global style settings", -> expect(rulesets[0]).toEqual - selector: '.editor' + selector: '.editor, .editor .gutter' properties: 'background-color': '#141414' 'color': '#F8F8F8' @@ -37,7 +37,7 @@ describe "TextMateTheme", -> 'background-color': "rgba(221, 240, 255, 0.2)" it "returns an array of objects representing the theme's scope selectors", -> - expect(rulesets[11]).toEqual + expect(rulesets[12]).toEqual comment: "Invalid – Deprecated" selector: ".invalid.deprecated" properties: @@ -45,7 +45,7 @@ describe "TextMateTheme", -> # 'font-style': 'italic' 'text-decoration': 'underline' - expect(rulesets[12]).toEqual + expect(rulesets[13]).toEqual comment: "Invalid – Illegal" selector: ".invalid.illegal" properties: diff --git a/spec/fixtures/packages/package-with-module/index.coffee b/spec/fixtures/packages/package-with-module/index.coffee index 25df27829..6b54f633a 100644 --- a/spec/fixtures/packages/package-with-module/index.coffee +++ b/spec/fixtures/packages/package-with-module/index.coffee @@ -1,3 +1,6 @@ +AtomPackage = require 'atom-package' + module.exports = +class MyPackage extends AtomPackage activate: -> @activateCalled = true diff --git a/spec/fixtures/packages/textmate-package.tmbundle/Snippets/.hidden-file b/spec/fixtures/packages/textmate-package.tmbundle/Snippets/.hidden-file new file mode 100644 index 000000000..35b867918 --- /dev/null +++ b/spec/fixtures/packages/textmate-package.tmbundle/Snippets/.hidden-file @@ -0,0 +1 @@ +I am hidden so I shouldn't be loaded diff --git a/spec/fixtures/packages/textmate-package.tmbundle/Snippets/invalid.plist b/spec/fixtures/packages/textmate-package.tmbundle/Snippets/invalid.plist new file mode 100644 index 000000000..d6970c8b7 --- /dev/null +++ b/spec/fixtures/packages/textmate-package.tmbundle/Snippets/invalid.plist @@ -0,0 +1 @@ +I am not a valid plist but that shouldn't cause a crisis diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 01736d4af..a0e49740a 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -35,6 +35,7 @@ beforeEach -> spyOn(config, 'save') config.set "editor.fontSize", 16 config.set "editor.autoIndent", false + config.set "core.disabledPackages", ["package-that-throws-an-exception"] # make editor display updates synchronous spyOn(Editor.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay() diff --git a/spec/stdlib/onig-reg-exp-spec.coffee b/spec/stdlib/onig-reg-exp-spec.coffee index 0b65ab120..14955c317 100644 --- a/spec/stdlib/onig-reg-exp-spec.coffee +++ b/spec/stdlib/onig-reg-exp-spec.coffee @@ -1,3 +1,5 @@ +OnigRegExp = require 'onig-reg-exp' + describe "OnigRegExp", -> describe ".search(string, index)", -> it "returns an array of the match and all capture groups", -> diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index e86678a37..bb1ce071b 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -5,6 +5,7 @@ module.exports = class AtomPackage extends Package metadata: null keymapsDirPath: null + autoloadStylesheets: true constructor: (@name) -> super @@ -12,15 +13,13 @@ class AtomPackage extends Package load: -> try - if @requireModule - @module = require(@path) - @module.name = @name @loadMetadata() @loadKeymaps() - @loadStylesheets() - rootView.activatePackage(@name, @module) if @module + @loadStylesheets() if @autoloadStylesheets + rootView?.activatePackage(@name, this) unless @isDirectory catch e console.warn "Failed to load package named '#{@name}'", e.stack + this loadMetadata: -> if metadataPath = fs.resolveExtension(fs.join(@path, "package"), ['cson', 'json']) diff --git a/src/app/atom.coffee b/src/app/atom.coffee index ee5c8a442..455382926 100644 --- a/src/app/atom.coffee +++ b/src/app/atom.coffee @@ -3,20 +3,31 @@ _ = require 'underscore' Package = require 'package' TextMatePackage = require 'text-mate-package' Theme = require 'theme' +LoadTextMatePackagesTask = require 'load-text-mate-packages-task' messageIdCounter = 1 originalSendMessageToBrowserProcess = atom.sendMessageToBrowserProcess _.extend atom, exitWhenDone: window.location.params.exitWhenDone - + loadedThemes: [] pendingBrowserProcessCallbacks: {} loadPackages: -> - pack.load() for pack in @getPackages() + {packages, asyncTextMatePackages} = _.groupBy @getPackages(), (pack) -> + if pack instanceof TextMatePackage and pack.name isnt 'text.tmbundle' + 'asyncTextMatePackages' + else + 'packages' + + pack.load() for pack in packages + if asyncTextMatePackages.length + new LoadTextMatePackagesTask(asyncTextMatePackages).start() getPackages: -> - @getPackageNames().map (name) -> Package.build(name) + @packages ?= @getPackageNames().map((name) -> Package.build(name)) + .filter((pack) -> pack?) + new Array(@packages...) loadTextMatePackages: -> pack.load() for pack in @getTextMatePackages() @@ -25,7 +36,7 @@ _.extend atom, @getPackages().filter (pack) -> pack instanceof TextMatePackage loadPackage: (name) -> - Package.build(name).load() + Package.build(name)?.load() getPackageNames: -> disabledPackages = config.get("core.disabledPackages") ? [] @@ -39,12 +50,16 @@ _.extend atom, .filter (name) -> not _.contains(disabledPackages, name) loadThemes: -> - themeNames = config.get("core.themes") ? ['IR_Black'] + themeNames = config.get("core.themes") ? ['Atom - Dark', 'IR_Black'] themeNames = [themeNames] unless _.isArray(themeNames) @loadTheme(themeName) for themeName in themeNames loadTheme: (name) -> - Theme.load(name) + @loadedThemes.push Theme.load(name) + + getAtomThemeStylesheets: -> + themeNames = config.get("core.themes") ? ['Atom - Dark', 'IR_Black'] + themeNames = [themeNames] unless _.isArray(themeNames) open: (args...) -> @sendMessageToBrowserProcess('open', args) diff --git a/src/app/buffer-change-operation.coffee b/src/app/buffer-change-operation.coffee index 6fd0f2654..06b241c75 100644 --- a/src/app/buffer-change-operation.coffee +++ b/src/app/buffer-change-operation.coffee @@ -1,4 +1,5 @@ Range = require 'range' +_ = require 'underscore' module.exports = class BufferChangeOperation @@ -8,7 +9,8 @@ class BufferChangeOperation newRange: null newText: null - constructor: ({@buffer, @oldRange, @newText}) -> + constructor: ({@buffer, @oldRange, @newText, @options}) -> + @options ?= {} do: -> @oldText = @buffer.getTextInRange(@oldRange) @@ -26,18 +28,39 @@ class BufferChangeOperation oldText: @newText newText: @oldText + splitLines: (text) -> + lines = text.split('\n') + lineEndings = [] + for line, index in lines + if _.endsWith(line, '\r') + lines[index] = line[...-1] + lineEndings[index] = '\r\n' + else + lineEndings[index] = '\n' + {lines, lineEndings} + changeBuffer: ({ oldRange, newRange, newText, oldText }) -> { prefix, suffix } = @buffer.prefixAndSuffixForRange(oldRange) - newTextLines = newText.split('\n') - if newTextLines.length == 1 - newTextLines = [prefix + newText + suffix] - else - lastLineIndex = newTextLines.length - 1 - newTextLines[0] = prefix + newTextLines[0] - newTextLines[lastLineIndex] += suffix + {lines, lineEndings} = @splitLines(newText) + lastLineIndex = lines.length - 1 - @buffer.replaceLines(oldRange.start.row, oldRange.end.row, newTextLines) + if lines.length == 1 + lines = [prefix + newText + suffix] + else + lines[0] = prefix + lines[0] + lines[lastLineIndex] += suffix + + startRow = oldRange.start.row + endRow = oldRange.end.row + + normalizeLineEndings = @options.normalizeLineEndings ? true + if normalizeLineEndings and suggestedLineEnding = @buffer.suggestedLineEndingForRow(startRow) + lineEndings[index] = suggestedLineEnding for index in [0..lastLineIndex] + @buffer.lines[startRow..endRow] = lines + @buffer.lineEndings[startRow..endRow] = lineEndings + @buffer.cachedMemoryContents = null + @buffer.conflict = false if @buffer.conflict and !@buffer.isModified() event = { oldRange, newRange, oldText, newText } @buffer.trigger 'changed', event @@ -47,11 +70,11 @@ class BufferChangeOperation calculateNewRange: (oldRange, newText) -> newRange = new Range(oldRange.start.copy(), oldRange.start.copy()) - newTextLines = newText.split('\n') - if newTextLines.length == 1 + {lines} = @splitLines(newText) + if lines.length == 1 newRange.end.column += newText.length else - lastLineIndex = newTextLines.length - 1 + lastLineIndex = lines.length - 1 newRange.end.row += lastLineIndex - newRange.end.column = newTextLines[lastLineIndex].length + newRange.end.column = lines[lastLineIndex].length newRange diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index d5f9bd34c..266b30ba2 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -19,6 +19,7 @@ class Buffer cachedMemoryContents: null conflict: false lines: null + lineEndings: null file: null anchors: null anchorRanges: null @@ -29,6 +30,7 @@ class Buffer @anchors = [] @anchorRanges = [] @lines = [''] + @lineEndings = [] if path throw "Path '#{path}' does not exist" unless fs.exists(path) @@ -92,9 +94,8 @@ class Buffer @file?.off() @file = new File(path) - if @file.exists() - @file.read() - @subscribeToFile() + @file.read() if @file.exists() + @subscribeToFile() @trigger "path-changed", this @@ -105,10 +106,10 @@ class Buffer null getText: -> - @cachedMemoryContents ?= @lines.join('\n') + @cachedMemoryContents ?= @getTextInRange(@getRange()) setText: (text) -> - @change(@getRange(), text) + @change(@getRange(), text, normalizeLineEndings: false) getRange: -> new Range([0, 0], [@getLastRow(), @getLastLine().length]) @@ -119,12 +120,14 @@ class Buffer return @lines[range.start.row][range.start.column...range.end.column] multipleLines = [] - multipleLines.push @lines[range.start.row][range.start.column..] # first line + multipleLines.push @lineForRow(range.start.row)[range.start.column..] # first line + multipleLines.push @lineEndingForRow(range.start.row) for row in [range.start.row + 1...range.end.row] - multipleLines.push @lines[row] # middle lines - multipleLines.push @lines[range.end.row][0...range.end.column] # last line + multipleLines.push @lineForRow(row) # middle lines + multipleLines.push @lineEndingForRow(row) + multipleLines.push @lineForRow(range.end.row)[0...range.end.column] # last line - return multipleLines.join '\n' + return multipleLines.join '' getLines: -> @lines @@ -132,6 +135,12 @@ class Buffer lineForRow: (row) -> @lines[row] + lineEndingForRow: (row) -> + @lineEndings[row] unless row is @getLastRow() + + suggestedLineEndingForRow: (row) -> + @lineEndingForRow(row) ? @lineEndingForRow(row - 1) + lineLengthForRow: (row) -> @lines[row].length @@ -196,9 +205,9 @@ class Buffer delete: (range) -> @change(range, '') - change: (oldRange, newText) -> + change: (oldRange, newText, options) -> oldRange = Range.fromObject(oldRange) - operation = new BufferChangeOperation({buffer: this, oldRange, newText}) + operation = new BufferChangeOperation({buffer: this, oldRange, newText, options}) range = @pushOperation(operation) range @@ -215,11 +224,6 @@ class Buffer prefix: @lines[range.start.row][0...range.start.column] suffix: @lines[range.end.row][range.end.column..] - replaceLines: (startRow, endRow, newLines) -> - @lines[startRow..endRow] = newLines - @cachedMemoryContents = null - @conflict = false if @conflict and !@isModified() - pushOperation: (operation, editSession) -> if @undoManager @undoManager.pushOperation(operation, editSession) @@ -242,7 +246,6 @@ class Buffer @setPath(path) @cachedDiskContents = @getText() @file.write(@getText()) - @subscribeToFile() @trigger 'saved' isModified: -> diff --git a/src/app/config.coffee b/src/app/config.coffee index 448a7fc2d..ab1eae901 100644 --- a/src/app/config.coffee +++ b/src/app/config.coffee @@ -9,9 +9,10 @@ Theme = require 'theme' configDirPath = fs.absolute("~/.atom") configJsonPath = fs.join(configDirPath, "config.json") userInitScriptPath = fs.join(configDirPath, "atom.coffee") -bundledThemesDirPath = fs.join(resourcePath, "themes") bundledPackagesDirPath = fs.join(resourcePath, "src/packages") -bundledVendorPackagesDirPath = fs.join(resourcePath, "vendor/packages") +bundledThemesDirPath = fs.join(resourcePath, "themes") +vendoredPackagesDirPath = fs.join(resourcePath, "vendor/packages") +vendoredThemesDirPath = fs.join(resourcePath, "vendor/themes") userThemesDirPath = fs.join(configDirPath, "themes") userPackagesDirPath = fs.join(configDirPath, "packages") @@ -20,8 +21,8 @@ require.paths.unshift userPackagesDirPath module.exports = class Config configDirPath: configDirPath - themeDirPaths: [userThemesDirPath, bundledThemesDirPath] - packageDirPaths: [userPackagesDirPath, bundledVendorPackagesDirPath, bundledPackagesDirPath] + themeDirPaths: [userThemesDirPath, bundledThemesDirPath, vendoredThemesDirPath] + packageDirPaths: [userPackagesDirPath, vendoredPackagesDirPath, bundledPackagesDirPath] defaultSettings: null settings: null @@ -34,8 +35,8 @@ class Config load: -> @loadUserConfig() @requireUserInitScript() - atom.loadPackages() atom.loadThemes() + atom.loadPackages() loadUserConfig: -> if fs.exists(configJsonPath) diff --git a/src/app/deferred-atom-package.coffee b/src/app/deferred-atom-package.coffee new file mode 100644 index 000000000..1f328fc02 --- /dev/null +++ b/src/app/deferred-atom-package.coffee @@ -0,0 +1,36 @@ +AtomPackage = require 'atom-package' +_ = require 'underscore' + +module.exports = +class DeferredAtomPackage extends AtomPackage + + constructor: -> + super + + @autoloadStylesheets = false + + activate: (@rootView, @state) -> + @instance = null + onLoadEvent = (e) => @onLoadEvent(e, @getInstance()) + if _.isArray(@loadEvents) + for event in @loadEvents + @rootView.command(event, onLoadEvent) + else + for event, selector of @loadEvents + @rootView.command(event, selector, onLoadEvent) + this + + deactivate: -> @instance?.deactivate?() + + serialize: -> + if @instance + @instance.serialize?() + else + @state + + getInstance: -> + unless @instance + @loadStylesheets() + InstanceClass = require @instanceClass + @instance = InstanceClass.activate(@rootView, @state) + @instance diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 8e64e2012..74fe4a2a3 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -211,6 +211,10 @@ class EditSession autoIndentSelectedRows: -> @mutateSelectedText (selection) -> selection.autoIndentSelectedRows() + normalizeTabsInBufferRange: (bufferRange) -> + return unless @softTabs + @scanInRange /\t/, bufferRange, (match, range, {replace}) => replace(@getTabText()) + cutToEndOfLine: -> maintainPasteboard = false @mutateSelectedText (selection) -> @@ -251,8 +255,9 @@ class EditSession undo: (editSession) -> editSession?.setSelectedBufferRanges(oldSelectedRanges) if fn - fn() + result = fn() @commit() if isNewTransaction + result commit: -> newSelectedRanges = @getSelectedBufferRanges() diff --git a/src/app/editor.coffee b/src/app/editor.coffee index f06487f45..d4a1a4093 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -182,6 +182,7 @@ class Editor extends View 'editor:close-other-edit-sessions': @destroyInactiveEditSessions 'editor:close-all-edit-sessions': @destroyAllEditSessions 'editor:select-grammar': @selectGrammar + 'editor:copy-path': @copyPathToPasteboard documentation = {} for name, method of editorBindings @@ -310,9 +311,10 @@ class Editor extends View setInvisibles: (@invisibles={}) -> _.defaults @invisibles, - eol: '\u00ac', - space: '\u2022', + eol: '\u00ac' + space: '\u2022' tab: '\u00bb' + cr: '\u00a4' @resetDisplay() checkoutHead: -> @getBuffer().checkoutHead() @@ -402,6 +404,11 @@ class Editor extends View @gutter.widthChanged = (newWidth) => @scrollView.css('left', newWidth + 'px') + syntax.on 'grammars-loaded', => + @reloadGrammar() + for session in @editSessions + session.reloadGrammar() unless session is @activeEditSession + @scrollView.on 'scroll', => if @scrollView.scrollLeft() == 0 @gutter.removeClass('drop-shadow') @@ -1074,8 +1081,11 @@ class Editor extends View position += token.value.length popScope() while scopeStack.length > 0 - if not @mini and invisibles?.eol - line.push("") + if invisibles and not @mini and not screenLine.isSoftWrapped() + if invisibles.cr and screenLine.lineEnding is '\r\n' + line.push("") + if invisibles.eol + line.push("") line.push('') line.join('') @@ -1154,3 +1164,7 @@ class Editor extends View @insertText(text, select: true) true + + copyPathToPasteboard: -> + path = @getPath() + pasteboard.write(path) if path? diff --git a/src/app/git.coffee b/src/app/git.coffee index a08595ffb..f862fe6b8 100644 --- a/src/app/git.coffee +++ b/src/app/git.coffee @@ -1,6 +1,7 @@ $ = require 'jquery' _ = require 'underscore' Subscriber = require 'subscriber' +GitRepository = require 'git-repository' module.exports = class Git diff --git a/src/app/grammar-view.coffee b/src/app/grammar-view.coffee index ad7311b01..bd0b73251 100644 --- a/src/app/grammar-view.coffee +++ b/src/app/grammar-view.coffee @@ -35,10 +35,6 @@ class GrammarView extends SelectList grammars.unshift(@autoDetect) @setArray(grammars) - cancelled: -> - @miniEditor.setText('') - @editor.rootView()?.focus() if @miniEditor.isFocused - confirmed: (grammar) -> @cancel() if grammar is @autoDetect @@ -48,5 +44,7 @@ class GrammarView extends SelectList @editor.reloadGrammar() attach: -> + super + @editor.rootView()?.append(this) @miniEditor.focus() diff --git a/src/app/keymaps/atom.cson b/src/app/keymaps/atom.cson index a4f64a990..97c080d26 100644 --- a/src/app/keymaps/atom.cson +++ b/src/app/keymaps/atom.cson @@ -27,6 +27,7 @@ 'meta-+': 'window:increase-font-size' 'meta--': 'window:decrease-font-size' 'ctrl-w w': 'window:focus-next-pane' + 'ctrl-tab': 'window:focus-next-pane' 'alt-meta-i': 'toggle-dev-tools' diff --git a/src/app/keymaps/editor.cson b/src/app/keymaps/editor.cson index 2f48d27bb..06f0dd571 100644 --- a/src/app/keymaps/editor.cson +++ b/src/app/keymaps/editor.cson @@ -36,4 +36,5 @@ 'meta-U': 'editor:lower-case' 'alt-meta-w': 'editor:close-other-edit-sessions' 'meta-P': 'editor:close-all-edit-sessions' - 'meta-l': 'editor:select-grammar' + 'meta-L': 'editor:select-grammar' + 'ctrl-C': 'editor:copy-path' diff --git a/src/app/language-mode.coffee b/src/app/language-mode.coffee index 2ca57a60e..bfc6cb108 100644 --- a/src/app/language-mode.coffee +++ b/src/app/language-mode.coffee @@ -1,6 +1,7 @@ Range = require 'range' _ = require 'underscore' require 'underscore-extensions' +OnigRegExp = require 'onig-reg-exp' module.exports = class LanguageMode @@ -23,15 +24,19 @@ class LanguageMode return true if @editSession.hasMultipleCursors() cursorBufferPosition = @editSession.getCursorBufferPosition() - previousCharachter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition]) - nextCharachter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])]) + previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition]) + nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])]) - hasWordAfterCursor = /\w/.test(nextCharachter) - hasWordBeforeCursor = /\w/.test(previousCharachter) + if @isOpeningBracket(text) and not @editSession.getSelection().isEmpty() + @wrapSelectionInBrackets(text) + return false + + hasWordAfterCursor = /\w/.test(nextCharacter) + hasWordBeforeCursor = /\w/.test(previousCharacter) autoCompleteOpeningBracket = @isOpeningBracket(text) and not hasWordAfterCursor and not (@isQuote(text) and hasWordBeforeCursor) skipOverExistingClosingBracket = false - if @isClosingBracket(text) and nextCharachter == text + if @isClosingBracket(text) and nextCharacter == text if bracketAnchorRange = @bracketAnchorRanges.filter((anchorRange) -> anchorRange.getBufferRange().end.isEqual(cursorBufferPosition))[0] skipOverExistingClosingBracket = true @@ -47,6 +52,35 @@ class LanguageMode @bracketAnchorRanges.push @editSession.addAnchorRange(range) false + _.adviseBefore @editSession, 'backspace', => + return if @editSession.hasMultipleCursors() + return unless @editSession.getSelection().isEmpty() + + cursorBufferPosition = @editSession.getCursorBufferPosition() + previousCharacter = @editSession.getTextInBufferRange([cursorBufferPosition.add([0, -1]), cursorBufferPosition]) + nextCharacter = @editSession.getTextInBufferRange([cursorBufferPosition, cursorBufferPosition.add([0,1])]) + if @pairedCharacters[previousCharacter] is nextCharacter + @editSession.transact => + @editSession.moveCursorLeft() + @editSession.delete() + @editSession.delete() + false + + wrapSelectionInBrackets: (bracket) -> + pair = @pairedCharacters[bracket] + @editSession.mutateSelectedText (selection) => + return if selection.isEmpty() + + range = selection.getBufferRange() + options = reverse: selection.isReversed() + selection.insertText("#{bracket}#{selection.getText()}#{pair}") + selectionStart = range.start.add([0, 1]) + if range.start.row is range.end.row + selectionEnd = range.end.add([0, 1]) + else + selectionEnd = range.end + selection.setBufferRange([selectionStart, selectionEnd], options) + reloadGrammar: -> path = @buffer.getPath() pathContents = @buffer.cachedDiskContents @@ -188,12 +222,14 @@ class LanguageMode return unless decreaseIndentRegex.test(line) currentIndentLevel = @editSession.indentationForBufferRow(bufferRow) + return if currentIndentLevel is 0 precedingRow = @buffer.previousNonBlankRow(bufferRow) + return unless precedingRow? precedingLine = @buffer.lineForRow(precedingRow) desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow) desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine) - if desiredIndentLevel < currentIndentLevel + if desiredIndentLevel >= 0 and desiredIndentLevel < currentIndentLevel @editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel) tokenizeLine: (line, stack, firstLine) -> diff --git a/src/app/load-text-mate-packages-handler.coffee b/src/app/load-text-mate-packages-handler.coffee new file mode 100644 index 000000000..c2e675bd1 --- /dev/null +++ b/src/app/load-text-mate-packages-handler.coffee @@ -0,0 +1,5 @@ +TextMatePackage = require 'text-mate-package' + +module.exports = + loadPackage: (name) -> + callTaskMethod('packageLoaded', new TextMatePackage(name).readGrammars()) diff --git a/src/app/load-text-mate-packages-task.coffee b/src/app/load-text-mate-packages-task.coffee new file mode 100644 index 000000000..2eb904676 --- /dev/null +++ b/src/app/load-text-mate-packages-task.coffee @@ -0,0 +1,26 @@ +Task = require 'Task' + +module.exports = +class LoadTextMatePackagesTask extends Task + + constructor: (@packages) -> + super('load-text-mate-packages-handler') + + started: -> + @loadNextPackage() + + loadNextPackage: -> + unless @packages.length + @terminate() + syntax.trigger 'grammars-loaded' + return + + @package = @packages.shift() + @loadPackage(@package.name) + + loadPackage: (name) -> + @callWorkerMethod('loadPackage', name) + + packageLoaded: (grammars) -> + @package.loadGrammars(grammars) + @loadNextPackage() diff --git a/src/app/package.coffee b/src/app/package.coffee index 8bcbecfa1..01bdde1fa 100644 --- a/src/app/package.coffee +++ b/src/app/package.coffee @@ -2,25 +2,34 @@ fs = require 'fs' module.exports = class Package + @resolve: (name) -> + path = require.resolve(name, verifyExistence: false) + return path if path + throw new Error("No package found named '#{name}'") + @build: (name) -> - AtomPackage = require 'atom-package' TextMatePackage = require 'text-mate-package' + AtomPackage = require 'atom-package' if TextMatePackage.testName(name) new TextMatePackage(name) else - new AtomPackage(name) + if fs.isDirectory(@resolve(name)) + new AtomPackage(name) + else + try + PackageClass = require name + new PackageClass(name) if typeof PackageClass is 'function' + catch e + console.warn "Failed to load package named '#{name}'", e.stack name: null path: null - requireModule: null + isDirectory: false module: null constructor: (@name) -> - @path = require.resolve(@name, verifyExistence: false) - throw new Error("No package found named '#{@name}'") unless @path + @path = Package.resolve(@name) + @isDirectory = fs.isDirectory(@path) + @path = fs.directory(@path) unless @isDirectory - if fs.isDirectory(@path) - @requireModule = false - else - @requireModule = true - @path = fs.directory(@path) + activate: (rootView) -> diff --git a/src/app/root-view.coffee b/src/app/root-view.coffee index 3a187d6a7..4063ee863 100644 --- a/src/app/root-view.coffee +++ b/src/app/root-view.coffee @@ -18,7 +18,7 @@ class RootView extends View disabledPackages: [] @content: -> - @div id: 'root-view', tabindex: -1, => + @div id: 'root-view', tabindex: 0, => @div id: 'horizontal', outlet: 'horizontal', => @div id: 'vertical', outlet: 'vertical', => @div id: 'panes', outlet: 'panes' diff --git a/src/app/screen-line.coffee b/src/app/screen-line.coffee index 31d93e879..a590d8e86 100644 --- a/src/app/screen-line.coffee +++ b/src/app/screen-line.coffee @@ -2,7 +2,7 @@ _ = require 'underscore' module.exports = class ScreenLine - constructor: ({tokens, @ruleStack, @bufferRows, @startBufferColumn, @fold, tabLength}) -> + constructor: ({tokens, @lineEnding, @ruleStack, @bufferRows, @startBufferColumn, @fold, tabLength}) -> @tokens = @breakOutAtomicTokens(tokens, tabLength) @bufferRows ?= 1 @startBufferColumn ?= 0 @@ -74,11 +74,13 @@ class ScreenLine bufferRows: 0 startBufferColumn: @startBufferColumn ruleStack: @ruleStack + lineEnding: @lineEnding ) rightFragment = new ScreenLine( tokens: rightTokens startBufferColumn: @startBufferColumn + column ruleStack: @ruleStack + lineEnding: @lineEnding ) [leftFragment, rightFragment] diff --git a/src/app/select-list.coffee b/src/app/select-list.coffee index 0f8bb6c10..0b4cd9a87 100644 --- a/src/app/select-list.coffee +++ b/src/app/select-list.coffee @@ -26,6 +26,12 @@ class SelectList extends View @miniEditor.on 'focusout', => @cancel() unless @cancelling @on 'core:move-up', => @selectPreviousItem() @on 'core:move-down', => @selectNextItem() + @on 'core:move-to-top', => + @selectItem(@list.find('li:first')) + @list.scrollToTop() + @on 'core:move-to-bottom', => + @selectItem(@list.find('li:last')) + @list.scrollToBottom() @on 'core:confirm', => @confirmSelection() @on 'core:cancel', => @cancel() @@ -62,6 +68,8 @@ class SelectList extends View @loading.text(message).show() populateList: -> + return unless @array? + filterQuery = @miniEditor.getText() if filterQuery.length filteredArray = fuzzyFilter(@array, filterQuery, key: @filterKey) @@ -121,10 +129,24 @@ class SelectList extends View else @cancel() + attach: -> + @storeFocusedElement() + + storeFocusedElement: -> + @previouslyFocusedElement = $(':focus') + + restoreFocus: -> + @previouslyFocusedElement?.focus() + + cancelled: -> + @miniEditor.setText('') + cancel: -> @list.empty() @cancelling = true + miniEditorFocused = @miniEditor.isFocused @cancelled() @detach() + @restoreFocus() if miniEditorFocused @cancelling = false clearTimeout(@scheduleTimeout) diff --git a/src/app/selection.coffee b/src/app/selection.coffee index f30eea09a..8123d1157 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -185,6 +185,8 @@ class Selection else @editSession.autoDecreaseIndentForRow(newBufferRange.start.row) + newBufferRange + indent: ({ autoIndent }={})-> { row, column } = @cursor.getBufferPosition() diff --git a/src/app/syntax.coffee b/src/app/syntax.coffee index 1ff5e8663..1488ddf67 100644 --- a/src/app/syntax.coffee +++ b/src/app/syntax.coffee @@ -3,6 +3,7 @@ jQuery = require 'jquery' Specificity = require 'specificity' {$$} = require 'space-pen' fs = require 'fs' +EventEmitter = require 'event-emitter' module.exports = class Syntax @@ -104,3 +105,5 @@ class Syntax deepestChild[0] else element[0] + +_.extend(Syntax.prototype, EventEmitter) diff --git a/src/app/text-mate-grammar.coffee b/src/app/text-mate-grammar.coffee index 1bd96d996..1c1478070 100644 --- a/src/app/text-mate-grammar.coffee +++ b/src/app/text-mate-grammar.coffee @@ -2,16 +2,18 @@ _ = require 'underscore' fs = require 'fs' plist = require 'plist' Token = require 'token' +OnigRegExp = require 'onig-reg-exp' +OnigScanner = require 'onig-scanner' module.exports = class TextMateGrammar - @loadFromPath: (path) -> - grammar = null + @readFromPath: (path) -> + grammarContent = null plist.parseString fs.read(path), (e, data) -> throw new Error(e) if e - grammar = new TextMateGrammar(data[0]) - throw new Error("Failed to load grammar at path `#{path}`") unless grammar - grammar + grammarContent = data[0] + throw new Error("Failed to load grammar at path `#{path}`") unless grammarContent + grammarContent name: null fileTypes: null diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index a7cc7bcbc..97eea6189 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -22,27 +22,41 @@ class TextMatePackage extends Package super @preferencesPath = fs.join(@path, "Preferences") @syntaxesPath = fs.join(@path, "Syntaxes") + @grammars = [] load: -> try - for grammar in @getGrammars() - syntax.addGrammar(grammar) - - for { selector, properties } in @getScopedProperties() - syntax.addProperties(selector, properties) + @loadGrammars() catch e console.warn "Failed to load package named '#{@name}'", e.stack + this + + getGrammars: -> @grammars + + readGrammars: -> + grammars = [] + for grammarPath in fs.list(@syntaxesPath) + try + grammars.push(TextMateGrammar.readFromPath(grammarPath)) + catch e + console.warn "Failed to load grammar at path '#{grammarPath}'", e.stack + grammars + + addGrammar: (rawGrammar) -> + grammar = new TextMateGrammar(rawGrammar) + @grammars.push(grammar) + syntax.addGrammar(grammar) + + loadGrammars: (rawGrammars) -> + rawGrammars = @readGrammars() unless rawGrammars? - getGrammars: -> - return @grammars if @grammars @grammars = [] - if fs.exists(@syntaxesPath) - for grammarPath in fs.list(@syntaxesPath) - try - @grammars.push TextMateGrammar.loadFromPath(grammarPath) - catch e - console.warn "Failed to load grammar at path '#{grammarPath}'", e.stack - @grammars + @addGrammar(rawGrammar) for rawGrammar in rawGrammars + @loadScopedProperties() + + loadScopedProperties: -> + for { selector, properties } in @getScopedProperties() + syntax.addProperties(selector, properties) getScopedProperties: -> scopedProperties = [] diff --git a/src/app/text-mate-theme.coffee b/src/app/text-mate-theme.coffee index 9c56ec222..ee78cdea7 100644 --- a/src/app/text-mate-theme.coffee +++ b/src/app/text-mate-theme.coffee @@ -35,10 +35,10 @@ class TextMateTheme extends Theme getRulesets: -> @rulesets buildGlobalSettingsRulesets: ({settings}) -> - { background, foreground, caret, selection } = settings + { background, foreground, caret, selection, lineHighlight } = settings @rulesets.push - selector: '.editor' + selector: '.editor, .editor .gutter' properties: 'background-color': @translateColor(background) 'color': @translateColor(foreground) @@ -53,6 +53,11 @@ class TextMateTheme extends Theme properties: 'background-color': @translateColor(selection) + @rulesets.push + selector: '.editor.focused .line-number.cursor-line-no-selection, .editor.focused .line.cursor-line' + properties: + 'background-color': @translateColor(lineHighlight) + buildScopeSelectorRulesets: (scopeSelectorSettings) -> for { name, scope, settings } in scopeSelectorSettings continue unless scope diff --git a/src/app/theme.coffee b/src/app/theme.coffee index 3c438b9b2..c3f574977 100644 --- a/src/app/theme.coffee +++ b/src/app/theme.coffee @@ -1,5 +1,4 @@ -fs = require("fs") -_ = require 'underscore' +fs = require 'fs' module.exports = class Theme @@ -12,8 +11,7 @@ class Theme if fs.exists(name) path = name else - path = fs.resolve(config.themeDirPaths..., name) - path ?= fs.resolve(config.themeDirPaths..., name + ".tmTheme") + path = fs.resolve(config.themeDirPaths..., name, ['', '.tmTheme']) throw new Error("No theme exists named '#{name}'") unless path @@ -31,7 +29,7 @@ class Theme load: -> for stylesheetPath, stylesheetContent of @stylesheets - applyStylesheet(stylesheetPath, stylesheetContent) + applyStylesheet(stylesheetPath, stylesheetContent, 'userTheme') deactivate: -> for stylesheetPath, stylesheetContent of @stylesheets diff --git a/src/app/tokenized-buffer.coffee b/src/app/tokenized-buffer.coffee index 6646fd54f..9e0930bf0 100644 --- a/src/app/tokenized-buffer.coffee +++ b/src/app/tokenized-buffer.coffee @@ -137,8 +137,9 @@ class TokenizedBuffer buildTokenizedScreenLineForRow: (row, ruleStack) -> line = @buffer.lineForRow(row) + lineEnding = @buffer.lineEndingForRow(row) { tokens, ruleStack } = @languageMode.tokenizeLine(line, ruleStack, row is 0) - new ScreenLine({tokens, ruleStack, @tabLength}) + new ScreenLine({tokens, ruleStack, @tabLength, lineEnding}) lineForScreenRow: (row) -> @linesForScreenRows(row, row)[0] diff --git a/src/app/window.coffee b/src/app/window.coffee index 9e53ed5b6..d990b28a4 100644 --- a/src/app/window.coffee +++ b/src/app/window.coffee @@ -3,9 +3,7 @@ Native = require 'native' fs = require 'fs' -_ = require 'underscore' $ = require 'jquery' -{CoffeeScript} = require 'coffee-script' Config = require 'config' Syntax = require 'syntax' RootView = require 'root-view' @@ -70,18 +68,23 @@ windowAdditions = $("head style[id='#{id}']") requireStylesheet: (path) -> - unless fullPath = require.resolve(path) + if fullPath = require.resolve(path) + window.applyStylesheet(fullPath, fs.read(fullPath)) + unless fullPath throw new Error("Could not find a file at path '#{path}'") - window.applyStylesheet(fullPath, fs.read(fullPath)) removeStylesheet: (path) -> unless fullPath = require.resolve(path) throw new Error("Could not find a file at path '#{path}'") window.stylesheetElementForId(fullPath).remove() - applyStylesheet: (id, text) -> + applyStylesheet: (id, text, ttype = 'bundled') -> unless window.stylesheetElementForId(id).length - $('head').append "" + if $("head style.#{ttype}").length + $("head style.#{ttype}:last").after "" + else + $("head").append "" + reload: -> if rootView?.getModifiedBuffers().length > 0 diff --git a/src/packages/autocomplete/index.coffee b/src/packages/autocomplete/index.coffee index 5a86b1576..902c08e24 100644 --- a/src/packages/autocomplete/index.coffee +++ b/src/packages/autocomplete/index.coffee @@ -1 +1,6 @@ -module.exports = require 'autocomplete/src/autocomplete' +AtomPackage = require 'atom-package' +AutocompleteView = require './src/autocomplete-view' + +module.exports = +class Autocomplete extends AtomPackage + activate: (rootView) -> AutocompleteView.activate(rootView) diff --git a/src/packages/autocomplete/spec/autocomplete-spec.coffee b/src/packages/autocomplete/spec/autocomplete-spec.coffee index 9283e5b14..d9b2da85a 100644 --- a/src/packages/autocomplete/spec/autocomplete-spec.coffee +++ b/src/packages/autocomplete/spec/autocomplete-spec.coffee @@ -1,5 +1,5 @@ $ = require 'jquery' -Autocomplete = require 'autocomplete' +Autocomplete = require 'autocomplete/src/autocomplete-view' Buffer = require 'buffer' Editor = require 'editor' RootView = require 'root-view' @@ -11,6 +11,7 @@ describe "Autocomplete", -> beforeEach -> editor = new Editor(editSession: fixturesProject.buildEditSessionForPath('sample.js')) + atom.loadPackage('autocomplete') autocomplete = new Autocomplete(editor) miniEditor = autocomplete.miniEditor diff --git a/src/packages/autocomplete/src/autocomplete.coffee b/src/packages/autocomplete/src/autocomplete-view.coffee similarity index 97% rename from src/packages/autocomplete/src/autocomplete.coffee rename to src/packages/autocomplete/src/autocomplete-view.coffee index 47a0f5764..1e071ccf3 100644 --- a/src/packages/autocomplete/src/autocomplete.coffee +++ b/src/packages/autocomplete/src/autocomplete-view.coffee @@ -3,10 +3,10 @@ Range = require 'range' SelectList = require 'select-list' module.exports = -class Autocomplete extends SelectList +class AutocompleteView extends SelectList @activate: (rootView) -> rootView.eachEditor (editor) -> - new Autocomplete(editor) if editor.attached and not editor.mini + new AutocompleteView(editor) if editor.attached and not editor.mini @viewClass: -> "autocomplete #{super}" @@ -74,10 +74,10 @@ class Autocomplete extends SelectList @editor.setCursorBufferPosition([position.row, position.column + match.suffix.length]) cancelled: -> + super + @editor.abort() @editor.setSelectedBufferRange(@originalSelectionBufferRange) - - @miniEditor.setText('') @editor.rootView()?.focus() if @miniEditor.isFocused attach: -> diff --git a/src/packages/autocomplete/stylesheets/autocomplete.css b/src/packages/autocomplete/stylesheets/autocomplete.css index 7f6c17bdb..9142f6a5e 100644 --- a/src/packages/autocomplete/stylesheets/autocomplete.css +++ b/src/packages/autocomplete/stylesheets/autocomplete.css @@ -1,11 +1,6 @@ .select-list.autocomplete { - min-width: 150px; - border: 2px solid #222; - webkit-box-shadow: 0 0 3px 3px rgba(0, 0, 0, .5); box-sizing: content-box; margin-left: 0px; - width: auto; - -webkit-box-shadow: none; } .autocomplete ol { @@ -13,7 +8,3 @@ overflow-y: scroll; max-height: 200px; } - -.autocomplete ol li { - padding: 0.1em 0.2em; -} diff --git a/src/packages/autoflow/index.coffee b/src/packages/autoflow/index.coffee index 950ab2727..73b52d8ed 100644 --- a/src/packages/autoflow/index.coffee +++ b/src/packages/autoflow/index.coffee @@ -1 +1,36 @@ -module.exports = require './lib/autoflow' +AtomPackage = require 'atom-package' + +module.exports = +class Autoflow extends AtomPackage + activate: (rootView) -> + rootView.command 'autoflow:reflow-paragraph', '.editor', (e) => + @reflowParagraph(e.currentTargetView()) + + reflowParagraph: (editor) -> + if range = editor.getCurrentParagraphBufferRange() + editor.getBuffer().change(range, @reflow(editor.getTextInRange(range))) + + reflow: (text) -> + wrapColumn = config.get('editor.preferredLineLength') ? 80 + lines = [] + + currentLine = [] + currentLineLength = 0 + for segment in @segmentText(text.replace(/\n/g, ' ')) + if /\w/.test(segment) and + (currentLineLength + segment.length > wrapColumn) and + (currentLineLength > 0 or segment.length < wrapColumn) + lines.push(currentLine.join('')) + currentLine = [] + currentLineLength = 0 + currentLine.push(segment) + currentLineLength += segment.length + lines.push(currentLine.join('')) + + lines.join('\n').replace(/\s+\n/g, '\n') + + segmentText: (text) -> + segments = [] + re = /[\s]+|[^\s]+/g + segments.push(match[0]) while match = re.exec(text) + segments diff --git a/src/packages/autoflow/lib/autoflow.coffee b/src/packages/autoflow/lib/autoflow.coffee deleted file mode 100644 index a1dc9f73b..000000000 --- a/src/packages/autoflow/lib/autoflow.coffee +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = - activate: (rootView) -> - rootView.command 'autoflow:reflow-paragraph', '.editor', (e) => - @reflowParagraph(e.currentTargetView()) - - reflowParagraph: (editor) -> - if range = editor.getCurrentParagraphBufferRange() - editor.getBuffer().change(range, @reflow(editor.getTextInRange(range))) - - reflow: (text) -> - wrapColumn = config.get('editor.preferredLineLength') ? 80 - lines = [] - - currentLine = [] - currentLineLength = 0 - for segment in @segmentText(text.replace(/\n/g, ' ')) - if /\w/.test(segment) and - (currentLineLength + segment.length > wrapColumn) and - (currentLineLength > 0 or segment.length < wrapColumn) - lines.push(currentLine.join('')) - currentLine = [] - currentLineLength = 0 - currentLine.push(segment) - currentLineLength += segment.length - lines.push(currentLine.join('')) - - lines.join('\n').replace(/\s+\n/g, '\n') - - segmentText: (text) -> - segments = [] - re = /[\s]+|[^\s]+/g - segments.push(match[0]) while match = re.exec(text) - segments diff --git a/src/packages/command-logger/index.coffee b/src/packages/command-logger/index.coffee index 4bff38c81..39dd9ad68 100644 --- a/src/packages/command-logger/index.coffee +++ b/src/packages/command-logger/index.coffee @@ -1 +1,10 @@ -module.exports = require 'command-logger/src/command-logger' +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class CommandLogger extends DeferredAtomPackage + + loadEvents: ['command-logger:toggle'] + + instanceClass: 'command-logger/src/command-logger-view' + + onLoadEvent: (event, instance) -> instance.toggle() diff --git a/src/packages/command-logger/spec/command-logger-spec.coffee b/src/packages/command-logger/spec/command-logger-spec.coffee index 1eaee9318..c01f24320 100644 --- a/src/packages/command-logger/spec/command-logger-spec.coffee +++ b/src/packages/command-logger/spec/command-logger-spec.coffee @@ -1,12 +1,12 @@ RootView = require 'root-view' -CommandLogger = require 'command-logger' +CommandLogger = require 'command-logger/src/command-logger-view' describe "CommandLogger", -> [rootView, commandLogger, editor] = [] beforeEach -> rootView = new RootView(require.resolve('fixtures/sample.js')) - atom.loadPackage 'command-logger' + atom.loadPackage('command-logger').getInstance() editor = rootView.getActiveEditor() commandLogger = CommandLogger.instance @@ -26,9 +26,13 @@ describe "CommandLogger", -> editor.trigger 'core:backspace' lastRun = commandLogger.eventLog['core:backspace'].lastRun expect(lastRun).toBeGreaterThan 0 - advanceClock(100) - editor.trigger 'core:backspace' - expect(commandLogger.eventLog['core:backspace'].lastRun).toBeGreaterThan lastRun + start = new Date().getTime() + waitsFor -> + new Date().getTime() > start + + runs -> + editor.trigger 'core:backspace' + expect(commandLogger.eventLog['core:backspace'].lastRun).toBeGreaterThan lastRun describe "when the data is cleared", -> it "removes all triggered events from the log", -> diff --git a/src/packages/command-logger/src/command-logger.coffee b/src/packages/command-logger/src/command-logger-view.coffee similarity index 97% rename from src/packages/command-logger/src/command-logger.coffee rename to src/packages/command-logger/src/command-logger-view.coffee index ebe1e7164..01496a2d0 100644 --- a/src/packages/command-logger/src/command-logger.coffee +++ b/src/packages/command-logger/src/command-logger-view.coffee @@ -4,9 +4,9 @@ $ = require 'jquery' _ = require 'underscore' module.exports = -class CommandLogger extends ScrollView +class CommandLoggerView extends ScrollView @activate: (rootView, state) -> - @instance = new CommandLogger(rootView, state?.eventLog) + @instance = new CommandLoggerView(rootView, state?.eventLog) @content: (rootView) -> @div class: 'command-logger', tabindex: -1, => @@ -34,7 +34,6 @@ class CommandLogger extends ScrollView initialize: (@rootView, @eventLog={}) -> super - @rootView.command 'command-logger:toggle', => @toggle() @rootView.command 'command-logger:clear-data', => @eventLog = {} @command 'core:cancel', => @detach() diff --git a/src/packages/command-logger/stylesheets/command-logger.css b/src/packages/command-logger/stylesheets/command-logger.css index 5e9f34ffa..87a21e502 100644 --- a/src/packages/command-logger/stylesheets/command-logger.css +++ b/src/packages/command-logger/stylesheets/command-logger.css @@ -4,34 +4,8 @@ height: 100%; top: 0px; left: 0px; - background: #1e1e1e; - color: #eee; overflow: auto; z-index: 99; - padding-top: 10px; - padding-bottom: 10px; -} - -.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 { - margin: auto; - background-color: #efefef; - border: 1px solid #999; -} - -body.command-logger-node-text { - background-color: transparent; } .command-logger-node-text div { @@ -42,8 +16,5 @@ body.command-logger-node-text { } .command-logger-node-text span { - font-size: 10px; - color: #fff; - text-shadow: #000 1px 1px 4px; -webkit-user-select: none; } diff --git a/src/packages/command-palette/index.coffee b/src/packages/command-palette/index.coffee index d097e0ea0..15d41efb5 100644 --- a/src/packages/command-palette/index.coffee +++ b/src/packages/command-palette/index.coffee @@ -1 +1,10 @@ -module.exports = require 'command-palette/src/command-palette' +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class CommandPalette extends DeferredAtomPackage + + loadEvents: ['command-palette:toggle'] + + instanceClass: 'command-palette/src/command-palette-view' + + onLoadEvent: (event, instance) -> instance.attach() diff --git a/src/packages/command-palette/spec/command-palette-spec.coffee b/src/packages/command-palette/spec/command-palette-spec.coffee index f95f2d7d3..2f62d1b7b 100644 --- a/src/packages/command-palette/spec/command-palette-spec.coffee +++ b/src/packages/command-palette/spec/command-palette-spec.coffee @@ -1,5 +1,5 @@ RootView = require 'root-view' -CommandPalette = require 'command-palette' +CommandPalette = require 'command-palette/src/command-palette-view' $ = require 'jquery' _ = require 'underscore' @@ -8,7 +8,7 @@ describe "CommandPalette", -> beforeEach -> rootView = new RootView(require.resolve('fixtures/sample.js')) - atom.loadPackage("command-palette") + atom.loadPackage("command-palette").getInstance() palette = CommandPalette.instance rootView.attachToDom().focus() rootView.trigger 'command-palette:toggle' diff --git a/src/packages/command-palette/src/command-palette.coffee b/src/packages/command-palette/src/command-palette-view.coffee similarity index 81% rename from src/packages/command-palette/src/command-palette.coffee rename to src/packages/command-palette/src/command-palette-view.coffee index 6ba7d7cae..d723afa54 100644 --- a/src/packages/command-palette/src/command-palette.coffee +++ b/src/packages/command-palette/src/command-palette-view.coffee @@ -4,10 +4,9 @@ $ = require 'jquery' _ = require 'underscore' module.exports = -class CommandPalette extends SelectList +class CommandPaletteView extends SelectList @activate: (rootView) -> - @instance = new CommandPalette(rootView) - rootView.command 'command-palette:toggle', => @instance.attach() + @instance = new CommandPaletteView(rootView) @viewClass: -> "#{super} command-palette" @@ -24,7 +23,8 @@ class CommandPalette extends SelectList super attach: -> - @previouslyFocusedElement = $(':focus') + super + @keyBindings = _.losslessInvert(keymap.bindingsForElement(@previouslyFocusedElement)) events = [] @@ -35,7 +35,6 @@ class CommandPalette extends SelectList @setArray(events) @appendTo(@rootView) - @miniEditor.setText('') @miniEditor.focus() itemForElement: ({eventName, eventDescription}) -> @@ -52,6 +51,3 @@ class CommandPalette extends SelectList confirmed: ({eventName}) -> @cancel() @previouslyFocusedElement.trigger(eventName) - - cancelled: -> - @previouslyFocusedElement.focus() if @miniEditor.isFocused diff --git a/src/packages/command-panel/index.coffee b/src/packages/command-panel/index.coffee index f3622c933..4f1a26c8a 100644 --- a/src/packages/command-panel/index.coffee +++ b/src/packages/command-panel/index.coffee @@ -1 +1,33 @@ -module.exports = require 'command-panel/src/command-panel' +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class CommandPanel extends DeferredAtomPackage + + loadEvents: [ + 'command-panel:toggle' + 'command-panel:toggle-preview' + 'command-panel:find-in-file' + 'command-panel:find-in-project' + 'command-panel:repeat-relative-address' + 'command-panel:repeat-relative-address-in-reverse' + 'command-panel:set-selection-as-regex-address' + ] + + instanceClass: 'command-panel/src/command-panel-view' + + onLoadEvent: (event, instance) -> + switch event.type + when 'command-panel:toggle' + instance.toggle() + when 'command-panel:toggle-preview' + instance.togglePreview() + when 'command-panel:find-in-file' + instance.attach("/") + when 'command-panel:find-in-project' + instance.attach("Xx/") + when 'command-panel:repeat-relative-address' + instance.repeatRelativeAddress() + when 'command-panel:repeat-relative-address-in-reverse' + instance.repeatRelativeAddressInReverse() + when 'command-panel:set-selection-as-regex-address' + instance.setSelectionAsLastRelativeAddress() diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee index 500b401e9..635613912 100644 --- a/src/packages/command-panel/spec/command-panel-spec.coffee +++ b/src/packages/command-panel/spec/command-panel-spec.coffee @@ -1,9 +1,9 @@ RootView = require 'root-view' -CommandPanel = require 'command-panel' +CommandPanelView = require 'command-panel/src/command-panel-view' _ = require 'underscore' describe "CommandPanel", -> - [rootView, editor, buffer, commandPanel, project] = [] + [rootView, editor, buffer, commandPanel, project, CommandPanel] = [] beforeEach -> rootView = new RootView @@ -12,8 +12,8 @@ describe "CommandPanel", -> project = rootView.project editor = rootView.getActiveEditor() buffer = editor.activeEditSession.buffer - atom.loadPackage('command-panel') - commandPanel = CommandPanel.instance + CommandPanel = atom.loadPackage('command-panel') + commandPanel = CommandPanel.getInstance() commandPanel.history = [] commandPanel.historyIndex = 0 @@ -36,7 +36,7 @@ describe "CommandPanel", -> rootView.deactivate() rootView2.attachToDom() - commandPanel = rootView2.activatePackage('command-panel', CommandPanel) + commandPanel = rootView2.activatePackage('command-panel', CommandPanel).getInstance() expect(rootView2.find('.command-panel')).toExist() expect(commandPanel.miniEditor.getText()).toBe 'abc' expect(commandPanel.miniEditor.isFocused).toBeTruthy() @@ -49,7 +49,7 @@ describe "CommandPanel", -> rootView3 = RootView.deserialize(rootView2.serialize()) rootView2.deactivate() rootView3.attachToDom() - commandPanel = rootView3.activatePackage('command-panel', CommandPanel) + commandPanel = rootView3.activatePackage('command-panel', CommandPanel).getInstance() expect(commandPanel.miniEditor.isFocused).toBeFalsy() rootView3.deactivate() @@ -71,7 +71,7 @@ describe "CommandPanel", -> rootView.deactivate() rootView2.attachToDom() - commandPanel = rootView2.activatePackage('command-panel', CommandPanel) + commandPanel = rootView2.activatePackage('command-panel', CommandPanel).getInstance() expect(commandPanel.history.length).toBe(2) expect(commandPanel.history[0]).toBe('/test2') expect(commandPanel.history[1]).toBe('/test3') @@ -180,17 +180,19 @@ describe "CommandPanel", -> expect(commandPanel.hasParent()).toBeTruthy() describe "when the mini editor is focused", -> - it "retains focus on the mini editor and does not show the preview list", -> + it "retains focus on the mini editor and does not show the preview list or preview count", -> expect(commandPanel.miniEditor.isFocused).toBeTruthy() rootView.trigger 'command-panel:toggle-preview' expect(commandPanel.previewList).toBeHidden() + expect(commandPanel.previewCount).toBeHidden() expect(commandPanel.miniEditor.isFocused).toBeTruthy() describe "when the mini editor is not focused", -> - it "focuses the mini editor and does not show the preview list", -> + it "focuses the mini editor and does not show the preview list or preview count", -> rootView.focus() rootView.trigger 'command-panel:toggle-preview' expect(commandPanel.previewList).toBeHidden() + expect(commandPanel.previewCount).toBeHidden() expect(commandPanel.miniEditor.isFocused).toBeTruthy() describe "when the command panel is not visible", -> @@ -297,7 +299,7 @@ describe "CommandPanel", -> expect(commandPanel.previewList).toBeVisible() expect(commandPanel.previewList).toMatchSelector ':focus' previewItem = commandPanel.previewList.find("li:contains(sample.js):first") - expect(previewItem.text()).toBe "sample.js" + expect(previewItem.text()).toBe "sample.js(1)" expect(previewItem.next().find('.preview').text()).toBe "var quicksort = function () {" expect(previewItem.next().find('.preview > .match').text()).toBe "quicksort" @@ -341,7 +343,7 @@ describe "CommandPanel", -> expect(commandPanel.errorMessages).not.toBeVisible() - describe "when the command contains an escaped charachter", -> + describe "when the command contains an escaped character", -> it "executes the command with the escaped character (instead of as a backslash followed by the character)", -> rootView.trigger 'command-panel:toggle' @@ -377,6 +379,10 @@ describe "CommandPanel", -> rootView.trigger 'command-panel:toggle' waitsForPromise -> commandPanel.execute('X x/sort/') + it "displays the number of files and operations", -> + rootView.attachToDom() + expect(commandPanel.previewCount.text()).toBe '17 matches in 4 files' + describe "when move-down and move-up are triggered on the preview list", -> it "selects the next/previous operation (if there is one), and scrolls the list if needed", -> rootView.attachToDom() @@ -405,28 +411,15 @@ describe "CommandPanel", -> previewList.trigger 'core:move-down' expect(previewList.scrollTop()).toBe 0 - it "wraps around when the list is at the beginning or end", -> - rootView.attachToDom() - expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' - expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0] - - previewList.trigger 'core:move-up' - expect(previewList.find('li.operation:last')).toHaveClass 'selected' - expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations()) - - previewList.trigger 'core:move-down' - expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' - expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0] - it "doesn't bubble up the event and the command panel text doesn't change", -> rootView.attachToDom() commandPanel.miniEditor.setText "command" previewList.focus() previewList.trigger 'core:move-up' - expect(previewList.find('li.operation:last')).toHaveClass 'selected' + expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' expect(commandPanel.miniEditor.getText()).toBe 'command' previewList.trigger 'core:move-down' - expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' + expect(previewList.find('li.operation:eq(1)')).toHaveClass 'selected' expect(commandPanel.miniEditor.getText()).toBe 'command' describe "when move-to-top and move-to-bottom are triggered on the preview list", -> diff --git a/src/packages/command-panel/src/command-panel.coffee b/src/packages/command-panel/src/command-panel-view.coffee similarity index 79% rename from src/packages/command-panel/src/command-panel.coffee rename to src/packages/command-panel/src/command-panel-view.coffee index 05db2a1ba..7ccb74a48 100644 --- a/src/packages/command-panel/src/command-panel.coffee +++ b/src/packages/command-panel/src/command-panel-view.coffee @@ -9,30 +9,22 @@ Editor = require 'editor' _ = require 'underscore' module.exports = -class CommandPanel extends View +class CommandPanelView extends View @activate: (rootView, state) -> if state? - @instance = CommandPanel.deserialize(state, rootView) + @instance = @deserialize(state, rootView) else - @instance = new CommandPanel(rootView) - - @deactivate: -> - @instance.destroy() - - @serialize: -> - text: @instance.miniEditor.getText() - visible: @instance.hasParent() - miniEditorFocused: @instance.miniEditor.isFocused - history: @instance.history[-@instance.maxSerializedHistorySize..] + @instance = new CommandPanelView(rootView) @deserialize: (state, rootView) -> - commandPanel = new CommandPanel(rootView, state.history) + commandPanel = new CommandPanelView(rootView, state.history) commandPanel.attach(state.text, focus: false) if state.visible commandPanel.miniEditor.focus() if state.miniEditorFocused commandPanel @content: (rootView) -> @div class: 'command-panel tool-panel', => + @div outlet: 'previewCount', class: 'preview-count' @subview 'previewList', new PreviewList(rootView) @ul class: 'error-messages', outlet: 'errorMessages' @div class: 'prompt-and-editor', => @@ -53,22 +45,22 @@ class CommandPanel extends View @command 'tool-panel:unfocus', => @rootView.focus() @command 'core:close', => @detach(); false @command 'core:confirm', => @execute() - - @rootView.command 'command-panel:toggle', => @toggle() - @rootView.command 'command-panel:toggle-preview', => @togglePreview() - @rootView.command 'command-panel:find-in-file', => @attach("/") - @rootView.command 'command-panel:find-in-project', => @attach("Xx/") - @rootView.command 'command-panel:repeat-relative-address', => @repeatRelativeAddress() - @rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse() - @rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress() - @command 'core:move-up', => @navigateBackwardInHistory() @command 'core:move-down', => @navigateForwardInHistory() @previewList.hide() + @previewCount.hide() @errorMessages.hide() @prompt.iconSize(@miniEditor.fontSize) + serialize: -> + text: @miniEditor.getText() + visible: @hasParent() + miniEditorFocused: @miniEditor.isFocused + history: @history[-@maxSerializedHistorySize..] + + deactivate: -> @destroy() + destroy: -> @previewList.destroy() @@ -83,12 +75,14 @@ class CommandPanel extends View togglePreview: -> if @previewList.is(':focus') @previewList.hide() + @previewCount.hide() @detach() @rootView.focus() else @attach() unless @hasParent() if @previewList.hasOperations() @previewList.show().focus() + @previewCount.show() else @miniEditor.focus() @@ -104,6 +98,7 @@ class CommandPanel extends View detach: -> @rootView.focus() @previewList.hide() + @previewCount.hide() super escapedCommand: -> @@ -125,6 +120,7 @@ class CommandPanel extends View else if operationsToPreview?.length @previewList.populate(operationsToPreview) @previewList.focus() + @previewCount.text("#{_.pluralize(operationsToPreview.length, 'match', 'matches')} in #{_.pluralize(@previewList.getPathCount(), 'file')}").show() else @detach() catch error diff --git a/src/packages/command-panel/src/preview-list.coffee b/src/packages/command-panel/src/preview-list.coffee index 44280eac5..34cbd240c 100644 --- a/src/packages/command-panel/src/preview-list.coffee +++ b/src/packages/command-panel/src/preview-list.coffee @@ -34,7 +34,9 @@ class PreviewList extends ScrollView operation.index = index for operation, index in operations operationsByPath = _.groupBy(operations, (operation) -> operation.getPath()) for path, ops of operationsByPath - @li path, class: 'path' + @li class: 'path', => + @span path + @span "(#{ops.length})", class: 'path-match-number' for operation in ops {prefix, suffix, match, range} = operation.preview() @li 'data-index': operation.index, class: 'operation', => @@ -56,16 +58,10 @@ class PreviewList extends ScrollView lineNumbers.width(maxWidth) selectNextOperation: -> - if @selectedOperationIndex is @operations.length - 1 - @setSelectedOperationIndex(0) - else - @setSelectedOperationIndex(@selectedOperationIndex + 1) + @setSelectedOperationIndex(@selectedOperationIndex + 1) selectPreviousOperation: -> - if @selectedOperationIndex is 0 - @setSelectedOperationIndex(@operations.length - 1) - else - @setSelectedOperationIndex(@selectedOperationIndex - 1) + @setSelectedOperationIndex(@selectedOperationIndex - 1) setSelectedOperationIndex: (index, scrollToOperation=true) -> index = Math.max(0, index) @@ -90,6 +86,9 @@ class PreviewList extends ScrollView @rootView.focus() false + getPathCount: -> + _.keys(_.groupBy(@operations, (operation) -> operation.getPath())).length + getOperations: -> new Array(@operations...) diff --git a/src/packages/fuzzy-finder/index.coffee b/src/packages/fuzzy-finder/index.coffee index 3dd4e515f..1d815057e 100644 --- a/src/packages/fuzzy-finder/index.coffee +++ b/src/packages/fuzzy-finder/index.coffee @@ -1 +1,21 @@ -module.exports = require 'fuzzy-finder/src/fuzzy-finder' +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class FuzzyFinder extends DeferredAtomPackage + + loadEvents: [ + 'fuzzy-finder:toggle-file-finder' + 'fuzzy-finder:toggle-buffer-finder' + 'fuzzy-finder:find-under-cursor' + ] + + instanceClass: 'fuzzy-finder/src/fuzzy-finder-view' + + onLoadEvent: (event, instance) -> + switch event.type + when 'fuzzy-finder:toggle-file-finder' + instance.toggleFileFinder() + when 'fuzzy-finder:toggle-buffer-finder' + instance.toggleBufferFinder() + when 'fuzzy-finder:find-under-cursor' + instance.findUnderCursor() diff --git a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee index 462550729..ad40e0010 100644 --- a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee +++ b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee @@ -1,5 +1,5 @@ RootView = require 'root-view' -FuzzyFinder = require 'fuzzy-finder' +FuzzyFinder = require 'fuzzy-finder/src/fuzzy-finder-view' $ = require 'jquery' {$$} = require 'space-pen' fs = require 'fs' @@ -10,7 +10,7 @@ describe 'FuzzyFinder', -> beforeEach -> rootView = new RootView(require.resolve('fixtures/sample.js')) rootView.enableKeymap() - atom.loadPackage("fuzzy-finder") + atom.loadPackage("fuzzy-finder").getInstance() finder = FuzzyFinder.instance afterEach -> @@ -187,21 +187,38 @@ describe 'FuzzyFinder', -> describe "common behavior between file and buffer finder", -> describe "when the fuzzy finder is cancelled", -> - it "detaches the finder and focuses the previously focused element", -> - rootView.attachToDom() - activeEditor = rootView.getActiveEditor() - activeEditor.focus() + describe "when an editor is open", -> + it "detaches the finder and focuses the previously focused element", -> + rootView.attachToDom() + activeEditor = rootView.getActiveEditor() + activeEditor.focus() - rootView.trigger 'fuzzy-finder:toggle-file-finder' - expect(finder.hasParent()).toBeTruthy() - expect(activeEditor.isFocused).toBeFalsy() - expect(finder.miniEditor.isFocused).toBeTruthy() + rootView.trigger 'fuzzy-finder:toggle-file-finder' + expect(finder.hasParent()).toBeTruthy() + expect(activeEditor.isFocused).toBeFalsy() + expect(finder.miniEditor.isFocused).toBeTruthy() - finder.cancel() + finder.cancel() - expect(finder.hasParent()).toBeFalsy() - expect(activeEditor.isFocused).toBeTruthy() - expect(finder.miniEditor.isFocused).toBeFalsy() + expect(finder.hasParent()).toBeFalsy() + expect(activeEditor.isFocused).toBeTruthy() + expect(finder.miniEditor.isFocused).toBeFalsy() + + describe "when no editors are open", -> + it "detaches the finder and focuses the previously focused element", -> + rootView.attachToDom() + rootView.getActiveEditor().destroyActiveEditSession() + + rootView.trigger 'fuzzy-finder:toggle-file-finder' + expect(finder.hasParent()).toBeTruthy() + expect(rootView.isFocused).toBeFalsy() + expect(finder.miniEditor.isFocused).toBeTruthy() + + finder.cancel() + + expect(finder.hasParent()).toBeFalsy() + expect($(document.activeElement).view()).toBe rootView + expect(finder.miniEditor.isFocused).toBeFalsy() describe "cached file paths", -> it "caches file paths after first time", -> diff --git a/src/packages/fuzzy-finder/src/fuzzy-finder.coffee b/src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee similarity index 91% rename from src/packages/fuzzy-finder/src/fuzzy-finder.coffee rename to src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee index 01bdade9a..2365fc4d7 100644 --- a/src/packages/fuzzy-finder/src/fuzzy-finder.coffee +++ b/src/packages/fuzzy-finder/src/fuzzy-finder-view.coffee @@ -5,14 +5,11 @@ $ = require 'jquery' fs = require 'fs' module.exports = -class FuzzyFinder extends SelectList +class FuzzyFinderView extends SelectList filenameRegex: /[\w\.\-\/\\]+/ @activate: (rootView) -> - @instance = new FuzzyFinder(rootView) - rootView.command 'fuzzy-finder:toggle-file-finder', => @instance.toggleFileFinder() - rootView.command 'fuzzy-finder:toggle-buffer-finder', => @instance.toggleBufferFinder() - rootView.command 'fuzzy-finder:find-under-cursor', => @instance.findUnderCursor() + @instance = new FuzzyFinderView(rootView) @viewClass: -> [super, 'fuzzy-finder'].join(' ') @@ -75,10 +72,6 @@ class FuzzyFinder extends SelectList @setError('Selected path does not exist') setTimeout((=> @setError()), 2000) - cancelled: -> - @miniEditor.setText('') - @rootView.focus() if @miniEditor.isFocused - toggleFileFinder: -> if @hasParent() @cancel() @@ -160,5 +153,7 @@ class FuzzyFinder extends SelectList @setArray(@paths) attach: -> + super + @rootView.append(this) @miniEditor.focus() diff --git a/src/packages/gists/index.coffee b/src/packages/gists/index.coffee new file mode 100644 index 000000000..6205cb366 --- /dev/null +++ b/src/packages/gists/index.coffee @@ -0,0 +1,12 @@ +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class GistsPackage extends DeferredAtomPackage + + loadEvents: + 'gist:create': '.editor' + + instanceClass: 'gists/lib/gists' + + onLoadEvent: (event, instance) -> + instance.createGist(event.currentTargetView()) diff --git a/src/packages/gists/keymaps/gists.cson b/src/packages/gists/keymaps/gists.cson new file mode 100644 index 000000000..fa7699100 --- /dev/null +++ b/src/packages/gists/keymaps/gists.cson @@ -0,0 +1,2 @@ +'body': + 'alt-meta-g': 'gist:create' diff --git a/src/packages/gists/lib/gists.coffee b/src/packages/gists/lib/gists.coffee new file mode 100644 index 000000000..434603636 --- /dev/null +++ b/src/packages/gists/lib/gists.coffee @@ -0,0 +1,31 @@ +$ = require 'jquery' +{$$} = require 'space-pen' + +module.exports = +class Gists + + @activate: (rootView) -> new Gists(rootView) + + constructor: (@rootView) -> + + createGist: (editor) -> + gist = { public: false, files: {} } + gist.files[editor.getBuffer().getBaseName()] = + content: editor.getSelectedText() or editor.getText() + + $.ajax + url: 'https://api.github.com/gists' + type: 'POST' + dataType: 'json' + contentType: 'application/json; charset=UTF-8' + data: JSON.stringify(gist) + success: (response) => + pasteboard.write(response.html_url) + notification = $$ -> + @div class: 'gist-notification', => + @div class: 'message-area', => + @span "Gist #{response.id} created", class: 'message' + @br() + @span "The url is on your clipboard", class: 'clipboard' + @rootView.append(notification.hide()) + notification.fadeIn().delay(2000).fadeOut(complete: -> $(this).remove()) diff --git a/src/packages/gists/spec/gists-spec.coffee b/src/packages/gists/spec/gists-spec.coffee new file mode 100644 index 000000000..64227744a --- /dev/null +++ b/src/packages/gists/spec/gists-spec.coffee @@ -0,0 +1,61 @@ +RootView = require 'root-view' +$ = require 'jquery' + +describe "Gists package", -> + + [rootView, editor] = [] + + beforeEach -> + rootView = new RootView(fixturesProject.resolve('sample.js')) + atom.loadPackage('gists').getInstance() + editor = rootView.getActiveEditor() + spyOn($, 'ajax') + + afterEach -> + rootView.deactivate() + + describe "when gist:create is triggered on an editor", -> + + describe "when the editor has no selection", -> + [request, originalFxOffValue] = [] + + beforeEach -> + originalFxOffValue = $.fx.off + $.fx.off = true + editor.trigger 'gist:create' + expect($.ajax).toHaveBeenCalled() + request = $.ajax.argsForCall[0][0] + + afterEach -> + $.fx.off = originalFxOffValue + + it "creates an Ajax request to api.github.com with the entire buffer contents as the Gist's content", -> + expect(request.url).toBe 'https://api.github.com/gists' + expect(request.type).toBe 'POST' + requestData = JSON.parse(request.data) + expect(requestData.public).toBeFalsy() + expect(requestData.files).toEqual 'sample.js': content: editor.getText() + + describe "when the server responds successfully", -> + beforeEach -> + request.success(html_url: 'https://gist.github.com/1', id: '1') + + it "places the created Gist's URL on the clipboard", -> + expect(pasteboard.read()[0]).toBe 'https://gist.github.com/1' + + it "flashes that the Gist was created", -> + expect(rootView.find('.gist-notification')).toExist() + expect(rootView.find('.gist-notification .message').text()).toBe 'Gist 1 created' + advanceClock(2000) + expect(rootView.find('.gist-notification')).not.toExist() + + describe "when the editor has a selection", -> + beforeEach -> + editor.setSelectedBufferRange [[4, 0], [8, 0]] + + it "creates an Ajax with the selected text as the Gist's content", -> + editor.trigger 'gist:create' + expect($.ajax).toHaveBeenCalled() + request = $.ajax.argsForCall[0][0] + requestData = JSON.parse(request.data) + expect(requestData.files).toEqual 'sample.js': content: editor.getSelectedText() diff --git a/src/packages/go-to-line/index.coffee b/src/packages/go-to-line/index.coffee new file mode 100644 index 000000000..12601c00e --- /dev/null +++ b/src/packages/go-to-line/index.coffee @@ -0,0 +1,12 @@ +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class GoToLinePackage extends DeferredAtomPackage + + loadEvents: + 'editor:go-to-line': '.editor' + + instanceClass: 'go-to-line/lib/go-to-line-view' + + onLoadEvent: (event, instance) -> + instance.toggle(event.currentTargetView()) diff --git a/src/packages/go-to-line/keymaps/go-to-line.cson b/src/packages/go-to-line/keymaps/go-to-line.cson new file mode 100644 index 000000000..5686829bd --- /dev/null +++ b/src/packages/go-to-line/keymaps/go-to-line.cson @@ -0,0 +1,6 @@ +'body': + 'meta-l': 'editor:go-to-line' +'.go-to-line .mini.editor input': + 'enter': 'core:confirm', + 'escape': 'core:cancel' + 'meta-w': 'core:cancel' diff --git a/src/packages/go-to-line/lib/go-to-line-view.coffee b/src/packages/go-to-line/lib/go-to-line-view.coffee new file mode 100644 index 000000000..ce99ece31 --- /dev/null +++ b/src/packages/go-to-line/lib/go-to-line-view.coffee @@ -0,0 +1,54 @@ +{View} = require 'space-pen' +Editor = require 'editor' +$ = require 'jquery' +Point = require 'point' + +module.exports = +class GoToLineView extends View + + @activate: (rootView) -> new GoToLineView(rootView) + + @content: -> + @div class: 'go-to-line', => + @subview 'miniEditor', new Editor(mini: true) + @div class: 'message', outlet: 'message' + + initialize: (@rootView) -> + @miniEditor.on 'focusout', => @detach() + @on 'core:confirm', => @confirm() + @on 'core:cancel', => @detach() + + @miniEditor.preempt 'textInput', (e) => + false unless e.originalEvent.data.match(/[0-9]/) + + toggle: -> + if @hasParent() + @detach() + else + @attach() + + detach: -> + return unless @hasParent() + + @miniEditor.setText('') + @previouslyFocusedElement?.focus() + + super + + confirm: -> + lineNumber = @miniEditor.getText() + editor = rootView.getActiveEditor() + + @detach() + + return unless editor and lineNumber.length + position = new Point(parseInt(lineNumber - 1, 0)) + editor.scrollToBufferPosition(position, center: true) + editor.setCursorBufferPosition(position) + editor.moveCursorToFirstCharacterOfLine() + + attach: -> + @previouslyFocusedElement = $(':focus') + @rootView.append(this) + @message.text("Enter a line number 1-#{@rootView.getActiveEditor().getLineCount()}") + @miniEditor.focus() diff --git a/src/packages/go-to-line/spec/go-to-line-spec.coffee b/src/packages/go-to-line/spec/go-to-line-spec.coffee new file mode 100644 index 000000000..775bde131 --- /dev/null +++ b/src/packages/go-to-line/spec/go-to-line-spec.coffee @@ -0,0 +1,51 @@ +RootView = require 'root-view' + +describe 'GoToLine', -> + [rootView, goToLine, editor] = [] + + beforeEach -> + rootView = new RootView(require.resolve('fixtures/sample.js')) + rootView.enableKeymap() + goToLine = atom.loadPackage("go-to-line").getInstance() + editor = rootView.getActiveEditor() + editor.setCursorBufferPosition([1,0]) + + afterEach -> + rootView.remove() + + describe "when editor:go-to-line is triggered", -> + it "attaches to the root view", -> + expect(goToLine.hasParent()).toBeFalsy() + editor.trigger 'editor:go-to-line' + expect(goToLine.hasParent()).toBeTruthy() + + describe "when entering a line number", -> + it "only allows 0-9 to be entered in the mini editor", -> + expect(goToLine.miniEditor.getText()).toBe '' + goToLine.miniEditor.textInput 'a' + expect(goToLine.miniEditor.getText()).toBe '' + goToLine.miniEditor.textInput '40' + expect(goToLine.miniEditor.getText()).toBe '40' + + describe "when core:confirm is triggered", -> + describe "when a line number has been entered", -> + it "moves the cursor to the first character of the line", -> + goToLine.miniEditor.textInput '3' + goToLine.miniEditor.trigger 'core:confirm' + expect(editor.getCursorBufferPosition()).toEqual [2, 4] + + describe "when no line number has been entered", -> + it "closes the view and does not update the cursor position", -> + editor.trigger 'editor:go-to-line' + expect(goToLine.hasParent()).toBeTruthy() + goToLine.miniEditor.trigger 'core:confirm' + expect(goToLine.hasParent()).toBeFalsy() + expect(editor.getCursorBufferPosition()).toEqual [1, 0] + + describe "when core:cancel is triggered", -> + it "closes the view and does not update the cursor position", -> + editor.trigger 'editor:go-to-line' + expect(goToLine.hasParent()).toBeTruthy() + goToLine.miniEditor.trigger 'core:cancel' + expect(goToLine.hasParent()).toBeFalsy() + expect(editor.getCursorBufferPosition()).toEqual [1, 0] diff --git a/src/packages/markdown-preview/index.coffee b/src/packages/markdown-preview/index.coffee index 5dca810d4..7cbba03f0 100644 --- a/src/packages/markdown-preview/index.coffee +++ b/src/packages/markdown-preview/index.coffee @@ -1 +1,9 @@ -module.exports = require 'markdown-preview/src/markdown-preview' +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class MarkdownPreview extends DeferredAtomPackage + loadEvents: ['markdown-preview:toggle'] + + instanceClass: 'markdown-preview/src/markdown-preview-view' + + onLoadEvent: (event, instance) -> instance.toggle() diff --git a/src/packages/markdown-preview/spec/markdown-preview-spec.coffee b/src/packages/markdown-preview/spec/markdown-preview-spec.coffee index aff38972b..49066159b 100644 --- a/src/packages/markdown-preview/spec/markdown-preview-spec.coffee +++ b/src/packages/markdown-preview/spec/markdown-preview-spec.coffee @@ -1,14 +1,12 @@ $ = require 'jquery' RootView = require 'root-view' -MarkdownPreview = require 'markdown-preview' +MarkdownPreview = require 'markdown-preview/src/markdown-preview-view' describe "MarkdownPreview", -> [rootView, markdownPreview] = [] beforeEach -> rootView = new RootView(require.resolve('fixtures/markdown')) - atom.loadPackage("markdown-preview") - markdownPreview = MarkdownPreview.instance afterEach -> rootView.deactivate() @@ -17,6 +15,7 @@ describe "MarkdownPreview", -> it "toggles on/off a preview for a .md file", -> rootView.open('file.md') editor = rootView.getActiveEditor() + markdownPreview = atom.loadPackage("markdown-preview").getInstance() expect(rootView.find('.markdown-preview')).not.toExist() spyOn(markdownPreview, 'loadHtml') editor.trigger('markdown-preview:toggle') @@ -30,6 +29,7 @@ describe "MarkdownPreview", -> it "displays a preview for a .markdown file", -> rootView.open('file.markdown') editor = rootView.getActiveEditor() + markdownPreview = atom.loadPackage("markdown-preview").getInstance() expect(rootView.find('.markdown-preview')).not.toExist() spyOn(markdownPreview, 'loadHtml') editor.trigger('markdown-preview:toggle') @@ -39,6 +39,7 @@ describe "MarkdownPreview", -> it "does not display a preview for non-markdown file", -> rootView.open('file.js') editor = rootView.getActiveEditor() + markdownPreview = atom.loadPackage("markdown-preview").getInstance() expect(rootView.find('.markdown-preview')).not.toExist() spyOn(markdownPreview, 'loadHtml') editor.trigger('markdown-preview:toggle') @@ -49,6 +50,7 @@ describe "MarkdownPreview", -> it "removes markdown preview", -> rootView.open('file.md') editor = rootView.getActiveEditor() + markdownPreview = atom.loadPackage("markdown-preview").getInstance() expect(rootView.find('.markdown-preview')).not.toExist() spyOn(markdownPreview, 'loadHtml') editor.trigger('markdown-preview:toggle') @@ -57,3 +59,17 @@ describe "MarkdownPreview", -> expect(markdownPreviewView).toExist() markdownPreviewView.trigger('core:cancel') expect(rootView.find('.markdown-preview')).not.toExist() + + describe "when the editor receives focus", -> + it "removes the markdown preview view", -> + rootView.open('file.md') + editor = rootView.getActiveEditor() + markdownPreview = atom.loadPackage("markdown-preview").getInstance() + expect(rootView.find('.markdown-preview')).not.toExist() + spyOn(markdownPreview, 'loadHtml') + editor.trigger('markdown-preview:toggle') + + markdownPreviewView = rootView.find('.markdown-preview') + expect(markdownPreviewView).toExist() + editor.focus() + expect(rootView.find('.markdown-preview')).not.toExist() diff --git a/src/packages/markdown-preview/src/markdown-preview.coffee b/src/packages/markdown-preview/src/markdown-preview-view.coffee similarity index 83% rename from src/packages/markdown-preview/src/markdown-preview.coffee rename to src/packages/markdown-preview/src/markdown-preview-view.coffee index 88a39c2f6..c044623ab 100644 --- a/src/packages/markdown-preview/src/markdown-preview.coffee +++ b/src/packages/markdown-preview/src/markdown-preview-view.coffee @@ -4,7 +4,7 @@ $ = require 'jquery' {$$$} = require 'space-pen' module.exports = -class MarkdownPreview extends ScrollView +class MarkdownPreviewView extends ScrollView @activate: (rootView, state) -> @instance = new this(rootView) @@ -14,8 +14,10 @@ class MarkdownPreview extends ScrollView initialize: (@rootView) -> super - @rootView.command 'markdown-preview:toggle', => @toggle() - @command 'core:cancel', => @detach() + + @editor = @rootView.getActiveEditor() + @subscribe @editor, 'focus', => @detach() unless @detaching + @command 'core:cancel', => @detach() unless @detaching toggle: -> if @hasParent() @@ -31,14 +33,16 @@ class MarkdownPreview extends ScrollView @focus() detach: -> - super() + @detaching = true + super @rootView.focus() + @detaching = false getActivePath: -> - @rootView.getActiveEditor()?.getPath() + @editor.getPath() getActiveText: -> - @rootView.getActiveEditor()?.getText() + @editor.getText() getErrorHtml: (error) -> $$$ -> diff --git a/src/packages/outline-view/index.coffee b/src/packages/outline-view/index.coffee deleted file mode 100644 index 049aa16ea..000000000 --- a/src/packages/outline-view/index.coffee +++ /dev/null @@ -1 +0,0 @@ -module.exports = require 'outline-view/src/outline-view' diff --git a/src/packages/outline-view/keymaps/outline-view.cson b/src/packages/outline-view/keymaps/outline-view.cson deleted file mode 100644 index e47463687..000000000 --- a/src/packages/outline-view/keymaps/outline-view.cson +++ /dev/null @@ -1,6 +0,0 @@ -'.editor': - 'meta-j': 'outline-view:toggle-file-outline' - 'meta-.': 'outline-view:jump-to-declaration' - -'body': - 'meta-J': 'outline-view:toggle-project-outline' diff --git a/src/packages/outline-view/spec/outline-view-spec.coffee b/src/packages/outline-view/spec/outline-view-spec.coffee deleted file mode 100644 index e74981663..000000000 --- a/src/packages/outline-view/spec/outline-view-spec.coffee +++ /dev/null @@ -1,174 +0,0 @@ -RootView = require 'root-view' -OutlineView = require 'outline-view' -TagGenerator = require 'outline-view/src/tag-generator' - -describe "OutlineView", -> - [rootView, outlineView, setArraySpy] = [] - - beforeEach -> - rootView = new RootView(require.resolve('fixtures')) - atom.loadPackage("outline-view") - outlineView = OutlineView.instance - rootView.attachToDom() - setArraySpy = spyOn(outlineView, 'setArray').andCallThrough() - - afterEach -> - rootView.deactivate() - setArraySpy.reset() - - describe "when tags can be generated for a file", -> - it "initially displays all JavaScript functions with line numbers", -> - rootView.open('sample.js') - expect(rootView.find('.outline-view')).not.toExist() - rootView.getActiveEditor().trigger "outline-view:toggle-file-outline" - expect(outlineView.find('.loading')).toHaveText 'Generating symbols...' - - waitsFor -> - setArraySpy.callCount > 0 - - runs -> - expect(outlineView.find('.loading')).toBeEmpty() - expect(rootView.find('.outline-view')).toExist() - expect(outlineView.list.children('li').length).toBe 2 - expect(outlineView.list.children('li:first').find('.function-name')).toHaveText 'quicksort' - expect(outlineView.list.children('li:first').find('.function-details')).toHaveText 'Line 1' - expect(outlineView.list.children('li:last').find('.function-name')).toHaveText 'quicksort.sort' - expect(outlineView.list.children('li:last').find('.function-details')).toHaveText 'Line 2' - expect(outlineView).not.toHaveClass "error" - expect(outlineView.error).not.toBeVisible() - - it "displays error when no tags match text in mini-editor", -> - rootView.open('sample.js') - expect(rootView.find('.outline-view')).not.toExist() - rootView.getActiveEditor().trigger "outline-view:toggle-file-outline" - - waitsFor -> - setArraySpy.callCount > 0 - - runs -> - outlineView.miniEditor.setText("nothing will match this") - window.advanceClock(outlineView.inputThrottle) - - expect(rootView.find('.outline-view')).toExist() - expect(outlineView.list.children('li').length).toBe 0 - expect(outlineView.error).toBeVisible() - expect(outlineView.error.text().length).toBeGreaterThan 0 - expect(outlineView).toHaveClass "error" - - # Should remove error - outlineView.miniEditor.setText("") - window.advanceClock(outlineView.inputThrottle) - - expect(outlineView.list.children('li').length).toBe 2 - expect(outlineView).not.toHaveClass "error" - expect(outlineView.error).not.toBeVisible() - - describe "when tags can't be generated for a file", -> - it "shows an error message when no matching tags are found", -> - rootView.open('sample.txt') - expect(rootView.find('.outline-view')).not.toExist() - rootView.getActiveEditor().trigger "outline-view:toggle-file-outline" - setErrorSpy = spyOn(outlineView, "setError").andCallThrough() - - waitsFor -> - setErrorSpy.callCount > 0 - - runs -> - expect(rootView.find('.outline-view')).toExist() - expect(outlineView.list.children('li').length).toBe 0 - expect(outlineView.error).toBeVisible() - expect(outlineView.error.text().length).toBeGreaterThan 0 - expect(outlineView).toHaveClass "error" - expect(outlineView.find('.loading')).not.toBeVisible() - - it "moves the cursor to the selected function", -> - tags = [] - waitsForPromise -> - tags = [] - path = require.resolve('fixtures/sample.js') - callback = (tag) -> - tags.push tag - generator = new TagGenerator(path, callback) - generator.generate() - - runs -> - rootView.open('sample.js') - expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [0,0] - expect(rootView.find('.outline-view')).not.toExist() - outlineView.setArray(tags) - outlineView.attach() - expect(rootView.find('.outline-view')).toExist() - outlineView.confirmed(tags[1]) - expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [1,2] - - describe "TagGenerator", -> - it "generates tags for all JavaScript functions", -> - waitsForPromise -> - tags = [] - path = require.resolve('fixtures/sample.js') - callback = (tag) -> - tags.push tag - generator = new TagGenerator(path, callback) - generator.generate().done -> - expect(tags.length).toBe 2 - expect(tags[0].name).toBe "quicksort" - expect(tags[0].position.row).toBe 0 - expect(tags[1].name).toBe "quicksort.sort" - expect(tags[1].position.row).toBe 1 - - it "generates no tags for text file", -> - waitsForPromise -> - tags = [] - path = require.resolve('fixtures/sample.txt') - callback = (tag) -> - tags.push tag - generator = new TagGenerator(path, callback) - generator.generate().done -> - expect(tags.length).toBe 0 - - describe "jump to declaration", -> - it "doesn't move the cursor when no declaration is found", -> - rootView.open("tagged.js") - editor = rootView.getActiveEditor() - editor.setCursorBufferPosition([0,2]) - editor.trigger 'outline-view:jump-to-declaration' - expect(editor.getCursorBufferPosition()).toEqual [0,2] - - it "moves the cursor to the declaration", -> - rootView.open("tagged.js") - editor = rootView.getActiveEditor() - editor.setCursorBufferPosition([6,24]) - editor.trigger 'outline-view:jump-to-declaration' - expect(editor.getCursorBufferPosition()).toEqual [2,0] - - it "displays matches when more than one exists and opens the selected match", -> - rootView.open("tagged.js") - editor = rootView.getActiveEditor() - editor.setCursorBufferPosition([8,14]) - editor.trigger 'outline-view:jump-to-declaration' - expect(outlineView.list.children('li').length).toBe 2 - expect(outlineView).toBeVisible() - outlineView.confirmed(outlineView.array[0]) - expect(rootView.getActiveEditor().getPath()).toBe rootView.project.resolve("tagged-duplicate.js") - expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [0,4] - - describe "project outline", -> - it "displays all tags", -> - rootView.open("tagged.js") - expect(rootView.find('.outline-view')).not.toExist() - rootView.trigger "outline-view:toggle-project-outline" - expect(outlineView.find('.loading')).toHaveText 'Loading symbols...' - - waitsFor -> - setArraySpy.callCount > 0 - - runs -> - expect(outlineView.find('.loading')).toBeEmpty() - expect(rootView.find('.outline-view')).toExist() - expect(outlineView.list.children('li').length).toBe 4 - expect(outlineView.list.children('li:first').find('.function-name')).toHaveText 'callMeMaybe' - expect(outlineView.list.children('li:first').find('.function-details')).toHaveText 'tagged.js' - expect(outlineView.list.children('li:last').find('.function-name')).toHaveText 'thisIsCrazy' - expect(outlineView.list.children('li:last').find('.function-details')).toHaveText 'tagged.js' - expect(outlineView).not.toHaveClass "error" - expect(outlineView.error).not.toBeVisible() diff --git a/src/packages/snippets/index.coffee b/src/packages/snippets/index.coffee index b58971121..6778eb145 100644 --- a/src/packages/snippets/index.coffee +++ b/src/packages/snippets/index.coffee @@ -1 +1,62 @@ -module.exports = require 'snippets/src/snippets' +AtomPackage = require 'atom-package' +fs = require 'fs' +_ = require 'underscore' +SnippetExpansion = require './src/snippet-expansion' +Snippet = require './src/snippet' +LoadSnippetsTask = require './src/load-snippets-task' + +module.exports = +class Snippets extends AtomPackage + snippetsByExtension: {} + loaded: false + + activate: (@rootView) -> + window.snippets = this + @loadAll() + @rootView.on 'editor:attached', (e, editor) => @enableSnippetsInEditor(editor) + + loadAll: -> + new LoadSnippetsTask(this).start() + + loadDirectory: (snippetsDirPath) -> + for snippetsPath in fs.list(snippetsDirPath) when fs.base(snippetsPath).indexOf('.') isnt 0 + snippets.loadFile(snippetsPath) + + loadFile: (snippetsPath) -> + try + snippets = fs.readObject(snippetsPath) + catch e + console.warn "Error reading snippets file '#{snippetsPath}'" + @add(snippets) + + add: (snippetsBySelector) -> + for selector, snippetsByName of snippetsBySelector + snippetsByPrefix = {} + for name, attributes of snippetsByName + { prefix, body, bodyTree } = attributes + # if `add` isn't called by the loader task (in specs for example), we need to parse the body + bodyTree ?= @getBodyParser().parse(body) + snippet = new Snippet({name, prefix, bodyTree}) + snippetsByPrefix[snippet.prefix] = snippet + syntax.addProperties(selector, snippets: snippetsByPrefix) + + getBodyParser: -> + require 'snippets/src/snippet-body-parser' + + enableSnippetsInEditor: (editor) -> + editor.command 'snippets:expand', (e) => + editSession = editor.activeEditSession + prefix = editSession.getCursor().getCurrentWordPrefix() + if snippet = syntax.getProperty(editSession.getCursorScopes(), "snippets.#{prefix}") + editSession.transact -> + new SnippetExpansion(snippet, editSession) + else + e.abortKeyBinding() + + editor.command 'snippets:next-tab-stop', (e) -> + unless editor.activeEditSession.snippetExpansion?.goToNextTabStop() + e.abortKeyBinding() + + editor.command 'snippets:previous-tab-stop', (e) -> + unless editor.activeEditSession.snippetExpansion?.goToPreviousTabStop() + e.abortKeyBinding() diff --git a/src/packages/snippets/spec/snippets-spec.coffee b/src/packages/snippets/spec/snippets-spec.coffee index f03a86452..046807746 100644 --- a/src/packages/snippets/spec/snippets-spec.coffee +++ b/src/packages/snippets/spec/snippets-spec.coffee @@ -1,21 +1,20 @@ Snippets = require 'snippets' Snippet = require 'snippets/src/snippet' +LoadSnippetsTask = require 'snippets/src/load-snippets-task' RootView = require 'root-view' Buffer = require 'buffer' Editor = require 'editor' _ = require 'underscore' fs = require 'fs' -AtomPackage = require 'atom-package' -TextMatePackage = require 'text-mate-package' describe "Snippets extension", -> - [buffer, editor] = [] + [buffer, editor, editSession] = [] beforeEach -> rootView = new RootView(require.resolve('fixtures/sample.js')) - spyOn(AtomPackage.prototype, 'loadSnippets') - spyOn(TextMatePackage.prototype, 'loadSnippets') + spyOn(LoadSnippetsTask.prototype, 'start') atom.loadPackage("snippets") editor = rootView.getActiveEditor() + editSession = rootView.getActiveEditSession() buffer = editor.getBuffer() rootView.simulateDomAttachment() rootView.enableKeymap() @@ -44,15 +43,7 @@ describe "Snippets extension", -> prefix: "t3" body: """ line 1 - line 2$1 - - """ - - "tab stop placeholders": - prefix: "t4" - body: """ - go here ${1:first - think a while}, and then here ${2:second} + \tline 2$1 """ @@ -67,6 +58,15 @@ describe "Snippets extension", -> ${2:placeholder ending second line} """ + "contains empty lines": + prefix: "t7" + body: """ + first line $1 + + + fourth line after blanks $2 + """ + describe "when the letters preceding the cursor trigger a snippet", -> describe "when the snippet contains no tab stops", -> it "replaces the prefix with the snippet text and places the cursor at its end", -> @@ -77,6 +77,13 @@ describe "Snippets extension", -> expect(buffer.lineForRow(0)).toBe "this is a testvar quicksort = function () {" expect(editor.getCursorScreenPosition()).toEqual [0, 14] + it "inserts a real tab the next time a tab is pressed after the snippet is expanded", -> + editor.insertText("t1") + editor.trigger keydownEvent('tab', target: editor[0]) + expect(buffer.lineForRow(0)).toBe "this is a testvar quicksort = function () {" + editor.trigger keydownEvent('tab', target: editor[0]) + expect(buffer.lineForRow(0)).toBe "this is a test var quicksort = function () {" + describe "when the snippet contains tab stops", -> it "places the cursor at the first tab-stop, and moves the cursor in response to 'next-tab-stop' events", -> anchorCountBefore = editor.activeEditSession.getAnchors().length @@ -113,16 +120,6 @@ describe "Snippets extension", -> expect(buffer.lineForRow(2)).toBe "go here next:(abc) and finally go here:( )" expect(editor.activeEditSession.getAnchors().length).toBe anchorCountBefore - describe "when the tab stops have placeholder text", -> - it "auto-fills the placeholder text and highlights it when navigating to that tab stop", -> - editor.insertText 't4' - editor.trigger 'snippets:expand' - expect(buffer.lineForRow(0)).toBe 'go here first' - expect(buffer.lineForRow(1)).toBe 'think a while, and then here second' - expect(editor.getSelectedBufferRange()).toEqual [[0, 8], [1, 13]] - editor.trigger keydownEvent('tab', target: editor[0]) - expect(editor.getSelectedBufferRange()).toEqual [[1, 29], [1, 35]] - describe "when tab stops are nested", -> it "destroys the inner tab stop if the outer tab stop is modified", -> buffer.setText('') @@ -134,6 +131,14 @@ describe "Snippets extension", -> editor.trigger keydownEvent('tab', target: editor[0]) expect(editor.getSelectedBufferRange()).toEqual [[0, 5], [0, 10]] + describe "when tab stops are separated by blank lines", -> + it "correctly places the tab stops (regression)", -> + buffer.setText('') + editor.insertText 't7' + editor.trigger 'snippets:expand' + editor.trigger 'snippets:next-tab-stop' + expect(editSession.getCursorBufferPosition()).toEqual [3, 25] + describe "when the cursor is moved beyond the bounds of a tab stop", -> it "terminates the snippet", -> editor.setCursorScreenPosition([2, 0]) @@ -157,7 +162,24 @@ describe "Snippets extension", -> editor.trigger keydownEvent('tab', shiftKey: true, target: editor[0]) expect(editor.getCursorBufferPosition()).toEqual [4, 15] - describe "when a the start of the snippet is indented", -> + describe "when the snippet contains hard tabs", -> + describe "when the edit session is in soft-tabs mode", -> + it "translates hard tabs in the snippet to the appropriate number of spaces", -> + expect(editSession.softTabs).toBeTruthy() + editor.insertText("t3") + editor.trigger keydownEvent('tab', target: editor[0]) + expect(buffer.lineForRow(1)).toBe " line 2" + expect(editSession.getCursorBufferPosition()).toEqual [1, 8] + + describe "when the edit session is in hard-tabs mode", -> + it "inserts hard tabs in the snippet directly", -> + editSession.setSoftTabs(false) + editor.insertText("t3") + editor.trigger keydownEvent('tab', target: editor[0]) + expect(buffer.lineForRow(1)).toBe "\tline 2" + expect(editSession.getCursorBufferPosition()).toEqual [1, 7] + + describe "when the snippet prefix is indented", -> describe "when the snippet spans a single line", -> it "does not indent the next line", -> editor.setCursorScreenPosition([2, Infinity]) @@ -167,6 +189,7 @@ describe "Snippets extension", -> describe "when the snippet spans multiple lines", -> it "indents the subsequent lines of the snippet to be even with the start of the first line", -> + expect(editSession.softTabs).toBeTruthy() editor.setCursorScreenPosition([2, Infinity]) editor.insertText ' t3' editor.trigger 'snippets:expand' @@ -197,9 +220,10 @@ describe "Snippets extension", -> describe "when a snippet expansion is undone and redone", -> it "recreates the snippet's tab stops", -> editor.insertText ' t6\n' - editor.setCursorBufferPosition [0, 6] + editor.setCursorBufferPosition [0, Infinity] editor.trigger keydownEvent('tab', target: editor[0]) expect(buffer.lineForRow(0)).toBe " first line" + expect(editor.getCursorBufferPosition()).toEqual [0, 14] editor.undo() editor.redo() expect(editor.getCursorBufferPosition()).toEqual [0, 14] @@ -207,34 +231,65 @@ describe "Snippets extension", -> expect(editor.getSelectedBufferRange()).toEqual [[1, 6], [1, 36]] describe "snippet loading", -> + beforeEach -> + atom.packages = null + jasmine.unspy(LoadSnippetsTask.prototype, 'start') + spyOn(LoadSnippetsTask.prototype, 'loadAtomSnippets').andCallFake -> @snippetsLoaded({}) + spyOn(LoadSnippetsTask.prototype, 'loadTextMateSnippets').andCallFake -> @snippetsLoaded({}) + it "loads non-hidden snippet files from all atom packages with snippets directories, logging a warning if a file can't be parsed", -> + jasmine.unspy(LoadSnippetsTask.prototype, 'loadAtomSnippets') spyOn(console, 'warn') - jasmine.unspy(AtomPackage.prototype, 'loadSnippets') + snippets.loaded = false snippets.loadAll() - expect(syntax.getProperty(['.test'], 'snippets.test')?.constructor).toBe Snippet + waitsFor "all snippets to load", 5000, -> snippets.loaded - # warn about junk-file, but don't even try to parse a hidden file - expect(console.warn).toHaveBeenCalled() - expect(console.warn.calls.length).toBe 1 + runs -> + expect(syntax.getProperty(['.test'], 'snippets.test')?.constructor).toBe Snippet + + # warn about junk-file, but don't even try to parse a hidden file + expect(console.warn).toHaveBeenCalled() + expect(console.warn.calls.length).toBe 1 it "loads snippets from all TextMate packages with snippets", -> - jasmine.unspy(TextMatePackage.prototype, 'loadSnippets') + jasmine.unspy(LoadSnippetsTask.prototype, 'loadTextMateSnippets') + spyOn(console, 'warn') + snippets.loaded = false snippets.loadAll() - snippet = syntax.getProperty(['.source.js'], 'snippets.fun') - expect(snippet.constructor).toBe Snippet - expect(snippet.prefix).toBe 'fun' - expect(snippet.name).toBe 'Function' - expect(snippet.body).toBe """ - function function_name (argument) { - \t// body... - } - """ + waitsFor "all snippets to load", 5000, -> snippets.loaded - describe "Snippets parser", -> + runs -> + snippet = syntax.getProperty(['.source.js'], 'snippets.fun') + expect(snippet.constructor).toBe Snippet + expect(snippet.prefix).toBe 'fun' + expect(snippet.name).toBe 'Function' + expect(snippet.body).toBe """ + function function_name (argument) { + \t// body... + } + """ + + # warn about junk-file, but don't even try to parse a hidden file + expect(console.warn).toHaveBeenCalled() + expect(console.warn.calls.length).toBe 1 + + it "terminates the worker when loading completes", -> + jasmine.unspy(LoadSnippetsTask.prototype, 'loadAtomSnippets') + spyOn(Worker.prototype, 'terminate').andCallThrough() + snippets.loaded = false + snippets.loadAll() + + waitsFor "all snippets to load", 5000, -> snippets.loaded + + runs -> + expect(Worker.prototype.terminate).toHaveBeenCalled() + expect(Worker.prototype.terminate.calls.length).toBe 1 + + describe "snippet body parser", -> it "breaks a snippet body into lines, with each line containing tab stops at the appropriate position", -> - bodyTree = Snippets.parser.parse """ + bodyTree = snippets.getBodyParser().parse """ the quick brown $1fox ${2:jumped ${3:over} }the ${4:lazy} dog """ @@ -255,3 +310,16 @@ describe "Snippets extension", -> { index: 4, content: ["lazy"] }, " dog" ] + + it "removes interpolated variables in placeholder text (we don't currently support it)", -> + bodyTree = snippets.getBodyParser().parse """ + module ${1:ActiveRecord::${TM_FILENAME/(?:\\A|_)([A-Za-z0-9]+)(?:\\.rb)?/(?2::\\u$1)/g}} + """ + + expect(bodyTree).toEqual [ + "module ", + { + "index": 1, + "content": ["ActiveRecord::", ""] + } + ] diff --git a/src/packages/snippets/src/load-snippets-handler.coffee b/src/packages/snippets/src/load-snippets-handler.coffee new file mode 100644 index 000000000..ba4f16c13 --- /dev/null +++ b/src/packages/snippets/src/load-snippets-handler.coffee @@ -0,0 +1,53 @@ +fs = require 'fs' +TextMatePackage = require 'text-mate-package' +SnippetBodyParser = require './snippet-body-parser' + +module.exports = + snippetsLoaded: (snippets) -> + for snippet in snippets + for selector, snippetsByName of snippet + for name, attributes of snippetsByName + attributes.bodyTree = SnippetBodyParser.parse(attributes.body) + callTaskMethod('snippetsLoaded', snippets) + + loadTextMateSnippets: (path) -> + snippetsDirPath = fs.join(path, 'Snippets') + snippets = [] + + for snippetsPath in fs.list(snippetsDirPath) + logWarning = -> + console.warn "Error reading TextMate snippets file '#{snippetsPath}'" + + continue if fs.base(snippetsPath).indexOf('.') is 0 + try + if object = fs.readPlist(snippetsPath) + snippets.push(object) if object + else + logWarning() + catch e + logWarning() + + @snippetsLoaded(@translateTextmateSnippets(snippets)) + + loadAtomSnippets: (path) -> + snippetsDirPath = fs.join(path, 'snippets') + snippets = [] + for snippetsPath in fs.list(snippetsDirPath) + continue if fs.base(snippetsPath).indexOf('.') is 0 + try + snippets.push(fs.readObject(snippetsPath)) + catch e + console.warn "Error reading snippets file '#{snippetsPath}'" + @snippetsLoaded(snippets) + + translateTextmateSnippets: (tmSnippets) -> + atomSnippets = {} + for { scope, name, content, tabTrigger } in tmSnippets + if scope + scope = TextMatePackage.cssSelectorFromScopeSelector(scope) + else + scope = '*' + + snippetsForScope = (atomSnippets[scope] ?= {}) + snippetsForScope[name] = { prefix: tabTrigger, body: content } + [atomSnippets] diff --git a/src/packages/snippets/src/load-snippets-task.coffee b/src/packages/snippets/src/load-snippets-task.coffee new file mode 100644 index 000000000..bbef9d681 --- /dev/null +++ b/src/packages/snippets/src/load-snippets-task.coffee @@ -0,0 +1,34 @@ +Task = require 'Task' +TextMatePackage = require 'text-mate-package' + +module.exports = +class LoadSnippetsTask extends Task + constructor: (@snippets) -> + super('snippets/src/load-snippets-handler') + @packages = atom.getPackages() + @packages.push(path: config.configDirPath) + + started: -> + @loadNextPackageSnippets() + + loadNextPackageSnippets: -> + unless @packages.length + @terminate() + @snippets.loaded = true + return + + @packageBeingLoaded = @packages.shift() + if @packageBeingLoaded instanceof TextMatePackage + @loadTextMateSnippets(@packageBeingLoaded.path) + else + @loadAtomSnippets(@packageBeingLoaded.path) + + loadAtomSnippets: (path) -> + @callWorkerMethod('loadAtomSnippets', path) + + loadTextMateSnippets: (path) -> + @callWorkerMethod('loadTextMateSnippets', path) + + snippetsLoaded: (snippets) -> + @snippets.add(snippet) for snippet in snippets + @loadNextPackageSnippets() diff --git a/src/packages/snippets/src/package-extensions.coffee b/src/packages/snippets/src/package-extensions.coffee deleted file mode 100644 index 342d20ecd..000000000 --- a/src/packages/snippets/src/package-extensions.coffee +++ /dev/null @@ -1,25 +0,0 @@ -AtomPackage = require 'atom-package' -TextMatePackage = require 'text-mate-package' -fs = require 'fs' - -AtomPackage.prototype.loadSnippets = -> - snippetsDirPath = fs.join(@path, 'snippets') - snippets.loadDirectory(snippetsDirPath) if fs.exists(snippetsDirPath) - -TextMatePackage.prototype.loadSnippets = -> - snippetsDirPath = fs.join(@path, 'Snippets') - if fs.exists(snippetsDirPath) - tmSnippets = fs.list(snippetsDirPath).map (snippetPath) -> fs.readPlist(snippetPath) - snippets.add(@translateSnippets(tmSnippets)) - -TextMatePackage.prototype.translateSnippets = (tmSnippets) -> - atomSnippets = {} - for { scope, name, content, tabTrigger } in tmSnippets - if scope - scope = TextMatePackage.cssSelectorFromScopeSelector(scope) - else - scope = '*' - - snippetsForScope = (atomSnippets[scope] ?= {}) - snippetsForScope[name] = { prefix: tabTrigger, body: content } - atomSnippets diff --git a/src/packages/snippets/src/snippet-body-parser.coffee b/src/packages/snippets/src/snippet-body-parser.coffee new file mode 100644 index 000000000..0239fee3f --- /dev/null +++ b/src/packages/snippets/src/snippet-body-parser.coffee @@ -0,0 +1,4 @@ +PEG = require 'pegjs' +fs = require 'fs' +grammarSrc = fs.read(require.resolve('./snippet-body.pegjs')) +module.exports = PEG.buildParser(grammarSrc, trackLineAndColumn: true) diff --git a/src/packages/snippets/snippets.pegjs b/src/packages/snippets/src/snippet-body.pegjs similarity index 52% rename from src/packages/snippets/snippets.pegjs rename to src/packages/snippets/src/snippet-body.pegjs index 72ec9be48..ce4f992fb 100644 --- a/src/packages/snippets/snippets.pegjs +++ b/src/packages/snippets/src/snippet-body.pegjs @@ -2,10 +2,6 @@ bodyContent = content:(tabStop / bodyContentText)* { return content; } bodyContentText = text:bodyContentChar+ { return text.join(''); } bodyContentChar = !tabStop char:. { return char; } -placeholderContent = content:(tabStop / placeholderContentText)* { return content; } -placeholderContentText = text:placeholderContentChar+ { return text.join(''); } -placeholderContentChar = !tabStop char:[^}] { return char; } - tabStop = simpleTabStop / tabStopWithPlaceholder simpleTabStop = '$' index:[0-9]+ { return { index: parseInt(index), content: [] }; @@ -13,3 +9,13 @@ simpleTabStop = '$' index:[0-9]+ { tabStopWithPlaceholder = '${' index:[0-9]+ ':' content:placeholderContent '}' { return { index: parseInt(index), content: content }; } +placeholderContent = content:(tabStop / variable / placeholderContentText)* { return content; } +placeholderContentText = text:placeholderContentChar+ { return text.join(''); } +placeholderContentChar = !tabStop !variable char:[^}] { return char; } + +variable = '${' variableContent '}' { + return ''; // we eat variables and do nothing with them for now +} +variableContent = content:(variable / variableContentText)* { return content; } +variableContentText = text:variableContentChar+ { return text.join(''); } +variableContentChar = !variable char:[^}] { return char; } diff --git a/src/packages/snippets/src/snippet-expansion.coffee b/src/packages/snippets/src/snippet-expansion.coffee index 74dcd5d6f..9c2187af9 100644 --- a/src/packages/snippets/src/snippet-expansion.coffee +++ b/src/packages/snippets/src/snippet-expansion.coffee @@ -11,13 +11,15 @@ class SnippetExpansion @editSession.selectToBeginningOfWord() startPosition = @editSession.getCursorBufferPosition() @editSession.transact => - @editSession.insertText(snippet.body, autoIndent: false) - editSession.pushOperation - do: => - @subscribe @editSession, 'cursor-moved.snippet-expansion', (e) => @cursorMoved(e) - @placeTabStopAnchorRanges(startPosition, snippet.tabStops) - @editSession.snippetExpansion = this - undo: => @destroy() + [newRange] = @editSession.insertText(snippet.body, autoIndent: false) + if snippet.tabStops.length > 0 + editSession.pushOperation + do: => + @subscribe @editSession, 'cursor-moved.snippet-expansion', (e) => @cursorMoved(e) + @placeTabStopAnchorRanges(startPosition, snippet.tabStops) + @editSession.snippetExpansion = this + undo: => @destroy() + @editSession.normalizeTabsInBufferRange(newRange) @indentSubsequentLines(startPosition.row, snippet) if snippet.lineCount > 1 cursorMoved: ({oldBufferPosition, newBufferPosition}) -> @@ -29,8 +31,6 @@ class SnippetExpansion @destroy() unless _.intersect(oldTabStops, newTabStops).length placeTabStopAnchorRanges: (startPosition, tabStopRanges) -> - return unless @snippet.tabStops.length > 0 - @tabStopAnchorRanges = tabStopRanges.map ({start, end}) => anchorRange = @editSession.addAnchorRange([startPosition.add(start), startPosition.add(end)]) @subscribe anchorRange, 'destroyed', => @@ -38,7 +38,6 @@ class SnippetExpansion anchorRange @setTabStopIndex(0) - indentSubsequentLines: (startRow, snippet) -> initialIndent = @editSession.lineForBufferRow(startRow).match(/^\s*/)[0] for row in [startRow + 1...startRow + snippet.lineCount] diff --git a/src/packages/snippets/src/snippet.coffee b/src/packages/snippets/src/snippet.coffee index ef7c3d0aa..6e0069862 100644 --- a/src/packages/snippets/src/snippet.coffee +++ b/src/packages/snippets/src/snippet.coffee @@ -30,7 +30,7 @@ class Snippet bodyText.push(segment) segmentLines = segment.split('\n') column += segmentLines.shift().length - while nextLine = segmentLines.shift() + while (nextLine = segmentLines.shift())? row += 1 column = nextLine.length diff --git a/src/packages/snippets/src/snippets.coffee b/src/packages/snippets/src/snippets.coffee deleted file mode 100644 index 769b59aef..000000000 --- a/src/packages/snippets/src/snippets.coffee +++ /dev/null @@ -1,61 +0,0 @@ -fs = require 'fs' -PEG = require 'pegjs' -_ = require 'underscore' -SnippetExpansion = require 'snippets/src/snippet-expansion' -Snippet = require './snippet' -require './package-extensions' - -module.exports = - snippetsByExtension: {} - parser: PEG.buildParser(fs.read(require.resolve 'snippets/snippets.pegjs'), trackLineAndColumn: true) - userSnippetsDir: fs.join(config.configDirPath, 'snippets') - - activate: (@rootView) -> - window.snippets = this - @loadAll() - @rootView.on 'editor:attached', (e, editor) => @enableSnippetsInEditor(editor) - - loadAll: -> - for pack in atom.getPackages() - pack.loadSnippets() - - @loadDirectory(@userSnippetsDir) if fs.exists(@userSnippetsDir) - - loadDirectory: (snippetsDirPath) -> - for snippetsPath in fs.list(snippetsDirPath) when fs.base(snippetsPath).indexOf('.') isnt 0 - snippets.load(snippetsPath) - - load: (snippetsPath) -> - try - snippets = fs.readObject(snippetsPath) - catch e - console.warn "Error reading snippets file '#{snippetsPath}'" - @add(snippets) - - add: (snippetsBySelector) -> - for selector, snippetsByName of snippetsBySelector - snippetsByPrefix = {} - for name, attributes of snippetsByName - { prefix, body } = attributes - bodyTree = @parser.parse(body) - snippet = new Snippet({name, prefix, bodyTree}) - snippetsByPrefix[snippet.prefix] = snippet - syntax.addProperties(selector, snippets: snippetsByPrefix) - - enableSnippetsInEditor: (editor) -> - editor.command 'snippets:expand', (e) => - editSession = editor.activeEditSession - prefix = editSession.getCursor().getCurrentWordPrefix() - if snippet = syntax.getProperty(editSession.getCursorScopes(), "snippets.#{prefix}") - editSession.transact -> - new SnippetExpansion(snippet, editSession) - else - e.abortKeyBinding() - - editor.command 'snippets:next-tab-stop', (e) -> - unless editor.activeEditSession.snippetExpansion?.goToNextTabStop() - e.abortKeyBinding() - - editor.command 'snippets:previous-tab-stop', (e) -> - unless editor.activeEditSession.snippetExpansion?.goToPreviousTabStop() - e.abortKeyBinding() diff --git a/src/packages/status-bar/index.coffee b/src/packages/status-bar/index.coffee index 739dd32ad..7d05f5962 100644 --- a/src/packages/status-bar/index.coffee +++ b/src/packages/status-bar/index.coffee @@ -1 +1,6 @@ -module.exports = require 'status-bar/src/status-bar' +AtomPackage = require 'atom-package' +StatusBarView = require './src/status-bar-view' + +module.exports = +class StatusBar extends AtomPackage + activate: (rootView) -> StatusBarView.activate(rootView) diff --git a/src/packages/status-bar/spec/status-bar-spec.coffee b/src/packages/status-bar/spec/status-bar-spec.coffee index d3c9a2b7f..16e4bcc20 100644 --- a/src/packages/status-bar/spec/status-bar-spec.coffee +++ b/src/packages/status-bar/spec/status-bar-spec.coffee @@ -1,7 +1,7 @@ $ = require 'jquery' _ = require 'underscore' RootView = require 'root-view' -StatusBar = require 'status-bar' +StatusBar = require 'status-bar/src/status-bar-view' fs = require 'fs' describe "StatusBar", -> diff --git a/src/packages/status-bar/src/status-bar.coffee b/src/packages/status-bar/src/status-bar-view.coffee similarity index 97% rename from src/packages/status-bar/src/status-bar.coffee rename to src/packages/status-bar/src/status-bar-view.coffee index 2c93db40b..565532679 100644 --- a/src/packages/status-bar/src/status-bar.coffee +++ b/src/packages/status-bar/src/status-bar-view.coffee @@ -3,14 +3,14 @@ _ = require 'underscore' $ = require 'jquery' module.exports = -class StatusBar extends View +class StatusBarView extends View @activate: (rootView) -> rootView.eachEditor (editor) => @appendToEditorPane(rootView, editor) if editor.attached @appendToEditorPane: (rootView, editor) -> if pane = editor.pane() - pane.append(new StatusBar(rootView, editor)) + pane.append(new StatusBarView(rootView, editor)) @content: -> @div class: 'status-bar', => diff --git a/src/packages/status-bar/stylesheets/status-bar.css b/src/packages/status-bar/stylesheets/status-bar.css index e15105d5e..3fe635f49 100644 --- a/src/packages/status-bar/stylesheets/status-bar.css +++ b/src/packages/status-bar/stylesheets/status-bar.css @@ -1,68 +1,9 @@ .status-bar { - background-color: #303030; - border-top: 1px solid #454545; - padding: 4px 10px 3px; - font-size: 11px; - line-height: 14px; - color: #969696; position: relative; -webkit-user-select: none; cursor: default; } -.status-bar .cursor-position, -.status-bar .grammar-name { - padding-left: 10px; -} - -.status-bar .grammar-name { - cursor: pointer; -} - .status-bar .git-branch { float: right; -} - -.status-bar .branch-label { - vertical-align: baseline; -} - -.status-bar .git-status.octicons { - display: none; - padding-left: 10px; - margin-top:-2px; -} - -.status-bar .octicons:before { - font-family: 'Octicons Regular'; - font-size: 14px; - width: 14px; - height: 14px; - line-height: 14px; - -webkit-font-smoothing: antialiased; - display: inline-block; - vertical-align: middle; - margin-right: 5px; -} - -.status-bar .branch-icon:before { - content: "\f020"; -} - -.status-bar .git-status.octicons.modified-status-icon { - color: #f78a46; - display: inline-block; -} - -.status-bar .modified-status-icon:before { - content: "\f26d"; -} - -.status-bar .git-status.octicons.new-status-icon { - color: #5293d8; - display: inline-block; -} - -.status-bar .new-status-icon:before { - content: "\f26b"; -} +} \ No newline at end of file diff --git a/src/packages/strip-trailing-whitespace/index.coffee b/src/packages/strip-trailing-whitespace/index.coffee index e0caa961b..20b3e6d74 100644 --- a/src/packages/strip-trailing-whitespace/index.coffee +++ b/src/packages/strip-trailing-whitespace/index.coffee @@ -1 +1,19 @@ -module.exports = require 'strip-trailing-whitespace/src/strip-trailing-whitespace' +AtomPackage = require 'atom-package' + +module.exports = +class StripTrailingWhitespace extends AtomPackage + activate: (rootView) -> + rootView.eachBuffer (buffer) => @stripTrailingWhitespaceBeforeSave(buffer) + + stripTrailingWhitespaceBeforeSave: (buffer) -> + buffer.on 'will-be-saved', -> + buffer.transact -> + buffer.scan /[ \t]+$/g, (match, range, { replace }) -> + replace('') + if config.get('stripTrailingWhitespace.singleTrailingNewline') + if buffer.getLastLine() is '' + row = buffer.getLastRow() - 1 + while row and buffer.lineForRow(row) is '' + buffer.deleteRow(row--) + else + buffer.append('\n') diff --git a/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee b/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee index 9b5f7a304..c7e6bc990 100644 --- a/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee +++ b/src/packages/strip-trailing-whitespace/spec/strip-trailing-whitespace-spec.coffee @@ -1,4 +1,3 @@ -StripTrailingWhitespace = require 'strip-trailing-whitespace' RootView = require 'root-view' fs = require 'fs' @@ -10,7 +9,7 @@ describe "StripTrailingWhitespace", -> fs.write(path, "") rootView = new RootView(path) - StripTrailingWhitespace.activate(rootView) + atom.loadPackage('strip-trailing-whitespace') rootView.focus() editor = rootView.getActiveEditor() diff --git a/src/packages/strip-trailing-whitespace/src/strip-trailing-whitespace.coffee b/src/packages/strip-trailing-whitespace/src/strip-trailing-whitespace.coffee deleted file mode 100644 index bf01c6bbe..000000000 --- a/src/packages/strip-trailing-whitespace/src/strip-trailing-whitespace.coffee +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = - activate: (rootView) -> - rootView.eachBuffer (buffer) => @stripTrailingWhitespaceBeforeSave(buffer) - - stripTrailingWhitespaceBeforeSave: (buffer) -> - buffer.on 'will-be-saved', -> - buffer.transact -> - buffer.scan /[ \t]+$/g, (match, range, { replace }) -> - replace('') - if config.get('stripTrailingWhitespace.singleTrailingNewline') - if buffer.getLastLine() is '' - row = buffer.getLastRow() - 1 - while row and buffer.lineForRow(row) is '' - buffer.deleteRow(row--) - else - buffer.append('\n') diff --git a/src/packages/symbols-view/index.coffee b/src/packages/symbols-view/index.coffee new file mode 100644 index 000000000..50d9a89c0 --- /dev/null +++ b/src/packages/symbols-view/index.coffee @@ -0,0 +1,21 @@ +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class Symbols extends DeferredAtomPackage + + loadEvents: [ + 'symbols-view:toggle-file-symbols' + 'symbols-view:toggle-project-symbols' + 'symbols-view:go-to-declaration' + ] + + instanceClass: 'symbols-view/src/symbols-view' + + onLoadEvent: (event, instance) -> + switch event.type + when 'symbols-view:toggle-file-symbols' + instance.toggleFileSymbols() + when 'symbols-view:toggle-project-symbols' + instance.toggleProjectSymbols() + when 'symbols-view:go-to-declaration' + instance.goToDeclaration() diff --git a/src/packages/symbols-view/keymaps/symbols-view.cson b/src/packages/symbols-view/keymaps/symbols-view.cson new file mode 100644 index 000000000..1e579abe0 --- /dev/null +++ b/src/packages/symbols-view/keymaps/symbols-view.cson @@ -0,0 +1,6 @@ +'.editor': + 'meta-j': 'symbols-view:toggle-file-symbols' + 'meta-.': 'symbols-view:go-to-declaration' + +'body': + 'meta-J': 'symbols-view:toggle-project-symbols' diff --git a/src/packages/symbols-view/spec/symbols-view-spec.coffee b/src/packages/symbols-view/spec/symbols-view-spec.coffee new file mode 100644 index 000000000..89476c8d5 --- /dev/null +++ b/src/packages/symbols-view/spec/symbols-view-spec.coffee @@ -0,0 +1,189 @@ +RootView = require 'root-view' +SymbolsView = require 'symbols-view/src/symbols-view' +TagGenerator = require 'symbols-view/src/tag-generator' +fs = require 'fs' + +describe "SymbolsView", -> + [rootView, symbolsView, setArraySpy] = [] + + beforeEach -> + rootView = new RootView(require.resolve('fixtures')) + symbolsView = atom.loadPackage("symbols-view").getInstance() + rootView.attachToDom() + setArraySpy = spyOn(symbolsView, 'setArray').andCallThrough() + + afterEach -> + rootView.deactivate() + setArraySpy.reset() + + describe "when tags can be generated for a file", -> + it "initially displays all JavaScript functions with line numbers", -> + rootView.open('sample.js') + expect(rootView.find('.symbols-view')).not.toExist() + rootView.getActiveEditor().trigger "symbols-view:toggle-file-symbols" + expect(symbolsView.find('.loading')).toHaveText 'Generating symbols...' + + waitsFor -> + setArraySpy.callCount > 0 + + runs -> + expect(symbolsView.find('.loading')).toBeEmpty() + expect(rootView.find('.symbols-view')).toExist() + expect(symbolsView.list.children('li').length).toBe 2 + expect(symbolsView.list.children('li:first').find('.function-name')).toHaveText 'quicksort' + expect(symbolsView.list.children('li:first').find('.function-details')).toHaveText 'Line 1' + expect(symbolsView.list.children('li:last').find('.function-name')).toHaveText 'quicksort.sort' + expect(symbolsView.list.children('li:last').find('.function-details')).toHaveText 'Line 2' + expect(symbolsView).not.toHaveClass "error" + expect(symbolsView.error).not.toBeVisible() + + it "displays error when no tags match text in mini-editor", -> + rootView.open('sample.js') + expect(rootView.find('.symbols-view')).not.toExist() + rootView.getActiveEditor().trigger "symbols-view:toggle-file-symbols" + + waitsFor -> + setArraySpy.callCount > 0 + + runs -> + symbolsView.miniEditor.setText("nothing will match this") + window.advanceClock(symbolsView.inputThrottle) + + expect(rootView.find('.symbols-view')).toExist() + expect(symbolsView.list.children('li').length).toBe 0 + expect(symbolsView.error).toBeVisible() + expect(symbolsView.error.text().length).toBeGreaterThan 0 + expect(symbolsView).toHaveClass "error" + + # Should remove error + symbolsView.miniEditor.setText("") + window.advanceClock(symbolsView.inputThrottle) + + expect(symbolsView.list.children('li').length).toBe 2 + expect(symbolsView).not.toHaveClass "error" + expect(symbolsView.error).not.toBeVisible() + + describe "when tags can't be generated for a file", -> + it "shows an error message when no matching tags are found", -> + rootView.open('sample.txt') + expect(rootView.find('.symbols-view')).not.toExist() + rootView.getActiveEditor().trigger "symbols-view:toggle-file-symbols" + setErrorSpy = spyOn(symbolsView, "setError").andCallThrough() + + waitsFor -> + setErrorSpy.callCount > 0 + + runs -> + expect(rootView.find('.symbols-view')).toExist() + expect(symbolsView.list.children('li').length).toBe 0 + expect(symbolsView.error).toBeVisible() + expect(symbolsView.error.text().length).toBeGreaterThan 0 + expect(symbolsView).toHaveClass "error" + expect(symbolsView.find('.loading')).not.toBeVisible() + + it "moves the cursor to the selected function", -> + tags = [] + waitsForPromise -> + tags = [] + path = require.resolve('fixtures/sample.js') + callback = (tag) -> + tags.push tag + generator = new TagGenerator(path, callback) + generator.generate() + + runs -> + rootView.open('sample.js') + expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [0,0] + expect(rootView.find('.symbols-view')).not.toExist() + symbolsView.setArray(tags) + symbolsView.attach() + expect(rootView.find('.symbols-view')).toExist() + symbolsView.confirmed(tags[1]) + expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [1,2] + + describe "TagGenerator", -> + it "generates tags for all JavaScript functions", -> + waitsForPromise -> + tags = [] + path = require.resolve('fixtures/sample.js') + callback = (tag) -> + tags.push tag + generator = new TagGenerator(path, callback) + generator.generate().done -> + expect(tags.length).toBe 2 + expect(tags[0].name).toBe "quicksort" + expect(tags[0].position.row).toBe 0 + expect(tags[1].name).toBe "quicksort.sort" + expect(tags[1].position.row).toBe 1 + + it "generates no tags for text file", -> + waitsForPromise -> + tags = [] + path = require.resolve('fixtures/sample.txt') + callback = (tag) -> + tags.push tag + generator = new TagGenerator(path, callback) + generator.generate().done -> + expect(tags.length).toBe 0 + + describe "go to declaration", -> + it "doesn't move the cursor when no declaration is found", -> + rootView.open("tagged.js") + editor = rootView.getActiveEditor() + editor.setCursorBufferPosition([0,2]) + editor.trigger 'symbols-view:go-to-declaration' + expect(editor.getCursorBufferPosition()).toEqual [0,2] + + it "moves the cursor to the declaration", -> + rootView.open("tagged.js") + editor = rootView.getActiveEditor() + editor.setCursorBufferPosition([6,24]) + editor.trigger 'symbols-view:go-to-declaration' + expect(editor.getCursorBufferPosition()).toEqual [2,0] + + it "displays matches when more than one exists and opens the selected match", -> + rootView.open("tagged.js") + editor = rootView.getActiveEditor() + editor.setCursorBufferPosition([8,14]) + editor.trigger 'symbols-view:go-to-declaration' + expect(symbolsView.list.children('li').length).toBe 2 + expect(symbolsView).toBeVisible() + symbolsView.confirmed(symbolsView.array[0]) + expect(rootView.getActiveEditor().getPath()).toBe rootView.project.resolve("tagged-duplicate.js") + expect(rootView.getActiveEditor().getCursorBufferPosition()).toEqual [0,4] + + describe "when the tag is in a file that doesn't exist", -> + beforeEach -> + fs.move(rootView.project.resolve("tagged-duplicate.js"), rootView.project.resolve("tagged-duplicate-renamed.js")) + + afterEach -> + fs.move(rootView.project.resolve("tagged-duplicate-renamed.js"), rootView.project.resolve("tagged-duplicate.js")) + + it "doesn't display the tag", -> + rootView.open("tagged.js") + editor = rootView.getActiveEditor() + editor.setCursorBufferPosition([8,14]) + editor.trigger 'symbols-view:go-to-declaration' + expect(symbolsView.list.children('li').length).toBe 1 + expect(symbolsView.list.children('li:first').find('.function-name')).toHaveText 'tagged.js' + + describe "project symbols", -> + it "displays all tags", -> + rootView.open("tagged.js") + expect(rootView.find('.symbols-view')).not.toExist() + rootView.trigger "symbols-view:toggle-project-symbols" + expect(symbolsView.find('.loading')).toHaveText 'Loading symbols...' + + waitsFor -> + setArraySpy.callCount > 0 + + runs -> + expect(symbolsView.find('.loading')).toBeEmpty() + expect(rootView.find('.symbols-view')).toExist() + expect(symbolsView.list.children('li').length).toBe 4 + expect(symbolsView.list.children('li:first').find('.function-name')).toHaveText 'callMeMaybe' + expect(symbolsView.list.children('li:first').find('.function-details')).toHaveText 'tagged.js' + expect(symbolsView.list.children('li:last').find('.function-name')).toHaveText 'thisIsCrazy' + expect(symbolsView.list.children('li:last').find('.function-details')).toHaveText 'tagged.js' + expect(symbolsView).not.toHaveClass "error" + expect(symbolsView.error).not.toBeVisible() diff --git a/src/packages/outline-view/src/outline-view.coffee b/src/packages/symbols-view/src/symbols-view.coffee similarity index 76% rename from src/packages/outline-view/src/outline-view.coffee rename to src/packages/symbols-view/src/symbols-view.coffee index fadd4e788..c0d019132 100644 --- a/src/packages/outline-view/src/outline-view.coffee +++ b/src/packages/symbols-view/src/symbols-view.coffee @@ -1,21 +1,18 @@ {$$} = require 'space-pen' SelectList = require 'select-list' -TagGenerator = require 'outline-view/src/tag-generator' -TagReader = require 'outline-view/src/tag-reader' +TagGenerator = require 'symbols-view/src/tag-generator' +TagReader = require 'symbols-view/src/tag-reader' Point = require 'point' fs = require 'fs' $ = require 'jquery' module.exports = -class OutlineView extends SelectList +class SymbolsView extends SelectList @activate: (rootView) -> - @instance = new OutlineView(rootView) - rootView.command 'outline-view:toggle-file-outline', => @instance.toggleFileOutline() - rootView.command 'outline-view:toggle-project-outline', => @instance.toggleProjectOutline() - rootView.command 'outline-view:jump-to-declaration', => @instance.jumpToDeclaration() + @instance = new SymbolsView(rootView) - @viewClass: -> "#{super} outline-view" + @viewClass: -> "#{super} symbols-view" filterKey: 'name' @@ -34,14 +31,14 @@ class OutlineView extends SelectList @div text, class: 'function-details' @div class: 'clear-float' - toggleFileOutline: -> + toggleFileSymbols: -> if @hasParent() @cancel() else - @populateFileOutline() + @populateFileSymbols() @attach() - populateFileOutline: -> + populateFileSymbols: -> tags = [] callback = (tag) -> tags.push tag path = @rootView.getActiveEditor().getPath() @@ -56,14 +53,14 @@ class OutlineView extends SelectList @setError("No symbols found") setTimeout (=> @detach()), 2000 - toggleProjectOutline: -> + toggleProjectSymbols: -> if @hasParent() @cancel() else - @populateProjectOutline() + @populateProjectSymbols() @attach() - populateProjectOutline: -> + populateProjectSymbols: -> @setLoading("Loading symbols...") TagReader.getAllTags(@rootView.project).done (tags) => if tags.length > 0 @@ -91,21 +88,21 @@ class OutlineView extends SelectList editor.setCursorBufferPosition(position) editor.moveCursorToFirstCharacterOfLine() - cancelled: -> - @miniEditor.setText('') - @rootView.focus() if @miniEditor.isFocused - attach: -> + super + @rootView.append(this) @miniEditor.focus() getTagLine: (tag) -> pattern = $.trim(tag.pattern?.replace(/(^^\/\^)|(\$\/$)/g, '')) # Remove leading /^ and trailing $/ return unless pattern - for line, index in fs.read(@rootView.project.resolve(tag.file)).split('\n') + file = @rootView.project.resolve(tag.file) + return unless fs.isFile(file) + for line, index in fs.read(file).split('\n') return new Point(index, 0) if pattern is $.trim(line) - jumpToDeclaration: -> + goToDeclaration: -> editor = @rootView.getActiveEditor() matches = TagReader.find(editor) return unless matches.length diff --git a/src/packages/outline-view/src/tag-generator.coffee b/src/packages/symbols-view/src/tag-generator.coffee similarity index 100% rename from src/packages/outline-view/src/tag-generator.coffee rename to src/packages/symbols-view/src/tag-generator.coffee diff --git a/src/packages/outline-view/src/tag-reader.coffee b/src/packages/symbols-view/src/tag-reader.coffee similarity index 100% rename from src/packages/outline-view/src/tag-reader.coffee rename to src/packages/symbols-view/src/tag-reader.coffee diff --git a/src/packages/tabs/index.coffee b/src/packages/tabs/index.coffee index 8b5de5d05..58a88c08a 100644 --- a/src/packages/tabs/index.coffee +++ b/src/packages/tabs/index.coffee @@ -1 +1,6 @@ -module.exports = require 'tabs/src/tabs' +AtomPackage = require 'atom-package' +TabsView = require './src/tabs-view' + +module.exports = +class Tabs extends AtomPackage + activate: (rootView) -> TabsView.activate(rootView) diff --git a/src/packages/tabs/spec/tabs-spec.coffee b/src/packages/tabs/spec/tabs-spec.coffee index c002ba04d..c3055d081 100644 --- a/src/packages/tabs/spec/tabs-spec.coffee +++ b/src/packages/tabs/spec/tabs-spec.coffee @@ -75,6 +75,14 @@ describe "Tabs", -> tabs.find('.tab:eq(1)').click() expect(editor.getActiveEditSessionIndex()).toBe 1 + it "focuses the associated editor", -> + rootView.attachToDom() + expect(editor).toMatchSelector ":has(:focus)" + editor.splitRight() + expect(editor).not.toMatchSelector ":has(:focus)" + tabs.find('.tab:eq(0)').click() + expect(editor).toMatchSelector ":has(:focus)" + describe "when a file name associated with a tab changes", -> [buffer, oldPath, newPath] = [] diff --git a/src/packages/tabs/src/tabs.coffee b/src/packages/tabs/src/tabs-view.coffee similarity index 98% rename from src/packages/tabs/src/tabs.coffee rename to src/packages/tabs/src/tabs-view.coffee index 98212f426..e7322dc64 100644 --- a/src/packages/tabs/src/tabs.coffee +++ b/src/packages/tabs/src/tabs-view.coffee @@ -26,6 +26,7 @@ class Tabs extends View @on 'click', '.tab', (e) => @editor.setActiveEditSessionIndex($(e.target).closest('.tab').index()) + @editor.focus() @on 'click', '.tab .close-icon', (e) => index = $(e.target).closest('.tab').index() diff --git a/src/packages/tabs/stylesheets/tabs.css b/src/packages/tabs/stylesheets/tabs.css index 02650af58..ebdfad7f2 100644 --- a/src/packages/tabs/stylesheets/tabs.css +++ b/src/packages/tabs/stylesheets/tabs.css @@ -1,143 +1,33 @@ .tabs { - background: #333333; - border-bottom: 4px solid #424242; - font: caption; -webkit-user-select: none; - user-select: none; + display: -webkit-box; + -webkit-box-align: center; } .tab { - cursor: default; - padding: 2px 21px 2px 9px; - background-image: -webkit-linear-gradient(#444, #3d3d3d); - display: table-cell; + -webkit-box-flex: 2; position: relative; - width:175px; - border-top: 1px solid #383838; - border-right: 1px solid #2e2e2e; - border-bottom: 1px solid #2e2e2e; - box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a, inset 1px 0 0 #4a4a4a; + width: 175px; + max-width: 175px; min-width: 40px; box-sizing: border-box; - height: 24px; } -.tab, -.tab .close-icon { - color: #aaa; +.tab.active { + -webkit-box-flex: 1; } .tab.file-modified .close-icon { - border-color: #aaa; -} - -.tab.active, -.tab.active:hover, -.tab.active .close-icon { - color: #e6e6e6; -} - -.tab.file-modified.active .close-icon { - border-color: #e6e6e6; -} - -.tab:hover .close-icon { - color: #c8c8c8; - border-color: #c8c8c8; -} - -.tab.file-modified .close-icon { - border: 3px solid #777; top: 6px; - border-radius: 10px; width: 5px; height: 5px; right: 5px; } -.tab.file-modified .close-icon:before { - content: ""; -} - -.tab:first-child { - box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a; -} - -.tab.active:first-child, -.tab.active:first-child:hover { - box-shadow: inset -1px 0 0 #595959; -} - -.tab.active, -.tab.active:hover { - border-top: 1px solid #4a4a4a; - box-shadow: inset -1px 0 0 #595959, inset 1px 0 0 #595959; - border-bottom: 0 none; - background-image: -webkit-linear-gradient(#555555, #424242); -} - -.tab.active:before, -.tab.active:after { - position: absolute; - bottom: -1px; - width: 4px; - height: 4px; - content: " "; - z-index: 3; - border: 1px solid #595959; -} -.tab.active:before { - border-bottom-right-radius: 4px; - border-width: 0 1px 1px 0; - box-shadow: 2px 2px 0 #424242; - left: -4px; -} -.tab.active:after { - right: -4px; - border-bottom-left-radius: 4px; - border-width: 0 0 1px 1px; - box-shadow: -2px 2px 0 #424242; -} -.tab.active:first-child:before { - display: none; -} - -.tab:hover { - color: #c8c8c8; - background-image: -webkit-linear-gradient(#474747, #444444); -} - .tab .file-name { - font-size: 11px; display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; - text-shadow: 0 -1px 1px black; - position: absolute; - left: 9px; - top:4px; - bottom:4px; - right: 21px; -} - -.tab .close-icon { - font-family: 'Octicons Regular'; - font-size: 14px; - width: 14px; - height: 14px; - display: block; - cursor: pointer; - position: absolute; - right: 4px; - top: -1px; - -webkit-font-smoothing: antialiased; -} - -.tab .close-icon:before { - content: "\f081"; -} - -.tab .close-icon:hover { - color: white; -} + padding: 3px 5px; +} \ No newline at end of file diff --git a/src/packages/tree-view/index.coffee b/src/packages/tree-view/index.coffee index a57ff5b90..b2228f183 100644 --- a/src/packages/tree-view/index.coffee +++ b/src/packages/tree-view/index.coffee @@ -1 +1,26 @@ -module.exports = require 'tree-view/src/tree-view' +DeferredAtomPackage = require 'deferred-atom-package' + +module.exports = +class Tree extends DeferredAtomPackage + + loadEvents: [ + 'tree-view:toggle' + 'tree-view:reveal-active-file' + ] + + instanceClass: 'tree-view/src/tree-view' + + activate: (rootView, state) -> + super + + if state + @getInstance().attach() if state.attached + else if rootView.project.getPath() and not rootView.pathToOpenIsFile + @getInstance().attach() + + onLoadEvent: (event, instance) -> + switch event.type + when 'tree-view:toggle' + instance.toggle() + when 'tree-view:reveal-active-file' + instance.revealActiveFile() diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee index c06a1cf44..c788842bf 100644 --- a/src/packages/tree-view/spec/tree-view-spec.coffee +++ b/src/packages/tree-view/spec/tree-view-spec.coffee @@ -1,6 +1,6 @@ $ = require 'jquery' _ = require 'underscore' -TreeView = require 'tree-view' +TreeView = require 'tree-view/src/tree-view' RootView = require 'root-view' Directory = require 'directory' Native = require 'native' @@ -13,9 +13,8 @@ describe "TreeView", -> rootView = new RootView(require.resolve('fixtures/tree-view')) project = rootView.project - atom.loadPackage("tree-view") - treeView = TreeView.instance - treeView.root = treeView.find('> li:first').view() + treeView = atom.loadPackage("tree-view").getInstance() + treeView.root = treeView.find('ol > li:first').view() sampleJs = treeView.find('.file:contains(tree-view.js)') sampleTxt = treeView.find('.file:contains(tree-view.txt)') @@ -51,8 +50,7 @@ describe "TreeView", -> rootView.deactivate() rootView = new RootView - atom.loadPackage 'tree-view' - treeView = TreeView.instance + treeView = atom.loadPackage("tree-view").getInstance() it "does not attach to the root view or create a root node when initialized", -> expect(treeView.hasParent()).toBeFalsy() @@ -78,8 +76,7 @@ describe "TreeView", -> rootView.deactivate() rootView = new RootView(require.resolve('fixtures/tree-view/tree-view.js')) - atom.loadPackage 'tree-view' - treeView = TreeView.instance + treeView = atom.loadPackage("tree-view").getInstance() it "does not attach to the root view but does create a root node when initialized", -> expect(treeView.hasParent()).toBeFalsy() @@ -108,7 +105,7 @@ describe "TreeView", -> it "restores the focus state of the tree view", -> rootView.attachToDom() treeView.focus() - expect(treeView).toMatchSelector ':focus' + expect(treeView.find(".tree-view")).toMatchSelector ':focus' newRootView = RootView.deserialize(rootView.serialize()) rootView.deactivate() # Deactivates previous TreeView @@ -117,7 +114,7 @@ describe "TreeView", -> newRootView.activatePackage('tree-view', TreeView) newTreeView = newRootView.find(".tree-view").view() - expect(newTreeView).toMatchSelector ':focus' + expect(newTreeView.find(".tree-view")).toMatchSelector ':focus' it "restores the scroll top when toggled", -> rootView.height(5) @@ -154,14 +151,14 @@ describe "TreeView", -> rootView.focus() rootView.trigger 'tree-view:toggle' expect(treeView).toBeVisible() - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') describe "when the tree view is hidden", -> it "shows and focuses the tree view", -> treeView.detach() rootView.trigger 'tree-view:toggle' expect(treeView.hasParent()).toBeTruthy() - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') describe "when tree-view:reveal-current-file is triggered on the root view", -> beforeEach -> @@ -196,10 +193,10 @@ describe "TreeView", -> rootView.open() # When we trigger 'tool-panel:unfocus' below, we want an editor to become focused rootView.attachToDom() treeView.focus() - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') treeView.trigger 'tool-panel:unfocus' expect(treeView).toBeVisible() - expect(treeView).not.toMatchSelector(':focus') + expect(treeView.find(".tree-view")).not.toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeTruthy() describe "when core:close is triggered on the tree view", -> @@ -434,7 +431,7 @@ describe "TreeView", -> treeView.height(100) treeView.attachToDom() $(element).view().expand() for element in treeView.find('.directory') - expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight() + expect(treeView.find(".tree-view").prop('scrollHeight')).toBeGreaterThan treeView.find(".tree-view").outerHeight() expect(treeView.scrollTop()).toBe 0 @@ -458,11 +455,11 @@ describe "TreeView", -> treeView.height(100) treeView.attachToDom() $(element).view().expand() for element in treeView.find('.directory') - expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight() + expect(treeView.find(".tree-view").prop('scrollHeight')).toBeGreaterThan treeView.find(".tree-view").outerHeight() expect(treeView.scrollTop()).toBe 0 treeView.trigger 'core:move-to-bottom' - expect(treeView.scrollBottom()).toBe treeView.prop('scrollHeight') + expect(treeView.scrollBottom()).toBe treeView.find(".tree-view").prop('scrollHeight') it "selects the last entry", -> expect(treeView.root).toHaveClass 'selected' @@ -474,7 +471,7 @@ describe "TreeView", -> treeView.height(5) treeView.attachToDom() $(element).view().expand() for element in treeView.find('.directory') - expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight() + expect(treeView.find(".tree-view").prop('scrollHeight')).toBeGreaterThan treeView.find(".tree-view").outerHeight() expect(treeView.scrollTop()).toBe 0 treeView.scrollToBottom() @@ -489,7 +486,7 @@ describe "TreeView", -> treeView.height(5) treeView.attachToDom() $(element).view().expand() for element in treeView.find('.directory') - expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight() + expect(treeView.find(".tree-view").prop('scrollHeight')).toBeGreaterThan treeView.find(".tree-view").outerHeight() expect(treeView.scrollTop()).toBe 0 treeView.trigger 'core:page-down' @@ -500,14 +497,14 @@ describe "TreeView", -> treeView.height(100) treeView.attachToDom() $(element).view().expand() for element in treeView.find('.directory') - expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight() + expect(treeView.find(".tree-view").prop('scrollHeight')).toBeGreaterThan treeView.find(".tree-view").outerHeight() treeView.moveDown() expect(treeView.scrollTop()).toBe 0 entryCount = treeView.find(".entry").length _.times entryCount, -> treeView.moveDown() - expect(treeView.scrollBottom() + 2).toBe treeView.prop('scrollHeight') + expect(treeView.scrollBottom()).toBe treeView.find(".tree-view").prop('scrollHeight') _.times entryCount, -> treeView.moveUp() expect(treeView.scrollTop()).toBe 0 @@ -687,7 +684,7 @@ describe "TreeView", -> expect(fs.isDirectory(newPath)).toBeTruthy() expect(addDialog.parent()).not.toExist() expect(rootView.getActiveEditor().getPath()).not.toBe newPath - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeFalsy() expect(dirView.find('.directory.selected:contains(new)').length).toBe(1) @@ -700,7 +697,7 @@ describe "TreeView", -> expect(fs.isDirectory(newPath)).toBeTruthy() expect(addDialog.parent()).not.toExist() expect(rootView.getActiveEditor().getPath()).not.toBe newPath - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeFalsy() expect(dirView.find('.directory.selected:contains(new2)').length).toBe(1) @@ -721,7 +718,7 @@ describe "TreeView", -> treeView.attachToDom() addDialog.trigger 'core:cancel' expect(addDialog.parent()).not.toExist() - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') describe "when the add dialog's editor loses focus", -> it "removes the dialog and focuses root view", -> @@ -835,7 +832,7 @@ describe "TreeView", -> treeView.attachToDom() moveDialog.trigger 'core:cancel' expect(moveDialog.parent()).not.toExist() - expect(treeView).toMatchSelector(':focus') + expect(treeView.find(".tree-view")).toMatchSelector(':focus') describe "when the move dialog's editor loses focus", -> it "removes the dialog and focuses root view", -> diff --git a/src/packages/tree-view/src/tree-view.coffee b/src/packages/tree-view/src/tree-view.coffee index 8811d2718..038f3d6bc 100644 --- a/src/packages/tree-view/src/tree-view.coffee +++ b/src/packages/tree-view/src/tree-view.coffee @@ -17,9 +17,6 @@ class TreeView extends ScrollView else @instance = new TreeView(rootView) - if rootView.project.getPath() and not rootView.pathToOpenIsFile - @instance.attach() - @deactivate: -> @instance.deactivate() @@ -27,7 +24,8 @@ class TreeView extends ScrollView @instance.serialize() @content: (rootView) -> - @ol class: 'tree-view tool-panel', tabindex: -1, => + @div class: 'tree-view-wrapper', => + @ol class: 'tree-view tool-panel', tabindex: -1, outlet: 'treeViewList' @div class: 'tree-view-resizer', outlet: 'resizer' @deserialize: (state, rootView) -> @@ -64,8 +62,7 @@ class TreeView extends ScrollView @selectEntryForPath(@selectedPath) if @selectedPath else @selectActiveFile() - @rootView.command 'tree-view:toggle', => @toggle() - @rootView.command 'tree-view:reveal-active-file', => @revealActiveFile() + @rootView.on 'root-view:active-path-changed', => @selectActiveFile() @rootView.project.on 'path-changed', => @updateRoot() @observeConfig 'core.hideGitIgnoredFiles', => @updateRoot() @@ -106,8 +103,11 @@ class TreeView extends ScrollView super @rootView.focus() + focus: -> + @treeViewList.focus() + hasFocus: -> - @is(':focus') + @treeViewList.is(':focus') entryClicked: (e) -> entry = $(e.currentTarget).view() @@ -135,13 +135,12 @@ class TreeView extends ScrollView resizeTreeView: (e) => @css(width: e.pageX) - @resizer.css(left: e.pageX) updateRoot: -> @root?.remove() if rootDirectory = @rootView.project.getRootDirectory() @root = new DirectoryView(directory: rootDirectory, isExpanded: true, project: @rootView.project) - @append(@root) + @treeViewList.append(@root) else @root = null @@ -164,6 +163,7 @@ class TreeView extends ScrollView entry.expand() else @selectEntry(entry) + @scrollToEntry(entry) entryForPath: (path) -> fn = (bestMatchEntry, element) -> @@ -174,7 +174,7 @@ class TreeView extends ScrollView else bestMatchEntry - @find(".entry").toArray().reduce(fn, @root) + @treeViewList.find(".entry").toArray().reduce(fn, @root) selectEntryForPath: (path) -> @selectEntry(@entryForPath(path)) @@ -201,7 +201,7 @@ class TreeView extends ScrollView else @selectEntry(selectedEntry.parents('.directory').first()) else - @selectEntry(@find('.entry').last()) + @selectEntry(@treeViewList.find('.entry').last()) @scrollToEntry(@selectedEntry()) @@ -295,32 +295,43 @@ class TreeView extends ScrollView @rootView.append(dialog) selectedEntry: -> - @find('.selected')?.view() + @treeViewList.find('.selected')?.view() selectEntry: (entry) -> return false unless entry.get(0) entry = entry.view() unless entry instanceof View @selectedPath = entry.getPath() - @find('.selected').removeClass('selected') + @treeViewList.find('.selected').removeClass('selected') entry.addClass('selected') + scrollTop: (top) -> + if top + @treeViewList.scrollTop(top) + else + @treeViewList.scrollTop() + + scrollBottom: (bottom) -> + if bottom + @treeViewList.scrollBottom(bottom) + else + @treeViewList.scrollBottom() + scrollToEntry: (entry) -> displayElement = if entry instanceof DirectoryView then entry.header else entry - top = @scrollTop() + displayElement.position().top bottom = top + displayElement.outerHeight() - if bottom > @scrollBottom() - @scrollBottom(bottom) + @treeViewList.scrollBottom(bottom) if top < @scrollTop() - @scrollTop(top) + @treeViewList.scrollTop(top) scrollToBottom: -> super() @selectEntry(@root.find('.entry:last')) if @root + @scrollToEntry(@root.find('.entry:last')) if @root scrollToTop: -> super() - @selectEntry(@root) if @root + @treeViewList.scrollTop(0) diff --git a/src/packages/tree-view/stylesheets/tree-view.css b/src/packages/tree-view/stylesheets/tree-view.css index 6376a0c09..723b85f2e 100644 --- a/src/packages/tree-view/stylesheets/tree-view.css +++ b/src/packages/tree-view/stylesheets/tree-view.css @@ -1,211 +1,57 @@ -.tree-view { +.tree-view-wrapper { position: relative; height: 100%; - background: #1e1e1e; - overflow: auto; cursor: default; -webkit-user-select: none; - border-right: 2px solid #191919; - min-width: 100px; + min-width: 50px; z-index: 2; } -.tree-view .tree-view-resizer { - float: right; +.tree-view { + position: relative; + cursor: default; + -webkit-user-select: none; + overflow: auto; height: 100%; +} + +.tree-view-wrapper .tree-view-resizer { + position: absolute; + top: 0; + right: 0; + bottom: 0; width: 10px; - background: transparent; cursor: col-resize; + z-index: 3; } .tree-view .entry { - text-shadow: 0 -1px 0 #000; text-wrap: none; white-space: nowrap; } -.tree-view .entries { - margin-left: 12px; -} - -.tree-view .entries .file .name { - margin-left: 15px; -} - -.tree-view .directory.selected > .header > .name, -.tree-view .selected > .name { - color: #d2d2d2; +.tree-view .entry > .header, +.tree-view .entry > .name { + z-index: 1; + position: relative; + display: inline-block; } .tree-view .selected > .highlight { - background-image: -webkit-linear-gradient(#4e4e4e, #434343); position: absolute; left: 0; right: 0; height: 24px; - margin-top:-24px; - z-index: -1; -} - -.tree-view:focus .selected > .highlight { - background-image: -webkit-linear-gradient(#7e7e7e, #737373); -} - -.tree-view:focus .directory.selected > .header > .name, -.tree-view:focus .selected > .name { - color: #fff; - text-shadow: 0 -1px 0 #7E4521; -} - -.tree-view .entry.file .name { - display: block; } .tree-view .disclosure-arrow { display: inline-block; } -.tree-view .directory .header { - color: #bebebe; -} - -.tree-view .file { - color: #7d7d7d; -} - -.tree-view .entry:hover, -.tree-view .directory .header:hover .name, -.tree-view .directory .header:hover .disclosure-arrow { - color: #ebebeb; -} - -.tree-view .file .name, -.tree-view .directory .header { - padding-top: 4px; - padding-bottom: 4px; - padding-right: 10px; -} - -.tree-view .ignored { - color: #555; -} - -.tree-view .modified { - color: #f78a46; -} - -.tree-view .new { - color: #5293d8; -} - .tree-view-dialog { position: absolute; bottom: 0; left: 0; right: 0; - background-color: #333; - border-top: 1px solid #555; - -webkit-box-shadow: 0 0 3px 3px rgba(0, 0, 0, .5); z-index: 99; - padding: 5px; -} - -.tree-view-dialog .prompt { - padding-bottom: 3px; - font-size: 12px; - line-height: 16px; - color: #aaa; -} - -.tree-view-dialog .prompt span { - position: relative; - top: -1px; -} - -.tree-view-dialog .prompt:before { - font-family: 'Octicons Regular'; - font-size: 16px; - width: 16px; - height: 16px; - margin-right: 3px; - -webkit-font-smoothing: antialiased; -} - -.tree-view-dialog .prompt.add:before { - content: "\f086"; -} - -.tree-view-dialog .prompt.move:before { - content: "\f03e"; -} - -.tree-view .directory .header .name, -.tree-view .file .name { - position: relative; - padding-left: 21px; -} - -.tree-view .directory .header .name:before, -.tree-view .file .name:before { - font-family: 'Octicons Regular'; - font-size: 16px; - width: 16px; - height: 16px; - margin-right: 5px; - -webkit-font-smoothing: antialiased; - position: absolute; - left: 0; -} - -.tree-view .disclosure-arrow:before { - font-family: 'Octicons Regular'; - font-size: 12px; - width: 12px; - height: 12px; - line-height: 16px; - margin-right: 3px; - -webkit-font-smoothing: antialiased; -} - -.tree-view .directory .header .directory-icon:before { - content: "\f016"; - top: -5px; -} - -.tree-view .directory .header .repository-icon:before { - content: "\f001"; - top: -4px; -} - -.tree-view .directory .header .submodule-icon:before { - content: "\f017"; - top: -5px; -} - -.tree-view .file .text-icon:before { - content: "\f011"; - top: -2px; -} - -.tree-view .file .image-icon:before { - content: "\f012"; - top: -2px; -} - -.tree-view .file .compressed-icon:before { - content: "\f013"; - top: -2px; -} - -.tree-view .file .pdf-icon:before { - content: "\f014"; - top: -2px; -} - -.tree-view .directory > .header .disclosure-arrow:before { - content: "\f05a"; -} - -.tree-view .directory.expanded > .header .disclosure-arrow:before { - content: "\f05b"; } diff --git a/src/packages/wrap-guide/index.coffee b/src/packages/wrap-guide/index.coffee index f8a95c569..1f9ab8ffd 100644 --- a/src/packages/wrap-guide/index.coffee +++ b/src/packages/wrap-guide/index.coffee @@ -1 +1,6 @@ -module.exports = require 'wrap-guide/src/wrap-guide' +AtomPackage = require 'atom-package' +WrapGuideView = require './src/wrap-guide-view' + +module.exports = +class WrapGuide extends AtomPackage + activate: (rootView) -> WrapGuideView.activate(rootView) diff --git a/src/packages/wrap-guide/src/wrap-guide.coffee b/src/packages/wrap-guide/src/wrap-guide-view.coffee similarity index 93% rename from src/packages/wrap-guide/src/wrap-guide.coffee rename to src/packages/wrap-guide/src/wrap-guide-view.coffee index ffc9a95b7..35dd192d8 100644 --- a/src/packages/wrap-guide/src/wrap-guide.coffee +++ b/src/packages/wrap-guide/src/wrap-guide-view.coffee @@ -3,14 +3,14 @@ $ = require 'jquery' _ = require 'underscore' module.exports = -class WrapGuide extends View +class WrapGuideView extends View @activate: (rootView, state) -> rootView.eachEditor (editor) => @appendToEditorPane(rootView, editor) if editor.attached @appendToEditorPane: (rootView, editor) -> if underlayer = editor.pane()?.find('.underlayer') - underlayer.append(new WrapGuide(rootView, editor)) + underlayer.append(new WrapGuideView(rootView, editor)) @content: -> @div class: 'wrap-guide' diff --git a/src/packages/wrap-guide/stylesheets/wrap-guide.css b/src/packages/wrap-guide/stylesheets/wrap-guide.css index 9f93ee19e..b73c85264 100644 --- a/src/packages/wrap-guide/stylesheets/wrap-guide.css +++ b/src/packages/wrap-guide/stylesheets/wrap-guide.css @@ -1,7 +1,6 @@ .wrap-guide { height: 100%; width: 1px; - background: rgba(150, 150, 150, .30); z-index: 100; position: absolute; top: 0px; diff --git a/src/stdlib/fs.coffee b/src/stdlib/fs.coffee index 976f3bb5f..a9eb755da 100644 --- a/src/stdlib/fs.coffee +++ b/src/stdlib/fs.coffee @@ -2,7 +2,6 @@ # http://ringojs.org/api/v0.8/fs/ _ = require 'underscore' -$ = require 'jquery' module.exports = # Make the given path absolute by resolving it against the @@ -143,7 +142,7 @@ module.exports = if extension == "" return path if @exists(path) else - pathWithExtension = path + "." + extension + pathWithExtension = path + "." + extension.replace(/^\./, "") return pathWithExtension if @exists(pathWithExtension) undefined diff --git a/src/stdlib/git-repository.coffee b/src/stdlib/git-repository.coffee new file mode 100644 index 000000000..fc03e1368 --- /dev/null +++ b/src/stdlib/git-repository.coffee @@ -0,0 +1,18 @@ +module.exports = +class GitRepository + constructor: (path) -> + unless repo = $git.getRepository(path) + throw new Error("No Git repository found searching path: " + path) + repo.constructor = GitRepository + repo.__proto__ = GitRepository.prototype + return repo + + getHead: $git.getHead + getPath: $git.getPath + getStatus: $git.getStatus + isIgnored: $git.isIgnored + checkoutHead: $git.checkoutHead + getDiffStats: $git.getDiffStats + isSubmodule: $git.isSubmodule + refreshIndex: $git.refreshIndex + destroy: $git.destroy diff --git a/src/stdlib/onig-reg-exp.coffee b/src/stdlib/onig-reg-exp.coffee new file mode 100644 index 000000000..93883da20 --- /dev/null +++ b/src/stdlib/onig-reg-exp.coffee @@ -0,0 +1,11 @@ +module.exports = +class OnigRegExp + constructor: (source) -> + regexp = $onigRegExp.buildOnigRegExp(source); + regexp.constructor = OnigRegExp + regexp.__proto__ = OnigRegExp.prototype + regexp.source = source + return regexp + + search: $onigRegExp.search + test: $onigRegExp.test diff --git a/src/stdlib/onig-scanner.coffee b/src/stdlib/onig-scanner.coffee new file mode 100644 index 000000000..fb26939ec --- /dev/null +++ b/src/stdlib/onig-scanner.coffee @@ -0,0 +1,10 @@ +module.exports = +class OnigScanner + constructor: (sources) -> + scanner = $onigScanner.buildScanner(sources) + scanner.constructor = OnigScanner + scanner.__proto__ = OnigScanner.prototype + scanner.sources = sources + return scanner + + findNextMatch: $onigScanner.findNextMatch diff --git a/src/stdlib/require.coffee b/src/stdlib/require.coffee index 1076bcc49..4a6f919aa 100644 --- a/src/stdlib/require.coffee +++ b/src/stdlib/require.coffee @@ -25,17 +25,16 @@ require = (path, cb) -> unless file = resolve(path) throw new Error("Require can't find file at path '#{path}'") - parts = file.split '.' - ext = parts[parts.length-1] + ext = file.split('.').pop() if __moduleExists file if not __modules.loaded[file.toLowerCase()]? - console.warn "Circular require: #{__filename} required #{file}" + console.warn "Circular require: #{window.__filename} required #{file}" return __modules[file] else if __modules.loaded[file.toLowerCase()] console.warn "Multiple requires (different cases) for #{file}" - [ previousFilename, window.__filename ] = [ __filename, file ] + [ previousFilename, window.__filename ] = [ window.__filename, file ] __modules[file] = {} # Fix for circular references __modules[file] = (exts[ext] or (file) -> __read file) file window.__filename = previousFilename @@ -43,33 +42,67 @@ require = (path, cb) -> define = (cb) -> __defines.push -> - exports = __modules[__filename] or {} + exports = __modules[window.__filename] or {} module = exports: exports cb.call exports, require, exports, module - __modules.loaded[__filename.toLowerCase()] = true + __modules.loaded[window.__filename.toLowerCase()] = true module.exports or exports exts = js: (file, code) -> code or= __read file - eval("define(function(require, exports, module) { 'use strict';" + code + "})\n//@ sourceURL=" + file) + eval("define(function(require, exports, module) { 'use strict';#{code}})\n//@ sourceURL=#{file}") __defines.pop()?.call() - coffee: (file) -> - exts.js(file, __coffeeCache(file)) + coffee: (file, retry=true) -> + cacheFilePath = getCacheFilePath(file) + if __exists(cacheFilePath) + compiled = __read(cacheFilePath) + writeToCache = false + else + {CoffeeScript} = require 'coffee-script' + compiled = CoffeeScript.compile(__read(file), filename: file) + writeToCache = true + + try + evaluated = exts.js(file, compiled) + $native.write(cacheFilePath, compiled) if writeToCache + evaluated + catch e + if retry + # Attempt a second compile to work around mysterious CEF/CoffeeScript + # timing issue where the CoffeeScript compiler generates invalid + # JavaScript such as [object Object]. + console.warn "Error evaluating #{file}. Trying again...", e.stack + exts.coffee(file, false) + else + throw e + +getPath = (path) -> + path = resolve(path) + return path unless path.split('.').pop() is 'coffee' + + cacheFilePath = getCacheFilePath(path) + unless __exists(cacheFilePath) + {CoffeeScript} = require 'coffee-script' + compiled = CoffeeScript.compile(__read(path), filename: path) + $native.write(cacheFilePath, compiled) + cacheFilePath + +getCacheFilePath = (path) -> + "/tmp/atom-compiled-scripts/#{$native.md5ForPath(path)}" resolve = (name, {verifyExistence}={}) -> verifyExistence ?= true file = name if /!/.test file - parts = file.split '!' - file = parts[parts.length-1] + file = file.split('!').pop() if file[0..1] is './' - prefix = __filename.split('/')[0..-2].join '/' + prefix = window.__filename.split('/')[0..-2].join '/' file = file.replace './', "#{prefix}/" if file[0..2] is '../' - prefix = __filename.split('/')[0..-3].join '/' + prefix = window.__filename.split('/')[0..-3].join '/' file = file.replace '../', "#{prefix}/" if file[0] isnt '/' @@ -130,18 +163,6 @@ __exists = (path) -> __isFile = (path) -> $native.isFile path -__coffeeCache = (filePath) -> - {CoffeeScript} = require 'coffee-script' - tmpPath = "/tmp/atom-compiled-scripts" - cacheFilePath = [tmpPath, $native.md5ForPath(filePath)].join("/") - - if __exists(cacheFilePath) - __read(cacheFilePath) - else - compiled = CoffeeScript.compile(__read(filePath), filename: filePath) - $native.write(cacheFilePath, compiled) - compiled - __read = (path) -> try $native.read(path) @@ -157,6 +178,7 @@ this.nakedLoad = nakedLoad this.define = define this.require.paths = paths +this.require.getPath = getPath this.require.exts = exts this.require.resolve = resolve diff --git a/src/stdlib/task-shell.coffee b/src/stdlib/task-shell.coffee new file mode 100644 index 000000000..ea7f84ecf --- /dev/null +++ b/src/stdlib/task-shell.coffee @@ -0,0 +1,29 @@ +# This file is loaded within Task's worker thread. It will attempt to invoke +# any message with a 'method' and 'args' key on the global `handler` object. The +# initial `handler` object contains the `start` method, which is called by the +# task itself to relay information from the window thread and bootstrap the +# worker's environment. The `start` method then replaces the handler with an +# object required from the given `handlerPath`. + +self.window = {} +self.attachEvent = -> +self.console = + warn: -> callTaskMethod 'warn', arguments... + log: -> callTaskMethod 'log', arguments... + error: -> callTaskMethod 'error', arguments... + +# `callTaskMethod` can be used to invoke method's on the parent `Task` object +# back in the window thread. +self.callTaskMethod = (method, args...) -> + postMessage(method: method, args: args) + +# The worker's initial handler replaces itself when `start` is invoked +self.handler = + start: ({resourcePath, requirePath, handlerPath}) -> + window.resourcePath = resourcePath + importScripts(requirePath) + self.handler = require(handlerPath) + callTaskMethod 'started' + +self.addEventListener 'message', ({data}) -> + handler[data.method]?(data.args...) if data.method diff --git a/src/stdlib/task.coffee b/src/stdlib/task.coffee new file mode 100644 index 000000000..463c806bb --- /dev/null +++ b/src/stdlib/task.coffee @@ -0,0 +1,35 @@ +module.exports = +class Task + constructor: (@path) -> + + start: -> + @worker = new Worker(require.getPath('task-shell')) + @worker.onmessage = ({data}) => + if data.method and this[data.method] + this[data.method](data.args...) + else + @onMessage(data) + @startWorker() + + log: -> console.log(arguments...) + warn: -> console.warn(arguments...) + error: -> console.error(arguments...) + + startWorker: -> + @callWorkerMethod 'start' + resourcePath: window.resourcePath + requirePath: require.getPath('require') + handlerPath: @path + + started: -> + + onMessage: (message) -> + + callWorkerMethod: (method, args...) -> + @postMessage({method, args}) + + postMessage: (data) -> + @worker.postMessage(data) + + terminate: -> + @worker.terminate() diff --git a/src/window-bootstrap.coffee b/src/window-bootstrap.coffee index fa815e832..cca57c7d7 100644 --- a/src/window-bootstrap.coffee +++ b/src/window-bootstrap.coffee @@ -1,7 +1,9 @@ # Like sands through the hourglass, so are the days of our lives. +date = new Date().getTime() require 'atom' require 'window' pathToOpen = atom.getWindowState('pathToOpen') ? window.location.params.pathToOpen window.attachRootView(pathToOpen) atom.show() +console.log "Load time: #{new Date().getTime() - date}" diff --git a/static/atom.css b/static/atom.css index 13a207fee..4f70a0574 100644 --- a/static/atom.css +++ b/static/atom.css @@ -1,5 +1,4 @@ html, body { - font: caption; width: 100%; height: 100%; overflow: hidden; @@ -9,7 +8,6 @@ html, body { height: 100%; overflow: hidden; position: relative; - background-color: #333333; } #root-view #horizontal { @@ -28,17 +26,6 @@ html, body { position: relative; } -#root-view #panes:before { - display: block; - content: "\f208"; - font-family: 'Octicons Regular'; - color: #303030; - -webkit-font-smoothing: antialiased; - font-size: 100vmin; - line-height: 100vmin; - text-align: center; -} - #root-view #panes .column { position: absolute; top: 0; @@ -66,28 +53,4 @@ html, body { left: 0; right: 0; box-sizing: border-box; -} - -#root-view #panes .row > * + * { - border-left: 5px solid #515151; -} - -#root-view #panes .column > * + * { - border-top: 5px solid #515151; -} - -.error { - background: #991212 !important; - -webkit-transition: background 300ms ease-out; -} - -.clear-float { - clear: both; -} - -@font-face { - font-family: 'Octicons Regular'; - src: url("octicons-regular-webfont.woff") format("woff"); - font-weight: normal; - font-style: normal; -} +} \ No newline at end of file diff --git a/static/editor.css b/static/editor.css index b2f84e73a..bdd9f2825 100644 --- a/static/editor.css +++ b/static/editor.css @@ -6,7 +6,6 @@ -webkit-box-flex: 1; position: relative; z-index: 0; - font-family: Inconsolata, Monaco, Courier; } .editor.mini { @@ -17,7 +16,6 @@ position: absolute; height: 100%; overflow: hidden; - color: rgba(255, 255, 255, .3); text-align: right; } @@ -25,28 +23,10 @@ position: relative; } -.editor .gutter .line-number { - padding-left: 0.4em; - padding-right: 0.8em; -} - -.editor.focused .line-number.cursor-line { - color: rgba(255, 255, 255, .6); -} - -.editor.focused .line-number.cursor-line-no-selection, -.editor.focused .line.cursor-line { - background-color: rgba(255, 255, 255, .20); -} - .editor.mini .gutter { display: none; } -.editor .gutter.drop-shadow { - -webkit-box-shadow: -2px 0px 10px 2px #222; -} - .editor .vertical-scrollbar { position: absolute; right: 0; @@ -123,27 +103,4 @@ position: absolute; pointer-events: none; z-index: -1; -} - -@-webkit-keyframes highlight { - from { background-color: rgba(100, 255, 100, 0.7); } - to { background-color: null; } -} - -.editor .highlighted.selection .region { - -webkit-animation-name: highlight; - -webkit-animation-duration: 1s; - -webkit-animation-iteration-count: 1; -} - -.editor .fold { - background-color: #444; -} - -.editor .fold.selected { - background-color: #244; -} - -.editor .invisible { - opacity: 0.2; -} +} \ No newline at end of file diff --git a/static/grammar-view.css b/static/grammar-view.css index 582dd98d8..1cbeeba30 100644 --- a/static/grammar-view.css +++ b/static/grammar-view.css @@ -5,24 +5,4 @@ .grammar-view ol { max-height: 300px; -} - -.grammar-view ol li { - padding: 2px; - border-bottom: 1px solid rgba(255, 255, 255, .05); - line-height: 16px; -} - -.grammar-view ol li.grammar { - padding-left: 21px; -} - -.grammar-view ol li.current-grammar:before { - font-family: 'Octicons Regular'; - width: 16px; - height: 16px; - margin-right: 5px; - -webkit-font-smoothing: antialiased; - color: #ccc; - content: '\f03a'; -} +} \ No newline at end of file diff --git a/static/index.html b/static/index.html index 582a8c87b..0e27bf115 100644 --- a/static/index.html +++ b/static/index.html @@ -1,5 +1,5 @@ - + diff --git a/static/select-list.css b/static/select-list.css index a17e22023..f2472e3c6 100644 --- a/static/select-list.css +++ b/static/select-list.css @@ -1,36 +1,19 @@ .select-list { position: absolute; - width: 80%; + width: 600px; top: 0; left: 50%; - margin-left: -40%; - background-color: #444; + margin-left: -300px; box-sizing: border-box; - color: #eee; - -webkit-box-shadow: 0 0 5px 5px #222; - padding: 5px; z-index: 99; - cursor: pointer; } .select-list .editor { - margin-bottom: 5px; + box-sizing: border-box; + padding: 5px; } .select-list ol { position: relative; overflow-y: auto; -} - -.select-list li:hover { - background-color: #555; -} - -.select-list ol .selected { - background: green; -} - -.select-list .error { - padding-top: 5px; - font-weight: bold; -} +} \ No newline at end of file diff --git a/themes/Atom - Dark/atom.css b/themes/Atom - Dark/atom.css new file mode 100644 index 000000000..2e5a1355b --- /dev/null +++ b/themes/Atom - Dark/atom.css @@ -0,0 +1,40 @@ +html, body, +#root-view { + font: caption; + background-color: #333333; +} + +#root-view #panes:before { + display: block; + content: "\f208"; + font-family: 'Octicons Regular'; + color: #303030; + -webkit-font-smoothing: antialiased; + font-size: 100vmin; + line-height: 100vmin; + text-align: center; +} + +#root-view #panes .row > * + * { + border-left: 5px solid #515151; +} + +#root-view #panes .column > * + * { + border-top: 5px solid #515151; +} + +.error { + background: #991212 !important; + -webkit-transition: background 300ms ease-out; +} + +.clear-float { + clear: both; +} + +@font-face { + font-family: 'Octicons Regular'; + src: url("octicons-regular-webfont.woff") format("woff"); + font-weight: normal; + font-style: normal; +} diff --git a/themes/Atom - Dark/autocomplete.css b/themes/Atom - Dark/autocomplete.css new file mode 100644 index 000000000..290713336 --- /dev/null +++ b/themes/Atom - Dark/autocomplete.css @@ -0,0 +1,17 @@ +.select-list.autocomplete { + min-width: 150px; + border: 2px solid #222; + webkit-box-shadow: 0 0 3px 3px rgba(0, 0, 0, .5); + margin-left: 0px; + width: auto; +} + +.autocomplete ol { + position: relative; + overflow-y: scroll; + max-height: 200px; +} + +.autocomplete ol li { + padding: 0.1em 0.2em; +} diff --git a/themes/Atom - Dark/command-logger.css b/themes/Atom - Dark/command-logger.css new file mode 100644 index 000000000..56822c247 --- /dev/null +++ b/themes/Atom - Dark/command-logger.css @@ -0,0 +1,41 @@ +.command-logger { + background: #1e1e1e; + color: #eee; + padding-top: 10px; + padding-bottom: 10px; +} + +.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 { + margin: auto; + background-color: #efefef; + border: 1px solid #999; +} + +body.command-logger-node-text { + background-color: transparent; +} + +.command-logger-node-text div { + display: table-cell; + vertical-align: middle; + text-align: center; + cursor: pointer; +} + +.command-logger-node-text span { + font-size: 10px; + color: #fff; + text-shadow: #000 1px 1px 4px; +} diff --git a/src/packages/command-palette/stylesheets/command-palette.css b/themes/Atom - Dark/command-palette.css similarity index 86% rename from src/packages/command-palette/stylesheets/command-palette.css rename to themes/Atom - Dark/command-palette.css index c3c29053c..0cadfbcae 100644 --- a/src/packages/command-palette/stylesheets/command-palette.css +++ b/themes/Atom - Dark/command-palette.css @@ -7,11 +7,6 @@ max-height: 300px; } -.command-palette ol li { - padding: 2px; - border-bottom: 1px solid rgba(255, 255, 255, .05); -} - .command-palette ol .event-description { float: left; display: inline-block; diff --git a/src/packages/command-panel/stylesheets/command-panel.css b/themes/Atom - Dark/command-panel.css similarity index 88% rename from src/packages/command-panel/stylesheets/command-panel.css rename to themes/Atom - Dark/command-panel.css index 8f4a6e405..dfc7f225b 100644 --- a/src/packages/command-panel/stylesheets/command-panel.css +++ b/themes/Atom - Dark/command-panel.css @@ -15,6 +15,13 @@ cursor: default; } +.command-panel .preview-count { + font-size: 11px; + color: #969696; + text-align: right; + padding-bottom: 1px; +} + .command-panel .preview-list li.selected, .command-panel .preview-list li.operation:hover { background-color: rgba(255, 255, 255, .13); } @@ -53,6 +60,11 @@ display: inline-block; } +.command-panel .preview-list .path-match-number { + padding-left: 8px; + color: rgba(255, 255, 255, .3); +} + .command-panel .preview-list .preview { word-break: break-all; } diff --git a/themes/Atom - Dark/editor.css b/themes/Atom - Dark/editor.css new file mode 100644 index 000000000..6581aaa59 --- /dev/null +++ b/themes/Atom - Dark/editor.css @@ -0,0 +1,46 @@ +.editor { + font-family: Inconsolata, Monaco, Courier; +} + +.editor.mini { + height: auto; +} + +.editor .gutter .line-number { + padding-right: 1.3em; + min-width: 35px; + box-sizing: border-box; + text-align: right; + opacity: 0.6; +} + +.editor .gutter .line-number.cursor-line { + opacity: 1; +} + +.editor .gutter.drop-shadow { + -webkit-box-shadow: -2px 0px 10px 2px #222; +} + +@-webkit-keyframes highlight { + from { background-color: rgba(100, 255, 100, 0.7); } + to { background-color: null; } +} + +.editor .highlighted.selection .region { + -webkit-animation-name: highlight; + -webkit-animation-duration: 1s; + -webkit-animation-iteration-count: 1; +} + +.editor .fold { + background-color: #444; +} + +.editor .fold.selected { + background-color: #244; +} + +.editor .invisible { + opacity: 0.2; +} diff --git a/src/packages/fuzzy-finder/stylesheets/fuzzy-finder.css b/themes/Atom - Dark/fuzzy-finder.css similarity index 86% rename from src/packages/fuzzy-finder/stylesheets/fuzzy-finder.css rename to themes/Atom - Dark/fuzzy-finder.css index 4257e3729..3d0218083 100644 --- a/src/packages/fuzzy-finder/stylesheets/fuzzy-finder.css +++ b/themes/Atom - Dark/fuzzy-finder.css @@ -1,12 +1,12 @@ .fuzzy-finder ol { overflow: hidden; - margin-bottom: 5px; -webkit-user-select: none; cursor: default; } .fuzzy-finder ol:empty { margin-bottom: 0; + border: none; } .fuzzy-finder .directory { @@ -39,8 +39,4 @@ .fuzzy-finder .file.pdf-name:before { content: "\f014"; -} - -.fuzzy-finder ol li { - border-bottom: 1px solid rgba(255, 255, 255, .05); -} +} \ No newline at end of file diff --git a/themes/Atom - Dark/gists.css b/themes/Atom - Dark/gists.css new file mode 100644 index 000000000..dde2dbd25 --- /dev/null +++ b/themes/Atom - Dark/gists.css @@ -0,0 +1,35 @@ +.gist-notification { + position: absolute; + top: 6px; + left: 50%; + margin-left: -5%; + z-index: 99; + padding-left: 5px; + padding-right: 10px; + -webkit-box-shadow: 0px 0px 5px 5px #222; + color: #BBB; + background-color: #333; +} + +.gist-notification .message-area { + float: right; + padding-top: 11px; +} + +.gist-notification .message { + font-size: 13px; +} + +.gist-notification .clipboard { + font-size: 11px; +} + +.gist-notification:before { + font-family: 'Octicons Regular'; + font-size: 32px; + width: 32px; + height: 32px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + content: "\f08c"; +} diff --git a/themes/Atom - Dark/go-to-line.css b/themes/Atom - Dark/go-to-line.css new file mode 100644 index 000000000..4ceec81aa --- /dev/null +++ b/themes/Atom - Dark/go-to-line.css @@ -0,0 +1,27 @@ +.go-to-line { + position: absolute; + width: 200px; + top: 0; + left: 50%; + margin-left: -100px; + box-sizing: border-box; + z-index: 99; + background-color: #484848; + border: 1px solid #444; + color: #d2d2d2; + box-shadow: 0 0 10px #000; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + padding: 5px; + cursor: pointer; +} + +.go-to-line .editor { + box-sizing: border-box; + padding: 5px; +} + +.go-to-line .message { + padding-top: 2px; + font-size: 11px; +} diff --git a/themes/Atom - Dark/grammar-view.css b/themes/Atom - Dark/grammar-view.css new file mode 100644 index 000000000..7be94f4c0 --- /dev/null +++ b/themes/Atom - Dark/grammar-view.css @@ -0,0 +1,17 @@ +.grammar-view ol li { + line-height: 16px; +} + +.grammar-view ol li.grammar { + padding-left: 21px; +} + +.grammar-view ol li.current-grammar:before { + font-family: 'Octicons Regular'; + width: 16px; + height: 16px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + color: #ccc; + content: '\f03a'; +} diff --git a/src/packages/markdown-preview/stylesheets/markdown-preview.css b/themes/Atom - Dark/markdown-preview.css similarity index 100% rename from src/packages/markdown-preview/stylesheets/markdown-preview.css rename to themes/Atom - Dark/markdown-preview.css diff --git a/themes/Atom - Dark/package.json b/themes/Atom - Dark/package.json new file mode 100644 index 000000000..28f90e051 --- /dev/null +++ b/themes/Atom - Dark/package.json @@ -0,0 +1,21 @@ +{ + "stylesheets":[ + "atom.css", + "editor.css", + "grammar-view.css", + "select-list.css", + "tree-view.css", + "tabs.css", + "wrap-guide.css", + "status-bar.css", + "symbols-view.css", + "markdown-preview.css", + "fuzzy-finder.css", + "command-panel.css", + "command-palette.css", + "command-logger.css", + "autocomplete.css", + "gists.css", + "go-to-line.css" + ] +} diff --git a/themes/Atom - Dark/select-list.css b/themes/Atom - Dark/select-list.css new file mode 100644 index 000000000..29aac3f03 --- /dev/null +++ b/themes/Atom - Dark/select-list.css @@ -0,0 +1,42 @@ +.select-list { + background-color: #484848; + border: 1px solid #444; + color: #d2d2d2; + box-shadow: 0 0 10px #000; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + padding: 5px; + cursor: pointer; +} + +.select-list ol { + border: 1px solid #212121; +} + +.select-list ol li { + background-color: #292929; + border-bottom: 1px solid #212121; + padding: 5px; +} + +.select-list ol li:last-child { + border-bottom: none; +} + +.select-list .editor { + margin-bottom: 5px; +} + +.select-list li:hover { + background-color: #555; +} + +.select-list ol .selected { + background-image: -webkit-linear-gradient(#7e7e7e, #737373); +} + +.select-list .error { + font-weight: bold; + color: white; + text-shadow: 0 1px 0 #4E0000; +} \ No newline at end of file diff --git a/themes/Atom - Dark/status-bar.css b/themes/Atom - Dark/status-bar.css new file mode 100644 index 000000000..f517760f4 --- /dev/null +++ b/themes/Atom - Dark/status-bar.css @@ -0,0 +1,61 @@ +.status-bar { + background-color: #303030; + border-top: 1px solid #454545; + padding: 4px 10px 3px; + font-size: 11px; + line-height: 14px; + color: #969696; +} + +.status-bar .cursor-position, +.status-bar .grammar-name { + padding-left: 10px; +} + +.status-bar .grammar-name { + cursor: pointer; +} + +.status-bar .branch-label { + vertical-align: baseline; +} + +.status-bar .git-status.octicons { + display: none; + padding-left: 10px; + margin-top:-2px; +} + +.status-bar .octicons:before { + font-family: 'Octicons Regular'; + font-size: 14px; + width: 14px; + height: 14px; + line-height: 14px; + -webkit-font-smoothing: antialiased; + display: inline-block; + vertical-align: middle; + margin-right: 5px; +} + +.status-bar .branch-icon:before { + content: "\f020"; +} + +.status-bar .git-status.octicons.modified-status-icon { + color: #f78a46; + display: inline-block; +} + +.status-bar .modified-status-icon:before { + content: "\f26d"; +} + +.status-bar .git-status.octicons.new-status-icon { + color: #5293d8; + display: inline-block; +} + +.status-bar .new-status-icon:before { + content: "\f26b"; +} diff --git a/src/packages/outline-view/stylesheets/outline-view.css b/themes/Atom - Dark/symbols-view.css similarity index 72% rename from src/packages/outline-view/stylesheets/outline-view.css rename to themes/Atom - Dark/symbols-view.css index a5146bc38..0cbdbfa53 100644 --- a/src/packages/outline-view/stylesheets/outline-view.css +++ b/themes/Atom - Dark/symbols-view.css @@ -1,29 +1,29 @@ -.outline-view { +.symbols-view { width: 50%; margin-left: -25%; } -.outline-view ol { +.symbols-view ol { max-height: 300px; } -.outline-view ol li { +.symbols-view ol li { padding: 2px; border-bottom: 1px solid rgba(255, 255, 255, .05); } -.outline-view ol .function-name { +.symbols-view ol .function-name { float: left; display: inline-block; margin-right: .5em; margin: 4px 0; } -.outline-view li .right { +.symbols-view li .right { float: right; } -.outline-view ol .function-details { +.symbols-view ol .function-details { display: inline-block; margin: 4px 0; margin-right: .5em; diff --git a/themes/Atom - Dark/tabs.css b/themes/Atom - Dark/tabs.css new file mode 100644 index 000000000..09942bec6 --- /dev/null +++ b/themes/Atom - Dark/tabs.css @@ -0,0 +1,123 @@ +.tabs { + background: #333333; + border-bottom: 4px solid #424242; + font: caption; + box-shadow: inset 0 -1px 0 #2e2e2e; +} + +.tab { + cursor: default; + padding: 2px 21px 2px 9px; + background-image: -webkit-linear-gradient(#444, #3d3d3d); + border-top: 1px solid #383838; + border-right: 1px solid #2e2e2e; + border-bottom: 1px solid #2e2e2e; + box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a, inset 1px 0 0 #4a4a4a; +} + +.tab, +.tab .close-icon { + color: #aaa; +} + +.tab.file-modified .close-icon { + border-color: #aaa; +} + +.tab.active, +.tab.active:hover, +.tab.active .close-icon { + color: #e6e6e6; +} + +.tab.file-modified.active .close-icon { + border-color: #e6e6e6; +} + +.tab:hover .close-icon { + color: #c8c8c8; + border-color: #c8c8c8; +} + +.tab.file-modified .close-icon { + border: 3px solid #777; + border-radius: 10px; +} + +.tab.file-modified .close-icon:before { + content: ""; +} + +.tab:first-child { + box-shadow: inset 0 0 5px #383838, 0 1px 0 #585858, inset -1px 0 0 #4a4a4a; +} + +.tab.active:first-child, +.tab.active:first-child:hover { + box-shadow: inset -1px 0 0 #595959; +} + +.tab.active, +.tab.active:hover { + border-top: 1px solid #4a4a4a; + box-shadow: inset -1px 0 0 #595959, inset 1px 0 0 #595959; + border-bottom-color: #424242; + background-image: -webkit-linear-gradient(#555555, #424242); +} + +.tab.active:before, +.tab.active:after { + position: absolute; + bottom: -1px; + width: 4px; + height: 4px; + content: " "; + z-index: 3; + border: 1px solid #595959; +} +.tab.active:before { + border-bottom-right-radius: 4px; + border-width: 0 1px 1px 0; + box-shadow: 2px 2px 0 #424242; + left: -4px; +} +.tab.active:after { + right: -4px; + border-bottom-left-radius: 4px; + border-width: 0 0 1px 1px; + box-shadow: -2px 2px 0 #424242; +} +.tab.active:first-child:before { + display: none; +} + +.tab:hover { + color: #c8c8c8; + background-image: -webkit-linear-gradient(#474747, #444444); +} + +.tab .file-name { + font-size: 11px; + text-shadow: 0 -1px 1px black; +} + +.tab .close-icon { + font-family: 'Octicons Regular'; + font-size: 14px; + width: 14px; + height: 14px; + display: block; + cursor: pointer; + position: absolute; + right: 4px; + top: -1px; + -webkit-font-smoothing: antialiased; +} + +.tab .close-icon:before { + content: "\f081"; +} + +.tab .close-icon:hover { + color: white; +} diff --git a/themes/Atom - Dark/tree-view.css b/themes/Atom - Dark/tree-view.css new file mode 100644 index 000000000..ea27fd587 --- /dev/null +++ b/themes/Atom - Dark/tree-view.css @@ -0,0 +1,179 @@ +.tree-view { + background: #1e1e1e; + border-right: 2px solid #191919; +} + +.tree-view .entry { + text-shadow: 0 -1px 0 #000; +} + +.tree-view .entries { + margin-left: 12px; +} + +.tree-view .entries .file .name { + margin-left: 20px; +} + +.tree-view .directory.selected > .header > .name, +.tree-view .selected > .name { + color: #d2d2d2; +} + +.tree-view .selected > .highlight { + background-image: -webkit-linear-gradient(#4e4e4e, #434343); +} + +.tree-view:focus .selected > .highlight { + background-image: -webkit-linear-gradient(#7e7e7e, #737373); +} + +.tree-view:focus .directory.selected > .header > .name, +.tree-view:focus .selected > .name { + color: #fff; + text-shadow: 0 -1px 0 #7E4521; +} + +.tree-view .directory .header { + color: #bebebe; +} + +.tree-view .file { + color: #7d7d7d; +} + +.tree-view .entry:hover, +.tree-view .directory .header:hover .name, +.tree-view .directory .header:hover .disclosure-arrow { + color: #ebebeb; +} + +.tree-view .file .name, +.tree-view .directory .header { + padding-top: 4px; + padding-bottom: 4px; + padding-right: 10px; +} + +.tree-view .directory .header { + padding-left: 5px; +} + +.tree-view .ignored { + color: #555; +} + +.tree-view .modified { + color: #f78a46; +} + +.tree-view .new { + color: #5293d8; +} + +.tree-view-dialog { + background-color: #333; + border-top: 1px solid #555; + -webkit-box-shadow: 0 0 3px 3px rgba(0, 0, 0, .5); + padding: 5px; +} + +.tree-view-dialog .prompt { + padding-bottom: 3px; + font-size: 12px; + line-height: 16px; + color: #aaa; +} + +.tree-view-dialog .prompt span { + position: relative; + top: -1px; +} + +.tree-view-dialog .prompt:before { + font-family: 'Octicons Regular'; + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 3px; + -webkit-font-smoothing: antialiased; +} + +.tree-view-dialog .prompt.add:before { + content: "\f086"; +} + +.tree-view-dialog .prompt.move:before { + content: "\f03e"; +} + +.tree-view .directory .header .name, +.tree-view .file .name { + position: relative; + padding-left: 21px; +} + +.tree-view .directory .header .name:before, +.tree-view .file .name:before { + font-family: 'Octicons Regular'; + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + position: absolute; + left: 0; +} + +.tree-view .disclosure-arrow:before { + font-family: 'Octicons Regular'; + font-size: 12px; + width: 12px; + height: 12px; + line-height: 16px; + margin-right: 3px; + -webkit-font-smoothing: antialiased; +} + +.tree-view .directory .header .directory-icon:before { + content: "\f016"; + top: -5px; +} + +.tree-view .directory .header .repository-icon:before { + content: "\f001"; + top: -4px; +} + +.tree-view .directory .header .submodule-icon:before { + content: "\f017"; + top: -5px; +} + +.tree-view .file .text-icon:before { + content: "\f011"; + top: -2px; +} + +.tree-view .file .image-icon:before { + content: "\f012"; + top: -2px; +} + +.tree-view .file .compressed-icon:before { + content: "\f013"; + top: -2px; +} + +.tree-view .file .pdf-icon:before { + content: "\f014"; + top: -2px; +} + +.tree-view .directory > .header .disclosure-arrow:before { + content: "\f05a"; +} + +.tree-view .directory.expanded > .header .disclosure-arrow:before { + content: "\f05b"; +} diff --git a/themes/Atom - Dark/wrap-guide.css b/themes/Atom - Dark/wrap-guide.css new file mode 100644 index 000000000..51660ea4c --- /dev/null +++ b/themes/Atom - Dark/wrap-guide.css @@ -0,0 +1,3 @@ +.wrap-guide { + background: rgba(150, 150, 150, .30); +} diff --git a/themes/Atom - Light/atom.css b/themes/Atom - Light/atom.css new file mode 100644 index 000000000..772922301 --- /dev/null +++ b/themes/Atom - Light/atom.css @@ -0,0 +1,29 @@ +html, body, +#root-view { + font: caption; + background-color: #f4f4f4; +} + +#root-view #panes .row > * + * { + border-left: 1px solid #989898; +} + +#root-view #panes .column > * + * { + border-top: 1px solid #989898; +} + +.error { + background: #991212 !important; + -webkit-transition: background 300ms ease-out; +} + +.clear-float { + clear: both; +} + +@font-face { + font-family: 'Octicons Regular'; + src: url("octicons-regular-webfont.woff") format("woff"); + font-weight: normal; + font-style: normal; +} diff --git a/themes/Atom - Light/autocomplete.css b/themes/Atom - Light/autocomplete.css new file mode 100644 index 000000000..c121407d0 --- /dev/null +++ b/themes/Atom - Light/autocomplete.css @@ -0,0 +1,16 @@ +.select-list.autocomplete { + min-width: 150px; + webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .5); + margin-left: 0px; + width: auto; +} + +.autocomplete ol { + position: relative; + overflow-y: scroll; + max-height: 200px; +} + +.autocomplete ol li { + padding: 0.1em 0.2em; +} diff --git a/themes/Atom - Light/command-logger.css b/themes/Atom - Light/command-logger.css new file mode 100644 index 000000000..56822c247 --- /dev/null +++ b/themes/Atom - Light/command-logger.css @@ -0,0 +1,41 @@ +.command-logger { + background: #1e1e1e; + color: #eee; + padding-top: 10px; + padding-bottom: 10px; +} + +.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 { + margin: auto; + background-color: #efefef; + border: 1px solid #999; +} + +body.command-logger-node-text { + background-color: transparent; +} + +.command-logger-node-text div { + display: table-cell; + vertical-align: middle; + text-align: center; + cursor: pointer; +} + +.command-logger-node-text span { + font-size: 10px; + color: #fff; + text-shadow: #000 1px 1px 4px; +} diff --git a/themes/Atom - Light/command-palette.css b/themes/Atom - Light/command-palette.css new file mode 100644 index 000000000..272b6b806 --- /dev/null +++ b/themes/Atom - Light/command-palette.css @@ -0,0 +1,34 @@ +.command-palette { + width: 50%; + margin-left: -25%; +} + +.command-palette ol { + max-height: 300px; +} + +.command-palette ol .event-description { + float: left; + display: inline-block; + margin-right: .5em; + margin: 4px 0; +} + +.command-palette li .right { + float: right; +} + +.command-palette ol .event-name, .command-palette ol .key-binding { + display: inline-block; + margin: 4px 0; + margin-right: .5em; + font-size: 90%; + color: #969696; + -webkit-border-radius: 3px; + padding: 0 4px; +} + +.command-palette ol .event-name { + background: rgba(0, 0, 0, .2); + color: #fff; +} \ No newline at end of file diff --git a/themes/Atom - Light/command-panel.css b/themes/Atom - Light/command-panel.css new file mode 100644 index 000000000..4bfff1d22 --- /dev/null +++ b/themes/Atom - Light/command-panel.css @@ -0,0 +1,98 @@ +.command-panel { + background-color: #f4f4f4; + border-top: 1px solid #979797; + color: #ededed; + padding: 10px; +} + +.command-panel .preview-list { + max-height: 300px; + overflow: auto; + margin-bottom: 10px; + position: relative; + background-color: #e7e7e7; + color: #222; + cursor: default; + border: 1px solid #989898; +} + +.command-panel .preview-count { + font-size: 11px; + color: #333; + text-align: right; + padding-bottom: 1px; +} + +.command-panel .preview-list li.selected, .command-panel .preview-list li.operation:hover { + background-color: rgba(255, 255, 255, .6); +} + +.command-panel .preview-list .path { + padding-left: 5px; + color: #3D5075; +} + +.command-panel .preview-list .path:before { + font-family: 'Octicons Regular'; + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + content: "\f011"; + position: relative; + top: 1px; +} + +.command-panel .preview-list .operation { + padding-top: 2px; + padding-bottom: 2px; +} + +.command-panel .preview-list .line-number { + padding-left: 3px; + color: #3D5075; + margin-right: 1ex; + text-align: right; + display: inline-block; +} + +.command-panel .preview-list .path-match-number { + padding-left: 8px; + color: #3D5075; +} + +.command-panel .preview-list .preview { + word-break: break-all; +} + +.command-panel .preview-list .preview .match { + background-color: #c8d4d7; + -webkit-border-radius: 2px; + padding: 1px; +} + +.command-panel .prompt-and-editor { + display: -webkit-box; +} + +.command-panel .prompt-and-editor .prompt:before { + color: #969696; + content: '\f078'; + font-family: 'Octicons Regular'; + position: relative; + top: -4px; + left: -5px; + -webkit-font-smoothing: antialiased; +} + +.command-panel .prompt-and-editor .editor { + position: relative; + left: -4px; + margin-right: -4px; +} + +.error-messages { + padding: 5px 1em; + color: white; +} diff --git a/themes/Atom - Light/editor.css b/themes/Atom - Light/editor.css new file mode 100644 index 000000000..ebdf4ad12 --- /dev/null +++ b/themes/Atom - Light/editor.css @@ -0,0 +1,46 @@ +.editor { + font-family: Inconsolata, Monaco, Courier; +} + +.editor.mini { + height: auto; +} + +.editor .gutter .line-number { + padding-right: 1.3em; + min-width: 35px; + box-sizing: border-box; + text-align: right; + opacity: 0.5; +} + +.editor .gutter .line-number.cursor-line { + opacity: 1; +} + +.editor .gutter.drop-shadow { + -webkit-box-shadow: -2px 0px 10px 2px #222; +} + +@-webkit-keyframes highlight { + from { background-color: rgba(100, 255, 100, 0.7); } + to { background-color: null; } +} + +.editor .highlighted.selection .region { + -webkit-animation-name: highlight; + -webkit-animation-duration: 1s; + -webkit-animation-iteration-count: 1; +} + +.editor .fold { + background-color: #444; +} + +.editor .fold.selected { + background-color: #244; +} + +.editor .invisible { + opacity: 0.2; +} diff --git a/themes/Atom - Light/fuzzy-finder.css b/themes/Atom - Light/fuzzy-finder.css new file mode 100644 index 000000000..0cc921e02 --- /dev/null +++ b/themes/Atom - Light/fuzzy-finder.css @@ -0,0 +1,42 @@ +.fuzzy-finder ol { + overflow: hidden; + -webkit-user-select: none; + cursor: default; +} + +.fuzzy-finder ol:empty { + margin-bottom: 0; + border: none; +} + +.fuzzy-finder .directory { + color: #b2b2b2; + padding-left: .5em; +} + +.fuzzy-finder .file:before { + font-family: 'Octicons Regular'; + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 5px; + margin-left: 5px; + -webkit-font-smoothing: antialiased; + color: #9d9d9d; +} + +.fuzzy-finder .file.text-name:before { + content: "\f011"; +} + +.fuzzy-finder .file.image-name:before { + content: "\f012"; +} + +.fuzzy-finder .file.compressed-name:before { + content: "\f013"; +} + +.fuzzy-finder .file.pdf-name:before { + content: "\f014"; +} \ No newline at end of file diff --git a/themes/Atom - Light/gists.css b/themes/Atom - Light/gists.css new file mode 100644 index 000000000..0209ce3e3 --- /dev/null +++ b/themes/Atom - Light/gists.css @@ -0,0 +1,35 @@ +.gist-notification { + position: absolute; + top: 6px; + left: 50%; + margin-left: -5%; + z-index: 99; + padding-left: 5px; + padding-right: 10px; + -webkit-box-shadow: 0px 0px 5px 5px #222; + color: #BBB; + background-color: #444; +} + +.gist-notification .message-area { + float: right; + padding-top: 11px; +} + +.gist-notification .message { + font-size: 13px; +} + +.gist-notification .clipboard { + font-size: 11px; +} + +.gist-notification:before { + font-family: 'Octicons Regular'; + font-size: 32px; + width: 32px; + height: 32px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + content: "\f08c"; +} diff --git a/themes/Atom - Light/go-to-line.css b/themes/Atom - Light/go-to-line.css new file mode 100644 index 000000000..9f6c3ec8b --- /dev/null +++ b/themes/Atom - Light/go-to-line.css @@ -0,0 +1,27 @@ +.go-to-line { + position: absolute; + width: 200px; + top: 0; + left: 50%; + margin-left: -100px; + box-sizing: border-box; + z-index: 99; + background-color: #eeeeee; + border: 1px solid #c6c6c6; + color: #323232; + box-shadow: 0 0 10px #555; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + padding: 5px; + cursor: pointer; +} + +.go-to-line .editor { + box-sizing: border-box; + padding: 5px; +} + +.go-to-line .message { + padding-top: 2px; + font-size: 11px; +} diff --git a/themes/Atom - Light/grammar-view.css b/themes/Atom - Light/grammar-view.css new file mode 100644 index 000000000..7be94f4c0 --- /dev/null +++ b/themes/Atom - Light/grammar-view.css @@ -0,0 +1,17 @@ +.grammar-view ol li { + line-height: 16px; +} + +.grammar-view ol li.grammar { + padding-left: 21px; +} + +.grammar-view ol li.current-grammar:before { + font-family: 'Octicons Regular'; + width: 16px; + height: 16px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + color: #ccc; + content: '\f03a'; +} diff --git a/themes/Atom - Light/markdown-preview.css b/themes/Atom - Light/markdown-preview.css new file mode 100644 index 000000000..f5274f2df --- /dev/null +++ b/themes/Atom - Light/markdown-preview.css @@ -0,0 +1,438 @@ +.markdown-preview { + position: absolute; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + background-color: #F4F4F4; + overflow: auto; + z-index: 3; + box-sizing: border-box; + padding: 20px; +} + +.markdown-body { + background-color: #fff; + box-shadow: rgba(0, 0, 0, 0.1) 0 0 0 1px,rgba(0, 0, 0, 0.3) 0 1px 3px; + border-radius: 5px; + max-width: 914px; + min-width: 680px; + margin-left: auto; + margin-right: auto; + padding: 30px; +} + +.markdown-body pre, +.markdown-body code, +.markdown-body tt { + font-size: 12px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +.markdown-body ol > li { + list-style-type: decimal; +} + +.markdown-body ul > li { + list-style-type: disc; +} + +.markdown-spinner { + margin: auto; + background-image: url(images/octocat-spinner-128.gif); + background-repeat: no-repeat; + background-size: 64px; + background-position: top center; + padding-top: 70px; + text-align: center; +} + + +/* this code below was copied from https://github.com/assets/stylesheets/primer/components/markdown.css */ +/* we really need to get primer in here somehow. */ +.markdown-body { + font-size: 14px; + line-height: 1.6; + overflow: hidden; } + .markdown-body > *:first-child { + margin-top: 0 !important; } + .markdown-body > *:last-child { + margin-bottom: 0 !important; } + .markdown-body a.absent { + color: #c00; } + .markdown-body a.anchor { + display: block; + padding-left: 30px; + margin-left: -30px; + cursor: pointer; + position: absolute; + top: 0; + left: 0; + bottom: 0; } + .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { + margin: 20px 0 10px; + padding: 0; + font-weight: bold; + -webkit-font-smoothing: antialiased; + cursor: text; + position: relative; } + .markdown-body h1 .mini-icon-link, .markdown-body h2 .mini-icon-link, .markdown-body h3 .mini-icon-link, .markdown-body h4 .mini-icon-link, .markdown-body h5 .mini-icon-link, .markdown-body h6 .mini-icon-link { + display: none; + color: #000; } + .markdown-body h1:hover a.anchor, .markdown-body h2:hover a.anchor, .markdown-body h3:hover a.anchor, .markdown-body h4:hover a.anchor, .markdown-body h5:hover a.anchor, .markdown-body h6:hover a.anchor { + text-decoration: none; + line-height: 1; + padding-left: 0; + margin-left: -22px; + top: 15%; } + .markdown-body h1:hover a.anchor .mini-icon-link, .markdown-body h2:hover a.anchor .mini-icon-link, .markdown-body h3:hover a.anchor .mini-icon-link, .markdown-body h4:hover a.anchor .mini-icon-link, .markdown-body h5:hover a.anchor .mini-icon-link, .markdown-body h6:hover a.anchor .mini-icon-link { + display: inline-block; } + .markdown-body h1 tt, .markdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code { + font-size: inherit; } + .markdown-body h1 { + font-size: 28px; + color: #000; } + .markdown-body h2 { + font-size: 24px; + border-bottom: 1px solid #ccc; + color: #000; } + .markdown-body h3 { + font-size: 18px; } + .markdown-body h4 { + font-size: 16px; } + .markdown-body h5 { + font-size: 14px; } + .markdown-body h6 { + color: #777; + font-size: 14px; } + .markdown-body p, + .markdown-body blockquote, + .markdown-body ul, .markdown-body ol, .markdown-body dl, + .markdown-body table, + .markdown-body pre { + margin: 15px 0; } + .markdown-body hr { + background: transparent url("https://a248.e.akamai.net/assets.github.com/assets/primer/markdown/dirty-shade-0e7d81b119cc9beae17b0c98093d121fa0050a74.png") repeat-x 0 0; + border: 0 none; + color: #ccc; + height: 4px; + padding: 0; } + .markdown-body > h2:first-child, .markdown-body > h1:first-child, .markdown-body > h1:first-child + h2, .markdown-body > h3:first-child, .markdown-body > h4:first-child, .markdown-body > h5:first-child, .markdown-body > h6:first-child { + margin-top: 0; + padding-top: 0; } + .markdown-body a:first-child h1, .markdown-body a:first-child h2, .markdown-body a:first-child h3, .markdown-body a:first-child h4, .markdown-body a:first-child h5, .markdown-body a:first-child h6 { + margin-top: 0; + padding-top: 0; } + .markdown-body h1 + p, + .markdown-body h2 + p, + .markdown-body h3 + p, + .markdown-body h4 + p, + .markdown-body h5 + p, + .markdown-body h6 + p { + margin-top: 0; } + .markdown-body li p.first { + display: inline-block; } + .markdown-body ul, .markdown-body ol { + padding-left: 30px; } + .markdown-body ul.no-list, .markdown-body ol.no-list { + list-style-type: none; + padding: 0; } + .markdown-body ul li > :first-child, + .markdown-body ul li ul:first-of-type, .markdown-body ol li > :first-child, + .markdown-body ol li ul:first-of-type { + margin-top: 0px; } + .markdown-body ul ul, + .markdown-body ul ol, + .markdown-body ol ol, + .markdown-body ol ul { + margin-bottom: 0; } + .markdown-body dl { + padding: 0; } + .markdown-body dl dt { + font-size: 14px; + font-weight: bold; + font-style: italic; + padding: 0; + margin: 15px 0 5px; } + .markdown-body dl dt:first-child { + padding: 0; } + .markdown-body dl dt > :first-child { + margin-top: 0px; } + .markdown-body dl dt > :last-child { + margin-bottom: 0px; } + .markdown-body dl dd { + margin: 0 0 15px; + padding: 0 15px; } + .markdown-body dl dd > :first-child { + margin-top: 0px; } + .markdown-body dl dd > :last-child { + margin-bottom: 0px; } + .markdown-body blockquote { + border-left: 4px solid #DDD; + padding: 0 15px; + color: #777; } + .markdown-body blockquote > :first-child { + margin-top: 0px; } + .markdown-body blockquote > :last-child { + margin-bottom: 0px; } + .markdown-body table th { + font-weight: bold; } + .markdown-body table th, .markdown-body table td { + border: 1px solid #ccc; + padding: 6px 13px; } + .markdown-body table tr { + border-top: 1px solid #ccc; + background-color: #fff; } + .markdown-body table tr:nth-child(2n) { + background-color: #f8f8f8; } + .markdown-body img { + max-width: 100%; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .markdown-body span.frame { + display: block; + overflow: hidden; } + .markdown-body span.frame > span { + border: 1px solid #ddd; + display: block; + float: left; + overflow: hidden; + margin: 13px 0 0; + padding: 7px; + width: auto; } + .markdown-body span.frame span img { + display: block; + float: left; } + .markdown-body span.frame span span { + clear: both; + color: #333; + display: block; + padding: 5px 0 0; } + .markdown-body span.align-center { + display: block; + overflow: hidden; + clear: both; } + .markdown-body span.align-center > span { + display: block; + overflow: hidden; + margin: 13px auto 0; + text-align: center; } + .markdown-body span.align-center span img { + margin: 0 auto; + text-align: center; } + .markdown-body span.align-right { + display: block; + overflow: hidden; + clear: both; } + .markdown-body span.align-right > span { + display: block; + overflow: hidden; + margin: 13px 0 0; + text-align: right; } + .markdown-body span.align-right span img { + margin: 0; + text-align: right; } + .markdown-body span.float-left { + display: block; + margin-right: 13px; + overflow: hidden; + float: left; } + .markdown-body span.float-left span { + margin: 13px 0 0; } + .markdown-body span.float-right { + display: block; + margin-left: 13px; + overflow: hidden; + float: right; } + .markdown-body span.float-right > span { + display: block; + overflow: hidden; + margin: 13px auto 0; + text-align: right; } + .markdown-body code, .markdown-body tt { + margin: 0 2px; + padding: 0px 5px; + border: 1px solid #eaeaea; + background-color: #f8f8f8; + border-radius: 3px; } + .markdown-body code { + white-space: nowrap; } + .markdown-body pre > code { + margin: 0; + padding: 0; + white-space: pre; + border: none; + background: transparent; } + .markdown-body .highlight pre, .markdown-body pre { + background-color: #f8f8f8; + border: 1px solid #ccc; + font-size: 13px; + line-height: 19px; + overflow: auto; + padding: 6px 10px; + border-radius: 3px; } + .markdown-body pre code, .markdown-body pre tt { + margin: 0; + padding: 0; + background-color: transparent; + border: none; } + +/* this code was copied from https://github.com/assets/stylesheets/primer/components/pygments.css */ +/* the .markdown-body class was then added to all rules */ +.markdown-body .highlight { + background: #ffffff; } + .markdown-body .highlight .c { + color: #999988; + font-style: italic; } + .markdown-body .highlight .err { + color: #a61717; + background-color: #e3d2d2; } + .markdown-body .highlight .k { + font-weight: bold; } + .markdown-body .highlight .o { + font-weight: bold; } + .markdown-body .highlight .cm { + color: #999988; + font-style: italic; } + .markdown-body .highlight .cp { + color: #999999; + font-weight: bold; } + .markdown-body .highlight .c1 { + color: #999988; + font-style: italic; } + .markdown-body .highlight .cs { + color: #999999; + font-weight: bold; + font-style: italic; } + .markdown-body .highlight .gd { + color: #000000; + background-color: #ffdddd; } + .markdown-body .highlight .gd .x { + color: #000000; + background-color: #ffaaaa; } + .markdown-body .highlight .ge { + font-style: italic; } + .markdown-body .highlight .gr { + color: #aa0000; } + .markdown-body .highlight .gh { + color: #999999; } + .markdown-body .highlight .gi { + color: #000000; + background-color: #ddffdd; } + .markdown-body .highlight .gi .x { + color: #000000; + background-color: #aaffaa; } + .markdown-body .highlight .go { + color: #888888; } + .markdown-body .highlight .gp { + color: #555555; } + .markdown-body .highlight .gs { + font-weight: bold; } + .markdown-body .highlight .gu { + color: #800080; + font-weight: bold; } + .markdown-body .highlight .gt { + color: #aa0000; } + .markdown-body .highlight .kc { + font-weight: bold; } + .markdown-body .highlight .kd { + font-weight: bold; } + .markdown-body .highlight .kn { + font-weight: bold; } + .markdown-body .highlight .kp { + font-weight: bold; } + .markdown-body .highlight .kr { + font-weight: bold; } + .markdown-body .highlight .kt { + color: #445588; + font-weight: bold; } + .markdown-body .highlight .m { + color: #009999; } + .markdown-body .highlight .s { + color: #d14; } + .markdown-body .highlight .na { + color: #008080; } + .markdown-body .highlight .nb { + color: #0086B3; } + .markdown-body .highlight .nc { + color: #445588; + font-weight: bold; } + .markdown-body .highlight .no { + color: #008080; } + .markdown-body .highlight .ni { + color: #800080; } + .markdown-body .highlight .ne { + color: #990000; + font-weight: bold; } + .markdown-body .highlight .nf { + color: #990000; + font-weight: bold; } + .markdown-body .highlight .nn { + color: #555555; } + .markdown-body .highlight .nt { + color: #000080; } + .markdown-body .highlight .nv { + color: #008080; } + .markdown-body .highlight .ow { + font-weight: bold; } + .markdown-body .highlight .w { + color: #bbbbbb; } + .markdown-body .highlight .mf { + color: #009999; } + .markdown-body .highlight .mh { + color: #009999; } + .markdown-body .highlight .mi { + color: #009999; } + .markdown-body .highlight .mo { + color: #009999; } + .markdown-body .highlight .sb { + color: #d14; } + .markdown-body .highlight .sc { + color: #d14; } + .markdown-body .highlight .sd { + color: #d14; } + .markdown-body .highlight .s2 { + color: #d14; } + .markdown-body .highlight .se { + color: #d14; } + .markdown-body .highlight .sh { + color: #d14; } + .markdown-body .highlight .si { + color: #d14; } + .markdown-body .highlight .sx { + color: #d14; } + .markdown-body .highlight .sr { + color: #009926; } + .markdown-body .highlight .s1 { + color: #d14; } + .markdown-body .highlight .ss { + color: #990073; } + .markdown-body .highlight .bp { + color: #999999; } + .markdown-body .highlight .vc { + color: #008080; } + .markdown-body .highlight .vg { + color: #008080; } + .markdown-body .highlight .vi { + color: #008080; } + .markdown-body .highlight .il { + color: #009999; } + .markdown-body .highlight .gc { + color: #999; + background-color: #EAF2F5; } + +.type-csharp .markdown-body .highlight .k { + color: #0000FF; } +.type-csharp .markdown-body .highlight .kt { + color: #0000FF; } +.type-csharp .markdown-body .highlight .nf { + color: #000000; + font-weight: normal; } +.type-csharp .markdown-body .highlight .nc { + color: #2B91AF; } +.type-csharp .markdown-body .highlight .nn { + color: #000000; } +.type-csharp .markdown-body .highlight .s { + color: #A31515; } +.type-csharp .markdown-body .highlight .sc { + color: #A31515; } diff --git a/themes/Atom - Light/package.json b/themes/Atom - Light/package.json new file mode 100644 index 000000000..28f90e051 --- /dev/null +++ b/themes/Atom - Light/package.json @@ -0,0 +1,21 @@ +{ + "stylesheets":[ + "atom.css", + "editor.css", + "grammar-view.css", + "select-list.css", + "tree-view.css", + "tabs.css", + "wrap-guide.css", + "status-bar.css", + "symbols-view.css", + "markdown-preview.css", + "fuzzy-finder.css", + "command-panel.css", + "command-palette.css", + "command-logger.css", + "autocomplete.css", + "gists.css", + "go-to-line.css" + ] +} diff --git a/themes/Atom - Light/select-list.css b/themes/Atom - Light/select-list.css new file mode 100644 index 000000000..6142a4c13 --- /dev/null +++ b/themes/Atom - Light/select-list.css @@ -0,0 +1,47 @@ +.select-list { + background-color: #eeeeee; + border: 1px solid #c6c6c6; + color: #323232; + box-shadow: 0 0 10px #555; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + padding: 5px; + cursor: pointer; +} + +.select-list .editor { + border: 1px solid #afafaf; + box-shadow: inset 0 0 2px #ccc; +} + +.select-list ol { + border: 1px solid #d2d2d2; +} + +.select-list ol li { + background-color: #f5f5f5; + border-bottom: 1px solid #e6e6e6; + padding: 5px; +} + +.select-list ol li:last-child { + border-bottom: none; +} + +.select-list .editor { + margin-bottom: 5px; +} + +.select-list li:hover { + background-color: #f9f9f9; +} + +.select-list ol .selected { + background-color: #e1e1e1; +} + +.select-list .error { + font-weight: bold; + color: white; + text-shadow: 0 1px 0 #4E0000; +} \ No newline at end of file diff --git a/themes/Atom - Light/status-bar.css b/themes/Atom - Light/status-bar.css new file mode 100644 index 000000000..88995cd78 --- /dev/null +++ b/themes/Atom - Light/status-bar.css @@ -0,0 +1,61 @@ +.status-bar { + background-color: #e5e5e5; + border-top: 1px solid #959595; + padding: 4px 10px 3px; + font-size: 11px; + line-height: 14px; + color: #333; +} + +.status-bar .cursor-position, +.status-bar .grammar-name { + padding-left: 10px; +} + +.status-bar .grammar-name { + cursor: pointer; +} + +.status-bar .branch-label { + vertical-align: baseline; +} + +.status-bar .git-status.octicons { + display: none; + padding-left: 10px; + margin-top:-2px; +} + +.status-bar .octicons:before { + font-family: 'Octicons Regular'; + font-size: 14px; + width: 14px; + height: 14px; + line-height: 14px; + -webkit-font-smoothing: antialiased; + display: inline-block; + vertical-align: middle; + margin-right: 5px; +} + +.status-bar .branch-icon:before { + content: "\f020"; +} + +.status-bar .git-status.octicons.modified-status-icon { + color: #f78a46; + display: inline-block; +} + +.status-bar .modified-status-icon:before { + content: "\f26d"; +} + +.status-bar .git-status.octicons.new-status-icon { + color: #5293d8; + display: inline-block; +} + +.status-bar .new-status-icon:before { + content: "\f26b"; +} diff --git a/themes/Atom - Light/symbols-view.css b/themes/Atom - Light/symbols-view.css new file mode 100644 index 000000000..0cbdbfa53 --- /dev/null +++ b/themes/Atom - Light/symbols-view.css @@ -0,0 +1,35 @@ +.symbols-view { + width: 50%; + margin-left: -25%; +} + +.symbols-view ol { + max-height: 300px; +} + +.symbols-view ol li { + padding: 2px; + border-bottom: 1px solid rgba(255, 255, 255, .05); +} + +.symbols-view ol .function-name { + float: left; + display: inline-block; + margin-right: .5em; + margin: 4px 0; +} + +.symbols-view li .right { + float: right; +} + +.symbols-view ol .function-details { + display: inline-block; + margin: 4px 0; + margin-right: .5em; + font-size: 90%; + color: #ddd; + -webkit-border-radius: 3px; + padding: 0 4px; + background: rgba(0, 0, 0, .2); +} diff --git a/themes/Atom - Light/tabs.css b/themes/Atom - Light/tabs.css new file mode 100644 index 000000000..6b286ad61 --- /dev/null +++ b/themes/Atom - Light/tabs.css @@ -0,0 +1,116 @@ +.tabs { + background: #e3e3e3; + border-bottom: 4px solid #e5e5e5; + font: caption; + box-shadow: inset 0 -1px 0 #959595; +} + +.tab { + cursor: default; + padding: 2px 21px 2px 9px; + background-image: -webkit-linear-gradient(#e0e0e0, #bfbfbf); + border-top: none; + border-right: 1px solid #959595; + border-bottom: 1px solid #959595; + box-shadow: inset 0 0 5px #eee, 0 1px 0 #eee, inset -1px 0 0 #e0e0e0, inset 1px 0 0 #e0e0e0; + color: #323232; +} + +.tab:hover { + background-image: -webkit-linear-gradient(#e2e2e2, #e0e0e0); +} + +.tab .close-icon { + color: rgba(0,0,0,0.3); +} + +.tab.active, +.tab.active:hover { + color: #010101; +} + +.tab.active:first-child, +.tab.active:first-child:hover { + box-shadow: none; +} + +.tab.file-modified.active .close-icon { + border-color: #aaa; +} + +.tab:hover .close-icon { + color: #c8c8c8; + border-color: #c8c8c8; +} + +.tab.file-modified .close-icon { + border: 3px solid #777; + border-radius: 10px; +} + +.tab.file-modified .close-icon:before { + content: ""; +} + +.tab.active, +.tab.active:hover { + border-bottom-color: #e5e5e5; + box-shadow: inset -1px 0 0 #e0e0e0, inset 1px 0 0 #e0e0e0; + background-image: -webkit-linear-gradient(#fefefe, #e7e6e7); +} + +.tab.active:before, +.tab.active:after { + position: absolute; + bottom: -1px; + width: 4px; + height: 4px; + content: " "; + z-index: 3; + border: 1px solid #959595; +} +.tab.active:before { + border-bottom-right-radius: 4px; + border-width: 0 1px 1px 0; + box-shadow: 2px 2px 0 #e5e5e5; + left: -5px; +} +.tab.active:after { + right: -5px; + border-bottom-left-radius: 4px; + border-width: 0 0 1px 1px; + box-shadow: -2px 2px 0 #e5e5e5; +} +.tab.active:first-child:before { + display: none; +} + +.tab:hover { + background-image: -webkit-linear-gradient(#e2e2e2, #e0e0e0); +} + +.tab .file-name { + font-size: 11px; + text-shadow: 0 1px 0 #e0e0e0; +} + +.tab .close-icon { + font-family: 'Octicons Regular'; + font-size: 14px; + width: 14px; + height: 14px; + display: block; + cursor: pointer; + position: absolute; + right: 4px; + top: -1px; + -webkit-font-smoothing: antialiased; +} + +.tab .close-icon:before { + content: "\f081"; +} + +.tab .close-icon:hover { + color: #aaa; +} diff --git a/themes/Atom - Light/tree-view.css b/themes/Atom - Light/tree-view.css new file mode 100644 index 000000000..c0f599fc2 --- /dev/null +++ b/themes/Atom - Light/tree-view.css @@ -0,0 +1,201 @@ +.tree-view { + background: #dde3e8; + border-right: 1px solid #989898; +} + +.tree-view .entry { + text-shadow: 0 1px 0 #fff; +} + +.tree-view .entries { + margin-left: 12px; +} + +.tree-view .entries .file .name { + margin-left: 20px; +} + +.tree-view .directory.selected > .header > .name, +.tree-view .selected > .name { + color: #262626; +} + +.tree-view .selected > .highlight { + box-sizing: border-box; + border-top: 1px solid #97a4a7; + border-bottom: 1px solid #97a4a7; + box-shadow: 0 -1px 0 #dde4e6, 0 1px 0 #dde4e6; + background-image: -webkit-linear-gradient(#cad5d8, #bcccce); +} + +.tree-view:focus .selected > .highlight { + border-top: 1px solid #3D4552; + border-bottom: 1px solid #3D4552; + background-image: -webkit-linear-gradient(#7e868d, #69717b); +} + +.tree-view:focus .directory.selected > .header > .name, +.tree-view:focus .selected > .name, +.tree-view:focus .directory.selected > .header > .name:before, +.tree-view:focus .selected > .name:before { + color: #fff; + text-shadow: 0 1px 0 #000; +} + +.tree-view .directory .header { + color: #262626; +} + +.tree-view .file { + color: #262626; +} + +.tree-view .name:before { + color: #7e8692; +} + +.tree-view .entry:hover, +.tree-view .directory .header:hover .name, +.tree-view .directory .header:hover .disclosure-arrow { + color: #4e5666; +} + +.tree-view .directory .header .disclosure-arrow, +.tree-view .directory .header:hover .disclosure-arrow { + text-shadow: none; + color: #4e5666; +} + +.tree-view:focus .directory .header .disclosure-arrow, +.tree-view:focus .directory .header:hover .disclosure-arrow { + color: #3D4552; +} + +.tree-view .file .name, +.tree-view .directory .header { + padding-top: 4px; + padding-bottom: 4px; + padding-right: 10px; +} + +.tree-view .directory .header { + padding-left: 5px; +} + +.tree-view .ignored { + color: #555; +} + +.tree-view .modified { + color: #f78a46; +} + +.tree-view .new { + color: #5293d8; +} + +.tree-view-dialog { + background-color: #e7e7e7; + border-top: 1px solid #989898; + padding: 5px; +} + +.tree-view-dialog .prompt { + padding-bottom: 3px; + font-size: 12px; + line-height: 16px; + color: #333; +} + +.tree-view-dialog .prompt span { + position: relative; + top: -1px; +} + +.tree-view-dialog .prompt:before { + font-family: 'Octicons Regular'; + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 3px; + -webkit-font-smoothing: antialiased; +} + +.tree-view-dialog .prompt.add:before { + content: "\f086"; +} + +.tree-view-dialog .prompt.move:before { + content: "\f03e"; +} + +.tree-view .directory .header .name, +.tree-view .file .name { + position: relative; + padding-left: 21px; +} + +.tree-view .directory .header .name:before, +.tree-view .file .name:before { + font-family: 'Octicons Regular'; + font-size: 16px; + width: 16px; + height: 16px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + position: absolute; + left: 0; +} + +.tree-view .disclosure-arrow:before { + font-family: 'Octicons Regular'; + font-size: 12px; + width: 12px; + height: 12px; + line-height: 16px; + margin-right: 3px; + -webkit-font-smoothing: antialiased; +} + +.tree-view .directory .header .directory-icon:before { + content: "\f016"; + top: -5px; +} + +.tree-view .directory .header .repository-icon:before { + content: "\f001"; + top: -4px; +} + +.tree-view .directory .header .submodule-icon:before { + content: "\f017"; + top: -5px; +} + +.tree-view .file .text-icon:before { + content: "\f011"; + top: -2px; +} + +.tree-view .file .image-icon:before { + content: "\f012"; + top: -2px; +} + +.tree-view .file .compressed-icon:before { + content: "\f013"; + top: -2px; +} + +.tree-view .file .pdf-icon:before { + content: "\f014"; + top: -2px; +} + +.tree-view .directory > .header .disclosure-arrow:before { + content: "\f05a"; +} + +.tree-view .directory.expanded > .header .disclosure-arrow:before { + content: "\f05b"; +} diff --git a/themes/Atom - Light/wrap-guide.css b/themes/Atom - Light/wrap-guide.css new file mode 100644 index 000000000..51660ea4c --- /dev/null +++ b/themes/Atom - Light/wrap-guide.css @@ -0,0 +1,3 @@ +.wrap-guide { + background: rgba(150, 150, 150, .30); +} diff --git a/themes/IR_Black.tmTheme b/themes/IR_Black.tmTheme deleted file mode 100644 index cbc18d0b9..000000000 --- a/themes/IR_Black.tmTheme +++ /dev/null @@ -1,810 +0,0 @@ - - - - - name - IR_Black - settings - - - settings - - background - #000000 - caret - #FFFFFF - foreground - #EDEDED - invisibles - #CAE2FB3D - lineHighlight - #FFFFFF24 - selection - #333333 - - - - name - Comment - scope - comment - settings - - fontStyle - - foreground - #7C7C7C - - - - name - Entity - scope - entity - settings - - fontStyle - - foreground - #FFD2A7 - - - - name - Keyword - scope - keyword - settings - - fontStyle - - foreground - #96CBFE - - - - name - Keyword.control - scope - keyword.control - settings - - fontStyle - - foreground - #96CBFE - - - - name - Keyword.Operator - scope - keyword.operator - settings - - foreground - #EDEDED - - - - name - Class - scope - entity.name.type - settings - - fontStyle - underline - foreground - #FFFFB6 - - - - name - Support - scope - support - settings - - fontStyle - - foreground - #FFFFB6 - - - - name - Storage - scope - storage - settings - - fontStyle - - foreground - #CFCB90 - - - - name - Storage.modifier - scope - storage.modifier - settings - - fontStyle - - foreground - #96CBFE - - - - name - Constant - scope - constant - settings - - fontStyle - - foreground - #99CC99 - - - - name - String - scope - string - settings - - fontStyle - bold - foreground - #A8FF60 - - - - name - Number - scope - constant.numeric - settings - - fontStyle - bold - foreground - #FF73FD - - - - name - Punctuation - scope - punctuation - settings - - fontStyle - - - - - name - Variable - scope - variable - settings - - fontStyle - - foreground - #C6C5FE - - - - name - Invalid – Deprecated - scope - invalid.deprecated - settings - - fontStyle - italic underline - foreground - #FD5FF1 - - - - name - Invalid – Illegal - scope - invalid.illegal - settings - - background - #562D56BF - foreground - #FD5FF1 - - - - name - ----------------------------------- - settings - - - - name - ♦ Embedded Source (Bright) - scope - text source - settings - - background - #B1B3BA08 - fontStyle - - - - - name - ♦ Entity inherited-class - scope - entity.other.inherited-class - settings - - fontStyle - italic - foreground - #9B5C2E - - - - name - ♦ String embedded-variable - scope - source string source - settings - - fontStyle - - foreground - #EDEDED - - - - name - ♦ String punctuation - scope - source string source punctuation.section.embedded - settings - - fontStyle - - foreground - #00A0A0 - - - - name - ♦ String constant - scope - string constant - settings - - fontStyle - - foreground - #00A0A0 - - - - name - ♦ String.regexp - scope - string.regexp - settings - - foreground - #E9C062 - - - - name - ♦ String.regexp.«special» - scope - string.regexp constant.character.escape, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repitition - settings - - fontStyle - - foreground - #FF8000 - - - - name - ♦ String.regexp.group - scope - string.regexp.group - settings - - background - #FFFFFF0F - fontStyle - - foreground - #C6A24F - - - - name - ♦ String.regexp.character-class - scope - string.regexp.character-class - settings - - fontStyle - - foreground - #B18A3D - - - - name - ♦ String variable - scope - string variable - settings - - fontStyle - - foreground - #8A9A95 - - - - name - ♦ Support.function - scope - support.function - settings - - fontStyle - - foreground - #DAD085 - - - - name - ♦ Support.constant - scope - support.constant - settings - - fontStyle - - foreground - #FFD2A7 - - - - name - c C/C++ Preprocessor Line - scope - meta.preprocessor.c - settings - - foreground - #8996A8 - - - - name - c C/C++ Preprocessor Directive - scope - meta.preprocessor.c keyword - settings - - fontStyle - - foreground - #AFC4DB - - - - name - j Cast - scope - meta.cast - settings - - fontStyle - italic - foreground - #676767 - - - - name - ✘ Doctype/XML Processing - scope - meta.sgml.html meta.doctype, meta.sgml.html meta.doctype entity, meta.sgml.html meta.doctype string, meta.xml-processing, meta.xml-processing entity, meta.xml-processing string - settings - - foreground - #494949 - - - - name - ✘ Meta.tag.«all» - scope - meta.tag, meta.tag entity - settings - - fontStyle - bold - foreground - #96CBFE - - - - name - ✘ Meta.tag.inline - scope - source entity.name.tag, source entity.other.attribute-name, meta.tag.inline, meta.tag.inline entity - settings - - fontStyle - - foreground - #96CBFE - - - - name - ✘ Meta.tag.attribute-name - scope - entity.other.attribute-name - settings - - fontStyle - - foreground - #FFD7B1 - - - - name - ✘ Namespaces - scope - entity.name.tag.namespace, entity.other.attribute-name.namespace - settings - - fontStyle - - foreground - #E18964 - - - - name - § css tag-name - scope - meta.selector.css entity.name.tag - settings - - fontStyle - underline - foreground - #96CBFE - - - - name - § css:pseudo-class - scope - meta.selector.css entity.other.attribute-name.tag.pseudo-class - settings - - fontStyle - - foreground - #8F9D6A - - - - name - § css#id - scope - meta.selector.css entity.other.attribute-name.id - settings - - fontStyle - - foreground - #8B98AB - - - - name - § css.class - scope - meta.selector.css entity.other.attribute-name.class - settings - - fontStyle - - foreground - #62B1FE - - - - name - § css property-name: - scope - support.type.property-name.css - settings - - foreground - #EDEDED - - - - name - § css property-value; - scope - meta.property-group support.constant.property-value.css, meta.property-value support.constant.property-value.css - settings - - fontStyle - - foreground - #F9EE98 - - - - name - § css @at-rule - scope - meta.preprocessor.at-rule keyword.control.at-rule - settings - - foreground - #8693A5 - - - - name - § css additional-constants - scope - meta.property-value support.constant.named-color.css, meta.property-value constant - settings - - fontStyle - - foreground - #87C38A - - - - name - § css constructor.argument - scope - meta.constructor.argument.css - settings - - foreground - #8F9D6A - - - - name - ⎇ diff.header - scope - meta.diff, meta.diff.header - settings - - background - #0E2231 - fontStyle - italic - foreground - #F8F8F8 - - - - name - ⎇ diff.deleted - scope - markup.deleted - settings - - background - #420E09 - foreground - #F8F8F8 - - - - name - ⎇ diff.changed - scope - markup.changed - settings - - background - #4A410D - foreground - #F8F8F8 - - - - name - ⎇ diff.inserted - scope - markup.inserted - settings - - background - #253B22 - foreground - #F8F8F8 - - - - name - -------------------------------- - settings - - - - name - Markup: Italic - scope - markup.italic - settings - - fontStyle - italic - foreground - #E9C062 - - - - name - Markup: Bold - scope - markup.bold - settings - - fontStyle - bold - foreground - #E9C062 - - - - name - Markup: Underline - scope - markup.underline - settings - - fontStyle - underline - foreground - #E18964 - - - - name - Markup: Quote - scope - markup.quote - settings - - background - #FEE09C12 - fontStyle - italic - foreground - #E1D4B9 - - - - name - Markup: Heading - scope - markup.heading, markup.heading entity - settings - - background - #632D04 - fontStyle - - foreground - #FEDCC5 - - - - name - Markup: List - scope - markup.list - settings - - foreground - #E1D4B9 - - - - name - Markup: Raw - scope - markup.raw - settings - - background - #B1B3BA08 - fontStyle - - foreground - #578BB3 - - - - name - Markup: Comment - scope - markup comment - settings - - fontStyle - italic - foreground - #F67B37 - - - - name - Markup: Separator - scope - meta.separator - settings - - background - #242424 - foreground - #60A633 - - - - name - Log Entry - scope - meta.line.entry.logfile, meta.line.exit.logfile - settings - - background - #EEEEEE29 - - - - name - Log Entry Error - scope - meta.line.error.logfile - settings - - background - #751012 - - - - uuid - D039AEA9-9DD2-4237-A963-E84494B0B3FB - - diff --git a/themes/All Hallow's Eve.tmTheme b/vendor/themes/All Hallow's Eve.tmTheme similarity index 100% rename from themes/All Hallow's Eve.tmTheme rename to vendor/themes/All Hallow's Eve.tmTheme diff --git a/themes/Amy.tmTheme b/vendor/themes/Amy.tmTheme similarity index 100% rename from themes/Amy.tmTheme rename to vendor/themes/Amy.tmTheme diff --git a/themes/Blackboard.tmTheme b/vendor/themes/Blackboard.tmTheme similarity index 100% rename from themes/Blackboard.tmTheme rename to vendor/themes/Blackboard.tmTheme diff --git a/themes/Brilliance Black.tmTheme b/vendor/themes/Brilliance Black.tmTheme similarity index 100% rename from themes/Brilliance Black.tmTheme rename to vendor/themes/Brilliance Black.tmTheme diff --git a/themes/Brilliance Dull.tmTheme b/vendor/themes/Brilliance Dull.tmTheme similarity index 100% rename from themes/Brilliance Dull.tmTheme rename to vendor/themes/Brilliance Dull.tmTheme diff --git a/themes/Cobalt.tmTheme b/vendor/themes/Cobalt.tmTheme similarity index 100% rename from themes/Cobalt.tmTheme rename to vendor/themes/Cobalt.tmTheme diff --git a/themes/Dawn.tmTheme b/vendor/themes/Dawn.tmTheme similarity index 100% rename from themes/Dawn.tmTheme rename to vendor/themes/Dawn.tmTheme diff --git a/themes/Espresso Libre.tmTheme b/vendor/themes/Espresso Libre.tmTheme similarity index 100% rename from themes/Espresso Libre.tmTheme rename to vendor/themes/Espresso Libre.tmTheme diff --git a/themes/IDLE.tmTheme b/vendor/themes/IDLE.tmTheme similarity index 100% rename from themes/IDLE.tmTheme rename to vendor/themes/IDLE.tmTheme diff --git a/.atom/themes/IR_Black.tmTheme b/vendor/themes/IR_Black.tmTheme similarity index 100% rename from .atom/themes/IR_Black.tmTheme rename to vendor/themes/IR_Black.tmTheme diff --git a/themes/LAZY.tmTheme b/vendor/themes/LAZY.tmTheme similarity index 100% rename from themes/LAZY.tmTheme rename to vendor/themes/LAZY.tmTheme diff --git a/themes/Mac Classic.tmTheme b/vendor/themes/Mac Classic.tmTheme similarity index 100% rename from themes/Mac Classic.tmTheme rename to vendor/themes/Mac Classic.tmTheme diff --git a/themes/MagicWB (Amiga).tmTheme b/vendor/themes/MagicWB (Amiga).tmTheme similarity index 100% rename from themes/MagicWB (Amiga).tmTheme rename to vendor/themes/MagicWB (Amiga).tmTheme diff --git a/vendor/themes/Monokai.tmTheme b/vendor/themes/Monokai.tmTheme new file mode 100755 index 000000000..496ef6c2a --- /dev/null +++ b/vendor/themes/Monokai.tmTheme @@ -0,0 +1,289 @@ + + + + + name + Monokai + settings + + + settings + + background + #272822 + caret + #F8F8F0 + foreground + #F8F8F2 + invisibles + #3B3A32 + lineHighlight + #3E3D32 + selection + #49483E + + + + name + Comment + scope + comment + settings + + foreground + #75715E + + + + name + String + scope + string + settings + + foreground + #E6DB74 + + + + name + Number + scope + constant.numeric + settings + + foreground + #AE81FF + + + + name + Built-in constant + scope + constant.language + settings + + foreground + #AE81FF + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #AE81FF + + + + name + Variable + scope + variable + settings + + fontStyle + + + + + name + Keyword + scope + keyword + settings + + foreground + #F92672 + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #F92672 + + + + name + Storage type + scope + storage.type + settings + + fontStyle + italic + foreground + #66D9EF + + + + name + Class name + scope + entity.name.class + settings + + fontStyle + underline + foreground + #A6E22E + + + + name + Inherited class + scope + entity.other.inherited-class + settings + + fontStyle + italic underline + foreground + #A6E22E + + + + name + Function name + scope + entity.name.function + settings + + fontStyle + + foreground + #A6E22E + + + + name + Function argument + scope + variable.parameter + settings + + fontStyle + italic + foreground + #FD971F + + + + name + Tag name + scope + entity.name.tag + settings + + fontStyle + + foreground + #F92672 + + + + name + Tag attribute + scope + entity.other.attribute-name + settings + + fontStyle + + foreground + #A6E22E + + + + name + Library function + scope + support.function + settings + + fontStyle + + foreground + #66D9EF + + + + name + Library constant + scope + support.constant + settings + + fontStyle + + foreground + #66D9EF + + + + name + Library class/type + scope + support.type, support.class + settings + + fontStyle + italic + foreground + #66D9EF + + + + name + Library variable + scope + support.other.variable + settings + + fontStyle + + + + + name + Invalid + scope + invalid + settings + + background + #F92672 + fontStyle + + foreground + #F8F8F0 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #AE81FF + foreground + #F8F8F0 + + + + uuid + D8D5E82E-3D5B-46B5-B38E-8C841C21347D + + diff --git a/themes/Pastels on Dark.tmTheme b/vendor/themes/Pastels on Dark.tmTheme similarity index 100% rename from themes/Pastels on Dark.tmTheme rename to vendor/themes/Pastels on Dark.tmTheme diff --git a/themes/Slush & Poppies.tmTheme b/vendor/themes/Slush & Poppies.tmTheme similarity index 100% rename from themes/Slush & Poppies.tmTheme rename to vendor/themes/Slush & Poppies.tmTheme diff --git a/themes/Solarized (dark).tmTheme b/vendor/themes/Solarized (dark).tmTheme similarity index 100% rename from themes/Solarized (dark).tmTheme rename to vendor/themes/Solarized (dark).tmTheme diff --git a/themes/SpaceCadet.tmTheme b/vendor/themes/SpaceCadet.tmTheme similarity index 100% rename from themes/SpaceCadet.tmTheme rename to vendor/themes/SpaceCadet.tmTheme diff --git a/themes/Sunburst.tmTheme b/vendor/themes/Sunburst.tmTheme similarity index 100% rename from themes/Sunburst.tmTheme rename to vendor/themes/Sunburst.tmTheme diff --git a/themes/Twilight.tmTheme b/vendor/themes/Twilight.tmTheme similarity index 100% rename from themes/Twilight.tmTheme rename to vendor/themes/Twilight.tmTheme diff --git a/themes/Zenburnesque.tmTheme b/vendor/themes/Zenburnesque.tmTheme similarity index 100% rename from themes/Zenburnesque.tmTheme rename to vendor/themes/Zenburnesque.tmTheme diff --git a/themes/iPlastic.tmTheme b/vendor/themes/iPlastic.tmTheme similarity index 100% rename from themes/iPlastic.tmTheme rename to vendor/themes/iPlastic.tmTheme