Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions M2/Macaulay2/editors/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ prism/prism.js
prism/prism.js.LICENSE.txt
pygments/macaulay2.py
rouge/macaulay2.rb
vim/dict/m2.vim.dict
vim/syntax/m2.vim
7 changes: 2 additions & 5 deletions M2/Macaulay2/editors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
## - M2-editors generates grammar files
## - M2-emacs generates the M2-mode package for Emacs

# TODO: generate vim grammar
# TODO: generate textmate grammar

set(M2 ${M2_DIST_PREFIX}/${M2_INSTALL_BINDIR}/M2)
set(M2_ARGS --script)

Expand All @@ -17,8 +14,8 @@ set(GRAMMAR_FILES
prism/macaulay2.js
pygments/macaulay2.py
# rouge/macaulay2.rb
vim/m2.vim.syntax
vim/m2.vim.dict
vim/syntax/m2.vim
vim/dict/m2.vim.dict
emacs/M2-symbols.el)

set(GRAMMAR_TEMPLATES ${GRAMMAR_FILES})
Expand Down
6 changes: 3 additions & 3 deletions M2/Macaulay2/editors/make-M2-symbols.m2
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ generateGrammar("emacs/M2-symbols.el", x -> demark(" ", format \ x))
-- Prism: Write macaulay2.js
generateGrammar("prism/macaulay2.js", x -> demark("|", x))

-- Vim: Write m2.vim.syntax and m2.vim.dict
generateGrammar("vim/m2.vim.syntax", x -> demark(" ", x))
generateGrammar("vim/m2.vim.dict", x -> demark(" ", x)) -- TODO: is this necessary?
-- Vim: Write syntax/m2.vim and dict/m2.vim.dict
generateGrammar("vim/syntax/m2.vim", x -> demark(" ", x))
generateGrammar("vim/dict/m2.vim.dict", x -> demark(" ", x))

