diff --git a/src/VimBindings.jl b/src/VimBindings.jl index 75d98ca..1823dc6 100644 --- a/src/VimBindings.jl +++ b/src/VimBindings.jl @@ -62,11 +62,12 @@ mutable struct VimState register::Char mode::VimMode last_edit_index::Int # where the most recent edit started + latest_find::Union{Nothing, CompositeMotionCommand} end -const global STATE = VimState(Dict{Char,String}(), '"', insert_mode, 0) +const global STATE = VimState(Dict{Char,String}(), '"', insert_mode, 0, nothing) const global KEY_STACK = Char[] const global INITIALIZED = Ref(false) diff --git a/src/command.jl b/src/command.jl index f51c131..8504ec6 100644 --- a/src/command.jl +++ b/src/command.jl @@ -16,6 +16,15 @@ struct SimpleMotionCommand <: MotionCommand name :: Char end +""" +Command which repeats a motion, e.g. `;` or `,` repeats a search +""" +struct RepeatMotionCommand <: MotionCommand + r1 :: Int + name :: Char + latest_find :: CompositeMotionCommand +end + SimpleMotionCommand(::Nothing, name :: Char) = SimpleMotionCommand(1, name) function Base.:(==)(cmd1 :: Command, cmd2 :: Command) diff --git a/src/execute.jl b/src/execute.jl index 2d2fed4..43e7158 100644 --- a/src/execute.jl +++ b/src/execute.jl @@ -41,8 +41,17 @@ function execute(buf, command::MotionCommand)::Union{VimMode,ReplAction,Nothing} motion(buf) end end + if command isa CompositeMotionCommand + @debug "Saving latest search command to state" command + STATE.latest_find = command + end return repl_action end + +function execute(buf, command::RepeatMotionCommand)::Union{VimMode,Nothing} + +end + function execute(buf, command::LineOperatorCommand)::Union{VimMode,Nothing} local op_fn = nothing diff --git a/src/motion.jl b/src/motion.jl index 8426aaa..8bd2467 100644 --- a/src/motion.jl +++ b/src/motion.jl @@ -8,7 +8,7 @@ using ..Util using ..Commands export Motion, MotionType, simple_motions, complex_motions, partial_complex_motions, insert_motions, gen_motion, - is_stationary, down, up, word_next, word_big_next, word_end, word_back, + is_stationary, distance, down, up, word_next, word_big_next, word_end, word_back, word_big_back, word_big_end, line_end, line_begin, line_zero, find_c, find_c_back, get_safe_name, all_keys, special_keys, exclusive, inclusive, linewise, endd, left, right @@ -79,9 +79,11 @@ endd(motion::Motion)::Int = motion.stop end -is_stationary(motion::Motion)::Bool = motion.start == motion.stop +is_stationary(motion::Motion)::Bool = max(motion) == min(motion) -Base.length(motion::Motion) = max(motion) - min(motion) +distance(motion::Motion) = max(motion) - min(motion) + +sign(motion::Motion) = Base.sign(motion.start - endd(motion)) function Base.:+(motion1::Motion, motion2::Motion) low = Base.min( @@ -375,6 +377,14 @@ function find_c_back(buf::IO, query_c::Int) return find_c_back(buf, '0' + query_c) end +function repeat_find(buf::IO) + latest = STATE.latest_find + +end + +function repeat_find_reverse(buf::IO) +end + const insert_motions = Dict{Char,Any}( 'i' => (buf) -> Motion(buf), 'I' => (buf) -> line_begin(buf), @@ -408,6 +418,8 @@ const simple_motions = Dict{Char,Any}( '^' => line_begin, # exclusive) '$' => line_end, # inclusive) '0' => line_zero, # TODO how to parse this? it's a digit, not an alphabetical character. + ';' => repeat_find, + ',' => repeat_find_reverse, '{' => nothing, '}' => nothing, '(' => nothing,