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
21 changes: 16 additions & 5 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
name: Format
on: [push, pull_request]
on:
push:
branches: [main]
paths:
- '**.lua'
- '.stylua.toml'
- '.github/workflows/lint.yml'
pull_request:

jobs:
format:
stylua:
name: Check Lua formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4

- uses: JohnnyMorganz/stylua-action@v4
- name: Run StyLua
uses: JohnnyMorganz/stylua-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: latest
token: ${{ secrets.GITHUB_TOKEN }}
args: --check lua/ --config-path=.stylua.toml
18 changes: 13 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
name: Lint
on: [push, pull_request]

on:
push:
branches:
- main
pull_request:

jobs:
format:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4

- name: Dependencies
- name: Install luacheck
run: |
sudo apt-get update
sudo apt-get install luarocks -y
sudo apt-get install -y luarocks
sudo luarocks install luacheck

- name: Lint
- name: Run luacheck
run: luacheck lua/ --globals vim
42 changes: 30 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
name: Tests
on: [push, pull_request]

on:
push:
branches:
- main
pull_request:

jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Dependencies
- name: Checkout code
uses: actions/checkout@v4

- name: Install Node.js and dependencies
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci

- name: Clone Neovim dependencies
run: |
mkdir -p dependencies
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim.git dependencies/plenary.nvim
git clone --depth 1 https://github.com/nvim-treesitter/nvim-treesitter.git dependencies/nvim-treesitter

npm i -g ts-node

- name: Prepare
- name: Setup Neovim 0.11.1
shell: bash
run: |
mkdir -p _nvim
curl -sL "https://github.com/neovim/neovim/releases/download/v0.9.0/nvim-linux64.tar.gz" | tar xzf - --strip-components=1 -C "${PWD}/_nvim"
curl -sL "https://github.com/neovim/neovim/releases/download/v0.11.1/nvim-linux-x86_64.tar.gz" | tar xzf - --strip-components=1 -C _nvim
echo "${PWD}/_nvim/bin" >> $GITHUB_PATH

- name: Update Treesitter parsers
shell: bash
run: |
export PATH="${PWD}/_nvim/bin:${PATH}"

nvim --headless -u scripts/minimal.vim -c 'TSUpdateSync javascript typescript' -c 'q'

_nvim/bin/nvim --headless -u scripts/minimal.vim -c 'TSUpdateSync javascript typescript' -c 'q'

- name: Run tests
shell: bash
run: |
export PATH="${PWD}/_nvim/bin:${PATH}"
nvim --version
_nvim/bin/nvim --version
make test
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
/lua_modules
/.luarocks
/dependencies

/node_modules
205 changes: 83 additions & 122 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,126 +1,35 @@
![](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)
![Status](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)

