mirror of
https://github.com/jiriks74/presence.nvim
synced 2025-04-05 12:03:00 +02:00
Merge branch 'main' into lazy-plugin-manager
This commit is contained in:
commit
8b18beb367
15 changed files with 2264 additions and 1938 deletions
59
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
59
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -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
|
||||
|
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -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.
|
34
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
34
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
|
@ -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
|
14
.github/workflows/CI.yml
vendored
14
.github/workflows/CI.yml
vendored
|
@ -1,14 +0,0 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: nebularg/actions-luacheck@v1
|
||||
with:
|
||||
files: 'lua'
|
10
.github/workflows/luacheck.yml
vendored
Normal file
10
.github/workflows/luacheck.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
name: Luacheck
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
Luacheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Luacheck linter
|
||||
uses: lunarmodules/luacheck@v1
|
15
.github/workflows/stylua.yml
vendored
Normal file
15
.github/workflows/stylua.yml
vendored
Normal file
|
@ -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 .
|
123
README.md
123
README.md
|
@ -1,41 +1,63 @@
|
|||
<img src="https://gist.githubusercontent.com/andweeb/df3216345530234289b87cf5080c2c60/raw/8de399cfed82c137f793e9f580027b5246bc4379/presence.nvim.png" alt="presence.nvim">​
|
||||
# 
|
||||
|
||||
**[Features](#features)** | **[Installation](#installation)** | **[Configuration](#configuration)** | **[Troubleshooting](#troubleshooting)** | **[Development](#development)** | **[Contributing](#contributing)**
|
||||
This repository uses
|
||||
[](https://conventionalcommits.org)
|
||||
|
||||
**[Features](#features)** | **[Installation](#installation)** |
|
||||
**[Configuration](#configuration)** | **[Troubleshooting](#troubleshooting)** |
|
||||
**[Development](#development)** | **[Contributing](#contributing)**
|
||||
|
||||
> Discord [Rich Presence](https://discord.com/rich-presence) plugin for [Neovim](https://neovim.io)
|
||||
|
||||
<img src="https://gist.githubusercontent.com/andweeb/df3216345530234289b87cf5080c2c60/raw/ad916fec8de921d0021801a0af877a5349621e7e/presence-demo-a.gif" width="100%" alt="demo.gif">
|
||||

|
||||
|
||||
## Features
|
||||
* Light and unobtrusive
|
||||
* No Python/Node providers (or CoC) required
|
||||
* Cross-platform support: macOS, nixOS, Linux[\*](#notes), Windows[\*](https://github.com/andweeb/presence.nvim/projects/1#card-60537963), WSL[\*](https://github.com/andweeb/presence.nvim/wiki/Rich-Presence-in-WSL)
|
||||
* Startup time is fast(er than other Rich Presence plugins, by [kind of a lot](https://github.com/andweeb/presence.nvim/wiki/Plugin-Comparisons))
|
||||
* Written in Lua and [highly configurable](#configuration) in Lua (but also configurable in VimL if you want)
|
||||
* Manages Rich Presence across multiple Neovim instances in various environments (tmux panes/windows, ssh sessions, terminal tabs/windows, etc.)
|
||||
|
||||
- Light and unobtrusive
|
||||
- No Python/Node providers (or CoC) required
|
||||
- Cross-platform support: macOS, nixOS, Linux[\*](#notes),
|
||||
Windows, WSL
|
||||
- Startup time is fast(er than other Rich Presence plugins, by
|
||||
[kind of a lot](https://github.com/andweeb/presence.nvim/wiki/Plugin-Comparisons))
|
||||
- Written in Lua and [highly configurable](#configuration) in Lua
|
||||
(but also configurable in VimL if you want)
|
||||
- Manages Rich Presence across multiple Neovim instances in various environments
|
||||
(tmux panes/windows, ssh sessions, terminal tabs/windows, etc.)
|
||||
- Now with Flatpak support!
|
||||
|
||||
## Installation
|
||||
|
||||
Use your favorite plugin manager
|
||||
* [vim-plug](https://github.com/junegunn/vim-plug): `Plug 'andweeb/presence.nvim'`
|
||||
* [packer.nvim](https://github.com/wbthomason/packer.nvim): `use 'andweeb/presence.nvim'`
|
||||
|
||||
- [vim-plug](https://github.com/junegunn/vim-plug): `Plug 'jiriks74/presence.nvim'`
|
||||
- [packer.nvim](https://github.com/wbthomason/packer.nvim): `use 'jiriks74/presence.nvim'`
|
||||
- [lazy.nvim](https://github.com/folke/lazy.nvim):
|
||||
|
||||
```lua
|
||||
{
|
||||
'andweeb/presence.nvim',
|
||||
event = 'UIEnter',
|
||||
}
|
||||
"jiriks74/presence.nvim",
|
||||
event = "UIEnter",
|
||||
},
|
||||
```
|
||||
|
||||
#### Notes
|
||||
* Requires [Neovim 0.5](https://github.com/neovim/neovim/releases/tag/v0.5.0) or higher
|
||||
* Rich Presence should work automatically after installation (unless you're using WSL, in which case [see here](https://github.com/andweeb/presence.nvim/wiki/Rich-Presence-in-WSL))
|
||||
* If you're using an unofficial Discord package on Linux ([flatpak](https://flathub.org/apps/details/com.discordapp.Discord), [snap](https://snapcraft.io/discord), etc.), you may need to follow some instructions to expose the Discord socket on your system (e.g. [flatpak instructions](https://github.com/flathub/com.discordapp.Discord/wiki/Rich-Precense-(discord-rpc)))
|
||||
### Notes
|
||||
|
||||
- Requires [Neovim 0.5](https://github.com/neovim/neovim/releases/tag/v0.5.0)
|
||||
or higher
|
||||
- Rich Presence should work automatically after installation
|
||||
(unless you're using WSL, in which case
|
||||
[see here](https://github.com/andweeb/presence.nvim/wiki/Rich-Presence-in-WSL))
|
||||
|
||||
## Configuration
|
||||
Configuration is not necessary for Rich Presence to work. But for those that want to override the default configs, the following options are available to configure in either Lua or VimL.
|
||||
|
||||
Configuration is not necesary unless you want to override the default config.
|
||||
|
||||
If you want to change the default config here are your options in Lua and VimL:
|
||||
|
||||
### Lua
|
||||
Require the plugin and call `setup` with a config table with one or more of the following keys:
|
||||
|
||||
Require the plugin and call `setup` with a config table with one or more of the
|
||||
following keys:
|
||||
|
||||
```lua
|
||||
-- The setup config table shows all available config options with their default values:
|
||||
|
@ -44,7 +66,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
|
||||
|
@ -65,13 +87,15 @@ require("presence").setup({
|
|||
```
|
||||
|
||||
### VimL
|
||||
|
||||
Or if global variables are more your thing, you can use any of the following instead:
|
||||
|
||||
```viml
|
||||
" General options
|
||||
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
|
||||
|
@ -91,23 +115,48 @@ let g:presence_line_number_text = "Line %s out of %s"
|
|||
```
|
||||
|
||||
## Troubleshooting
|
||||
* Ensure that Discord is running
|
||||
* Ensure that your Neovim version is 0.5 or higher
|
||||
* Ensure Game Activity is enabled in your Discord settings
|
||||
* Enable logging and inspect the logs after opening a buffer
|
||||
* Set the [`log_level`](#lua) setup option or [`g:presence_log_level`](#viml) to `"debug"`
|
||||
* Load a file and inspect the logs with `:messages`
|
||||
* If there is a `Failed to determine Discord IPC socket` error, your particular OS may not yet be supported
|
||||
* If you don't see an existing [issue](https://github.com/andweeb/presence.nvim/issues) or [card](https://github.com/andweeb/presence.nvim/projects/1#column-14183588) for your OS, create a prefixed [issue](https://github.com/andweeb/presence.nvim/issues/new) (e.g. `[Void Linux]`)
|
||||
* Still not working and need help? Create a new [issue](https://github.com/andweeb/presence.nvim/issues)!
|
||||
|
||||
- Ensure that Discord is running
|
||||
- Ensure that your Neovim version is 0.5 or higher
|
||||
- Ensure Game Activity is enabled in your Discord settings
|
||||
- Enable logging and inspect the logs after opening a buffer
|
||||
- Set the [`log_level`](#lua) setup option or [`g:presence_log_level`](#viml)
|
||||
to `"debug"`
|
||||
- Load a file and inspect the logs with `:messages`
|
||||
- If there is a `Failed to determine Discord IPC socket` error, your particular
|
||||
OS may not yet be supported
|
||||
- If you don't see an existing
|
||||
[issue](https://github.com/jiriks74/presence.nvim/issues)
|
||||
or [card](https://github.com/jiriks74/presence.nvim/projects/1#column-14183588)
|
||||
for your OS, create a prefixed
|
||||
[issue](https://github.com/jiriks74/presence.nvim/issues/new)
|
||||
(e.g. `[Void Linux]`)
|
||||
- Still not working and need help? Create a new
|
||||
[issue](https://github.com/jiriks74/presence.nvim/issues)!
|
||||
|
||||
## Development
|
||||
* Clone the repo: `git clone https://github.com/andweeb/presence.nvim.git`
|
||||
* Enable [logging](#configuration) and ensure that `presence.nvim` is **_not_** in the list of vim plugins in your config
|
||||
* Run `nvim` with your local changes: `nvim --cmd 'set rtp+=path/to/your/local/presence.nvim' file.txt`
|
||||
* Ensure that there are no [luacheck](https://github.com/mpeterv/luacheck/) errors: `luacheck lua`
|
||||
|
||||
- Clone the repo: `git clone https://github.com/jiriks74/presence.nvim.git`
|
||||
- Enable [logging](#configuration) and ensure that `presence.nvim` is **_not_**
|
||||
in the list of vim plugins in your config
|
||||
- Run `nvim` with your local changes: `nvim --cmd
|
||||
'set rtp+=path/to/your/local/presence.nvim' file.txt`
|
||||
- Ensure that there are no [luacheck](https://github.com/mpeterv/luacheck/)
|
||||
errors: `luacheck lua`
|
||||
|
||||
## Contributing
|
||||
Pull requests are very welcome, feel free to open an issue to work on any of the open [todo items](https://github.com/andweeb/presence.nvim/projects/1?add_cards_query=is%3Aopen) or message [droob#1322](https://discordapp.com/users/241953146232897550) on Discord!
|
||||
|
||||
Asset additions and changes are also welcome! Supported file types can be found in [`file_assets.lua`](lua/presence/file_assets.lua) and their referenced asset files can be found [in this folder](https://www.dropbox.com/sh/j8913f0gav3toeh/AADxjn0NuTprGFtv3Il1Pqz-a?dl=0).
|
||||
**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)!
|
||||
|
||||
Asset additions and changes are also welcome! Supported file types can be found in
|
||||
[`file_assets.lua`](lua/presence/file_assets.lua) and their referenced asset files
|
||||
can be found [in this folder](https://www.dropbox.com/sh/j8913f0gav3toeh/AADxjn0NuTprGFtv3Il1Pqz-a?dl=0).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" },
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue