Skip to content

Latest commit

 

History

History
287 lines (215 loc) · 8.63 KB

DEVELOPMENT.md

File metadata and controls

287 lines (215 loc) · 8.63 KB

Development

MIT license

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



Pre-requisites

  1. Have already configured the plugin
  2. Type annotations
  3. Pointers in Lua (i.e. tables)



Setting up environment

  • Remove the plugin from your plugins list

  • Clone the repo

    git clone git@github.com:pandasoli/nekovim.git;\
    cd nekovim

To test changes run:

nvim --cmd 'set rtp+=.' <any file path>



Taken decisions

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.




Structure

  • 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.

    • deps — dependencies/used libraries

    • lib — some generic scripts

    • nekovim — source folder

    • types — type definitions

    • utils — useful scripts




Logging

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 = {}



Generic files

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.luaVIM helpers
  • lua/nekovim/std.lua — functions to deal with Lua data structures



Events

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 Vim
  • FocusGained — When focus the window
  • BufEnter — When select another buffer
  • ModeChanged — When change the mode (normal, visual, replace...)
  • BufWinLeave — Before closing a buffer



Core

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 presence
  • current_buf — id of the current buffer
  • idle_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).


Multiple instances

If the WorkProps received disables multiple instances we just call :connect().
Otherwise we create two events with vim-sockets.

  • update presence — calls self:update(Presence?)
  • make connection — calls self: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).


Events

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.


Data makers

  • :make_buf_props() creates a BufferProps for the current buffer
    if it doesn't yet exist inside buffers_props accessable with the buffer's id

  • :make_presence() returns a Presence based on the presence_makers

  • :make_work_props(WorkPropsMakers) solves WorkPropsMakers and returns returns WorkProps




:update(presence)

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.




:shutdown()

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.







Journey Ended


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).