The Window and Tabpage classes represent Neovim windows and tabpages, providing methods for layout management, cursor positioning, dimensions, and scoped variables and options.
/**
* Represents a Neovim window.
* Extends BaseApi and provides window-specific operations.
*/
class Window {
/** Window ID - unique identifier that doesn't change within Vim session */
id: number;
// Properties
/** Buffer displayed in this window */
buffer: AsyncBuffer;
/** Tabpage containing this window */
tabpage: AsyncTabpage;
/** Cursor position [row, col] (1-indexed row, 0-indexed col) */
cursor: [number, number] | Promise<[number, number]>;
/** Window height in rows */
height: number | Promise<number>;
/** Window width in columns */
width: number | Promise<number>;
/** Window position [row, col] */
position: Promise<[number, number]>;
/** Window row position */
row: Promise<number>;
/** Window column position */
col: Promise<number>;
/** Whether window is valid */
valid: Promise<boolean>;
/** Window number */
number: Promise<number>;
/**
* Close the window.
*
* @param force - Force close even if buffer has unsaved changes
*/
close(force?: boolean): Promise<void>;
/**
* Configure window (for floating/external windows).
* Sets window layout and appearance options.
*
* @param options - Window configuration
* @returns Configuration result
*/
config(options?: object): any;
// Inherited from BaseApi
/**
* Get window variable (w:var).
*
* @param name - Variable name
* @returns Variable value
*/
getVar(name: string): Promise<VimValue>;
/**
* Set window variable (w:var).
*
* @param name - Variable name
* @param value - Variable value
*/
setVar(name: string, value: VimValue): Promise<void>;
/**
* Delete window variable (w:var).
*
* @param name - Variable name
*/
deleteVar(name: string): Promise<void>;
/**
* Get window option.
*
* @param name - Option name
* @returns Option value
*/
getOption(name: string): Promise<VimValue>;
/**
* Set window option.
*
* @param name - Option name
* @param value - Option value
*/
setOption(name: string, value: VimValue): Promise<void>;
/**
* Compare with another window.
*
* @param other - Object to compare
* @returns true if windows are equal
*/
equals(other: any): boolean;
/**
* Send RPC request to Neovim for this window.
*
* @param name - API method name
* @param args - Method arguments
* @returns Response from Neovim
*/
request(name: string, args?: any[]): Promise<any>;
/**
* Send notification to Neovim for this window (non-blocking).
*
* @param name - Notification name
* @param args - Notification arguments
*/
notify(name: string, args: any[]): void;
}
type AsyncBuffer = Promise<Buffer> & Omit<Buffer, 'id' | 'isAttached'>;
type AsyncTabpage = Promise<Tabpage>;
type VimValue = number | boolean | string | number[] | { [key: string]: any };Usage Examples:
import { attach } from 'neovim';
const nvim = attach({ proc: nvim_proc });
// Get all windows
const windows = await nvim.windows;
console.log('Window count:', windows.length);
// Get current window
const win = await nvim.window;
// Window ID
console.log('Window ID:', win.id);
// Get window buffer
const buf = await win.buffer;
console.log('Buffer in window:', buf.id);
// Get window dimensions
const height = await win.height;
const width = await win.width;
console.log(`Window size: ${width}x${height}`);
// Set window dimensions
win.height = 20;
win.width = 80;
// Get cursor position
const [row, col] = await win.cursor;
console.log(`Cursor at: ${row}:${col}`);
// Set cursor position (row is 1-indexed, col is 0-indexed)
win.cursor = [10, 5];
// Get window position
const [winRow, winCol] = await win.position;
console.log(`Window at: ${winRow}, ${winCol}`);
// Get window number
const winNum = await win.number;
console.log('Window number:', winNum);
// Check if window is valid
const isValid = await win.valid;
console.log('Window valid:', isValid);
// Close window
await win.close(false); // Close if no unsaved changes
await win.close(true); // Force close
// Set current window
nvim.window = windows[0];
// Iterate through windows
for (const w of windows) {
const num = await w.number;
const buf = await w.buffer;
const bufName = await buf.name;
console.log(`Window ${num}: ${bufName}`);
}const win = await nvim.window;
// Window variables (w:)
await win.setVar('my_window_var', 'value');
const winVar = await win.getVar('my_window_var');
console.log('Window var:', winVar);
await win.deleteVar('my_window_var');
// Window options
await win.setOption('number', true);
await win.setOption('relativenumber', true);
await win.setOption('wrap', false);
await win.setOption('cursorline', true);
const hasNumbers = await win.getOption('number');
console.log('Line numbers:', hasNumbers);
// Common window options
await win.setOption('list', true);
await win.setOption('spell', true);
await win.setOption('foldmethod', 'indent');
await win.setOption('colorcolumn', '80');
// Window-local buffer options
await win.setOption('syntax', 'javascript');
await win.setOption('filetype', 'javascript');const nvim = attach({ proc: nvim_proc });
// Create buffer for floating window
const buf = await nvim.createBuffer(false, true);
await buf.setLines(['Floating window content', 'Line 2', 'Line 3']);
// Open floating window
const floatWin = await nvim.openWindow(buf, true, {
relative: 'editor', // Position relative to editor
width: 50,
height: 10,
row: 5,
col: 10,
anchor: 'NW', // Anchor to NW corner
style: 'minimal', // Minimal UI
border: 'rounded' // Border style
});
// Configure floating window
await floatWin.config({
relative: 'editor',
width: 60,
height: 15,
row: 10,
col: 20,
anchor: 'NW',
style: 'minimal',
border: ['╔', '═', '╗', '║', '╝', '═', '╚', '║']
});
// Position relative to cursor
const cursorFloatWin = await nvim.openWindow(buf, false, {
relative: 'cursor',
width: 30,
height: 5,
row: 1,
col: 0,
anchor: 'NW',
style: 'minimal'
});
// Centered floating window
const [editorHeight, editorWidth] = [50, 150]; // Get from UI
const floatHeight = 20;
const floatWidth = 80;
const centerWin = await nvim.openWindow(buf, true, {
relative: 'editor',
width: floatWidth,
height: floatHeight,
row: Math.floor((editorHeight - floatHeight) / 2),
col: Math.floor((editorWidth - floatWidth) / 2),
anchor: 'NW',
style: 'minimal',
border: 'single'
});
// Close floating window
await floatWin.close(true);const nvim = attach({ proc: nvim_proc });
// Create splits
await nvim.command('vsp'); // Vertical split
await nvim.command('sp'); // Horizontal split
// Get all windows after splits
const windows = await nvim.windows;
console.log('Windows after splits:', windows.length);
// Resize windows
const [win1, win2, win3] = windows;
win1.height = 20;
win1.width = 40;
win2.height = 15;
win3.width = 60;
// Balance window sizes
await nvim.command('wincmd =');
// Navigate between windows
await nvim.command('wincmd w'); // Next window
await nvim.command('wincmd h'); // Left window
await nvim.command('wincmd j'); // Down window
await nvim.command('wincmd k'); // Up window
await nvim.command('wincmd l'); // Right window
// Move windows
await nvim.command('wincmd H'); // Move to far left
await nvim.command('wincmd J'); // Move to far bottom
await nvim.command('wincmd K'); // Move to far top
await nvim.command('wincmd L'); // Move to far right
// Close windows
await win1.close(false);
await nvim.command('only'); // Close all but current windowconst win = await nvim.window;
const buf = await win.buffer;
// Get current cursor position
const [row, col] = await win.cursor;
console.log(`Cursor: line ${row}, column ${col}`);
// Move cursor to specific position
win.cursor = [1, 0]; // Top of file
win.cursor = [10, 5]; // Line 10, column 5
// Move cursor to end of file
const lineCount = await buf.length;
win.cursor = [lineCount, 0];
// Move cursor to end of line
const lines = await buf.lines;
const currentLine = await nvim.call('line', ['.']);
const lineLength = lines[currentLine - 1].length;
win.cursor = [currentLine, lineLength];
// Save and restore cursor position
const savedCursor = await win.cursor;
// ... do operations ...
win.cursor = savedCursor;
// Center cursor in window
await nvim.command('normal! zz');
// Scroll window
await nvim.command('normal! \\<C-d>'); // Scroll down
await nvim.command('normal! \\<C-u>'); // Scroll up
await nvim.command('normal! \\<C-f>'); // Page down
await nvim.command('normal! \\<C-b>'); // Page up/**
* Represents a Neovim tabpage.
* Extends BaseApi but does not support options (getOption/setOption will log errors).
*/
class Tabpage {
// Properties
/** All windows in this tabpage */
windows: Promise<Window[]>;
/** Current window of this tabpage */
window: AsyncWindow;
/** Whether tabpage is valid */
valid: Promise<boolean>;
/** Tabpage number */
number: Promise<number>;
/**
* Get option (not supported - logs error).
* Tabpages do not have options.
*/
getOption(): void;
/**
* Set option (not supported - logs error).
* Tabpages do not have options.
*/
setOption(): void;
// Inherited from BaseApi
/**
* Get tabpage variable (t:var).
*
* @param name - Variable name
* @returns Variable value
*/
getVar(name: string): Promise<VimValue>;
/**
* Set tabpage variable (t:var).
*
* @param name - Variable name
* @param value - Variable value
*/
setVar(name: string, value: VimValue): Promise<void>;
/**
* Delete tabpage variable (t:var).
*
* @param name - Variable name
*/
deleteVar(name: string): Promise<void>;
/**
* Compare with another tabpage.
*
* @param other - Object to compare
* @returns true if tabpages are equal
*/
equals(other: any): boolean;
/**
* Send RPC request to Neovim for this tabpage.
*
* @param name - API method name
* @param args - Method arguments
* @returns Response from Neovim
*/
request(name: string, args?: any[]): Promise<any>;
/**
* Send notification to Neovim for this tabpage (non-blocking).
*
* @param name - Notification name
* @param args - Notification arguments
*/
notify(name: string, args: any[]): void;
}
type AsyncWindow = Promise<Window> & Omit<Window, 'id'>;Usage Examples:
import { attach } from 'neovim';
const nvim = attach({ proc: nvim_proc });
// Get all tabpages
const tabpages = await nvim.tabpages;
console.log('Tabpage count:', tabpages.length);
// Get current tabpage
const tab = await nvim.tabpage;
// Get tabpage number
const tabNum = await tab.number;
console.log('Current tabpage:', tabNum);
// Check if valid
const isValid = await tab.valid;
console.log('Tabpage valid:', isValid);
// Get windows in tabpage
const windows = await tab.windows;
console.log('Windows in tabpage:', windows.length);
// Get current window of tabpage
const currentWin = await tab.window;
console.log('Current window:', currentWin.id);
// Set current tabpage
nvim.tabpage = tabpages[0];
// Iterate through tabpages
for (const t of tabpages) {
const num = await t.number;
const wins = await t.windows;
console.log(`Tabpage ${num}: ${wins.length} windows`);
}
// Tabpage variables (t:)
await tab.setVar('my_tab_var', 'tabpage value');
const tabVar = await tab.getVar('my_tab_var');
console.log('Tab var:', tabVar);
await tab.deleteVar('my_tab_var');
// Note: Tabpages don't support options
// tab.getOption('name') // Will log error
// tab.setOption('name', 'value') // Will log errorconst nvim = attach({ proc: nvim_proc });
// Create new tabpage
await nvim.command('tabnew');
await nvim.command('tabnew file.txt');
// Get tabpages after creation
const tabs = await nvim.tabpages;
console.log('Tabpage count:', tabs.length);
// Switch between tabpages
await nvim.command('tabn'); // Next tabpage
await nvim.command('tabp'); // Previous tabpage
await nvim.command('tabfirst'); // First tabpage
await nvim.command('tablast'); // Last tabpage
await nvim.command('tabn 3'); // Go to tabpage 3
// Set current tabpage
nvim.tabpage = tabs[1];
// Close tabpages
await nvim.command('tabclose'); // Close current
await nvim.command('tabclose 2'); // Close tabpage 2
await nvim.command('tabonly'); // Close all but current
// Move tabpage
await nvim.command('tabmove 0'); // Move to first
await nvim.command('tabmove $'); // Move to last
await nvim.command('tabmove +1'); // Move one right
await nvim.command('tabmove -1'); // Move one left
// Get info about all tabpages
for (const tab of tabs) {
const num = await tab.number;
const windows = await tab.windows;
const currentWin = await tab.window;
console.log(`Tabpage ${num}:`);
console.log(` Windows: ${windows.length}`);
console.log(` Current window: ${currentWin.id}`);
for (const win of windows) {
const buf = await win.buffer;
const bufName = await buf.name;
console.log(` Window ${win.id}: ${bufName}`);
}
}async function navigateWindows(nvim: NeovimClient) {
const windows = await nvim.windows;
console.log('Available windows:');
for (let i = 0; i < windows.length; i++) {
const win = windows[i];
const buf = await win.buffer;
const name = await buf.name || '[No Name]';
const [h, w] = await Promise.all([win.height, win.width]);
console.log(`${i}: ${name} (${w}x${h})`);
}
// Switch to window by index
nvim.window = windows[2];
}async function setupSplitView(nvim: NeovimClient, files: string[]) {
// Close all windows
await nvim.command('only');
// Open files in splits
for (let i = 0; i < files.length; i++) {
if (i > 0) {
await nvim.command('vsp');
}
await nvim.command(`e ${files[i]}`);
}
// Balance window sizes
await nvim.command('wincmd =');
const windows = await nvim.windows;
console.log(`Created ${windows.length} split windows`);
}async function showMenu(nvim: NeovimClient, items: string[]) {
// Create buffer with menu items
const buf = await nvim.createBuffer(false, true);
await buf.setLines(items);
// Calculate dimensions
const maxWidth = Math.max(...items.map(item => item.length));
const height = items.length;
// Create centered floating window
const floatWin = await nvim.openWindow(buf, true, {
relative: 'editor',
width: maxWidth + 4,
height: height + 2,
row: 10,
col: 20,
anchor: 'NW',
style: 'minimal',
border: 'rounded'
});
// Set window options
await floatWin.setOption('cursorline', true);
await floatWin.setOption('number', false);
// Position cursor at first item
floatWin.cursor = [1, 0];
return floatWin;
}async function setupProjectLayout(nvim: NeovimClient) {
// Tab 1: Main code
await nvim.command('tabnew');
await nvim.command('e src/main.ts');
await nvim.command('vsp src/utils.ts');
// Tab 2: Tests
await nvim.command('tabnew');
await nvim.command('e src/main.test.ts');
await nvim.command('sp src/utils.test.ts');
// Tab 3: Documentation
await nvim.command('tabnew');
await nvim.command('e README.md');
// Return to first tab
await nvim.command('tabfirst');
const tabs = await nvim.tabpages;
console.log(`Created ${tabs.length} tabpages`);
// Set tab variables for identification
await tabs[0].setVar('tab_name', 'Code');
await tabs[1].setVar('tab_name', 'Tests');
await tabs[2].setVar('tab_name', 'Docs');
}async function monitorWindowSizes(nvim: NeovimClient) {
setInterval(async () => {
const windows = await nvim.windows;
console.log('Window sizes:');
for (const win of windows) {
const [h, w] = await Promise.all([win.height, win.width]);
const num = await win.number;
console.log(` Window ${num}: ${w}x${h}`);
}
}, 5000);
}config() to reconfigure floating windows after creationvalid property to check if window/tabpage still existswincmd = after resizing