kiyoon / jupynium.nvim

Selenium-automated Jupyter Notebook that is synchronised with NeoVim in real-time.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Yanking and Pasting into *.ju.py file creates duplicated lines

torifaye opened this issue · comments

Describe the bug
When pasting text that's in your clipboard/register(s)/etc, the notebook open in the browser seems to post a number of duplicate lines which then causes a de-sync between the file open in neovim and the text in the notebook. For example, I yanked the text "pd.read_sql(sql, CONNECTION_STRING)" from another neovim buffer I had open (a normal .py file), and then pasted it in my .ju.py file, and then the notebook open in the firefox window shows a number of duplicates, or to be exact:

pd.read_sql(sql, CONNECTION_STRING)
pd.read_sql(sql, CONNECTION_STRING)
pd.read_sql(sql, CONNECTION_STRING)
pd.read_sql(sql, CONNECTION_STRING)
pd.read_sql(sql, CONNECTION_STRING)

This issue also pops up when you have something like autopairs that completes closing quotes (e.g.
typing """ in python and it automatically generates the closing """. It seems to always result in 4 additional copies, as far as I can tell.

To Reproduce
Steps to reproduce the behavior:

  1. Start up jupynium as described in readme
  2. Have another buffer/tab/etc open containing other code
  3. Yank some text/code
  4. Paste it in your .ju.py file
  5. Results in duplicate lines in notebook

Expected behavior
Expected behavior is to have pasted text in neovim buffer to result in same exact text in notebook

Output when using jupynium command
If you launch Jupynium server using the command line program, it gives you more helpful logs.

N/A (using neovim plugin rather than command line tool)

Output of jupynium --version

N/A (using neovim plugin rather than command line tool)

Output of nvim --version

NVIM v0.9.1
Build type: Release
LuaJIT 2.1.0-beta3

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/local/share/nvim"

Run :checkhealth for more info

Additional context
N/A

FWIW I'm also seeing the same issue.

I never had this problem yet but I'll need to confirm this.

I think this should be the neovim problem, because I'm updating using their buffer update event APIs. Maybe neovim is giving updates in a wrong way..

Indeed, there seems to be multiple events generated from neovim:

jupynium.events_control:  197 - INFO - Event from nvim: ['notification', 'on_lines', [1, ['print("hello, world")'], 7, 7, 8]]
jupynium.events_control:  197 - INFO - Event from nvim: ['notification', 'on_lines', [1, ['print("hello, world")'], 7, 7, 8]]
jupynium.buffer:  443 - INFO - Converting to code cells: [2]
jupynium.events_control:  197 - INFO - Event from nvim: ['notification', 'on_lines', [1, ['print("hello, world")'], 7, 7, 8]]
jupynium.buffer:  443 - INFO - Converting to code cells: [2]
jupynium.events_control:  197 - INFO - Event from nvim: ['notification', 'CursorMoved', [1, 7, 7]]
jupynium.buffer:  443 - INFO - Converting to code cells: [2]

The above log was generated by yanking and pasting the line print("hello, world") once.

Hmm, after updating my neovim plugins (with lazy) I no longer see this issue. Will test a bit more tomorrow and report back if it resurfaces!

Nevermind, the issue is still there, but I made a discovery:

The first time the file is opened with JupyniumStartSync, the issue is gone.
However, after closing the notebook and re-opening by calling JupyniumStartSync, pasting produces two copies of the line (and two events).
If I close the notebook again, and re-open, pasting produces three copies of the line (and three events).
My guess is that there is some event handler that is not cleaned up properly after a notebook is closed.

The issue happens regardless of how the notebook is closed, e.g., by closing the browser tab or calling JupyniumStopSync.

@joh Okay, thank you. Now that's more clear. I think that it's not closing the event updates and forcing to receive another events when you sync again.

In this case it's not the neovim bug. If this is the case, however, you should have two copies for all letters you type not only the copy pasting, though.

Right, after some digging I figured out the problem, which is indeed in the lua code.

Jupynium_start_sync may, in certain cases, attach multiple on_lines event handlers.

The sequence of events which may cause this is as follows:

  1. JupyniumStartSync: marks buffer as synced (Jupynium_syncing_bufs) and attaches on_lines event handler number 1
  2. JupyniumStopSync: marks buffer as no longer synced
  3. At this point the event handler is still attached, but will ignore events since the buffer is no longer marked as synced
  4. JupyniumStartSync: marks buffer as synced (Jupynium_syncing_bufs) and attaches a new on_lines event handler number 2
  5. Now when either of the on_lines event handlers are called, they will see the buffer is marked as synced again, and emit one RPC event each. Repeating steps 1-2 will attached yet another sync handler.

The neovim API doesn't provide any nvim_buf_detach function. Instead the event handler is expected to return true to detach. So we must keep track of which buffers the on_event handler has been attached. The linked PR does exactly that, and avoids attaching any extra event handlers in case there is one already attached for the buffer. In addition, the on_event handler returns true to detach in case it is called while the buffer is not marked as synced.