vim Archives - ProdSens.live https://prodsens.live/tag/vim/ News for Project Managers - PMI Sun, 11 Feb 2024 18:20:11 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 https://prodsens.live/wp-content/uploads/2022/09/prod.png vim Archives - ProdSens.live https://prodsens.live/tag/vim/ 32 32 Vim https://prodsens.live/2024/02/11/vim/?utm_source=rss&utm_medium=rss&utm_campaign=vim https://prodsens.live/2024/02/11/vim/#respond Sun, 11 Feb 2024 18:20:11 +0000 https://prodsens.live/2024/02/11/vim/ vim

Vi Improved, a programmer’s text editor To open a file, type vim followed by the file name in…

The post Vim appeared first on ProdSens.live.

]]>
vim

Vi Improved, a programmer’s text editor

Image description

To open a file, type vim followed by the file name in terminal.

Image description

vim file

Modal Mindset

Unlike your typical text editor, Vim operates in different “modes.” This might seem daunting at first, but mastering these modes unlocks its true potential.

Image description

  • Normal Mode: Your command center. Move the cursor, navigate text, issue commands with keyboard shortcuts. Think of it as your spaceship’s bridge.

  • Insert Mode: Where you type like usual. Imagine yourself at the helm, crafting your code or text.

  • Visual Mode: Highlight and manipulate text blocks like a Jedi wielding a lightsaber.

Essential Navigation

Image description

  • Cursor Movement: h, j, k, l: Left, down, up, right (more ergonomic than arrows).

  • Jumping Around: /pattern: Search for text and jump to its first occurrence. n: Repeat search in the same direction.

  • Going Places: G: Jump to a specific line number. gg: Go to the very beginning. G$: Go to the very end.

Image description

Now, as we know Vim has multiple modes to start editing your file you need to be in insert mode. By default when we open vim it’s always in normal mode.

To switch to insert mode press

i

Image description

As we switched to insert mode now,we can type and it will be visible.

To go back to normal mode press

Esc

Exit Vim

Haha,no need to terminate or kill the process :V

Image description

First thing first, make sure you are in normal mode.Then you need to press : followed by

Image description

Save and exit

:wq

Exit without saving

:q!

Great it’s not that hard to exit right. So, now try to open vim and write some random paragraph. Lazy you could use Lorem too.

Let’s now see how to navigate.

Here, we have two paragraph in this file.Again we need to be normal mode to navigate.

Image description

To jump to the last of the line

Shift + g

To jump to the top of the file

gg

Find

To find something in file, make sure you are in normal mode.

Image description

/word

For next (same word can be repeated multiple times in the file)

n

That’s not all.

We can even search in reverse direction (bottom to top)

?word

For next

n

If the cursor is in the word you want to find.

In forward direction(asterisk)

* 

In Reverse direction direction(hash)

#

Replace

Replacing a word in the file.

Image description

So, we need to substitute word1 with word2 globally

:%s/word1/word2/g

Image description

In the above image all the string will be replaced with character

Undo

Image description

To undo the last changes made

:u

Redo

Image description

To Redo the changes

Ctrl + r

Editing

Image description

In Normal mode to start editing in next line

o

To start editing on line above the cursor

Shift + o

To start from the start of the line if cursor in b/w the line.

Shift + i

To start editing from the end of the line

Shift + a

Delete

Image description

To delete a character where cursor is present
small

x

To delete a line
twice

dd

To replace a single character
small

r

Delete multiple lines

In normal mode make sure the cursor is on the line from where you want to delete

Let’s say you want to delete 10 lines

10 dd

To undo all the changes

:e!

Copy/Paste

Image description

To paste cut/copied text

p

To paste above the cursor

Shift + p

In copy/paste section we will see the visual mode sit back and focus.

Image description

Haha, now let’s see…

To select whole line

Shift + v

Okay,but how to select what we need huh???

To select what we need we need to go in visual mode how you ask

v

Yes, that’s it just press v and the best part is using the arrow keys you can even select up,down,left,right

Image description

Now after selecting

To copy_(yank)_ the selected text

y

To paste press p and it will get pasted.

Remember dd command it used to cut it will be your clipboard, it can be paste by hitting p

Misc

Line Number

Image description

To print the lines numbers in file

:set nu

To remove the line numbers

:set nonu

Image description

This serial line numbers you can enable an disable as you wish.

Syntax Highlighting

This is for Programmers to turn on the syntax highlighting feature, it’s possible.

Turn on color coding

