-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
キーバインドで必須と任意の修飾キーを設定できるようにし、Option + Enterを .enterとして扱うようにする #173
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ちょっとアドホックな気もしますが、とはいえIntelliJが不便な状況になっちゃてるので直るならマージでよさそう 🙆♀️
macSKK/KeyBindingSet.swift
Outdated
if keyBind.0.key == input.key { | ||
switch input.key { | ||
case .character(let c): | ||
if KeyBinding.Key.characters.contains(c) && keyBind.0.modifierFlags == input.modifierFlags { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
KeyBinding.Key.characters.contains(c)
はこれinput.key
のコンストラクト時 👇 にもチェックしています。
macSKK/macSKK/KeyBinding.swift
Lines 107 to 109 in 18db2f0
init(event: NSEvent) { | |
if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) { | |
key = .character(character) |
よって.character
のケースに進入した以上はもうこのチェックは不要ということで
if KeyBinding.Key.characters.contains(c) && keyBind.0.modifierFlags == input.modifierFlags { | |
keyBind.0.modifierFlags == input.modifierFlags { |
☝️ こうしても大丈夫なような 🤔
macSKK/KeyBindingSet.swift
Outdated
return keyBind.1 | ||
} | ||
case .code(let code): | ||
if input.modifierFlags.contains(keyBind.0.modifierFlags) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ほほー、input.key
側が.code
かどうかによってmodifierFlags
を完全一致にするかcontains
にするかどうか的なロジックですか 👀
これは 👇 こういうちゃんとした(?)modifierFlags
の取り扱いをするまでの一旦の凌ぎみたいな感じということかな 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
直感でいけるかな? とおおまかに分けたんですが、さすがに自信がないので見直します。
このPR内でv0.22.xまでのKeyBinding入力前と同じような挙動になるように修正しようかなと思っています。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
「ちゃんとしたmodifierFlagsの取り扱い」をするのもそう大変ではなかったので、大きく舵切ってこのPRでやることにしました。 f9f259d
将来ユーザーがキーバインドをカスタマイズするときには必須modifierFlagsにユーザーが入力したもの、optionalFlagsはデフォルトは空でユーザーがカスタマイズ可能にするつもりです (EnterをOption押しててもありにする、みたいなカスタマイズ)。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
自分もこれ実は裏でやろうとしてたんですが、なかなかoptionalFlags
をどう持つかとかがあまりうまくいかず、いったんOption + Enterだけ局所的にどうにかする方向でいいか 🤔 と思ってましたが、全体的にこのPRでやってよくなっていると思います 👍
Co-authored-by: YOSHIMURA Yuu <yyu@mental.poker>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
些細な指摘もしたけどトータルでよさそう! 👍
case .code: | ||
hasher.combine(modifierFlags.subtracting(.shift).rawValue) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(メモ)
この.shift
を特別扱いするhash
を消すの、個人的にはすごく賛成です 👍
ディクショナリーのキーなどに暗黙的に用いられるであろう関数において.shift
に関する特別処理が記述されているというのは後々なにか問題の種になる可能性があると思ったので、optionalModifierFlags
導入とKeyBindingSet.dict
廃止によりこのhash
が消えることは将来にわたってとてもいい判断になると確信しています。
} else { | ||
return lhs.key == rhs.key && lhs.modifierFlags == rhs.modifierFlags | ||
} | ||
return lhs.key == rhs.key && lhs.modifierFlags == rhs.modifierFlags && lhs.optionalModifierFlags == rhs.optionalModifierFlags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(メモ)
同様にこの==
も.shift
に関する特別処理が消えて相当自明になったと思うのでこの実装を支持します 👍
if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) { | ||
if key != .character(character) { | ||
return false | ||
} | ||
} else if key != .code(event.keyCode) { | ||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
めちゃくちゃ微粒子レベルの指摘にはなりますが、else if
でやっている比較のほうがなんか単純な比較だけなので、先にそっちをやったほうが、そっちでもうreturn false
となったら Key.characters.contains
をやらなくてよくなって超微妙に効率がよかったりますかね?
if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) { | |
if key != .character(character) { | |
return false | |
} | |
} else if key != .code(event.keyCode) { | |
return false | |
} | |
if key != .code(event.keyCode) { | |
return false | |
} else if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) { | |
if key != .character(character) { | |
return false | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
このaccept、最大で登録されているキーバインドの回数だけ呼ばれるのでそれも含めて富豪的な書き方になってますね。
ちゃんとやるならNSEventを引数にするのを止めて、ここでやってるちょっとした前処理を初期化で済ませた別の構造体に入れておくかなあとか思います。
struct CurrentInput {
let key: Key
let modifierFlags: NSEvent.ModifierFlags
init(event: NSEvent) {
if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) {
self.key = .character(character)
}
...
}
}
みたいな。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど、そうですね 👍
もともとはNSEvent
からKeyBinding.Input
をインスタンシーエションしていて、KeyBinding
に用いるInput
というデータ構造と入力のmodifierFlags
やキーコードなどを整理しておくデータ構造は別であったほうがいいと思ってました。
今回のPRの変更では、やや副作用かもしれませんがKeyBinding.Input
がNSEvent
からインスタンシーエションされるパスが消滅しKeyBinding.Input
が真にKeyBinding
用のデータ構造になったと思います。いったんこのPRの段階では今の状態でも十分とは思いますが、将来的にはCurrentInput
のようなデータ構造がKeyBinding.Input
とは別に定義されるのはとてもいいと思いました 👍
} else if key != .code(event.keyCode) { | ||
return false | ||
} | ||
return modifierFlags.isSubset(of: event.modifierFlags) && modifierFlags.union(optionalModifierFlags).isSuperset(of: event.modifierFlags) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど、たしかにisSubset
とisSuperset
でこう表現できるのか。(メモ)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
よさそう。
レビューありがとうございました。 |
#172 で問題となった、Option + Enterがv0.23.0からIMEで拾われるようになってしまったことへの対処として、KeyBinding.Inputに「必須の修飾キーの集合」と「押していてもよい任意の修飾キーの集合」を設定するようにします。
2024-06-15: 既存のキーバインドは、矢印キーはShiftあり、エンターはOptionありとしていますがマージする前にもう少し考えます。