From 244995ded1cfb1238c4245deba9e240e2c43597a Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Thu, 31 Jul 2014 11:11:29 -0400 Subject: [PATCH 01/25] Spec-first. --- lib/navigation-view.coffee | 5 +++++ spec/navigation-view-spec.coffee | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 lib/navigation-view.coffee create mode 100644 spec/navigation-view-spec.coffee diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee new file mode 100644 index 0000000..710f0d6 --- /dev/null +++ b/lib/navigation-view.coffee @@ -0,0 +1,5 @@ +{View} = require 'atom' + +class NavigationView extends View + +module.exports = NavigationView: NavigationView diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee new file mode 100644 index 0000000..bd3fb13 --- /dev/null +++ b/spec/navigation-view-spec.coffee @@ -0,0 +1,31 @@ +{WorkspaceView} = require 'atom' +{Stacktrace, Frame} = require '../lib/stacktrace' +{NavigationView} = require '../lib/navigation-view' + +describe 'NavigationView', -> + + it 'attaches itself to the workspace' + + describe 'with an active stacktrace', -> + + it 'shows the active trace name' + + it 'navigates back to the trace on a click' + + it 'deactivates the trace' + + describe 'on an editor corresponding to a single frame', -> + + it 'shows the frame index' + + it 'navigates to the next frame' + + it 'navigates to the previous frame' + + describe 'on an editor not corresponding to a frame', -> + + it 'navigates back to the last active frame' + + describe 'without an active stacktrace', -> + + it 'hides itself' From 77d03dfd8b9209811877fadb447088374c5100a0 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Thu, 31 Jul 2014 11:28:05 -0400 Subject: [PATCH 02/25] More specs for the multiple-frame case. --- spec/navigation-view-spec.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index bd3fb13..c1f4be8 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -22,6 +22,10 @@ describe 'NavigationView', -> it 'navigates to the previous frame' + describe 'on an editor with multiple frames', -> + + it 'notices if you manually navigate to a different frame' + describe 'on an editor not corresponding to a frame', -> it 'navigates back to the last active frame' From 1e3e03c441fb63832463a7202169fd856791daf7 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 9 Aug 2014 10:45:08 -0400 Subject: [PATCH 03/25] Attach the navigation view to the workspace. --- lib/main.coffee | 14 +++++++++----- lib/navigation-view.coffee | 3 +++ spec/navigation-view-spec.coffee | 12 +++++++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/main.coffee b/lib/main.coffee index f24b80c..50f1f7f 100644 --- a/lib/main.coffee +++ b/lib/main.coffee @@ -1,6 +1,7 @@ EnterDialog = require './enter-dialog' {Stacktrace} = require './stacktrace' {StacktraceView} = require './stacktrace-view' +{NavigationView} = require './navigation-view' editorDecorator = require './editor-decorator' module.exports = @@ -15,18 +16,21 @@ module.exports = atom.emit 'stacktrace:accept-trace', trace: text atom.workspace.eachEditor editorDecorator - Stacktrace.on 'active-changed', -> + @activeChanged = Stacktrace.on 'active-changed', -> editorDecorator(e) for e in atom.workspace.getEditors() + @navigationView = new NavigationView + atom.workspaceView.appendToBottom @navigationView + StacktraceView.registerIn(atom.workspace) - atom.on 'stacktrace:accept-trace', ({trace}) => + @acceptTrace = atom.on 'stacktrace:accept-trace', ({trace}) => for trace in Stacktrace.parse(trace) trace.register() atom.workspace.open trace.getUrl() deactivate: -> - Stacktrace.off 'active-changed' - atom.off 'stacktrace:accept-trace' + @navigationView.remove() - serialize: -> + @activeChanged.off() + @acceptTrace.off() diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 710f0d6..8d56c16 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -2,4 +2,7 @@ class NavigationView extends View + @content: -> + @div class: 'tool-panel panel-bottom padded stacktrace navigation' + module.exports = NavigationView: NavigationView diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index c1f4be8..da7f2e6 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -4,7 +4,17 @@ describe 'NavigationView', -> - it 'attaches itself to the workspace' + beforeEach -> + atom.workspaceView = new WorkspaceView + atom.workspaceView.attachToDom() + activationPromise = atom.packages.activatePackage('stacktrace') + + atom.workspaceView.trigger 'stacktrace:paste' + + waitsForPromise -> activationPromise + + it 'attaches itself to the workspace', -> + expect(atom.workspaceView.find '.stacktrace.navigation').toHaveLength 1 describe 'with an active stacktrace', -> From 0fd987cc04b2e7a41162fc7bd37763c038736d0a Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 9 Aug 2014 10:55:32 -0400 Subject: [PATCH 04/25] Tests for displaying the active trace. --- lib/navigation-view.coffee | 1 + spec/navigation-view-spec.coffee | 36 ++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 8d56c16..4a01ed1 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -1,4 +1,5 @@ {View} = require 'atom' +{Stacktrace} = require './stacktrace' class NavigationView extends View diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index da7f2e6..0ca3161 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -2,7 +2,15 @@ {Stacktrace, Frame} = require '../lib/stacktrace' {NavigationView} = require '../lib/navigation-view' +frames = [ + new Frame('raw0', 'bottom.rb', 12, 'botfunc') + new Frame('raw1', 'middle.rb', 42, 'midfunc') + new Frame('raw2', 'top.rb', 37, 'topfunc') +] +trace = new Stacktrace(frames, 'Boom') + describe 'NavigationView', -> + [view] = [] beforeEach -> atom.workspaceView = new WorkspaceView @@ -13,16 +21,36 @@ describe 'NavigationView', -> waitsForPromise -> activationPromise + runs -> + view = atom.workspaceView.find('.stacktrace.navigation').view() + + afterEach -> + Stacktrace.getActivated()?.deactivate() + it 'attaches itself to the workspace', -> - expect(atom.workspaceView.find '.stacktrace.navigation').toHaveLength 1 + expect(view).not.toBeNull() describe 'with an active stacktrace', -> + [view] = [] + + beforeEach -> + trace.activate() + view = atom.workspaceView.find('.stacktrace.navigation').view() + + it 'should be visible', -> + expect(view.hasClass 'active').toBeTruthy() - it 'shows the active trace name' + it 'shows the active trace name', -> + text = view.find('.message').text() + expect(text).toEqual('Boom') - it 'navigates back to the trace on a click' + it 'navigates back to the trace on a click', -> + view.backToTrace() + expect(atom.workspaceView.getActiveView().hasClass '.stacktrace.traceview').toBeTruthy() - it 'deactivates the trace' + it 'deactivates the trace', -> + view.deactivateTrace() + expect(trace.isActive()).toBeFalsy() describe 'on an editor corresponding to a single frame', -> From c8ccf25e170d6d8ecade8f7c0a96f3c4bf7d55fa Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 9 Aug 2014 11:02:36 -0400 Subject: [PATCH 05/25] Toggle the "inactive" class on trace activation. --- lib/navigation-view.coffee | 14 +++++++++++++- spec/navigation-view-spec.coffee | 4 +--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 4a01ed1..e998bb4 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -1,9 +1,21 @@ {View} = require 'atom' +{Subscriber} = require 'emissary' {Stacktrace} = require './stacktrace' class NavigationView extends View + Subscriber.includeInto this + @content: -> - @div class: 'tool-panel panel-bottom padded stacktrace navigation' + activatedClass = if Stacktrace.getActivated()? then '' else 'inactive' + + @div class: "tool-panel panel-bottom padded stacktrace navigation #{activatedClass}" + + initialize: -> + @subscribe Stacktrace, 'active-changed', (e) => + if e.newTrace? then @removeClass 'inactive' else @addClass 'inactive' + + beforeRemove: -> + @unsubscribe Stacktrace module.exports = NavigationView: NavigationView diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index 0ca3161..aa1c537 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -31,14 +31,12 @@ describe 'NavigationView', -> expect(view).not.toBeNull() describe 'with an active stacktrace', -> - [view] = [] beforeEach -> trace.activate() - view = atom.workspaceView.find('.stacktrace.navigation').view() it 'should be visible', -> - expect(view.hasClass 'active').toBeTruthy() + expect(view.hasClass 'inactive').toBeFalsy() it 'shows the active trace name', -> text = view.find('.message').text() From 0750ad329b39fdf089b9c2ca93f04d7b89d5ce0e Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 10 Aug 2014 10:55:15 -0400 Subject: [PATCH 06/25] Upgrade line-chomper. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da6d9ce..863a87c 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,6 @@ "dependencies": { "emissary": "^1.2.1", "jssha": "^1.5.0", - "line-chomper": "git+https://github.com/smashwilson/line-chomper.git#optional-trim" + "line-chomper": "^0.4.5" } } From ed3608762bbf68a92d9a49385743bb0ec001fce7 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 10 Aug 2014 11:16:25 -0400 Subject: [PATCH 07/25] Open the active Stacktrace when clicking the message. --- lib/navigation-view.coffee | 17 +++++++++++++++-- lib/stacktrace-view.coffee | 1 + spec/navigation-view-spec.coffee | 8 ++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index e998bb4..61d5817 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -9,13 +9,26 @@ class NavigationView extends View @content: -> activatedClass = if Stacktrace.getActivated()? then '' else 'inactive' - @div class: "tool-panel panel-bottom padded stacktrace navigation #{activatedClass}" + @div class: "tool-panel panel-bottom padded stacktrace navigation #{activatedClass}", => + @h2 class: 'text-highlight message', outlet: 'message', click: 'backToTrace' initialize: -> @subscribe Stacktrace, 'active-changed', (e) => - if e.newTrace? then @removeClass 'inactive' else @addClass 'inactive' + if e.newTrace? then @useTrace(e.newTrace) else @noTrace() beforeRemove: -> @unsubscribe Stacktrace + useTrace: (trace) -> + @removeClass 'inactive' + @message.text(trace.message) + + noTrace: -> + @addClass 'inactive' + @message.text('') + + backToTrace: -> + url = Stacktrace.getActivated()?.getUrl() + atom.workspace.open(url) if url + module.exports = NavigationView: NavigationView diff --git a/lib/stacktrace-view.coffee b/lib/stacktrace-view.coffee index 17e73b9..6bb05b2 100644 --- a/lib/stacktrace-view.coffee +++ b/lib/stacktrace-view.coffee @@ -23,6 +23,7 @@ class StacktraceView extends View @subview 'frame', new FrameView frame, => trace.activate() initialize: (@trace) -> + @uri = @trace.getUrl() @subscribe Stacktrace, 'active-changed', (e) => if e.newTrace is @trace @addClass 'activated' diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index aa1c537..a725535 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -43,8 +43,12 @@ describe 'NavigationView', -> expect(text).toEqual('Boom') it 'navigates back to the trace on a click', -> - view.backToTrace() - expect(atom.workspaceView.getActiveView().hasClass '.stacktrace.traceview').toBeTruthy() + promise = view.backToTrace() + + waitsForPromise -> promise + + runs -> + expect(atom.workspaceView.getActiveView().hasClass '.stacktrace.traceview').toBeTruthy() it 'deactivates the trace', -> view.deactivateTrace() From 49161ce9661c7f048bbfd13e018d0c7a17cdb22e Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 10 Aug 2014 11:43:34 -0400 Subject: [PATCH 08/25] Actually register the trace. --- spec/navigation-view-spec.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index a725535..e329d88 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -26,6 +26,7 @@ describe 'NavigationView', -> afterEach -> Stacktrace.getActivated()?.deactivate() + Stacktrace.clearRegistry() it 'attaches itself to the workspace', -> expect(view).not.toBeNull() @@ -33,6 +34,7 @@ describe 'NavigationView', -> describe 'with an active stacktrace', -> beforeEach -> + trace.register() trace.activate() it 'should be visible', -> @@ -43,12 +45,10 @@ describe 'NavigationView', -> expect(text).toEqual('Boom') it 'navigates back to the trace on a click', -> - promise = view.backToTrace() - - waitsForPromise -> promise + waitsForPromise -> view.backToTrace() runs -> - expect(atom.workspaceView.getActiveView().hasClass '.stacktrace.traceview').toBeTruthy() + expect(atom.workspaceView.getActiveView().hasClass 'traceview').toBeTruthy() it 'deactivates the trace', -> view.deactivateTrace() From 6e6f6695c7bee8d96f3ce6ed08083aebc95e3558 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Mon, 18 Aug 2014 15:30:48 -0400 Subject: [PATCH 09/25] Improve the CSS selectors to target new markup. --- stylesheets/stacktrace.less | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/stylesheets/stacktrace.less b/stylesheets/stacktrace.less index 5bfc3c8..f55eacf 100644 --- a/stylesheets/stacktrace.less +++ b/stylesheets/stacktrace.less @@ -11,6 +11,7 @@ .stacktrace { &.enter-dialog .editor { height: 300px; + max-height: 300px; } .frame .panel-heading { @@ -37,7 +38,11 @@ } .editor { - cursor: pointer; + .editor-contents { + cursor: pointer; + } + height: 175px; + max-height: 175px; } } From ddc93beb244242b8422f8cbd9754cd214b972089 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 23 Aug 2014 19:01:58 -0400 Subject: [PATCH 10/25] Deactive a trace with the "x" button. --- lib/navigation-view.coffee | 9 ++++++++- stylesheets/stacktrace.less | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 61d5817..eb74530 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -10,7 +10,9 @@ class NavigationView extends View activatedClass = if Stacktrace.getActivated()? then '' else 'inactive' @div class: "tool-panel panel-bottom padded stacktrace navigation #{activatedClass}", => - @h2 class: 'text-highlight message', outlet: 'message', click: 'backToTrace' + @div class: 'trace-name', => + @h2 class: 'inline-block text-highlight message', outlet: 'message', click: 'backToTrace' + @span class: 'inline-block icon icon-x', click: 'deactivateTrace' initialize: -> @subscribe Stacktrace, 'active-changed', (e) => @@ -22,10 +24,15 @@ class NavigationView extends View useTrace: (trace) -> @removeClass 'inactive' @message.text(trace.message) + @show() + + deactivateTrace: -> + Stacktrace.getActivated().deactivate() noTrace: -> @addClass 'inactive' @message.text('') + @hide() backToTrace: -> url = Stacktrace.getActivated()?.getUrl() diff --git a/stylesheets/stacktrace.less b/stylesheets/stacktrace.less index f55eacf..716d58a 100644 --- a/stylesheets/stacktrace.less +++ b/stylesheets/stacktrace.less @@ -46,6 +46,20 @@ } } + &.navigation { + .trace-name { + h2 { + margin: 0 15px 0 5px; + font-weight: bold; + cursor: pointer; + } + span.icon-x { + font-size: 1.5em; + cursor: pointer; + } + } + } + .deactivate-control { display: none; } &.activated { From e5525a1a68a92fca2a39235a96b562501c47f12b Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 23 Aug 2014 19:07:32 -0400 Subject: [PATCH 11/25] Hide the navigation panel if there's no trace. --- lib/navigation-view.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index eb74530..f89bd5d 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -17,6 +17,7 @@ class NavigationView extends View initialize: -> @subscribe Stacktrace, 'active-changed', (e) => if e.newTrace? then @useTrace(e.newTrace) else @noTrace() + if Stacktrace.getActivated? then @hide() beforeRemove: -> @unsubscribe Stacktrace From 726346a1f6fda65108c16bf63c081146664b2c7e Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 23 Aug 2014 19:07:45 -0400 Subject: [PATCH 12/25] Remove the activation controls from StacktraceView. --- lib/stacktrace-view.coffee | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/stacktrace-view.coffee b/lib/stacktrace-view.coffee index 6bb05b2..99e1b3d 100644 --- a/lib/stacktrace-view.coffee +++ b/lib/stacktrace-view.coffee @@ -12,12 +12,6 @@ class StacktraceView extends View @div class: "stacktrace traceview tool-panel padded #{tclass}", => @div class: 'panel padded', => @h2 class: 'error-message', trace.message - @p class: 'activate-control', => - @button class: 'btn btn-primary selected inline-block', click: 'activate', 'Activate' - @span class: 'inline-block', 'to navigate around this stacktrace.' - @p class: 'deactivate-control', => - @button class: 'btn btn-primary inline-block', click: 'deactivate', 'Deactivate' - @span class: 'inline-block', 'to close the stacktrace navigation panel.' @div class: 'frames', => for frame in trace.frames @subview 'frame', new FrameView frame, => trace.activate() @@ -38,14 +32,6 @@ class StacktraceView extends View getTitle: -> @trace.message - # Public: Activate the current {Stacktrace}. - # - activate: -> @trace.activate() - - # Public: Deactivate the current {Stacktrace}. - # - deactivate: -> @trace.deactivate() - # Internal: Register an opener function in the workspace to handle URLs # generated by a Stacktrace. # From 426b28a9b4dccdda89925993c67d121591040dec Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 23 Aug 2014 19:20:14 -0400 Subject: [PATCH 13/25] Tests for showing information about the frame. --- spec/navigation-view-spec.coffee | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index e329d88..a5573eb 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -55,8 +55,18 @@ describe 'NavigationView', -> expect(trace.isActive()).toBeFalsy() describe 'on an editor corresponding to a single frame', -> + [editor] = [] - it 'shows the frame index' + beforeEach -> + waitsForPromise -> trace.frames[1].navigateTo() + + runs -> + editor = atom.workspace.getActiveEditor() + + it 'shows the current frame and its index', -> + expect(view.find('.current-frame.function').text()).toBe('midfunc') + expect(view.find('.current-frame.index').text()).toBe('2') + expect(view.find('.current-frame.total').text()).toBe('3') it 'navigates to the next frame' From bed65f2b0d17c88c2a2c450661fdf9d3e817bf56 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 23 Aug 2014 19:54:03 -0400 Subject: [PATCH 14/25] Stacktrace and Frame recognize Editor positions. --- lib/stacktrace.coffee | 18 ++++++++++++++++++ spec/stacktrace-spec.coffee | 31 ++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/stacktrace.coffee b/lib/stacktrace.coffee index 14aaf8e..debcb58 100644 --- a/lib/stacktrace.coffee +++ b/lib/stacktrace.coffee @@ -64,6 +64,19 @@ class Stacktrace ACTIVE = null Stacktrace.emit 'active-changed', oldTrace: this, newTrace: null + # Public: Return the Frame corresponding to an Editor position, if any, along with its position + # within the trace. + # + # object - "position" should be a Point corresponding to a cursor position, and "path" the full + # path of an Editor. + # + atPosition: (editorPosition) -> + [index, total] = [1, @frames.length] + for frame in @frames + return {frame, index, total} if frame.isOn editorPosition + index += 1 + return null + # Public: Parse zero to many Stacktrace instances from a corpus of text. # # text - A raw blob of text. @@ -122,6 +135,11 @@ class Frame if editorView? editorView.scrollToBufferPosition position, center: true + # Public: Return true if the buffer position and path correspond to this Frame's line. + # + isOn: ({position, path}) -> + path is @realPath and position.row is @bufferLineNumber() + module.exports = PREFIX: PREFIX diff --git a/spec/stacktrace-spec.coffee b/spec/stacktrace-spec.coffee index f6cd82e..aecd764 100644 --- a/spec/stacktrace-spec.coffee +++ b/spec/stacktrace-spec.coffee @@ -1,3 +1,4 @@ +{Point} = require 'atom' path = require 'path' {Stacktrace, Frame} = require '../lib/stacktrace' @@ -102,8 +103,26 @@ describe 'Stacktrace', -> expect(event.oldTrace).toBeNull() expect(event.newTrace).toBe(trace) + describe 'active frame location', -> + + it 'locates the frame corresponding to an Editor position', -> + {frame, index, total} = trace.atPosition + position: Point.fromObject([4, 0]) + path: '/home/smash/samples/tracer/otherdir/file2.rb' + + expect(frame).toBe(trace.frames[2]) + expect(index).toBe(3) + expect(total).toBe(5) + + it 'returns null if none are found', -> + result = trace.atPosition + position: Point.fromObject([2, 1]) + path: '/home/smash/samples/tracer/otherdir/file2.rb' + + expect(result).toBeNull() + describe 'Frame', -> - [frame] = [] + [frame, fixturePath] = [] beforeEach -> fixturePath = path.join __dirname, 'fixtures', 'context.txt' @@ -125,3 +144,13 @@ describe 'Frame', -> expect(lines[2]).toEqual('five') expect(lines[3]).toEqual('six') expect(lines[4]).toEqual('') + + describe 'recognizes itself in an Editor', -> + it 'is on a cursor', -> + expect(frame.isOn(position: Point.fromObject([4, 0]), path: fixturePath)).toBeTruthy() + + it 'is not on a cursor', -> + expect(frame.isOn(position: Point.fromObject([2, 0]), path: fixturePath)).toBeFalsy() + + it 'is on a different file', -> + expect(frame.isOn(position: Point.fromObject([4, 0]), path: 'some/other/path.rb')).toBeFalsy() From 668aec2c8489b8504fbafd5d570c3636231ab0f7 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sat, 23 Aug 2014 19:54:22 -0400 Subject: [PATCH 15/25] Comment touchups :lipstick: --- lib/stacktrace.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/stacktrace.coffee b/lib/stacktrace.coffee index debcb58..6146a35 100644 --- a/lib/stacktrace.coffee +++ b/lib/stacktrace.coffee @@ -87,10 +87,12 @@ class Stacktrace # Internal: Return a registered trace, or null if none match the provided # URL. + # @forUrl: (url) -> REGISTRY[url] # Internal: Clear the global trace registry. + # @clearRegistry: -> REGISTRY = {} From 718835353fe7d9962c82d206517c19cfe131fb9b Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 16:07:56 -0400 Subject: [PATCH 16/25] Show the current frame on the NavigationView. --- lib/navigation-view.coffee | 42 +++++++++++++++++++++++++++++--- spec/navigation-view-spec.coffee | 17 ++++++++----- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index f89bd5d..46ba4bf 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -13,28 +13,62 @@ class NavigationView extends View @div class: 'trace-name', => @h2 class: 'inline-block text-highlight message', outlet: 'message', click: 'backToTrace' @span class: 'inline-block icon icon-x', click: 'deactivateTrace' + @div class: 'current-frame unfocused', outlet: 'frameContainer', => + @span class: 'inline-block icon icon-code' + @span class: 'inline-block function', outlet: 'frameFunction' + @span class: 'inline-block index', outlet: 'frameIndex' + @span class: 'inline-block divider', '/' + @span class: 'inline-block total', outlet: 'frameTotal' initialize: -> @subscribe Stacktrace, 'active-changed', (e) => if e.newTrace? then @useTrace(e.newTrace) else @noTrace() + + # Subscribe to opening editors. Set the current frame when a cursor is moved over a frame's + # line. + atom.workspace.eachEditor (e) => + @subscribe e, 'cursors-moved', => + if @trace? + frame = @trace.atPosition + position: e.getCursorBufferPosition() + path: e.getPath() + if frame? then @useFrame(frame) else @unfocusFrame() + if Stacktrace.getActivated? then @hide() beforeRemove: -> @unsubscribe Stacktrace - useTrace: (trace) -> + useTrace: (@trace) -> @removeClass 'inactive' @message.text(trace.message) + @noFrame() @show() - deactivateTrace: -> - Stacktrace.getActivated().deactivate() - noTrace: -> @addClass 'inactive' @message.text('') + @noFrame() @hide() + useFrame: ({@frame, index, total}) -> + @frameContainer.removeClass 'unfocused' + @frameFunction.text @frame.functionName + @frameIndex.text index.toString() + @frameTotal.text total.toString() + + unfocusFrame: -> + @frameContainer.addClass 'unfocused' + + noFrame: -> + @unfocusFrame() + @frameFunction.text '' + @frameIndex.text '' + @frameTotal.text '' + + deactivateTrace: -> + Stacktrace.getActivated().deactivate() + backToTrace: -> url = Stacktrace.getActivated()?.getUrl() atom.workspace.open(url) if url diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index a5573eb..3e2573a 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -2,10 +2,15 @@ {Stacktrace, Frame} = require '../lib/stacktrace' {NavigationView} = require '../lib/navigation-view' +path = require 'path' + +fixturePath = (p) -> + path.join __dirname, 'fixtures', p + frames = [ - new Frame('raw0', 'bottom.rb', 12, 'botfunc') - new Frame('raw1', 'middle.rb', 42, 'midfunc') - new Frame('raw2', 'top.rb', 37, 'topfunc') + new Frame('raw0', fixturePath('bottom.rb'), 12, 'botfunc') + new Frame('raw1', fixturePath('middle.rb'), 42,'midfunc') + new Frame('raw2', fixturePath('top.rb'), 37, 'topfunc') ] trace = new Stacktrace(frames, 'Boom') @@ -64,9 +69,9 @@ describe 'NavigationView', -> editor = atom.workspace.getActiveEditor() it 'shows the current frame and its index', -> - expect(view.find('.current-frame.function').text()).toBe('midfunc') - expect(view.find('.current-frame.index').text()).toBe('2') - expect(view.find('.current-frame.total').text()).toBe('3') + expect(view.find('.current-frame .function').text()).toBe('midfunc') + expect(view.find('.current-frame .index').text()).toBe('2') + expect(view.find('.current-frame .total').text()).toBe('3') it 'navigates to the next frame' From b02fa7f32d1d590de193da5ca2c498348683e8ca Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 16:27:14 -0400 Subject: [PATCH 17/25] Fuss with styles. --- lib/navigation-view.coffee | 6 ++++-- stylesheets/stacktrace.less | 29 ++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 46ba4bf..528f0b9 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -10,10 +10,10 @@ class NavigationView extends View activatedClass = if Stacktrace.getActivated()? then '' else 'inactive' @div class: "tool-panel panel-bottom padded stacktrace navigation #{activatedClass}", => - @div class: 'trace-name', => + @div class: 'inline-block trace-name', => @h2 class: 'inline-block text-highlight message', outlet: 'message', click: 'backToTrace' @span class: 'inline-block icon icon-x', click: 'deactivateTrace' - @div class: 'current-frame unfocused', outlet: 'frameContainer', => + @div class: 'inline-block current-frame unfocused', outlet: 'frameContainer', => @span class: 'inline-block icon icon-code' @span class: 'inline-block function', outlet: 'frameFunction' @span class: 'inline-block index', outlet: 'frameIndex' @@ -54,11 +54,13 @@ class NavigationView extends View useFrame: ({@frame, index, total}) -> @frameContainer.removeClass 'unfocused' @frameFunction.text @frame.functionName + @frameFunction.addClass 'highlight-info' @frameIndex.text index.toString() @frameTotal.text total.toString() unfocusFrame: -> @frameContainer.addClass 'unfocused' + @frameFunction.removeClass 'highlight-info' noFrame: -> @unfocusFrame() diff --git a/stylesheets/stacktrace.less b/stylesheets/stacktrace.less index 716d58a..2b3b8f3 100644 --- a/stylesheets/stacktrace.less +++ b/stylesheets/stacktrace.less @@ -48,8 +48,10 @@ &.navigation { .trace-name { + margin-right: 30px; + h2 { - margin: 0 15px 0 5px; + margin: 2px 15px 0 5px; font-weight: bold; cursor: pointer; } @@ -58,19 +60,32 @@ cursor: pointer; } } - } - .deactivate-control { display: none; } + .current-frame { + span.icon-code { + margin: 0; + } - &.activated { - .deactivate-control { display: block; } - .activate-control { display: none; } + &.unfocused { + color: @text-color-subtle; + + span.function { + padding: 1px 3px; + font-weight: bold; + } + } + } } } .editor { - .line.line-stackframe { + .line.line-stackframe, .line.line-stackframe.cursor-line { + background: @stackframe-background; + } + + // Work around some selector precedence issues. + &.is-focused .line.line-stackframe, &.is-focused .line.line-stackframe.cursor-line { background: @stackframe-background; } From f372a6876fbb9fcf5d553becebf71ed011beac84 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 16:36:18 -0400 Subject: [PATCH 18/25] Give precedence to already-focused frames. --- lib/navigation-view.coffee | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 528f0b9..6196be9 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -29,10 +29,18 @@ class NavigationView extends View atom.workspace.eachEditor (e) => @subscribe e, 'cursors-moved', => if @trace? - frame = @trace.atPosition + pos = position: e.getCursorBufferPosition() path: e.getPath() - if frame? then @useFrame(frame) else @unfocusFrame() + + # Allow the already-set @frame a chance to see if it still applies. + # This lets the caller and called navigation work properly, even if multiple frames are + # on the same line. + unless @frame? and @frame.isOn(pos) + + # Otherwise, scan the trace for a matching frame. + result = @trace.atPosition(pos) + if result? then @useFrame(result) else @unfocusFrame() if Stacktrace.getActivated? then @hide() From 6bd63c52ae467b647d7b32156a9159c633a556a1 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 16:43:22 -0400 Subject: [PATCH 19/25] Assign indices to frames on Trace construction. --- lib/stacktrace.coffee | 9 +++++++++ spec/stacktrace-spec.coffee | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/lib/stacktrace.coffee b/lib/stacktrace.coffee index 6146a35..fd583eb 100644 --- a/lib/stacktrace.coffee +++ b/lib/stacktrace.coffee @@ -19,6 +19,10 @@ class Stacktrace Emitter.extend this constructor: (@frames = [], @message = '') -> + i = 0 + for f in @frames + f.index = i + i += 1 # Internal: Compute the SHA256 checksum of the normalized stacktrace. # @@ -105,12 +109,17 @@ class Stacktrace class Frame constructor: (@rawLine, @rawPath, @lineNumber, @functionName) -> + @index = null @realPath = @rawPath # Public: Return the zero-indexed line number. # bufferLineNumber: -> @lineNumber - 1 + # Public: Return the one-based frame index. + # + humanIndex: -> @index + 1 + # Public: Asynchronously collect n lines of context around the specified line number in this # frame's source file. # diff --git a/spec/stacktrace-spec.coffee b/spec/stacktrace-spec.coffee index aecd764..7e9cc55 100644 --- a/spec/stacktrace-spec.coffee +++ b/spec/stacktrace-spec.coffee @@ -55,6 +55,10 @@ describe 'Stacktrace', -> ] expect(functionNames).toEqual(expected) + it 'assigns an index to each frame', -> + positions = (frame.index for frame in trace.frames) + expect(positions).toEqual([0..4]) + describe 'registration', -> afterEach -> Stacktrace.clearRegistry() From d18f1957f8cf22da9748b89d1aeab7c7dca6e441 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 16:57:49 -0400 Subject: [PATCH 20/25] Access callers and callees of stack frames. --- lib/stacktrace.coffee | 13 +++++++++++++ spec/stacktrace-spec.coffee | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/stacktrace.coffee b/lib/stacktrace.coffee index fd583eb..64656ec 100644 --- a/lib/stacktrace.coffee +++ b/lib/stacktrace.coffee @@ -81,6 +81,19 @@ class Stacktrace index += 1 return null + # Public: Return the Frame that called the given Frame, or undefined if given the top of the stack. + # + # frame - The current Frame to use as a reference point. + # + callerOf: (frame) -> @frames[frame.index + 1] + + # Public: Return the Frame that a given Frame called into, or undefined if given the bottom of the + # stack. + # + # frame - The current Frame to use as a reference point. + # + calledFrom: (frame) -> @frames[frame.index - 1] + # Public: Parse zero to many Stacktrace instances from a corpus of text. # # text - A raw blob of text. diff --git a/spec/stacktrace-spec.coffee b/spec/stacktrace-spec.coffee index 7e9cc55..ef5dce0 100644 --- a/spec/stacktrace-spec.coffee +++ b/spec/stacktrace-spec.coffee @@ -107,6 +107,30 @@ describe 'Stacktrace', -> expect(event.oldTrace).toBeNull() expect(event.newTrace).toBe(trace) + describe 'walking up and down the stack', -> + + it 'links to the callee of each frame', -> + callees = (trace.calledFrom(f) for f in trace.frames) + expected = [ + undefined + trace.frames[0] + trace.frames[1] + trace.frames[2] + trace.frames[3] + ] + expect(callees).toEqual(expected) + + it 'links to the caller of each frame', -> + callers = (trace.callerOf(f) for f in trace.frames) + expected = [ + trace.frames[1] + trace.frames[2] + trace.frames[3] + trace.frames[4] + undefined + ] + expect(callers).toEqual(expected) + describe 'active frame location', -> it 'locates the frame corresponding to an Editor position', -> From c8a8f603eebe95ae136cc3b4e5066355c23efdeb Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 17:06:05 -0400 Subject: [PATCH 21/25] Just return a Frame from atEditorPosition. --- lib/navigation-view.coffee | 10 +++++----- lib/stacktrace.coffee | 4 ++-- spec/stacktrace-spec.coffee | 9 ++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 6196be9..d4f1171 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -39,8 +39,8 @@ class NavigationView extends View unless @frame? and @frame.isOn(pos) # Otherwise, scan the trace for a matching frame. - result = @trace.atPosition(pos) - if result? then @useFrame(result) else @unfocusFrame() + frame = @trace.atEditorPosition(pos) + if frame? then @useFrame(frame) else @unfocusFrame() if Stacktrace.getActivated? then @hide() @@ -59,12 +59,12 @@ class NavigationView extends View @noFrame() @hide() - useFrame: ({@frame, index, total}) -> + useFrame: (@frame) -> @frameContainer.removeClass 'unfocused' @frameFunction.text @frame.functionName @frameFunction.addClass 'highlight-info' - @frameIndex.text index.toString() - @frameTotal.text total.toString() + @frameIndex.text @frame.humanIndex().toString() + @frameTotal.text @trace.frames.length.toString() unfocusFrame: -> @frameContainer.addClass 'unfocused' diff --git a/lib/stacktrace.coffee b/lib/stacktrace.coffee index 64656ec..7b6e1ba 100644 --- a/lib/stacktrace.coffee +++ b/lib/stacktrace.coffee @@ -74,10 +74,10 @@ class Stacktrace # object - "position" should be a Point corresponding to a cursor position, and "path" the full # path of an Editor. # - atPosition: (editorPosition) -> + atEditorPosition: (editorPosition) -> [index, total] = [1, @frames.length] for frame in @frames - return {frame, index, total} if frame.isOn editorPosition + return frame if frame.isOn editorPosition index += 1 return null diff --git a/spec/stacktrace-spec.coffee b/spec/stacktrace-spec.coffee index ef5dce0..5c0e76b 100644 --- a/spec/stacktrace-spec.coffee +++ b/spec/stacktrace-spec.coffee @@ -134,20 +134,19 @@ describe 'Stacktrace', -> describe 'active frame location', -> it 'locates the frame corresponding to an Editor position', -> - {frame, index, total} = trace.atPosition + frame = trace.atEditorPosition position: Point.fromObject([4, 0]) path: '/home/smash/samples/tracer/otherdir/file2.rb' expect(frame).toBe(trace.frames[2]) - expect(index).toBe(3) - expect(total).toBe(5) + expect(frame.humanIndex()).toBe(3) it 'returns null if none are found', -> - result = trace.atPosition + frame = trace.atEditorPosition position: Point.fromObject([2, 1]) path: '/home/smash/samples/tracer/otherdir/file2.rb' - expect(result).toBeNull() + expect(frame).toBeNull() describe 'Frame', -> [frame, fixturePath] = [] From e0fa818efa7ab69c71ae8b348ab17cf1dbc8ea0e Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 17:08:25 -0400 Subject: [PATCH 22/25] Navigate to caller and callee of a frame. --- lib/navigation-view.coffee | 10 ++++++++++ spec/navigation-view-spec.coffee | 12 ++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index d4f1171..05bb357 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -83,4 +83,14 @@ class NavigationView extends View url = Stacktrace.getActivated()?.getUrl() atom.workspace.open(url) if url + navigateToCaller: -> + return unless @trace? and @frame? + + @trace.callerOf(@frame)?.navigateTo() + + navigateToCalled: -> + return unless @trace? and @frame? + + @trace.calledFrom(@frame)?.navigateTo() + module.exports = NavigationView: NavigationView diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index 3e2573a..38e96b8 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -73,9 +73,17 @@ describe 'NavigationView', -> expect(view.find('.current-frame .index').text()).toBe('2') expect(view.find('.current-frame .total').text()).toBe('3') - it 'navigates to the next frame' + it "navigates to the caller's frame", -> + waitsForPromise -> view.navigateToCaller() - it 'navigates to the previous frame' + runs -> + expect(view.frame).toBe(trace.frames[2]) + + it 'navigates to the called frame', -> + waitsForPromise -> view.navigateToCalled() + + runs -> + expect(view.frame).toBe(trace.frames[0]) describe 'on an editor with multiple frames', -> From 8316fa7f93c5c8019c8bfe561fad49025774afb9 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 17:33:35 -0400 Subject: [PATCH 23/25] Add buttons for stack navigation. --- lib/navigation-view.coffee | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 05bb357..96aec66 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -19,6 +19,13 @@ class NavigationView extends View @span class: 'inline-block index', outlet: 'frameIndex' @span class: 'inline-block divider', '/' @span class: 'inline-block total', outlet: 'frameTotal' + @div class: 'pull-right controls', => + @button class: 'inline-block btn', click: 'navigateToCaller', => + @span class: 'icon icon-arrow-up' + @text 'Caller' + @button class: 'inline-block btn', click: 'navigateToCalled', => + @span class: 'icon icon-arrow-down' + @text 'Follow Call' initialize: -> @subscribe Stacktrace, 'active-changed', (e) => @@ -36,8 +43,9 @@ class NavigationView extends View # Allow the already-set @frame a chance to see if it still applies. # This lets the caller and called navigation work properly, even if multiple frames are # on the same line. - unless @frame? and @frame.isOn(pos) - + if @frame? and @frame.isOn(pos) + @useFrame(@frame) + else # Otherwise, scan the trace for a matching frame. frame = @trace.atEditorPosition(pos) if frame? then @useFrame(frame) else @unfocusFrame() @@ -86,11 +94,17 @@ class NavigationView extends View navigateToCaller: -> return unless @trace? and @frame? - @trace.callerOf(@frame)?.navigateTo() + f = @trace.callerOf(@frame) + if f? + @frame = f + @frame.navigateTo() navigateToCalled: -> return unless @trace? and @frame? - @trace.calledFrom(@frame)?.navigateTo() + f = @trace.calledFrom(@frame) + if f? + @frame = f + @frame.navigateTo() module.exports = NavigationView: NavigationView From e504089141f7ba011e4aa51fd89c6ff7bda691e7 Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 17:55:54 -0400 Subject: [PATCH 24/25] Navigate back to the last active frame. --- lib/navigation-view.coffee | 4 ++++ spec/navigation-view-spec.coffee | 40 ++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index 96aec66..f8b38b1 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -107,4 +107,8 @@ class NavigationView extends View @frame = f @frame.navigateTo() + navigateToLastActive: -> + return unless @frame? + @frame.navigateTo() + module.exports = NavigationView: NavigationView diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index 38e96b8..0ba0dfc 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -9,8 +9,9 @@ fixturePath = (p) -> frames = [ new Frame('raw0', fixturePath('bottom.rb'), 12, 'botfunc') - new Frame('raw1', fixturePath('middle.rb'), 42,'midfunc') + new Frame('raw1', fixturePath('middle.rb'), 42, 'midfunc') new Frame('raw2', fixturePath('top.rb'), 37, 'topfunc') + new Frame('raw3', fixturePath('middle.rb'), 5, 'otherfunc') ] trace = new Stacktrace(frames, 'Boom') @@ -63,36 +64,51 @@ describe 'NavigationView', -> [editor] = [] beforeEach -> - waitsForPromise -> trace.frames[1].navigateTo() + waitsForPromise -> trace.frames[2].navigateTo() runs -> editor = atom.workspace.getActiveEditor() it 'shows the current frame and its index', -> - expect(view.find('.current-frame .function').text()).toBe('midfunc') - expect(view.find('.current-frame .index').text()).toBe('2') - expect(view.find('.current-frame .total').text()).toBe('3') + expect(view.find('.current-frame .function').text()).toBe('topfunc') + expect(view.find('.current-frame .index').text()).toBe('3') + expect(view.find('.current-frame .total').text()).toBe('4') it "navigates to the caller's frame", -> waitsForPromise -> view.navigateToCaller() runs -> - expect(view.frame).toBe(trace.frames[2]) + expect(view.frame).toBe(trace.frames[3]) it 'navigates to the called frame', -> waitsForPromise -> view.navigateToCalled() runs -> - expect(view.frame).toBe(trace.frames[0]) + expect(view.frame).toBe(trace.frames[1]) + + it 'navigates back to the last active frame', -> + editor.setCursorBufferPosition [5, 0] + expect(view.find '.current-frame.unfocused').toHaveLength 1 + + waitsForPromise -> view.navigateToLastActive() + + runs -> + expect(view.find '.current-frame.unfocused').toHaveLength 0 + expect(editor.getCursorBufferPosition().row).toBe 36 describe 'on an editor with multiple frames', -> + [editor] = [] - it 'notices if you manually navigate to a different frame' + beforeEach -> + waitsForPromise -> trace.frames[1].navigateTo() - describe 'on an editor not corresponding to a frame', -> + runs -> + editor = atom.workspace.getActiveEditor() - it 'navigates back to the last active frame' + it 'notices if you manually navigate to a different frame', -> + expect(view.find('.current-frame.function').text()).toEqual 'midfunc' - describe 'without an active stacktrace', -> + editor.setCursorBufferPosition [4, 1] - it 'hides itself' + expect(view.frame).toBe(trace.frames[3]) + expect(view.find('.current-frame.function').text()).toEqual 'otherfunc' From e3c8b3ee7baeebe1c65857ac54543c2111dd230d Mon Sep 17 00:00:00 2001 From: Ash Wilson Date: Sun, 24 Aug 2014 18:07:21 -0400 Subject: [PATCH 25/25] Get those tests passing. --- lib/navigation-view.coffee | 2 +- spec/navigation-view-spec.coffee | 4 ++-- stylesheets/stacktrace.less | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/navigation-view.coffee b/lib/navigation-view.coffee index f8b38b1..c972878 100644 --- a/lib/navigation-view.coffee +++ b/lib/navigation-view.coffee @@ -15,7 +15,7 @@ class NavigationView extends View @span class: 'inline-block icon icon-x', click: 'deactivateTrace' @div class: 'inline-block current-frame unfocused', outlet: 'frameContainer', => @span class: 'inline-block icon icon-code' - @span class: 'inline-block function', outlet: 'frameFunction' + @span class: 'inline-block function', outlet: 'frameFunction', click: 'navigateToLastActive' @span class: 'inline-block index', outlet: 'frameIndex' @span class: 'inline-block divider', '/' @span class: 'inline-block total', outlet: 'frameTotal' diff --git a/spec/navigation-view-spec.coffee b/spec/navigation-view-spec.coffee index 0ba0dfc..c8e9127 100644 --- a/spec/navigation-view-spec.coffee +++ b/spec/navigation-view-spec.coffee @@ -106,9 +106,9 @@ describe 'NavigationView', -> editor = atom.workspace.getActiveEditor() it 'notices if you manually navigate to a different frame', -> - expect(view.find('.current-frame.function').text()).toEqual 'midfunc' + expect(view.find('.current-frame .function').text()).toEqual 'midfunc' editor.setCursorBufferPosition [4, 1] expect(view.frame).toBe(trace.frames[3]) - expect(view.find('.current-frame.function').text()).toEqual 'otherfunc' + expect(view.find('.current-frame .function').text()).toEqual 'otherfunc' diff --git a/stylesheets/stacktrace.less b/stylesheets/stacktrace.less index 2b3b8f3..2af477a 100644 --- a/stylesheets/stacktrace.less +++ b/stylesheets/stacktrace.less @@ -72,6 +72,11 @@ span.function { padding: 1px 3px; font-weight: bold; + + &:hover { + cursor: pointer; + text-decoration: underline; + } } } }