:syntax on

Turn off color coding

:syntax off

Jump to given line

Turn on your line numbers, suppose you want to jump to 20th line

:20

Working with Multiple files

Image description

To read multiple files at once

vim -o file1 file2

To switch between files opened
Press twice

Ctrl + w

Compare two files

Image description

Side by side difference with highlighted changes

vim -d file1 file2

Time to practice and flex

Image description

The post Vim appeared first on ProdSens.live.

]]>
https://prodsens.live/2024/02/11/vim/feed/ 0
Using only vim to solve AdventOfCode Challenges | Episode 2 https://prodsens.live/2023/12/17/using-only-vim-to-solve-adventofcode-challenges-episode-2/?utm_source=rss&utm_medium=rss&utm_campaign=using-only-vim-to-solve-adventofcode-challenges-episode-2 https://prodsens.live/2023/12/17/using-only-vim-to-solve-adventofcode-challenges-episode-2/#respond Sun, 17 Dec 2023 22:25:07 +0000 https://prodsens.live/2023/12/17/using-only-vim-to-solve-adventofcode-challenges-episode-2/ using-only-vim-to-solve-adventofcode-challenges-|-episode-2

Note: It’s important to read the first episode to understand the context of how these challenges are solved.…

The post Using only vim to solve AdventOfCode Challenges | Episode 2 appeared first on ProdSens.live.

]]>
using-only-vim-to-solve-adventofcode-challenges-|-episode-2

Note: It’s important to read the first episode to understand the context of how these challenges are solved.

1. Getting Started

Open today’s challenge and make sure that you are in sync with your team, if you don’t have a team yet submit your application here

Take your time with the challenge and solve the puzzle in the two mentioned scenarios. Good luck.

1.1 Rules

  1. In the first scenario, if you plan to hardcode all possible outcomes of the game, avoid manual entry. Instead, find an automatic way to handle them. Imagine having one million potential outcomes for the game—your approach should be automated for speed. Utilize your editor for efficiency. Remember, the emphasis in the first scenario is on speed.

  2. In the second scenario, write a Vimscript that accommodates the worst-case scenario. Consider a situation where each symbol might signify something else in the future. Structure your code to distinctly separate the game logic from symbol deciphering.

1.2 Sample Data

The provided sample data should be used for testing the commands. Once you feel comfortable and confident, you can apply these commands to your actual input data.

Input:

A Y
B X
C Z

Expected output:

  • part1: 15
  • part2: 12

2. Solutions

This guide assumes you’ve already watched the accompanying walk-through YouTube video. If you haven’t, please do.

2.1 The First Scenario

2.1.1 Part One

Our input data consists of symbols representing each player’s move, and our task is to calculate the score of each game. The quickest way is to map all possible outcomes and replace each line with the corresponding score. For example:

A Y
B X
C Z

will translate to:

8
1
6

This mapping can be done using Vim dictionaries, acting like hashtables or objects. Below is a function Swap containing a dictionary with all possible game outcomes:

function! Swap(line)
  let scores = {
     'A X': '4',
     'A Y': '8',
     'A Z': '3',
     'B X': '1',
     'B Y': '5',
     'B Z': '9',
     'C X': '7',
     'C Y': '2',
     'C Z': '6',
   }

  return scores[a:line]
endfunction

While we can use this function immediately, today’s challenge rules prohibit hard coding outcomes. Instead, we need a fast and creative way to enter them.

To generate all possible symbols, use :r! echo \n{A..C}" "{X..Z}.

In the walkthrough video, alternatives to Bash were discussed, showcasing the flexibility to choose more powerful tools based on specific needs.

This Haskell code achieves the same result as the previous Bash code, but with a key advantage: scalability. We can easily make further transformations to the generated output by adding additional functions to the pipeline.

main = putStr $ unlines [[x, ' ', y] | x <- ['A'..'C'], y <- ['X'..'Z']]

So far, this is what we have:

A X 
A Y 
A Z 
B X 
B Y 
B Z 
C X 
C Y 
C Z

and our end goal is:

A X: score 
A Y: score
... 
C Z: score

First let’s create a function on the fly, that will assign the bonus points, if we loose we get no bonus, if we end with a draw we get the hand move point plus 3 and if we win we get the hand move point plus 6.

