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

Snippets in neatvi #4

Closed
Vouivre opened this issue Dec 11, 2020 · 11 comments
Closed

Snippets in neatvi #4

Vouivre opened this issue Dec 11, 2020 · 11 comments

Comments

@Vouivre
Copy link
Collaborator

Vouivre commented Dec 11, 2020

I find snippets to be very convenient and I would like to have the possibility to define snippets in neatvi. I know, it's rather a feature than a customization.

At the moment I use snippets in vim but without using plugins. So I think it would be possible to have snippets in neatvi. But I need the map feature from vi. I have the following in my vimrc for example:

inoremap ,dmath \begin{displaymath}<Enter>\end{displaymath}<Esc>O

I bind ,dmath to

\begin{displaymath}

\end{displaymath}

After the <Esc> key at the end, I use the command O to open a line above \end{displaymath} so my cursor is at the right place to write Latex code.

It's even possible to define some placeholders, for example:

inoremap ,fr \frac{}{<++>}<++><Esc>Fcla

In this case I want to insert \frac{}{}. After writing ,fr in insert mode, \frac{}{<++>}<++> is inserted and the cursor is in the first curly brace. Then I have to define a shortcut to jump to the next <++>. Perhaps it's not so powerful with some other snippets plugins, but it's enough for me and without the need to install a lot of dependencies.

To use it, I rely on map! which is availabe in traditionnal vi. I did some tests, but it seems that the commands map and map! don't exist. Another problem, I defined the snippets in the vimrc and if I understand right, there is no configuration file, only the config.h. For me it would be no problem to write my snippet directly in the config.h.

For more information and to see some animated examples: https://www.tomchaplin.xyz/blog/2019_02_10/Vim-for-LaTeX/ (go directly to: "placeholders").

Would be something like this possible ? Perhaps it's not even necessary to have the map feature, but the possibility to write some code in the config.h.

@kyx0r
Copy link
Owner

kyx0r commented Dec 11, 2020

This won't be implemented in my fork because its too specific for LATEX, which I don't use. But I won't leave you empty handed either. In order to discover the full capability of customization you will have to write C code to do that. Here is an idea of how I would have done it.

diff --git a/vi.c b/vi.c
index 24cc36a..874bd4e 100644
--- a/vi.c
+++ b/vi.c
@@ -1889,6 +1889,21 @@ void vi(void)
                        case '@':
                                vc_execute();
                                break;
+                       case '*':
+                               //put 3 new lines
+                               reg_put(vi_ybuf, "\n", 1);
+                               vc_put('p');
+                               vc_put('p');
+                               vc_put('p');
+                               xrow--; //center correctly
+                               //do the replace
+                               lbuf_edit(xb, "\\begin{displaymath}\n", xrow - 1, xrow);
+                               lbuf_edit(xb, "\n", xrow, xrow+1);
+                               lbuf_edit(xb, "\\end{displaymath}\n", xrow+1, xrow+2);
+                               //put into insert
+                               vi_back('i');
+                               mod = 1;
+                               break;
                        default:
                                continue;
                        }

Pick the key that is not in use, I used * for this example. Don't implement this kind of stuff in insert mode, it will be too difficult to time keys correctly, but if you really cut short for keys you can still try or just bind one key in insert, not a sequence like ",dmath".
Hope you can see how powerful this kind of customization is, you can do anything you want, just take your time, learn C and neatvi source code and you will be the independent master mind :) . Also learning C is a universal skill, which is way better than learning any other skript kiddie tools.

@Vouivre
Copy link
Collaborator Author

Vouivre commented Dec 11, 2020

Thank you for the code, it works perfectly! Do I understand you right: if somebody wants such a feature, it's not possible to have it indenpendant of the language. The snippets must be integrated in the code with the shortcuts. Right ?

@Vouivre
Copy link
Collaborator Author

Vouivre commented Dec 13, 2020

Forget my last comment, I thought about it. I want to do some tests. I will try something the next days and I will close this issue as it is or close it with a suggestion if somebody else read this issue.

@Vouivre
Copy link
Collaborator Author

Vouivre commented Dec 16, 2020

I tried to customize it, and with your example it's pretty easy to add more snippets. I did the following:

  --- a/vi.c
+++ b/vi.c
@@ -1903,6 +1903,34 @@
            case '@':
                    vc_execute();
                    break;
+            case '*':
+                k = vi_read();
+                if (k == 'd')
+                {
+                    //put 3 new lines
+                    reg_put(vi_ybuf, "\n", 1);
+                    vc_put('p');
+                    vc_put('p');
+                    vc_put('p');
+                    xrow--; //center correctly
+                    //do the replace
+                    lbuf_edit(xb, "\\begin{displaymath}\n", xrow - 1, xrow);
+                    lbuf_edit(xb, "\n", xrow, xrow+1);
+                    lbuf_edit(xb, "\\end{displaymath}\n", xrow+1, xrow+2);
+                    //put into insert
+                    vi_back('i');
+                    mod = 1;
+                    break;
+                } else if (k == 'i') {
+                    reg_put(vi_ybuf, "\n", 1);
+                    vc_put('p');
+                    lbuf_edit(xb, "\\ifdef\\corr{}{}\n", xrow, xrow+1);
+                    //put into insert
+                    vi_back('i');
+                    mod = 1;
+                    break;
+                }
+                break;
             default:
                   continue;
              }