# nvim-exec for javascript/typescript
[![Lua](https://img.shields.io/badge/Lua-blue.svg?style=for-the-badge&logo=lua)](http://www.lua.org)
[![Neovim](https://img.shields.io/badge/Neovim%200.8+-green.svg?style=for-the-badge&logo=neovim)](https://neovim.io)

Sometimes you need fast feedback on the code you are writing. This plugin allows you to execute code
from your current buffer. It displays the output as a comment in the same buffer. Currently only **javascript** and **typescript**
are supported.

You can execute any code within a comment block. The output will be displayed
as a comment in the next line(s).
# nvim-exec

Example:
Suppose you have the following fibonacci function in your buffer (btw, this is a terrible way to calculate
fibonacci numbers). If you place the cursor in the comment block and execute :ExecCode, you will see the
output in the next line(s).

```javascript
// fibs(10)
// [
// 1, 1, 2, 3, 5,
// 8, 13, 21, 34, 55
// ]
//
const fibs = (n) => {
const go = (n) => {
if (n < 2) return 1;
return go(n - 1) + go(n - 2);
}

return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []);
}
```
[![Lua](https://img.shields.io/badge/Lua-blue.svg?style=for-the-badge&logo=lua)](http://www.lua.org)
[![Neovim](https://img.shields.io/badge/Neovim%200.9.5+-green.svg?style=for-the-badge&logo=neovim)](https://neovim.io)

The plugin configures a timeout for the code execution. If the code takes longer than the timeout, the
execution will be stopped. The default timeout is 10 seconds.
> Execute JavaScript/TypeScript code directly from your Neovim buffer and see the results instantly

```javascript
// fibs(100)
// Job timed out
//
const fibs = (n) => {
const go = (n) => {
if (n < 2) return 1;
return go(n - 1) + go(n - 2);
}
## Features

return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []);
}
```
- ✅ Execute JavaScript/TypeScript code directly from your buffer
- ✅ View results as comments or in a separate window
- ✅ Built-in timeout protection for long-running code
- ✅ Seamless integration with your Neovim workflow

Of course you know a better way of calculating fibonacci numbers using memoization. You can use the
following code to calculate the first 100 fibonacci numbers. If you place the cursor in the comment block
and execute :ExecCode, you will see the output in the next line(s).
## Installation

```javascript
// fibs(100)
// [
// 1, 1, 2,
// 3, 5, 8,
// 13, 21, 34,
// 55, 89, 144,
// 233, 377, 610,
// 987, 1597, 2584,
// 4181, 6765, 10946,
// 17711, 28657, 46368,
// 75025, 121393, 196418,
// 317811, 514229, 832040,
// 1346269, 2178309, 3524578,
// 5702887, 9227465, 14930352,
// 24157817, 39088169, 63245986,
// 102334155, 165580141, 267914296,
// 433494437, 701408733, 1134903170,
// 1836311903, 2971215073, 4807526976,
// 7778742049, 12586269025, 20365011074,
// 32951280099, 53316291173, 86267571272,
// 139583862445, 225851433717, 365435296162,
// 591286729879, 956722026041, 1548008755920,
// 2504730781961, 4052739537881, 6557470319842,
// 10610209857723, 17167680177565, 27777890035288,
// 44945570212853, 72723460248141, 117669030460994,
// 190392490709135, 308061521170129, 498454011879264,
// 806515533049393, 1304969544928657, 2111485077978050,
// 3416454622906707, 5527939700884757, 8944394323791464,
// 14472334024676220, 23416728348467684, 37889062373143900,
// 61305790721611580, 99194853094755490, 160500643816367070,
// 259695496911122560, 420196140727489660, 679891637638612200,
// 1100087778366101900, 1779979416004714000, 2880067194370816000,
// 4660046610375530000, 7540113804746346000, 12200160415121877000,
// 19740274219868226000, 31940434634990100000, 51680708854858330000,
// 83621143489848430000, 135301852344706760000, 218922995834555200000,
// 354224848179262000000
// ]
//
const fibs = (n) => {
const memo = new Map();
const go = (n) => {
if (n < 2) return 1;
if (memo.has(n)) return memo.get(n);
const result = go(n - 1) + go(n - 2);
memo.set(n, result);
return result;
}
### Requirements

return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []);
}
```

# Quickstart
## Requirements
- **Neovim 0.9.5** or later
- Node.js installation
- Nvim-treesitter with parser installation. This plugin uses the treesitter parser to identify the language
of the code you want to execute. You can install the parser for the language you are using by running
`:TSInstall <language>` in neovim.
- nvim-treesitter with appropriate parser installation
- Install language parsers using `:TSInstall javascript` or `:TSInstall typescript`

### For TypeScript Support

## Requirements for Typescript
- Typescript installation
- ts-node

## Installation
- Example configuration for lazy:
### Using [lazy.nvim](https://github.com/folke/lazy.nvim)

```lua
return {
"tbsklg/nvim-exec",
Expand All @@ -138,24 +47,76 @@ return {
nvim_exec.run()
end, { desc = "Execute code" })
end,
ft = "javascript",
ft = { "javascript", "typescript" },
}
```

## Default configuration
```lua
{
timeout = 10000, -- Timeout in milliseconds for code execution
output_mode = "window", -- "comment" || "window"
## Usage

1. Write your JavaScript/TypeScript code in a buffer
2. Add a comment with code to execute (e.g. `// fibs(10)`)
3. Place your cursor on the comment line
4. Execute `:ExecCode` or use your configured keybinding (e.g. `<leader>r`)
5. See results appear below as comments or in a window

### Example

```javascript
// fibs(10)
// [
// 1, 1, 2, 3, 5,
// 8, 13, 21, 34, 55
// ]
//
const fibs = (n) => {
const go = (n) => {
if (n < 2) return 1;
return go(n - 1) + go(n - 2);
}

return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []);
}
```

# Development
## Run linting
```make lint```
### Timeout Protection

The plugin automatically terminates code execution that takes longer than the configured timeout (default: 10 seconds).

```javascript
// fibs(100) // Using the inefficient implementation
// Job timed out
//
```

## Configuration

```lua
require("nvim-exec").setup({
timeout = 10000, -- Timeout in milliseconds (default: 10000)
output_mode = "window" -- "comment" or "window" (default: "window")
})
```

| Option | Description | Default |
|--------|-------------|---------|
| `timeout` | Maximum execution time in milliseconds | `10000` |
| `output_mode` | Where to display results (`"comment"` or `"window"`) | `"window"` |

## Development

### Prerequisites

- Lua and Neovim development environment
- Make

### Available Commands

```bash
make lint # Run linting
make fmt # Run formatting
make test # Run tests
```

## Run formatting
```make fmt```
## License

## Run tests
```make test```
[MIT](LICENSE)
Loading