Skip to content

Commit

Permalink
Fixed a control+tab issue
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredpar committed Jan 6, 2011
1 parent e300ce4 commit 430d528
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 83 deletions.
20 changes: 11 additions & 9 deletions VimCore/CoreInterfaces.fs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,16 @@ type KeyInputSet =
SeqUtil.contentsEqual (left |> Seq.ofList) (right |> Seq.ofList |> Seq.take left.Length)
else false

member x.CompareTo (other : KeyInputSet) =
let rec inner (left:KeyInput list) (right:KeyInput list) =
if left.IsEmpty && right.IsEmpty then 0
elif left.IsEmpty then -1
elif right.IsEmpty then 1
elif left.Head < right.Head then -1
elif left.Head > right.Head then 1
else inner (List.tail left) (List.tail right)
inner x.KeyInputs other.KeyInputs

override x.GetHashCode() =
match x with
| Empty -> 1
Expand Down Expand Up @@ -357,15 +367,7 @@ type KeyInputSet =
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? KeyInputSet as y ->
let rec inner (left:KeyInput list) (right:KeyInput list) =
if left.IsEmpty && right.IsEmpty then 0
elif left.IsEmpty then -1
elif right.IsEmpty then 1
elif left.Head < right.Head then -1
elif left.Head > right.Head then 1
else inner (List.tail left) (List.tail right)
inner x.KeyInputs y.KeyInputs
| :? KeyInputSet as y -> x.CompareTo y
| _ -> failwith "Cannot compare values of different types"

module KeyInputSetUtil =
Expand Down
110 changes: 83 additions & 27 deletions VimCore/KeyInput.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ type KeyInput
_modKey:KeyModifiers,
_literal:char option ) =

static let _alternateEnterKeyInput = KeyInput(VimKey.LowerM, KeyModifiers.Control, Some 'm')
static let _alternateEscapeKeyInput = KeyInput(VimKey.OpenBracket, KeyModifiers.Control, Some '[')
static let _alternateLineFeedKeyInput = KeyInput(VimKey.LowerJ, KeyModifiers.Control, Some 'j')
static let _alternateTabKeyInput = KeyInput(VimKey.LowerI, KeyModifiers.Control, Some 'i')
static let _alternateKeyInputList =
[
_alternateEnterKeyInput
_alternateEscapeKeyInput
_alternateTabKeyInput
_alternateLineFeedKeyInput
]

member x.Char = _literal |> OptionUtil.getOrDefault CharUtil.MinValue
member x.RawChar = _literal
member x.IsCharOnly = Option.isSome _literal && _modKey = KeyModifiers.None
Expand Down Expand Up @@ -43,40 +55,68 @@ type KeyInput

member x.IsControlAndLetter = x.KeyModifiers = KeyModifiers.Control && CharUtil.IsLetter x.Char

member x.GetAlternate () =
if x.KeyModifiers = KeyModifiers.None then
match x.Key with
| VimKey.Enter -> Some _alternateEnterKeyInput
| VimKey.Escape -> Some _alternateEscapeKeyInput
| VimKey.LineFeed -> Some _alternateLineFeedKeyInput
| VimKey.Tab -> Some _alternateTabKeyInput
| _ -> None
else
None

/// In general Vim keys compare ordinally. The one exception is when the control
/// modifier is applied to a letter key. In that case the keys compare in a case insensitive
/// fashion
member x.CompareTo (other:KeyInput) =
if x.IsControlAndLetter then
if other.IsControlAndLetter then
compare (CharUtil.ToLower x.Char) (CharUtil.ToLower other.Char)
member x.CompareTo (right : KeyInput) =

let maybeGetAlternate (x : KeyInput) =
match x.GetAlternate() with
| Some(alternate) -> alternate
| None -> x
let left = maybeGetAlternate x
let right = maybeGetAlternate right

if left.IsControlAndLetter then
if right.IsControlAndLetter then
compare (CharUtil.ToLower left.Char) (CharUtil.ToLower right.Char)
else
-1
elif other.IsControlAndLetter then
elif right.IsControlAndLetter then
1
else
let comp = compare x.KeyModifiers other.KeyModifiers
let comp = compare left.KeyModifiers right.KeyModifiers
if comp <> 0 then comp
else
let comp = compare x.Char other.Char
let comp = compare left.Char right.Char
if comp <> 0 then comp
else compare x.Key other.Key
else compare left.Key right.Key

override x.GetHashCode() =
let c = if x.IsControlAndLetter then CharUtil.ToLower x.Char else x.Char
int32 c
match x.GetAlternate() with
| Some(alternate) ->
alternate.GetHashCode()
| None ->
let c = if x.IsControlAndLetter then CharUtil.ToLower x.Char else x.Char
int32 c

override x.Equals(obj) =
match obj with
| :? KeyInput as other ->
0 = x.CompareTo other
| :? KeyInput as other -> 0 = x.CompareTo other
| _ -> false

override x.ToString() = System.String.Format("{0}:{1}:{2}", x.Char, x.Key, x.KeyModifiers);

