1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-11-24 03:25:03 +03:00

GH-274 Use ignore patterns pref items

This commit is contained in:
Tae Won Ha 2016-09-11 14:28:56 +02:00
parent 3a7a5eed2f
commit 828ac1c690
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
13 changed files with 162 additions and 91 deletions

View File

@ -120,6 +120,13 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
NSPipe *inputPipe = [NSPipe pipe];
_neoVimServerTask = [[NSTask alloc] init];
#ifndef DEBUG
NSFileHandle *nullFileHandle = [NSFileHandle fileHandleWithNullDevice];
_neoVimServerTask.standardOutput = nullFileHandle;
_neoVimServerTask.standardError = nullFileHandle;
#endif
_neoVimServerTask.standardInput = inputPipe;
_neoVimServerTask.currentDirectoryPath = NSHomeDirectory();
_neoVimServerTask.launchPath = shellPath;

View File

@ -109,6 +109,7 @@
4BEE79171D16D3800012EDAA /* CellAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE79161D16D3800012EDAA /* CellAttributes.swift */; };
4BF07EE41D51326A009BECEB /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 4BF07EE61D51326A009BECEB /* Credits.rtf */; };
4BF6E29C1D34153C0053FA76 /* KeyUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF6E29B1D34153C0053FA76 /* KeyUtils.swift */; };
4BF8EED81D85574800CAC08A /* PrefUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8EED71D85574800CAC08A /* PrefUtils.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -297,6 +298,7 @@
4BEE79161D16D3800012EDAA /* CellAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellAttributes.swift; sourceTree = "<group>"; };
4BF07EE51D51326A009BECEB /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = Base; path = Base.lproj/Credits.rtf; sourceTree = "<group>"; };
4BF6E29B1D34153C0053FA76 /* KeyUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyUtils.swift; sourceTree = "<group>"; };
4BF8EED71D85574800CAC08A /* PrefUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefUtils.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -385,6 +387,7 @@
4B56CE2F1D5FC27100337673 /* GeneralPrefPane.swift */,
4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */,
4B37ADBA1D6EC11600970D55 /* TestPane.swift */,
4BF8EED71D85574800CAC08A /* PrefUtils.swift */,
);
name = Preferences;
sourceTree = "<group>";
@ -873,6 +876,7 @@
4B4FC8E61D3E8739009352C3 /* PrefWindowComponent.swift in Sources */,
4B6A70961D6100E300E12030 /* SwiftCommons.swift in Sources */,
4B56CE301D5FC27100337673 /* GeneralPrefPane.swift in Sources */,
4BF8EED81D85574800CAC08A /* PrefUtils.swift in Sources */,
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */,
1929B165820D7177743B537A /* Component.swift in Sources */,
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */,

View File

@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4B2A2BF61D0351810074CE9A"
BuildableName = "SwiftNeoVim.framework"
BuildableName = "SwiftNeoVim"
BlueprintName = "SwiftNeoVim"
ReferencedContainer = "container:VimR.xcodeproj">
</BuildableReference>

View File

@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BEBA5041CFF374B00673FDF"
BuildableName = "VimR.app"
BuildableName = "VimR"
BlueprintName = "VimR"
ReferencedContainer = "container:VimR.xcodeproj">
</BuildableReference>
@ -66,7 +66,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BEBA5041CFF374B00673FDF"
BuildableName = "VimR.app"
BuildableName = "VimR"
BlueprintName = "VimR"
ReferencedContainer = "container:VimR.xcodeproj">
</BuildableReference>

View File