let BonusOf = {a, b -> a > b ? 0 : (a < b ? 6 : 3)

Now, to assign the correct score to each combination, let's record a quick macro.

Start by recording a macro on the first line with the following commands:

:let ln = line('.')
:let playerA = ln-1/3 + 1
:let playerB = ln%3 ? ln%3 : 3

gg0C'pA: =playerB + (playerA>1 && playerB>1 ? BonusOf(playerA,playerB) : BonusOf(playerA%3,playerB%3))jq

As we covered in the walkthrough video, we're using line numbers to determine the value of each hand. By default, "A, X" is 1, "B, Y" is 2, and so on.

We also use BonusOf(playerA%3, playerB%3) to round the value of each hand by three. This is because "Rock" is typically 1 and "Paper" is 2. However, we need to adjust this logic for "Scissors" (3), which should not be considered stronger than "Rock." The walkthrough video explains this rounding process in more detail.

Now, let's apply the macro we recorded on the first line to the rest of the lines. Simply use .,$ norm @q and you're good to go!

Then wrap everything in a function:

function! Swap(line)
  let scores = {
         'A X': 4,
         'A Y': 8,
         'A Z': 3,
         'B X': 1,
         'B Y': 5,
         'B Z': 9,
         'C X': 7,
         'C Y': 2,
         'C Z': 6,
         }

  return scores[a:line]
endfunction

Open the input file and run the function on each line using :%s/.*/=Swap(submatch(0)). To calculate the sum of all lines, use %! paste -sd+ | bc.

2.1.2 Part Two

For the second part of the challenge, the approach remains similar. Adjust the way you calculate the score for each round. You'll end up with a function like this:

function! Swap2(line)
  let scores = {
     'A X': 3,
     'A Y': 4,
     'A Z': 8,
     'B X': 1,
     'B Y': 5,
     'B Z': 9,
     'C X': 2,
     'C Y': 6,
     'C Z': 7,
   }

  return scores[a:line]
endfunction

Apply the same steps as in Part One to obtain the answer for the second part efficiently. Don't retype your previous commands, just recall them from the command history. this step shouldn't take more than 5 seconds.

2.2 The Second Scenario

Defining Essential Functions

First and foremost, let's address the essential functions required for our game logic:

let Bonus = {a, b -> a > b ? 0 : (a < b ? 6 : 3)}
let Score = {a, b -> a>1 && b>1 ? g:Bonus(a, b) + b : g:Bonus(a%3, b%3) + b}

These functions establish the scoring mechanism for the game.

Handling Hand Moves

To proceed, we need to assign points to each hand move:

let pointOf = {'rock': 1, 'paper': 2, 'scissors': 3}

Additionally, we create a dictionary to map each move to its defeating move:

let next = {'rock': 'scissors', 'paper': 'rock', 'scissors': 'paper'}

Processing Input Data

Assuming our input data is stored in a file named input, we start by reading and printing its content:

echo readfile("input")

The output is a list of lines in the format ['symbolA symbolB', 'symbolA symbolB', ...]. We transform it to [['symbolA', 'symbolB'], ...]:

echo
       readfile("inputdemo.vim")
       ->map("split(v:val, ' ')")

The next step now is to translate each symbol to what it mean, whether is it 'rock', 'paper' or 'scissors'. for now, we are still in the testing phase, let's create a dummy function that will do this translation.

function ToHand(symbol)
  return {_ -> 'rock'}
endfunction

Our ToHand function takes a symbol and returns a new function. This new function, in turn, takes an argument and ultimately returns the name of the hand. In our example, it will always return "rock."

You might wonder why we don't just create a function that directly returns the string "rock" instead of adding an extra layer of abstraction. The reason is that the function we return will later be able to accept symbols from either the left or right column. This allows each function to have information about the opponent's move.

While ToHand may seem simple now, we'll revisit it and expand its functionality later.

echo
       readfile("inputdemo.vim")
       ->map("split(v:val, ' ')")
       ->map({_, xs -> [ToHand(xs[0])(xs[1]), xs[1]]})

Here, we map over each element, applying ToHand to symbols in the left column for player one's move, and then applying it to the right column for player two's move.

       ->map({_, xs -> [xs[0], ToHand(xs[1])(xs[0])]})

While applying both functions simultaneously might seem tempting, it would make our lambda function unnecessarily complex. Instead, we'll follow the natural flow of the game: player one plays their move, the game state updates, and then player two reacts based on the updated state. This approach keeps our code easy to read.

Next, we convert hand names to their corresponding points:

       ->map({_, xs -> map(xs, "g:pointOf[v:val]")})

We call the Score function to obtain the score for each game round and sum up all the numbers in the list:

       ->map({_, v -> g:Score(v[0], v[1])})
       ->reduce({a, b -> a + b})

This encapsulates the entire game logic.

Note: While this script utilizes nested maps, it aligns with the nature of Vimscript. In other languages, we might explore composition or transduction, but for now, we'll keep Vimscript within its natural confines. Any future modifications will be limited to the ToHand function.

Note: I have written this using map on top of map. for this script is fine, in other languages, I might compose or transduce but let's not push vimscript doing things that aren't naturally built for. However, it's acknowledged that in future iterations, Lua may be explored for enhanced functionality, as hinted in the seond season.

Moving forward, the sole modification we'll make is to our placeholder function ToHand; all other aspects of the script remain unchanged.

2.2.1 Part One

In the initial phase of the puzzle, we assign 'rock' to A and X, 'paper' to B and Y, and 'scissors' to C and Z.

Now, let's refine our 'ToHand' function to accurately represent each symbol.

function ToHand(symbol)
  let symbols = {
         'A': {_ -> 'rock'},
         'B': {_ -> 'paper'},
         'C': {_ -> 'scissors'},
         'X': {_ -> 'rock'},
         'Y': {_ -> 'paper'},
         'Z': {_ -> 'scissors'},
        }

  return symbols[a:symbol]
endfunction

This modification ensures that our 'ToHand' function correctly translates each symbol to its corresponding hand gesture.

And that's it – we're finished!

2.2.2 Part Two

In the second part, we define the conditions for three scenarios: losing, drawing, and winning denoted by X, Y, and Z respectively. Achieving these outcomes involves specific modifications to our ToHand function.

         'X': {x -> g:next[x]}

For scenario X, which corresponds to a loss, we take the enemy's hand move, represented by arg x, and call the next function to determine the subsequent move required for a loss.

         'Y': {x -> x}

In the case of Y, signifying a draw, we simply return the same enemy move denoted by x.

         'Z': {x -> g:next[g:next[x]]}

For Z, indicating a win, we perform the inverse of the X scenario.

2.2.3 The Final Script

That's all the necessary adjustments to the ToHand function. The final and comprehensive script is provided below.

function ToHand(symbol)
  let symbols = {
         'A': {_ -> 'rock'},
         'B': {_ -> 'paper'},
         'C': {_ -> 'scissors'},
         'X': {x -> g:next[x]},
         'Y': {x -> x},
         'Z': {x -> g:next[g:next[x]]},
        }

  return symbols[a:symbol]
endfunction


" CORE, DO NOT TOUCH
let pointOf = {'rock': 1, 'paper': 2, 'scissors': 3}
let next = {'rock': 'scissors', 'paper': 'rock', 'scissors': 'paper'}
let Bonus = {a, b -> a > b ? 0 : (a < b ? 6 : 3)}
let Score = {a, b -> a>1 && b>1 ? g:Bonus(a, b) + b : g:Bonus(a%3, b%3) + b}

echo
       readfile("inputdemo.vim")
       ->map("split(v:val, ' ')")
       ->map({_, xs -> [ToHand(xs[0])(xs[1]), xs[1]]})
       ->map({_, xs -> [xs[0], ToHand(xs[1])(xs[0])]})
       ->map({_, xs -> map(xs, "g:pointOf[v:val]")})
       ->map({_, v -> g:Score(v[0], v[1])})
       ->reduce({a, b -> a + b})

Exercises

  1. In your preferred programming language, create a script that can automatically generate all potential game outcomes and their score.

  2. Run your code in Vim to generate all the required data automatically.

Below is an example using Javascript:

const log = console.log;

const getCombos = xs => ys =>
  xs.flatMap (x => ys.map (y => [x, y]));

const pointOf = move => {
  const moves = {'X': 1, 'Y': 2, 'Z': 3,};
  return moves[move];
};

const some = xs => xA => xB =>
  xs
    .map (x => x.split(""))
    .some (x => x[0] === xA && x[1] === xB);

const isDraw = some (['AX', 'BY', 'CZ']);

const isLost = some (['AZ', 'BX', 'CY']);

const format = combos => {
  return (
    combos.map (combo => {
      const enemyMove = combo[0];
      const myMove = combo[1];
      const shapeScore = pointOf (myMove);

      const score = (
        isDraw (enemyMove) (myMove)
          ? 3 + shapeScore
          : isLost (enemyMove) (myMove) ? shapeScore : 6 + shapeScore
      );

      return `'${enemyMove} ${myMove}':${score},`
    })
  );
};

log (format (getCombos (['A', 'B', 'C']) (['X', 'Y', 'Z'])))

The post Using only vim to solve AdventOfCode Challenges | Episode 2 appeared first on ProdSens.live.

]]>
https://prodsens.live/2023/12/17/using-only-vim-to-solve-adventofcode-challenges-episode-2/feed/ 0
An opinionated article about vim https://prodsens.live/2023/06/30/an-opinionated-article-about-vim/?utm_source=rss&utm_medium=rss&utm_campaign=an-opinionated-article-about-vim https://prodsens.live/2023/06/30/an-opinionated-article-about-vim/#respond Fri, 30 Jun 2023 09:25:26 +0000 https://prodsens.live/2023/06/30/an-opinionated-article-about-vim/ an-opinionated-article-about-vim