static member DefaultValue = KeyInput(VimKey.NotWellKnown, KeyModifiers.None, None)
static member op_Equality(this,other) = System.Collections.Generic.EqualityComparer<KeyInput>.Default.Equals(this,other)
static member op_Inequality(this,other) = not (System.Collections.Generic.EqualityComparer<KeyInput>.Default.Equals(this,other))

static member AlternateEnterKey = _alternateEnterKeyInput
static member AlternateEscapeKey = _alternateEscapeKeyInput
static member AlternateTabKey = _alternateTabKeyInput
static member AlternateLineFeedKey = _alternateLineFeedKeyInput
static member AlternateKeyInputList = _alternateKeyInputList

interface System.IComparable with
member x.CompareTo yObj =
Expand All @@ -96,6 +136,8 @@ module KeyInputUtil =
let VimKeyRawData = [
(VimKey.Back, Some '\b')
(VimKey.FormFeed, None)
(VimKey.Enter, None)
(VimKey.Escape, None)
(VimKey.Left, None)
(VimKey.Up, None)
(VimKey.Right, None)
Expand Down Expand Up @@ -229,28 +271,16 @@ module KeyInputUtil =
(VimKey.Colon, Some ':')
(VimKey.Tilde, Some '~')
(VimKey.Space, Some ' ')
(VimKey.Dollar, Some '$') ]
(VimKey.Dollar, Some '$')
(VimKey.Tab, None)
(VimKey.LineFeed, None) ]

let EscapeKey = KeyInput(VimKey.OpenBracket, KeyModifiers.Control, Some '[')
let TabKey = KeyInput(VimKey.LowerI, KeyModifiers.Control, Some 'i')
let LineFeedKey = KeyInput(VimKey.LowerJ, KeyModifiers.Control, Some 'j')
let EnterKey = KeyInput(VimKey.LowerM, KeyModifiers.Control, Some 'm')

let SpecialKeyInputList =
[
EscapeKey
TabKey
LineFeedKey
EnterKey
]

let VimKeyInputList =
VimKeyRawData
|> Seq.map (fun (key,charOpt) -> KeyInput(key, KeyModifiers.None, charOpt ))
|> List.ofSeq

let AllKeyInputList = List.append VimKeyInputList SpecialKeyInputList

let VimKeyCharList =
VimKeyInputList
|> Seq.map (fun ki -> ki.RawChar)
Expand Down Expand Up @@ -307,4 +337,30 @@ module KeyInputUtil =
let ki = ch |> CharToKeyInput
ChangeKeyModifiers ki (ki.KeyModifiers ||| KeyModifiers.Shift)

let AlternateEnterKey = KeyInput.AlternateEnterKey
let AlternateEscapeKey = KeyInput.AlternateEscapeKey
let AlternateLineFeedKey = KeyInput.AlternateLineFeedKey
let AlternateTabKey = KeyInput.AlternateTabKey
let EscapeKey = VimKeyToKeyInput VimKey.Escape
let TabKey = VimKeyToKeyInput VimKey.Tab
let LineFeedKey = VimKeyToKeyInput VimKey.LineFeed
let EnterKey = VimKeyToKeyInput VimKey.Enter

let AlternateKeyInputList = KeyInput.AlternateKeyInputList

let AlternateKeyInputPairList =
[
(EscapeKey, AlternateEscapeKey)
(TabKey, AlternateTabKey)
(LineFeedKey, AlternateLineFeedKey)
(EnterKey, AlternateEnterKey)
]

let AllKeyInputList = List.append VimKeyInputList AlternateKeyInputList

let GetAlternate (ki : KeyInput) = ki.GetAlternate()

let GetAlternateTarget (ki : KeyInput) =
AlternateKeyInputPairList
|> List.tryPick (fun (target, alternate) -> if alternate = ki then Some target else None)

41 changes: 30 additions & 11 deletions VimCore/KeyInput.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,32 @@ type KeyInput =

module KeyInputUtil =

/// The Escape / <Esc> / <C-[> Key
val EscapeKey : KeyInput
/// The Alternate Enter Key : <C-m>
val AlternateEnterKey : KeyInput

/// The Tab / <Tab> / <C-I> Key
val TabKey : KeyInput
/// The Alternate Escape Key: <C-[>
val AlternateEscapeKey : KeyInput

/// The alternate LineFeed key: <C-j>
val AlternateLineFeedKey : KeyInput

/// The Alternate Tab Key <C-i>
val AlternateTabKey : KeyInput

/// The LineFeed / <NL> / <C-J> key
/// The Enter Key: VimKey.Enter
val EnterKey : KeyInput

/// The Escape Key: VimKey.Escape
val EscapeKey : KeyInput

/// The LineFeed key: VimKey.LineFeed
val LineFeedKey : KeyInput

/// The Enter / <CR> / <Enter> / <C-M> / <Return>
val EnterKey : KeyInput
/// The Tab Key: VimKey.Tab
val TabKey : KeyInput

/// The set of special keys which have multiple real aliases back at a single
/// Key
val SpecialKeyInputList : KeyInput list
/// The set of special keys which are alias's back into core VimKey values
val AlternateKeyInputList : KeyInput list

