From ad0bbbc72d1fa166227dd1bd90f014594c6230e8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 13:52:28 -0700 Subject: [PATCH 01/17] Add initial outline view --- .atom/default-config.coffee | 1 + src/extensions/outline-view/index.coffee | 1 + src/extensions/outline-view/keymap.coffee | 2 + .../outline-view/outline-view.coffee | 83 +++++++++++++++++++ static/outline-view.css | 38 +++++++++ 5 files changed, 125 insertions(+) create mode 100644 src/extensions/outline-view/index.coffee create mode 100644 src/extensions/outline-view/keymap.coffee create mode 100644 src/extensions/outline-view/outline-view.coffee create mode 100644 static/outline-view.css diff --git a/.atom/default-config.coffee b/.atom/default-config.coffee index d394e6801..1e243478d 100644 --- a/.atom/default-config.coffee +++ b/.atom/default-config.coffee @@ -9,3 +9,4 @@ requireExtension 'snippets' requireExtension 'status-bar' requireExtension 'wrap-guide' requireExtension 'markdown-preview' +requireExtension 'outline-view' diff --git a/src/extensions/outline-view/index.coffee b/src/extensions/outline-view/index.coffee new file mode 100644 index 000000000..1a19f8519 --- /dev/null +++ b/src/extensions/outline-view/index.coffee @@ -0,0 +1 @@ +module.exports = require 'outline-view/outline-view' diff --git a/src/extensions/outline-view/keymap.coffee b/src/extensions/outline-view/keymap.coffee new file mode 100644 index 000000000..46344df44 --- /dev/null +++ b/src/extensions/outline-view/keymap.coffee @@ -0,0 +1,2 @@ +window.keymap.bindKeys '.editor' + 'ctrl-o': 'outline-view:toggle' diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee new file mode 100644 index 000000000..c3773194e --- /dev/null +++ b/src/extensions/outline-view/outline-view.coffee @@ -0,0 +1,83 @@ +{View, $$} = require 'space-pen' +SelectList = require 'select-list' +stringScore = require 'stringscore' +fuzzyFilter = require 'fuzzy-filter' +_ = require 'underscore' +Editor = require 'editor' + +module.exports = +class OutlineView extends SelectList + + @activate: (rootView) -> + requireStylesheet 'select-list.css' + requireStylesheet 'outline-view.css' + @instance = new OutlineView(rootView) + rootView.command 'outline-view:toggle', => @instance.toggle() + + @viewClass: -> "#{super} outline-view" + + filterKey: 'name' + + initialize: (@rootView) -> + super + + itemForElement: ({row, name}) -> + $$ -> + @li => + @div name, class: 'function-name' + @div class: 'right', => + @div "Line #{row}", class: 'function-line' + @div class: 'clear-float' + + toggle: -> + if @hasParent() + @cancel() + else + @populate() + @attach() + + populate: -> + editor = @rootView.getActiveEditor() + session = editor.activeEditSession + buffer = session.buffer + language = session.tokenizedBuffer.languageMode + + functions = [] + functionTester = (scope) -> + scope.indexOf('entity.name.function.') is 0 + registerFunction = (row, column, name) -> + return unless name.length > 0 + functions.push + row: row + column: column + name: name + + for row in [0...editor.getLineCount()] + line = buffer.lineForRow(row) + continue unless line.length + {tokens} = language.getLineTokens(line) + name = '' + column = 0 + for token in tokens + if _.find(token.scopes, functionTester) + name += token.value + else + registerFunction(row, column, name) + column += token.value.length + name = '' + registerFunction(row, column, name) + + @setArray(functions) + + confirmed : ({row, column, name}) -> + return unless name.length + @cancel() + @rootView.getActiveEditor().setCursorBufferPosition([row, column]) + + cancelled: -> + @miniEditor.setText('') + @rootView.focus() if @miniEditor.isFocused + + attach: -> + @rootView.append(this) + @miniEditor.focus() diff --git a/static/outline-view.css b/static/outline-view.css new file mode 100644 index 000000000..1b67d9139 --- /dev/null +++ b/static/outline-view.css @@ -0,0 +1,38 @@ +.outline-view { + width: 50%; + margin-left: -25%; +} + +.outline-view ol { + max-height: 300px; +} + +.outline-view ol li { + padding: 2px; + border-bottom: 1px solid rgba(255, 255, 255, .05); +} + +.outline-view ol .function-name { + float: left; + display: inline-block; + margin-right: .5em; + margin: 4px 0; +} + +.outline-view li .right { + float: right; +} + +.outline-view ol .function-line { + display: inline-block; + margin: 4px 0; + margin-right: .5em; + font-size: 90%; + color: #ddd; + -webkit-border-radius: 3px; + padding: 0 4px; +} + +.outline-view ol .function-line { + background: rgba(0, 0, 0, .2); +} From 6867405bd73239d42e9f802070fcfe5467bb5907 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 14:06:31 -0700 Subject: [PATCH 02/17] Move outline view stylesheet to extensions dir --- src/extensions/outline-view/outline-view.coffee | 2 +- {static => src/extensions/outline-view}/outline-view.css | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {static => src/extensions/outline-view}/outline-view.css (100%) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index c3773194e..3de95f983 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -10,7 +10,7 @@ class OutlineView extends SelectList @activate: (rootView) -> requireStylesheet 'select-list.css' - requireStylesheet 'outline-view.css' + requireStylesheet 'outline-view/outline-view.css' @instance = new OutlineView(rootView) rootView.command 'outline-view:toggle', => @instance.toggle() diff --git a/static/outline-view.css b/src/extensions/outline-view/outline-view.css similarity index 100% rename from static/outline-view.css rename to src/extensions/outline-view/outline-view.css From 4a766139dcbc3e720d9db1132a98688b4659f2b4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 15:34:46 -0700 Subject: [PATCH 03/17] Use regex instead of line tokens --- .../outline-view/outline-view.coffee | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index 3de95f983..b80dd7675 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -1,7 +1,5 @@ {View, $$} = require 'space-pen' SelectList = require 'select-list' -stringScore = require 'stringscore' -fuzzyFilter = require 'fuzzy-filter' _ = require 'underscore' Editor = require 'editor' @@ -33,41 +31,28 @@ class OutlineView extends SelectList if @hasParent() @cancel() else - @populate() - @attach() + @attach() if @populate() populate: -> editor = @rootView.getActiveEditor() session = editor.activeEditSession - buffer = session.buffer - language = session.tokenizedBuffer.languageMode + language = session.tokenizedBuffer.languageMode.grammar.name + return false unless language is "CoffeeScript" functions = [] - functionTester = (scope) -> - scope.indexOf('entity.name.function.') is 0 - registerFunction = (row, column, name) -> - return unless name.length > 0 - functions.push - row: row - column: column - name: name - - for row in [0...editor.getLineCount()] - line = buffer.lineForRow(row) + functionRegex = /(\s*)(@?[a-zA-Z$_]+)\s*(=|\:)\s*(\([^\)]*\))?\s*(-|=)>/ + lineCount = editor.getLineCount() + for row in [0...lineCount] + line = session.buffer.lineForRow(row) continue unless line.length - {tokens} = language.getLineTokens(line) - name = '' - column = 0 - for token in tokens - if _.find(token.scopes, functionTester) - name += token.value - else - registerFunction(row, column, name) - column += token.value.length - name = '' - registerFunction(row, column, name) - + matches = line.match(functionRegex) + if matches + functions.push + row: row + column: matches[1].length + name: matches[2] @setArray(functions) + true confirmed : ({row, column, name}) -> return unless name.length From 7724b2db8f11e8a10e4d63d0a3f356cd324e84e9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 15:47:13 -0700 Subject: [PATCH 04/17] Use single quotes --- src/extensions/outline-view/outline-view.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index b80dd7675..c6ae117e2 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -37,7 +37,7 @@ class OutlineView extends SelectList editor = @rootView.getActiveEditor() session = editor.activeEditSession language = session.tokenizedBuffer.languageMode.grammar.name - return false unless language is "CoffeeScript" + return false unless language is 'CoffeeScript' functions = [] functionRegex = /(\s*)(@?[a-zA-Z$_]+)\s*(=|\:)\s*(\([^\)]*\))?\s*(-|=)>/ From 3152ab7219516365abea8186be409752de972fac Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 15:47:36 -0700 Subject: [PATCH 05/17] Remove unneeded check --- src/extensions/outline-view/outline-view.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index c6ae117e2..a20e135a8 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -55,7 +55,6 @@ class OutlineView extends SelectList true confirmed : ({row, column, name}) -> - return unless name.length @cancel() @rootView.getActiveEditor().setCursorBufferPosition([row, column]) From 8acb37338dca370be9f714af825699f7c5204fbb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 16:04:49 -0700 Subject: [PATCH 06/17] Add initial outline view specs --- spec/extensions/outline-view-spec.coffee | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 spec/extensions/outline-view-spec.coffee diff --git a/spec/extensions/outline-view-spec.coffee b/spec/extensions/outline-view-spec.coffee new file mode 100644 index 000000000..c68258780 --- /dev/null +++ b/spec/extensions/outline-view-spec.coffee @@ -0,0 +1,29 @@ +RootView = require 'root-view' +OutlineView = require 'outline-view' + +describe "OutlineView", -> + [rootView, outlineView] = [] + + beforeEach -> + rootView = new RootView(require.resolve('fixtures/coffee.coffee')) + rootView.activateExtension(OutlineView) + outlineView = OutlineView.instance + rootView.attachToDom() + + afterEach -> + rootView.deactivate() + + it "displays both functions", -> + expect(rootView.find('.outline-view')).not.toExist() + rootView.trigger 'outline-view:toggle' + expect(rootView.find('.outline-view')).toExist() + expect(outlineView.list.children('li').length).toBe 2 + expect(outlineView.list.find("li:contains(sort)")).toExist() + expect(outlineView.list.find("li:contains(noop)")).toExist() + expect(outlineView.list.children().first()).toHaveClass 'selected' + + it "doesn't display for unsupported languages", -> + rootView.open(require.resolve('fixtures/sample.txt')) + expect(rootView.find('.outline-view')).not.toExist() + rootView.trigger 'outline-view:toggle' + expect(rootView.find('.outline-view')).not.toExist() From f720b14f229843f7dc56c33391066535015d105b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 16:09:29 -0700 Subject: [PATCH 07/17] Don't show when empty --- spec/extensions/outline-view-spec.coffee | 6 ++++++ src/extensions/outline-view/outline-view.coffee | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/extensions/outline-view-spec.coffee b/spec/extensions/outline-view-spec.coffee index c68258780..22061b7cd 100644 --- a/spec/extensions/outline-view-spec.coffee +++ b/spec/extensions/outline-view-spec.coffee @@ -27,3 +27,9 @@ describe "OutlineView", -> expect(rootView.find('.outline-view')).not.toExist() rootView.trigger 'outline-view:toggle' expect(rootView.find('.outline-view')).not.toExist() + + it "doesn't display when no functions exist", -> + rootView.open(require.resolve('fixtures/sample-with-tabs.coffee')) + expect(rootView.find('.outline-view')).not.toExist() + rootView.trigger 'outline-view:toggle' + expect(rootView.find('.outline-view')).not.toExist() diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index a20e135a8..d241f5b39 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -52,7 +52,7 @@ class OutlineView extends SelectList column: matches[1].length name: matches[2] @setArray(functions) - true + return functions.length > 0 confirmed : ({row, column, name}) -> @cancel() From 3c74eeffbca067158004d9ee3038c6f7fd10b95b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 18:44:30 -0700 Subject: [PATCH 08/17] Use ctags to populate list --- .../outline-view/outline-view.coffee | 65 +++++++++++++------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index d241f5b39..72fb904e7 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -2,6 +2,7 @@ SelectList = require 'select-list' _ = require 'underscore' Editor = require 'editor' +ChildProcess = require 'child-process' module.exports = class OutlineView extends SelectList @@ -31,28 +32,54 @@ class OutlineView extends SelectList if @hasParent() @cancel() else - @attach() if @populate() + @populate() + + parsePrefix: (section = "") -> + if section.indexOf('class:') is 0 + section.substring(6) + else if section.indexOf('namespace:') is 0 + section.substring(10) + else if section.indexOf('file:') is 0 + section.substring(5) + else if section.indexOf('signature:') is 0 + section.substring(10) + else + section + + parseTagLine: (line) -> + sections = line.split('\t') + return null if sections.length < 4 + + label = sections[0] + line = parseInt(sections[2]) - 1 + if prefix = @parsePrefix(sections[4]) + label = "#{prefix}::#{label}" + if signature = @parsePrefix(sections[5]) + label = "#{label}#{signature}" + + tag = + row: line + column: 0 + name: label + + return tag populate: -> - editor = @rootView.getActiveEditor() - session = editor.activeEditSession - language = session.tokenizedBuffer.languageMode.grammar.name - return false unless language is 'CoffeeScript' + tags = [] + options = + bufferLines: true + stdout: (data) => + lines = data.split('\n') + for line in lines + tag = @parseTagLine(line) + tags.push(tag) if tag + if tags.length > 0 + @setArray(tags) + @attach() - functions = [] - functionRegex = /(\s*)(@?[a-zA-Z$_]+)\s*(=|\:)\s*(\([^\)]*\))?\s*(-|=)>/ - lineCount = editor.getLineCount() - for row in [0...lineCount] - line = session.buffer.lineForRow(row) - continue unless line.length - matches = line.match(functionRegex) - if matches - functions.push - row: row - column: matches[1].length - name: matches[2] - @setArray(functions) - return functions.length > 0 + path = @rootView.getActiveEditor().getPath() + command = "ctags --fields=+KS -nf - #{path}" + deferred = ChildProcess.exec command, options confirmed : ({row, column, name}) -> @cancel() From 5808609bfdfd053257e95044e3af8a77bf6f2d56 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 21:03:47 -0700 Subject: [PATCH 09/17] Display results from done callback --- src/extensions/outline-view/outline-view.coffee | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index 72fb904e7..b04e6e497 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -73,13 +73,15 @@ class OutlineView extends SelectList for line in lines tag = @parseTagLine(line) tags.push(tag) if tag - if tags.length > 0 - @setArray(tags) - @attach() path = @rootView.getActiveEditor().getPath() command = "ctags --fields=+KS -nf - #{path}" deferred = ChildProcess.exec command, options + deferred.done (stdout, stderr) => + options.stdout(stdout) + if tags.length > 0 + @setArray(tags) + @attach() confirmed : ({row, column, name}) -> @cancel() From b4b9a0c76bb893f83a2fe0a09dce37bf04442200 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 23 Oct 2012 21:30:29 -0700 Subject: [PATCH 10/17] Don't forward output on done --- src/extensions/outline-view/outline-view.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index b04e6e497..c732447ae 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -77,8 +77,7 @@ class OutlineView extends SelectList path = @rootView.getActiveEditor().getPath() command = "ctags --fields=+KS -nf - #{path}" deferred = ChildProcess.exec command, options - deferred.done (stdout, stderr) => - options.stdout(stdout) + deferred.done => if tags.length > 0 @setArray(tags) @attach() From 8fa8d4bf08c2d0e42a96ba5a06d35e850139ae6b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 24 Oct 2012 08:10:21 -0700 Subject: [PATCH 11/17] Add tag generator class --- .../outline-view/outline-view.coffee | 46 ++---------------- .../outline-view/tag-generator.coffee | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 src/extensions/outline-view/tag-generator.coffee diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index c732447ae..cafd5825b 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -2,7 +2,7 @@ SelectList = require 'select-list' _ = require 'underscore' Editor = require 'editor' -ChildProcess = require 'child-process' +TagGenerator = require 'outline-view/tag-generator' module.exports = class OutlineView extends SelectList @@ -34,50 +34,12 @@ class OutlineView extends SelectList else @populate() - parsePrefix: (section = "") -> - if section.indexOf('class:') is 0 - section.substring(6) - else if section.indexOf('namespace:') is 0 - section.substring(10) - else if section.indexOf('file:') is 0 - section.substring(5) - else if section.indexOf('signature:') is 0 - section.substring(10) - else - section - - parseTagLine: (line) -> - sections = line.split('\t') - return null if sections.length < 4 - - label = sections[0] - line = parseInt(sections[2]) - 1 - if prefix = @parsePrefix(sections[4]) - label = "#{prefix}::#{label}" - if signature = @parsePrefix(sections[5]) - label = "#{label}#{signature}" - - tag = - row: line - column: 0 - name: label - - return tag - populate: -> tags = [] - options = - bufferLines: true - stdout: (data) => - lines = data.split('\n') - for line in lines - tag = @parseTagLine(line) - tags.push(tag) if tag - + callback = (tag) -> + tags.push tag path = @rootView.getActiveEditor().getPath() - command = "ctags --fields=+KS -nf - #{path}" - deferred = ChildProcess.exec command, options - deferred.done => + new TagGenerator(path, callback).generate().done => if tags.length > 0 @setArray(tags) @attach() diff --git a/src/extensions/outline-view/tag-generator.coffee b/src/extensions/outline-view/tag-generator.coffee new file mode 100644 index 000000000..3b87f65fc --- /dev/null +++ b/src/extensions/outline-view/tag-generator.coffee @@ -0,0 +1,47 @@ +ChildProcess = require 'child-process' + +module.exports = +class TagGenerator + + constructor: (@path, @callback) -> + + parsePrefix: (section = "") -> + if section.indexOf('class:') is 0 + section.substring(6) + else if section.indexOf('namespace:') is 0 + section.substring(10) + else if section.indexOf('file:') is 0 + section.substring(5) + else if section.indexOf('signature:') is 0 + section.substring(10) + else + section + + parseTagLine: (line) -> + sections = line.split('\t') + return null if sections.length < 4 + + label = sections[0] + line = parseInt(sections[2]) - 1 + if prefix = @parsePrefix(sections[4]) + label = "#{prefix}::#{label}" + if signature = @parsePrefix(sections[5]) + label = "#{label}#{signature}" + + tag = + row: line + column: 0 + name: label + + return tag + + generate: -> + options = + bufferLines: true + stdout: (data) => + lines = data.split('\n') + for line in lines + tag = @parseTagLine(line) + @callback(tag) if tag + command = "ctags --fields=+KS -nf - #{@path}" + ChildProcess.exec(command, options) From c0feef66cc645d305506314cba2436279c16c02c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 24 Oct 2012 08:16:40 -0700 Subject: [PATCH 12/17] Increment line row by 1 in label --- src/extensions/outline-view/outline-view.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index cafd5825b..d273e9551 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -25,7 +25,7 @@ class OutlineView extends SelectList @li => @div name, class: 'function-name' @div class: 'right', => - @div "Line #{row}", class: 'function-line' + @div "Line #{row + 1}", class: 'function-line' @div class: 'clear-float' toggle: -> From 7d670b8597e91d39c7e9b848c4d6aca5265fd9c8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 24 Oct 2012 08:21:16 -0700 Subject: [PATCH 13/17] Add initial specs of TagGenerator class --- spec/extensions/outline-view-spec.coffee | 55 +++++++++++------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/spec/extensions/outline-view-spec.coffee b/spec/extensions/outline-view-spec.coffee index 22061b7cd..2a98d45f4 100644 --- a/spec/extensions/outline-view-spec.coffee +++ b/spec/extensions/outline-view-spec.coffee @@ -1,35 +1,28 @@ -RootView = require 'root-view' -OutlineView = require 'outline-view' +TagGenerator = require 'outline-view/tag-generator' describe "OutlineView", -> - [rootView, outlineView] = [] - beforeEach -> - rootView = new RootView(require.resolve('fixtures/coffee.coffee')) - rootView.activateExtension(OutlineView) - outlineView = OutlineView.instance - rootView.attachToDom() + 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].row).toBe 0 + expect(tags[1].name).toBe "quicksort.sort" + expect(tags[1].row).toBe 1 - afterEach -> - rootView.deactivate() - - it "displays both functions", -> - expect(rootView.find('.outline-view')).not.toExist() - rootView.trigger 'outline-view:toggle' - expect(rootView.find('.outline-view')).toExist() - expect(outlineView.list.children('li').length).toBe 2 - expect(outlineView.list.find("li:contains(sort)")).toExist() - expect(outlineView.list.find("li:contains(noop)")).toExist() - expect(outlineView.list.children().first()).toHaveClass 'selected' - - it "doesn't display for unsupported languages", -> - rootView.open(require.resolve('fixtures/sample.txt')) - expect(rootView.find('.outline-view')).not.toExist() - rootView.trigger 'outline-view:toggle' - expect(rootView.find('.outline-view')).not.toExist() - - it "doesn't display when no functions exist", -> - rootView.open(require.resolve('fixtures/sample-with-tabs.coffee')) - expect(rootView.find('.outline-view')).not.toExist() - rootView.trigger 'outline-view:toggle' - expect(rootView.find('.outline-view')).not.toExist() + 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 From f1a8a5d68400cd295dc122d6530abec355dd102e Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 24 Oct 2012 08:24:16 -0700 Subject: [PATCH 14/17] Store tag location in a Point --- spec/extensions/outline-view-spec.coffee | 4 ++-- src/extensions/outline-view/outline-view.coffee | 8 ++++---- src/extensions/outline-view/tag-generator.coffee | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/extensions/outline-view-spec.coffee b/spec/extensions/outline-view-spec.coffee index 2a98d45f4..d183ffe75 100644 --- a/spec/extensions/outline-view-spec.coffee +++ b/spec/extensions/outline-view-spec.coffee @@ -13,9 +13,9 @@ describe "OutlineView", -> generator.generate().done -> expect(tags.length).toBe 2 expect(tags[0].name).toBe "quicksort" - expect(tags[0].row).toBe 0 + expect(tags[0].position.row).toBe 0 expect(tags[1].name).toBe "quicksort.sort" - expect(tags[1].row).toBe 1 + expect(tags[1].position.row).toBe 1 it "generates no tags for text file", -> waitsForPromise -> diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index d273e9551..2d6780c48 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -20,12 +20,12 @@ class OutlineView extends SelectList initialize: (@rootView) -> super - itemForElement: ({row, name}) -> + itemForElement: ({position, name}) -> $$ -> @li => @div name, class: 'function-name' @div class: 'right', => - @div "Line #{row + 1}", class: 'function-line' + @div "Line #{position.row + 1}", class: 'function-line' @div class: 'clear-float' toggle: -> @@ -44,9 +44,9 @@ class OutlineView extends SelectList @setArray(tags) @attach() - confirmed : ({row, column, name}) -> + confirmed : ({position, name}) -> @cancel() - @rootView.getActiveEditor().setCursorBufferPosition([row, column]) + @rootView.getActiveEditor().setCursorBufferPosition(position) cancelled: -> @miniEditor.setText('') diff --git a/src/extensions/outline-view/tag-generator.coffee b/src/extensions/outline-view/tag-generator.coffee index 3b87f65fc..c0079fbde 100644 --- a/src/extensions/outline-view/tag-generator.coffee +++ b/src/extensions/outline-view/tag-generator.coffee @@ -1,3 +1,4 @@ +Point = require 'point' ChildProcess = require 'child-process' module.exports = @@ -29,8 +30,7 @@ class TagGenerator label = "#{label}#{signature}" tag = - row: line - column: 0 + position: new Point(line, 0) name: label return tag From de1543619cb23fced7636407efbc57d688cdfc16 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 24 Oct 2012 08:32:38 -0700 Subject: [PATCH 15/17] Remove unneeded require --- src/extensions/outline-view/outline-view.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/extensions/outline-view/outline-view.coffee b/src/extensions/outline-view/outline-view.coffee index 2d6780c48..57a94e6b4 100644 --- a/src/extensions/outline-view/outline-view.coffee +++ b/src/extensions/outline-view/outline-view.coffee @@ -1,6 +1,5 @@ {View, $$} = require 'space-pen' SelectList = require 'select-list' -_ = require 'underscore' Editor = require 'editor' TagGenerator = require 'outline-view/tag-generator' From f995cbb45cdeab3b799782b2a5a55744655e22b3 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 24 Oct 2012 14:36:46 -0700 Subject: [PATCH 16/17] :lipstick: --- src/app/editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index a5cc6633b..9cb6d4a35 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -854,7 +854,7 @@ class Editor extends View break if _.isEqual(scopeStack[0...i], desiredScopes[0...i]) popScope() - # push on top of common prefix until scopStacks == desiredScopes + # push on top of common prefix until scopeStack == desiredScopes for j in [i...desiredScopes.length] pushScope(desiredScopes[j]) From 23573f611f1c2accd5bfc524aa39548bc0204352 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 25 Oct 2012 10:38:01 -0700 Subject: [PATCH 17/17] Add specs of outline view UI --- spec/extensions/outline-view-spec.coffee | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/spec/extensions/outline-view-spec.coffee b/spec/extensions/outline-view-spec.coffee index d183ffe75..85f477ad0 100644 --- a/spec/extensions/outline-view-spec.coffee +++ b/spec/extensions/outline-view-spec.coffee @@ -1,6 +1,61 @@ +RootView = require 'root-view' +OutlineView = require 'outline-view' TagGenerator = require 'outline-view/tag-generator' describe "OutlineView", -> + [rootView, outlineView] = [] + + beforeEach -> + rootView = new RootView(require.resolve('fixtures')) + rootView.activateExtension(OutlineView) + outlineView = OutlineView.instance + rootView.attachToDom() + + afterEach -> + rootView.deactivate() + + it "displays all JavaScript functions with line numbers", -> + 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() + 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-line')).toHaveText 'Line 1' + expect(outlineView.list.children('li:last').find('.function-name')).toHaveText 'quicksort.sort' + expect(outlineView.list.children('li:last').find('.function-line')).toHaveText 'Line 2' + + 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,0] describe "TagGenerator", -> it "generates tags for all JavaScript functions", ->