Introduction I have now been using vim and neovim for almost a year. In that time I built…

The post An opinionated article about vim appeared first on ProdSens.live.

]]>
an-opinionated-article-about-vim

Introduction

I have now been using vim and neovim for almost a year. In that time I built a lot of experience with the IDE, which I wanted to share with people thinking about making the switch.
This article will mostly just go over why I like vim, but I’ll also be talking about some disadvantages.
When showing code to use as an example of editing, I’ll be taking code from my own Redmine plugin: gnosis.

Super fast code navigation

The most obvious and most talked about point is how fast you can navigate code with vim. There are a lot of keybindings used for jumping around code. One example would be following:

protect_from_forgery except: %i[github_webhook_catcher semaphore_webhook_catcher]

Now if I want to remove the github_webhook_catcher from the protect_from_forgery statement, I would go following steps (assuming my cursor is somewhere completely random): :4 WWW db does the job. Here is a video of how that might look:

Video of text being deleted, vim style

There are a lot more keybindings and tricks that improve your speed. If you have trouble memorizing them all, this cheat sheet was A-tier.

Extreme configuration

A personal favorite is how much you can personalize vim. Everything is customizable, from your background color to very specific keybindings. One example of that would be my own .vimrc.
As someone who gets irritated as soon as something tiny is wrong with their code editor, the ability to customize everything was a very big bonus.
Currently I am using nvchad with my own nvchad config, which makes for a beautiful code editor:
Screenshot of my nvchad dashboard
Screenshot of nvchad with open code