-- Pygments: Write macaulay2.py
generateGrammar("pygments/macaulay2.py",
Expand Down
55 changes: 55 additions & 0 deletions M2/Macaulay2/editors/vim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Vim Plugin for Macaulay2

Syntax highlighting and key mappings to send code to a running Macaulay2 session.

> **Neovim users:** The [macaulay2.nvim](https://github.com/Macaulean/macaulay2.nvim) plugin provides a more complete Neovim integration.

## Requirements

- Vim 8.1+
- `M2` on your `PATH`

## Installation

```sh
cp -r dict ftdetect ftplugin syntax ~/.vim/
```

Then, in Macaulay2, generate the symbol files. You may also do this after a
new Macaulay2 release to update the files with any new symbols.

```m2
needsPackage "Style"
changeDirectory "~/.vim"
generateGrammar("dict/m2.vim.dict", demark_" ")
generateGrammar("syntax/m2.vim", demark_" ")
Copy link
Copy Markdown
Contributor

@dimpase dimpase May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we, instead for copying templates to ~/.vim/, keep them in the M2 sources dir?
Then we would only need to cp -r ftdetect ftplugin ~/.vim/.

I'd do the latter with copyDirectory, and wrap the whole thing in a small M2 function installVimPlugin of something like this.

This can be done in another PR, though, if you prefer.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that makes sense. Another PR sounds good. Should we merge this and you can start from there?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. By the way, how does one navigate M2 source tree from M2? I presume there's some build-in for the root of it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're running from a just-built copy of M2, then topSrcdir tells you the root directory. It's unexported, so you have to debug Core or importFrom(Core, "topSrcdir"). It's just null when running in a distributed copy of M2.

```

Ensure your `~/.vimrc` contains:

```vim
filetype plugin on
syntax on
```

## Usage

### Key mappings

| Key | Mode | Action |
|-----|------|--------|
| `F12` | Normal | Start M2 in a terminal split (or switch to it) |
| `F11` | Normal/Visual | Send current line or visual selection to M2 |
| `F11` | Insert | Send current line to M2 and continue editing |
| `Tab` | Insert | Complete word from dictionary, or insert tab |

### Commands

| Command | Action |
|---------|--------|
| `:M2Start` | Open M2 in a terminal split, or switch to it if already running |
| `:M2Restart` | Restart M2 |
| `:M2Exit` | Exit M2 |
| `:M2Send` | Send current line or visual selection to M2 |
| `:M2SendBuffer` | Send the entire buffer to M2 |
| `:M2SendString {str}` | Send a string to M2 |
49 changes: 0 additions & 49 deletions M2/Macaulay2/editors/vim/README_linux

This file was deleted.

59 changes: 0 additions & 59 deletions M2/Macaulay2/editors/vim/README_macos

This file was deleted.

14 changes: 0 additions & 14 deletions M2/Macaulay2/editors/vim/VimM2.scpt

This file was deleted.

1 change: 1 addition & 0 deletions M2/Macaulay2/editors/vim/dict/m2.vim.dict.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@M2SYMBOLS@
1 change: 1 addition & 0 deletions M2/Macaulay2/editors/vim/ftdetect/m2.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
au BufRead,BufNewFile *.m2 set filetype=m2
123 changes: 123 additions & 0 deletions M2/Macaulay2/editors/vim/ftplugin/m2.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
" Authors: David Cook II <dcook@ms.uky.edu>
" Manoj Kummini <mkummini@cmi.ac.in>
" License: Public Domain

" Per-buffer settings
setlocal cpt+=k
setlocal dict+=~/.vim/dict/m2.vim.dict

" Tab: complete from dictionary when cursor is after a word character,
" otherwise insert a literal tab.
if !exists('*M2_Tab_Or_Complete')
function! M2_Tab_Or_Complete()
if col('.')>1 && strpart(getline('.'), col('.')-2, 3) =~ '^\w'
return "\<C-N>"
else
return "\<Tab>"
endif
endfunction
endif
inoremap <buffer> <Tab> <C-R>=M2_Tab_Or_Complete()<CR>

function! M2Warning(msg)
echohl WarningMsg
echo a:msg
echohl Normal
endfunction

if !executable('M2')
call M2Warning('vim-M2-plugin: M2 not found on PATH')
finish
endif

let g:m2_terminal_buf = get(g:, 'm2_terminal_buf', -1)

command! -nargs=0 M2Start :call M2Start()
command! -nargs=0 M2Restart :call M2Restart()
command! -nargs=0 M2Exit :call M2Exit()
command! -nargs=1 M2SendString :call M2SendString(<args>)
command! -nargs=0 M2SendBuffer :call M2SendBuffer()
command! -nargs=0 -range M2Send :call M2Send(<line1>,<line2>)

nnoremap <buffer> <F12> :M2Start<CR>
noremap <buffer> <F11> :M2Send<CR>j0
inoremap <buffer> <F11> <ESC>:M2Send<CR>o

function! M2IsRunning()
if g:m2_terminal_buf == -1 || !bufexists(g:m2_terminal_buf)
return 0
endif
let job = term_getjob(g:m2_terminal_buf)
return job isnot 0 && job_status(job) ==# 'run'
endfunction

" Open M2 in a terminal split, or switch to it if already running.
function! M2Start()
if M2IsRunning()
execute 'buffer ' . g:m2_terminal_buf
return
endif
let g:m2_terminal_buf = term_start('M2', {'term_name': 'Macaulay2', 'term_finish': 'open'})
endfunction

function! M2Restart()
call M2SendString('restart')
endfunction

function! M2Exit()
call M2SendString('exit')
endfunction

function! M2SendString(str)
if !M2IsRunning()
call M2Warning('vim-M2-plugin: M2 is not running. Use :M2Start or <F12>.')
return
endif
call term_sendkeys(g:m2_terminal_buf, a:str . "\<CR>")
endfunction

function! M2SendBuffer()
call M2Send('1', '$')
endfunction

" Send a string, list, or line range to M2.
function! M2Send(...)
if a:0 == 0
let lines = [getline('.')]
elseif a:0 == 1
let ta1 = type(a:1)
if ta1 == 1
let lines = split(a:1, "\n")
elseif ta1 == 3
let lines = a:1
else
call M2Warning('vim-M2-plugin: argument must be a string or a list.')
return
endif
elseif a:0 == 2
if type(a:1) <= 1 && type(a:2) <= 1
let lines = getline(a:1, a:2)
let mode = visualmode(1)
if mode != '' && line("'<") == a:1
if mode == 'v'
let start = col("'<") - 1
let end = col("'>") - 1
let lines[-1] = lines[-1][: end]
let lines[0] = lines[0][start :]
elseif mode == "\<c-v>"
let start = min([col("'<"), col("'>")]) - 1
call map(lines, 'v:val[start :]')
endif
endif
else
call M2Warning('vim-M2-plugin: arguments must be a pair of strings/integers.')
return
endif
else
call M2Warning('vim-M2-plugin: invalid number of arguments.')
return
endif
for lin in lines
call M2SendString(lin)
endfor
endfunction
6 changes: 0 additions & 6 deletions M2/Macaulay2/editors/vim/m2.vim.dict

This file was deleted.

6 changes: 0 additions & 6 deletions M2/Macaulay2/editors/vim/m2.vim.dict.in

This file was deleted.

Loading