diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index ae98a5a..580930c 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,47 +1,98 @@
 name: Issue report
 description: Report any errors, bugs, or unexpected behaviors related to presence.nvim
+title: "[Bug]: "
 labels: [bug]
+assignees:
+  - jiriks74
 body:
   - type: markdown
     attributes:
       value: |
         Before reporting, please search [existing issues](https://github.com/andweeb/presence.nvim/issues) and make sure that presence.nvim is updated to the latest version.
+
+  - type: checkboxes
+    attributes:
+      label: Are you on the latest version?
+      options:
+        - label: I have updated to the latest version.
+          required: true
+
+  - type: checkboxes
+    attributes:
+      label: Have you tried it with default config?
+      options:
+        - label: I have tried the default config.
+          required: true
+            
   - type: textarea
     attributes:
       label: "Description"
       description: "A short summary of the error, bug, or unexpected behavior you're facing."
     validations:
       required: true
+
   - type: textarea
     attributes:
       label: "Neovim version"
       description: "Output of `nvim --version`"
       render: markdown
       placeholder: |
-        NVIM v0.6.0-dev+209-g0603eba6e
+        NVIM: v0.6.0-dev+209-g0603eba6e
         Build type: Release
-        LuaJIT 2.1.0-beta3
+        LuaJIT: 2.1.0-beta3
+      value: |
+        NVIM:
+        Build type:
+        LuaJIT:
     validations:
       required: true
+
   - type: input
     attributes:
       label: "OS information"
       placeholder: "macOS 12.0.1"
     validations:
       required: true
+        
   - type: textarea
     attributes:
       label: "Steps to reproduce"
-      description: "Steps to reproduce the issue with your config(s) if applicable"
+      description: "Steps to reproduce the issue with your config(s) if applicable."
       placeholder: |
         1. Setup presence.nvim with `require("presence"):setup({...})`
         2. Run Neovim with `nvim test.txt`
         3. ...
     validations:
       required: true
+
   - type: textarea
     attributes:
       label: "Logs"
-      description: "The full list of `:messages` from one or more `nvim` instances"
+      description: "The full list of `:messages` from one or more `nvim` instances.\nPlease insert the logs into code blocks."
+      placeholder: |
+        <details>
+
+        ```
+        [presence.nvim] Using runtime path: /run/user/1000
+        [presence.nvim] Using Discord IPC socket path: /run/user/1000/discord-ipc-0
+        [presence.nvim] Checking Discord IPC socket at /run/user/1000/discord-ipc-0...
+        ```
+
+        </details>
+      value: |
+        <details>
+
+        ```
+
+        ```
+
+        </details>
     validations:
       required: true
+
+  - type: textarea
+    attributes:
+      label: "Aditional info"
+      description: "If you'd like to add anything else put it here."
+    validations:
+      required: false
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 11fc491..0000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: enhancement
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..9ebd200
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,34 @@
+name: Feature request
+description: Report any errors, bugs, or unexpected behaviors related to presence.nvim
+title: "[FEAT]: "
+labels: [enhancement]
+assignees:
+  - jiriks74
+body:
+  - type: textarea
+    attributes:
+      label: Is your feature request related to a problem?
+      description: A clear and concise description of what the problem is. Ex. I'm always frustrated when...
+    validations:
+      required: true
+
+  - type: textarea
+    attributes:
+      label: Describe the solution you'd like
+      description: A clear and concise description of what you want to happen.
+    validations:
+      required: false
+
+  - type: textarea
+    attributes:
+      label: Describe alternatives you've considered
+      description: A clear and concise description of any alternative solutions or features you've considered.
+    validations:
+      required: false
+
+  - type: textarea
+    attributes:
+      label: Additional context
+      description: Add any other context or screenshots about the feature request here.
+    validations:
+      required: false
diff --git a/.github/workflows/luacheck.yml b/.github/workflows/luacheck.yml
index 571609c..87145d9 100644
--- a/.github/workflows/luacheck.yml
+++ b/.github/workflows/luacheck.yml
@@ -1,7 +1,7 @@
 name: Luacheck
 on: [push, pull_request]
 jobs:
-  sile:
+  Luacheck:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
diff --git a/.github/workflows/stylua.yml b/.github/workflows/stylua.yml
new file mode 100644
index 0000000..639c7e1
--- /dev/null
+++ b/.github/workflows/stylua.yml
@@ -0,0 +1,15 @@
+name: StyLua
+on: [push, pull_request]
+jobs:
+  StyLuacheck:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: StyLua check
+        uses: JohnnyMorganz/stylua-action@v3
+        with:
+          token: ${{ secrets.GH_TOKEN }}
+          version: v0.18.2 # NOTE: we recommend pinning to a specific version in case of formatting changes
+          # CLI arguments
+          args: --check .
diff --git a/README.md b/README.md
index 2744b6c..29e3119 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ require("presence").setup({
     auto_update         = true,                       -- Update activity based on autocmd events (if `false`, map or manually execute `:lua package.loaded.presence:update()`)
     neovim_image_text   = "The One True Text Editor", -- Text displayed when hovered over the Neovim image
     main_image          = "neovim",                   -- Main image display (either "neovim" or "file")
-    client_id           = "793271441293967371",       -- Use your own Discord application client id (not recommended)
+    client_id           = "1172122807501594644",       -- Use your own Discord application client id (not recommended)
     log_level           = nil,                        -- Log messages at or above this level (one of the following: "debug", "info", "warn", "error")
     debounce_timeout    = 10,                         -- Number of seconds to debounce events (or calls to `:lua package.loaded.presence:update(<filename>, true)`)
     enable_line_number  = false,                      -- Displays the current line number instead of the current project
@@ -91,7 +91,7 @@ Or if global variables are more your thing, you can use any of the following ins
 let g:presence_auto_update         = 1
 let g:presence_neovim_image_text   = "The One True Text Editor"
 let g:presence_main_image          = "neovim"
-let g:presence_client_id           = "793271441293967371"
+let g:presence_client_id           = "1172122807501594644"
 let g:presence_log_level
 let g:presence_debounce_timeout    = 10
 let g:presence_enable_line_number  = 0
@@ -142,6 +142,8 @@ errors: `luacheck lua`
 **Please use [Conventional Commits](https://www.conventionalcommits.org/) if you want to contribute.
 It makes everyones jobs easier.**
 
+**This project uses [StyLua](https://github.com/JohnnyMorganz/StyLua). Please format your code using StyLua for better readability**
+
 Pull requests are very welcome, feel free to open an issue to work on
 or message [me (@jiriks74)](https://discordapp.com/users/517810049360461837) on my
 [Discord server](https://discord.gg/cCq3qcB4jB)!
diff --git a/lua/deps/msgpack.lua b/lua/deps/msgpack.lua
index a4b928b..d7ccfdd 100644
--- a/lua/deps/msgpack.lua
+++ b/lua/deps/msgpack.lua
@@ -9,120 +9,140 @@ local double_encode_count = 0
 -- cache bitops
 local band, rshift = luabit.band, luabit.brshift
 if not rshift then -- luajit differ from luabit
-    rshift = luabit.rshift
+	rshift = luabit.rshift
 end
 
-local function byte_mod(x,v)
-    if x < 0 then
-        x = x + 256
-    end
-    return (x%v)
+local function byte_mod(x, v)
+	if x < 0 then
+		x = x + 256
+	end
+	return (x % v)
 end
 
-
 -- buffer
 local strbuf = "" -- for unpacking
 local strary = {} -- for packing
 
-local function strary_append_int16(n,h)
-    if n < 0 then
-        n = n + 65536
-    end
-    table.insert( strary, tostr(h, math.floor(n / 256), n % 256 ) )
+local function strary_append_int16(n, h)
+	if n < 0 then
+		n = n + 65536
+	end
+	table.insert(strary, tostr(h, math.floor(n / 256), n % 256))
 end
 
-local function strary_append_int32(n,h)
-    if n < 0 then
-        n = n  + 4294967296
-    end
-    table.insert(strary, tostr(h,
-        math.floor(n / 16777216),
-        math.floor(n / 65536) % 256,
-        math.floor(n / 256) % 256,
-    n % 256 ))
+local function strary_append_int32(n, h)
+	if n < 0 then
+		n = n + 4294967296
+	end
+	table.insert(
+		strary,
+		tostr(h, math.floor(n / 16777216), math.floor(n / 65536) % 256, math.floor(n / 256) % 256, n % 256)
+	)
 end
 
 local doubleto8bytes
 local strary_append_double = function(n)
-    -- assume double
-    double_encode_count = double_encode_count + 1
-    local b = doubleto8bytes(n)
-    table.insert( strary, tostr(0xcb))
-    table.insert( strary, string.reverse(b) )   -- reverse: make big endian double precision
+	-- assume double
+	double_encode_count = double_encode_count + 1
+	local b = doubleto8bytes(n)
+	table.insert(strary, tostr(0xcb))
+	table.insert(strary, string.reverse(b)) -- reverse: make big endian double precision
 end
 
 --- IEEE 754
 
 -- out little endian
 doubleto8bytes = function(x)
-    local function grab_byte(v)
-        return math.floor(v / 256), tostr(math.fmod(math.floor(v), 256))
-    end
-    local sign = 0
-    if x < 0 then sign = 1; x = -x end
-    local mantissa, exponent = math.frexp(x)
-    if x == 0 then -- zero
-        mantissa, exponent = 0, 0
-    elseif x == 1/0 then
-        mantissa, exponent = 0, 2047
-    else
-        mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
-        exponent = exponent + 1022
-    end
+	local function grab_byte(v)
+		return math.floor(v / 256), tostr(math.fmod(math.floor(v), 256))
+	end
+	local sign = 0
+	if x < 0 then
+		sign = 1
+		x = -x
+	end
+	local mantissa, exponent = math.frexp(x)
+	if x == 0 then -- zero
+		mantissa, exponent = 0, 0
+	elseif x == 1 / 0 then
+		mantissa, exponent = 0, 2047
+	else
+		mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
+		exponent = exponent + 1022
+	end
 
-    local v, byte = "" -- convert to bytes
-    x = mantissa
-    for _ = 1,6 do
-        _, byte = grab_byte(x); v = v..byte -- 47:0
-    end
-    x, byte = grab_byte(exponent * 16 + x);  v = v..byte -- 55:48
-    x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
-    return v, x
+	local v, byte = "" -- convert to bytes
+	x = mantissa
+	for _ = 1, 6 do
+		_, byte = grab_byte(x)
+		v = v .. byte -- 47:0
+	end
+	x, byte = grab_byte(exponent * 16 + x)
+	v = v .. byte -- 55:48
+	x, byte = grab_byte(sign * 128 + x)
+	v = v .. byte -- 63:56
+	return v, x
 end
 
 local function bitstofrac(ary)
-    local x = 0
-    local cur = 0.5
-    for _, v in ipairs(ary) do
-        x = x + cur * v
-        cur = cur / 2
-    end
-    return x
+	local x = 0
+	local cur = 0.5
+	for _, v in ipairs(ary) do
+		x = x + cur * v
+		cur = cur / 2
+	end
+	return x
 end
 
 local function bytestobits(ary)
-    local out={}
-    for _, v in ipairs(ary) do
-        for j = 0, 7, 1 do
-            table.insert(out, band( rshift(v,7-j), 1 ) )
-        end
-    end
-    return out
+	local out = {}
+	for _, v in ipairs(ary) do
+		for j = 0, 7, 1 do
+			table.insert(out, band(rshift(v, 7 - j), 1))
+		end
+	end
+	return out
 end
 
 -- get little endian
 local function bytestodouble(v)
-    -- sign:1bit
-    -- exp: 11bit (2048, bias=1023)
-    local sign = math.floor(v:byte(8) / 128)
-    local exp = band( v:byte(8), 127 ) * 16 + rshift( v:byte(7), 4 ) - 1023 -- bias
-    -- frac: 52 bit
-    local fracbytes = {
-        band( v:byte(7), 15 ), v:byte(6), v:byte(5), v:byte(4), v:byte(3), v:byte(2), v:byte(1) -- big endian
-    }
-    local bits = bytestobits(fracbytes)
+	-- sign:1bit
+	-- exp: 11bit (2048, bias=1023)
+	local sign = math.floor(v:byte(8) / 128)
+	local exp = band(v:byte(8), 127) * 16 + rshift(v:byte(7), 4) - 1023 -- bias
+	-- frac: 52 bit
+	local fracbytes = {
+		band(v:byte(7), 15),
+		v:byte(6),
+		v:byte(5),
+		v:byte(4),
+		v:byte(3),
+		v:byte(2),
+		v:byte(1), -- big endian
+	}
+	local bits = bytestobits(fracbytes)
 
-    for _ = 1, 4 do table.remove(bits,1) end
+	for _ = 1, 4 do
+		table.remove(bits, 1)
+	end
 
-    if sign == 1 then sign = -1 else sign = 1 end
+	if sign == 1 then
+		sign = -1
+	else
+		sign = 1
+	end
 
-    local frac = bitstofrac(bits)
-    if exp == -1023 and frac==0 then return 0 end
-    if exp == 1024 and frac==0 then return 1/0 *sign end
+	local frac = bitstofrac(bits)
+	if exp == -1023 and frac == 0 then
+		return 0
+	end
+	if exp == 1024 and frac == 0 then
+		return 1 / 0 * sign
+	end
 
-    local real = math.ldexp(1+frac,exp)
+	local real = math.ldexp(1 + frac, exp)
 
-    return real * sign
+	return real * sign
 end
 
 --- packers
@@ -130,265 +150,285 @@ end
 local packers = {}
 
 packers.dynamic = function(data)
-    local t = type(data)
-    return packers[t](data)
+	local t = type(data)
+	return packers[t](data)
 end
 
 packers["nil"] = function()
-    table.insert( strary, tostr(0xc0))
+	table.insert(strary, tostr(0xc0))
 end
 
 packers.boolean = function(data)
-    if data then -- pack true
-        table.insert( strary, tostr(0xc3))
-    else -- pack false
-        table.insert( strary, tostr(0xc2))
-    end
+	if data then -- pack true
+		table.insert(strary, tostr(0xc3))
+	else -- pack false
+		table.insert(strary, tostr(0xc2))
+	end
 end
 
 packers.number = function(n)
-    if math.floor(n) == n then -- integer
-        if n >= 0 then -- positive integer
-            if n < 128 then -- positive fixnum
-                table.insert( strary, tostr(n))
-            elseif n < 256 then -- uint8
-                table.insert(strary, tostr(0xcc,n))
-            elseif n < 65536 then -- uint16
-                strary_append_int16(n,0xcd)
-            elseif n < 4294967296 then -- uint32
-                strary_append_int32(n,0xce)
-            else -- lua cannot handle uint64, so double
-                strary_append_double(n)
-            end
-        else -- negative integer
-            if n >= -32 then -- negative fixnum
-                table.insert( strary, tostr( 0xe0 + ((n+256)%32)) )
-            elseif n >= -128 then -- int8
-                table.insert( strary, tostr(0xd0,byte_mod(n,0x100)))
-            elseif n >= -32768 then -- int16
-                strary_append_int16(n,0xd1)
-            elseif n >= -2147483648 then -- int32
-                strary_append_int32(n,0xd2)
-            else -- lua cannot handle int64, so double
-                strary_append_double(n)
-            end
-        end
-    else -- floating point
-        strary_append_double(n)
-    end
+	if math.floor(n) == n then -- integer
+		if n >= 0 then -- positive integer
+			if n < 128 then -- positive fixnum
+				table.insert(strary, tostr(n))
+			elseif n < 256 then -- uint8
+				table.insert(strary, tostr(0xcc, n))
+			elseif n < 65536 then -- uint16
+				strary_append_int16(n, 0xcd)
+			elseif n < 4294967296 then -- uint32
+				strary_append_int32(n, 0xce)
+			else -- lua cannot handle uint64, so double
+				strary_append_double(n)
+			end
+		else -- negative integer
+			if n >= -32 then -- negative fixnum
+				table.insert(strary, tostr(0xe0 + ((n + 256) % 32)))
+			elseif n >= -128 then -- int8
+				table.insert(strary, tostr(0xd0, byte_mod(n, 0x100)))
+			elseif n >= -32768 then -- int16
+				strary_append_int16(n, 0xd1)
+			elseif n >= -2147483648 then -- int32
+				strary_append_int32(n, 0xd2)
+			else -- lua cannot handle int64, so double
+				strary_append_double(n)
+			end
+		end
+	else -- floating point
+		strary_append_double(n)
+	end
 end
 
 packers.string = function(data)
-    local n = #data
-    if n < 32 then
-        table.insert( strary, tostr( 0xa0+n ) )
-    elseif n < 65536 then
-        strary_append_int16(n,0xda)
-    elseif n < 4294967296 then
-        strary_append_int32(n,0xdb)
-    else
-        error("overflow")
-    end
-    table.insert( strary, data)
+	local n = #data
+	if n < 32 then
+		table.insert(strary, tostr(0xa0 + n))
+	elseif n < 65536 then
+		strary_append_int16(n, 0xda)
+	elseif n < 4294967296 then
+		strary_append_int32(n, 0xdb)
+	else
+		error("overflow")
+	end
+	table.insert(strary, data)
 end
 
 packers["function"] = function()
-    error("unimplemented:function")
+	error("unimplemented:function")
 end
 
 packers.userdata = function()
-    error("unimplemented:userdata")
+	error("unimplemented:userdata")
 end
 
 packers.thread = function()
-    error("unimplemented:thread")
+	error("unimplemented:thread")
 end
 
 packers.table = function(data)
-    local is_map,ndata,nmax = false,0,0
-    for k,_ in pairs(data) do
-        if type(k) == "number" then
-            if k > nmax then nmax = k end
-        else is_map = true end
-        ndata = ndata+1
-    end
-    if is_map then -- pack as map
-        if ndata < 16 then
-            table.insert( strary, tostr(0x80+ndata))
-        elseif ndata < 65536 then
-            strary_append_int16(ndata,0xde)
-        elseif ndata < 4294967296 then
-            strary_append_int32(ndata,0xdf)
-        else
-            error("overflow")
-        end
-        for k,v in pairs(data) do
-            packers[type(k)](k)
-            packers[type(v)](v)
-        end
-    else -- pack as array
-        if nmax < 16 then
-            table.insert( strary, tostr( 0x90+nmax ) )
-        elseif nmax < 65536 then
-            strary_append_int16(nmax,0xdc)
-        elseif nmax < 4294967296 then
-            strary_append_int32(nmax,0xdd)
-        else
-            error("overflow")
-        end
-        for i=1,nmax do packers[type(data[i])](data[i]) end
-    end
+	local is_map, ndata, nmax = false, 0, 0
+	for k, _ in pairs(data) do
+		if type(k) == "number" then
+			if k > nmax then
+				nmax = k
+			end
+		else
+			is_map = true
+		end
+		ndata = ndata + 1
+	end
+	if is_map then -- pack as map
+		if ndata < 16 then
+			table.insert(strary, tostr(0x80 + ndata))
+		elseif ndata < 65536 then
+			strary_append_int16(ndata, 0xde)
+		elseif ndata < 4294967296 then
+			strary_append_int32(ndata, 0xdf)
+		else
+			error("overflow")
+		end
+		for k, v in pairs(data) do
+			packers[type(k)](k)
+			packers[type(v)](v)
+		end
+	else -- pack as array
+		if nmax < 16 then
+			table.insert(strary, tostr(0x90 + nmax))
+		elseif nmax < 65536 then
+			strary_append_int16(nmax, 0xdc)
+		elseif nmax < 4294967296 then
+			strary_append_int32(nmax, 0xdd)
+		else
+			error("overflow")
+		end
+		for i = 1, nmax do
+			packers[type(data[i])](data[i])
+		end
+	end
 end
 
 -- types decoding
 
 local types_map = {
-    [0xc0] = "nil",
-    [0xc2] = "false",
-    [0xc3] = "true",
-    [0xca] = "float",
-    [0xcb] = "double",
-    [0xcc] = "uint8",
-    [0xcd] = "uint16",
-    [0xce] = "uint32",
-    [0xcf] = "uint64",
-    [0xd0] = "int8",
-    [0xd1] = "int16",
-    [0xd2] = "int32",
-    [0xd3] = "int64",
-    [0xda] = "raw16",
-    [0xdb] = "raw32",
-    [0xdc] = "array16",
-    [0xdd] = "array32",
-    [0xde] = "map16",
-    [0xdf] = "map32",
+	[0xc0] = "nil",
+	[0xc2] = "false",
+	[0xc3] = "true",
+	[0xca] = "float",
+	[0xcb] = "double",
+	[0xcc] = "uint8",
+	[0xcd] = "uint16",
+	[0xce] = "uint32",
+	[0xcf] = "uint64",
+	[0xd0] = "int8",
+	[0xd1] = "int16",
+	[0xd2] = "int32",
+	[0xd3] = "int64",
+	[0xda] = "raw16",
+	[0xdb] = "raw32",
+	[0xdc] = "array16",
+	[0xdd] = "array32",
+	[0xde] = "map16",
+	[0xdf] = "map32",
 }
 
 local type_for = function(n)
-
-    if types_map[n] then return types_map[n]
-    elseif n < 0xc0 then
-        if n < 0x80 then return "fixnum_posi"
-        elseif n < 0x90 then return "fixmap"
-        elseif n < 0xa0 then return "fixarray"
-        else return "fixraw" end
-    elseif n > 0xdf then return "fixnum_neg"
-    else return "undefined" end
+	if types_map[n] then
+		return types_map[n]
+	elseif n < 0xc0 then
+		if n < 0x80 then
+			return "fixnum_posi"
+		elseif n < 0x90 then
+			return "fixmap"
+		elseif n < 0xa0 then
+			return "fixarray"
+		else
+			return "fixraw"
+		end
+	elseif n > 0xdf then
+		return "fixnum_neg"
+	else
+		return "undefined"
+	end
 end
 
 local types_len_map = {
-    uint16 = 2, uint32 = 4, uint64 = 8,
-    int16 = 2, int32 = 4, int64 = 8,
-    float = 4, double = 8,
+	uint16 = 2,
+	uint32 = 4,
+	uint64 = 8,
+	int16 = 2,
+	int32 = 4,
+	int64 = 8,
+	float = 4,
+	double = 8,
 }
 
-
-
-
 --- unpackers
 
 local unpackers = {}
 
-local unpack_number = function(offset,ntype,nlen)
-    local b1,b2,b3,b4,b5,b6,b7,b8
-    if nlen>=2 then
-        b1,b2 = string.byte( strbuf, offset+1, offset+2 )
-    end
-    if nlen>=4 then
-        b3,b4 = string.byte( strbuf, offset+3, offset+4 )
-    end
-    if nlen>=8 then
-        b5,b6,b7,b8 = string.byte( strbuf, offset+5, offset+8 )
-    end
+local unpack_number = function(offset, ntype, nlen)
+	local b1, b2, b3, b4, b5, b6, b7, b8
+	if nlen >= 2 then
+		b1, b2 = string.byte(strbuf, offset + 1, offset + 2)
+	end
+	if nlen >= 4 then
+		b3, b4 = string.byte(strbuf, offset + 3, offset + 4)
+	end
+	if nlen >= 8 then
+		b5, b6, b7, b8 = string.byte(strbuf, offset + 5, offset + 8)
+	end
 
-    if ntype == "uint16_t" then
-        return b1 * 256 + b2
-    elseif ntype == "uint32_t" then
-        return b1*65536*256 + b2*65536 + b3 * 256 + b4
-    elseif ntype == "int16_t" then
-        local n = b1 * 256 + b2
-        local nn = (65536 - n)*-1
-        if nn == -65536 then nn = 0 end
-        return nn
-    elseif ntype == "int32_t" then
-        local n = b1*65536*256 + b2*65536 + b3 * 256 + b4
-        local nn = ( 4294967296 - n ) * -1
-        if nn == -4294967296 then nn = 0 end
-        return nn
-    elseif ntype == "double_t" then
-        local s = tostr(b8,b7,b6,b5,b4,b3,b2,b1)
-        double_decode_count = double_decode_count + 1
-        local n = bytestodouble( s )
-        return n
-    else
-        error("unpack_number: not impl:" .. ntype )
-    end
+	if ntype == "uint16_t" then
+		return b1 * 256 + b2
+	elseif ntype == "uint32_t" then
+		return b1 * 65536 * 256 + b2 * 65536 + b3 * 256 + b4
+	elseif ntype == "int16_t" then
+		local n = b1 * 256 + b2
+		local nn = (65536 - n) * -1
+		if nn == -65536 then
+			nn = 0
+		end
+		return nn
+	elseif ntype == "int32_t" then
+		local n = b1 * 65536 * 256 + b2 * 65536 + b3 * 256 + b4
+		local nn = (4294967296 - n) * -1
+		if nn == -4294967296 then
+			nn = 0
+		end
+		return nn
+	elseif ntype == "double_t" then
+		local s = tostr(b8, b7, b6, b5, b4, b3, b2, b1)
+		double_decode_count = double_decode_count + 1
+		local n = bytestodouble(s)
+		return n
+	else
+		error("unpack_number: not impl:" .. ntype)
+	end
 end
 
-
-
 local function unpacker_number(offset)
-    local obj_type = type_for( string.byte( strbuf, offset+1, offset+1 ) )
-    local nlen = types_len_map[obj_type]
-    local ntype
-    if (obj_type == "float") then
-        error("float is not implemented")
-    else
-        ntype = obj_type .. "_t"
-    end
-    return offset+nlen+1,unpack_number(offset+1,ntype,nlen)
+	local obj_type = type_for(string.byte(strbuf, offset + 1, offset + 1))
+	local nlen = types_len_map[obj_type]
+	local ntype
+	if obj_type == "float" then
+		error("float is not implemented")
+	else
+		ntype = obj_type .. "_t"
+	end
+	return offset + nlen + 1, unpack_number(offset + 1, ntype, nlen)
 end
 
-local function unpack_map(offset,n)
-    local r = {}
-    local k,v
-    for _ = 1, n do
-        offset,k = unpackers.dynamic(offset)
-        assert(offset)
-        offset,v = unpackers.dynamic(offset)
-        assert(offset)
-        r[k] = v
-    end
-    return offset,r
+local function unpack_map(offset, n)
+	local r = {}
+	local k, v
+	for _ = 1, n do
+		offset, k = unpackers.dynamic(offset)
+		assert(offset)
+		offset, v = unpackers.dynamic(offset)
+		assert(offset)
+		r[k] = v
+	end
+	return offset, r
 end
 
-local function unpack_array(offset,n)
-    local r = {}
-    for i=1,n do
-        offset,r[i] = unpackers.dynamic(offset)
-        assert(offset)
-    end
-    return offset,r
+local function unpack_array(offset, n)
+	local r = {}
+	for i = 1, n do
+		offset, r[i] = unpackers.dynamic(offset)
+		assert(offset)
+	end
+	return offset, r
 end
 
 function unpackers.dynamic(offset)
-    if offset >= #strbuf then error("need more data") end
-    local obj_type = type_for( string.byte( strbuf, offset+1, offset+1 ) )
-    return unpackers[obj_type](offset)
+	if offset >= #strbuf then
+		error("need more data")
+	end
+	local obj_type = type_for(string.byte(strbuf, offset + 1, offset + 1))
+	return unpackers[obj_type](offset)
 end
 
 function unpackers.undefined()
-    error("unimplemented:undefined")
+	error("unimplemented:undefined")
 end
 
 unpackers["nil"] = function(offset)
-    return offset+1,nil
+	return offset + 1, nil
 end
 
 unpackers["false"] = function(offset)
-    return offset+1,false
+	return offset + 1, false
 end
 
 unpackers["true"] = function(offset)
-    return offset+1,true
+	return offset + 1, true
 end
 
 unpackers.fixnum_posi = function(offset)
-    return offset+1, string.byte(strbuf, offset+1, offset+1)
+	return offset + 1, string.byte(strbuf, offset + 1, offset + 1)
 end
 
 unpackers.uint8 = function(offset)
-    return offset+2, string.byte(strbuf, offset+2, offset+2)
+	return offset + 2, string.byte(strbuf, offset + 2, offset + 2)
 end
 
 unpackers.uint16 = unpacker_number
@@ -396,18 +436,18 @@ unpackers.uint32 = unpacker_number
 unpackers.uint64 = unpacker_number
 
 unpackers.fixnum_neg = function(offset)
-    -- alternative to cast below:
-    local n = string.byte( strbuf, offset+1, offset+1)
-    local nn = ( 256 - n ) * -1
-    return offset+1,  nn
+	-- alternative to cast below:
+	local n = string.byte(strbuf, offset + 1, offset + 1)
+	local nn = (256 - n) * -1
+	return offset + 1, nn
 end
 
 unpackers.int8 = function(offset)
-    local i = string.byte( strbuf, offset+2, offset+2 )
-    if i > 127 then
-        i = (256 - i ) * -1
-    end
-    return offset+2, i
+	local i = string.byte(strbuf, offset + 2, offset + 2)
+	if i > 127 then
+		i = (256 - i) * -1
+	end
+	return offset + 2, i
 end
 
 unpackers.int16 = unpacker_number
@@ -418,92 +458,96 @@ unpackers.float = unpacker_number
 unpackers.double = unpacker_number
 
 unpackers.fixraw = function(offset)
-    local n = byte_mod( string.byte( strbuf, offset+1, offset+1) ,0x1f+1)
-    --  print("unpackers.fixraw: offset:", offset, "#buf:", #buf, "n:",n  )
-    local b
-    if ( #strbuf - 1 - offset ) < n then
-        error("require more data")
-    end
+	local n = byte_mod(string.byte(strbuf, offset + 1, offset + 1), 0x1f + 1)
+	--  print("unpackers.fixraw: offset:", offset, "#buf:", #buf, "n:",n  )
+	local b
+	if (#strbuf - 1 - offset) < n then
+		error("require more data")
+	end
 
-    if n > 0 then
-        b = string.sub( strbuf, offset + 1 + 1, offset + 1 + 1 + n - 1 )
-    else
-        b = ""
-    end
-    return offset+n+1, b
+	if n > 0 then
+		b = string.sub(strbuf, offset + 1 + 1, offset + 1 + 1 + n - 1)
+	else
+		b = ""
+	end
+	return offset + n + 1, b
 end
 
 unpackers.raw16 = function(offset)
-    local n = unpack_number(offset+1,"uint16_t",2)
-    if ( #strbuf - 1 - 2 - offset ) < n then
-        error("require more data")
-    end
-    local b = string.sub( strbuf, offset+1+1+2, offset+1 + 1+2 + n - 1 )
-    return offset+n+3, b
+	local n = unpack_number(offset + 1, "uint16_t", 2)
+	if (#strbuf - 1 - 2 - offset) < n then
+		error("require more data")
+	end
+	local b = string.sub(strbuf, offset + 1 + 1 + 2, offset + 1 + 1 + 2 + n - 1)
+	return offset + n + 3, b
 end
 
 unpackers.raw32 = function(offset)
-    local n = unpack_number(offset+1,"uint32_t",4)
-    if ( #strbuf  - 1 - 4 - offset ) < n then
-        error( "require more data (possibly bug)")
-    end
-    local b = string.sub( strbuf, offset+1+ 1+4, offset+1 + 1+4 +n -1 )
-    return offset+n+5,b
+	local n = unpack_number(offset + 1, "uint32_t", 4)
+	if (#strbuf - 1 - 4 - offset) < n then
+		error("require more data (possibly bug)")
+	end
+	local b = string.sub(strbuf, offset + 1 + 1 + 4, offset + 1 + 1 + 4 + n - 1)
+	return offset + n + 5, b
 end
 
 unpackers.fixarray = function(offset)
-    return unpack_array( offset+1,byte_mod( string.byte( strbuf, offset+1,offset+1),0x0f+1))
+	return unpack_array(offset + 1, byte_mod(string.byte(strbuf, offset + 1, offset + 1), 0x0f + 1))
 end
 
 unpackers.array16 = function(offset)
-    return unpack_array(offset+3,unpack_number(offset+1,"uint16_t",2))
+	return unpack_array(offset + 3, unpack_number(offset + 1, "uint16_t", 2))
 end
 
 unpackers.array32 = function(offset)
-    return unpack_array(offset+5,unpack_number(offset+1,"uint32_t",4))
+	return unpack_array(offset + 5, unpack_number(offset + 1, "uint32_t", 4))
 end
 
 unpackers.fixmap = function(offset)
-    return unpack_map(offset+1,byte_mod( string.byte( strbuf, offset+1,offset+1),0x0f+1))
+	return unpack_map(offset + 1, byte_mod(string.byte(strbuf, offset + 1, offset + 1), 0x0f + 1))
 end
 
 unpackers.map16 = function(offset)
-    return unpack_map(offset+3,unpack_number(offset+1,"uint16_t",2))
+	return unpack_map(offset + 3, unpack_number(offset + 1, "uint16_t", 2))
 end
 
 unpackers.map32 = function(offset)
-    return unpack_map(offset+5,unpack_number(offset+1,"uint32_t",4))
+	return unpack_map(offset + 5, unpack_number(offset + 1, "uint32_t", 4))
 end
 
 -- Main functions
 
 local ljp_pack = function(data)
-    strary={}
-    packers.dynamic(data)
-    local s = table.concat(strary,"")
-    return s
+	strary = {}
+	packers.dynamic(data)
+	local s = table.concat(strary, "")
+	return s
 end
 
-local ljp_unpack = function(s,offset)
-    if offset == nil then offset = 0 end
-    if type(s) ~= "string" then return false,"invalid argument" end
-    local data
-    strbuf = s
-    offset,data = unpackers.dynamic(offset)
-    return offset,data
+local ljp_unpack = function(s, offset)
+	if offset == nil then
+		offset = 0
+	end
+	if type(s) ~= "string" then
+		return false, "invalid argument"
+	end
+	local data
+	strbuf = s
+	offset, data = unpackers.dynamic(offset)
+	return offset, data
 end
 
 local function ljp_stat()
-    return {
-        double_decode_count = double_decode_count,
-        double_encode_count = double_encode_count
-    }
+	return {
+		double_decode_count = double_decode_count,
+		double_encode_count = double_encode_count,
+	}
 end
 
 local msgpack = {
-    pack = ljp_pack,
-    unpack = ljp_unpack,
-    stat = ljp_stat
+	pack = ljp_pack,
+	unpack = ljp_unpack,
+	stat = ljp_stat,
 }
 
 return msgpack
diff --git a/lua/deps/serpent.lua b/lua/deps/serpent.lua
index a043713..4503686 100644
--- a/lua/deps/serpent.lua
+++ b/lua/deps/serpent.lua
@@ -1,140 +1,265 @@
 local n, v = "serpent", "0.302" -- (C) 2012-18 Paul Kulchenko; MIT License
 local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
-local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
-local badtype = {thread = true, userdata = true, cdata = true}
+local snum = {
+	[tostring(1 / 0)] = "1/0 --[[math.huge]]",
+	[tostring(-1 / 0)] = "-1/0 --[[-math.huge]]",
+	[tostring(0 / 0)] = "0/0",
+}
+local badtype = { thread = true, userdata = true, cdata = true }
 local getmetatable = debug and debug.getmetatable or getmetatable
-local pairs = function(t) return next, t end -- avoid using __pairs in Lua 5.2+
+local pairs = function(t)
+	return next, t
+end -- avoid using __pairs in Lua 5.2+
 local keyword, globals, G = {}, {}, (_G or _ENV)
-for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
-  'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
-  'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end
-for k,v in pairs(G) do globals[v] = k end -- build func to name mapping
-for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do
-  for k,v in pairs(type(G[g]) == 'table' and G[g] or {}) do globals[v] = g..'.'..k end end
+for _, k in ipairs({
+	"and",
+	"break",
+	"do",
+	"else",
+	"elseif",
+	"end",
+	"false",
+	"for",
+	"function",
+	"goto",
+	"if",
+	"in",
+	"local",
+	"nil",
+	"not",
+	"or",
+	"repeat",
+	"return",
+	"then",
+	"true",
+	"until",
+	"while",
+}) do
+	keyword[k] = true
+end
+for k, v in pairs(G) do
+	globals[v] = k
+end -- build func to name mapping
+for _, g in ipairs({ "coroutine", "debug", "io", "math", "string", "table", "os" }) do
+	for k, v in pairs(type(G[g]) == "table" and G[g] or {}) do
+		globals[v] = g .. "." .. k
+	end
+end
 
 local function s(t, opts)
-  local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
-  local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
-  local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
-  local maxlen, metatostring = tonumber(opts.maxlength), opts.metatostring
-  local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
-  local numformat = opts.numformat or "%.17g"
-  local seen, sref, syms, symn = {}, {'local '..iname..'={}'}, {}, 0
-  local function gensym(val) return '_'..(tostring(tostring(val)):gsub("[^%w]",""):gsub("(%d%w+)",
-    -- tostring(val) is needed because __tostring may return a non-string value
-    function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return tostring(syms[s]) end)) end
-  local function safestr(s) return type(s) == "number" and tostring(huge and snum[tostring(s)] or numformat:format(s))
-    or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
-    or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
-  local function comment(s,l) return comm and (l or 0) < comm and ' --[['..select(2, pcall(tostring, s))..']]' or '' end
-  local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
-    and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
-  local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
-    local n = name == nil and '' or name
-    local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
-    local safe = plain and n or '['..safestr(n)..']'
-    return (path or '')..(plain and path and '.' or '')..safe, safe end
-  local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding
-    local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
-    local function padnum(d) return ("%0"..tostring(maxn).."d"):format(tonumber(d)) end
-    table.sort(k, function(a,b)
-      -- sort numeric keys first: k[key] is not nil for numerical keys
-      return (k[a] ~= nil and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
-           < (k[b] ~= nil and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
-  local function val2str(t, name, indent, insref, path, plainindex, level)
-    local ttype, level, mt = type(t), (level or 0), getmetatable(t)
-    local spath, sname = safename(path, name)
-    local tag = plainindex and
-      ((type(name) == "number") and '' or name..space..'='..space) or
-      (name ~= nil and sname..space..'='..space or '')
-    if seen[t] then -- already seen this element
-      sref[#sref+1] = spath..space..'='..space..seen[t]
-      return tag..'nil'..comment('ref', level) end
-    -- protect from those cases where __tostring may fail
-    if type(mt) == 'table' and metatostring ~= false then
-      local to, tr = pcall(function() return mt.__tostring(t) end)
-      local so, sr = pcall(function() return mt.__serialize(t) end)
-      if (to or so) then -- knows how to serialize itself
-        seen[t] = insref or spath
-        t = so and sr or tr
-        ttype = type(t)
-      end -- new value falls through to be serialized
-    end
-    if ttype == "table" then
-      if level >= maxl then return tag..'{}'..comment('maxlvl', level) end
-      seen[t] = insref or spath
-      if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
-      if maxlen and maxlen < 0 then return tag..'{}'..comment('maxlen', level) end
-      local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
-      for key = 1, maxn do o[key] = key end
-      if not maxnum or #o < maxnum then
-        local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
-        for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end end
-      if maxnum and #o > maxnum then o[maxnum+1] = nil end
-      if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end
-      local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
-      for n, key in ipairs(o) do
-        local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
-        if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
-        or opts.keyallow and not opts.keyallow[key]
-        or opts.keyignore and opts.keyignore[key]
-        or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
-        or sparse and value == nil then -- skipping nils; do nothing
-        elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
-          if not seen[key] and not globals[key] then
-            sref[#sref+1] = 'placeholder'
-            local sname = safename(iname, gensym(key)) -- iname is table for local variables
-            sref[#sref] = val2str(key,sname,indent,sname,iname,true) end
-          sref[#sref+1] = 'placeholder'
-          local path = seen[t]..'['..tostring(seen[key] or globals[key] or gensym(key))..']'
-          sref[#sref] = path..space..'='..space..tostring(seen[value] or val2str(value,nil,indent,path))
-        else
-          out[#out+1] = val2str(value,key,indent,nil,seen[t],plainindex,level+1)
-          if maxlen then
-            maxlen = maxlen - #out[#out]
-            if maxlen < 0 then break end
-          end
-        end
-      end
-      local prefix = string.rep(indent or '', level)
-      local head = indent and '{\n'..prefix..indent or '{'
-      local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
-      local tail = indent and "\n"..prefix..'}' or '}'
-      return (custom and custom(tag,head,body,tail,level) or tag..head..body..tail)..comment(t, level)
-    elseif badtype[ttype] then
-      seen[t] = insref or spath
-      return tag..globerr(t, level)
-    elseif ttype == 'function' then
-      seen[t] = insref or spath
-      if opts.nocode then return tag.."function() --[[..skipped..]] end"..comment(t, level) end
-      local ok, res = pcall(string.dump, t)
-      local func = ok and "((loadstring or load)("..safestr(res)..",'@serialized'))"..comment(t, level)
-      return tag..(func or globerr(t, level))
-    else return tag..safestr(t) end -- handle all other types
-  end
-  local sepr = indent and "\n" or ";"..space
-  local body = val2str(t, name, indent) -- this call also populates sref
-  local tail = #sref>1 and table.concat(sref, sepr)..sepr or ''
-  local warn = opts.comment and #sref>1 and space.."--[[incomplete output with shared/self-references skipped]]" or ''
-  return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end"
+	local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
+	local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
+	local space, maxl = (opts.compact and "" or " "), (opts.maxlevel or math.huge)
+	local maxlen, metatostring = tonumber(opts.maxlength), opts.metatostring
+	local iname, comm = "_" .. (name or ""), opts.comment and (tonumber(opts.comment) or math.huge)
+	local numformat = opts.numformat or "%.17g"
+	local seen, sref, syms, symn = {}, { "local " .. iname .. "={}" }, {}, 0
+	local function gensym(val)
+		return "_"
+			.. (
+				tostring(tostring(val)):gsub("[^%w]", ""):gsub(
+					"(%d%w+)",
+					-- tostring(val) is needed because __tostring may return a non-string value
+					function(s)
+						if not syms[s] then
+							symn = symn + 1
+							syms[s] = symn
+						end
+						return tostring(syms[s])
+					end
+				)
+			)
+	end
+	local function safestr(s)
+		return type(s) == "number" and tostring(huge and snum[tostring(s)] or numformat:format(s))
+			or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
+			or ("%q"):format(s):gsub("\010", "n"):gsub("\026", "\\026")
+	end
+	local function comment(s, l)
+		return comm and (l or 0) < comm and " --[[" .. select(2, pcall(tostring, s)) .. "]]" or ""
+	end
+	local function globerr(s, l)
+		return globals[s] and globals[s] .. comment(s, l)
+			or not fatal and safestr(select(2, pcall(tostring, s)))
+			or error("Can't serialize " .. tostring(s))
+	end
+	local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
+		local n = name == nil and "" or name
+		local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
+		local safe = plain and n or "[" .. safestr(n) .. "]"
+		return (path or "") .. (plain and path and "." or "") .. safe, safe
+	end
+	local alphanumsort = type(opts.sortkeys) == "function" and opts.sortkeys
+		or function(k, o, n) -- k=keys, o=originaltable, n=padding
+			local maxn, to = tonumber(n) or 12, { number = "a", string = "b" }
+			local function padnum(d)
+				return ("%0" .. tostring(maxn) .. "d"):format(tonumber(d))
+			end
+			table.sort(k, function(a, b)
+				-- sort numeric keys first: k[key] is not nil for numerical keys
+				return (k[a] ~= nil and 0 or to[type(a)] or "z") .. (tostring(a):gsub("%d+", padnum))
+					< (k[b] ~= nil and 0 or to[type(b)] or "z") .. (tostring(b):gsub("%d+", padnum))
+			end)
+		end
+	local function val2str(t, name, indent, insref, path, plainindex, level)
+		local ttype, level, mt = type(t), (level or 0), getmetatable(t)
+		local spath, sname = safename(path, name)
+		local tag = plainindex and ((type(name) == "number") and "" or name .. space .. "=" .. space)
+			or (name ~= nil and sname .. space .. "=" .. space or "")
+		if seen[t] then -- already seen this element
+			sref[#sref + 1] = spath .. space .. "=" .. space .. seen[t]
+			return tag .. "nil" .. comment("ref", level)
+		end
+		-- protect from those cases where __tostring may fail
+		if type(mt) == "table" and metatostring ~= false then
+			local to, tr = pcall(function()
+				return mt.__tostring(t)
+			end)
+			local so, sr = pcall(function()
+				return mt.__serialize(t)
+			end)
+			if to or so then -- knows how to serialize itself
+				seen[t] = insref or spath
+				t = so and sr or tr
+				ttype = type(t)
+			end -- new value falls through to be serialized
+		end
+		if ttype == "table" then
+			if level >= maxl then
+				return tag .. "{}" .. comment("maxlvl", level)
+			end
+			seen[t] = insref or spath
+			if next(t) == nil then
+				return tag .. "{}" .. comment(t, level)
+			end -- table empty
+			if maxlen and maxlen < 0 then
+				return tag .. "{}" .. comment("maxlen", level)
+			end
+			local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
+			for key = 1, maxn do
+				o[key] = key
+			end
+			if not maxnum or #o < maxnum then
+				local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
+				for key in pairs(t) do
+					if o[key] ~= key then
+						n = n + 1
+						o[n] = key
+					end
+				end
+			end
+			if maxnum and #o > maxnum then
+				o[maxnum + 1] = nil
+			end
+			if opts.sortkeys and #o > maxn then
+				alphanumsort(o, t, opts.sortkeys)
+			end
+			local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
+			for n, key in ipairs(o) do
+				local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
+				if
+					opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
+					or opts.keyallow and not opts.keyallow[key]
+					or opts.keyignore and opts.keyignore[key]
+					or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
+					or sparse and value == nil
+				then -- skipping nils; do nothing
+				elseif ktype == "table" or ktype == "function" or badtype[ktype] then
+					if not seen[key] and not globals[key] then
+						sref[#sref + 1] = "placeholder"
+						local sname = safename(iname, gensym(key)) -- iname is table for local variables
+						sref[#sref] = val2str(key, sname, indent, sname, iname, true)
+					end
+					sref[#sref + 1] = "placeholder"
+					local path = seen[t] .. "[" .. tostring(seen[key] or globals[key] or gensym(key)) .. "]"
+					sref[#sref] = path
+						.. space
+						.. "="
+						.. space
+						.. tostring(seen[value] or val2str(value, nil, indent, path))
+				else
+					out[#out + 1] = val2str(value, key, indent, nil, seen[t], plainindex, level + 1)
+					if maxlen then
+						maxlen = maxlen - #out[#out]
+						if maxlen < 0 then
+							break
+						end
+					end
+				end
+			end
+			local prefix = string.rep(indent or "", level)
+			local head = indent and "{\n" .. prefix .. indent or "{"
+			local body = table.concat(out, "," .. (indent and "\n" .. prefix .. indent or space))
+			local tail = indent and "\n" .. prefix .. "}" or "}"
+			return (custom and custom(tag, head, body, tail, level) or tag .. head .. body .. tail) .. comment(t, level)
+		elseif badtype[ttype] then
+			seen[t] = insref or spath
+			return tag .. globerr(t, level)
+		elseif ttype == "function" then
+			seen[t] = insref or spath
+			if opts.nocode then
+				return tag .. "function() --[[..skipped..]] end" .. comment(t, level)
+			end
+			local ok, res = pcall(string.dump, t)
+			local func = ok and "((loadstring or load)(" .. safestr(res) .. ",'@serialized'))" .. comment(t, level)
+			return tag .. (func or globerr(t, level))
+		else
+			return tag .. safestr(t)
+		end -- handle all other types
+	end
+	local sepr = indent and "\n" or ";" .. space
+	local body = val2str(t, name, indent) -- this call also populates sref
+	local tail = #sref > 1 and table.concat(sref, sepr) .. sepr or ""
+	local warn = opts.comment and #sref > 1 and space .. "--[[incomplete output with shared/self-references skipped]]"
+		or ""
+	return not name and body .. warn or "do local " .. body .. sepr .. tail .. "return " .. name .. sepr .. "end"
 end
 
 local function deserialize(data, opts)
-  local env = (opts and opts.safe == false) and G
-    or setmetatable({}, {
-        __index = function(t,k) return t end,
-        __call = function(t,...) error("cannot call functions") end
-      })
-  local f, res = (loadstring or load)('return '..data, nil, nil, env)
-  if not f then f, res = (loadstring or load)(data, nil, nil, env) end
-  if not f then return f, res end
-  if setfenv then setfenv(f, env) end
-  return pcall(f)
+	local env = (opts and opts.safe == false) and G
+		or setmetatable({}, {
+			__index = function(t, k)
+				return t
+			end,
+			__call = function(t, ...)
+				error("cannot call functions")
+			end,
+		})
+	local f, res = (loadstring or load)("return " .. data, nil, nil, env)
+	if not f then
+		f, res = (loadstring or load)(data, nil, nil, env)
+	end
+	if not f then
+		return f, res
+	end
+	if setfenv then
+		setfenv(f, env)
+	end
+	return pcall(f)
 end
 
-local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
-return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
-  load = deserialize,
-  dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
-  line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
-  block = function(a, opts) return s(a, merge({indent = '  ', sortkeys = true, comment = true}, opts)) end }
+local function merge(a, b)
+	if b then
+		for k, v in pairs(b) do
+			a[k] = v
+		end
+	end
+	return a
+end
+return {
+	_NAME = n,
+	_COPYRIGHT = c,
+	_DESCRIPTION = d,
+	_VERSION = v,
+	serialize = s,
+	load = deserialize,
+	dump = function(a, opts)
+		return s(a, merge({ name = "_", compact = true, sparse = true }, opts))
+	end,
+	line = function(a, opts)
+		return s(a, merge({ sortkeys = true, comment = true }, opts))
+	end,
+	block = function(a, opts)
+		return s(a, merge({ indent = "  ", sortkeys = true, comment = true }, opts))
+	end,
+}
diff --git a/lua/deps/struct.lua b/lua/deps/struct.lua
index 54b32d4..1b0e814 100644
--- a/lua/deps/struct.lua
+++ b/lua/deps/struct.lua
@@ -1,179 +1,178 @@
 local struct = {}
 
 function struct.pack(format, ...)
-    local stream = {}
-    local vars = {...}
-    local endianness = true
+	local stream = {}
+	local vars = { ... }
+	local endianness = true
 
-    for i = 1, format:len() do
-        local opt = format:sub(i, i)
+	for i = 1, format:len() do
+		local opt = format:sub(i, i)
 
-        if opt == '<' then
-            endianness = true
-        elseif opt == '>' then
-            endianness = false
-        elseif opt:find('[bBhHiIlL]') then
-            local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
-            local val = tonumber(table.remove(vars, 1))
+		if opt == "<" then
+			endianness = true
+		elseif opt == ">" then
+			endianness = false
+		elseif opt:find("[bBhHiIlL]") then
+			local n = opt:find("[hH]") and 2 or opt:find("[iI]") and 4 or opt:find("[lL]") and 8 or 1
+			local val = tonumber(table.remove(vars, 1))
 
-            local bytes = {}
-            for _ = 1, n do
-                table.insert(bytes, string.char(val % (2 ^ 8)))
-                val = math.floor(val / (2 ^ 8))
-            end
+			local bytes = {}
+			for _ = 1, n do
+				table.insert(bytes, string.char(val % (2 ^ 8)))
+				val = math.floor(val / (2 ^ 8))
+			end
 
-            if not endianness then
-                table.insert(stream, string.reverse(table.concat(bytes)))
-            else
-                table.insert(stream, table.concat(bytes))
-            end
-        elseif opt:find('[fd]') then
-            local val = tonumber(table.remove(vars, 1))
-            local sign = 0
+			if not endianness then
+				table.insert(stream, string.reverse(table.concat(bytes)))
+			else
+				table.insert(stream, table.concat(bytes))
+			end
+		elseif opt:find("[fd]") then
+			local val = tonumber(table.remove(vars, 1))
+			local sign = 0
 
-            if val < 0 then
-                sign = 1
-                val = -val
-            end
+			if val < 0 then
+				sign = 1
+				val = -val
+			end
 
-            local mantissa, exponent = math.frexp(val)
-            if val == 0 then
-                mantissa = 0
-                exponent = 0
-            else
-                mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24)
-                exponent = exponent + ((opt == 'd') and 1022 or 126)
-            end
+			local mantissa, exponent = math.frexp(val)
+			if val == 0 then
+				mantissa = 0
+				exponent = 0
+			else
+				mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == "d") and 53 or 24)
+				exponent = exponent + ((opt == "d") and 1022 or 126)
+			end
 
-            local bytes = {}
-            if opt == 'd' then
-                val = mantissa
-                for _ = 1, 6 do
-                    table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
-                    val = math.floor(val / (2 ^ 8))
-                end
-            else
-                table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
-                val = math.floor(mantissa / (2 ^ 8))
-                table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
-                val = math.floor(val / (2 ^ 8))
-            end
+			local bytes = {}
+			if opt == "d" then
+				val = mantissa
+				for _ = 1, 6 do
+					table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
+					val = math.floor(val / (2 ^ 8))
+				end
+			else
+				table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
+				val = math.floor(mantissa / (2 ^ 8))
+				table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
+				val = math.floor(val / (2 ^ 8))
+			end
 
-            table.insert(bytes, string.char(math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8)))
-            val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8))
-            table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
+			table.insert(bytes, string.char(math.floor(exponent * ((opt == "d") and 16 or 128) + val) % (2 ^ 8)))
+			val = math.floor((exponent * ((opt == "d") and 16 or 128) + val) / (2 ^ 8))
+			table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
 
-            if not endianness then
-                table.insert(stream, string.reverse(table.concat(bytes)))
-            else
-                table.insert(stream, table.concat(bytes))
-            end
-        elseif opt == 's' then
-            table.insert(stream, tostring(table.remove(vars, 1)))
-            table.insert(stream, string.char(0))
-        elseif opt == 'c' then
-            local n = format:sub(i + 1):match('%d+')
-            local str = tostring(table.remove(vars, 1))
-            local len = tonumber(n)
-            if len <= 0 then
-                len = str:len()
-            end
-            if len - str:len() > 0 then
-                str = str .. string.rep(' ', len - str:len())
-            end
-            table.insert(stream, str:sub(1, len))
-        end
-    end
+			if not endianness then
+				table.insert(stream, string.reverse(table.concat(bytes)))
+			else
+				table.insert(stream, table.concat(bytes))
+			end
+		elseif opt == "s" then
+			table.insert(stream, tostring(table.remove(vars, 1)))
+			table.insert(stream, string.char(0))
+		elseif opt == "c" then
+			local n = format:sub(i + 1):match("%d+")
+			local str = tostring(table.remove(vars, 1))
+			local len = tonumber(n)
+			if len <= 0 then
+				len = str:len()
+			end
+			if len - str:len() > 0 then
+				str = str .. string.rep(" ", len - str:len())
+			end
+			table.insert(stream, str:sub(1, len))
+		end
+	end
 
-    return table.concat(stream)
+	return table.concat(stream)
 end
 
 function struct.unpack(format, stream, pos)
-    local vars = {}
-    local iterator = pos or 1
-    local endianness = true
+	local vars = {}
+	local iterator = pos or 1
+	local endianness = true
 
-    for i = 1, format:len() do
-        local opt = format:sub(i, i)
+	for i = 1, format:len() do
+		local opt = format:sub(i, i)
 
-        if opt == '<' then
-            endianness = true
-        elseif opt == '>' then
-            endianness = false
-        elseif opt:find('[bBhHiIlL]') then
-            local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
-            local signed = opt:lower() == opt
+		if opt == "<" then
+			endianness = true
+		elseif opt == ">" then
+			endianness = false
+		elseif opt:find("[bBhHiIlL]") then
+			local n = opt:find("[hH]") and 2 or opt:find("[iI]") and 4 or opt:find("[lL]") and 8 or 1
+			local signed = opt:lower() == opt
 
-            local val = 0
-            for j = 1, n do
-                local byte = string.byte(stream:sub(iterator, iterator))
-                if endianness then
-                    val = val + byte * (2 ^ ((j - 1) * 8))
-                else
-                    val = val + byte * (2 ^ ((n - j) * 8))
-                end
-                iterator = iterator + 1
-            end
+			local val = 0
+			for j = 1, n do
+				local byte = string.byte(stream:sub(iterator, iterator))
+				if endianness then
+					val = val + byte * (2 ^ ((j - 1) * 8))
+				else
+					val = val + byte * (2 ^ ((n - j) * 8))
+				end
+				iterator = iterator + 1
+			end
 
-            if signed and val >= 2 ^ (n * 8 - 1) then
-                val = val - 2 ^ (n * 8)
-            end
+			if signed and val >= 2 ^ (n * 8 - 1) then
+				val = val - 2 ^ (n * 8)
+			end
 
-            table.insert(vars, math.floor(val))
-        elseif opt:find('[fd]') then
-            local n = (opt == 'd') and 8 or 4
-            local x = stream:sub(iterator, iterator + n - 1)
-            iterator = iterator + n
+			table.insert(vars, math.floor(val))
+		elseif opt:find("[fd]") then
+			local n = (opt == "d") and 8 or 4
+			local x = stream:sub(iterator, iterator + n - 1)
+			iterator = iterator + n
 
-            if not endianness then
-                x = string.reverse(x)
-            end
+			if not endianness then
+				x = string.reverse(x)
+			end
 
-            local sign = 1
-            local mantissa = string.byte(x, (opt == 'd') and 7 or 3) % ((opt == 'd') and 16 or 128)
-            for j = n - 2, 1, -1 do
-                mantissa = mantissa * (2 ^ 8) + string.byte(x, j)
-            end
+			local sign = 1
+			local mantissa = string.byte(x, (opt == "d") and 7 or 3) % ((opt == "d") and 16 or 128)
+			for j = n - 2, 1, -1 do
+				mantissa = mantissa * (2 ^ 8) + string.byte(x, j)
+			end
 
-            if string.byte(x, n) > 127 then
-                sign = -1
-            end
+			if string.byte(x, n) > 127 then
+				sign = -1
+			end
 
-            local exponent = (string.byte(x, n) % 128) * ((opt == 'd') and 16 or 2) +
-                math.floor(string.byte(x, n - 1) /
-                ((opt == 'd') and 16 or 128))
-            if exponent == 0 then
-                table.insert(vars, 0.0)
-            else
-                mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign
-                table.insert(vars, math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127)))
-            end
-        elseif opt == 's' then
-            local bytes = {}
-            for j = iterator, stream:len() do
-                if stream:sub(j,j) == string.char(0) or  stream:sub(j) == '' then
-                    break
-                end
+			local exponent = (string.byte(x, n) % 128) * ((opt == "d") and 16 or 2)
+				+ math.floor(string.byte(x, n - 1) / ((opt == "d") and 16 or 128))
+			if exponent == 0 then
+				table.insert(vars, 0.0)
+			else
+				mantissa = (math.ldexp(mantissa, (opt == "d") and -52 or -23) + 1) * sign
+				table.insert(vars, math.ldexp(mantissa, exponent - ((opt == "d") and 1023 or 127)))
+			end
+		elseif opt == "s" then
+			local bytes = {}
+			for j = iterator, stream:len() do
+				if stream:sub(j, j) == string.char(0) or stream:sub(j) == "" then
+					break
+				end
 
-                table.insert(bytes, stream:sub(j, j))
-            end
+				table.insert(bytes, stream:sub(j, j))
+			end
 
-            local str = table.concat(bytes)
-            iterator = iterator + str:len() + 1
-            table.insert(vars, str)
-        elseif opt == 'c' then
-            local n = format:sub(i + 1):match('%d+')
-            local len = tonumber(n)
-            if len <= 0 then
-                len = table.remove(vars)
-            end
+			local str = table.concat(bytes)
+			iterator = iterator + str:len() + 1
+			table.insert(vars, str)
+		elseif opt == "c" then
+			local n = format:sub(i + 1):match("%d+")
+			local len = tonumber(n)
+			if len <= 0 then
+				len = table.remove(vars)
+			end
 
-            table.insert(vars, stream:sub(iterator, iterator + len - 1))
-            iterator = iterator + len
-        end
-    end
+			table.insert(vars, stream:sub(iterator, iterator + len - 1))
+			iterator = iterator + len
+		end
+	end
 
-    return unpack(vars)
+	return unpack(vars)
 end
 
 return struct
diff --git a/lua/lib/log.lua b/lua/lib/log.lua
index b7b71e4..dcacdb3 100644
--- a/lua/lib/log.lua
+++ b/lua/lib/log.lua
@@ -2,37 +2,37 @@ local Log = {}
 
 Log.codes = {}
 Log.levels = {
-    { "debug", "Comment" },
-    { "info", "None" },
-    { "warn", "WarningMsg" },
-    { "error", "ErrorMsg" },
+	{ "debug", "Comment" },
+	{ "info", "None" },
+	{ "warn", "WarningMsg" },
+	{ "error", "ErrorMsg" },
 }
 
 function Log:init(options)
-    self.level = options.level
-    return self
+	self.level = options.level
+	return self
 end
 
 -- Initialize logger with log functions for each level
 for i = 1, #Log.levels do
-    local level, hl = unpack(Log.levels[i])
+	local level, hl = unpack(Log.levels[i])
 
-    Log.codes[level] = i
+	Log.codes[level] = i
 
-    Log[level] = function(self, message)
-        -- Skip if log level is not set or the log is below the configured or default level
-        if not self.level or self.codes[level] < self.codes[self.level] or type(message) ~= "string" then
-            return
-        end
+	Log[level] = function(self, message)
+		-- Skip if log level is not set or the log is below the configured or default level
+		if not self.level or self.codes[level] < self.codes[self.level] or type(message) ~= "string" then
+			return
+		end
 
-        vim.schedule(function()
-            local escaped_message = vim.fn.escape(message, '"'):gsub("\n", "\\n")
+		vim.schedule(function()
+			local escaped_message = vim.fn.escape(message, '"'):gsub("\n", "\\n")
 
-            vim.cmd(string.format("echohl %s", hl))
-            vim.cmd(string.format([[echom "[%s] %s"]], "presence.nvim", escaped_message))
-            vim.cmd("echohl NONE")
-        end)
-    end
+			vim.cmd(string.format("echohl %s", hl))
+			vim.cmd(string.format([[echom "[%s] %s"]], "presence.nvim", escaped_message))
+			vim.cmd("echohl NONE")
+		end)
+	end
 end
 
 return Log
diff --git a/lua/presence/discord.lua b/lua/presence/discord.lua
index 83fd77a..6ab2f55 100644
--- a/lua/presence/discord.lua
+++ b/lua/presence/discord.lua
@@ -1,9 +1,9 @@
 local Discord = {}
 
 Discord.opcodes = {
-    auth = 0,
-    frame = 1,
-    closed = 2,
+	auth = 0,
+	frame = 1,
+	closed = 2,
 }
 
 -- Discord RPC Subscription events
@@ -11,190 +11,187 @@ Discord.opcodes = {
 -- Ready: https://discord.com/developers/docs/topics/rpc#ready
 -- Error: https://discord.com/developers/docs/topics/rpc#error
 Discord.events = {
-    READY = "READY",
-    ERROR = "ERROR",
+	READY = "READY",
+	ERROR = "ERROR",
 }
 
 local struct = require("deps.struct")
 
 -- Initialize a new Discord RPC client
 function Discord:init(options)
-    self.log = options.logger
-    self.client_id = options.client_id
-    self.ipc_socket = options.ipc_socket
+	self.log = options.logger
+	self.client_id = options.client_id
+	self.ipc_socket = options.ipc_socket
 
-    self.pipe = vim.loop.new_pipe(false)
+	self.pipe = vim.loop.new_pipe(false)
 
-    return self
+	return self
 end
 
 -- Connect to the local Discord RPC socket
 -- TODO Might need to check for pipes ranging from discord-ipc-0 to discord-ipc-9:
 -- https://github.com/discord/discord-rpc/blob/master/documentation/hard-mode.md#notes
 function Discord:connect(on_connect)
-    if self.pipe:is_closing() then
-        self.pipe = vim.loop.new_pipe(false)
-    end
+	if self.pipe:is_closing() then
+		self.pipe = vim.loop.new_pipe(false)
+	end
 
-    self.pipe:connect(self.ipc_socket, on_connect)
+	self.pipe:connect(self.ipc_socket, on_connect)
 end
 
 function Discord:is_connected()
-    return self.pipe:is_active()
+	return self.pipe:is_active()
 end
 
 -- Disconnect from the local Discord RPC socket
 function Discord:disconnect(on_close)
-    self.pipe:shutdown()
-    if not self.pipe:is_closing() then
-        self.pipe:close(on_close)
-    end
+	self.pipe:shutdown()
+	if not self.pipe:is_closing() then
+		self.pipe:close(on_close)
+	end
 end
 
 -- Make a remote procedure call to Discord
 -- Callback argument in format: on_response(error[, response_table])
 function Discord:call(opcode, payload, on_response)
-    self.encode_json(payload, function(success, body)
-        if not success then
-            self.log:warn(string.format("Failed to encode payload: %s", vim.inspect(body)))
-            return
-        end
+	self.encode_json(payload, function(success, body)
+		if not success then
+			self.log:warn(string.format("Failed to encode payload: %s", vim.inspect(body)))
+			return
+		end
 
-        -- Start reading for the response
-        self.pipe:read_start(function(...)
-            self:read_message(payload.nonce, on_response, ...)
-        end)
+		-- Start reading for the response
+		self.pipe:read_start(function(...)
+			self:read_message(payload.nonce, on_response, ...)
+		end)
 
-        -- Construct message denoting little endian, auth opcode, msg length
-        local message = struct.pack("<ii", opcode, #body)..body
+		-- Construct message denoting little endian, auth opcode, msg length
+		local message = struct.pack("<ii", opcode, #body) .. body
 
-        -- Write the message to the pipe
-        self.pipe:write(message, function(err)
-            if err then
-                local err_format = "Pipe write error - %s"
-                local err_message = string.format(err_format, err)
+		-- Write the message to the pipe
+		self.pipe:write(message, function(err)
+			if err then
+				local err_format = "Pipe write error - %s"
+				local err_message = string.format(err_format, err)
 
-                on_response(err_message)
-            else
-                self.log:debug("Wrote message to pipe")
-            end
-        end)
-    end)
+				on_response(err_message)
+			else
+				self.log:debug("Wrote message to pipe")
+			end
+		end)
+	end)
 end
 
 -- Read and handle socket messages
 function Discord:read_message(nonce, on_response, err, chunk)
-    if err then
-        local err_format = "Pipe read error - %s"
-        local err_message = string.format(err_format, err)
+	if err then
+		local err_format = "Pipe read error - %s"
+		local err_message = string.format(err_format, err)
 
-        on_response(err_message)
+		on_response(err_message)
+	elseif chunk then
+		-- Strip header from the chunk
+		local message = chunk:match("({.+)")
+		local response_opcode = struct.unpack("<ii", chunk)
 
-    elseif chunk then
-        -- Strip header from the chunk
-        local message = chunk:match("({.+)")
-        local response_opcode = struct.unpack("<ii", chunk)
+		self.decode_json(message, function(success, response)
+			-- Check for a non-frame opcode in the response
+			if response_opcode ~= self.opcodes.frame then
+				local err_format = "Received unexpected opcode - %s (code %s)"
+				local err_message = string.format(err_format, response.message, response.code)
 
-        self.decode_json(message, function(success, response)
-            -- Check for a non-frame opcode in the response
-            if response_opcode ~= self.opcodes.frame then
-                local err_format = "Received unexpected opcode - %s (code %s)"
-                local err_message = string.format(err_format, response.message, response.code)
+				return on_response(err_message)
+			end
 
-                return on_response(err_message)
-            end
+			-- Unable to decode the response
+			if not success then
+				-- Indetermine state at this point, no choice but to simply warn on the parse failure
+				-- but invoke empty response callback as request may still have succeeded
+				self.log:warn(string.format("Failed to decode payload: %s", vim.inspect(message)))
+				return on_response()
+			end
 
-            -- Unable to decode the response
-            if not success then
-                -- Indetermine state at this point, no choice but to simply warn on the parse failure
-                -- but invoke empty response callback as request may still have succeeded
-                self.log:warn(string.format("Failed to decode payload: %s", vim.inspect(message)))
-                return on_response()
-            end
+			-- Check for an error event response
+			if response.evt == self.events.ERROR then
+				local data = response.data
+				local err_format = "Received error event - %s (code %s)"
+				local err_message = string.format(err_format, data.message, data.code)
 
-            -- Check for an error event response
-            if response.evt == self.events.ERROR then
-                local data = response.data
-                local err_format = "Received error event - %s (code %s)"
-                local err_message = string.format(err_format, data.message, data.code)
+				return on_response(err_message)
+			end
 
-                return on_response(err_message)
-            end
+			-- Check for a valid nonce value
+			if response.nonce and response.nonce ~= vim.NIL and response.nonce ~= nonce then
+				local err_format = "Received unexpected nonce - %s (expected %s)"
+				local err_message = string.format(err_format, response.nonce, nonce)
 
-            -- Check for a valid nonce value
-            if response.nonce and response.nonce ~= vim.NIL and response.nonce ~= nonce then
-                local err_format = "Received unexpected nonce - %s (expected %s)"
-                local err_message = string.format(err_format, response.nonce, nonce)
+				return on_response(err_message)
+			end
 
-                return on_response(err_message)
-            end
-
-            on_response(nil, response)
-        end)
-    else
-        -- TODO: Handle when pipe is closed
-        self.log:warn("Pipe was closed")
-    end
+			on_response(nil, response)
+		end)
+	else
+		-- TODO: Handle when pipe is closed
+		self.log:warn("Pipe was closed")
+	end
 end
 
 -- Call to authorize the client connection with Discord
 -- Callback argument in format: on_authorize(error[, response_table])
 function Discord:authorize(on_authorize)
-    local payload = {
-        client_id = self.client_id,
-        v = 1,
-    }
+	local payload = {
+		client_id = self.client_id,
+		v = 1,
+	}
 
-    self:call(self.opcodes.auth, payload, on_authorize)
+	self:call(self.opcodes.auth, payload, on_authorize)
 end
 
 -- Call to set the Neovim activity to Discord
 function Discord:set_activity(activity, on_response)
-    local payload = {
-        cmd = "SET_ACTIVITY",
-        nonce = self.generate_uuid(),
-        args = {
-            activity = activity,
-            pid = vim.loop:os_getpid(),
-        },
-    }
+	local payload = {
+		cmd = "SET_ACTIVITY",
+		nonce = self.generate_uuid(),
+		args = {
+			activity = activity,
+			pid = vim.loop:os_getpid(),
+		},
+	}
 
-    self:call(self.opcodes.frame, payload, on_response)
+	self:call(self.opcodes.frame, payload, on_response)
 end
 
 function Discord.generate_uuid(seed)
-    local index = 0
-    local template ="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
+	local index = 0
+	local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
 
-    local uuid = template:gsub("[xy]", function(char)
-        -- Increment an index to seed per char
-        index = index + 1
-        math.randomseed((seed or os.clock()) / index)
+	local uuid = template:gsub("[xy]", function(char)
+		-- Increment an index to seed per char
+		index = index + 1
+		math.randomseed((seed or os.clock()) / index)
 
-        local n = char == "x"
-            and math.random(0, 0xf)
-            or math.random(8, 0xb)
+		local n = char == "x" and math.random(0, 0xf) or math.random(8, 0xb)
 
-        return string.format("%x", n)
-    end)
+		return string.format("%x", n)
+	end)
 
-    return uuid
+	return uuid
 end
 
 function Discord.decode_json(t, on_done)
-    vim.schedule(function()
-        on_done(pcall(function()
-            return vim.fn.json_decode(t)
-        end))
-    end)
+	vim.schedule(function()
+		on_done(pcall(function()
+			return vim.fn.json_decode(t)
+		end))
+	end)
 end
 
 function Discord.encode_json(t, on_done)
-    vim.schedule(function()
-        on_done(pcall(function()
-            return vim.fn.json_encode(t)
-        end))
-    end)
+	vim.schedule(function()
+		on_done(pcall(function()
+			return vim.fn.json_encode(t)
+		end))
+	end)
 end
 
 return Discord
diff --git a/lua/presence/file_assets.lua b/lua/presence/file_assets.lua
index f906a28..9ecfbb6 100644
--- a/lua/presence/file_assets.lua
+++ b/lua/presence/file_assets.lua
@@ -11,266 +11,266 @@
 --     go = { "Go", "https://go.dev/blog/go-brand/Go-Logo/PNG/Go-Logo_Aqua.png" },
 -- }
 return {
-    [".aliases"] = { ".aliases", "shell" },
-    [".appveyor.yml"] = { "AppVeyor config", "appveyor" },
-    [".babelrc"] = { "Babel config", "babel" },
-    [".babelrc.cjs"] = { "Babel config", "babel" },
-    [".babelrc.js"] = { "Babel config", "babel" },
-    [".babelrc.json"] = { "Babel config", "babel" },
-    [".babelrc.mjs"] = { "Babel config", "babel" },
-    [".bash_login"] = { ".bash_login", "shell" },
-    [".bash_logout"] = { ".bash_logout", "shell" },
-    [".bash_profile"] = { ".bash_profile", "shell" },
-    [".bash_prompt"] = { ".bash_prompt", "shell" },
-    [".bashrc"] = { ".bashrc", "shell" },
-    [".cshrc"] = { ".cshrc", "shell" },
-    [".dockercfg"] = { "Docker", "docker" },
-    [".dockerfile"] = { "Docker", "docker" },
-    [".dockerignore"] = { "Docker", "docker" },
-    [".editorconfig"] = { "EditorConfig", "editorconfig" },
-    [".eslintignore"] = { "ESLint", "eslint" },
-    [".eslintrc"] = { "ESLint", "eslint" },
-    [".eslintrc.cjs"] = { "ESLint", "eslint" },
-    [".eslintrc.js"] = { "ESLint", "eslint" },
-    [".eslintrc.json"] = { "ESLint", "eslint" },
-    [".eslintrc.yaml"] = { "ESLint", "eslint" },
-    [".eslintrc.yml"] = { "ESLint", "eslint" },
-    [".gitattributes"] = { "git", "git" },
-    [".gitconfig"] = { "git", "git" },
-    [".gitignore"] = { "git", "git" },
-    [".gitlab-ci.yaml"] = { "GitLab CI", "gitlab" },
-    [".gitlab-ci.yml"] = { "GitLab CI", "gitlab" },
-    [".gitmodules"] = { "git", "git" },
-    [".login"] = { ".login", "shell" },
-    [".logout"] = { ".login", "shell" },
-    [".luacheckrc"] = { ".luacheckrc", "lua" },
-    [".npmignore"] = { "npm config", "npm" },
-    [".npmrc"] = { "npm config", "npm" },
-    [".nvmrc"] = { ".nvmrc", "nodejs" },
-    [".prettierrc"] = { "Prettier", "prettier" },
-    [".prettierrc.cjs"] = { "Prettier", "prettier" },
-    [".prettierrc.js"] = { "Prettier", "prettier" },
-    [".prettierrc.json"] = { "Prettier", "prettier" },
-    [".prettierrc.json5"] = { "Prettier", "prettier" },
-    [".prettierrc.toml"] = { "Prettier", "prettier" },
-    [".prettierrc.yaml"] = { "Prettier", "prettier" },
-    [".prettierrc.yml"] = { "Prettier", "prettier" },
-    [".profile"] = { ".profile", "shell" },
-    [".tcshrc"] = { ".tcshrc", "shell" },
-    [".terraformrc"] = { "Terraform config", "terraform" },
-    [".tmux.conf"] = { "tmux", "tmux" },
-    [".travis.yml"] = { "Travis CI", "travis" },
-    [".vimrc"] = { ".vimrc", "vim" },
-    [".watchmanconfig"] = { "Watchman config", "watchman" },
-    [".yarnrc"] = { "Yarn config", "yarn" },
-    [".zlogin"] = { ".zlogin", "shell" },
-    [".zprofile"] = { ".zprofile", "shell" },
-    [".zshenv"] = { ".zshenv", "shell" },
-    [".zshrc"] = { ".zshrc", "shell" },
-    ["Brewfile"] = { "Brewfile", "homebrew" },
-    ["Brewfile.lock.json"] = { "Brewfile.lock.json", "homebrew" },
-    ["CHANGELOG"] = { "CHANGELOG", "text" },
-    ["CODE_OF_CONDUCT"] = { "Code of Conduct", "text" },
-    ["COMMIT_EDITMSG"] = { "git", "git" },
-    ["CONTRIBUTING"] = { "CONTRIBUTING", "text" },
-    ["Cargo.lock"] = { "Cargo lockfile", "cargo" },
-    ["Cargo.toml"] = { "Cargo.toml", "cargo" },
-    ["Dockerfile"] = { "Docker", "docker" },
-    ["Gemfile"] = { "Gemfile", "ruby" },
-    ["Gemfile.lock"] = { "Gemfile lockfile", "ruby" },
-    ["LICENSE"] = { "LICENSE", "text" },
-    ["Makefile"] = { "Makefile", "code" },
-    ["Rakefile"] = { "Rakefile", "ruby" },
-    ["abookrc"] = { "abook", "abook" },
-    ["alacritty.yaml"] = { "Alacritty config", "alacritty" },
-    ["alacritty.yml"] = { "Alacritty config", "alacritty" },
-    ["appveyor.yml"] = { "AppVeyor config", "appveyor" },
-    ["babel.config.cjs"] = { "Babel config", "babel" },
-    ["babel.config.js"] = { "Babel config", "babel" },
-    ["babel.config.json"] = { "Babel config", "babel" },
-    ["babel.config.mjs"] = { "Babel config", "babel" },
-    ["brew.sh"] = { "brew.sh", "homebrew" },
-    ["docker-compose.yaml"] = { "Docker", "docker" },
-    ["docker-compose.yml"] = { "Docker", "docker" },
-    ["gitconfig"] = { "git", "git" },
-    ["gitlab.rb"] = { "GitLab config", "gitlab" },
-    ["gitlab.yml"] = { "GitLab config", "gitlab" },
-    ["go.mod"] = { "go.mod", "go" },
-    ["go.sum"] = { "go.sum", "go" },
-    ["jest.config.js"] = { "Jest config", "jest" },
-    ["jest.setup.js"] = { "Jest config", "jest" },
-    ["jest.setup.ts"] = { "Jest config", "jest" },
-    ["kitty.conf"] = { "Kitty config", "kitty" },
-    ["next-env.d.ts"] = { "Next.js config", "nextjs" },
-    ["next.config.js"] = { "Next.js config", "nextjs" },
-    ["nginx"] = { "NGINX", "nginx" },
-    ["nginx.conf"] = { "NGINX", "nginx" },
-    ["nuxt.config.js"] = { "Nuxt config", "nuxtjs" },
-    ["prettier.config.cjs"] = { "Prettier", "prettier" },
-    ["prettier.config.js"] = { "Prettier", "prettier" },
-    ["profile"] = { "profile", "shell" },
-    ["renovate.json"] = { "Renovate config", "renovate" },
-    ["requirements.txt"] = { "requirements.txt", "python" },
-    ["tailwind.config.js"] = { "Tailwind", "tailwind" },
-    ["terraform.rc"] = { "Terraform config", "terraform" },
-    ["v.mod"] = { "v.mod", "vlang" },
-    ["watchman.json"] = { "Watchman config", "watchman" },
-    ["webpack.config.js"] = { "Webpack", "webpack" },
-    ["webpack.config.ts"] = { "Webpack", "webpack" },
-    ["yarn.lock"] = { "Yarn lockfile", "yarn" },
-    ["zlogin"] = { "zlogin", "shell" },
-    ["zlogout"] = { "zlogout", "shell" },
-    ["zprofile"] = { "zprofile", "shell" },
-    ["zshenv"] = { "zshenv", "shell" },
-    ["zshrc"] = { "zshrc", "shell" },
-    addressbook = { "abook", "abook" },
-    ahk = { "Autohotkey", "autohotkey" },
-    applescript = { "Applescript", "applescript" },
-    bash = { "Bash script", "shell" },
-    bib = { "BibTeX", "latex" },
-    c = { "C ", "c" },
-    cabal = { "Cabal file", "haskell" },
-    cc = { "C++", "c_plus_plus" },
-    cf = { "Configuration file", "config" },
-    cfg = { "Configuration file", "config" },
-    cl = { "Common Lisp", "lisp" },
-    clj = { "Clojure", "clojure" },
-    cljs = { "ClojureScript", "clojurescript" },
-    cls = { "Visual Basic class module", "visual_basic" },
-    cnf = { "Configuration file", "config" },
-    coffee = { "CoffeeScript", "coffeescript" },
-    conf = { "Configuration file", "config" },
-    config = { "Configuration file", "config" },
-    cpp = { "C++", "c_plus_plus" },
-    cr = { "Crystal", "crystal" },
-    cs = { "C#", "c_sharp" },
-    css = { "CSS", "css" },
-    cxx = { "C++", "c_plus_plus" },
-    d = { "D", "d" },
-    dart = { "Dart", "dart" },
-    dll =  { "DLL file", "visual_basic" },
-    e = { "Eiffel", "eiffel" },
-    elm = { "Elm", "elm" },
-    erl = { "Erlang", "erlang" },
-    ex = { "Elixir", "elixir" },
-    expect = { "Expect", "tcl" },
-    fasl = { "Common Lisp", "lisp" },
-    fish = { "Fish script", "fish" },
-    fnl = { "Fennel", "fennel" },
-    fs = { "F#", "f_sharp" },
-    g = { "ANTLR grammar", "antlr" },
-    g3 = { "ANTLR 3 grammar", "antlr" },
-    g4 = { "ANTLR 4 grammar", "antlr" },
-    gemspec = { "Gem Spec", "ruby" },
-    go = { "Go", "go" },
-    gql = { "GraphQL", "graphql" },
-    graphql = { "GraphQL", "graphql" },
-    groovy = { "Groovy", "groovy" },
-    gsh = { "Groovy", "groovy" },
-    gvy = { "Groovy", "groovy" },
-    gy = { "Groovy", "groovy" },
-    h = { "C header file", "c" },
-    hack = { "Hack", "hack" },
-    haml = { "Haml", "haml" },
-    hpp = { "C++ header file", "c_plus_plus" },
-    hs = { "Haskell", "haskell" },
-    html = { "HTML", "html" },
-    hx = { "Haxe", "haxe" },
-    hxx = { "C++ header file", "c_plus_plus" },
-    idr = { "Idris", "idris" },
-    ini = { "Configuration file", "config" },
-    ino = { "Arduino", "arduino" },
-    ipynb = { "Jupyter Notebook", "jupyter" },
-    java = { "Java", "java" },
-    jl = { "Julia", "julia" },
-    js = { "JavaScript", "javascript" },
-    json = { "JSON", "json" },
-    jsx = { "React", "react" },
-    ksh = { "KornShell script", "shell" },
-    kshrc = { "KornShell config", "shell" },
-    kt = { "Kotlin", "kotlin" },
-    kv = { "Kivy", "kivy" },
-    l = { "Common Lisp", "lisp" },
-    less = { "Less", "less" },
-    lidr = { "Idris", "idris" },
-    liquid = { "Liquid", "liquid" },
-    lisp = { "Common Lisp", "lisp" },
-    log = { "Log file", "code" },
-    lsp  = { "Common Lisp", "lisp" },
-    lua = { "Lua", "lua" },
-    m = { "MATLAB", "matlab" },
-    markdown = { "Markdown", "markdown" },
-    mat = { "MATLAB", "matlab" },
-    md = { "Markdown", "markdown" },
-    mdx = { "MDX", "mdx" },
-    mjs = { "JavaScript", "javascript" },
-    ml = { "OCaml", "ocaml" },
-    nim = { "Nim", "nim" },
-    nix = { "Nix", "nix" },
-    norg = { "Neorg", "neorg" },
-    org = { "Org", "org" },
-    pb = { "Protobuf", "protobuf" },
-    pcss = { "PostCSS", "postcss" },
-    pgsql = { "PostgreSQL", "pgsql" },
-    php = { "PHP", "php" },
-    pl = { "Perl", "perl" },
-    plist = { "Property List", "markup" },
-    postcss = { "PostCSS", "postcss" },
-    proto = { "Protobuf", "protobuf" },
-    ps1 = { "PowerShell", "powershell" },
-    psd1 = { "PowerShell", "powershell" },
-    psm1 = { "PowerShell", "powershell" },
-    purs = { "PureScript", "purescript" },
-    py = { "Python", "python" },
-    r = { "R", "r" },
-    raku = { "Raku", "raku" },
-    rakudoc = { "Raku", "raku" },
-    rakumod = { "Raku", "raku" },
-    rakutest = { "Raku", "raku" },
-    rb = { "Ruby", "ruby" },
-    re = { "Reason", "reason" },
-    res = { "ReScript", "rescript" },
-    rkt = { "Racket", "racket"},
-    rs = { "Rust", "rust" },
-    sass = { "Sass", "sass" },
-    scala = { "Scala", "scala" },
-    scm = { "Scheme", "scheme" },
-    scss = { "Sass", "scss" },
-    sh = { "Shell script", "shell" },
-    shrc = { "Shell config", "shell" },
-    snap = { "Jest Snapshot", "jest" },
-    sql = { "SQL", "database" },
-    ss = { "Scheme", "scheme" },
-    svelte = { "Svelte", "svelte" },
-    svg = { "SVG", "markup" },
-    swift = { "Swift", "swift" },
-    tcl = { "Tcl", "tcl" },
-    tex = { "LaTeX", "latex" },
-    text = { "Text file", "text" },
-    tf = { "Terraform", "terraform" },
-    tk = { "Tcl/Tk", "tcl" },
-    tl = { "Teal", "teal" },
-    toml = { "TOML", "toml" },
-    ts = { "TypeScript", "typescript" },
-    tsx = { "React", "react" },
-    txt = { "Text file", "text" },
-    uc = { "UnrealScript", "unreal" },
-    v = { "Vlang", "vlang" },
-    vsh = { "Vlang shell script", "vlang" },
-    vb = { "Visual Basic", "visual_basic" },
-    vbp = { "Visual Basic project file", "visual_basic" },
-    vim = { "Vim", "vim" },
-    viml = { "Vim", "vim" },
-    vue = { "Vue", "vue" },
-    wasm =  { "WebAssembly", "webassembly" },
-    wast =  { "WebAssembly", "webassembly" },
-    wat =  { "WebAssembly", "webassembly" },
-    xml = { "XML", "markup" },
-    xsd = { "XML Schema", "markup" },
-    xslt = { "XSLT", "markup" },
-    yaml = { "YAML", "yaml" },
-    yml = { "YAML", "yaml" },
-    zig = { "Zig", "zig" },
-    zsh = { "Zsh script", "shell" },
-    zu = { "Zimbu", "zimbu" },
+	[".aliases"] = { ".aliases", "shell" },
+	[".appveyor.yml"] = { "AppVeyor config", "appveyor" },
+	[".babelrc"] = { "Babel config", "babel" },
+	[".babelrc.cjs"] = { "Babel config", "babel" },
+	[".babelrc.js"] = { "Babel config", "babel" },
+	[".babelrc.json"] = { "Babel config", "babel" },
+	[".babelrc.mjs"] = { "Babel config", "babel" },
+	[".bash_login"] = { ".bash_login", "shell" },
+	[".bash_logout"] = { ".bash_logout", "shell" },
+	[".bash_profile"] = { ".bash_profile", "shell" },
+	[".bash_prompt"] = { ".bash_prompt", "shell" },
+	[".bashrc"] = { ".bashrc", "shell" },
+	[".cshrc"] = { ".cshrc", "shell" },
+	[".dockercfg"] = { "Docker", "docker" },
+	[".dockerfile"] = { "Docker", "docker" },
+	[".dockerignore"] = { "Docker", "docker" },
+	[".editorconfig"] = { "EditorConfig", "editorconfig" },
+	[".eslintignore"] = { "ESLint", "eslint" },
+	[".eslintrc"] = { "ESLint", "eslint" },
+	[".eslintrc.cjs"] = { "ESLint", "eslint" },
+	[".eslintrc.js"] = { "ESLint", "eslint" },
+	[".eslintrc.json"] = { "ESLint", "eslint" },
+	[".eslintrc.yaml"] = { "ESLint", "eslint" },
+	[".eslintrc.yml"] = { "ESLint", "eslint" },
+	[".gitattributes"] = { "git", "git" },
+	[".gitconfig"] = { "git", "git" },
+	[".gitignore"] = { "git", "git" },
+	[".gitlab-ci.yaml"] = { "GitLab CI", "gitlab" },
+	[".gitlab-ci.yml"] = { "GitLab CI", "gitlab" },
+	[".gitmodules"] = { "git", "git" },
+	[".login"] = { ".login", "shell" },
+	[".logout"] = { ".login", "shell" },
+	[".luacheckrc"] = { ".luacheckrc", "lua" },
+	[".npmignore"] = { "npm config", "npm" },
+	[".npmrc"] = { "npm config", "npm" },
+	[".nvmrc"] = { ".nvmrc", "nodejs" },
+	[".prettierrc"] = { "Prettier", "prettier" },
+	[".prettierrc.cjs"] = { "Prettier", "prettier" },
+	[".prettierrc.js"] = { "Prettier", "prettier" },
+	[".prettierrc.json"] = { "Prettier", "prettier" },
+	[".prettierrc.json5"] = { "Prettier", "prettier" },
+	[".prettierrc.toml"] = { "Prettier", "prettier" },
+	[".prettierrc.yaml"] = { "Prettier", "prettier" },
+	[".prettierrc.yml"] = { "Prettier", "prettier" },
+	[".profile"] = { ".profile", "shell" },
+	[".tcshrc"] = { ".tcshrc", "shell" },
+	[".terraformrc"] = { "Terraform config", "terraform" },
+	[".tmux.conf"] = { "tmux", "tmux" },
+	[".travis.yml"] = { "Travis CI", "travis" },
+	[".vimrc"] = { ".vimrc", "vim" },
+	[".watchmanconfig"] = { "Watchman config", "watchman" },
+	[".yarnrc"] = { "Yarn config", "yarn" },
+	[".zlogin"] = { ".zlogin", "shell" },
+	[".zprofile"] = { ".zprofile", "shell" },
+	[".zshenv"] = { ".zshenv", "shell" },
+	[".zshrc"] = { ".zshrc", "shell" },
+	["Brewfile"] = { "Brewfile", "homebrew" },
+	["Brewfile.lock.json"] = { "Brewfile.lock.json", "homebrew" },
+	["CHANGELOG"] = { "CHANGELOG", "text" },
+	["CODE_OF_CONDUCT"] = { "Code of Conduct", "text" },
+	["COMMIT_EDITMSG"] = { "git", "git" },
+	["CONTRIBUTING"] = { "CONTRIBUTING", "text" },
+	["Cargo.lock"] = { "Cargo lockfile", "cargo" },
+	["Cargo.toml"] = { "Cargo.toml", "cargo" },
+	["Dockerfile"] = { "Docker", "docker" },
+	["Gemfile"] = { "Gemfile", "ruby" },
+	["Gemfile.lock"] = { "Gemfile lockfile", "ruby" },
+	["LICENSE"] = { "LICENSE", "text" },
+	["Makefile"] = { "Makefile", "code" },
+	["Rakefile"] = { "Rakefile", "ruby" },
+	["abookrc"] = { "abook", "abook" },
+	["alacritty.yaml"] = { "Alacritty config", "alacritty" },
+	["alacritty.yml"] = { "Alacritty config", "alacritty" },
+	["appveyor.yml"] = { "AppVeyor config", "appveyor" },
+	["babel.config.cjs"] = { "Babel config", "babel" },
+	["babel.config.js"] = { "Babel config", "babel" },
+	["babel.config.json"] = { "Babel config", "babel" },
+	["babel.config.mjs"] = { "Babel config", "babel" },
+	["brew.sh"] = { "brew.sh", "homebrew" },
+	["docker-compose.yaml"] = { "Docker", "docker" },
+	["docker-compose.yml"] = { "Docker", "docker" },
+	["gitconfig"] = { "git", "git" },
+	["gitlab.rb"] = { "GitLab config", "gitlab" },
+	["gitlab.yml"] = { "GitLab config", "gitlab" },
+	["go.mod"] = { "go.mod", "go" },
+	["go.sum"] = { "go.sum", "go" },
+	["jest.config.js"] = { "Jest config", "jest" },
+	["jest.setup.js"] = { "Jest config", "jest" },
+	["jest.setup.ts"] = { "Jest config", "jest" },
+	["kitty.conf"] = { "Kitty config", "kitty" },
+	["next-env.d.ts"] = { "Next.js config", "nextjs" },
+	["next.config.js"] = { "Next.js config", "nextjs" },
+	["nginx"] = { "NGINX", "nginx" },
+	["nginx.conf"] = { "NGINX", "nginx" },
+	["nuxt.config.js"] = { "Nuxt config", "nuxtjs" },
+	["prettier.config.cjs"] = { "Prettier", "prettier" },
+	["prettier.config.js"] = { "Prettier", "prettier" },
+	["profile"] = { "profile", "shell" },
+	["renovate.json"] = { "Renovate config", "renovate" },
+	["requirements.txt"] = { "requirements.txt", "python" },
+	["tailwind.config.js"] = { "Tailwind", "tailwind" },
+	["terraform.rc"] = { "Terraform config", "terraform" },
+	["v.mod"] = { "v.mod", "vlang" },
+	["watchman.json"] = { "Watchman config", "watchman" },
+	["webpack.config.js"] = { "Webpack", "webpack" },
+	["webpack.config.ts"] = { "Webpack", "webpack" },
+	["yarn.lock"] = { "Yarn lockfile", "yarn" },
+	["zlogin"] = { "zlogin", "shell" },
+	["zlogout"] = { "zlogout", "shell" },
+	["zprofile"] = { "zprofile", "shell" },
+	["zshenv"] = { "zshenv", "shell" },
+	["zshrc"] = { "zshrc", "shell" },
+	addressbook = { "abook", "abook" },
+	ahk = { "Autohotkey", "autohotkey" },
+	applescript = { "Applescript", "applescript" },
+	bash = { "Bash script", "shell" },
+	bib = { "BibTeX", "latex" },
+	c = { "C ", "c" },
+	cabal = { "Cabal file", "haskell" },
+	cc = { "C++", "c_plus_plus" },
+	cf = { "Configuration file", "config" },
+	cfg = { "Configuration file", "config" },
+	cl = { "Common Lisp", "lisp" },
+	clj = { "Clojure", "clojure" },
+	cljs = { "ClojureScript", "clojurescript" },
+	cls = { "Visual Basic class module", "visual_basic" },
+	cnf = { "Configuration file", "config" },
+	coffee = { "CoffeeScript", "coffeescript" },
+	conf = { "Configuration file", "config" },
+	config = { "Configuration file", "config" },
+	cpp = { "C++", "c_plus_plus" },
+	cr = { "Crystal", "crystal" },
+	cs = { "C#", "c_sharp" },
+	css = { "CSS", "css" },
+	cxx = { "C++", "c_plus_plus" },
+	d = { "D", "d" },
+	dart = { "Dart", "dart" },
+	dll = { "DLL file", "visual_basic" },
+	e = { "Eiffel", "eiffel" },
+	elm = { "Elm", "elm" },
+	erl = { "Erlang", "erlang" },
+	ex = { "Elixir", "elixir" },
+	expect = { "Expect", "tcl" },
+	fasl = { "Common Lisp", "lisp" },
+	fish = { "Fish script", "fish" },
+	fnl = { "Fennel", "fennel" },
+	fs = { "F#", "f_sharp" },
+	g = { "ANTLR grammar", "antlr" },
+	g3 = { "ANTLR 3 grammar", "antlr" },
+	g4 = { "ANTLR 4 grammar", "antlr" },
+	gemspec = { "Gem Spec", "ruby" },
+	go = { "Go", "go" },
+	gql = { "GraphQL", "graphql" },
+	graphql = { "GraphQL", "graphql" },
+	groovy = { "Groovy", "groovy" },
+	gsh = { "Groovy", "groovy" },
+	gvy = { "Groovy", "groovy" },
+	gy = { "Groovy", "groovy" },
+	h = { "C header file", "c" },
+	hack = { "Hack", "hack" },
+	haml = { "Haml", "haml" },
+	hpp = { "C++ header file", "c_plus_plus" },
+	hs = { "Haskell", "haskell" },
+	html = { "HTML", "html" },
+	hx = { "Haxe", "haxe" },
+	hxx = { "C++ header file", "c_plus_plus" },
+	idr = { "Idris", "idris" },
+	ini = { "Configuration file", "config" },
+	ino = { "Arduino", "arduino" },
+	ipynb = { "Jupyter Notebook", "jupyter" },
+	java = { "Java", "java" },
+	jl = { "Julia", "julia" },
+	js = { "JavaScript", "javascript" },
+	json = { "JSON", "json" },
+	jsx = { "React", "react" },
+	ksh = { "KornShell script", "shell" },
+	kshrc = { "KornShell config", "shell" },
+	kt = { "Kotlin", "kotlin" },
+	kv = { "Kivy", "kivy" },
+	l = { "Common Lisp", "lisp" },
+	less = { "Less", "less" },
+	lidr = { "Idris", "idris" },
+	liquid = { "Liquid", "liquid" },
+	lisp = { "Common Lisp", "lisp" },
+	log = { "Log file", "code" },
+	lsp = { "Common Lisp", "lisp" },
+	lua = { "Lua", "lua" },
+	m = { "MATLAB", "matlab" },
+	markdown = { "Markdown", "markdown" },
+	mat = { "MATLAB", "matlab" },
+	md = { "Markdown", "markdown" },
+	mdx = { "MDX", "mdx" },
+	mjs = { "JavaScript", "javascript" },
+	ml = { "OCaml", "ocaml" },
+	nim = { "Nim", "nim" },
+	nix = { "Nix", "nix" },
+	norg = { "Neorg", "neorg" },
+	org = { "Org", "org" },
+	pb = { "Protobuf", "protobuf" },
+	pcss = { "PostCSS", "postcss" },
+	pgsql = { "PostgreSQL", "pgsql" },
+	php = { "PHP", "php" },
+	pl = { "Perl", "perl" },
+	plist = { "Property List", "markup" },
+	postcss = { "PostCSS", "postcss" },
+	proto = { "Protobuf", "protobuf" },
+	ps1 = { "PowerShell", "powershell" },
+	psd1 = { "PowerShell", "powershell" },
+	psm1 = { "PowerShell", "powershell" },
+	purs = { "PureScript", "purescript" },
+	py = { "Python", "python" },
+	r = { "R", "r" },
+	raku = { "Raku", "raku" },
+	rakudoc = { "Raku", "raku" },
+	rakumod = { "Raku", "raku" },
+	rakutest = { "Raku", "raku" },
+	rb = { "Ruby", "ruby" },
+	re = { "Reason", "reason" },
+	res = { "ReScript", "rescript" },
+	rkt = { "Racket", "racket" },
+	rs = { "Rust", "rust" },
+	sass = { "Sass", "sass" },
+	scala = { "Scala", "scala" },
+	scm = { "Scheme", "scheme" },
+	scss = { "Sass", "scss" },
+	sh = { "Shell script", "shell" },
+	shrc = { "Shell config", "shell" },
+	snap = { "Jest Snapshot", "jest" },
+	sql = { "SQL", "database" },
+	ss = { "Scheme", "scheme" },
+	svelte = { "Svelte", "svelte" },
+	svg = { "SVG", "markup" },
+	swift = { "Swift", "swift" },
+	tcl = { "Tcl", "tcl" },
+	tex = { "LaTeX", "latex" },
+	text = { "Text file", "text" },
+	tf = { "Terraform", "terraform" },
+	tk = { "Tcl/Tk", "tcl" },
+	tl = { "Teal", "teal" },
+	toml = { "TOML", "toml" },
+	ts = { "TypeScript", "typescript" },
+	tsx = { "React", "react" },
+	txt = { "Text file", "text" },
+	uc = { "UnrealScript", "unreal" },
+	v = { "Vlang", "vlang" },
+	vsh = { "Vlang shell script", "vlang" },
+	vb = { "Visual Basic", "visual_basic" },
+	vbp = { "Visual Basic project file", "visual_basic" },
+	vim = { "Vim", "vim" },
+	viml = { "Vim", "vim" },
+	vue = { "Vue", "vue" },
+	wasm = { "WebAssembly", "webassembly" },
+	wast = { "WebAssembly", "webassembly" },
+	wat = { "WebAssembly", "webassembly" },
+	xml = { "XML", "markup" },
+	xsd = { "XML Schema", "markup" },
+	xslt = { "XSLT", "markup" },
+	yaml = { "YAML", "yaml" },
+	yml = { "YAML", "yaml" },
+	zig = { "Zig", "zig" },
+	zsh = { "Zsh script", "shell" },
+	zu = { "Zimbu", "zimbu" },
 }
diff --git a/lua/presence/file_explorers.lua b/lua/presence/file_explorers.lua
index 050d8e7..5d33273 100644
--- a/lua/presence/file_explorers.lua
+++ b/lua/presence/file_explorers.lua
@@ -1,10 +1,10 @@
 -- Different neovim file explorer names keyed by filetype or buffer name
 return {
-    ["NvimTree"] = "NvimTree",
-    ["NERD_tree_"] = "NERDTree",
-    ["[defx] default-"] = "Defx",
-    ["netrw"] = "Netrw",
-    ["TelescopePrompt"] = "Telescope",
-    ['neo-tree'] = 'Neotree',
-    ['fern'] = 'Fern'
+	["NvimTree"] = "NvimTree",
+	["NERD_tree_"] = "NERDTree",
+	["[defx] default-"] = "Defx",
+	["netrw"] = "Netrw",
+	["TelescopePrompt"] = "Telescope",
+	["neo-tree"] = "Neotree",
+	["fern"] = "Fern",
 }
diff --git a/lua/presence/init.lua b/lua/presence/init.lua
index d3dddac..c913242 100644
--- a/lua/presence/init.lua
+++ b/lua/presence/init.lua
@@ -69,928 +69,929 @@ local plugin_managers = require("presence.plugin_managers")
 local Discord = require("presence.discord")
 
 function Presence:setup(...)
-    -- Support setup invocation via both dot and colon syntax.
-    -- To maintain backwards compatibility, colon syntax will still
-    -- be supported, but dot syntax should be recommended.
-    local args = { ... }
-    local options = args[1]
-    if #args == 0 then
-        options = self
-        self = Presence
-    end
+	-- Support setup invocation via both dot and colon syntax.
+	-- To maintain backwards compatibility, colon syntax will still
+	-- be supported, but dot syntax should be recommended.
+	local args = { ... }
+	local options = args[1]
+	if #args == 0 then
+		options = self
+		self = Presence
+	end
 
-    options = options or {}
-    self.options = options
+	options = options or {}
+	self.options = options
 
-    -- Initialize logger
-    self:set_option("log_level", nil, false)
-    self.log = log:init({ level = options.log_level })
+	-- Initialize logger
+	self:set_option("log_level", nil, false)
+	self.log = log:init({ level = options.log_level })
 
-    -- Get operating system information including path separator
-    -- http://www.lua.org/manual/5.3/manual.html#pdf-package.config
-    local uname = vim.loop.os_uname()
-    local separator = package.config:sub(1, 1)
-    local wsl_distro_name = os.getenv("WSL_DISTRO_NAME")
-    local os_name = self.get_os_name(uname)
-    self.os = {
-        name = os_name,
-        is_wsl = uname.release:lower():find("microsoft") ~= nil,
-        path_separator = separator,
-    }
+	-- Get operating system information including path separator
+	-- http://www.lua.org/manual/5.3/manual.html#pdf-package.config
+	local uname = vim.loop.os_uname()
+	local separator = package.config:sub(1, 1)
+	local wsl_distro_name = os.getenv("WSL_DISTRO_NAME")
+	local os_name = self.get_os_name(uname)
+	self.os = {
+		name = os_name,
+		is_wsl = uname.release:lower():find("microsoft") ~= nil,
+		path_separator = separator,
+	}
 
-    -- Print setup message with OS information
-    local setup_message_fmt = "Setting up plugin for %s"
-    if self.os.name then
-        local setup_message = self.os.is_wsl
-            and string.format(setup_message_fmt .. " in WSL (%s)", self.os.name, vim.inspect(wsl_distro_name))
-            or string.format(setup_message_fmt, self.os.name)
-        self.log:debug(setup_message)
-    else
-        self.log:error(string.format("Unable to detect operating system: %s", vim.inspect(vim.loop.os_uname())))
-    end
+	-- Print setup message with OS information
+	local setup_message_fmt = "Setting up plugin for %s"
+	if self.os.name then
+		local setup_message = self.os.is_wsl
+				and string.format(setup_message_fmt .. " in WSL (%s)", self.os.name, vim.inspect(wsl_distro_name))
+			or string.format(setup_message_fmt, self.os.name)
+		self.log:debug(setup_message)
+	else
+		self.log:error(string.format("Unable to detect operating system: %s", vim.inspect(vim.loop.os_uname())))
+	end
 
-    -- Use the default or user-defined client id if provided
-    if options.client_id then
-        self.log:info("Using user-defined Discord client id")
-    end
+	-- Use the default or user-defined client id if provided
+	if options.client_id then
+		self.log:info("Using user-defined Discord client id")
+	end
 
-    -- General options
-    self:set_option("auto_update", 1)
-    self:set_option("client_id", "793271441293967371")
-    self:set_option("debounce_timeout", 10)
-    self:set_option("neovim_image_text", "The One True Text Editor")
-    self:set_option("main_image", "neovim")
-    self:set_option("enable_line_number", false)
-    -- Status text options
-    self:set_option("editing_text", "Editing %s")
-    self:set_option("file_explorer_text", "Browsing %s")
-    self:set_option("git_commit_text", "Committing changes")
-    self:set_option("plugin_manager_text", "Managing plugins")
-    self:set_option("reading_text", "Reading %s")
-    self:set_option("workspace_text", "Working on %s")
-    self:set_option("line_number_text", "Line %s out of %s")
-    self:set_option("blacklist", {})
-    self:set_option("buttons", true)
-    self:set_option("show_time", true)
-    -- File assets options
-    self:set_option("file_assets", {})
-    for name, asset in pairs(default_file_assets) do
-        if not self.options.file_assets[name] then
-            self.options.file_assets[name] = asset
-        end
-    end
+	-- General options
+	self:set_option("auto_update", 1)
+	self:set_option("client_id", "1172122807501594644")
+	self:set_option("debounce_timeout", 10)
+	self:set_option("neovim_image_text", "The One True Text Editor")
+	self:set_option("main_image", "neovim")
+	self:set_option("enable_line_number", false)
+	-- Status text options
+	self:set_option("editing_text", "Editing %s")
+	self:set_option("file_explorer_text", "Browsing %s")
+	self:set_option("git_commit_text", "Committing changes")
+	self:set_option("plugin_manager_text", "Managing plugins")
+	self:set_option("reading_text", "Reading %s")
+	self:set_option("workspace_text", "Working on %s")
+	self:set_option("line_number_text", "Line %s out of %s")
+	self:set_option("blacklist", {})
+	self:set_option("buttons", true)
+	self:set_option("show_time", true)
+	-- File assets options
+	self:set_option("file_assets", {})
+	for name, asset in pairs(default_file_assets) do
+		if not self.options.file_assets[name] then
+			self.options.file_assets[name] = asset
+		end
+	end
 
-    -- Get and check discord socket path
-    local discord_socket_path = self:get_discord_socket_path()
-    if discord_socket_path then
-        self.log:debug(string.format("Using Discord IPC socket path: %s", discord_socket_path))
-        self:check_discord_socket(discord_socket_path)
-    else
-        self.log:error("Failed to determine Discord IPC socket path")
-    end
+	-- Get and check discord socket path
+	local discord_socket_path = self:get_discord_socket_path()
+	if discord_socket_path then
+		self.log:debug(string.format("Using Discord IPC socket path: %s", discord_socket_path))
+		self:check_discord_socket(discord_socket_path)
+	else
+		self.log:error("Failed to determine Discord IPC socket path")
+	end
 
-    -- Initialize discord RPC client
-    self.discord = Discord:init({
-        logger = self.log,
-        client_id = options.client_id,
-        ipc_socket = discord_socket_path,
-    })
+	-- Initialize discord RPC client
+	self.discord = Discord:init({
+		logger = self.log,
+		client_id = options.client_id,
+		ipc_socket = discord_socket_path,
+	})
 
-    -- Seed instance id using unique socket path
-    local seed_nums = {}
-    self.socket:gsub(".", function(c)
-        table.insert(seed_nums, c:byte())
-    end)
-    self.id = self.discord.generate_uuid(tonumber(table.concat(seed_nums)) / os.clock())
-    self.log:debug(string.format("Using id %s", self.id))
+	-- Seed instance id using unique socket path
+	local seed_nums = {}
+	self.socket:gsub(".", function(c)
+		table.insert(seed_nums, c:byte())
+	end)
+	self.id = self.discord.generate_uuid(tonumber(table.concat(seed_nums)) / os.clock())
+	self.log:debug(string.format("Using id %s", self.id))
 
-    -- Ensure auto-update config is reflected in its global var setting
-    vim.api.nvim_set_var("presence_auto_update", options.auto_update)
+	-- Ensure auto-update config is reflected in its global var setting
+	vim.api.nvim_set_var("presence_auto_update", options.auto_update)
 
-    -- Set autocommands
-    vim.fn["presence#SetAutoCmds"]()
+	-- Set autocommands
+	vim.fn["presence#SetAutoCmds"]()
 
-    self.log:info("Completed plugin setup")
+	self.log:info("Completed plugin setup")
 
-    -- Set global variable to indicate plugin has been set up
-    vim.api.nvim_set_var("presence_has_setup", 1)
+	-- Set global variable to indicate plugin has been set up
+	vim.api.nvim_set_var("presence_has_setup", 1)
 
-    -- Register self to any remote Neovim instances
-    self:register_self()
+	-- Register self to any remote Neovim instances
+	self:register_self()
 
-    return self
+	return self
 end
 
 -- Normalize the OS name from uname
 function Presence.get_os_name(uname)
-    if uname.sysname:find("Windows") or uname.sysname:find("MINGW") then
-        return "windows"
-    elseif uname.sysname:find("Darwin") then
-        return "macos"
-    elseif uname.sysname:find("Linux") then
-        return "linux"
-    end
+	if uname.sysname:find("Windows") or uname.sysname:find("MINGW") then
+		return "windows"
+	elseif uname.sysname:find("Darwin") then
+		return "macos"
+	elseif uname.sysname:find("Linux") then
+		return "linux"
+	end
 
-    return "unknown"
+	return "unknown"
 end
 
 -- To ensure consistent option values, coalesce true and false values to 1 and 0
 function Presence.coalesce_option(value)
-    if type(value) == "boolean" then
-        return value and 1 or 0
-    end
+	if type(value) == "boolean" then
+		return value and 1 or 0
+	end
 
-    return value
+	return value
 end
 
 -- Set option using either vim global or setup table
 function Presence:set_option(option, default, validate)
-    default = self.coalesce_option(default)
-    validate = validate == nil and true or validate
+	default = self.coalesce_option(default)
+	validate = validate == nil and true or validate
 
-    local g_variable = string.format("presence_%s", option)
+	local g_variable = string.format("presence_%s", option)
 
-    self.options[option] = self.coalesce_option(self.options[option])
+	self.options[option] = self.coalesce_option(self.options[option])
 
-    if validate then
-        -- Warn on any duplicate user-defined options
-        self:check_dup_options(option)
-    end
+	if validate then
+		-- Warn on any duplicate user-defined options
+		self:check_dup_options(option)
+	end
 
-    self.options[option] = self.options[option] or vim.g[g_variable] or default
+	self.options[option] = self.options[option] or vim.g[g_variable] or default
 end
 
 -- Check and warn for duplicate user-defined options
 function Presence:check_dup_options(option)
-    local g_variable = string.format("presence_%s", option)
+	local g_variable = string.format("presence_%s", option)
 
-    if self.options[option] ~= nil and vim.g[g_variable] ~= nil then
-        local warning_fmt = "Duplicate options: `g:%s` and setup option `%s`"
-        local warning_msg = string.format(warning_fmt, g_variable, option)
+	if self.options[option] ~= nil and vim.g[g_variable] ~= nil then
+		local warning_fmt = "Duplicate options: `g:%s` and setup option `%s`"
+		local warning_msg = string.format(warning_fmt, g_variable, option)
 
-        self.log:warn(warning_msg)
-    end
+		self.log:warn(warning_msg)
+	end
 end
 
 -- Check the Discord socket at the given path
 function Presence:check_discord_socket(path)
-    self.log:debug(string.format("Checking Discord IPC socket at %s...", path))
+	self.log:debug(string.format("Checking Discord IPC socket at %s...", path))
 
-    -- Asynchronously check socket path via stat
-    vim.loop.fs_stat(path, function(err, stats)
-        if err then
-            local err_msg = "Failed to get socket information"
-            self.log:error(string.format("%s: %s", err_msg, err))
-            return
-        end
+	-- Asynchronously check socket path via stat
+	vim.loop.fs_stat(path, function(err, stats)
+		if err then
+			local err_msg = "Failed to get socket information"
+			self.log:error(string.format("%s: %s", err_msg, err))
+			return
+		end
 
-        if stats.type ~= "socket" then
-            local warning_msg = "Found unexpected Discord IPC socket type"
-            self.log:warn(string.format("%s: %s", warning_msg, err))
-            return
-        end
+		if stats.type ~= "socket" then
+			local warning_msg = "Found unexpected Discord IPC socket type"
+			self.log:warn(string.format("%s: %s", warning_msg, err))
+			return
+		end
 
-        self.log:debug("Checked Discord IPC socket, looks good!")
-    end)
+		self.log:debug("Checked Discord IPC socket, looks good!")
+	end)
 end
 
 -- Send a nil activity to unset the presence
 function Presence:cancel()
-    self.log:debug("Canceling Discord presence...")
+	self.log:debug("Canceling Discord presence...")
 
-    if not self.discord:is_connected() then
-        return
-    end
+	if not self.discord:is_connected() then
+		return
+	end
 
-    self.discord:set_activity(nil, function(err)
-        if err then
-            self.log:error(string.format("Failed to cancel activity in Discord: %s", err))
-            return
-        end
+	self.discord:set_activity(nil, function(err)
+		if err then
+			self.log:error(string.format("Failed to cancel activity in Discord: %s", err))
+			return
+		end
 
-        self.log:info("Canceled Discord presence")
-    end)
+		self.log:info("Canceled Discord presence")
+	end)
 end
 
 -- Call a command on a remote Neovim instance at the provided IPC path
 function Presence:call_remote_nvim_instance(socket, command)
-    local remote_nvim_instance = vim.loop.new_pipe(true)
+	local remote_nvim_instance = vim.loop.new_pipe(true)
 
-    remote_nvim_instance:connect(socket, function()
-        self.log:debug(string.format("Connected to remote nvim instance at %s", socket))
+	remote_nvim_instance:connect(socket, function()
+		self.log:debug(string.format("Connected to remote nvim instance at %s", socket))
 
-        local packed = msgpack.pack({ 0, 0, "nvim_command", { command } })
+		local packed = msgpack.pack({ 0, 0, "nvim_command", { command } })
 
-        remote_nvim_instance:write(packed, function()
-            self.log:debug(string.format("Wrote to remote nvim instance: %s", socket))
-        end)
-    end)
+		remote_nvim_instance:write(packed, function()
+			self.log:debug(string.format("Wrote to remote nvim instance: %s", socket))
+		end)
+	end)
 end
 
 -- Call a Presence method on a remote instance with a given list of arguments
 function Presence:call_remote_method(socket, name, args)
-    local command_fmt = "lua package.loaded.presence:%s(%s)"
+	local command_fmt = "lua package.loaded.presence:%s(%s)"
 
-    -- Stringify the list of args
-    for i = 1, #args do
-        local arg = args[i]
-        if type(arg) == "string" then
-            args[i] = string.format([["%s"]], arg)
-        elseif type(arg) == "boolean" then
-            args[i] = string.format([["%s"]], tostring(arg))
-        elseif type(arg) == "table" then
-            -- Wrap serpent dump with function invocation to pass in the table value
-            args[i] = string.format("(function() %s end)()", serpent.dump(arg))
-        end
-    end
+	-- Stringify the list of args
+	for i = 1, #args do
+		local arg = args[i]
+		if type(arg) == "string" then
+			args[i] = string.format([["%s"]], arg)
+		elseif type(arg) == "boolean" then
+			args[i] = string.format([["%s"]], tostring(arg))
+		elseif type(arg) == "table" then
+			-- Wrap serpent dump with function invocation to pass in the table value
+			args[i] = string.format("(function() %s end)()", serpent.dump(arg))
+		end
+	end
 
-    local arglist = table.concat(args or {}, ",")
-    local command = string.format(command_fmt, name, arglist)
-    self:call_remote_nvim_instance(socket, command)
+	local arglist = table.concat(args or {}, ",")
+	local command = string.format(command_fmt, name, arglist)
+	self:call_remote_nvim_instance(socket, command)
 end
 
 function Presence:connect(on_done)
-    self.log:debug("Connecting to Discord...")
+	self.log:debug("Connecting to Discord...")
 
-    self.is_connecting = true
+	self.is_connecting = true
 
-    self.discord:connect(function(err)
-        self.is_connecting = false
+	self.discord:connect(function(err)
+		self.is_connecting = false
 
-        -- Handle known connection errors
-        if err == "EISCONN" then
-            self.log:info("Already connected to Discord")
-        elseif err == "ECONNREFUSED" then
-            self.log:warn("Failed to connect to Discord: " .. err .. " (is Discord running?)")
-            return
-        elseif err then
-            self.log:error("Failed to connect to Discord: " .. err)
-            return
-        end
+		-- Handle known connection errors
+		if err == "EISCONN" then
+			self.log:info("Already connected to Discord")
+		elseif err == "ECONNREFUSED" then
+			self.log:warn("Failed to connect to Discord: " .. err .. " (is Discord running?)")
+			return
+		elseif err then
+			self.log:error("Failed to connect to Discord: " .. err)
+			return
+		end
 
-        self.log:info("Connected to Discord")
-        self.is_connected = true
+		self.log:info("Connected to Discord")
+		self.is_connected = true
 
-        if on_done then
-            on_done()
-        end
-    end)
+		if on_done then
+			on_done()
+		end
+	end)
 end
 
 function Presence:authorize(on_done)
-    self.log:debug("Authorizing with Discord...")
+	self.log:debug("Authorizing with Discord...")
 
-    -- Track authorization state to avoid race conditions
-    -- (Discord rejects when multiple auth requests are sent at once)
-    self.is_authorizing = true
+	-- Track authorization state to avoid race conditions
+	-- (Discord rejects when multiple auth requests are sent at once)
+	self.is_authorizing = true
 
-    self.discord:authorize(function(err, response)
-        self.is_authorizing = false
+	self.discord:authorize(function(err, response)
+		self.is_authorizing = false
 
-        if err and err:find(".*already did handshake.*") then
-            self.log:info("Already authorized with Discord")
-            self.is_authorized = true
-            return on_done()
-        elseif err then
-            self.log:error("Failed to authorize with Discord: " .. err)
-            self.is_authorized = false
-            return
-        end
+		if err and err:find(".*already did handshake.*") then
+			self.log:info("Already authorized with Discord")
+			self.is_authorized = true
+			return on_done()
+		elseif err then
+			self.log:error("Failed to authorize with Discord: " .. err)
+			self.is_authorized = false
+			return
+		end
 
-        if not response then
-            self.log:info(string.format("Authorized with Discord for %s", "Response was nil"))
-        else
-            self.log:info(string.format("Authorized with Discord for %s", response.data.user.username))
-        end
+		if not response then
+			self.log:info(string.format("Authorized with Discord for %s", "Response was nil"))
+		else
+			self.log:info(string.format("Authorized with Discord for %s", response.data.user.username))
+		end
 
-        self.is_authorized = true
+		self.is_authorized = true
 
-        if on_done then
-            on_done()
-        end
-    end)
+		if on_done then
+			on_done()
+		end
+	end)
 end
 
 -- Find the Discord socket from temp runtime directories
 function Presence:get_discord_socket_path()
-    local sock_name = "discord-ipc-0"
-    local sock_path = nil
+	local sock_name = "discord-ipc-0"
+	local sock_path = nil
 
-    if self.os.is_wsl then
-        -- Use socket created by relay for WSL
-        sock_path = "/var/run/" .. sock_name
-    elseif self.os.name == "windows" then
-        -- Use named pipe in NPFS for Windows
-        sock_path = [[\\.\pipe\]] .. sock_name
-    elseif self.os.name == "macos" then
-        -- Use $TMPDIR for macOS
-        local path = os.getenv("TMPDIR")
+	if self.os.is_wsl then
+		-- Use socket created by relay for WSL
+		sock_path = "/var/run/" .. sock_name
+	elseif self.os.name == "windows" then
+		-- Use named pipe in NPFS for Windows
+		sock_path = [[\\.\pipe\]] .. sock_name
+	elseif self.os.name == "macos" then
+		-- Use $TMPDIR for macOS
+		local path = os.getenv("TMPDIR")
 
-        if path then
-            sock_path = path:match("/$") and path .. sock_name or path .. "/" .. sock_name
-        end
-    elseif self.os.name == "linux" then
-        -- Check various temp directory environment variables
-        local env_vars = {
-            "XDG_RUNTIME_DIR",
-            "TEMP",
-            "TMP",
-            "TMPDIR",
-        }
+		if path then
+			sock_path = path:match("/$") and path .. sock_name or path .. "/" .. sock_name
+		end
+	elseif self.os.name == "linux" then
+		-- Check various temp directory environment variables
+		local env_vars = {
+			"XDG_RUNTIME_DIR",
+			"TEMP",
+			"TMP",
+			"TMPDIR",
+		}
 
-        local xdg_path = os.getenv("XDG_RUNTIME_DIR")
-        if xdg_path then
-            -- Append app/com.discordapp.Discord/ to the end of the path (make sure that / is at the end of xdg_path
-            -- before appending)
-            xdg_path = xdg_path and xdg_path:match("/$") and xdg_path .. "app/com.discordapp.Discord"
-                or xdg_path .. "/app/com.discordapp.Discord"
-            self.log:debug(string.format("Using XDG runtime path: %s", xdg_path))
-            sock_path = xdg_path:match("/$") and xdg_path .. sock_name or xdg_path .. "/" .. sock_name
-            -- Check if the socket path exists and if not set it to nil
-            sock_path = vim.fn.filereadable(sock_path) == 1 and sock_path or nil
-        end
+		local xdg_path = os.getenv("XDG_RUNTIME_DIR")
+		if xdg_path then
+			-- Append app/com.discordapp.Discord/ to the end of the path (make sure that / is at the end of xdg_path
+			-- before appending)
+			xdg_path = xdg_path and xdg_path:match("/$") and xdg_path .. "app/com.discordapp.Discord"
+				or xdg_path .. "/app/com.discordapp.Discord"
+			self.log:debug(string.format("Using XDG runtime path: %s", xdg_path))
+			sock_path = xdg_path:match("/$") and xdg_path .. sock_name or xdg_path .. "/" .. sock_name
+			-- Check if the socket path exists and if not set it to nil
+			sock_path = vim.fn.filereadable(sock_path) == 1 and sock_path or nil
+		end
 
-        -- If the socket path is still nil, check other temp directories
-        if not sock_path then
-            for i = 1, #env_vars do
-                local var = env_vars[i]
-                local path = os.getenv(var)
-                if path then
-                    self.log:debug(string.format("Using runtime path: %s", path))
-                    sock_path = path:match("/$") and path .. sock_name or path .. "/" .. sock_name
-                    break
-                end
-            end
-        end
-    end
+		-- If the socket path is still nil, check other temp directories
+		if not sock_path then
+			for i = 1, #env_vars do
+				local var = env_vars[i]
+				local path = os.getenv(var)
+				if path then
+					self.log:debug(string.format("Using runtime path: %s", path))
+					sock_path = path:match("/$") and path .. sock_name or path .. "/" .. sock_name
+					break
+				end
+			end
+		end
+	end
 
-    return sock_path
+	return sock_path
 end
 
 -- Gets the file path of the current vim buffer
 function Presence.get_current_buffer()
-    local current_buffer = vim.api.nvim_get_current_buf()
-    return vim.api.nvim_buf_get_name(current_buffer)
+	local current_buffer = vim.api.nvim_get_current_buf()
+	return vim.api.nvim_buf_get_name(current_buffer)
 end
 
 -- Gets the current project name
 function Presence:get_project_name(file_path)
-    if not file_path then
-        return nil
-    end
+	if not file_path then
+		return nil
+	end
 
-    -- Escape quotes in the file path
-    file_path = file_path:gsub([["]], [[\"]])
+	-- Escape quotes in the file path
+	file_path = file_path:gsub([["]], [[\"]])
 
-    -- TODO: Only checks for a git repository, could add more checks here
-    -- Might want to run this in a background process depending on performance
-    local project_path_cmd = "git rev-parse --show-toplevel"
-    project_path_cmd = file_path and string.format([[cd "%s" && %s]], file_path, project_path_cmd) or project_path_cmd
+	-- TODO: Only checks for a git repository, could add more checks here
+	-- Might want to run this in a background process depending on performance
+	local project_path_cmd = "git rev-parse --show-toplevel"
+	project_path_cmd = file_path and string.format([[cd "%s" && %s]], file_path, project_path_cmd) or project_path_cmd
 
-    local project_path = vim.fn.system(project_path_cmd)
-    project_path = vim.trim(project_path)
+	local project_path = vim.fn.system(project_path_cmd)
+	project_path = vim.trim(project_path)
 
-    if project_path:find("fatal.*") then
-        self.log:info("Not a git repository, skipping...")
-        return nil
-    end
-    if vim.v.shell_error ~= 0 or #project_path == 0 then
-        local message_fmt = "Failed to get project name (error code %d): %s"
-        self.log:error(string.format(message_fmt, vim.v.shell_error, project_path))
-        return nil
-    end
+	if project_path:find("fatal.*") then
+		self.log:info("Not a git repository, skipping...")
+		return nil
+	end
+	if vim.v.shell_error ~= 0 or #project_path == 0 then
+		local message_fmt = "Failed to get project name (error code %d): %s"
+		self.log:error(string.format(message_fmt, vim.v.shell_error, project_path))
+		return nil
+	end
 
-    -- Since git always uses forward slashes, replace with backslash in Windows
-    if self.os.name == "windows" then
-        project_path = project_path:gsub("/", [[\]])
-    end
+	-- Since git always uses forward slashes, replace with backslash in Windows
+	if self.os.name == "windows" then
+		project_path = project_path:gsub("/", [[\]])
+	end
 
-    return self.get_filename(project_path, self.os.path_separator), project_path
+	return self.get_filename(project_path, self.os.path_separator), project_path
 end
 
 -- Get the name of the parent directory for the given path
 function Presence.get_dir_path(path, path_separator)
-    return path:match(string.format("^(.+%s.+)%s.*$", path_separator, path_separator))
+	return path:match(string.format("^(.+%s.+)%s.*$", path_separator, path_separator))
 end
 
 -- Get the name of the file for the given path
 function Presence.get_filename(path, path_separator)
-    return path:match(string.format("^.+%s(.+)$", path_separator))
+	return path:match(string.format("^.+%s(.+)$", path_separator))
 end
 
 -- Get the file extension for the given filename
 function Presence.get_file_extension(path)
-    return path:match("^.+%.(.+)$")
+	return path:match("^.+%.(.+)$")
 end
 
 -- Format any status text via options and support custom formatter functions
 function Presence:format_status_text(status_type, ...)
-    local option_name = string.format("%s_text", status_type)
-    local text_option = self.options[option_name]
-    if type(text_option) == "function" then
-        return text_option(...)
-    else
-        return string.format(text_option, ...)
-    end
+	local option_name = string.format("%s_text", status_type)
+	local text_option = self.options[option_name]
+	if type(text_option) == "function" then
+		return text_option(...)
+	else
+		return string.format(text_option, ...)
+	end
 end
 
 -- Get the status text for the current buffer
 function Presence:get_status_text(filename)
-    local file_explorer = file_explorers[vim.bo.filetype:match("[^%d]+")]
-        or file_explorers[(filename or ""):match("[^%d]+")]
-    local plugin_manager = plugin_managers[vim.bo.filetype]
+	local file_explorer = file_explorers[vim.bo.filetype:match("[^%d]+")]
+		or file_explorers[(filename or ""):match("[^%d]+")]
+	local plugin_manager = plugin_managers[vim.bo.filetype]
 
-    if file_explorer then
-        return self:format_status_text("file_explorer", file_explorer)
-    elseif plugin_manager then
-        return self:format_status_text("plugin_manager", plugin_manager)
-    end
+	if file_explorer then
+		return self:format_status_text("file_explorer", file_explorer)
+	elseif plugin_manager then
+		return self:format_status_text("plugin_manager", plugin_manager)
+	end
 
-    if not filename or filename == "" then
-        return nil
-    end
+	if not filename or filename == "" then
+		return nil
+	end
 
-    if vim.bo.modifiable and not vim.bo.readonly then
-        if vim.bo.filetype == "gitcommit" then
-            return self:format_status_text("git_commit", filename)
-        elseif filename then
-            return self:format_status_text("editing", filename)
-        end
-    elseif filename then
-        return self:format_status_text("reading", filename)
-    end
+	if vim.bo.modifiable and not vim.bo.readonly then
+		if vim.bo.filetype == "gitcommit" then
+			return self:format_status_text("git_commit", filename)
+		elseif filename then
+			return self:format_status_text("editing", filename)
+		end
+	elseif filename then
+		return self:format_status_text("reading", filename)
+	end
 end
 
 -- Get all local nvim socket paths
 function Presence:get_nvim_socket_paths(on_done)
-    self.log:debug("Getting nvim socket paths...")
-    local sockets = {}
-    local parser = {}
-    local cmd
+	self.log:debug("Getting nvim socket paths...")
+	local sockets = {}
+	local parser = {}
+	local cmd
 
-    if self.os.is_wsl then
-        -- TODO: There needs to be a better way of doing this... no support for ss/netstat?
-        -- (See https://github.com/microsoft/WSL/issues/2249)
-        local cmd_fmt = "for file in %s/nvim*; do echo $file/0; done"
-        local shell_cmd = string.format(cmd_fmt, vim.loop.os_tmpdir() or "/tmp")
+	if self.os.is_wsl then
+		-- TODO: There needs to be a better way of doing this... no support for ss/netstat?
+		-- (See https://github.com/microsoft/WSL/issues/2249)
+		local cmd_fmt = "for file in %s/nvim*; do echo $file/0; done"
+		local shell_cmd = string.format(cmd_fmt, vim.loop.os_tmpdir() or "/tmp")
 
-        cmd = {
-            "sh",
-            "-c",
-            shell_cmd,
-        }
-    elseif self.os.name == "windows" then
-        cmd = {
-            "powershell.exe",
-            "-Command",
-            [[(Get-ChildItem \\.\pipe\).FullName | findstr 'nvim']],
-        }
-    elseif self.os.name == "macos" then
-        if vim.fn.executable("netstat") == 0 then
-            self.log:warn("Unable to get nvim socket paths: `netstat` command unavailable")
-            return
-        end
+		cmd = {
+			"sh",
+			"-c",
+			shell_cmd,
+		}
+	elseif self.os.name == "windows" then
+		cmd = {
+			"powershell.exe",
+			"-Command",
+			[[(Get-ChildItem \\.\pipe\).FullName | findstr 'nvim']],
+		}
+	elseif self.os.name == "macos" then
+		if vim.fn.executable("netstat") == 0 then
+			self.log:warn("Unable to get nvim socket paths: `netstat` command unavailable")
+			return
+		end
 
-        -- Define macOS BSD netstat output parser
-        function parser.parse(data)
-            return data:match("%s(/.+)")
-        end
+		-- Define macOS BSD netstat output parser
+		function parser.parse(data)
+			return data:match("%s(/.+)")
+		end
 
-        cmd = table.concat({
-            "netstat -u",
-            [[grep --color=never "nvim.*/0"]],
-        }, "|")
-    elseif self.os.name == "linux" then
-        if vim.fn.executable("ss") == 1 then
-            -- Use `ss` if available
-            cmd = table.concat({
-                "ss -lx",
-                [[grep "nvim.*/0"]],
-            }, "|")
+		cmd = table.concat({
+			"netstat -u",
+			[[grep --color=never "nvim.*/0"]],
+		}, "|")
+	elseif self.os.name == "linux" then
+		if vim.fn.executable("ss") == 1 then
+			-- Use `ss` if available
+			cmd = table.concat({
+				"ss -lx",
+				[[grep "nvim.*/0"]],
+			}, "|")
 
-            -- Define ss output parser
-            function parser.parse(data)
-                return data:match("%s(/.-)%s")
-            end
-        elseif vim.fn.executable("netstat") == 1 then
-            -- Use `netstat` if available
-            cmd = table.concat({
-                "netstat -u",
-                [[grep --color=never "nvim.*/0"]],
-            }, "|")
+			-- Define ss output parser
+			function parser.parse(data)
+				return data:match("%s(/.-)%s")
+			end
+		elseif vim.fn.executable("netstat") == 1 then
+			-- Use `netstat` if available
+			cmd = table.concat({
+				"netstat -u",
+				[[grep --color=never "nvim.*/0"]],
+			}, "|")
 
-            -- Define netstat output parser
-            function parser.parse(data)
-                return data:match("%s(/.+)")
-            end
-        else
-            local warning_msg = "Unable to get nvim socket paths: `netstat` and `ss` commands unavailable"
-            self.log:warn(warning_msg)
-            return
-        end
-    else
-        local warning_fmt = "Unable to get nvim socket paths: Unexpected OS: %s"
-        self.log:warn(string.format(warning_fmt, self.os.name))
-        return
-    end
+			-- Define netstat output parser
+			function parser.parse(data)
+				return data:match("%s(/.+)")
+			end
+		else
+			local warning_msg = "Unable to get nvim socket paths: `netstat` and `ss` commands unavailable"
+			self.log:warn(warning_msg)
+			return
+		end
+	else
+		local warning_fmt = "Unable to get nvim socket paths: Unexpected OS: %s"
+		self.log:warn(string.format(warning_fmt, self.os.name))
+		return
+	end
 
-    local function handle_data(_, data)
-        if not data then
-            return
-        end
+	local function handle_data(_, data)
+		if not data then
+			return
+		end
 
-        for i = 1, #data do
-            local socket = parser.parse and parser.parse(vim.trim(data[i])) or vim.trim(data[i])
-            if socket and socket ~= "" and socket ~= self.socket then
-                table.insert(sockets, socket)
-            end
-        end
-    end
+		for i = 1, #data do
+			local socket = parser.parse and parser.parse(vim.trim(data[i])) or vim.trim(data[i])
+			if socket and socket ~= "" and socket ~= self.socket then
+				table.insert(sockets, socket)
+			end
+		end
+	end
 
-    local function handle_error(_, data)
-        if not data then
-            return
-        end
+	local function handle_error(_, data)
+		if not data then
+			return
+		end
 
-        if data[1] ~= "" then
-            self.log:error(string.format("Unable to get nvim socket paths: %s", data[1]))
-        end
-    end
+		if data[1] ~= "" then
+			self.log:error(string.format("Unable to get nvim socket paths: %s", data[1]))
+		end
+	end
 
-    local function handle_exit()
-        self.log:debug(string.format("Got nvim socket paths: %s", vim.inspect(sockets)))
-        on_done(sockets)
-    end
+	local function handle_exit()
+		self.log:debug(string.format("Got nvim socket paths: %s", vim.inspect(sockets)))
+		on_done(sockets)
+	end
 
-    local cmd_str = type(cmd) == "table" and table.concat(cmd, ", ") or cmd
-    self.log:debug(string.format("Executing command: `%s`", cmd_str))
-    vim.fn.jobstart(cmd, {
-        on_stdout = handle_data,
-        on_stderr = handle_error,
-        on_exit = handle_exit,
-    })
+	local cmd_str = type(cmd) == "table" and table.concat(cmd, ", ") or cmd
+	self.log:debug(string.format("Executing command: `%s`", cmd_str))
+	vim.fn.jobstart(cmd, {
+		on_stdout = handle_data,
+		on_stderr = handle_error,
+		on_exit = handle_exit,
+	})
 end
 
 -- Wrap calls to Discord that require prior connection and authorization
 function Presence.discord_event(on_ready)
-    return function(self, ...)
-        if not self.discord.ipc_socket then
-            self.log:debug("Discord IPC socket not found, skipping...")
-            return
-        end
+	return function(self, ...)
+		if not self.discord.ipc_socket then
+			self.log:debug("Discord IPC socket not found, skipping...")
+			return
+		end
 
-        local args = { ... }
-        local callback = function()
-            on_ready(self, unpack(args))
-        end
+		local args = { ... }
+		local callback = function()
+			on_ready(self, unpack(args))
+		end
 
-        -- Call Discord if already connected and authorized
-        if self.is_connected and self.is_authorized then
-            return callback()
-        end
+		-- Call Discord if already connected and authorized
+		if self.is_connected and self.is_authorized then
+			return callback()
+		end
 
-        -- Schedule event if currently authorizing with Discord
-        if self.is_connecting or self.is_authorizing then
-            local action = self.is_connecting and "connecting" or "authorizing"
-            local message_fmt = "Currently %s with Discord, scheduling callback for later..."
-            self.log:debug(string.format(message_fmt, action))
-            return vim.schedule(callback)
-        end
+		-- Schedule event if currently authorizing with Discord
+		if self.is_connecting or self.is_authorizing then
+			local action = self.is_connecting and "connecting" or "authorizing"
+			local message_fmt = "Currently %s with Discord, scheduling callback for later..."
+			self.log:debug(string.format(message_fmt, action))
+			return vim.schedule(callback)
+		end
 
-        -- Authorize if connected but not yet authorized yet
-        if self.is_connected and not self.is_authorized then
-            return self:authorize(callback)
-        end
+		-- Authorize if connected but not yet authorized yet
+		if self.is_connected and not self.is_authorized then
+			return self:authorize(callback)
+		end
 
-        -- Connect and authorize plugin with Discord
-        self:connect(function()
-            if self.is_authorized then
-                return callback()
-            end
+		-- Connect and authorize plugin with Discord
+		self:connect(function()
+			if self.is_authorized then
+				return callback()
+			end
 
-            self:authorize(callback)
-        end)
-    end
+			self:authorize(callback)
+		end)
+	end
 end
 
 -- Check if the current project/parent is in blacklist
 function Presence:check_blacklist(buffer, parent_dirpath, project_dirpath)
-    local parent_dirname = nil
-    local project_dirname = nil
+	local parent_dirname = nil
+	local project_dirname = nil
 
-    -- Parse parent/project directory name
-    if parent_dirpath then
-        parent_dirname = self.get_filename(parent_dirpath, self.os.path_separator)
-    end
+	-- Parse parent/project directory name
+	if parent_dirpath then
+		parent_dirname = self.get_filename(parent_dirpath, self.os.path_separator)
+	end
 
-    if project_dirpath then
-        project_dirname = self.get_filename(project_dirpath, self.os.path_separator)
-    end
+	if project_dirpath then
+		project_dirname = self.get_filename(project_dirpath, self.os.path_separator)
+	end
 
-    -- Blacklist table
-    local blacklist_table = self.options["blacklist"]
+	-- Blacklist table
+	local blacklist_table = self.options["blacklist"]
 
-    -- Loop over the values to see if the provided project/path is in the blacklist
-    for _, val in pairs(blacklist_table) do
-        -- Matches buffer exactly
-        if buffer:match(val) == buffer then
-            return true
-        end
-        -- Match parent either by Lua pattern or by plain string
-        local is_parent_directory_blacklisted = parent_dirpath
-            and (
-                (parent_dirpath:match(val) == parent_dirpath or parent_dirname:match(val) == parent_dirname)
-                or (parent_dirpath:find(val, nil, true) or parent_dirname:find(val, nil, true))
-            )
-        if is_parent_directory_blacklisted then
-            return true
-        end
-        -- Match project either by Lua pattern or by plain string
-        local is_project_directory_blacklisted = project_dirpath
-            and (
-                (project_dirpath:match(val) == project_dirpath or project_dirname:match(val) == project_dirname)
-                or (project_dirpath:find(val, nil, true) or project_dirname:find(val, nil, true))
-            )
-        if is_project_directory_blacklisted then
-            return true
-        end
-    end
+	-- Loop over the values to see if the provided project/path is in the blacklist
+	for _, val in pairs(blacklist_table) do
+		-- Matches buffer exactly
+		if buffer:match(val) == buffer then
+			return true
+		end
+		-- Match parent either by Lua pattern or by plain string
+		local is_parent_directory_blacklisted = parent_dirpath
+			and (
+				(parent_dirpath:match(val) == parent_dirpath or parent_dirname:match(val) == parent_dirname)
+				or (parent_dirpath:find(val, nil, true) or parent_dirname:find(val, nil, true))
+			)
+		if is_parent_directory_blacklisted then
+			return true
+		end
+		-- Match project either by Lua pattern or by plain string
+		local is_project_directory_blacklisted = project_dirpath
+			and (
+				(project_dirpath:match(val) == project_dirpath or project_dirname:match(val) == project_dirname)
+				or (project_dirpath:find(val, nil, true) or project_dirname:find(val, nil, true))
+			)
+		if is_project_directory_blacklisted then
+			return true
+		end
+	end
 
-    return false
+	return false
 end
 
 -- Get either user-configured buttons or the create default "View Repository" button definition
 function Presence:get_buttons(buffer, parent_dirpath)
-    -- User configured a static buttons table
-    if type(self.options.buttons) == "table" then
-        local is_plural = #self.options.buttons > 1
-        local s = is_plural and "s" or ""
-        self.log:debug(string.format("Using custom-defined button%s", s))
+	-- User configured a static buttons table
+	if type(self.options.buttons) == "table" then
+		local is_plural = #self.options.buttons > 1
+		local s = is_plural and "s" or ""
+		self.log:debug(string.format("Using custom-defined button%s", s))
 
-        return self.options.buttons
-    end
+		return self.options.buttons
+	end
 
-    -- Retrieve the git repository URL
-    local repo_url
-    if parent_dirpath then
-        -- Escape quotes in the file path
-        local path = parent_dirpath:gsub([["]], [[\"]])
-        local git_url_cmd = "git config --get remote.origin.url"
-        local cmd = path and string.format([[cd "%s" && %s]], path, git_url_cmd) or git_url_cmd
+	-- Retrieve the git repository URL
+	local repo_url
+	if parent_dirpath then
+		-- Escape quotes in the file path
+		local path = parent_dirpath:gsub([["]], [[\"]])
+		local git_url_cmd = "git config --get remote.origin.url"
+		local cmd = path and string.format([[cd "%s" && %s]], path, git_url_cmd) or git_url_cmd
 
-        -- Trim and coerce empty string value to null
-        repo_url = vim.trim(vim.fn.system(cmd))
-        repo_url = repo_url ~= "" and repo_url or nil
-    end
+		-- Trim and coerce empty string value to null
+		repo_url = vim.trim(vim.fn.system(cmd))
+		repo_url = repo_url ~= "" and repo_url or nil
+	end
 
-    -- User configured a function to dynamically create buttons table
-    if type(self.options.buttons) == "function" then
-        self.log:debug("Using custom-defined button config function")
-        return self.options.buttons(buffer, repo_url)
-    end
+	-- User configured a function to dynamically create buttons table
+	if type(self.options.buttons) == "function" then
+		self.log:debug("Using custom-defined button config function")
+		return self.options.buttons(buffer, repo_url)
+	end
 
-    -- Default behavior to show a "View Repository" button if the repo URL is valid
-    if repo_url then
-        -- Check if repo url uses short ssh syntax
-        local domain, project = repo_url:match("^git@(.+):(.+)$")
-        if domain and project then
-            self.log:debug(string.format("Repository URL uses short ssh syntax: %s", repo_url))
-            repo_url = string.format("https://%s/%s", domain, project)
-        end
+	-- Default behavior to show a "View Repository" button if the repo URL is valid
+	if repo_url then
+		-- Check if repo url uses short ssh syntax
+		local domain, project = repo_url:match("^git@(.+):(.+)$")
+		if domain and project then
+			self.log:debug(string.format("Repository URL uses short ssh syntax: %s", repo_url))
+			repo_url = string.format("https://%s/%s", domain, project)
+		end
 
-        -- Check if repo url uses a valid protocol
-        local protocols = {
-            "ftp",
-            "git",
-            "http",
-            "https",
-            "ssh",
-        }
-        local protocol, relative = repo_url:match("^(.+)://(.+)$")
-        if not vim.tbl_contains(protocols, protocol) or not relative then
-            self.log:debug(string.format("Repository URL uses invalid protocol: %s", repo_url))
-            return nil
-        end
+		-- Check if repo url uses a valid protocol
+		local protocols = {
+			"ftp",
+			"git",
+			"http",
+			"https",
+			"ssh",
+		}
+		local protocol, relative = repo_url:match("^(.+)://(.+)$")
+		if not vim.tbl_contains(protocols, protocol) or not relative then
+			self.log:debug(string.format("Repository URL uses invalid protocol: %s", repo_url))
+			return nil
+		end
 
-        -- Check if repo url has the user specified
-        local user, path = relative:match("^(.+)@(.+)$")
-        if user and path then
-            self.log:debug(string.format("Repository URL has user specified: %s", repo_url))
-            repo_url = string.format("https://%s", path)
-        else
-            repo_url = string.format("https://%s", relative)
-        end
+		-- Check if repo url has the user specified
+		local user, path = relative:match("^(.+)@(.+)$")
+		if user and path then
+			self.log:debug(string.format("Repository URL has user specified: %s", repo_url))
+			repo_url = string.format("https://%s", path)
+		else
+			repo_url = string.format("https://%s", relative)
+		end
 
-        self.log:debug(string.format("Adding button with repository URL: %s", repo_url))
+		self.log:debug(string.format("Adding button with repository URL: %s", repo_url))
 
-        return {
-            { label = "View Repository", url = repo_url },
-        }
-    end
+		return {
+			{ label = "View Repository", url = repo_url },
+		}
+	end
 
-    return nil
+	return nil
 end
 
 -- Update Rich Presence for the provided vim buffer
 function Presence:update_for_buffer(buffer, should_debounce)
-    -- Avoid unnecessary updates if the previous activity was for the current buffer
-    -- (allow same-buffer updates when line numbers are enabled)
-    if self.options.enable_line_number == 0 and self.last_activity.file == buffer then
-        self.log:debug(string.format("Activity already set for %s, skipping...", buffer))
-        return
-    end
+	-- Avoid unnecessary updates if the previous activity was for the current buffer
+	-- (allow same-buffer updates when line numbers are enabled)
+	if self.options.enable_line_number == 0 and self.last_activity.file == buffer then
+		self.log:debug(string.format("Activity already set for %s, skipping...", buffer))
+		return
+	end
 
-    -- Parse vim buffer
-    local filename = self.get_filename(buffer, self.os.path_separator)
-    local parent_dirpath = self.get_dir_path(buffer, self.os.path_separator)
-    local extension = filename and self.get_file_extension(filename) or nil
-    self.log:debug(string.format("Parsed filename %s with %s extension", filename, extension or "no"))
+	-- Parse vim buffer
+	local filename = self.get_filename(buffer, self.os.path_separator)
+	local parent_dirpath = self.get_dir_path(buffer, self.os.path_separator)
+	local extension = filename and self.get_file_extension(filename) or nil
+	self.log:debug(string.format("Parsed filename %s with %s extension", filename, extension or "no"))
 
-    -- Return early if there is no valid activity status text to set
-    local status_text = self:get_status_text(filename)
-    if not status_text then
-        return self.log:debug("No status text for the given buffer, skipping...")
-    end
+	-- Return early if there is no valid activity status text to set
+	local status_text = self:get_status_text(filename)
+	if not status_text then
+		return self.log:debug("No status text for the given buffer, skipping...")
+	end
 
-    -- Get project information
-    self.log:debug(string.format("Getting project name for %s...", parent_dirpath))
-    local project_name, project_path = self:get_project_name(parent_dirpath)
+	-- Get project information
+	self.log:debug(string.format("Getting project name for %s...", parent_dirpath))
+	local project_name, project_path = self:get_project_name(parent_dirpath)
 
-    -- Check for blacklist
-    local is_blacklisted = #self.options.blacklist > 0 and self:check_blacklist(buffer, parent_dirpath, project_path)
-    if is_blacklisted then
-        self.last_activity.file = buffer
-        self.log:debug("Either project or directory name is blacklisted, skipping...")
-        self:cancel()
-        return
-    end
+	-- Check for blacklist
+	local is_blacklisted = #self.options.blacklist > 0 and self:check_blacklist(buffer, parent_dirpath, project_path)
+	if is_blacklisted then
+		self.last_activity.file = buffer
+		self.log:debug("Either project or directory name is blacklisted, skipping...")
+		self:cancel()
+		return
+	end
 
-    local activity_set_at = os.time()
-    -- If we shouldn't debounce and we trigger an activity, keep this value the same.
-    -- Otherwise set it to the current time.
-    local relative_activity_set_at = should_debounce and self.last_activity.relative_set_at or os.time()
+	local activity_set_at = os.time()
+	-- If we shouldn't debounce and we trigger an activity, keep this value the same.
+	-- Otherwise set it to the current time.
+	local relative_activity_set_at = should_debounce and self.last_activity.relative_set_at or os.time()
 
-    self.log:debug(string.format("Setting activity for %s...", buffer and #buffer > 0 and buffer or "unnamed buffer"))
+	self.log:debug(string.format("Setting activity for %s...", buffer and #buffer > 0 and buffer or "unnamed buffer"))
 
-    -- Determine image text and asset key
-    local name = filename
-    local asset_key = "code"
-    local description = filename
-    local file_asset = self.options.file_assets[filename] or self.options.file_assets[extension]
-    if file_asset then
-        name, asset_key, description = unpack(file_asset)
-        self.log:debug(string.format("Using file asset: %s", vim.inspect(file_asset)))
-    end
+	-- Determine image text and asset key
+	local name = filename
+	local asset_key = "code"
+	local description = filename
+	local file_asset = self.options.file_assets[filename] or self.options.file_assets[extension]
+	if file_asset then
+		name, asset_key, description = unpack(file_asset)
+		self.log:debug(string.format("Using file asset: %s", vim.inspect(file_asset)))
+	end
 
-    -- Construct activity asset information
-    local file_text = description or name
-    local neovim_image_text = self.options.neovim_image_text
-    local use_file_as_main_image = self.options.main_image == "file"
-    local use_neovim_as_main_image = self.options.main_image == "neovim"
-    local assets = {
-        large_image = use_file_as_main_image and asset_key or use_neovim_as_main_image
-                      and "neovim" or self.options.main_image,
-        large_text = use_file_as_main_image and file_text or neovim_image_text,
-        small_image = use_file_as_main_image and "neovim" or asset_key,
-        small_text = use_file_as_main_image and neovim_image_text or file_text,
-    }
+	-- Construct activity asset information
+	local file_text = description or name
+	local neovim_image_text = self.options.neovim_image_text
+	local use_file_as_main_image = self.options.main_image == "file"
+	local use_neovim_as_main_image = self.options.main_image == "neovim"
+	local assets = {
+		large_image = use_file_as_main_image and asset_key
+			or use_neovim_as_main_image and "neovim"
+			or self.options.main_image,
+		large_text = use_file_as_main_image and file_text or neovim_image_text,
+		small_image = use_file_as_main_image and "neovim" or asset_key,
+		small_text = use_file_as_main_image and neovim_image_text or file_text,
+	}
 
-    local activity = {
-        state = status_text,
-        assets = assets,
-        timestamps = self.options.show_time == 1 and {
-            start = relative_activity_set_at,
-        } or nil,
-    }
+	local activity = {
+		state = status_text,
+		assets = assets,
+		timestamps = self.options.show_time == 1 and {
+			start = relative_activity_set_at,
+		} or nil,
+	}
 
-    -- Add button that links to the git workspace remote origin url
-    if self.options.buttons ~= 0 then
-        local buttons = self:get_buttons(buffer, parent_dirpath)
-        if buttons then
-            self.log:debug(string.format("Attaching buttons to activity: %s", vim.inspect(buttons)))
-            activity.buttons = buttons
-        end
-    end
+	-- Add button that links to the git workspace remote origin url
+	if self.options.buttons ~= 0 then
+		local buttons = self:get_buttons(buffer, parent_dirpath)
+		if buttons then
+			self.log:debug(string.format("Attaching buttons to activity: %s", vim.inspect(buttons)))
+			activity.buttons = buttons
+		end
+	end
 
-    -- Get the current line number and line count if the user has set the enable_line_number option
-    if self.options.enable_line_number == 1 then
-        self.log:debug("Getting line number for current buffer...")
+	-- Get the current line number and line count if the user has set the enable_line_number option
+	if self.options.enable_line_number == 1 then
+		self.log:debug("Getting line number for current buffer...")
 
-        local line_number = vim.api.nvim_win_get_cursor(0)[1]
-        local line_count = vim.api.nvim_buf_line_count(0)
-        local line_number_text = self:format_status_text("line_number", line_number, line_count)
+		local line_number = vim.api.nvim_win_get_cursor(0)[1]
+		local line_count = vim.api.nvim_buf_line_count(0)
+		local line_number_text = self:format_status_text("line_number", line_number, line_count)
 
-        activity.details = line_number_text
+		activity.details = line_number_text
 
-        self.workspace = nil
-        self.last_activity = {
-            id = self.id,
-            file = buffer,
-            set_at = activity_set_at,
-            relative_set_at = relative_activity_set_at,
-            workspace = nil,
-        }
-    else
-        -- Include project details if available and if the user hasn't set the enable_line_number option
-        if project_name then
-            self.log:debug(string.format("Detected project: %s", project_name))
+		self.workspace = nil
+		self.last_activity = {
+			id = self.id,
+			file = buffer,
+			set_at = activity_set_at,
+			relative_set_at = relative_activity_set_at,
+			workspace = nil,
+		}
+	else
+		-- Include project details if available and if the user hasn't set the enable_line_number option
+		if project_name then
+			self.log:debug(string.format("Detected project: %s", project_name))
 
-            activity.details = self:format_status_text("workspace", project_name, buffer)
+			activity.details = self:format_status_text("workspace", project_name, buffer)
 
-            self.workspace = project_path
-            self.last_activity = {
-                id = self.id,
-                file = buffer,
-                set_at = activity_set_at,
-                relative_set_at = relative_activity_set_at,
-                workspace = project_path,
-            }
+			self.workspace = project_path
+			self.last_activity = {
+				id = self.id,
+				file = buffer,
+				set_at = activity_set_at,
+				relative_set_at = relative_activity_set_at,
+				workspace = project_path,
+			}
 
-            if self.workspaces[project_path] then
-                self.workspaces[project_path].updated_at = activity_set_at
-                activity.timestamps = self.options.show_time == 1
-                    and {
-                        start = self.workspaces[project_path].started_at,
-                    }
-                    or nil
-            else
-                self.workspaces[project_path] = {
-                    started_at = activity_set_at,
-                    updated_at = activity_set_at,
-                }
-            end
-        else
-            self.log:debug("No project detected")
+			if self.workspaces[project_path] then
+				self.workspaces[project_path].updated_at = activity_set_at
+				activity.timestamps = self.options.show_time == 1
+						and {
+							start = self.workspaces[project_path].started_at,
+						}
+					or nil
+			else
+				self.workspaces[project_path] = {
+					started_at = activity_set_at,
+					updated_at = activity_set_at,
+				}
+			end
+		else
+			self.log:debug("No project detected")
 
-            self.workspace = nil
-            self.last_activity = {
-                id = self.id,
-                file = buffer,
-                set_at = activity_set_at,
-                relative_set_at = relative_activity_set_at,
-                workspace = nil,
-            }
+			self.workspace = nil
+			self.last_activity = {
+				id = self.id,
+				file = buffer,
+				set_at = activity_set_at,
+				relative_set_at = relative_activity_set_at,
+				workspace = nil,
+			}
 
-            -- When no project is detected, set custom workspace text if:
-            -- * The custom function returns custom workspace text
-            -- * The configured workspace text does not contain a directive
-            -- (can't use the `format_status_text` method here)
-            local workspace_text = self.options.workspace_text
-            if type(workspace_text) == "function" then
-                local custom_workspace_text = workspace_text(nil, buffer)
-                if custom_workspace_text then
-                    activity.details = custom_workspace_text
-                end
-            elseif not workspace_text:find("%s") then
-                activity.details = workspace_text
-            end
-        end
-    end
+			-- When no project is detected, set custom workspace text if:
+			-- * The custom function returns custom workspace text
+			-- * The configured workspace text does not contain a directive
+			-- (can't use the `format_status_text` method here)
+			local workspace_text = self.options.workspace_text
+			if type(workspace_text) == "function" then
+				local custom_workspace_text = workspace_text(nil, buffer)
+				if custom_workspace_text then
+					activity.details = custom_workspace_text
+				end
+			elseif not workspace_text:find("%s") then
+				activity.details = workspace_text
+			end
+		end
+	end
 
-    -- Sync activity to all peers
-    self.log:debug("Sync activity to all peers...")
-    self:sync_self_activity()
+	-- Sync activity to all peers
+	self.log:debug("Sync activity to all peers...")
+	self:sync_self_activity()
 
-    self.log:debug("Setting Discord activity...")
-    self.discord:set_activity(activity, function(err)
-        if err then
-            self.log:error(string.format("Failed to set activity in Discord: %s", err))
-            return
-        end
+	self.log:debug("Setting Discord activity...")
+	self.discord:set_activity(activity, function(err)
+		if err then
+			self.log:error(string.format("Failed to set activity in Discord: %s", err))
+			return
+		end
 
-        self.log:info(string.format("Set activity in Discord for %s", filename))
-    end)
+		self.log:info(string.format("Set activity in Discord for %s", filename))
+	end)
 end
 
 -- Update Rich Presence for the current or provided vim buffer for an authorized connection
 Presence.update = Presence.discord_event(function(self, buffer, should_debounce)
-    -- Default update to not debounce by default
-    if should_debounce == nil then
-        should_debounce = false
-    end
+	-- Default update to not debounce by default
+	if should_debounce == nil then
+		should_debounce = false
+	end
 
-    -- Debounce Rich Presence updates (default to 10 seconds):
-    -- https://discord.com/developers/docs/rich-presence/how-to#updating-presence
-    local last_updated_at = self.last_activity.set_at
-    local debounce_timeout = self.options.debounce_timeout
-    local should_skip = should_debounce
-        and debounce_timeout
-        and last_updated_at
-        and os.time() - last_updated_at <= debounce_timeout
+	-- Debounce Rich Presence updates (default to 10 seconds):
+	-- https://discord.com/developers/docs/rich-presence/how-to#updating-presence
+	local last_updated_at = self.last_activity.set_at
+	local debounce_timeout = self.options.debounce_timeout
+	local should_skip = should_debounce
+		and debounce_timeout
+		and last_updated_at
+		and os.time() - last_updated_at <= debounce_timeout
 
-    if should_skip then
-        local message_fmt = "Last activity sent was within %d seconds ago, skipping..."
-        self.log:debug(string.format(message_fmt, debounce_timeout))
-        return
-    end
+	if should_skip then
+		local message_fmt = "Last activity sent was within %d seconds ago, skipping..."
+		self.log:debug(string.format(message_fmt, debounce_timeout))
+		return
+	end
 
-    if buffer then
-        self:update_for_buffer(buffer, should_debounce)
-    else
-        vim.schedule(function()
-            self:update_for_buffer(self.get_current_buffer(), should_debounce)
-        end)
-    end
+	if buffer then
+		self:update_for_buffer(buffer, should_debounce)
+	else
+		vim.schedule(function()
+			self:update_for_buffer(self.get_current_buffer(), should_debounce)
+		end)
+	end
 end)
 
 --------------------------------------------------
@@ -999,190 +1000,190 @@ end)
 
 -- Register some remote peer
 function Presence:register_peer(id, socket)
-    self.log:debug(string.format("Registering peer %s...", id))
+	self.log:debug(string.format("Registering peer %s...", id))
 
-    self.peers[id] = {
-        socket = socket,
-        workspace = nil,
-    }
+	self.peers[id] = {
+		socket = socket,
+		workspace = nil,
+	}
 
-    self.log:info(string.format("Registered peer %s", id))
+	self.log:info(string.format("Registered peer %s", id))
 end
 
 -- Unregister some remote peer
 function Presence:unregister_peer(id, peer)
-    self.log:debug(string.format("Unregistering peer %s... %s", id, vim.inspect(peer)))
+	self.log:debug(string.format("Unregistering peer %s... %s", id, vim.inspect(peer)))
 
-    -- Remove workspace if no other peers share the same workspace
-    -- Initialize to remove if the workspace differs from the local workspace, check peers below
-    local should_remove_workspace = peer.workspace ~= self.workspace
+	-- Remove workspace if no other peers share the same workspace
+	-- Initialize to remove if the workspace differs from the local workspace, check peers below
+	local should_remove_workspace = peer.workspace ~= self.workspace
 
-    local peers = {}
-    for peer_id, peer_data in pairs(self.peers) do
-        -- Omit peer from peers list
-        if peer_id ~= id then
-            peers[peer_id] = peer_data
+	local peers = {}
+	for peer_id, peer_data in pairs(self.peers) do
+		-- Omit peer from peers list
+		if peer_id ~= id then
+			peers[peer_id] = peer_data
 
-            -- Should not remove workspace if another peer shares the workspace
-            if should_remove_workspace and peer.workspace == peer_data.workspace then
-                should_remove_workspace = false
-            end
-        end
-    end
+			-- Should not remove workspace if another peer shares the workspace
+			if should_remove_workspace and peer.workspace == peer_data.workspace then
+				should_remove_workspace = false
+			end
+		end
+	end
 
-    self.peers = peers
+	self.peers = peers
 
-    -- Update workspaces if necessary
-    local workspaces = {}
-    if should_remove_workspace then
-        self.log:debug(string.format("Should remove workspace %s", peer.workspace))
-        for workspace, data in pairs(self.workspaces) do
-            if workspace ~= peer.workspace then
-                workspaces[workspace] = data
-            end
-        end
+	-- Update workspaces if necessary
+	local workspaces = {}
+	if should_remove_workspace then
+		self.log:debug(string.format("Should remove workspace %s", peer.workspace))
+		for workspace, data in pairs(self.workspaces) do
+			if workspace ~= peer.workspace then
+				workspaces[workspace] = data
+			end
+		end
 
-        self.workspaces = workspaces
-    end
+		self.workspaces = workspaces
+	end
 
-    self.log:info(string.format("Unregistered peer %s", id))
+	self.log:info(string.format("Unregistered peer %s", id))
 end
 
 -- Unregister some remote peer and set activity
 function Presence:unregister_peer_and_set_activity(id, peer)
-    self:unregister_peer(id, peer)
-    self:update()
+	self:unregister_peer(id, peer)
+	self:update()
 end
 
 -- Register a remote peer and sync its data
 function Presence:register_and_sync_peer(id, socket)
-    self:register_peer(id, socket)
+	self:register_peer(id, socket)
 
-    self.log:debug("Syncing data with newly registered peer...")
+	self.log:debug("Syncing data with newly registered peer...")
 
-    -- Initialize the remote peer's list including self
-    local peers = {
-        [self.id] = {
-            socket = self.socket,
-            workspace = self.workspace,
-        },
-    }
-    for peer_id, peer in pairs(self.peers) do
-        if peer_id ~= id then
-            peers[peer_id] = peer
-        end
-    end
+	-- Initialize the remote peer's list including self
+	local peers = {
+		[self.id] = {
+			socket = self.socket,
+			workspace = self.workspace,
+		},
+	}
+	for peer_id, peer in pairs(self.peers) do
+		if peer_id ~= id then
+			peers[peer_id] = peer
+		end
+	end
 
-    self:call_remote_method(
-        socket,
-        "sync_self",
-        { {
-            last_activity = self.last_activity,
-            peers = peers,
-            workspaces = self.workspaces,
-        } }
-    )
+	self:call_remote_method(
+		socket,
+		"sync_self",
+		{ {
+			last_activity = self.last_activity,
+			peers = peers,
+			workspaces = self.workspaces,
+		} }
+	)
 end
 
 -- Register self to any remote Neovim instances
 -- Simply emits to all nvim sockets as we have not yet been synced with peer list
 function Presence:register_self()
-    self:get_nvim_socket_paths(function(sockets)
-        if #sockets == 0 then
-            self.log:debug("No other remote nvim instances")
-            return
-        end
+	self:get_nvim_socket_paths(function(sockets)
+		if #sockets == 0 then
+			self.log:debug("No other remote nvim instances")
+			return
+		end
 
-        self.log:debug(string.format("Registering as a new peer to %d instance(s)...", #sockets))
+		self.log:debug(string.format("Registering as a new peer to %d instance(s)...", #sockets))
 
-        -- Register and sync state with one of the sockets
-        self:call_remote_method(sockets[1], "register_and_sync_peer", { self.id, self.socket })
+		-- Register and sync state with one of the sockets
+		self:call_remote_method(sockets[1], "register_and_sync_peer", { self.id, self.socket })
 
-        if #sockets == 1 then
-            return
-        end
+		if #sockets == 1 then
+			return
+		end
 
-        for i = 2, #sockets do
-            self:call_remote_method(sockets[i], "register_peer", { self.id, self.socket })
-        end
-    end)
+		for i = 2, #sockets do
+			self:call_remote_method(sockets[i], "register_peer", { self.id, self.socket })
+		end
+	end)
 end
 
 -- Unregister self to all peers
 function Presence:unregister_self()
-    local self_as_peer = {
-        socket = self.socket,
-        workspace = self.workspace,
-    }
+	local self_as_peer = {
+		socket = self.socket,
+		workspace = self.workspace,
+	}
 
-    local i = 1
-    for id, peer in pairs(self.peers) do
-        if self.options.auto_update and i == 1 then
-            self.log:debug(string.format("Unregistering self and setting activity for peer %s...", id))
-            self:call_remote_method(peer.socket, "unregister_peer_and_set_activity", { self.id, self_as_peer })
-        else
-            self.log:debug(string.format("Unregistering self to peer %s...", id))
-            self:call_remote_method(peer.socket, "unregister_peer", { self.id, self_as_peer })
-        end
-        i = i + 1
-    end
+	local i = 1
+	for id, peer in pairs(self.peers) do
+		if self.options.auto_update and i == 1 then
+			self.log:debug(string.format("Unregistering self and setting activity for peer %s...", id))
+			self:call_remote_method(peer.socket, "unregister_peer_and_set_activity", { self.id, self_as_peer })
+		else
+			self.log:debug(string.format("Unregistering self to peer %s...", id))
+			self:call_remote_method(peer.socket, "unregister_peer", { self.id, self_as_peer })
+		end
+		i = i + 1
+	end
 end
 
 -- Sync self with data from a remote peer
 function Presence:sync_self(data)
-    self.log:debug(string.format("Syncing data from remote peer...", vim.inspect(data)))
+	self.log:debug(string.format("Syncing data from remote peer...", vim.inspect(data)))
 
-    for key, value in pairs(data) do
-        self[key] = value
-    end
+	for key, value in pairs(data) do
+		self[key] = value
+	end
 
-    self.log:info("Synced runtime data from remote peer")
+	self.log:info("Synced runtime data from remote peer")
 end
 
 -- Sync activity set by self to all peers
 function Presence:sync_self_activity()
-    local self_as_peer = {
-        socket = self.socket,
-        workspace = self.workspace,
-    }
+	local self_as_peer = {
+		socket = self.socket,
+		workspace = self.workspace,
+	}
 
-    for id, peer in pairs(self.peers) do
-        self.log:debug(string.format("Syncing activity to peer %s...", id))
+	for id, peer in pairs(self.peers) do
+		self.log:debug(string.format("Syncing activity to peer %s...", id))
 
-        local peers = { [self.id] = self_as_peer }
-        for peer_id, peer_data in pairs(self.peers) do
-            if peer_id ~= id then
-                peers[peer_id] = {
-                    socket = peer_data.socket,
-                    workspace = peer_data.workspace,
-                }
-            end
-        end
+		local peers = { [self.id] = self_as_peer }
+		for peer_id, peer_data in pairs(self.peers) do
+			if peer_id ~= id then
+				peers[peer_id] = {
+					socket = peer_data.socket,
+					workspace = peer_data.workspace,
+				}
+			end
+		end
 
-        self:call_remote_method(
-            peer.socket,
-            "sync_peer_activity",
-            { {
-                last_activity = self.last_activity,
-                peers = peers,
-                workspaces = self.workspaces,
-            } }
-        )
-    end
+		self:call_remote_method(
+			peer.socket,
+			"sync_peer_activity",
+			{ {
+				last_activity = self.last_activity,
+				peers = peers,
+				workspaces = self.workspaces,
+			} }
+		)
+	end
 end
 
 -- Sync activity set by peer
 function Presence:sync_peer_activity(data)
-    self.log:debug(string.format("Syncing peer activity %s...", vim.inspect(data)))
-    self:cancel()
-    self:sync_self(data)
+	self.log:debug(string.format("Syncing peer activity %s...", vim.inspect(data)))
+	self:cancel()
+	self:sync_self(data)
 end
 
 function Presence:stop()
-    self.log:debug("Disconnecting from Discord...")
-    self.discord:disconnect(function()
-        self.log:info("Disconnected from Discord")
-    end)
+	self.log:debug("Disconnecting from Discord...")
+	self.discord:disconnect(function()
+		self.log:info("Disconnected from Discord")
+	end)
 end
 
 --------------------------------------------------
@@ -1191,98 +1192,98 @@ end
 
 -- FocusGained events force-update the presence for the current buffer unless it's a quickfix window
 function Presence:handle_focus_gained()
-    self.log:debug("Handling FocusGained event...")
+	self.log:debug("Handling FocusGained event...")
 
-    -- Skip a potentially extraneous update call on initial startup if tmux is being used
-    -- (See https://github.com/neovim/neovim/issues/14572)
-    if next(self.last_activity) == nil and os.getenv("TMUX") then
-        self.log:debug("Skipping presence update for FocusGained event triggered by tmux...")
-        return
-    end
+	-- Skip a potentially extraneous update call on initial startup if tmux is being used
+	-- (See https://github.com/neovim/neovim/issues/14572)
+	if next(self.last_activity) == nil and os.getenv("TMUX") then
+		self.log:debug("Skipping presence update for FocusGained event triggered by tmux...")
+		return
+	end
 
-    if vim.bo.filetype == "qf" then
-        self.log:debug("Skipping presence update for quickfix window...")
-        return
-    end
+	if vim.bo.filetype == "qf" then
+		self.log:debug("Skipping presence update for quickfix window...")
+		return
+	end
 
-    self:update()
+	self:update()
 end
 
 -- TextChanged events debounce current buffer presence updates
 function Presence:handle_text_changed()
-    self.log:debug("Handling TextChanged event...")
-    self:update(nil, true)
+	self.log:debug("Handling TextChanged event...")
+	self:update(nil, true)
 end
 
 -- VimLeavePre events unregister the leaving instance to all peers and sets activity for the first peer
 function Presence:handle_vim_leave_pre()
-    self.log:debug("Handling VimLeavePre event...")
-    self:unregister_self()
-    self:cancel()
+	self.log:debug("Handling VimLeavePre event...")
+	self:unregister_self()
+	self:cancel()
 end
 
 -- WinEnter events force-update the current buffer presence unless it's a quickfix window
 function Presence:handle_win_enter()
-    self.log:debug("Handling WinEnter event...")
+	self.log:debug("Handling WinEnter event...")
 
-    vim.schedule(function()
-        if vim.bo.filetype == "qf" then
-            self.log:debug("Skipping presence update for quickfix window...")
-            return
-        end
+	vim.schedule(function()
+		if vim.bo.filetype == "qf" then
+			self.log:debug("Skipping presence update for quickfix window...")
+			return
+		end
 
-        self:update()
-    end)
+		self:update()
+	end)
 end
 
 -- WinLeave events cancel the current buffer presence
 function Presence:handle_win_leave()
-    self.log:debug("Handling WinLeave event...")
+	self.log:debug("Handling WinLeave event...")
 
-    local current_window = vim.api.nvim_get_current_win()
+	local current_window = vim.api.nvim_get_current_win()
 
-    vim.schedule(function()
-        -- Avoid canceling presence when switching to a quickfix window
-        if vim.bo.filetype == "qf" then
-            self.log:debug("Not canceling presence due to switching to quickfix window...")
-            return
-        end
+	vim.schedule(function()
+		-- Avoid canceling presence when switching to a quickfix window
+		if vim.bo.filetype == "qf" then
+			self.log:debug("Not canceling presence due to switching to quickfix window...")
+			return
+		end
 
-        -- Avoid canceling presence when switching between windows
-        if current_window ~= vim.api.nvim_get_current_win() then
-            self.log:debug("Not canceling presence due to switching to a window within the same instance...")
-            return
-        end
+		-- Avoid canceling presence when switching between windows
+		if current_window ~= vim.api.nvim_get_current_win() then
+			self.log:debug("Not canceling presence due to switching to a window within the same instance...")
+			return
+		end
 
-        self.log:debug("Canceling presence due to leaving window...")
-        self:cancel()
-    end)
+		self.log:debug("Canceling presence due to leaving window...")
+		self:cancel()
+	end)
 end
 
 -- BufEnter events force-update the presence for the current buffer unless it's a quickfix window
 function Presence:handle_buf_enter()
-    self.log:debug("Handling BufEnter event...")
+	self.log:debug("Handling BufEnter event...")
 
-    if vim.bo.filetype == "qf" then
-        self.log:debug("Skipping presence update for quickfix window...")
-        return
-    end
+	if vim.bo.filetype == "qf" then
+		self.log:debug("Skipping presence update for quickfix window...")
+		return
+	end
 
-    self:update()
+	self:update()
 end
 
 -- BufAdd events force-update the presence for the current buffer unless it's a quickfix window
 function Presence:handle_buf_add()
-    self.log:debug("Handling BufAdd event...")
+	self.log:debug("Handling BufAdd event...")
 
-    vim.schedule(function()
-        if vim.bo.filetype == "qf" then
-            self.log:debug("Skipping presence update for quickfix window...")
-            return
-        end
+	vim.schedule(function()
+		if vim.bo.filetype == "qf" then
+			self.log:debug("Skipping presence update for quickfix window...")
+			return
+		end
 
-        self:update()
-    end)
+		self:update()
+	end)
 end
 
 return Presence
diff --git a/lua/presence/plugin_managers.lua b/lua/presence/plugin_managers.lua
index 3789ba3..7b92a43 100644
--- a/lua/presence/plugin_managers.lua
+++ b/lua/presence/plugin_managers.lua
@@ -1,5 +1,5 @@
 -- Different plugin manager names
 return {
-    ["packer"] = "packer",
-    ["vim-plug"] = "vim-plug",
+	["packer"] = "packer",
+	["vim-plug"] = "vim-plug",
 }