Very good plugin system

(Neo)vim supports plugins, which make your code editor much better. You need a faster way to comment stuff? Sure, here is nvim-comment. Now you need a better tool to surround text by certain characters? Alright, we also have nvim-surround. And this goes on for almost everything you ever needed.
And in the rare case that you can’t find a plugin for what you need: Write it yourself! It’s very easy to write plugins, as vim and neovim both have a lot of functions that help with writing those.

The steep learning curve

The biggest problem to vim is its steep learning curve. If you’re someone who is already in a commercial setting and need to produce at a certain speed, learning vim will be pretty hard. As someone who is still in education I had the option of killing my coding speed for a few months, just so I could learn vim.

Alright, I’m convinced. Should I use vim or neovim?

That choice everybody should make for himself, but I use neovim.

What’s the difference between vim and neovim?

The major difference is that neovim uses lua for its plugins, which vim is still on vimscript.
Most people prefer lua, as it’s more intuitive to write and has loads of uses outside of writing neovim plugins, making lua a much more useful language than vimscript.

Which one has better plugins?

From personal experience, neovim has much better plugins, while not more.
The fact that they’re written in lua makes them more performant than vimscript, which already is a big benefit. On top of that: The fact that learning lua is much more useful than vimscript means that more people are willing to spend time learning it, making neovim plugins feel much more refined.

Example comparison: fzf-vim vs. telescope

As someone that has been using fzf for most of the time, changing to telescope opened up so much more options. Telescope has integrated git diffs, commit histories, language server settings, and much more.
This is an example of how the commit history check looks like
Commit history of telescope

Conclusion

I think learning vim is something everyone that is still in education should do, independent of if you actually stick with it or not.
The great amount of configuration and useful keybindings makes using vim a great experience.

The post An opinionated article about vim appeared first on ProdSens.live.

]]>
https://prodsens.live/2023/06/30/an-opinionated-article-about-vim/feed/ 0
How to create your own completion for vim https://prodsens.live/2023/06/26/how-to-create-your-own-completion-for-vim/?utm_source=rss&utm_medium=rss&utm_campaign=how-to-create-your-own-completion-for-vim https://prodsens.live/2023/06/26/how-to-create-your-own-completion-for-vim/#respond Mon, 26 Jun 2023 00:24:23 +0000 https://prodsens.live/2023/06/26/how-to-create-your-own-completion-for-vim/ how-to-create-your-own-completion-for-vim

