danth / pathfinder.vim Goto Github PK
View Code? Open in Web Editor NEWVim plugin to suggest better movements
License: MIT License
Vim plugin to suggest better movements
License: MIT License
set rtp+=~/.config/nvim/autoload/plug.vim
call plug#begin('~/.config/nvim/plugged')
Plug 'junegunn/vim-peekaboo'
Plug 'AlphaMycelium/pathfinder.vim'
call plug#end()
Press i<C-r>
Allow setting a timeout after which the pathfinder will give up trying to find a path.
xxCxxA
xxB
Given some text like the above, the script sometimes decides that the best route from A
to C
would be j
to move the cursor down to B
, then k
to move it back up to C
.
However, in reality Vim remembers the column the cursor was originally on, so moving back upwards ends up on A
.
I find often this plugin will show me hints that are exactly equivalent to the keys I pressed or insignificantly different. It would be neat if the plugin was aware of my own keypresses (at the very least the number of them) and could use this information to not show hints that take the same number (or a larger number) of keypresses to accomplish what I did.
aaaaaaaaZaaaaY
bbbbbbbbb
cccccccccccccccccXc
Start from X and go to Y. 2k
ends up on Y. kk
ends up on Z. Currently kk
is suggested.
Instead of just concatenating all the motions together, echo them out step-by-step along with descriptions.
This would help beginners to learn what things do without having to look it up with :help
.
I find that the amount of time the popup is shown is a bit too short for me to read and assimilate.
Is there a setting in the plugin to make the duration the popup is shown a bit longer?
Use G
along with a count to jump to a specific line, when &number
is enabled and the line number to jump to is visible on screen.
This is a feature request to make the plugin track my position between edits and take those two points as the beginning and ending points for the path to be optimized. The way this can work is PathfinderBegin is auto set to take the point where the last edit was made as the starting pint and the moment I do an edit PathfinderRun auto runs.
Vim freezes for a while when transferring a large file to the server for pathfinding.
If a buffer is read-only, or unmodified, send only the file path and allow the server to read it from disk. This will not work while editing, but since this problem occurs most often with the help pages it can be at least an improvement.
I'm getting the following error when trying to run pathfinder on my installation of Neovim:
Error detected while processing function provider#python3#Call:
line 18:
Error invoking 'python_execute' on channel 4 (python3-script-host):
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/jack/.local/share/nvim/plugged/pathfinder.vim/pathfinder/client/plugin.py", line 15, in __init__
self.client = Client()
File "/home/jack/.local/share/nvim/plugged/pathfinder.vim/pathfinder/client/client.py", line 24, in __init__
self.open()
File "/home/jack/.local/share/nvim/plugged/pathfinder.vim/pathfinder/client/client.py", line 34, in open
self._build_server_cmd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE
File "/home/jack/.local/share/nvim/plugged/pathfinder.vim/pathfinder/client/client.py", line 58, in _build_server_cmd
python3_host_prog = vim.eval("g:python3_host_prog")
File "/home/jack/.local/lib/python3.9/site-packages/pynvim/plugin/script_host.py", line 205, in eval
obj = self.request("vim_eval", expr)
File "/home/jack/.local/lib/python3.9/site-packages/pynvim/api/nvim.py", line 182, in request
res = self._session.request(name, *args, **kwargs)
File "/home/jack/.local/lib/python3.9/site-packages/pynvim/msgpack_rpc/session.py", line 102, in request
raise self.error_wrapper(err)
pynvim.api.common.NvimError: Vim:E121: Undefined variable: g:python3_host_prog
This is from my :checkhealth
:
## Python 3 provider (optional)
- INFO: `g:python3_host_prog` is not set. Searching for python3 in the environment.
- INFO: Multiple python3 executables found. Set `g:python3_host_prog` to avoid surprises.
- INFO: Executable: /home/linuxbrew/.linuxbrew/bin/python3
- INFO: Other python executable: /usr/bin/python3
- INFO: Other python executable: /bin/python3
- INFO: Python version: 3.9.13
- INFO: pynvim version: 0.4.3
- OK: Latest pynvim is installed.
And this is my version info:
NVIM v0.7.0
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Compilation: /usr/bin/cc -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DNVIM_TS_HAS_SET_MATCH_LIMIT -DNVIM_TS_HAS_SET_ALLOCATOR -O2 -g -Og -g -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes -Wimplicit-fallthrough -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wvla -fstack-protector-strong -fno-common -fdiagnostics-color=always -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -DNVIM_MSGPACK_HAS_FLOAT32 -DNVIM_UNIBI_HAS_VAR_FROM -DMIN_LOG_LEVEL=3 -I/build/nvim/parts/nvim/build/build/config -I/build/nvim/parts/nvim/build/src -I/build/nvim/parts/nvim/build/.deps/usr/include -I/usr/include -I/build/nvim/parts/nvim/build/build/src/nvim/auto -I/build/nvim/parts/nvim/build/build/include
Compiled by root@lcy02-amd64-012
Features: +acl +iconv +tui
See ":help feature-compile"
system vimrc file: "$VIM/sysinit.vim"
fall-back for $VIM: "/usr/share/nvim"
Say we start on [
at the end of line 2, and find a path to the beginning of "weight" on line 13.
The pathfinder returns 2*
. That is made from:
*
to search for the next [
(on line 12)*
again to search for "weight", which moves down to the next lineHowever, running 2*
instead of **
causes [
to be searched twice, and ends up somewhere else.
An IndexError
is caused when deleting something at the end of a file, e.g. G
dap
, and then trying to pathfind to that location. We should be pathfinding in the buffer from just before the deletion, not afterwards.
Error detected while processing function PathfinderLoop[6]..provider#python3#Call:
line 18:
Error invoking 'python_execute' on channel 4 (python3-script-host):
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/ed/.vim/plugged/pathfinder.vim/pathfinder/commands.py", line 72, in autorun
run()
File "/home/ed/.vim/plugged/pathfinder.vim/pathfinder/commands.py", line 49, in run
client.pathfind(start_state.view, current_state.view, show_output)
File "/home/ed/.vim/plugged/pathfinder.vim/pathfinder/client.py", line 125, in pathfind
self.server_connection.send(
AttributeError: 'NoneType' object has no attribute 'send'`
I have the latest python3
and did a pip3 install
for timers
and popupwin
Numbers from 1 to 100 can be used with %
to jump to percentages of the buffer's total lines. These only need to appear as children of the start node.
In visual-line mode, it doesn't matter where exactly the cursor is as long as it lands on the same line as the target. This can be used to accept shorter paths.
if all nodes on target line have been closed:
backtrack from the one with the lowest g
When installing the plugin, this timer does not launch until Vim is restarted.
Add weights to motions based on the difficulty to understand/use them. For example, j
would be cheaper than ]]
.
There can then be a scale between selecting the shortest path, and the simplest path.
OS: Fedora 31
$ vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Apr 14 2020 22:30:44)
Included patches: 1-579
...
$ vim --version | grep +timers
+channel +insert_expand +path_extra +timers
$ vim --version | grep +python3
+conceal +linebreak +python3 +visualextra
$ python -V
3.7.6
Steps to reproduce
NOTE: Before doing this, I've run rm -rf ~/.vim
.
minPlug
:$ git clone https://github.com/Jorengarenar/minPlug.git ~/.vim/pack/plugins/opt/minPlug/
~/.vim/vimrc
are as follows:packadd minPlug
MinPlug AlphaMycelium/pathfinder.vim
:MinPlugInstall!
While installing the plugins, the following happens:
Error detected while processing /home/amasquelier/.vim/pack/plugins/opt/pathfinder.vim/plugin/main.vim:
line 12:
E221: Marker cannot start with lower case letter
File "<string>", line 1
<< endpython
^
SyntaxError: invalid syntax
line 13:
E1042: import/export can only be used in vim9script
line 14:
E1042: import/export can only be used in vim9script
line 15:
E492: Not an editor command: from os.path import normpath, join
line 17:
E492: Not an editor command: plugin_root_dir = vim.eval("fnamemodify(resolve(expand('<sfile>:p')), ':h')")
line 18:
E319: Sorry, the command is not available in this version: python_root_dir = normpath(join(plugin_root_dir, '..', 'python'))
line 19:
E492: Not an editor command: sys.path.insert(0, python_root_dir)
line 20:
E492: Not an editor command: endpython
line 27:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'commands'
vim -V
, and observe:Executing BufEnter Autocommands for "*"
autocommand sil call s:LocalBrowse(expand("<amatch>"))
Executing VimEnter Autocommands for "*"
Press ENTER or type command to continue
autocommand let s:timer = timer_start(100, 'PathfinderLoop', {'repeat': -1})
Press ENTER or type command to continue
Executing VimEnter Autocommands for "*"
Press ENTER or type command to continue
Error detected while processing function PathfinderLoop:
line 2:
Traceback (most recent call last):
Press ENTER or type command to continue
Error detected while processing function PathfinderLoop:
line 2:
File "<string>", line 1, in <module>
Press ENTER or type command to continue
Error detected while processing function PathfinderLoop:
line 2:
NameError: name 'commands' is not defined
Press ENTER or type command to continue
Error detected while processing function PathfinderLoop:
line 6:
Traceback (most recent call last):
Press ENTER or type command to continue
Error detected while processing function PathfinderLoop:
line 6:
File "<string>", line 1, in <module>
Press ENTER or type command to continue
Error detected while processing function PathfinderLoop:
line 6:
NameError: name 'commands' is not defined
Modifying the loop to do:
function! PathfinderLoop(timer)
" Check for responses from the server
python3 print(sys.path)
python3 commands.client.poll_responses()
...
shows the following:
['/usr/lib64/python37.zip', '/usr/lib64/python3.7', '/usr/lib64/python3.7/lib-dynload', '/usr/local/lib/python3.7/site-packages', '/usr/lib64/python3.7/site-packages', '/usr/lib/python3.7/site-packages', '_vim_path_']
so I'm not sure if this is something that minPlug
is doing wrong, and how it works with other plugin managers. I'm also not sure how PYTHONPATH
really works in regards to Vim.
Any ideas here?
Sadly, neovim has no support for 'popup' but has a similar feature called Floating windows. It would be great if those could be used if the plugin runs in neovim.
PS: Thanks for the great plugin in general.
H
and L
accept a count to change the number of lines from the top/bottom.
Folds are not transferred to the server.
This and #42 could be fixed by using mksession
as part of the transfer. That may also help with #39 and #32 if it gives better performance. sessionoptions
can be temporarily changed to only include necessary information, and the session is written to a temporary file.
Implement the use of search commands (/
) as a motion.
As I suggested here, a way to get at least some functionality could be:
Using searches in combination with other motions seems like a more difficult problem to tackle.
Launching MacVim with pathfinder.vim installed complains about g:python3_host_prog
not being found:
Error detected while processing /Users/itai/.dotfiles/vim/.vim/bundle/pathfinder.vim/plugin/main.vim:
line 27:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/itai/.dotfiles/vim/.vim/bundle/pathfinder.vim/pathfinder/client/plugin.py", line 15, in __init__
self.client = Client()
File "/Users/itai/.dotfiles/vim/.vim/bundle/pathfinder.vim/pathfinder/client/client.py", line 24, in __init__
self.open()
File "/Users/itai/.dotfiles/vim/.vim/bundle/pathfinder.vim/pathfinder/client/client.py", line 34, in open
self._build_server_cmd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE
File "/Users/itai/.dotfiles/vim/.vim/bundle/pathfinder.vim/pathfinder/client/client.py", line 43, in _build_server_cmd
python3_host_prog = vim.eval("g:python3_host_prog")
vim.error: Vim:E121: Undefined variable: g:python3_host_prog
Press ENTER or type command to continue
Interestingly, this line is only supposed to be hit if nvim
is present:
def _build_server_cmd(self):
"""Build the command used to launch the server Vim."""
if vim.eval("has('nvim')"):
python3_host_prog = vim.eval("g:python3_host_prog")
options = [
"--headless",
"--cmd",
f"let g:python3_host_prog='{python3_host_prog}'",
]
else:
options = ["-v", "--not-a-term"]
However, I'm not in Neovim, and both :echo has('nvim')
and :py3 print(vim.eval("has('nvim')"))
print 0
. I'm not sure what could cause vim.eval("has('nvim')")
to evaluate to a truthy value especially since executing the same test manually doesn't replicate that value.
It's not exactly g:python3_host_prog
itself that's an issue, because even if I manually define it, pathfinder.vim is setting options in order to launch a Neovim instance, and regular vim doesn't recognize --headless
. Any idea what might be causing this? Would it make sense to inspect v:progpath
instead of has('nvim')
because that's what eventually gets launched anyway? (Changing the condition to if vim.eval("has('nvim')" == 1:
resolves the issue of course, but this seems hacky since 0
should be falsy anyway, right?)
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Dec 3 2020 11:33:19)
macOS version
Included patches: 1-1719
Compiled by Homebrew
Huge version with MacVim GUI. Features included (+) or not (-):
+acl +file_in_path -mouse_sysmouse -tag_old_static
+arabic +find_in_path +mouse_urxvt -tag_any_white
+autocmd +float +mouse_xterm +tcl
+autochdir +folding +multi_byte +termguicolors
-autoservername -footer +multi_lang +terminal
+balloon_eval +fork() -mzscheme +terminfo
+balloon_eval_term +fullscreen +netbeans_intg +termresponse
+browse +gettext +num64 +textobjects
++builtin_terms -hangul_input +odbeditor +textprop
+byte_offset +iconv +packages +timers
+channel +insert_expand +path_extra +title
+cindent +ipv6 +perl +toolbar
+clientserver +job +persistent_undo +transparency
+clipboard +jumplist +popupwin +user_commands
+cmdline_compl +keymap +postscript +vartabs
+cmdline_hist +lambda +printer +vertsplit
+cmdline_info +langmap +profile +virtualedit
+comments +libcall -python +visual
+conceal +linebreak +python3 +visualextra
+cryptv +lispindent +quickfix +viminfo
+cscope +listcmds +reltime +vreplace
+cursorbind +localmap +rightleft +wildignore
+cursorshape +lua +ruby +wildmenu
+dialog_con_gui +menu +scrollbind +windows
+diff +mksession +signs +writebackup
+digraphs +modify_fname +smartindent -X11
+dnd +mouse -sound -xfontset
-ebcdic +mouseshape +spell +xim
+emacs_tags +mouse_dec +startuptime -xpm
+eval -mouse_gpm +statusline -xsmp
+ex_extra -mouse_jsbterm -sun_workshop -xterm_clipboard
+extra_search +mouse_netterm +syntax -xterm_save
-farsi +mouse_sgr +tag_binary
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
system gvimrc file: "$VIM/gvimrc"
user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
defaults file: "$VIMRUNTIME/defaults.vim"
system menu file: "$VIMRUNTIME/menu.vim"
fall-back for $VIM: "/Applications/MacVim.app/Contents/Resources/vim"
Compilation: clang -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_MACVIM -Wall -Wno-unknown-pragmas -pipe -DMACOS_X -DMACOS_X_DARWIN -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: clang -L. -fstack-protector-strong -L/Users/itai/Homebrew/lib -L/Users/itai/Homebrew/opt/libyaml/lib -L/Users/itai/Homebrew/opt/[email protected]/lib -L/Users/itai/Homebrew/opt/readline/lib -L. -fstack-protector-strong -L/Users/itai/Homebrew/lib -L/Users/itai/Homebrew/opt/libyaml/lib -L/Users/itai/Homebrew/opt/[email protected]/lib -L/Users/itai/Homebrew/opt/readline/lib -L/Users/itai/Homebrew/lib -o Vim -framework Cocoa -framework Carbon -lm -lncurses -liconv /Users/itai/Homebrew/lib/libintl.a -framework AppKit -L/Users/itai/Homebrew/opt/lua/lib -llua5.4 -fstack-protector-strong -L/System/Library/Perl/5.28/darwin-thread-multi-2level/CORE -lperl -L/Users/itai/Homebrew/opt/[email protected]/Frameworks/Python.framework/Versions/3.9/lib/python3.9/config-3.9-darwin -lpython3.9 -lintl -framework CoreFoundation -F/System/Library/Frameworks -framework Tcl -framework CoreFoundation -lruby.2.7
Use pre-existing marks to create suggestions. They only need to appear as children of the start node, since making other movements and then jumping to a mark wouldn't make sense.
I'm using Plug to manage plugins. I have the simple line
"Plug 'AlphaMycelium/pathfinder.vim'
I have Python 3.8.5 and pynvim 0.4.1. Here is the trace back I get when I open vim on any file:
Error detected while processing function PathfinderLoop[2]..provider#python3#Call: line 18:
Error invoking 'python_execute' on channel 3 (python3-script-host):
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/user/.vim/plugged/pathfinder.vim/pathfinder/client/client.py", l
ine 87, in poll_responses
self.handle_response(response_type, data)
File "/home/user/.vim/plugged/pathfinder.vim/pathfinder/client/client.py", l
ine 133, in handle_response
raise Exception("Pathfinding server encountered an exception:\n" + data)
Exception: Pathfinding server encountered an exception:
Traceback (most recent call last):
File "/home/user/.vim/plugged/pathfinder.vim/pathfinder/server/server.py", l
ine 57, in message_loop
self.do_action(data)
File "/home/user/.vim/plugged/pathfinder.vim/pathfinder/server/server.py", l
ine 74, in do_action
vim.current.window.options["scrolloff"] = data["scrolloff"]
File "/home/user/.local/lib/python3.8/site-packages/pynvim/api/common.py", line 116, in __setitem__
self._set(key, value)
File "/home/user/.local/lib/python3.8/site-packages/pynvim/api/common.py", line 58, in request
return self._session.request(name, self, *args, **kwargs)
File "/home/user/.local/lib/python3.8/site-packages/pynvim/api/nvim.py", line 182, in request
res = self._session.request(name, *args, **kwargs)
File "/home/user/.local/lib/python3.8/site-packages/pynvim/msgpack_rpc/session.py", line 104, in request
raise self.error_wrapper(err)
pynvim.api.common.NvimError: Invalid option name 'scrolloff'
Please let me know if I can provide any other information. Really like your plugin ๐
Add some images, maybe even animated GIFs, to the README file to illustrate what the plugin does.
Maybe also create diagrams to explain concepts like the search area and server/client.
The current selected node should be the one with the lowest G value. (This was erroneously removed.)
This can be done either by sorting the list, or looping to find the lowest value, depending on which has better performance.
Caching the return value of CalcG
where possible would also be a good idea so it's not really slow.
Add support for the f
,t
,F
,T
motions.
To improve performance, look ahead at the rest of the line to find which unique characters occur rather than looping through and testing every possible letter.
Sometimes, if pathfinding takes a while, you can forget what motion you did so the suggestion isn't very useful. I originally thought to highlight the positions in the buffer - but that wouldn't work if the user entered insert mode and deleted something while it was running.
Therefore, I suggest displaying a snapshot of the characters around the start and target within the suggestion window. Maybe a 5x5 area around the cursor. This could be placed above the suggestion, or put the start to the left and the target to the right so the popup doesn't get too tall.
Use colors to make it look different from the suggestion text - perhaps even use the original syntax highlighting if that is possible.
This would be disabled by default since it takes up a lot of screen space.
The plugin sometimes comes out with movements such as jumping to the very bottom of the buffer in order to reach something and use #
on it. This is a very efficient way in the eyes of the machine, but a human could not do that without first scrolling down to see what was there.
Therefore, I am suggesting limiting the pathfinding algorithm's search area based on the start and target positions. This can be done by ignoring child nodes which fall outside of the allowed area - which is something like "half a window height above and below the cursor".
Perhaps make a configuration variable so users can toggle this on or off.
line
para
graph
parag
raph
Start at line
in the example above, and get to the blank line at the bottom. Currently, j2}
is chosen. A better solution would be 3}
.
This happens because j
appears first in the config, and }
goes to the same location with the same weight, so is ignored. Since we don't know the path ahead yet, we cannot make a choice between the two.
I have added the plugin with vim-plug as per the instructions, installed it, and went about editing a markdown file moving naively (jjjjjjjjjwwwww
) to see the plugin work.
But nothing happened. I have python3 and timers (:echo has('python3')
and :echo ('timers')
both return 1
), and the :PathfinderBegin
and :PathfinderRun
commands are set but if I run them, nothing happens either.
This is my .vimrc: https://github.com/coaxial/dotfiles/blob/vim-mov/.vimrc#L147-L151
and this is my vim version:
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Mar 18 2020 18:29:15)
Included patches: 1-1453
Modified by [email protected]
Compiled by [email protected]
Huge version without GUI. Features included (+) or not (-):
+acl +farsi +mouse_sgr -tag_any_white
+arabic +file_in_path -mouse_sysmouse -tcl
+autocmd +find_in_path +mouse_urxvt +termguicolors
-autoservername +float +mouse_xterm +terminal
-balloon_eval +folding +multi_byte +terminfo
+balloon_eval_term -footer +multi_lang +termresponse
-browse +fork() -mzscheme +textobjects
++builtin_terms +gettext +netbeans_intg +timers
+byte_offset -hangul_input +num64 +title
+channel +iconv +packages -toolbar
+cindent +insert_expand +path_extra +user_commands
-clientserver +job -perl +vertsplit
-clipboard +jumplist +persistent_undo +virtualedit
+cmdline_compl +keymap +postscript +visual
+cmdline_hist +lambda +printer +visualextra
+cmdline_info +langmap +profile +viminfo
+comments +libcall -python +vreplace
+conceal +linebreak +python3 +wildignore
+cryptv +lispindent +quickfix +wildmenu
+cscope +listcmds +reltime +windows
+cursorbind +localmap +rightleft +writebackup
+cursorshape -lua -ruby -X11
+dialog_con +menu +scrollbind -xfontset
+diff +mksession +signs -xim
+digraphs +modify_fname +smartindent -xpm
-dnd +mouse +startuptime -xsmp
-ebcdic -mouseshape +statusline -xterm_clipboard
+emacs_tags +mouse_dec -sun_workshop -xterm_save
+eval +mouse_gpm +syntax
+ex_extra -mouse_jsbterm +tag_binary
+extra_search +mouse_netterm +tag_old_static
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -Wdate-time -g -O2 -fdebug-prefix-map=/build/vim-dfCUyu/vim-8.0.1453=. -fstack-protector-strong -Wformat -Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim -lm -ltinfo -lnsl -lselinux -lacl -lattr -lgpm -ldl -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -lpython3.6m -lpthread -ldl -lutil -lm
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.