From 219aaca0f52f8bb34bb502823f06b2c951b3c670 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Dec 2012 10:41:02 -0800 Subject: [PATCH 01/18] Show diff stat in status bar Include the number of lines added and removed for new and modified files --- native/v8_extensions/git.js | 2 + native/v8_extensions/git.mm | 80 +++++++++++++++++++ src/app/git.coffee | 4 + .../status-bar/spec/status-bar-spec.coffee | 9 +++ src/packages/status-bar/src/status-bar.coffee | 12 ++- static/status-bar.css | 5 +- 6 files changed, 108 insertions(+), 4 deletions(-) diff --git a/native/v8_extensions/git.js b/native/v8_extensions/git.js index b240204ff..60de65ed1 100644 --- a/native/v8_extensions/git.js +++ b/native/v8_extensions/git.js @@ -7,6 +7,7 @@ var $git = {}; native function getStatus(path); native function isIgnored(path); native function checkoutHead(path); + native function getDiffStats(path); function GitRepository(path) { var repo = getRepository(path); @@ -20,5 +21,6 @@ var $git = {}; GitRepository.prototype.getStatus = getStatus; GitRepository.prototype.isIgnored = isIgnored; GitRepository.prototype.checkoutHead = checkoutHead; + GitRepository.prototype.getDiffStats = getDiffStats; this.GitRepository = GitRepository; })(); diff --git a/native/v8_extensions/git.mm b/native/v8_extensions/git.mm index 5ac5f23b7..9997feddd 100644 --- a/native/v8_extensions/git.mm +++ b/native/v8_extensions/git.mm @@ -105,6 +105,80 @@ public: } } + CefRefPtr GetDiffStats(const char *path) { + if (!exists) { + return CefV8Value::CreateNull(); + } + + char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); + strcpy(copiedPath, path); + git_diff_options options; + memset(&options, 0, sizeof(options)); + git_strarray paths; + paths.count = 1; + paths.strings = &copiedPath; + options.pathspec = paths; + options.context_lines = 1; + options.flags = GIT_DIFF_DISABLE_PATHSPEC_MATCH; + + git_reference *head; + if (git_repository_head(&head, repo) != GIT_OK) { + return CefV8Value::CreateNull(); + } + + const git_oid* sha = git_reference_oid(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(); + } + + git_diff_list *diffs; + int diffStatus = git_diff_workdir_to_tree(repo, &options, tree, &diffs); + if (diffStatus != GIT_OK) { + 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[2]; + lineType[1] = '\0'; + if (git_diff_patch_get_line_in_hunk(lineType, NULL, NULL, NULL, NULL, patch, i, j) == GIT_OK) { + if (strcmp(lineType, "+") == 0) { + added++; + } else if(strcmp(lineType, "-") == 0) { + deleted++; + } + } + } + } + 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; + } + IMPLEMENT_REFCOUNTING(GitRepository); }; @@ -156,6 +230,12 @@ bool Git::Execute(const CefString& name, return true; } + if (name == "getDiffStats") { + GitRepository *userData = (GitRepository *)object->GetUserData().get(); + retval = userData->GetDiffStats(arguments[0]->GetStringValue().ToString().c_str()); + return true; + } + return false; } diff --git a/src/app/git.coffee b/src/app/git.coffee index ea4127744..c8369a53c 100644 --- a/src/app/git.coffee +++ b/src/app/git.coffee @@ -63,3 +63,7 @@ class Git checkoutHead: (path) -> @repo.checkoutHead(@relativize(path)) + + getDiffStats: (path) -> + stats = @repo.getDiffStats(@relativize(path)) + stats or {'added': 0, 'deleted': 0} diff --git a/src/packages/status-bar/spec/status-bar-spec.coffee b/src/packages/status-bar/spec/status-bar-spec.coffee index 3f9f47d11..e0ad16b1e 100644 --- a/src/packages/status-bar/spec/status-bar-spec.coffee +++ b/src/packages/status-bar/spec/status-bar-spec.coffee @@ -166,3 +166,12 @@ describe "StatusBar", -> fs.write(path, originalPathText) $(window).trigger 'focus' expect(statusBar.gitStatusIcon).not.toHaveClass('modified-status-icon') + + it "displays the diff stat for modified files", -> + fs.write(path, "i've changed for the worse") + rootView.open(path) + expect(statusBar.gitStatusIcon).toHaveText('+1,-1') + + it "displays the diff stat for new files", -> + rootView.open(newPath) + expect(statusBar.gitStatusIcon).toHaveText('+1') diff --git a/src/packages/status-bar/src/status-bar.coffee b/src/packages/status-bar/src/status-bar.coffee index 83a3e4833..fc9080cc7 100644 --- a/src/packages/status-bar/src/status-bar.coffee +++ b/src/packages/status-bar/src/status-bar.coffee @@ -79,8 +79,18 @@ class StatusBar extends View @gitStatusIcon.removeClass().addClass('git-status octicons') if @buffer.getGit()?.isPathModified(path) @gitStatusIcon.addClass('modified-status-icon') - else if @buffer.getGit()?.isPathNew(path) + stats = @buffer.getGit().getDiffStats(path) + if stats.added and stats.deleted + @gitStatusIcon.text("+#{stats.added},-#{stats.deleted}") + else if stats.added + @gitStatusIcon.text("+#{stats.added}") + else if stats.deleted + @gitStatusIcon.text("-#{stats.deleted}") + else + @gitStatusIcon.text('') + else if @buffer.getGit()?.isPathNew(path) @gitStatusIcon.addClass('new-status-icon') + @gitStatusIcon.text("+#{@buffer.getLineCount()}") updatePathText: -> if path = @editor.getPath() diff --git a/static/status-bar.css b/static/status-bar.css index b3e6c1069..09ea8bb29 100644 --- a/static/status-bar.css +++ b/static/status-bar.css @@ -17,7 +17,6 @@ } .status-bar .branch-label { - padding-left: 5px; vertical-align: baseline; } @@ -27,7 +26,7 @@ margin-top:-2px; } -.status-bar .octicons { +.status-bar .octicons:before { font-family: 'Octicons Regular'; font-size: 14px; width: 14px; @@ -36,6 +35,7 @@ -webkit-font-smoothing: antialiased; display: inline-block; vertical-align: middle; + margin-right: 5px; } .status-bar .branch-icon:before { @@ -59,4 +59,3 @@ .status-bar .new-status-icon:before { content: "\f26b"; } - From d3ed0fca27e484f9b3ea8708cb20bdd795aae977 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Dec 2012 10:51:35 -0800 Subject: [PATCH 02/18] Free reference before returning result --- native/v8_extensions/git.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/native/v8_extensions/git.mm b/native/v8_extensions/git.mm index 9997feddd..3c572504d 100644 --- a/native/v8_extensions/git.mm +++ b/native/v8_extensions/git.mm @@ -37,10 +37,14 @@ public: 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); } } - return CefV8Value::CreateString(git_reference_name(head)); + + CefRefPtr result = CefV8Value::CreateString(git_reference_name(head)); + git_reference_free(head); + return result; } return CefV8Value::CreateNull(); From a561d5efab17e7d7a450af2aad1a9dd3ca232f2e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Dec 2012 10:53:13 -0800 Subject: [PATCH 03/18] Only create diff options when necessary --- native/v8_extensions/git.mm | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/native/v8_extensions/git.mm b/native/v8_extensions/git.mm index 3c572504d..e767b66fa 100644 --- a/native/v8_extensions/git.mm +++ b/native/v8_extensions/git.mm @@ -114,17 +114,6 @@ public: return CefV8Value::CreateNull(); } - char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); - strcpy(copiedPath, path); - git_diff_options options; - memset(&options, 0, sizeof(options)); - git_strarray paths; - paths.count = 1; - paths.strings = &copiedPath; - options.pathspec = paths; - options.context_lines = 1; - options.flags = GIT_DIFF_DISABLE_PATHSPEC_MATCH; - git_reference *head; if (git_repository_head(&head, repo) != GIT_OK) { return CefV8Value::CreateNull(); @@ -145,6 +134,17 @@ public: return CefV8Value::CreateNull(); } + char *copiedPath = (char *)malloc(sizeof(char) * (strlen(path) + 1)); + strcpy(copiedPath, path); + git_diff_options options; + memset(&options, 0, sizeof(options)); + 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_workdir_to_tree(repo, &options, tree, &diffs); if (diffStatus != GIT_OK) { From d328db65f226263d9edb7d52be540daaa2ce7399 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Dec 2012 10:54:06 -0800 Subject: [PATCH 04/18] Free path after generating diff list --- native/v8_extensions/git.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/native/v8_extensions/git.mm b/native/v8_extensions/git.mm index e767b66fa..43f7e6d3f 100644 --- a/native/v8_extensions/git.mm +++ b/native/v8_extensions/git.mm @@ -147,6 +147,7 @@ public: git_diff_list *diffs; int diffStatus = git_diff_workdir_to_tree(repo, &options, tree, &diffs); + free(copiedPath); if (diffStatus != GIT_OK) { return CefV8Value::CreateNull(); } From d97651d19ad70538d18fe16bb62f4d0248b201db Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 13:38:50 -0800 Subject: [PATCH 05/18] These importants are too harsh. and not necessary --- src/packages/tabs/src/tabs.css | 4 ++-- static/atom.css | 2 +- static/editor.css | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/packages/tabs/src/tabs.css b/src/packages/tabs/src/tabs.css index dc4be74fa..ba9b60995 100644 --- a/src/packages/tabs/src/tabs.css +++ b/src/packages/tabs/src/tabs.css @@ -1,7 +1,7 @@ .tabs { background: #333333; border-bottom: 4px solid #424242; - font: caption !important; + font: caption; } .tab { @@ -71,7 +71,7 @@ } .tab .file-name { - font-size: 11px !important; + font-size: 11px; display: block; overflow: hidden; white-space: nowrap; diff --git a/static/atom.css b/static/atom.css index d666aaac3..d43d6c5ba 100644 --- a/static/atom.css +++ b/static/atom.css @@ -1,5 +1,5 @@ html, body { - font: caption !important; + font: caption; width: 100%; height: 100%; overflow: hidden; diff --git a/static/editor.css b/static/editor.css index f95816056..000420ce1 100644 --- a/static/editor.css +++ b/static/editor.css @@ -6,7 +6,7 @@ -webkit-box-flex: 1; position: relative; z-index: 0; - font-family: Inconsolata, Monaco, Courier !important; + font-family: Inconsolata, Monaco, Courier; } .editor.mini { From 4f433ce0e83a81187042aa968b5fbe1f4823901a Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 21:01:17 -0800 Subject: [PATCH 06/18] Changing the close icon when the tab is modified --- src/packages/tabs/src/tab.coffee | 20 ++++++++++++++++++++ src/packages/tabs/src/tabs.css | 14 ++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/packages/tabs/src/tab.coffee b/src/packages/tabs/src/tab.coffee index 67935a3d5..7c472fd5c 100644 --- a/src/packages/tabs/src/tab.coffee +++ b/src/packages/tabs/src/tab.coffee @@ -11,6 +11,26 @@ class Tab extends View @updateFileName() @editSession.on 'buffer-path-change.tab', => @updateFileName() + @subscribeToBuffer() + + updateTab: -> + @updateBufferHasModifiedText(@buffer.isModified()) + + subscribeToBuffer: -> + @buffer?.off '.tabs' + @buffer = @editSession.buffer + @buffer.on 'contents-modified.tabs', (e) => @updateBufferHasModifiedText(e.differsFromDisk) + @buffer.on 'after-save.tabs', => @updateTab() + @buffer.on 'git-status-change.tabs', => @updateTab() + @updateTab() + + updateBufferHasModifiedText: (differsFromDisk) -> + if differsFromDisk + @toggleClass('file-modified') unless @isModified + @isModified = true + else + @removeClass('file-modified') if @isModified + @isModified = false updateFileName: -> @fileName.text(@editSession.buffer.getBaseName() ? 'untitled') diff --git a/src/packages/tabs/src/tabs.css b/src/packages/tabs/src/tabs.css index ba9b60995..d4d099a95 100644 --- a/src/packages/tabs/src/tabs.css +++ b/src/packages/tabs/src/tabs.css @@ -21,6 +21,20 @@ height: 24px; } +.tab.file-modified .close-icon { + box-shadow: inset 0 1px 2px #333; + background-color: #F9EE98; + top: 8px; + border-radius: 10px; + width: 7px; + height: 7px; + right: 7px; +} + +.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; } From 4fa92c72c2d08a871d5655c1d608331931ced5fb Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 21:04:18 -0800 Subject: [PATCH 07/18] matching the status-bar modified color to the tab color --- static/status-bar.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/status-bar.css b/static/status-bar.css index 09ea8bb29..457920340 100644 --- a/static/status-bar.css +++ b/static/status-bar.css @@ -43,7 +43,7 @@ } .status-bar .git-status.octicons.modified-status-icon { - color: #f78a46; + color: #F9EE98; display: inline-block; } From f07f42fc388f7773f5f36f8f85a996259fc3bf34 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Dec 2012 14:10:16 -0800 Subject: [PATCH 08/18] Add higher z-index to tree view dialog --- static/tree-view.css | 1 + 1 file changed, 1 insertion(+) diff --git a/static/tree-view.css b/static/tree-view.css index 18751fad1..5f148dfac 100644 --- a/static/tree-view.css +++ b/static/tree-view.css @@ -80,6 +80,7 @@ color: white; border: 2px solid #222; -webkit-box-shadow: 0 0 3px 3px rgba(0, 0, 0, .5); + z-index: 99; } .tree-view .directory .header .name, From 575e34d5e49b199d05b4d28f2f54f5b8ab5173d5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Dec 2012 21:53:43 -0800 Subject: [PATCH 09/18] Forward window focus when active element is body This problem was when the focus element is detached when navigating away from the window and when the window is then given focus again nothing has focus. The solution is to use RootView's focus handler on the window to bring focus to the editor or other view when the document's active element is the body meaning nothing inside the RootView currently has focus. --- src/app/root-view.coffee | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/app/root-view.coffee b/src/app/root-view.coffee index 957ec6713..059c983df 100644 --- a/src/app/root-view.coffee +++ b/src/app/root-view.coffee @@ -55,20 +55,24 @@ class RootView extends View panesViewState: @panes.children().view()?.serialize() extensionStates: @serializeExtensions() - handleEvents: -> - @on 'toggle-dev-tools', => atom.toggleDevTools() - @on 'focus', (e) => - if @getActiveEditor() - @getActiveEditor().focus() + handleFocus: (e) -> + if @getActiveEditor() + @getActiveEditor().focus() + false + else + @setTitle(null) + focusableChild = this.find("[tabindex=-1]:visible:first") + if focusableChild.length + focusableChild.focus() false else - @setTitle(null) - focusableChild = this.find("[tabindex=-1]:visible:first") - if focusableChild.length - focusableChild.focus() - false - else - true + true + + handleEvents: -> + @on 'toggle-dev-tools', => atom.toggleDevTools() + @on 'focus', (e) => @handleFocus(e) + $(window).on 'focus', (e) => + @handleFocus(e) if document.activeElement is document.body @on 'active-editor-path-change', (e, path) => @project.setPath(path) unless @project.getRootDirectory() From 6c66f20d68e8affdc3dfe8e00d59a2543c82a4b0 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 22:23:08 -0800 Subject: [PATCH 10/18] using `@subscribe` to subscribe to the buffer for garbage collection --- src/packages/tabs/src/tab.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/packages/tabs/src/tab.coffee b/src/packages/tabs/src/tab.coffee index 7c472fd5c..2d46e09c4 100644 --- a/src/packages/tabs/src/tab.coffee +++ b/src/packages/tabs/src/tab.coffee @@ -17,11 +17,10 @@ class Tab extends View @updateBufferHasModifiedText(@buffer.isModified()) subscribeToBuffer: -> - @buffer?.off '.tabs' @buffer = @editSession.buffer - @buffer.on 'contents-modified.tabs', (e) => @updateBufferHasModifiedText(e.differsFromDisk) - @buffer.on 'after-save.tabs', => @updateTab() - @buffer.on 'git-status-change.tabs', => @updateTab() + @subscribe @buffer, 'contents-modified.tabs', (e) => @updateBufferHasModifiedText(e.differsFromDisk) + @subscribe @buffer, 'after-save.tabs', => @updateTab() + @subscribe @buffer, 'git-status-change.tabs', => @updateTab() @updateTab() updateBufferHasModifiedText: (differsFromDisk) -> From c0fc67bb3b50c63e482ffc011e349203beb1e0a5 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 22:23:21 -0800 Subject: [PATCH 11/18] matching the circle color to the x --- src/packages/tabs/src/tabs.css | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/packages/tabs/src/tabs.css b/src/packages/tabs/src/tabs.css index d4d099a95..458fe74f3 100644 --- a/src/packages/tabs/src/tabs.css +++ b/src/packages/tabs/src/tabs.css @@ -22,13 +22,12 @@ } .tab.file-modified .close-icon { - box-shadow: inset 0 1px 2px #333; - background-color: #F9EE98; - top: 8px; + border: 3px solid #777; + top: 6px; border-radius: 10px; - width: 7px; - height: 7px; - right: 7px; + width: 5px; + height: 5px; + right: 5px; } .tab.file-modified .close-icon:before { From 5289705602fa831a33ff6ac26823fae4e990c78f Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 22:39:09 -0800 Subject: [PATCH 12/18] Adjusting the text and icon colors in the tabs --- src/packages/tabs/src/tabs.css | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/packages/tabs/src/tabs.css b/src/packages/tabs/src/tabs.css index 458fe74f3..8ddf33b0f 100644 --- a/src/packages/tabs/src/tabs.css +++ b/src/packages/tabs/src/tabs.css @@ -8,7 +8,6 @@ cursor: default; padding: 2px 21px 2px 9px; background-image: -webkit-linear-gradient(#444, #3d3d3d); - color: #a5aaaa; display: table-cell; position: relative; width:175px; @@ -21,6 +20,30 @@ height: 24px; } +.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; top: 6px; @@ -45,7 +68,6 @@ .tab.active, .tab.active:hover { - color: #dae6e6; border-top: 1px solid #4a4a4a; box-shadow: inset -1px 0 0 #595959, inset 1px 0 0 #595959; border-bottom: 0 none; @@ -79,7 +101,7 @@ } .tab:hover { - color: #c8c8c5; + color: #c8c8c8; background-image: -webkit-linear-gradient(#474747, #444444); } @@ -103,7 +125,6 @@ width: 14px; height: 14px; display: block; - color: #777; cursor: pointer; position: absolute; right: 4px; From 51e9cdbb94e85b977eede7d08494aaa3790e305f Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 22:48:23 -0800 Subject: [PATCH 13/18] removing the gradient from the status bar, and adding padding around command-panel --- static/command-panel.css | 4 ++-- static/status-bar.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/static/command-panel.css b/static/command-panel.css index 13cab5f5f..e404f7ddd 100644 --- a/static/command-panel.css +++ b/static/command-panel.css @@ -1,6 +1,6 @@ .command-panel { background: #515151; - padding: 3px; + padding: 5px; } .command-panel .preview-list { @@ -45,7 +45,7 @@ .command-panel .prompt { color: white; font-weight: bold; - padding: .2em; + padding-right: 5px; } .error-messages { diff --git a/static/status-bar.css b/static/status-bar.css index 457920340..b41bf54db 100644 --- a/static/status-bar.css +++ b/static/status-bar.css @@ -1,5 +1,5 @@ .status-bar { - background-image: -webkit-linear-gradient(#303030, #252525); + background-color: #303030; border-top: 1px solid #454545; padding: 4px 10px 3px; font-size: 11px; From f225b88bb2221ad05fd8c8c8c90f68267d1e5b13 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 22:59:23 -0800 Subject: [PATCH 14/18] Revert "don't close the tree view on cmd-w" This reverts commit ef48c355fbabbb668d723dfea74a696382828d81. --- src/packages/tree-view/src/tree-view.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/tree-view/src/tree-view.coffee b/src/packages/tree-view/src/tree-view.coffee index 92a7b4af8..a8c01378e 100644 --- a/src/packages/tree-view/src/tree-view.coffee +++ b/src/packages/tree-view/src/tree-view.coffee @@ -48,7 +48,7 @@ class TreeView extends ScrollView @on 'click', '.entry', (e) => @entryClicked(e) @command 'core:move-up', => @moveUp() @command 'core:move-down', => @moveDown() - @command 'core:close', => false + @command 'core:close', => @detach(); false @command 'tree-view:expand-directory', => @expandDirectory() @command 'tree-view:collapse-directory', => @collapseDirectory() @command 'tree-view:open-selected-entry', => @openSelectedEntry(true) From b88d097a429c9152a3e7b326494a66ff6b54bb9f Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Thu, 27 Dec 2012 22:59:36 -0800 Subject: [PATCH 15/18] Revert "removing the tree view core:close test, because cmd-w no longer closes the sidebar." This reverts commit ab144a6d312765a37aba0bc4bd9dd9d6bc3839f1. --- src/packages/tree-view/spec/tree-view-spec.coffee | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee index 65da47380..fbdca2edd 100644 --- a/src/packages/tree-view/spec/tree-view-spec.coffee +++ b/src/packages/tree-view/spec/tree-view-spec.coffee @@ -194,6 +194,19 @@ describe "TreeView", -> expect(treeView).not.toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeTruthy() + describe "when core:close is triggered on the tree view", -> + it "detaches the TreeView, focuses the RootView and does not bubble the core:close event", -> + treeView.attach() + treeView.focus() + rootViewCloseHandler = jasmine.createSpy('rootViewCloseHandler') + rootView.on 'core:close', rootViewCloseHandler + spyOn(rootView, 'focus') + + treeView.trigger('core:close') + expect(rootView.focus).toHaveBeenCalled() + expect(rootViewCloseHandler).not.toHaveBeenCalled() + expect(treeView.hasParent()).toBeFalsy() + describe "when a directory's disclosure arrow is clicked", -> it "expands / collapses the associated directory", -> subdir = treeView.root.find('.entries > li:contains(dir1)').view() From f24f95560ee69efecc0e5f5676ab5563ce6da6d0 Mon Sep 17 00:00:00 2001 From: Jon Rohan Date: Fri, 28 Dec 2012 08:28:20 -0800 Subject: [PATCH 16/18] Orange you glad I didn't say banana --- static/status-bar.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/status-bar.css b/static/status-bar.css index b41bf54db..14ba139c7 100644 --- a/static/status-bar.css +++ b/static/status-bar.css @@ -43,7 +43,7 @@ } .status-bar .git-status.octicons.modified-status-icon { - color: #F9EE98; + color: #f78a46; display: inline-block; } From 0aa8a65903e48930ebd2061666073f0e1a59d3e5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 28 Dec 2012 08:44:57 -0800 Subject: [PATCH 17/18] Support using custom guide columns via config --- .../wrap-guide/spec/wrap-guide-spec.coffee | 42 ++++++------------- src/packages/wrap-guide/src/wrap-guide.coffee | 26 +++++++----- 2 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/packages/wrap-guide/spec/wrap-guide-spec.coffee b/src/packages/wrap-guide/spec/wrap-guide-spec.coffee index 1bc562624..6e38845be 100644 --- a/src/packages/wrap-guide/spec/wrap-guide-spec.coffee +++ b/src/packages/wrap-guide/spec/wrap-guide-spec.coffee @@ -38,39 +38,23 @@ describe "WrapGuide", -> expect(wrapGuide.position().left).toBeGreaterThan(initial) expect(wrapGuide).toBeVisible() - describe "overriding getGuideColumn", -> - it "invokes the callback with the editor path", -> - editorPath = null - wrapGuide.getGuideColumn = (path) -> - editorPath = path - 80 + describe "using a custom config column", -> + it "places the wrap guide at the custom column", -> + config.set('wrapGuide.columns', [{pattern: '\.js$', column: 20}]) wrapGuide.updateGuide() - expect(editorPath).toBe(require.resolve('fixtures/sample.js')) - - it "invokes the callback with a default value", -> - column = null - wrapGuide.getGuideColumn = (path, defaultColumn) -> - editorPath = path - column = defaultColumn - defaultColumn + width = editor.charWidth * 20 + expect(width).toBeGreaterThan(0) + expect(wrapGuide.position().left).toBe(width) + it "uses the default column when no custom column matches the path", -> + config.set('wrapGuide.columns', [{pattern: '\.jsp$', column: '100'}]) wrapGuide.updateGuide() - expect(column).toBeGreaterThan(0) + width = editor.charWidth * wrapGuide.defaultColumn + expect(width).toBeGreaterThan(0) + expect(wrapGuide.position().left).toBe(width) - # this is disabled because we no longer support passing config to an extension - # at load time. we need to convert it to use the global config vars. - xit "uses the function from the config data", -> - rootView.find('.wrap-guide').remove() - config = - getGuideColumn: -> - 1 - atom.loadPackage('wrap-guide', config) - wrapGuide = rootView.find('.wrap-guide').view() - expect(wrapGuide.getGuideColumn).toBe(config.getGuideColumn) - - it "hides the guide when the column is less than 1", -> - wrapGuide.getGuideColumn = (path) -> - -1 + it "hides the guide when the config column is less than 1", -> + config.set('wrapGuide.columns', [{pattern: 'sample\.js$', column: -1}]) wrapGuide.updateGuide() expect(wrapGuide).toBeHidden() diff --git a/src/packages/wrap-guide/src/wrap-guide.coffee b/src/packages/wrap-guide/src/wrap-guide.coffee index 8442cc736..53f62c289 100644 --- a/src/packages/wrap-guide/src/wrap-guide.coffee +++ b/src/packages/wrap-guide/src/wrap-guide.coffee @@ -1,21 +1,22 @@ {View} = require 'space-pen' $ = require 'jquery' +_ = require 'underscore' module.exports = class WrapGuide extends View - @activate: (rootView, state, config) -> + @activate: (rootView, state) -> requireStylesheet 'wrap-guide.css' for editor in rootView.getEditors() if rootView.parents('html').length - @appendToEditorPane(rootView, editor, config) + @appendToEditorPane(rootView, editor) rootView.on 'editor-open', (e, editor) => - @appendToEditorPane(rootView, editor, config) + @appendToEditorPane(rootView, editor) @appendToEditorPane: (rootView, editor, config) -> if underlayer = editor.pane()?.find('.underlayer') - underlayer.append(new WrapGuide(rootView, editor, config)) + underlayer.append(new WrapGuide(rootView, editor)) @content: -> @div class: 'wrap-guide' @@ -23,17 +24,22 @@ class WrapGuide extends View getGuideColumn: null defaultColumn: 80 - initialize: (@rootView, @editor, options = {}) => - if typeof options.getGuideColumn is 'function' - @getGuideColumn = options.getGuideColumn - else - @getGuideColumn = (path, defaultColumn) -> defaultColumn - + initialize: (@rootView, @editor) => @observeConfig 'editor.fontSize', => @updateGuide() @subscribe @editor, 'editor-path-change', => @updateGuide() @subscribe @editor, 'editor:min-width-changed', => @updateGuide() @subscribe $(window), 'resize', => @updateGuide() + getGuideColumn: (path) -> + customColumns = config.get('wrapGuide.columns') + return @defaultColumn unless _.isArray(customColumns) + for customColumn in customColumns + continue unless _.isObject(customColumn) + regex = customColumn['pattern'] + continue unless regex + return parseInt(customColumn['column']) if new RegExp(regex).test(path) + @defaultColumn + updateGuide: -> column = @getGuideColumn(@editor.getPath(), @defaultColumn) if column > 0 From 5993b04e622eab72c5e129a4c790784061fccb6a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 28 Dec 2012 09:17:23 -0800 Subject: [PATCH 18/18] Colorize new and modified files in tree view --- .../tree-view/spec/tree-view-spec.coffee | 28 +++++++++++++++++++ src/packages/tree-view/src/file-view.coffee | 8 +++++- static/tree-view.css | 8 ++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/packages/tree-view/spec/tree-view-spec.coffee b/src/packages/tree-view/spec/tree-view-spec.coffee index fbdca2edd..1923e8ada 100644 --- a/src/packages/tree-view/spec/tree-view-spec.coffee +++ b/src/packages/tree-view/spec/tree-view-spec.coffee @@ -872,3 +872,31 @@ describe "TreeView", -> config.set("core.hideGitIgnoredFiles", false) expect(treeView.find('.file:contains(tree-view.js)').length).toBe 1 + + describe "Git status decorations", -> + [ignoreFile, modifiedFile, originalFileContent] = [] + + beforeEach -> + config.set "core.hideGitIgnoredFiles", false + ignoreFile = fs.join(require.resolve('fixtures/tree-view'), '.gitignore') + fs.write(ignoreFile, 'tree-view.js') + modifiedFile = fs.join(require.resolve('fixtures/tree-view'), 'tree-view.txt') + originalFileContent = fs.read(modifiedFile) + fs.write modifiedFile, 'ch ch changes' + treeView.updateRoot() + + afterEach -> + fs.remove(ignoreFile) if fs.exists(ignoreFile) + fs.write modifiedFile, originalFileContent + + describe "when a file is modified", -> + it "adds a custom style", -> + expect(treeView.find('.file:contains(tree-view.txt)')).toHaveClass 'modified' + + describe "when a file is new", -> + it "adds a custom style", -> + expect(treeView.find('.file:contains(.gitignore)')).toHaveClass 'new' + + describe "when a file is ignored", -> + it "adds a custom style", -> + expect(treeView.find('.file:contains(tree-view.js)')).toHaveClass 'ignored' diff --git a/src/packages/tree-view/src/file-view.coffee b/src/packages/tree-view/src/file-view.coffee index ea636cbfb..ec6f15872 100644 --- a/src/packages/tree-view/src/file-view.coffee +++ b/src/packages/tree-view/src/file-view.coffee @@ -25,7 +25,13 @@ class FileView extends View else @fileName.addClass('text-name') - @addClass('ignored') if new Git(path).isPathIgnored(path) + git = new Git(path) + if git.isPathIgnored(path) + @addClass('ignored') + else if git.isPathModified(path) + @addClass('modified') + else if git.isPathNew(path) + @addClass('new') getPath: -> @file.path diff --git a/static/tree-view.css b/static/tree-view.css index 5f148dfac..dd3d1bfcb 100644 --- a/static/tree-view.css +++ b/static/tree-view.css @@ -72,6 +72,14 @@ color: #555; } +.tree-view .modified { + color: #f78a46; +} + +.tree-view .new { + color: #5293d8; +} + .tree-view-dialog { position: absolute; bottom: 0;