Use path watcher to monitor note changes. Fix #2

Refactor so that the note/directory parsing is done in separate classes.
This commit is contained in:
Seong Jae Lee
2015-04-13 22:02:35 -07:00
parent 574bfc2b3d
commit 2b442b79e7
6 changed files with 279 additions and 70 deletions
+23 -69
View File
@@ -1,17 +1,22 @@
path = require 'path'
fs = require 'fs'
fsPlus = require 'fs-plus'
{$, $$, SelectListView} = require 'atom-space-pen-views'
NoteDirectory = require './note-directory'
Note = require './note'
module.exports =
class NotationalVelocityView extends SelectListView
initialize: ->
super
@addClass('notational-velocity from-top overlay')
@loadData()
rootDirectory = atom.config.get('notational-velocity.directory')
@noteDirectory = new NoteDirectory(rootDirectory, null, () => @updateNotes())
@updateNotes()
@prevFilterQuery = ''
@prevCursorPosition = 0
updateNotes: () ->
@notes = @noteDirectory.getNotes()
@setItems(@notes)
selectItem: (filterQuery) ->
if filterQuery.length == 0
@prevCursorPosition = 0
@@ -24,9 +29,8 @@ class NotationalVelocityView extends SelectListView
titleItem = null
for titlePattern in titlePatterns
titleItems = @items
.filter (x) -> x.title.match(titlePattern) != null
.sort (x, y) -> if x.modified.getTime() <= y.modified.getTime() then 1 else -1
titleItems = @notes
.filter (x) -> x.getTitle().match(titlePattern) != null
titleItem = if titleItems.length > 0 then titleItems[0] else null
if titleItem != null
break
@@ -36,74 +40,25 @@ class NotationalVelocityView extends SelectListView
editor = @filterEditorView.model
currCursorPosition = editor.getCursorBufferPosition().column
if titleItem != null && @prevCursorPosition < currCursorPosition
@prevFilterQuery = titleItem.title
editor.setText(titleItem.title)
editor.selectLeft(titleItem.title.length - filterQuery.length)
@prevFilterQuery = titleItem.getTitle()
editor.setText(titleItem.getTitle())
editor.selectLeft(titleItem.getTitle().length - filterQuery.length)
@prevCursorPosition = currCursorPosition
return titleItem
filter: (filterQuery) ->
if filterQuery.length == 0
return @items
return @notes
queries = filterQuery.split(' ')
.filter (x) -> x.length > 0
.map (x) -> new RegExp(x, 'gi')
contentItems = @items
return @notes
.filter (x) ->
queries
.map (q) -> q.test(x.filetext) || q.test(x.title)
.map (q) -> q.test(x.getText()) || q.test(x.getTitle())
.reduce (x, y) -> x && y
return contentItems
getSubPath: (baseDir, dir)->
ret = []
fullDir = path.join(baseDir, dir)
try
filenameList = fs.readdirSync(fullDir)
catch e
return ret
for filename in filenameList
filePath = path.join(dir, filename)
fullPath = path.join(baseDir, filePath)
try
fileStat = fs.statSync(fullPath)
catch e
continue
if fileStat.isDirectory()
ret = ret.concat(@getSubPath(baseDir, filePath))
else
if !fsPlus.isMarkdownExtension(path.extname(filename))
continue
ret.push(filePath)
return ret
loadData: ->
@data = []
basedir = atom.config.get('notational-velocity.directory')
for filepath in @getSubPath(basedir, '')
fullpath = path.join(basedir, filepath)
filename = path.basename(filepath, path.extname(filepath))
filetext = fs.readFileSync(fullpath, 'utf8')
title = path.join(path.dirname(filepath), filename)
modified = fs.statSync(fullpath).mtime
item = {
'title': title,
'modified': modified,
'filetext': filetext,
'filename': filename,
'filepath': fullpath
}
@data.push(item)
@data = @data.sort (x, y) -> if x.modified.getTime() <= y.modified.getTime() then 1 else -1
@setItems(@data)
getFilterKey: ->
'filetext'
@@ -116,14 +71,13 @@ class NotationalVelocityView extends SelectListView
@show()
viewForItem: (item) ->
index = item.filetext.search /\n/
content = item.filetext.slice(index, item.filetext.length)
content = item.getText()[0...100]
$$ ->
@li class: 'two-lines', =>
@div class: 'primary-line', =>
@span "#{item.title}"
@div class: 'metadata', "#{item.modified.toLocaleDateString()}"
@span "#{item.getTitle()}"
@div class: 'metadata', "#{item.getModified().toLocaleDateString()}"
@div class: 'secondary-line', "#{content}"
confirmSelection: ->
@@ -135,7 +89,7 @@ class NotationalVelocityView extends SelectListView
@cancel()
confirmed: (item) ->
atom.workspace.open(item.filepath)
atom.workspace.open(item.getFilePath())
@cancel()
destroy: ->
@@ -155,7 +109,7 @@ class NotationalVelocityView extends SelectListView
@panel?.hide()
populateList: ->
return unless @items?
return unless @notes?
filterQuery = @getFilterQuery()
filteredItems = @filter(filterQuery)
@@ -176,7 +130,7 @@ class NotationalVelocityView extends SelectListView
@selectItemView(@list.find("li:nth-child(#{n})"))
else
@setError(@getEmptyMessage(@items.length, filteredItems.length))
@setError(@getEmptyMessage(@notes.length, filteredItems.length))
schedulePopulateList: ->
# We can skip it when we are just moving the position of the cursor.
+58
View File
@@ -0,0 +1,58 @@
path = require 'path'
fs = require 'fs-plus'
pathWatcher = require 'pathwatcher'
Note = require './note'
module.exports =
class NoteDirectory
constructor: (@filePath, @parent, @onChangeCallback) ->
@directories = []
@notes = []
@updateMetadata()
@watcher = pathWatcher.watch(@filePath, (event) => @onChange(event))
destroy: ->
@notes.map (x) -> x.destroy()
@directories.map (x) -> x.destroy()
@watcher.close()
updateMetadata: ->
@notes.map (x) -> x.destroy()
@directories.map (x) -> x.destroy()
@directories = []
@notes = []
try
filenames = fs.readdirSync(@filePath)
catch e
return
for filename in filenames
@addChild(path.join(@filePath, filename))
addChild: (filePath) ->
try
fileStat = fs.statSync(filePath)
catch e
return
if fileStat.isDirectory()
@directories.push(new NoteDirectory(filePath, this, @onChangeCallback))
else
if fs.isMarkdownExtension(path.extname(filePath))
@notes.push(new Note(filePath, this, @onChangeCallback))
getNotes: ->
ret = []
ret = ret.concat(@notes)
for directory in @directories
ret = ret.concat(directory.getNotes())
if @parent is null
ret.sort (x, y) -> if x.getModified().getTime() <= y.getModified().getTime() then 1 else -1
return ret
onChange: (event) ->
# For the case of rename and change, it will be handled in its parent.
if event == 'change'
@updateMetadata()
if @onChangeCallback != null
@onChangeCallback()
+37
View File
@@ -0,0 +1,37 @@
path = require 'path'
fs = require 'fs'
pathWatcher = require 'pathwatcher'
module.exports =
class Note
constructor: (@filePath, @parent, @onChangeCallback) ->
@updateMetadata()
@updateText()
@watcher = pathWatcher.watch(@filePath, (event) => @onChange(event))
destroy: ->
@watcher.close()
updateMetadata: ->
@modified = fs.statSync(@filePath).mtime
relativePath = path.relative(atom.config.get('notational-velocity.directory'), @filePath)
@title = path.join(
path.dirname(relativePath),
path.basename(relativePath, path.extname(relativePath))
)
updateText: ->
@text = fs.readFileSync(@filePath, 'utf8')
onChange: (event) ->
# For the case of rename and change, it will be handled in its parent.
if event == 'change' && fs.existsSync(@filePath)
@updateMetadata()
@updateText()
if @onChangeCallback != null
@onChangeCallback()
getTitle: -> @title
getText: -> @text
getModified: -> @modified
getFilePath: -> @filePath