@ -48,7 +48,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
self.prefStore = PrefStore(source: self.actionSink)
self.fileItemService.set(ignorePatterns: Set([ "*/.git", "*.o", "*.d", "*.dia" ].map(FileItemIgnorePattern.init)))
self.fileItemService.set(ignorePatterns: self.prefStore.data.general.ignorePatterns)
self.prefWindowComponent = PrefWindowComponent(source: self.changeSink, initialData: self.prefStore.data)
self.mainWindowManager = MainWindowManager(source: self.changeSink,
@ -59,6 +59,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
super.init()
self.prefStore.sink
.filter { $0 is PrefData }
.map { $0 as! PrefData }
.subscribeNext { [unowned self] data in
if data.general.ignorePatterns == self.fileItemService.ignorePatterns {
return
}
self.fileItemService.set(ignorePatterns: data.general.ignorePatterns)
}
.addDisposableTo(self.disposeBag)
self.mainWindowManager.sink
.filter { $0 is MainWindowEvent || $0 is MainWindowAction }
.subscribeNext { [unowned self] event in

View File

@ -7,7 +7,7 @@ import Cocoa
import PureLayout
import RxSwift
struct AppearancePrefData {
struct AppearancePrefData: Equatable {
let editorFont: NSFont
let editorUsesLigatures: Bool
}
@ -16,25 +16,13 @@ func == (left: AppearancePrefData, right: AppearancePrefData) -> Bool {
return left.editorUsesLigatures == right.editorUsesLigatures && left.editorFont.isEqualTo(right.editorFont)
}
func != (left: AppearancePrefData, right: AppearancePrefData) -> Bool {
return !(left == right)
}
class AppearancePrefPane: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate {
override var pinToContainer: Bool {
return true
}
private var data: AppearancePrefData {
willSet {
self.updateViews(newData: newValue)
}
didSet {
self.publish(event: self.data)
}
}
private var data: AppearancePrefData
private let fontManager = NSFontManager.sharedFontManager()
@ -55,18 +43,28 @@ class AppearancePrefPane: PrefPane, NSComboBoxDelegate, NSControlTextEditingDele
init(source: Observable<Any>, initialData: AppearancePrefData) {
self.data = initialData
super.init(source: source)
self.updateViews(newData: initialData)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func set(data data: AppearancePrefData) {
self.data = data
self.publish(event: data)
}
override func subscription(source source: Observable<Any>) -> Disposable {
return source
.filter { $0 is PrefData }
.map { ($0 as! PrefData).appearance }
.filter { [unowned self] data in data != self.data }
.subscribeNext { [unowned self] data in self.data = data }
.subscribeNext { [unowned self] data in
self.updateViews(newData: data)
self.data = data
}
}
override func addViews() {
@ -157,15 +155,13 @@ class AppearancePrefPane: PrefPane, NSComboBoxDelegate, NSControlTextEditingDele
}
private func updateViews(newData newData: AppearancePrefData) {
let oldFont = self.data.editorFont
let newFont = newData.editorFont
let ligatureValueDiffers = newData.editorUsesLigatures != self.data.editorUsesLigatures
call(self.fontPopup.selectItemWithTitle(newFont.fontName), whenNot: newFont.fontName == oldFont.fontName)
call(self.sizeCombo.stringValue = String(Int(newFont.pointSize)), whenNot: newFont.pointSize == oldFont.pointSize)
call(self.ligatureCheckbox.boolState = newData.editorUsesLigatures, when: ligatureValueDiffers)
call(self.previewArea.font = newData.editorFont, whenNot: newFont.isEqualTo(self.data.editorFont))
if ligatureValueDiffers {
self.fontPopup.selectItemWithTitle(newFont.fontName)
self.sizeCombo.stringValue = String(Int(newFont.pointSize))
self.ligatureCheckbox.boolState = newData.editorUsesLigatures
self.previewArea.font = newData.editorFont
if newData.editorUsesLigatures {
self.previewArea.useAllLigatures(self)
} else {
@ -173,13 +169,12 @@ class AppearancePrefPane: PrefPane, NSComboBoxDelegate, NSControlTextEditingDele
}
}
}
}
// MARK: - Actions
extension AppearancePrefPane {
func usesLigaturesAction(sender: NSButton) {
self.data = AppearancePrefData(editorFont: self.data.editorFont, editorUsesLigatures: sender.boolState)
self.set(data: AppearancePrefData(editorFont: self.data.editorFont, editorUsesLigatures: sender.boolState))
}
func fontPopupAction(sender: NSPopUpButton) {
@ -195,7 +190,7 @@ extension AppearancePrefPane {
return
}
self.data = AppearancePrefData(editorFont: newFont, editorUsesLigatures: self.data.editorUsesLigatures)
self.set(data: AppearancePrefData(editorFont: newFont, editorUsesLigatures: self.data.editorUsesLigatures))
}
func comboBoxSelectionDidChange(notification: NSNotification) {
@ -206,14 +201,14 @@ extension AppearancePrefPane {
let newFontSize = self.cappedFontSize(Int(self.sizes[self.sizeCombo.indexOfSelectedItem]))
let newFont = self.fontManager.convertFont(self.data.editorFont, toSize: newFontSize)
self.data = AppearancePrefData(editorFont: newFont, editorUsesLigatures: self.data.editorUsesLigatures)
self.set(data: AppearancePrefData(editorFont: newFont, editorUsesLigatures: self.data.editorUsesLigatures))
}
func sizeComboBoxDidEnter(sender: AnyObject!) {
let newFontSize = self.cappedFontSize(self.sizeCombo.integerValue)
let newFont = self.fontManager.convertFont(self.data.editorFont, toSize: newFontSize)
self.data = AppearancePrefData(editorFont: newFont, editorUsesLigatures: self.data.editorUsesLigatures)
self.set(data: AppearancePrefData(editorFont: newFont, editorUsesLigatures: self.data.editorUsesLigatures))
}
private func cappedFontSize(size: Int) -> CGFloat {

View File

@ -12,7 +12,7 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" releasedWhenClosed="NO" frameAutosaveName="38.pref-window.frame" animationBehavior="default" id="QvC-M9-y7g">
<window title="Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="38.pref-window.frame" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="196" y="240" width="640" height="300"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>

View File

@ -6,15 +6,19 @@
import Foundation
func ==(lhs: FileItemIgnorePattern, rhs: FileItemIgnorePattern) -> Bool {
return false
return lhs.pattern == rhs.pattern
}
class FileItemIgnorePattern: Hashable {
class FileItemIgnorePattern: Hashable, CustomStringConvertible {
var hashValue: Int {
return self.pattern.hashValue
}
var description: String {
return "<FileItemIgnorePattern: pattern: '\(self.pattern)', folderPattern: '\(self.folderPattern)'>"
}
let folderPattern: Bool
let pattern: String

View File

@ -17,6 +17,7 @@ struct GeneralPrefData: Equatable {
func == (left: GeneralPrefData, right: GeneralPrefData) -> Bool {
return left.openNewWindowWhenLaunching == right.openNewWindowWhenLaunching
&& left.openNewWindowOnReactivation == right.openNewWindowOnReactivation
&& left.ignorePatterns == right.ignorePatterns
}
class GeneralPrefPane: PrefPane {
@ -25,22 +26,18 @@ class GeneralPrefPane: PrefPane {
return true
}
private var data: GeneralPrefData {
willSet {
self.updateViews(newData: newValue)
}
didSet {
self.publish(event: self.data)
}
}
private var data: GeneralPrefData
private let openWhenLaunchingCheckbox = NSButton(forAutoLayout: ())
private let openOnReactivationCheckbox = NSButton(forAutoLayout: ())
private let ignoreField = NSTextField(forAutoLayout: ())
init(source: Observable<Any>, initialData: GeneralPrefData) {
self.data = initialData
super.init(source: source)
self.updateViews(newData: initialData)
self.addReactions()
}
required init?(coder: NSCoder) {
@ -56,13 +53,13 @@ class GeneralPrefPane: PrefPane {
action: #selector(GeneralPrefPane.openUntitledWindowWhenLaunchingAction(_:)))
self.configureCheckbox(button: self.openOnReactivationCheckbox,
title: "On Re-Activation",
action: #selector(GeneralPrefPane.openUntitledWindowOnReactivation(_:)))
action: #selector(GeneralPrefPane.openUntitledWindowOnReactivationAction(_:)))
let whenLaunching = self.openWhenLaunchingCheckbox
let onReactivation = self.openOnReactivationCheckbox
let ignoreListTitle = self.titleTextField(title: "Files To Ignore:")
let ignoreField = NSTextField(forAutoLayout: ())
let ignoreField = self.ignoreField
let ignoreInfo = self.infoTextField(text: "")
ignoreInfo.attributedStringValue = self.ignoreInfoText()
@ -139,40 +136,55 @@ class GeneralPrefPane: PrefPane {
.filter { $0 is PrefData }
.map { ($0 as! PrefData).general }
.filter { [unowned self] data in data != self.data }
.subscribeNext { [unowned self] data in self.data = data }
.subscribeNext { [unowned self] data in
self.updateViews(newData: data)
self.data = data
}
}
private func addReactions() {
self.ignoreField.rx_text
.skip(1) // To skip the event when the field gets created and is not yet initialized.
.throttle(0.2, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { Observable.just(PrefUtils.ignorePatterns(fromString: $0)) }
.subscribeNext { [unowned self] patterns in
self.ignorePatternsAction(patterns)
}
.addDisposableTo(self.disposeBag)
}
private func set(data data: GeneralPrefData) {
self.data = data
self.publish(event: data)
}
private func ignoreInfoText() -> NSAttributedString {
let wikiUrl = NSURL(string: "https://github.com/qvacua/vimr/wiki")!
let font = NSFont.systemFontOfSize(NSFont.smallSystemFontSize())
let attrs = [
NSFontAttributeName: font,
NSForegroundColorAttributeName: NSColor.grayColor()
]
let wikiUrl = NSURL(string: "https://github.com/qvacua/vimr/wiki")!
let linkStr = NSAttributedString.link(withUrl: wikiUrl, text: "VimR Wiki", font: font)
let ignoreInfoStr = NSMutableAttributedString(string:
"Comma-separated list of ignore patterns\n"
+ "Matching files will be ignored in \"Open Quickly\".\n"
+ "Example: */.git, */node_modules\n"
+ "For detailed information go to ",
attributes:[
NSFontAttributeName: font,
NSForegroundColorAttributeName: NSColor.grayColor()
]
)
attributes:attrs)
ignoreInfoStr.appendAttributedString(linkStr)
ignoreInfoStr.appendAttributedString(
NSAttributedString(string: ".", attributes: [
NSFontAttributeName: font,
NSForegroundColorAttributeName: NSColor.grayColor()
])
)
ignoreInfoStr.appendAttributedString(NSAttributedString(string: ".", attributes: attrs))
return ignoreInfoStr
}
private func updateViews(newData newData: GeneralPrefData) {
call(self.openWhenLaunchingCheckbox.boolState = newData.openNewWindowWhenLaunching,
whenNot: newData.openNewWindowWhenLaunching == self.data.openNewWindowWhenLaunching)
call(self.openOnReactivationCheckbox.boolState = newData.openNewWindowOnReactivation,
whenNot: newData.openNewWindowOnReactivation == self.data.openNewWindowOnReactivation)
self.openWhenLaunchingCheckbox.boolState = newData.openNewWindowWhenLaunching
self.openOnReactivationCheckbox.boolState = newData.openNewWindowOnReactivation
self.ignoreField.stringValue = PrefUtils.ignorePatternString(fromSet: newData.ignorePatterns)
}
}
@ -210,15 +222,27 @@ extension GeneralPrefPane {
}
func openUntitledWindowWhenLaunchingAction(sender: NSButton) {
self.data = GeneralPrefData(openNewWindowWhenLaunching: self.openWhenLaunchingCheckbox.boolState,
self.set(data: GeneralPrefData(
openNewWindowWhenLaunching: self.openWhenLaunchingCheckbox.boolState,
openNewWindowOnReactivation: self.data.openNewWindowOnReactivation,
ignorePatterns: self.data.ignorePatterns)
)
}
func openUntitledWindowOnReactivation(sender: NSButton) {
self.data = GeneralPrefData(openNewWindowWhenLaunching: self.data.openNewWindowWhenLaunching,
func openUntitledWindowOnReactivationAction(sender: NSButton) {
self.set(data: GeneralPrefData(
openNewWindowWhenLaunching: self.data.openNewWindowWhenLaunching,
openNewWindowOnReactivation: self.openOnReactivationCheckbox.boolState,
ignorePatterns: self.data.ignorePatterns)
)
}
private func ignorePatternsAction(patterns: Set<FileItemIgnorePattern>) {
self.set(data: GeneralPrefData(
openNewWindowWhenLaunching: self.data.openNewWindowWhenLaunching,
openNewWindowOnReactivation: self.data.openNewWindowOnReactivation,
ignorePatterns: patterns)
)
}
private func alert(title title: String, info: String) {

View File

@ -8,8 +8,9 @@ import RxSwift
class PrefPane: NSView, Component {
let disposeBag = DisposeBag()
private let source: Observable<Any>
private let disposeBag = DisposeBag()
private let subject = PublishSubject<Any>()
var sink: Observable<Any> {

View File

@ -58,18 +58,6 @@ class PrefStore: Store {
self.subject.onCompleted()
}
private func ignorePatterns(fromString str: String) -> Set<FileItemIgnorePattern> {
return Set(str
.componentsSeparatedByString(",")
.map {
FileItemIgnorePattern(pattern: $0.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()))
})
}
private func ignorePatternString(fromSet set: Set<FileItemIgnorePattern>) -> String {
return set.reduce("") { "\($0), \($1.pattern)" }
}
private func prefDataFromDict(prefs: [String: AnyObject]) -> PrefData {
let editorFontName = prefs[PrefKeys.editorFontName] as? String ?? PrefStore.defaultEditorFont.fontName
@ -83,7 +71,7 @@ class PrefStore: Store {
let openNewWindowOnReactivation = (prefs[PrefKeys.openNewWindowOnReactivation] as? NSNumber)?.boolValue ?? true
let ignorePatternsList = (prefs[PrefKeys.openQuicklyIgnorePatterns] as? String) ?? "*/.git, *.o, *.d, *.dia"
let ignorePatterns = self.ignorePatterns(fromString: ignorePatternsList)
let ignorePatterns = PrefUtils.ignorePatterns(fromString: ignorePatternsList)
return PrefData(
general: GeneralPrefData(
@ -116,7 +104,7 @@ class PrefStore: Store {
// General
PrefKeys.openNewWindowWhenLaunching: generalData.openNewWindowWhenLaunching,
PrefKeys.openNewWindowOnReactivation: generalData.openNewWindowOnReactivation,
PrefKeys.openQuicklyIgnorePatterns: self.ignorePatternString(fromSet: generalData.ignorePatterns),
PrefKeys.openQuicklyIgnorePatterns: PrefUtils.ignorePatternString(fromSet: generalData.ignorePatterns),
// Appearance
PrefKeys.editorFontName: appearanceData.editorFont.fontName,

36
VimR/PrefUtils.swift Normal file
View File

@ -0,0 +1,36 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class PrefUtils {
private static let whitespaceCharSet = NSCharacterSet.whitespaceCharacterSet()
static func ignorePatterns(fromString str: String) -> Set<FileItemIgnorePattern> {
if str.stringByTrimmingCharactersInSet(self.whitespaceCharSet).characters.count == 0 {
return Set()
}
let patterns: [FileItemIgnorePattern] = str
.componentsSeparatedByString(",")
.flatMap {
let trimmed = $0.stringByTrimmingCharactersInSet(self.whitespaceCharSet)
if trimmed.characters.count == 0 {
return nil
}
return FileItemIgnorePattern(pattern: trimmed)
}
return Set(patterns)
}
static func ignorePatternString(fromSet set: Set<FileItemIgnorePattern>) -> String {
return set
.map { $0.pattern }
.joinWithSeparator(", ")
}
}