Have you ever thought about defining your own completion for particular things like emails, contact names or for…

The post How to create your own completion for vim appeared first on ProdSens.live.

]]>
how-to-create-your-own-completion-for-vim

Have you ever thought about defining your own completion for particular things like emails, contact names or for something complex like tailwind classes or github usernames? Well, my goal on this post is to show you how to do it in a simple and concise way!

A demo first

As you can see on the video above it’s quite a simple mechanism to define your
own completion, first you create a function that return an array of strings and
then you assigned to completefunc option that accept a function reference and
after that you can trigger the completion by pressing Ctrl+x Ctrl+u when on
insert mode. Now let’s understand the structure of this function and write a
more exciting one!

Understanding the completion function structure

Here is the function used on the video above for example:

function! MyCompletion(findstart, base) abort
  return ['something', 'to', 'complete', 'devto']
endfunction

The first argument findstart it’s a numeric argument and vim will call it with value 1 on the first execution of completion to find the column position of the current word (to position the completion popup for example), then on a second moment vim call this function again with a value 0 where it expects an actual lists of items.

That’s why on the video I got an error saying E745: Using a List as a Number, because vim was expecting the column number at that point of the completion cycle.

The second argument base is a string with all the previous completion matches grouped together, of course it’s empty on the first execution and gradually will be incremented if the user keep pressing the completion keybind.

Writing the simple version with filter

Now that we understand the basic structure for a completion function let’s
improve it a little bit with a filter! Basically we’ll detect the substring
that the user typed and return the correct option first so it’s easy to select
it.

Here is an example:

function! MyCompletion(findstart, base) abort
  if a:findstart
    return 0
  endif

  let s:matches = ['something', 'to', 'complete', 'devto']

  if a:base->len() == 0
    return s:matches
  endif

  return s:matches->matchfuzzy(a:base)
endfunction

The matchfuzzy on this context is a default function of vimscript and help us get an fuzzy matching algorithm that give our simple completion function a lot of power, as shown below:

demo video about completion with fuzzy

Last improvement on the basic example

If you mess with this function on your own setup you’ll observe that exists a bug, to clarify and keep us on the same page i’ll show the bug below:

demo video about completion bug

As you can see on the video we can only complete the first word and then everything stop working, that’s because we didn’t return a proper integer value for findstart! that way vim can’t find the start of the current word and provide correct base value, this is quite simple to solve and we can increment it like this:

function! MyCompletion(findstart, base) abort
  if a:findstart
    let s:startcol = col('.') - 1
    while s:startcol > 0 && getline('.')[s:startcol - 1] =~ 'a'
      let s:startcol -= 1
    endwhile
    return s:startcol
  endif

  let s:matches = ['something', 'to', 'complete', 'devto']

  if a:base->len() == 0
    return s:matches
  endif

  return s:matches->matchfuzzy(a:base)
endfunction

On this version we’re effective walking through the line and updating the startcol variable accordingly, that way vim will always find our current incompleted word and provide correct arguments.

Writing a more exciting completion function

Well at this point I think you understand the structure and power of a custom completion function in vim, so let’s spice things up and give a more complex example.

  1. Let’s assume we have a list of emails on /tmp/emails like this:
cherry@gmail.com
mel@gmail.com
morgana@outlook.com
yaya@heart.com
huelder@insiide.com.br
daniel@heart.com
  1. We’ll write a function that get the content of this file and return the emails using the fuzzy matching algorithm, this can be done with the following function:
function! EmailCompletion(findstart, base) abort
  if a:findstart
    let s:startcol = col('.') - 1
    while s:startcol > 0 && getline('.')[s:startcol - 1] =~ 'a'
      let s:startcol -= 1
    endwhile
    return s:startcol
  endif

  let s:emails = expand('/tmp/emails')->readfile()

  if a:base->len() == 0
    return s:emails
  endif

  return s:emails->matchfuzzy(a:base)
endfunction
  1. And voila! let’s see it working?

final demo with email completion

The post How to create your own completion for vim appeared first on ProdSens.live.

]]>
https://prodsens.live/2023/06/26/how-to-create-your-own-completion-for-vim/feed/ 0