aserowy / tmux.nvim Goto Github PK
View Code? Open in Web Editor NEWtmux integration for nvim features pane movement and resizing from within nvim.
License: MIT License
tmux integration for nvim features pane movement and resizing from within nvim.
License: MIT License
Resizing works fine except for one specific scenario:
When there is tmux pane on the left, and a vim pane on the right that has a horizontal split, resizing from the vim pane(from either split) will not work:
When there is no horizontal split it will work; resizing from the tmux pane will work, if the vim instance is on the left instead it will work, etc...
Only this specific scenario just does nothing
Some plugins allow us to omit setup call if we use default setting. Please only force user to setup call if they wanna change default behavior. This will help remove boilerplate code in our config. Thank you
Long pressing M-h or other arrow commands continue to resize even when they keys are released.
Seems like the event listener for the key stcks all the keypresses.
Ideally it would stop once the keys are released
This could be implemented using a debounce on the keypress event.
Not sure how feasble it is in lua or with the limitations of the neovim api.
Hi!
I recently installed the plugin, however looks like there is no way I can make <C-hjlk>
work.
I'm using the default configuration as mentioned in the readme, navigation within tmux panes works good but never across neovim splits.
Neovim config
use({
"aserowy/tmux.nvim",
config = function() return require("tmux").setup({
sync_clipboard = false,
sync_unnamed = false,
}) end
})
tmux config
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
bind-key -T copy-mode-vi 'C-h' select-pane -L
bind-key -T copy-mode-vi 'C-j' select-pane -D
bind-key -T copy-mode-vi 'C-k' select-pane -U
bind-key -T copy-mode-vi 'C-l' select-pane -R
Curiously enough executing :lua require('tmux').move_right()
(or any of the other variants) works well. I've tried to set up the keymaps manually with no success. I also tried binding the actions to a different set of bindings:
vim.keymap.set({'n', 't'}, '<leader>wj', function () tmux.move_bottom() end)
vim.keymap.set({'n', 't'}, '<leader>wk', function () tmux.move_top() end)
vim.keymap.set({'n', 't'}, '<leader>wl', function() tmux.move_right() end)
vim.keymap.set({'n', 't'}, '<leader>wh', function() tmux.move_left() end)
This works as expected, and is what I'm using now as a fallback while trying to solve this since ideally I prefer tmux bindings and nvim bindings to be the same
I tried to deactivate other plugins just in case they might be overwriting the specific default bindings but I had no luck with that either.
Any Idea on how to troubleshoot this one?
Thanks!
If you have installed neovim via Nix, the recommended grep expression won't match the process name that ps
returns. In most cases, nix users are installing a wrapped version of neovim that shows up as .nvim-wrapped
. This line is working for me as of now in my tmux.conf
:
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?\.nvim-wrapped$'"
The wrapped version runs under this process name for diff mode as well, so no need to worry about the name changing for other modes (in my case, at least)
May want to add this to the README :)
I tried this plugin when opening tmux in neovim terminal buffer, but it seems it is not working.
I want to use vim's default keybindings (Ctrl-w + hjkl) to move between vim and tmux
So I set it as follows:
init.lua (NVIM v0.6.0-dev+bec7f47ce)
local map = vim.api.nvim_set_keymap
local map_opts = {noremap = true, silent = true}
map("", "<C-w>h", ":lua require'tmux'.move_left()<cr>", map_opts)
map("", "<C-w>j", ":lua require'tmux'.move_bottom()<cr>", map_opts)
map("", "<C-w>k", ":lua require'tmux'.move_top()<cr>", map_opts)
map("", "<C-w>l", ":lua require'tmux'.move_right()<cr>", map_opts)
tmux.conf (tmux 3.2a)
bind -n C-w switch-client -T NAVIGATOR
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind -T NAVIGATOR h if-shell "$is_vim" "send-keys C-w h" "select-pane -L"
bind -T NAVIGATOR j if-shell "$is_vim" "send-keys C-w j" "select-pane -D"
bind -T NAVIGATOR k if-shell "$is_vim" "send-keys C-w k" "select-pane -U"
bind -T NAVIGATOR l if-shell "$is_vim" "send-keys C-w l" "select-pane -R"
bind -T NAVIGATOR C-w send-keys C-w
It was possible, but it stopped responding from a certain version
What's wrong?
Could the plugin support the default key bindings as well?
When there are a few windows in neovim, and also a few pane in tmux window, and current pane is in fullscreen, I use C-hjkl
to jump to other window in neovim, but it jumped to other tmux pane, which is not what I wanted, If we can disable jump tmux panes in fullscreen, it would be useful.
When sync_clipboard
is disabled, there is no way to set the unnamed register
Example:
lua vim.fn.setreg('"', 'some text to copy')
Then trying to paste:
p
will return whatever is in the tmux buffer instead of register "
Could probably modify get_buffer_names()
to take an ignore option.
Happy to help with a PR.
Say I open multiple Tmux panes, the pane under focus is running Neovim in insert mode. I am not able to navigate to other panes using keyboard shortcuts. I have to switch to normal mode in Neovim and only then can I navigate from the pane running Neovim to another pane.
With proper settings, I hope that I can navigate between Tmux panes freely using keyboard shortcuts, even when the pane is running Neovim/Vim in insert mode.
Tmux 3.3a
tmux.nvim commit 673782b (2023 Sept 6)
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' { if -F '#{pane_at_left}' '' 'select-pane -L' }
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' { if -F '#{pane_at_bottom}' '' 'select-pane -D' }
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' { if -F '#{pane_at_top}' '' 'select-pane -U' }
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' { if -F '#{pane_at_right}' '' 'select-pane -R' }
bind-key -T copy-mode-vi 'C-h' if -F '#{pane_at_left}' '' 'select-pane -L'
bind-key -T copy-mode-vi 'C-j' if -F '#{pane_at_bottom}' '' 'select-pane -D'
bind-key -T copy-mode-vi 'C-k' if -F '#{pane_at_top}' '' 'select-pane -U'
bind-key -T copy-mode-vi 'C-l' if -F '#{pane_at_right}' '' 'select-pane -R'
local status_ok, tmux = pcall(require, "tmux")
if not status_ok then
return
end
tmux.setup {
navigation = {
cycle_navigation = false,
enable_default_keybindings = true,
persist_zoom = false,
},
resize = {
enable_default_keybindings = false,
},
}
Is there any way in which I can navigate between Tmux panes freely using keyboard shortcuts, even when the pane is running Neovim/Vim in insert mode? If so, how? Thanks!
This may be a stupid question, but aside from remapping the navigation to use ALT+key instead of CTRL+key how can I keep the bash behaviour of CTRL-l
to clear the screen.
I use ALT+{h,l} to cycle bufferline, and I would like to keep it
Hi, thanks for this great plugin. As the title state I'm looking for a way to enable navigation from nvim to tmux only when i'm in normal mode and not insert mode. Currently when I type to delete the previous char it switches to the next tmux panel from nvim.
Is there any option to do that ?
Thanks in advance.
I am using https://github.com/folke/lazy.nvim as my package manager and when I open it via :Lazy
it opens a floating window in nvim.
Trying to then navigate using tmux.nvim results in:
E5108: Error executing lua ...are/nvim/lazy/tmux.nvim/lua/tmux/navigation/
navigate.lua:37: WinLeave Autocommands for "*": Vim(substitute):E21: Cannot make changes, 'modifiable' is off
stack traceback:
[C]: in function 'wincmd'
...are/nvim/lazy/tmux.nvim/lua/tmux/navigation/navigate.lua:37: in
function 'to'
...l/share/nvim/lazy/tmux.nvim/lua/tmux/navigation/init.lua:30: in
function 'move_right'
[string ":lua"]:1: in main chunk
My config
return {
"aserowy/tmux.nvim",
keys = { "<C-h>", "<C-j>", "<C-k>", "<C-l>" },
config = function()
require("tmux").setup({
copy_sync = { enable = false },
navigation = { cycle_navigation = true, enable_default_keybindings = true },
resize = { enable_default_keybindings = true, resize_step_x = 1, resize_step_y = 1 },
})
end,
}
My best guess is that I am missing some config flag for floating windows, but I also feel that it was happening only since my upgrade from nvim 0.9.2 to 0.9.4. I'm suspecting that maybe neovim/neovim#25523 introduced an issue (it did for other plugins using auto_cmd
enables syncing of registers in tmux and nvim
I get the following error when I start neovim outside a tmux session:
line 442:
E5108: Error executing lua vim/shared.lua:64: s: expected string, got nil
stack traceback:
vim/shared.lua:64: in function 'gsplit'
vim/shared.lua:111: in function 'split'
...leon/.config/nvim/plugged/tmux.nvim/lua/tmux/wrapper.lua:26: in function 'get_socket'
...leon/.config/nvim/plugged/tmux.nvim/lua/tmux/wrapper.lua:30: in function 'execute'
...leon/.config/nvim/plugged/tmux.nvim/lua/tmux/wrapper.lua:40: in function 'get_version'
...leon/.config/nvim/plugged/tmux.nvim/lua/tmux/wrapper.lua:52: in function 'setup'
/home/leon/.config/nvim/plugged/tmux.nvim/lua/tmux/init.lua:25: in function 'setup'
/home/leon/.config/nvim/lua/init.lua:47: in main chunk
[C]: in function 'require'
[string ":lua"]:1: in main chunk
Press ENTER or type command to continue
Can be fixed by not calling get_version()
in setup()
in tmux.nvim/lua/tmux/wrapper.lua
:
local M = {}
function M.setup()
M.is_tmux = get_tmux() ~= nil
+ if not M.is_tmux then
+ return
+ end
M.version = get_version()
end
Here is my configuration
return {
"aserowy/tmux.nvim",
event = "VeryLazy",
opts = {
resize = {
enable_default_keybindings = false,
}
},
config = function(_, opts)
local tmux = require("tmux")
tmux.setup(opts)
map("n", "<C-S-H>", "<cmd>lua require('tmux').resize_left()<cr>", "resize")
end
}
But nothing happen when I press <C-S-H>
. Is it a limitation of tmux to bind <C-S-*>
keys?
Hey @aserowy,
I am using this plugin as alternative to https://github.com/christoomey/vim-tmux-navigator.
Moving around and reszing works.
Although I needed to PackerCompile
everything first, this wasn't necessary for other plugins so I was confused at first why it wasn't working.
A different issue that I stumbled on is that yanking from nvim it seems that the selection is yanked into PRIMARY
.
I can paste this selection into a different tmux window with middle mouse click
just fine and also paasting between nvim sessions works.
However would it be possible that the yanked text to be synced to CLIPBOARD
instead?
For multiple use-cases:
Hello!
Have you considered forking vim-tmux-navigator (the tmux config, not the vim plugin) so that we could push the resize config into that repo? Main motivation is I'd rather have the tmux conf snippet for resizing moved into the tpm plugin, rather than copy pasting it into my own (and everyone else's) tmux.conf.
I could create the tpm plugin for myself, but I think it'd be beneficial for everyone to be able to do just:
set -g @plugin 'aserowy/tmux.nvim'
I can submit a PR if you'r open to it.
Thanks!
to prevent this behavior:
printf "%q" "--"
this means, all escapes need to be reworked!
Hi,
I'm not sure what is going on. But when I go to other tmux pane inside vim.
vim's statusline disappear (or just a message).
When I just move pane with tmux command it remains.
$ should get excaped as well
The feature described in #7 seems to only work in zoom now. I see there were some issues and changes since I implemented it but I haven't looked closely at the details to follow everything.
Did you intend to revert the cycling vim buffers feature or is this a bug?
As described in the title, when opening the nvim tree the resize feature cannot be used in the vim panel.
Video:
Cool plugin,
Maybe add a way to increase the resize step
It could be confired like this
{
navigation = {
...
},
resize = {
enable_default_keybindings = true,
resize_step = 3,m
}
}
This happens every time I want to navigate from neovim to another tmux pane using those mappings.
This is a recent behaviour that didn't happen on older versions.
local packer = require("packer")
local use = packer.use
packer.startup(function()
use "wbthomason/packer.nvim"
use { "aserowy/tmux.nvim", config = function()
require"tmux".setup {navigation = {enable_default_keybindings = false}}
vim.cmd [[nnoremap <C-w>h <cmd>lua require('tmux').move_left()<cr>]]
vim.cmd [[nnoremap <C-w>j <cmd>lua require('tmux').move_bottom()<cr>]]
vim.cmd [[nnoremap <C-w>k <cmd>lua require('tmux').move_top()<cr>]]
vim.cmd [[nnoremap <C-w>l <cmd>lua require('tmux').move_right()<cr>]]
end
}
end)
foo@bar:~$ nvim --version
NVIM v0.6.0-dev+181-g5d633546b
Build type: Release
LuaJIT 2.1.0-beta3
Compiled by datwaft@dguevara
Features: +acl +iconv +tui
See ":help feature-compile"
system vimrc file: "$VIM/sysinit.vim"
fall-back for $VIM: "
/home/linuxbrew/.linuxbrew/Cellar/neovim/HEAD-5d63354/share/nvim"
Run :checkhealth for more info
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-w' if-shell "$is_vim" 'send-keys C-w' 'switch-client -Ttable1'
bind-key -Ttable1 'h' { if -F '#{pane_at_left}' '' 'select-pane -L' }
bind-key -Ttable1 'j' { if -F '#{pane_at_bottom}' '' 'select-pane -D' }
bind-key -Ttable1 'k' { if -F '#{pane_at_top}' '' 'select-pane -U' }
bind-key -Ttable1 'l' { if -F '#{pane_at_right}' '' 'select-pane -R' }
bind-key -Ttable1 '\' select-pane -l
bind-key -Ttable1 's' split-window -v -c "#{pane_current_path}"
bind-key -Ttable1 'v' split-window -h -c "#{pane_current_path}"
bind-key -Ttable1 'C-w' send-keys C-w
foo@bar:~$ tmux -V
tmux 3.0a
Starting in the latest commit (cb1f401), I get the following error on startup:
Error detected while processing $XDG_CONFIG_HOME/nvim/init.lua:
next3.4 could not get parsed!
next3.4
is my tmux version:
$ tmux -V
tmux next-3.4
I'm using tmux-git
from the AUR.
Using the previous commit (6e9597a) works without issue.
Hello there. Hope you're doing well. Thank you for creating this unifying plugin; it makes switching between nvim buffers and tmux panes less cognitively demanding.
Please see the following video:
As you can see, pressing Alt-h
cycles the tmux panes.
Inside my .tmux.conf
:
# navigation
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'M-h' if-shell "$is_vim" 'send-keys M-h' { if -F '#{pane_at_left}' '' 'select-pane -L' }
bind-key -n 'M-j' if-shell "$is_vim" 'send-keys M-j' { if -F '#{pane_at_bottom}' '' 'select-pane -D' }
bind-key -n 'M-k' if-shell "$is_vim" 'send-keys M-k' { if -F '#{pane_at_top}' '' 'select-pane -U' }
bind-key -n 'M-l' if-shell "$is_vim" 'send-keys M-l' { if -F '#{pane_at_right}' '' 'select-pane -R' }
bind-key -T copy-mode-vi 'M-h' if -F '#{pane_at_left}' '' 'select-pane -L'
bind-key -T copy-mode-vi 'M-j' if -F '#{pane_at_bottom}' '' 'select-pane -D'
bind-key -T copy-mode-vi 'M-k' if -F '#{pane_at_top}' '' 'select-pane -U'
bind-key -T copy-mode-vi 'M-l' if -F '#{pane_at_right}' '' 'select-pane -R'
tmux.lua
:
require("tmux").setup({
navigation = {
-- C-hjkl
enable_default_keybindings = false,
cycle_navigation = false,
},
})
local function map(mode, lhs, rhs, opts)
local options = { noremap = true, silent = true }
if opts then
options = vim.tbl_extend("force", options, opts)
end
vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end
map("n", "<A-h>", '<cmd>lua require("tmux").move_left()<cr>')
map("n", "<A-l>", '<cmd>lua require("tmux").move_right()<cr>')
map("n", "<A-k>", '<cmd>lua require("tmux").move_top()<cr>')
map("n", "<A-j>", '<cmd>lua require("tmux").move_bottom()<cr>')
As per instructed, "bindings in nvim must match the defined bindings in tmux". In nvim buffers, cycling navigation is indeed disabled:
My question is, what went wrong and how do I disable cycling navigation in tmux panes as well?
Any input is much appreciated. Thank you:)
Hi, thanks for the wonderful plugin.
I may not be aware of the details of this implementation so my apologies if this is impossible.
There are some plugins that overrides y
and p
to perform custom yanking, like
vim-cutlass and vim-yoink.
I found a problem that in this way you can't use these plugins together.
I saw that there is an autocmd for text yanking.
Here's the minimal example:
vim.api.nvim_create_autocmd({ "TextYankPost" }, {
callback = function()
vim.highlight.on_yank({ higroup = "Visual", timeout = 200 })
end,
})
Perhaps you can use such autocmds to perform buffer syncing rather than remapping y
key, and if all plugin developers do that it should be possible to override multiple functionalities related to yanks.
What do you think?
Sorry, it seems like you're already doing this. I don't know why vim-yoink
stopped working with this plugin installed, then. Any idea to make both work together?
I was trying this plugin out but realized that this plugin adds significant lag to commands. I had some remaps that used commands and it made them unusable.
e.g.
vim.api.nvim_set_keymap("n", "}", [[:keepjumps normal! }<cr>]], { noremap = true })
vim.api.nvim_set_keymap("n", "{", [[:keepjumps normal! {<cr>]], { noremap = true })
The arguments size_step_x
and size_step_y
is not used to define the tmux command. The following function defines the step equals to 1
. Can we please update this function to use both arguments?
tmux.nvim/lua/tmux/wrapper/tmux.lua
Lines 92 to 94 in 6ed82c5
How can I choose to sync only the * and + registers with tmux?
The bug detail is in the video.
My tmux config:
# Pane navigation
is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' { if -F '#{pane_at_left}' '' 'select-pane -L' }
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' { if -F '#{pane_at_bottom}' '' 'select-pane -D' }
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' { if -F '#{pane_at_top}' '' 'select-pane -U' }
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' { if -F '#{pane_at_right}' '' 'select-pane -R' }
My vim config
local status_ok, tmux = pcall(require, "tmux")
if not status_ok then
return
end
tmux.setup {
copy_sync = {
enable = false,
redirect_to_clipboard = false,
sync_clipboard = false,
sync_deletes = false,
},
navigation = {
-- Enables default keybindings (C-hjkl) for normal mode
enable_default_keybindings = true,
},
resize = {
-- Enables default keybindings (A-hjkl) for normal mode
enable_default_keybindings = true,
resize_step_x = 3,
resize_step_y = 3,
},
}
If I split tmux window in two panes side by side and run nvim on each split, the mappings won't move from one split to another, it only works in:
It not working in:
I'm not sure whether it used to work, I suspect it did because I've been using it for quite a while and only noticed this problem lately.
Recently I migrate from vim-tmux-navigator but I encounter this bug, when the vim pane is zoomed in, it does not cycle, no matter what persist_zoom
you've set
After some debugging I found that #{pane_at_top}
means if the pane is at the top at the specific moment you ask.
That's why when we run this in a zoomed in pane we get 1
and when we run that in a zoomed out pane we get 0
tmux -S <YOUR-SESSION-SOCKET> display-message -p '#{pane_at_top}'
That variable is not appropiate to find out if it has a neighbor in X
direction, nor to find if it's the very last pane, so basically it's useless for that purpose
So my recommendation is to go back to the behavior of the plugin vim-tmux-navigator
, What do you think?
Hey there. I had been a long neovim + tmux Ctrl[j,jk,h,l] user for long time. And recently found another alternative setup which satisfies all my needs. It's wezterm + its built-in multiplexer, which gives me:
The only missing part is make it works with the Ctrl[j,jk,h,l] nav workflow: to switch back and forth between panes and neovim windows seamlessly (resize panes as well, which I do not use). The solution for emacs + evil (vim binds) is already implemented. And perhaps, it is time to make it work for neovim as well.
The trick is to ask wezterm about the available panes at the interested side and use these ids to direct navigation like:
wezterm cli get-pane-direction right # capture id number as stdout output
wezterm cli activate-pane --pane-id 46 # use the id
What about to create a new backend (lets say wezterm
) and make the plugin work for wezterm also? Thank you for any input.
I wanted to yank and paste from the system clipboard to neovim with "+y
and "+p
, it works fine until I enter tmux. So I dug in and found this key bind from the plugin intersects it.
Line 95 in 5722007
vim.api.nvim_del_keymap('n', '"')
as a workaround.The plugin does not work when opening a float window.
You can find the details in the following video.
send the current selected line in nvim to tmux pane and execute it
configuration should enable
a further feature could be sending multi line selects
At first sight I thoght persist_zoom
option was about keeping the vim pane zoom when re-enter that pane, instead is about preventing switching to other pane when zoomed in.
So It would be cool to keep the zoom in the vim panes, because I found myself constantly typing prefix + z
to recover the zoom when switching to the vim panes
e.g.
When switching to vim pane
Maybe we can create this feature keep_zoom
or something like that to achieve this behavior
Hi @aserowy thanks for this great plugin!
I'm running into some unexpected behavior currently. If I have a tmux session and open nvim, <c-j>
et all. works. However, if I first run poetry shell
it no longer works. The mapping is set, but now nothing happens.
It must have something to do with poetry since if I activate the environment manually with source .venv/bin/activate
it does work.
Any ideas? I believe poetry shell spawns a subshell, (though $TMUX
remains set) and that might have something to do with it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.