5

Recently I found myself in a situation that need to type in quite a number of matrices to LaTeX by hand, so I was wondering if there are some tools that can help me to save some keystrokes.

The desired tool would work as follows. Whenever I need to insert a matrix, I trigger the plugin, then it prompts to ask me about the dimension of the matrix (for example, 4 by 3). Then it generates the following template:

\begin{bmatrix}
<++> & <++> & <++>\\
<++> & <++> & <++>\\
<++> & <++> & <++>\\
<++> & <++> & <++>\\
\end{bmatrix}<++>

I am following the LaTeX-suite convention here, but the actual format doesn't really matter.

Are there such tools? If not, I'd be very interested in implementing one myself, so are there any tools that have a similar function that I can refer to?

2 Answers 2

5

You could probably implement this as a snippet by leveraging Ultisnips' Interpolation feature (VimCasts demo). As an alternative, I whipped up a simplistic function to generate a matrix template on the current line per your sample:

function! CreateMatrix(rows, ...) abort
  let cols = a:0 ? a:1 : 3
  let matrix = ['\begin{bmatrix}']
  call extend(matrix, repeat([repeat('<++> & ', cols - 1) . '<++>\\'], a:rows))
  call add(matrix, '\end{bmatrix}<++>')
  call append(line('.') - 1, matrix)
endfunction
command! -nargs=+ Matrix silent call CreateMatrix(<f-args>)

The provided command takes as arguments rows and optionally columns. If columns is left unspecified, it defaults to 3. For example, calling :Matrix 3 would add the following to the current buffer:

\begin{bmatrix}
<++> & <++> & <++>\\
<++> & <++> & <++>\\
<++> & <++> & <++>\\
\end{bmatrix}<++>

Invoking :Matrix 5 8 would add:

\begin{bmatrix}
<++> & <++> & <++> & <++> & <++> & <++> & <++> & <++>\\
<++> & <++> & <++> & <++> & <++> & <++> & <++> & <++>\\
<++> & <++> & <++> & <++> & <++> & <++> & <++> & <++>\\
<++> & <++> & <++> & <++> & <++> & <++> & <++> & <++>\\
<++> & <++> & <++> & <++> & <++> & <++> & <++> & <++>\\
\end{bmatrix}<++>

It should be easy enough to modify the function and/or command to your liking.

2
  • Thanks for both the function and the recommendation of ultisnips!
    – hzh
    Commented Sep 21, 2018 at 19:26
  • Excellent!. I would include saving your cursor position to return to the top of the matrix, to start editing.... Commented Mar 22, 2020 at 18:52
10

Honza's UltiSnips Snippet gentbl<number>x<number>

available in the repository https://github.com/honza/vim-snippets/blob/master/UltiSnips/tex.snippets

Using this snippet which uses the python interpolation feature of UltiSnips, you can enter e.g.

gentbl5x3<tab>

which will expand to

\begin{tabular}{||||}
   &  &  \\
   &  &  \\
   &  &  \\
   &  &  \\
   &  &  \\
\end{tabular}

Note the jump marks of UltiSnips are not visible.

For a possibility to adapt this for matrix environments, see the update of this answer.

Additionally rows can be added afterwards with the snippet tr<number><tab>. Having three columns you would enter

tr3<tab>

to get

 &  &  \\

Update due to request in comment

global !p
def create_matrix(snip):

        matrix_str = (snip.buffer[snip.line].split('mat')[0]+'matrix').strip()

        rows = 'x'.join(snip.buffer[snip.line].split("x", 2)[:-1])
        cols = 'x'.join(snip.buffer[snip.line].split("x", 2)[-1:])

        int_val = lambda string: int(''.join(s for s in string if s.isdigit()))

        rows = int_val(rows)
        cols = int_val(cols)

        offset = cols + 1
        old_spacing = snip.buffer[snip.line][:snip.buffer[snip.line].rfind('\t') + 1]

        snip.buffer[snip.line] = ''

        final_str = old_spacing + "\\begin{"+matrix_str+"}\n"
        for i in range(rows):
                final_str += old_spacing + '\t'
                final_str += " & ".join(['$' + str(i * cols + j + offset) for j in range(cols)])

                final_str += " \\\\\\\n"

        final_str += old_spacing + "\\end{"+matrix_str+"}\n$0"

        snip.expand_anon(final_str)
endglobal

pre_expand "create_matrix(snip)"
snippet "(small|[bBpvV])?mat(rix)?(\d+)x(\d+)" "Generate (small|[bBpvV])?matrix of *rows* by *columns*" br
endsnippet

This adds following snippet variants

matrix<N>x<M><Tab>
bmatrix<N>x<M><Tab>
Bmatrix<N>x<M><Tab>
pmatrix<N>x<M><Tab>
vmatrix<N>x<M><Tab>
Vmatrix<N>x<M><Tab>
smallmatrix<N>x<M><Tab>

Additionally, all of them can be shortened by replacing matrix with mat, e.g.

bmat4x3<Tab>

which will give you

\begin{bmatrix}
   &  &  \\
   &  &  \\
   &  &  \\
   &  &  \\
\end{bmatrix}

LuaSnip

for a LuaSnip version you can find a definition here:

https://github.com/evesdropper/luasnip-latex-snippets.nvim

2
  • Could you may be elaborate more on how to achieve this in the bmatrix environment? Thank you!
    – hzh
    Commented Oct 7, 2018 at 20:23
  • 1
    See update of answer. I hope it helps.
    – Hotschke
    Commented Oct 8, 2018 at 9:38

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.