I'm trying to make my struct's members accessible through an index like an array, so if I have a struct like this in rust:

pub struct SubjectsProgress {
    pub sword: i32,
    pub lance: i32,
    pub axe: i32,
    pub bow: i32,
    pub brawl: i32,
    pub reason: i32,
    pub faith: i32,
    pub authority: i32,
    pub heavy_armor: i32,
    pub riding: i32,
    pub flying: i32,

I want to make it accessible to an index so I can do this:

impl Index<usize> for SubjectsProgress {
    type Output = i32;

    fn index(&self, i: usize) -> &i32 {
        match i % 11 {
            0 => &self.sword,
            1 => &self.lance,
            2 => &self.axe,
            3 => &self.bow,
            4 => &self.brawl,
            5 => &self.reason,
            6 => &self.faith,
            7 => &self.authority,
            8 => &self.heavy_armor,
            9 => &self.riding,
            10 => &self.flying,

            _ => unreachable!(),

I do this by copying the struct members pub sword: i32,... into the match statement, select them and replace pub \(.*\):.* with n => \&self.\1, So the full thing looks like this: :'<,'>s/pub \(.*\):.*/n => \&self.\1,. However this doesn't match the match number, (0=>sword, 1=>lance,...), so I have to manually replace n. How do I keep the match number as well when replacing?

1 Answer 1


Generally, there is no such thing as a "match number." But, you can create a counter and refer to it:

:let count = 0
:'<,'>global/^/substitute/pub \(.*\):.*/\=printf('%d => &self.%s', count, submatch(1))/ | let count = count + 1

Here I've wrapped the substitution in a :global/^/ so that it still runs on each line, but also can increment the counter afterwards.

If you know the starting line number, you can also refer to it. In this case, it's the start of our visual range so we can do it programatically:

:'<,'>substitute/pub \(.*\):.*/\=printf('%d => &self.%s', line('.') - line("'<"), submatch(1))/

The key in both is that \= allows arbitrary expressions.

An alternative that is conceptually simpler: gCtrl-a.

  1. :'<,'>substitute/pub \(.*\):.*/0 => \&self.\1/
  2. '<j0f0Ctrl-v'>0f0gCtrl-a

The 0f0 may not be necessary to get the right cursor position, but sometimes it's better safe than sorry :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.