mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 19:17:09 +03:00
Add bookmarks service…
…for consumption by other packages. This is nearly the simplest possible interface around the `bookmarks` package, except that it will fire events when the number of bookmarks has changed.
This commit is contained in:
parent
99fbca95be
commit
3ed145afb3
31
packages/bookmarks/lib/bookmarks-provider.js
Normal file
31
packages/bookmarks/lib/bookmarks-provider.js
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
class BookmarksProvider {
|
||||
constructor(main) {
|
||||
this.main = main
|
||||
}
|
||||
|
||||
// Returns all bookmarks present in the given editor.
|
||||
//
|
||||
// Each bookmark tracks a buffer range and is represented by an instance of
|
||||
// {DisplayMarker}.
|
||||
//
|
||||
// Will return an empty array if there are no bookmarks in the given editor.
|
||||
//
|
||||
// Keep in mind that a single bookmark can span multiple buffer rows and/or
|
||||
// screen rows. Thus there isn't necessarily a 1:1 correlation between the
|
||||
// number of bookmarks in the editor and the number of bookmark icons that
|
||||
// the user will see in the gutter.
|
||||
getBookmarksForEditor(editor) {
|
||||
let instance = this.getInstanceForEditor(editor)
|
||||
if (!instance) return null
|
||||
return instance.getAllBookmarks()
|
||||
}
|
||||
|
||||
// Returns the instance of the `Bookmarks` class that is responsible for
|
||||
// managing bookmarks in the given editor.
|
||||
getInstanceForEditor(editor) {
|
||||
return this.main.editorsBookmarks.find(b => b.editor.id === editor.id)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BookmarksProvider
|
@ -1,12 +1,13 @@
|
||||
const {CompositeDisposable} = require('atom')
|
||||
const {CompositeDisposable, Emitter} = require('atom')
|
||||
|
||||
module.exports =
|
||||
class Bookmarks {
|
||||
static deserialize (editor, state) {
|
||||
static deserialize(editor, state) {
|
||||
return new Bookmarks(editor, editor.getMarkerLayer(state.markerLayerId))
|
||||
}
|
||||
|
||||
constructor (editor, markerLayer) {
|
||||
constructor(editor, markerLayer) {
|
||||
this.emitter = new Emitter()
|
||||
this.editor = editor
|
||||
this.markerLayer = markerLayer || this.editor.addMarkerLayer({persistent: true})
|
||||
this.decorationLayer = this.editor.decorateMarkerLayer(this.markerLayer, {type: 'line-number', class: 'bookmarked'})
|
||||
@ -24,23 +25,23 @@ class Bookmarks {
|
||||
this.disposables.add(this.editor.onDidDestroy(this.destroy.bind(this)))
|
||||
}
|
||||
|
||||
destroy () {
|
||||
destroy() {
|
||||
this.deactivate()
|
||||
this.markerLayer.destroy()
|
||||
}
|
||||
|
||||
deactivate () {
|
||||
deactivate() {
|
||||
this.decorationLayer.destroy()
|
||||
this.decorationLayerLine.destroy()
|
||||
this.decorationLayerHighlight.destroy()
|
||||
this.disposables.dispose()
|
||||
}
|
||||
|
||||
serialize () {
|
||||
serialize() {
|
||||
return {markerLayerId: this.markerLayer.id}
|
||||
}
|
||||
|
||||
toggleBookmark () {
|
||||
toggleBookmark() {
|
||||
for (const range of this.editor.getSelectedBufferRanges()) {
|
||||
const bookmarks = this.markerLayer.findMarkers({intersectsRowRange: [range.start.row, range.end.row]})
|
||||
if (bookmarks && bookmarks.length > 0) {
|
||||
@ -52,19 +53,34 @@ class Bookmarks {
|
||||
this.disposables.add(bookmark.onDidChange(({isValid}) => {
|
||||
if (!isValid) {
|
||||
bookmark.destroy()
|
||||
// TODO: If N bookmarks are affected by a buffer change,
|
||||
// `did-change-bookmarks` will be emitted N times. We could
|
||||
// debounce this if we were willing to go async.
|
||||
this.emitter.emit('did-change-bookmarks', this.getAllBookmarks())
|
||||
}
|
||||
}))
|
||||
}
|
||||
this.emitter.emit('did-change-bookmarks', this.getAllBookmarks())
|
||||
}
|
||||
}
|
||||
|
||||
clearBookmarks () {
|
||||
getAllBookmarks() {
|
||||
let markers = this.markerLayer.getMarkers()
|
||||
return markers
|
||||
}
|
||||
|
||||
onDidChangeBookmarks(callback) {
|
||||
return this.emitter.on('did-change-bookmarks', callback)
|
||||
}
|
||||
|
||||
clearBookmarks() {
|
||||
for (const bookmark of this.markerLayer.getMarkers()) {
|
||||
bookmark.destroy()
|
||||
}
|
||||
this.emitter.emit('did-change-bookmarks', [])
|
||||
}
|
||||
|
||||
jumpToNextBookmark () {
|
||||
jumpToNextBookmark() {
|
||||
if (this.markerLayer.getMarkerCount() > 0) {
|
||||
const bufferRow = this.editor.getLastCursor().getMarker().getStartBufferPosition().row
|
||||
const markers = this.markerLayer.getMarkers().sort((a, b) => a.compare(b))
|
||||
@ -76,7 +92,7 @@ class Bookmarks {
|
||||
}
|
||||
}
|
||||
|
||||
jumpToPreviousBookmark () {
|
||||
jumpToPreviousBookmark() {
|
||||
if (this.markerLayer.getMarkerCount() > 0) {
|
||||
const bufferRow = this.editor.getLastCursor().getMarker().getStartBufferPosition().row
|
||||
const markers = this.markerLayer.getMarkers().sort((a, b) => b.compare(a))
|
||||
@ -88,7 +104,7 @@ class Bookmarks {
|
||||
}
|
||||
}
|
||||
|
||||
selectToNextBookmark () {
|
||||
selectToNextBookmark() {
|
||||
if (this.markerLayer.getMarkerCount() > 0) {
|
||||
const bufferRow = this.editor.getLastCursor().getMarker().getStartBufferPosition().row
|
||||
const markers = this.markerLayer.getMarkers().sort((a, b) => a.compare(b))
|
||||
@ -103,7 +119,7 @@ class Bookmarks {
|
||||
}
|
||||
}
|
||||
|
||||
selectToPreviousBookmark () {
|
||||
selectToPreviousBookmark() {
|
||||
if (this.markerLayer.getMarkerCount() > 0) {
|
||||
const bufferRow = this.editor.getLastCursor().getMarker().getStartBufferPosition().row
|
||||
const markers = this.markerLayer.getMarkers().sort((a, b) => b.compare(a))
|
||||
|
@ -2,9 +2,10 @@ const {CompositeDisposable} = require('atom')
|
||||
|
||||
const Bookmarks = require('./bookmarks')
|
||||
const BookmarksView = require('./bookmarks-view')
|
||||
const BookmarksProvider = require('./bookmarks-provider')
|
||||
|
||||
module.exports = {
|
||||
activate (bookmarksByEditorId) {
|
||||
activate(bookmarksByEditorId) {
|
||||
this.bookmarksView = null
|
||||
this.editorsBookmarks = []
|
||||
this.disposables = new CompositeDisposable()
|
||||
@ -44,7 +45,7 @@ module.exports = {
|
||||
})
|
||||
},
|
||||
|
||||
deactivate () {
|
||||
deactivate() {
|
||||
if (this.bookmarksView != null) {
|
||||
this.bookmarksView.destroy()
|
||||
this.bookmarksView = null
|
||||
@ -56,11 +57,16 @@ module.exports = {
|
||||
this.disposables.dispose()
|
||||
},
|
||||
|
||||
serialize () {
|
||||
serialize() {
|
||||
const bookmarksByEditorId = {}
|
||||
for (let bookmarks of this.editorsBookmarks) {
|
||||
bookmarksByEditorId[bookmarks.editor.id] = bookmarks.serialize()
|
||||
}
|
||||
return bookmarksByEditorId
|
||||
},
|
||||
|
||||
provideBookmarks() {
|
||||
this.bookmarksProvider ??= new BookmarksProvider(this)
|
||||
return this.bookmarksProvider
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-select-list": "^0.7.0"
|
||||
},
|
||||
|
||||
"providedServices": {
|
||||
"bookmarks": {
|
||||
"description": "Provides a list of bookmarks to any package that wants to know about them.",
|
||||
"versions": {
|
||||
"1.0.0": "provideBookmarks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
describe('Bookmarks package', () => {
|
||||
let [workspaceElement, editorElement, editor, bookmarks] = []
|
||||
let workspaceElement, editorElement, editor, bookmarks, provider
|
||||
|
||||
const bookmarkedRangesForEditor = editor => {
|
||||
const decorationsById = editor.decorationsStateForScreenRowRange(0, editor.getLastScreenRow())
|
||||
@ -18,6 +18,7 @@ describe('Bookmarks package', () => {
|
||||
await atom.workspace.open('sample.js')
|
||||
|
||||
bookmarks = (await atom.packages.activatePackage('bookmarks')).mainModule
|
||||
provider = bookmarks.bookmarksProvider
|
||||
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
@ -32,17 +33,28 @@ describe('Bookmarks package', () => {
|
||||
expect(bookmarkedRangesForEditor(editor)).toEqual([])
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(bookmarkedRangesForEditor(editor)).toEqual([[[3, 10], [3, 10]]])
|
||||
|
||||
let marks = provider.getBookmarksForEditor(editor)
|
||||
expect(marks.length).toBe(1)
|
||||
expect(marks.map(m => m.getScreenRange())).toEqual(bookmarkedRangesForEditor(editor))
|
||||
})
|
||||
|
||||
it('removes marker when toggled', () => {
|
||||
let callback = jasmine.createSpy()
|
||||
|
||||
let instance = provider.getInstanceForEditor(editor)
|
||||
instance.onDidChangeBookmarks(callback)
|
||||
|
||||
editor.setCursorBufferPosition([3, 10])
|
||||
expect(bookmarkedRangesForEditor(editor).length).toBe(0)
|
||||
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(bookmarkedRangesForEditor(editor).length).toBe(1)
|
||||
expect(callback.callCount).toBe(1)
|
||||
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(bookmarkedRangesForEditor(editor).length).toBe(0)
|
||||
expect(callback.callCount).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
@ -53,6 +65,8 @@ describe('Bookmarks package', () => {
|
||||
expect(bookmarkedRangesForEditor(editor)).toEqual([])
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(bookmarkedRangesForEditor(editor)).toEqual([[[3, 10], [3, 10]], [[6, 11], [6, 11]]])
|
||||
let instance = provider.getInstanceForEditor(editor)
|
||||
expect(instance.getAllBookmarks().length).toBe(2)
|
||||
})
|
||||
|
||||
it('removes multiple markers when toggled', () => {
|
||||
@ -215,27 +229,39 @@ describe('Bookmarks package', () => {
|
||||
})
|
||||
|
||||
it('clears all bookmarks', () => {
|
||||
let callback = jasmine.createSpy()
|
||||
let instance = provider.getInstanceForEditor(editor)
|
||||
instance.onDidChangeBookmarks(callback)
|
||||
|
||||
editor.setCursorBufferPosition([3, 10])
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(callback.callCount).toBe(1)
|
||||
|
||||
editor.setCursorBufferPosition([5, 0])
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(callback.callCount).toBe(2)
|
||||
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:clear-bookmarks')
|
||||
expect(getBookmarkedLineNodes(editorElement).length).toBe(0)
|
||||
expect(callback.callCount).toBe(3)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a bookmark is invalidated', () => {
|
||||
it('creates a marker when toggled', () => {
|
||||
let callback = jasmine.createSpy()
|
||||
let instance = provider.getInstanceForEditor(editor)
|
||||
instance.onDidChangeBookmarks(callback)
|
||||
editor.setCursorBufferPosition([3, 10])
|
||||
expect(bookmarkedRangesForEditor(editor).length).toBe(0)
|
||||
|
||||
atom.commands.dispatch(editorElement, 'bookmarks:toggle-bookmark')
|
||||
expect(bookmarkedRangesForEditor(editor).length).toBe(1)
|
||||
expect(callback.callCount).toBe(1)
|
||||
|
||||
editor.setText('')
|
||||
expect(bookmarkedRangesForEditor(editor).length).toBe(0)
|
||||
expect(callback.callCount).toBe(2)
|
||||
})
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user