1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-29 00:34:26 +03:00
vimr/VimR/OpenQuicklyFilterOperation.swift

116 lines
3.2 KiB
Swift
Raw Normal View History

/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
2016-09-25 18:50:33 +03:00
class OpenQuicklyFilterOperation: Operation {
2016-09-25 18:50:33 +03:00
fileprivate let chunkSize = 100
fileprivate let maxResultCount = 500
2016-09-25 18:50:33 +03:00
fileprivate let pattern: String
fileprivate let flatFileItems: [FileItem]
fileprivate let cwd: URL
fileprivate unowned let openQuickly: OpenQuicklyWindow
init(forOpenQuickly openQuickly: OpenQuicklyWindow) {
self.openQuickly = openQuickly
self.pattern = openQuickly.pattern
self.cwd = openQuickly.cwd as URL
self.flatFileItems = openQuickly.flatFileItems
super.init()
}
override func main() {
self.openQuickly.scanCondition.lock()
self.openQuickly.pauseScan = true
defer {
self.openQuickly.pauseScan = false
self.openQuickly.scanCondition.broadcast()
self.openQuickly.scanCondition.unlock()
}
2016-09-25 18:50:33 +03:00
if self.isCancelled {
return
}
if self.flatFileItems.isEmpty {
return
}
let sorted: [ScoredFileItem]
if pattern.characters.count == 0 {
let truncatedItems = self.flatFileItems[0...min(self.maxResultCount, self.flatFileItems.count - 1)]
sorted = truncatedItems.map { ScoredFileItem(score: 0, url: $0.url) }
} else {
DispatchUtils.gui { self.openQuickly.startProgress() }
defer { DispatchUtils.gui { self.openQuickly.endProgress() } }
let count = self.flatFileItems.count
let chunksCount = Int(ceil(Float(count) / Float(self.chunkSize)))
2016-09-25 18:50:33 +03:00
let useFullPath = pattern.contains("/")
let cwdPath = self.cwd.path + "/"
var result = [ScoredFileItem]()
2016-09-06 19:45:15 +03:00
var spinLock = OS_SPINLOCK_INIT
2016-09-08 21:16:37 +03:00
2016-09-25 18:50:33 +03:00
let cleanedPattern = useFullPath ? self.pattern.replacingOccurrences(of: "/", with: "")
2016-09-08 21:16:37 +03:00
: self.pattern
2016-09-25 18:50:33 +03:00
DispatchQueue.concurrentPerform(iterations: chunksCount) { [unowned self] idx in
if self.isCancelled {
return
}
let startIndex = min(idx * self.chunkSize, count)
let endIndex = min(startIndex + self.chunkSize, count)
let chunkedItems = self.flatFileItems[startIndex..<endIndex]
let chunkedResult: [ScoredFileItem] = chunkedItems.flatMap {
2016-09-25 18:50:33 +03:00
if self.isCancelled {
return nil
}
let url = $0.url
2016-09-08 21:16:37 +03:00
if useFullPath {
2016-09-25 18:50:33 +03:00
let target = url.path.replacingOccurrences(of: cwdPath, with: "")
.replacingOccurrences(of: "/", with: "")
2016-09-08 21:16:37 +03:00
return ScoredFileItem(score: Scorer.score(target, pattern: cleanedPattern), url: url)
}
2016-09-25 18:50:33 +03:00
return ScoredFileItem(score: Scorer.score(url.lastPathComponent, pattern: cleanedPattern), url: url)
}
2016-09-25 18:50:33 +03:00
if self.isCancelled {
return
}
2016-09-06 19:45:15 +03:00
OSSpinLockLock(&spinLock)
2016-09-25 18:50:33 +03:00
result.append(contentsOf: chunkedResult)
2016-09-06 19:45:15 +03:00
OSSpinLockUnlock(&spinLock)
}
2016-09-25 18:50:33 +03:00
if self.isCancelled {
return
}
2016-09-25 18:50:33 +03:00
sorted = result.sorted(by: >)
}
2016-09-25 18:50:33 +03:00
if self.isCancelled {
return
}
DispatchUtils.gui {
let result = Array(sorted[0...min(self.maxResultCount, sorted.count - 1)])
self.openQuickly.reloadFileView(withScoredItems: result)
}
}
2016-09-25 18:50:33 +03:00
}