Skip to content
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

Add cursor overlay in beta #65

Merged
merged 1 commit into from
Nov 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/accessibility_buffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,21 @@ function AccessibilityBuffer:getRangeForLineNumber(lineNumber)
return Selection.fromRange(range)
end

function AccessibilityBuffer:isAtLastVisibleCharacter()
local visibleRange = self
:getCurrentElement()
:attributeValue("AXVisibleCharacterRange")

if not visibleRange then return false end

local selection = self:getSelectionRange()
if not selection then return false end

local lastVisibleIndex = visibleRange.length + visibleRange.location

return lastVisibleIndex <= selection.location
end

function AccessibilityBuffer.getCurrentApplication()
return ax.applicationElement(hs.application.frontmostApplication())
end
Expand Down
85 changes: 85 additions & 0 deletions lib/block_cursor.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
local AccessibilityBuffer = dofile(vimModeScriptPath .. "lib/accessibility_buffer.lua")

local BlockCursor = {}

function BlockCursor:new()
local canvas = hs.canvas.new({ x = 0, y = 0, h = 1, w = 1 })
local rectangleElementIndex = 1

canvas:level('overlay')
canvas:insertElement(
{
type = 'rectangle',
action = 'fill',
fillColor = { red = 0, green = 0, blue = 0, alpha = 0.2 },
frame = { x = "0%", y = "0%", h = "100%", w = "100%", },
withShadow = false
},
rectangleElementIndex
)

local cursor = {
canvas = canvas,
}

setmetatable(cursor, self)
self.__index = self

cursor.redrawTimer = hs.timer.new(1 / 60, function()
local result = cursor:_renderFrame()

if not result then
cursor:hide()
end
end)

return cursor
end

function BlockCursor:show()
if self.canvas:isShowing() then return nil end

self.redrawTimer:start()
self.canvas:show()
end

function BlockCursor:hide()
if not self.canvas:isShowing() then return nil end

self.canvas:hide()
self.redrawTimer:stop()
end

-- Renders a single frame. Returns `true` if successful.
function BlockCursor:_renderFrame()
local buffer = AccessibilityBuffer:new()
if not buffer:isValid() then return false end

local currentElement = buffer:getCurrentElement()

-- We don't want to draw the cursor if we're at the end of the textbox (or
-- past the end!)
if buffer:isAtLastVisibleCharacter() then return false end

-- Get the range for the next character after the blinking cursor
local range = buffer:getSelectionRange()
local caretRange = {
location = range.location,
length = 1,
}

-- Get the { h, w, x, y } bounding box for the next character's range so we
-- can draw over it.
local bounds = currentElement:parameterizedAttributeValue(
"AXBoundsForRange",
caretRange
)

-- move the position and resize
self.canvas:topLeft({ x = bounds.x, y = bounds.y })
self.canvas:size({ h = bounds.h, w = bounds.w })

return true
end

return BlockCursor
15 changes: 14 additions & 1 deletion lib/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ function Config:new(options)
alert = {
font = "Courier New"
},
betaFeatures = {},
shouldShowAlertInNormalMode = true,
shouldDimScreenInNormalMode = true
shouldDimScreenInNormalMode = true,
}

setmetatable(config, self)
Expand All @@ -26,4 +27,16 @@ function Config:setOptions(options)
end
end

function Config:isBetaFeatureEnabled(feature)
return not not self.betaFeatures[feature]
end

function Config:enableBetaFeature(feature)
self.betaFeatures[feature] = true
end

function Config:disableBetaFeature(feature)
self.betaFeatures[feature] = false
end

return Config
2 changes: 2 additions & 0 deletions lib/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ local function createStateMachine(vim)
},
callbacks = {
onenterNormal = function()
vim:enableBlockCursor()
vim:disableSequence()
vim:resetCommandState()
vim:setNormalMode()
vim:enterModal('normal')
end,
onenterInsert = function()
vim.visualCaretPosition = nil
vim:disableBlockCursor()
vim:exitAllModals()
vim:setInsertMode()
vim:resetCommandState()
Expand Down
18 changes: 18 additions & 0 deletions lib/vim.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dofile(vimModeScriptPath .. "lib/utils/benchmark.lua")
local AccessibilityBuffer = dofile(vimModeScriptPath .. "lib/accessibility_buffer.lua")
local AccessibilityStrategy = dofile(vimModeScriptPath .. "lib/strategies/accessibility_strategy.lua")
local AppWatcher = dofile(vimModeScriptPath .. "lib/app_watcher.lua")
local BlockCursor = dofile(vimModeScriptPath .. "lib/block_cursor.lua")
local CommandState = dofile(vimModeScriptPath .. "lib/command_state.lua")
local Config = dofile(vimModeScriptPath .. "lib/config.lua")
local KeySequence = dofile(vimModeScriptPath .. "lib/key_sequence.lua")
Expand Down Expand Up @@ -48,6 +49,7 @@ function VimMode:new()

vim:resetCommandState()

vim.blockCursor = BlockCursor:new()
vim.config = Config:new()
vim.enabled = true
vim.mode = 'insert'
Expand Down Expand Up @@ -95,6 +97,10 @@ end

---------------------------

function VimMode:enableBetaFeature(feature)
self.config:enableBetaFeature(feature)
end

function VimMode:shouldShowAlertInNormalMode(showAlert)
self.config.shouldShowAlertInNormalMode = showAlert
return self
Expand Down Expand Up @@ -217,6 +223,18 @@ function VimMode:exit()
self.state:enterInsert()
end

function VimMode:enableBlockCursor()
if not self.config:isBetaFeatureEnabled('block_cursor_overlay') then return end

self.blockCursor:show()
end

function VimMode:disableBlockCursor()
if not self.config:isBetaFeatureEnabled('block_cursor_overlay') then return end

self.blockCursor:hide()
end

function VimMode:setInsertMode()
self.mode = "insert"

Expand Down