Here I use *d to insert the fist snippet and *i to insert the second snippet.
Probably, I will use two keys, otherwise it will be complicated, because I have a lot of snippets. It still doesn't work as expected, because for some snippets I have to move the cursor to a given position, not simply positionning it in a line. But that's for later. First I have to understand the code of neatvi.

After trying that solution, I have the impression that it's faster to insert some code when it's defined at compile time. The gain remains small. But the at the end it's possible to have an editor small in size and customizable. I already had a look at C code. Thank your for showing me how to implement some snippets! Perhaps what I wrote can give some ideas to other people.

If there is no big problem in my code, I let you close this issue.

@kyx0r
Copy link
Owner

kyx0r commented Dec 16, 2020

You can control the cursor position using xrow and xoff variables. Function term_pos() prepares the move command and term_commit() actually does the thing. Normally you would not need to worry about those functions because they are called for you each draw update, unless you are doing something special. That said xrow and xoff is all you need. If you need to que commands in advance I'll have the function vi_argcmd() where you can que motion keys like hjlk (and more) in advance with an argument.

@Vouivre
Copy link
Collaborator Author

Vouivre commented Dec 18, 2020

Thank you for those information! I have begun to learn C code, I'll have a look next week. I have already tried but it didn't work. I will try again with those new information. Otherwise I will report what doesn't work.

@Vouivre
Copy link
Collaborator Author

Vouivre commented Jan 9, 2021

Sorry, for not responding until now. It's still on my list. I put this aside during holidays and tried to finish other stuffs. I have a look again on next week.

@kyx0r
Copy link
Owner

kyx0r commented Jan 9, 2021

Good point. Latest build versions were not very stable because I kept failing to find the correct solution to how to trim the syntax highlight to work only in range of the visible terminal cells. And there is bunch of things that makes it uneasy, variable length tabs, utf-8, double width characters, text direction. I kept breaking one of those while fixing the other. But now it should be stable. If you wanna have fun and test it out, make a file that consists of lines that are very long, probably like 30K characters and see performance difference between base neatvi version and mine.

@Vouivre
Copy link
Collaborator Author

Vouivre commented Jan 15, 2021

With your help, I was able to move the cursor. I got the following:

--- neatvi/vi.c
+++ neatvi_old/vi.c
@@ -1958,6 +1958,35 @@
                        case '@':
                                vc_execute();
                                break;
+            case '*':
+                k = vi_read();
+                if (k == 'd')
+                {
+                    //put 3 new lines
+                    reg_put(vi_ybuf, "\n", 1);
+                    vc_put('p');
+                    vc_put('p');
+                    vc_put('p');
+                    xrow--; //center correctly
+                    //do the replace
+                    lbuf_edit(xb, "\\begin{displaymath}\n", xrow - 1, xrow);
+                    lbuf_edit(xb, "\n", xrow, xrow+1);
+                    lbuf_edit(xb, "\\end{displaymath}\n", xrow+1, xrow+2);
+                    //put into insert
+                    vi_back('i');
+                    vi_mod = 1;
+                    break;
+                } else if (k == 'i') {
+                    reg_put(vi_ybuf, "\n", 1);
+                    vc_put('p');
+                    lbuf_edit(xb, "\t\\ifdef\\corr{}{}\n", xrow, xrow+1);
+                    xoff = xoff + 12;
+                    //put into insert
+                    vi_back('i');
+                    vi_mod = 1;
+                    break;
+                }
+                break;
                        default:
                                continue;
                        }
Only in neatvi_old: vi.o

I will try to implement some shortcuts this way.

I'm curious to try your improvements. But the problem is to have a file with lines of 30k characters. Does the content matter ? Could I create a file with for example:

for (i=4;i < 10; i++){ int i; i = 0; }

and repeat it until I have 30k characters ?

@kyx0r
Copy link
Owner

kyx0r commented Jan 15, 2021

Yes, you can just repeat that pattern "for (i=4;i < 10; i++){ int i; i = 0; }" on a single line. You can copy it like so: 0y$ and then just hold p to paste it, then rinse and repeat until you have a huge line. It's pretty rare to find huge lines like this in code, but I had once saw such a huge comment in glad.c library which listed the supported opengl extensions and it was 15K characters on one line. I quickly noticed that vi's performance has become quite unbearable because of that line to I had to optimize it in my fork. Otherwise I would have probably not even know that it can be so bad. It also might help if you ever get some obfuscated javascript code from some website, usually it will have all the code on one huge line, etc ...

@Vouivre
Copy link
Collaborator Author

Vouivre commented Jan 18, 2021

I tried it, but honestly I can't see any difference. They are both very fast. Maybe if the same code is repeated, it's not a problem. Or I did something wron

Thank you for your help, time now for me to implement my snippets... and enjoy your customizations!

@Vouivre Vouivre closed this as completed Jan 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants