From 00ff6829030f302e8ff24d0e3a68625dd1a3ac40 Mon Sep 17 00:00:00 2001 From: Floaterest <56704092+floaterest@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:32:03 -0500 Subject: [PATCH] Custom Port (#34) * feat: custom port (#34) * removed some early returns --------- Co-authored-by: floaterest Co-authored-by: chomosuke --- README.md | 4 ++ doc/typst-preview.nvim.txt | 5 ++ lua/typst-preview/config.lua | 1 + lua/typst-preview/servers/factory.lua | 92 +++++++++++++++------------ 4 files changed, 63 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index cf323ea..48d7dcf 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,10 @@ require 'typst-preview'.setup { -- Example: open_cmd = 'firefox %s -P typst-preview --class typst-preview' open_cmd = nil, + -- Custom port to open the preview server. Default is random. + -- Example: port = 8000 + port = 0, + -- Setting this to 'always' will invert black and white in the preview -- Setting this to 'auto' will invert depending if the browser has enable -- dark mode diff --git a/doc/typst-preview.nvim.txt b/doc/typst-preview.nvim.txt index 8c11fc7..3cf95d0 100644 --- a/doc/typst-preview.nvim.txt +++ b/doc/typst-preview.nvim.txt @@ -126,6 +126,11 @@ Provide a custom format string to open the output link in `%s`. Example value for open_cmd: `'firefox %s -P typst-preview --class typst-preview'`. Type: `string`, Default: `nil` +*typst-preview.port* +Provide a custom port for the preview server. If the port (e.g. 8000) is +already in use, the plugin will try to use the next port (e.g. 8001). + Type: `number`, Default: `0` (i.e. random) + *typst-preview.invert_colors* Can be used to invert colors in preview. Set to `'never'` to disable. diff --git a/lua/typst-preview/config.lua b/lua/typst-preview/config.lua index 8b8f0c2..1028601 100644 --- a/lua/typst-preview/config.lua +++ b/lua/typst-preview/config.lua @@ -2,6 +2,7 @@ local M = { opts = { debug = false, open_cmd = nil, + port = 0, -- tinymist will use a random port if this is 0 invert_colors = 'never', follow_cursor = true, dependencies_bin = { diff --git a/lua/typst-preview/servers/factory.lua b/lua/typst-preview/servers/factory.lua index bdc0974..4ab9dad 100644 --- a/lua/typst-preview/servers/factory.lua +++ b/lua/typst-preview/servers/factory.lua @@ -10,11 +10,11 @@ local M = {} ---@param mode mode ---@param callback fun(close: fun(), write: fun(data: string), read: fun(on_read: fun(data: string)), link: string) ---Called after server spawn completes -local function spawn(path, mode, callback) +local function spawn(path, port, mode, callback) local server_stdout = assert(vim.uv.new_pipe()) local server_stderr = assert(vim.uv.new_pipe()) local tinymist_bin = config.opts.dependencies_bin['tinymist'] - or (utils.get_data_path() .. fetch.get_tinymist_bin_name()) + or (utils.get_data_path() .. fetch.get_tinymist_bin_name()) local args = { 'preview', '--partial-rendering', @@ -28,7 +28,7 @@ local function spawn(path, mode, callback) '--control-plane-host', '127.0.0.1:0', '--static-file-host', - '127.0.0.1:0', + '127.0.0.1:' .. port, '--root', config.opts.get_root(path), config.opts.get_main_file(path), @@ -58,7 +58,7 @@ local function spawn(path, mode, callback) local stderr = assert(vim.uv.new_pipe()) local addr = 'ws://' .. host .. '/' local websocat_bin = config.opts.dependencies_bin['websocat'] - or (utils.get_data_path() .. fetch.get_websocat_bin_name()) + or (utils.get_data_path() .. fetch.get_websocat_bin_name()) local websocat_handle, _ = assert(vim.uv.spawn(websocat_bin, { args = { '-B', @@ -110,46 +110,60 @@ local function spawn(path, mode, callback) return server_output:sub(s + 1, e - 1):gsub('%s+', '') end end + local function read_server(serr, server_output) if serr then error(serr) - elseif server_output then - local control_host = - find_host(server_output, 'Control plane server listening on: ') - or find_host(server_output, 'Control panel server listening on: ') - local static_host = + end + + if not server_output then + return + end + + if server_output:find 'AddrInUse' then + print('Port ' .. port .. ' is already in use') + server_stdout:close() + server_stderr:close() + -- try again at port + 1 + vim.defer_fn(function() + spawn(path, port + 1, mode, callback) + end, 0) + end + local control_host = find_host( + server_output, + 'Control plane server listening on: ' + ) or find_host(server_output, 'Control panel server listening on: ') + local static_host = find_host(server_output, 'Static file server listening on: ') - if control_host then - utils.debug 'Connecting to server' - connect(control_host) - end - if static_host then - utils.debug 'Setting link' - vim.defer_fn(function() - utils.visit(static_host) - if callback_param ~= nil then - assert( - type(callback_param.close) == 'function' - and type(callback_param.write) == 'function' - and type(callback_param.read) == 'function', - "callback_param's type isn't a table of functions" - ) - callback( - callback_param.close, - callback_param.write, - callback_param.read, - static_host - ) - else - callback_param = static_host - end - end, 0) - end + if control_host then + utils.debug 'Connecting to server' + connect(control_host) end - if server_output then - utils.debug(server_output) + if static_host then + utils.debug 'Setting link' + vim.defer_fn(function() + utils.visit(static_host) + if callback_param ~= nil then + assert( + type(callback_param.close) == 'function' + and type(callback_param.write) == 'function' + and type(callback_param.read) == 'function', + "callback_param's type isn't a table of functions" + ) + callback( + callback_param.close, + callback_param.write, + callback_param.read, + static_host + ) + else + callback_param = static_host + end + end, 0) end + utils.debug(server_output) end + server_stdout:read_start(read_server) server_stderr:read_start(read_server) end @@ -161,7 +175,7 @@ end function M.new(path, mode, callback) local read_buffer = '' - spawn(path, mode, function(close, write, read, link) + spawn(path, config.opts.port, mode, function(close, write, read, link) ---@type Server local server = { path = path, @@ -193,7 +207,7 @@ function M.new(path, mode, callback) end if read_buffer ~= '' then - utils.debug('Leaving for next read: '..read_buffer) + utils.debug('Leaving for next read: ' .. read_buffer) end end, 0) end)