mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-24 11:37:32 +03:00
Merge pull request #830 from Shirk/remote_options_and_guifont
Implement support for 'set guifont' via optionSet. (fixes #779)
This commit is contained in:
commit
a42a6d87cb
@ -69,6 +69,37 @@ enum FontUtils {
|
||||
fontCache.set(ctFont, forKey: sizedFontTrait)
|
||||
return ctFont
|
||||
}
|
||||
|
||||
static func font(fromVimFontSpec fontSpec: String) -> NSFont? {
|
||||
let fontParams = fontSpec.components(separatedBy: ":")
|
||||
|
||||
guard fontParams.count == 2 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let fontName = fontParams[0].components(separatedBy: "_").joined(separator: " ")
|
||||
var fontSize = NvimView.defaultFont.pointSize // use a sane fallback
|
||||
|
||||
if fontParams[1].hasPrefix("h"), fontParams[1].count >= 2 {
|
||||
let sizeSpec = fontParams[1].dropFirst()
|
||||
if let parsed = Float(sizeSpec)?.rounded() {
|
||||
fontSize = CGFloat(parsed)
|
||||
|
||||
if fontSize < NvimView.minFontSize || fontSize > NvimView.maxFontSize {
|
||||
fontSize = NvimView.defaultFont.pointSize
|
||||
}
|
||||
}
|
||||
}
|
||||
return NSFont(name: fontName, size: CGFloat(fontSize))
|
||||
}
|
||||
|
||||
static func vimFontSpec(forFont font: NSFont) -> String {
|
||||
if let escapedName = font.displayName?.components(separatedBy: " ").joined(separator: "_") {
|
||||
return "\(escapedName):h\(Int(font.pointSize))"
|
||||
}
|
||||
// fontName always returns a valid result and works for font(name:, size:) as well
|
||||
return "\(font.fontName):h\(Int(font.pointSize))"
|
||||
}
|
||||
}
|
||||
|
||||
private let fontCache = FifoCache<SizedFontTrait, NSFont>(count: 100, queueQos: .userInteractive)
|
||||
|
106
NvimView/Sources/NvimView/NvimView+RemoteOptions.swift
Normal file
106
NvimView/Sources/NvimView/NvimView+RemoteOptions.swift
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Renee Koecher - @shirk
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import MessagePack
|
||||
import RxSwift
|
||||
|
||||
extension NvimView {
|
||||
enum RemoteOption {
|
||||
// list of currently handled remote options
|
||||
case guifont(fontSpec: String)
|
||||
case guifontWide(fontSpec: String)
|
||||
|
||||
static func fromValuePair(_ option: (key: MessagePackValue, value: MessagePackValue))
|
||||
-> RemoteOption?
|
||||
{
|
||||
guard let key = option.key.stringValue,
|
||||
let val = option.value.stringValue else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch key {
|
||||
case "guifont": return RemoteOption.guifont(fontSpec: val)
|
||||
case "guifontwide": return RemoteOption.guifontWide(fontSpec: val)
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
// convenience methods
|
||||
static func fromFont(_ font: NSFont, forWideFont isWide: Bool = false) -> RemoteOption {
|
||||
let fontSpec = FontUtils.vimFontSpec(forFont: font)
|
||||
|
||||
if isWide {
|
||||
return RemoteOption.guifontWide(fontSpec: fontSpec)
|
||||
}
|
||||
return RemoteOption.guifont(fontSpec: fontSpec)
|
||||
}
|
||||
}
|
||||
|
||||
final func handleRemoteOptions(_ options: [MessagePackValue: MessagePackValue]) {
|
||||
for kvPair in options {
|
||||
guard let option = RemoteOption.fromValuePair(kvPair) else {
|
||||
self.bridgeLogger.debug("Could not handle RemoteOption \(kvPair)")
|
||||
continue
|
||||
}
|
||||
|
||||
switch option {
|
||||
// FIXME: currently this treats gft and gfw the as the same
|
||||
case let .guifont(fontSpec): self.handleGuifontSet(fontSpec)
|
||||
case let .guifontWide(fontSpec): self.handleGuifontSet(fontSpec, forWideFont: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final func signalRemoteOptionChange(_ option: RemoteOption) {
|
||||
let command: Completable?
|
||||
|
||||
switch option {
|
||||
case let .guifont(fontSpec):
|
||||
command = self.api.setOption(name: "guifont", value: .string(fontSpec))
|
||||
|
||||
case let .guifontWide(fontSpec):
|
||||
command = self.api.setOption(name: "guifontwide", value: .string(fontSpec))
|
||||
}
|
||||
|
||||
command?.subscribe().disposed(by: self.disposeBag)
|
||||
}
|
||||
|
||||
public final func signalError(code: Int, message: String) {
|
||||
self.api.errWriteln(str: "E\(code): \(message)")
|
||||
.subscribe()
|
||||
.disposed(by: self.disposeBag)
|
||||
}
|
||||
|
||||
private func handleGuifontSet(_ fontSpec: String, forWideFont wideFlag: Bool = false) {
|
||||
if fontSpec.isEmpty {
|
||||
// this happens on connect - signal the current value
|
||||
self.signalRemoteOptionChange(RemoteOption.fromFont(self.font, forWideFont: wideFlag))
|
||||
return
|
||||
}
|
||||
|
||||
// stop if we would set the same font again
|
||||
let currentSpec = FontUtils.vimFontSpec(forFont: font)
|
||||
if currentSpec == fontSpec.components(separatedBy: " ").joined(separator: "_") {
|
||||
return
|
||||
}
|
||||
|
||||
guard let newFont = FontUtils.font(fromVimFontSpec: fontSpec) else {
|
||||
self.bridgeLogger.debug("Invalid specification for guifont '\(fontSpec)'")
|
||||
|
||||
self.signalError(code: 596, message: "Invalid font(s): gufont=\(fontSpec)")
|
||||
self.signalRemoteOptionChange(RemoteOption.fromFont(self.font, forWideFont: wideFlag))
|
||||
return
|
||||
}
|
||||
|
||||
gui.async {
|
||||
self.font = newFont
|
||||
self.markForRenderWholeView()
|
||||
self.eventsSubject.onNext(.guifontChanged(newFont))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let gui = DispatchQueue.main
|
@ -61,6 +61,7 @@ public extension NvimView {
|
||||
case bufferWritten(NvimView.Buffer)
|
||||
|
||||
case colorschemeChanged(NvimView.Theme)
|
||||
case guifontChanged(NSFont)
|
||||
|
||||
case ipcBecameInvalid(String)
|
||||
|
||||
|
@ -14,7 +14,14 @@ extension NvimView {
|
||||
self.eventsSubject.onNext(.initVimError)
|
||||
}
|
||||
|
||||
final func optionSet(_: MessagePackValue) {}
|
||||
final func optionSet(_ value: MessagePackValue) {
|
||||
guard let options = value.dictionaryValue else {
|
||||
self.bridgeLogger.error("Could not convert \(value)")
|
||||
return
|
||||
}
|
||||
|
||||
handleRemoteOptions(options);
|
||||
}
|
||||
|
||||
final func resize(_ value: MessagePackValue) {
|
||||
guard let array = MessagePackUtils.array(
|
||||
|
@ -95,6 +95,8 @@ public class NvimView: NSView,
|
||||
|
||||
self._font = newValue
|
||||
self.updateFontMetaData(newValue)
|
||||
|
||||
signalRemoteOptionChange(RemoteOption.fromFont(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,10 @@ extension MainWindow {
|
||||
.disposed(by: self.disposeBag)
|
||||
}
|
||||
|
||||
func guifontChanged(to font: NSFont) {
|
||||
self.emit(self.uuidAction(for: .setFont(font)))
|
||||
}
|
||||
|
||||
func ipcBecameInvalid(reason: String) {
|
||||
let alert = NSAlert()
|
||||
alert.addButton(withTitle: "Close")
|
||||
|
@ -296,6 +296,8 @@ class MainWindow: NSObject,
|
||||
|
||||
case let .colorschemeChanged(theme): self?.colorschemeChanged(to: theme)
|
||||
|
||||
case let .guifontChanged(font): self?.guifontChanged(to: font)
|
||||
|
||||
case let .ipcBecameInvalid(reason):
|
||||
self?.ipcBecameInvalid(reason: reason)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user