/// The KeyInput for every VimKey in the system (except Unknown)
val VimKeyInputList : KeyInput list
Expand All @@ -66,7 +77,7 @@ module KeyInputUtil =
val VimKeyCharList : char list

/// The core set of KeyInput values that Vim is concerned with. This includes all of the
/// VimKey entries and Special KeyInput values
/// VimKey entries and Alternate KeyInput values
val AllKeyInputList : KeyInput list

/// Try and convert the given char to a KeyInput value
Expand Down Expand Up @@ -94,3 +105,11 @@ module KeyInputUtil =
/// but it's a scenario that Vim supports (or doesn't support depending on how you
val ChangeKeyModifiers : KeyInput -> KeyModifiers -> KeyInput

/// Given a KeyInput value which is an Alternate KeyInput return the value it as an
/// alternate for
val GetAlternate : KeyInput -> KeyInput option

/// Given an alternate KeyInput get the value it targets
val GetAlternateTarget : KeyInput -> KeyInput option


3 changes: 2 additions & 1 deletion VimCore/Modes_Command_DefaultOperations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ type internal DefaultOperations ( _data : OperationsData ) =
|> Seq.append ( "mark line col file/text" |> Seq.singleton)
|> _statusUtil.OnStatusLong


member x.PrintModifiedSettings () =
_settings.AllSettings |> Seq.filter (fun s -> not s.IsValueDefault) |> Seq.map FormatSetting |> _statusUtil.OnStatusLong

Expand Down Expand Up @@ -169,6 +168,8 @@ type internal DefaultOperations ( _data : OperationsData ) =

let inner (ki:KeyInput) =

let ki = ki |> KeyInputUtil.GetAlternateTarget |> OptionUtil.getOrDefault ki

// Build up the prefix for the specified modifiers
let rec getPrefix modifiers =
if Util.IsFlagSet modifiers KeyModifiers.Alt then
Expand Down
3 changes: 1 addition & 2 deletions VimCore/Modes_Normal_NormalMode.fs
Original file line number Diff line number Diff line change
Expand Up @@ -762,9 +762,8 @@ type internal NormalMode
elif _displayWindowBroker.IsCompletionActive then false
elif _displayWindowBroker.IsSignatureHelpActive then false
elif _runner.IsWaitingForMoreInput then true
elif CharUtil.IsLetterOrDigit(ki.Char) then true
elif doesCommandStartWith ki then true
elif Set.contains ki.Char _coreCharSet then true
elif ki.IsCharOnly && Set.contains ki.Char _coreCharSet then true
else false

member this.Process ki = this.ProcessCore ki
Expand Down
2 changes: 1 addition & 1 deletion VimCore/MotionCapture.fs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ type internal MotionCapture

let MotionCommands = AllMotionsCore

let MotionCommandsMap = AllMotionsCore |> Seq.map (fun command -> (command.KeyInputSet,command)) |> Map.ofSeq
let MotionCommandsMap = AllMotionsCore |> Seq.map (fun command -> (command.KeyInputSet, command)) |> Map.ofSeq

/// Run a normal motion function
member x.RunMotionFunction command func arg returnFunc =
Expand Down
5 changes: 4 additions & 1 deletion VimCore/VimKey.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ type VimKey =
| NotWellKnown = 0
| Back = 1
| FormFeed = 2
// Gap
| Enter = 3
| Escape = 4
| Left = 5
| Up = 6
| Right = 7
Expand Down Expand Up @@ -142,6 +143,8 @@ type VimKey =
| Tilde = 136 // ~
| Space = 137 //
| Dollar = 138 // $
| Tab = 139
| LineFeed = 140

module VimKeyUtil =

Expand Down
34 changes: 34 additions & 0 deletions VimCoreTest/KeyInputSetTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.FSharp.Collections;
using NUnit.Framework;
using Vim;
using Vim.Extensions;

namespace VimCore.UnitTest
{
[TestFixture]
public sealed class KeyInputSetTest
{
[Test]
public void Compare_AlternateKeyInputShouldBeEqual()
{
var left = KeyInputSet.NewOneKeyInput(KeyInputUtil.EnterKey);
var right = KeyInputSet.NewOneKeyInput(KeyInputUtil.AlternateEnterKey);
Assert.IsTrue(0 == left.CompareTo(right));
Assert.IsTrue(0 == right.CompareTo(left));
}

[Test]
public void Compare_AlternateKeyInputShouldBeEqualInMap()
{
var left = KeyInputSet.NewOneKeyInput(KeyInputUtil.EnterKey);
var right = KeyInputSet.NewOneKeyInput(KeyInputUtil.AlternateEnterKey);
var map = MapModule.Empty<KeyInputSet, bool>().Add(left, true);
var result = MapModule.TryFind(right, map);
Assert.IsTrue(result.IsSome());

map = MapModule.Empty<KeyInputSet, bool>().Add(right, true);
result = MapModule.TryFind(left, map);
Assert.IsTrue(result.IsSome());
}
}
}
Loading

0 comments on commit 430d528

Please sign in to comment.