Please read with the code of the last commit of this file.
Pre-requisites | Setting up environment | Taken decisions
Structure | Logs | Generic files | Events | Core
- Have already configured the plugin
- Type annotations
- Pointers in Lua (i.e. tables)
-
Remove the plugin from your plugins list
-
Clone the repo
git clone [email protected]:pandasoli/nekovim.git;\ cd nekovim
To test changes run:
nvim --cmd 'set rtp+=.' <any file path>
To communicate with Discord I used the library discord-ipc .
It uses a sockets connection (IPC connection - like vim-sockets).
As Discord only accept the instance itself to modify its presence,
I used vim-sockets
to communicate with other instances of VIM.
I maintain one connected instance; others emit PresenceProps
when need to update.
- lua
-
default_makers
- assets
- images — all default available icons
This is not used,
I just leave it here in case you want to download it.
- images — all default available icons
- assets
-
deps — dependencies/used libraries
-
lib — some generic scripts
-
nekovim — source folder
-
types — type definitions
-
utils — useful scripts
-
I've modified all deps to log with this
The file lua/lib/log.lua
contains:
---@class Logger
---@field logs string[]
--
---@field debug fun(self: Logger, from: string, ...: any)
---@field info fun(self: Logger, from: string, ...: any)
---@field warn fun(self: Logger, from: string, ...: any)
---@field error fun(self: Logger, from: string, ...: any)
--
---@field print fun(self: Logger)
---@field write_to_file fun(self: Logger)
local Logger = {}
First, let's see some files you find in any Lua program,
then you will get less lost.
If you need, open them and take a look.
- Everything inside
lua/lib
- Everything inside
lua/utils
lua/utils/vim.lua
— VIM helpers
lua/nekovim/std.lua
— functions to deal with Lua data structures
lua/nekovim/event_handlers.lua
handles all the events.
---@param nekovim NekoVim
---@param log_to_file? boolean # Write logs to file every time an event is trigged
function EventHandlers:setup(nekovim, log_to_file) end
VimLeavePre
— Before exiting VimFocusGained
— When focus the windowBufEnter
— When select another bufferModeChanged
— When change the mode (normal, visual, replace...)BufWinLeave
— Before closing a buffer
require 'deps.vim-sockets'
---@class NekoVim
---@field presence_makers PresenceMakers
---@field presence_props PresenceProps
---@field buffers_props BuffersProps
---@field work_props WorkProps
---@field vim_sockets? VimSockets
---@field current_buf number
---@field idle_timer? number
local NekoVim = {}
presence_props
— store some information about the current status of the presencecurrent_buf
— id of the current bufferidle_timer
— id of VIM's timer used for idling
Everything starts from .setup(PresenceMakers, WorkPropsMakers)
.
It initializes every dependency and property.
It combines the default and received PresenceMakers
,
calls solve the WorkPropsMakers
to NekoVim.work_props
,
sets up multiple instances and the events, if enabled in the WorkProps
,
and creates a user command to show logs (:PrintNekoLogs
).
If the WorkProps
received disables multiple instances we just call :connect()
.
Otherwise we create two events with vim-sockets.
update presence
— callsself:update(Presence?)
make connection
— callsself:connect()
And if there are no other instances running we call :connect()
.
About self.vim_sockets
vim-sockets has functions inside itself used to receive the signals,
so it needs a way to access itself in other instances.
For that, we added it to self.vim_sockets
,
and then passed the path (package.loaded.nekovim.vim_sockets
).
If the WorkProps
received enables events we set up the EventHandlers
and
call :restart_idle_timer()
. Otherwise we just call :update(Presence?)
.
:restart_idle_timer()
sets presence_props.idling
to false,
then creates a timer that waits some seconds and then sets presence_props.idling
to true.
-
:make_buf_props()
creates aBufferProps
for the current buffer
if it doesn't yet exist insidebuffers_props
accessable with the buffer's id -
:make_presence()
returns aPresence
based on thepresence_makers
-
:make_work_props(WorkPropsMakers)
solvesWorkPropsMakers
and returns returnsWorkProps
if presence:
if discord.connected:
# update
else:
if presence := self.make_presence():
if discord.connected:
# update
else:
self.vim_sockets.emmit('update presence', presence)
Illustration
Text explanation
If the current instance is connected we just update.
If not we emit the event update presence
with the generated PresenceProps
to all other instances, just as #taken-decisions says.
But if presence
is valid, the event update presence
was received.
If this instance is connected, we update the presence.
If there is any other instance, we emit the events make connection
and update presence
without pass any value, it will make the instance think :update
was called by itself and update with its own PresenceProps
.
You probably started reading this doc thinking about helping me in this project .
I cannot give you money or anything for your time, but if you still want to help, I would be very happy!
I probably have some tasks to be done yet.
But that's it. This is just one more non-profit project made for devs.
I don't have a server on Discord focused on this project,
but you can talk to me there if you wish so (see my profile).