Skip to content

Commit

Permalink
feat: handle nvim statusline (#1895)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: vscode.get_status_item has been removed.
  • Loading branch information
xiyaowong committed Apr 21, 2024
1 parent eff4e20 commit fa5fc14
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 108 deletions.
24 changes: 4 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,10 @@ local vscode = require('vscode-neovim')
7. `vscode.notify()`: shows a vscode message (see also Nvim's `vim.notify`).
8. `vscode.to_op()`: A helper for `map-operator`. See [code_actions.lua](./runtime/plugin/code_actions.lua) for the
usage
9. `vscode.get_status_item`: Gets a vscode statusbar item. Properties can be assigned, which magically updates the
statusbar item.
10. `g:vscode_clipboard`: Clipboard provider using VSCode's clipboard API. Used by default when in WSL. See
`:h g:clipboard` for more details. Usage: `let g:clipboard = g:vscode_clipboard`
11. `vscode.eval()`: evaluate javascript synchronously in vscode and return the result
12. `vscode.eval_async()`: evaluate javascript asynchronously in vscode
9. `g:vscode_clipboard`: Clipboard provider using VSCode's clipboard API. Used by default when in WSL. See
`:h g:clipboard` for more details. Usage: `let g:clipboard = g:vscode_clipboard`
10. `vscode.eval()`: evaluate javascript synchronously in vscode and return the result
11. `vscode.eval_async()`: evaluate javascript asynchronously in vscode

### vscode.action(name, opts)

Expand Down Expand Up @@ -465,20 +463,6 @@ You can set `vscode.notify` as your default notify function.
vim.notify = vscode.notify
```

#### vscode.get_status_item(id)

Creates a status item

- `id` (string): The identifier of the item

```lua
local test = vscode.get_status_item('test')
test.text = 'hello' -- Show the text
test.text = '' -- Hide the item
test.text = nil -- Close the item
test.text = '' -- error: The status item "test" has been closed
```

### vscode.eval(code[, opts, timeout])

Evaluate javascript inside vscode and return the result. The code is executed in an async function context (so `await`
Expand Down
8 changes: 6 additions & 2 deletions runtime/lua/vscode-neovim.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ local vscode = {
notify = api.notify,
-- operatorfunc helper
to_op = api.to_op,
-- status item
get_status_item = api.get_status_item,

-- deprecated
get_status_item = function()
api.notify("Nvim statusline is now shown in vscode automatically. get_status_item was removed.")
return {}
end,
}

return vscode
60 changes: 0 additions & 60 deletions runtime/lua/vscode-neovim/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -418,64 +418,4 @@ do
end
end

--------------------------
------ status item ------
--------------------------

do
local _items = {}
local status_items = setmetatable({}, {
__newindex = function(_, k, v)
_items[k] = v
local status = vim.tbl_values(_items)
status = vim.tbl_filter(function(i)
return i ~= ""
end, status)
M.action("refresh-status-items", { args = { status } })
end,
__index = function(_, k)
return _items[k]
end,
})

---Creates a status item
---
---```lua
---local test = vscode.get_status_item('test')
---test.text = 'hello' -- Show the text
---test.text = '' -- Hide the item
---test.text = nil -- Close the item
---test.text = '' -- error: The status item "test" has been closed
---```
---
---@param id string The identifier of the item
function M.get_status_item(id)
vim.validate({ id = { id, "s" } })
status_items[id] = ""
return setmetatable({}, {
__newindex = function(_, k, v)
if k == "text" then
local curr = status_items[id]
if not curr then
error(([[The status item "%s" has been closed]]):format(id))
end
vim.validate({ text = { v, "s", true } })
if curr ~= v then
status_items[id] = v
end
end
end,
__index = function(_, k)
if k == "text" then
local curr = status_items[id]
if not curr then
error(([[The status item "%s" has been closed]]):format(id))
end
return curr
end
end,
})
end
end

return M
3 changes: 0 additions & 3 deletions runtime/lua/vscode-neovim/force-options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ vim.opt.cursorline = false
vim.opt.signcolumn = "no"
vim.opt.winblend = 0

--- Disable statusline and ruler since we don't need them anyway
vim.opt.statusline = ""
vim.opt.laststatus = 0
vim.opt.ruler = false
vim.opt.colorcolumn = nil

Expand Down
54 changes: 31 additions & 23 deletions src/status_line_manager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Disposable, StatusBarAlignment, StatusBarItem, window } from "vscode";

import actions from "./actions";
import { config } from "./config";
import { EventBusData, eventBus } from "./eventBus";
import { MainController } from "./main_controller";
Expand All @@ -10,7 +9,6 @@ enum StatusType {
Mode, // msg_showmode
Cmd, // msg_showcmd
Msg, // msg_show, msg_clear
Custom, // custom status item
}

export class StatusLineManager implements Disposable {
Expand All @@ -20,11 +18,11 @@ export class StatusLineManager implements Disposable {
private _modeText = "";
private _cmdText = "";
private _msgText = "";
// custom status items
private _customStatus: string[] = [];

private statusBar: StatusBarItem;

private nvimStatusLine = "";

private get client() {
return this.main.client;
}
Expand All @@ -33,28 +31,38 @@ export class StatusLineManager implements Disposable {
this.statusBar = window.createStatusBarItem(StatusBarAlignment.Left, -10);
this.statusBar.show();
this.disposables.push(this.statusBar, eventBus.on("redraw", this.handleRedraw, this));
actions.add("refresh-status-items", (items: string[]) => this.setStatus(items, StatusType.Custom));
}

private setStatus(status: string[], type: StatusType.Custom): void;
private setStatus(status: string, type: Omit<StatusType, "Custom">): void;
private setStatus(status: string | string[], type: StatusType): void {
if (Array.isArray(status)) {
this._customStatus = status;
} else {
switch (type) {
case StatusType.Mode:
this._modeText = status;
break;
case StatusType.Cmd:
this._cmdText = status;
break;
case StatusType.Msg:
this._msgText = status;
break;
const refreshNvimStatusLineTimer = setInterval(async () => {
let sl = (await this.client.lua(`
if vim.o.laststatus == 0 then return "" end
return vim.api.nvim_eval_statusline(vim.o.statusline, {}).str
`)) as any as string;
sl = sl.replace(/\n/g, " ").split(/\s+/g).join(" ");
if (this.nvimStatusLine !== sl) {
this.nvimStatusLine = sl;
this.updateStatus();
}
}, 120);
this.disposables.push(new Disposable(() => clearInterval(refreshNvimStatusLineTimer)));
}

private setStatus(status: string, type: StatusType): void {
switch (type) {
case StatusType.Mode:
this._modeText = status;
break;
case StatusType.Cmd:
this._cmdText = status;
break;
case StatusType.Msg:
this._msgText = status;
break;
}
this.statusBar.text = [this._modeText, this._cmdText, this._msgText, ...this._customStatus]
this.updateStatus();
}

private updateStatus() {
this.statusBar.text = [this.nvimStatusLine, this._modeText, this._cmdText, this._msgText]
.map((i) => i.replace(/\n/g, " ").trim())
.filter((i) => i.length)
.join(config.statusLineSeparator);
Expand Down

0 comments on commit fa5fc14

Please sign in to comment.