     @subscriptions.add @observeTextEditors()
     @subscriptions.add @observeActivePaneItem()
     @subscriptions.add @observeOnWillDestroyPaneItem()
-    # @subscriptions.add @extendSymbolsView()
 
   deactivate: ->
     for editorID, disposables of @editorSubscriptions

        LastEditor.saveDestroyedEditor item

  needRemember: (oldBufferPosition, newBufferPosition) ->
    # console.log [oldBufferPosition, newBufferPosition]
    # Line number delata exceeds or not.
    Math.abs(oldBufferPosition.row - newBufferPosition.row) > @rowDeltaToRemember

  # Helpers
  #-----------------
  withPanel: (panel, {onShow, onHide}) ->
    [oldEditor, oldPoint, newEditor, newPoint] = []
    panelSubscription = panel.onDidChangeVisible (visible) =>
      if visible
        @lock panel.getItem().constructor.name
        {editor: oldEditor, point: oldPoint} = onShow()
      else
        # ProjectView delayed changing cursor position after panel hidden(),
        setTimeout =>
          {editor: newEditor, point: newPoint} = onHide()

          # FIXME: oldPoint sometimes became undefined, so need to guard
          if oldPoint and newPoint and @needRemember(oldPoint, newPoint)
            @history.add oldEditor, oldPoint, oldEditor.getURI(), dumpMessage: "[Cursor moved] save history"
          @unLock()
        , 300

    @subscriptions.add panel.onDidDestroy ->
      panelSubscription.dispose()

  lock:     -> @locked = true
  unLock:   -> @locked = false
  isLocked: -> @locked

  jump: (direction) ->
    # Settings tab is not TextEditor instance.
    return unless activeEditor = @getEditor()
    return unless entry = @history["get#{direction}"]()

    if direction is 'Prev' and @history.isNewest()
      point = activeEditor.getCursorBufferPosition()
      URI   = activeEditor.getURI()
      @history.pushToHead activeEditor, point, URI

    @lock()

    {URI, point} = entry

    if activeEditor.getURI() is URI # Same pane.
      # Intentionally disable `autoscroll` to set cursor position middle of
      # screen afterward.
      activeEditor.setCursorBufferPosition point, autoscroll: false
      # Adjust cursor position to middle of screen.
      activeEditor.scrollToCursorPosition()
      @land direction
    else
      # Jump to different pane

      @openTags['GoToView']    = extendOpenTag main.createGoToView()
      @openTags['GoBackView']  = extendOpenTag main.createGoBackView()

  # For better handling symbols-view.
  # -------------------------
  observeModalPanel: ->
    withPanel = (panel, {onDidShow, onDidHide}) =>
      [oldEditor, oldPoint, newEditor, newPoint] = []
      panelSubscription = panel.onDidChangeVisible (visible) =>
        if visible
          @lock()
          {editor: oldEditor, point: oldPoint} = onDidShow()
        else
          # Final position is set after some delay from panel hidden.
          setTimeout =>
            {editor: newEditor, point: newPoint} = onDidHide()

            # FIXME: oldPoint sometimes became undefined, so need to guard
            if oldPoint and newPoint and @needRemember(oldPoint, newPoint)
              @history.add oldEditor, oldPoint, oldEditor.getURI(), dumpMessage: "[Cursor moved] save history"
            @unLock()
          , 300

      @subscriptions.add panel.onDidDestroy =>
        panelSubscription.dispose()

    symbolsViewHandlers =
      FileView: (panel) =>
        withPanel panel,
          # At the timing symbol-views panel show, first item in symobls
          # already selected(this mean cursor position have changed).
          # So we can't use TexitEditor::getCursorBufferPosition(), fotunately,
          # FileView serialize buffer state initaially, we use this.
          onDidShow: =>
            @debug "Shown FileView"
            editor = @getEditor()
            point  = panel.getItem().initialState?.bufferRanges[0].start
            {editor, point}
          onDidHide: =>
            @debug "Hidden FileView"
            editor = @getEditor()
            point  = @getPosition editor
            {editor, point}

      ProjectView: (panel) =>
        withPanel panel,
          onDidShow: =>
            @debug "Shown ProjectView"
            editor = @getEditor()
            point  = @getPosition editor
            {editor, point}
          onDidHide: =>
            @debug "Hidden ProjectView"
            editor = @getEditor()
            point  = @getPosition editor
            {editor, point}

    atom.workspace.panelContainers['modal'].onDidAddPanel ({panel, index}) =>
      # [CAUTION] Simply checking constructor name is not enough.
      # e.g. ProjectView is also used in `fuzzy-finder`.
      # return unless name in ['GoToView', 'GoBackView', 'FileView', 'ProjectView']
      item = panel.getItem()
      name = item.constructor.name
      if name in ['FileView', 'ProjectView'] and typeof(item.openTag) is 'function'
        symbolsViewHandlers[name]?(panel)

  observeTextEditors: ->
    onDidChangePath = (editor) =>
      oldURI = editor.getURI()

      editor.onDidChangePath =>
        newURI = editor.getURI()
        @history.rename oldURI, newURI
        @lastEditor.rename oldURI, newURI
        oldURI = newURI

    onDidChangeCursorPosition = (editor) =>
      editor.onDidChangeCursorPosition ({oldBufferPosition, newBufferPosition}) =>
        return if @isLocked() # for performance
        return if editor.hasMultipleCursors()
        return if oldBufferPosition.row is newBufferPosition.row # for performance
        return unless @needRemember(oldBufferPosition, newBufferPosition)

        setTimeout =>
          # When symbols-view's modal panel shown, we lock() but its delayed.
          # So we need lock state again here after some delay.
          return if @isLocked()
          # @debug "Move #{oldBufferPosition.toString()} -> #{newBufferPosition.toString()}"
          @history.add editor, oldBufferPosition, editor.getURI(), dumpMessage: "[Cursor moved] save history"
        , 300

    onDidDestroy = (editor) =>
