tmm1 / ripper-tags Goto Github PK
View Code? Open in Web Editor NEWfast, accurate ctags generator for ruby source code using Ripper
License: MIT License
fast, accurate ctags generator for ruby source code using Ripper
License: MIT License
Motivation:
Code completion engines for Vim can be configured to draw upon tag files to power their suggestions. However, some of the major engines (e.g. YouCompleteMe ) need the language field to be present in the tag files so that they can give appropriate completions for the type of file you are editing.
More generally speaking, I think that the more ripper-tags
resembles ctags
from an external interface POV, the better. The library should be plug-and-play replacement for the Ruby programmer.
What needs to be done:
In implementation terms, this simply means adding a column that reads language:Ruby
to every line produced by ripper-tags
.
Happy to send a PR if you're interested in supporting this option (though LMK if there are any gotchas I should watch out for!)
Hello, and thank you for this awesome project
I am wondering what's the best way to generate tags for my gems. When I use ctags this is how I do it:
ctags -R --languages=ruby --exclude=.git --exclude=log . $(bundle list --paths)
I replicated with ripper-tags this way:
ripper-tags -R --exclude=.git --exclude=log . $(bundle list --paths)
But it is very slow (seconds in ctags, minutes in ripper-tags). I imagine this is because ripper-tags is written in ruby so there must be some overhead, but wondering if there is any better way?
Thank you!
Using my gem-ripper-tags
project, this does not work. Need to look into it:
# gem install gherkin --debug
Exception `NoMethodError' at /home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:51 - undefined method `gsub' for :call:Symbol
ERROR: While executing gem ... (NoMethodError)
undefined method `gsub' for :call:Symbol
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:51:in `block (2 levels) in ctags'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:48:in `each'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:48:in `block in ctags'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:41:in `open'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:41:in `ctags'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:74:in `block in index'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:69:in `chdir'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems/commands/ripper_tags_command.rb:69:in `index'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/gem-ripper-tags-1.0.0/lib/rubygems_plugin.rb:7:in `block in <top (required)>'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/installer.rb:210:in `call'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/installer.rb:210:in `block in install'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/installer.rb:209:in `each'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/installer.rb:209:in `install'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/dependency_installer.rb:297:in `block in install'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/dependency_installer.rb:270:in `each'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/dependency_installer.rb:270:in `each_with_index'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/dependency_installer.rb:270:in `install'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/commands/install_command.rb:121:in `block in execute'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/commands/install_command.rb:115:in `each'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/commands/install_command.rb:115:in `execute'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/command.rb:278:in `invoke'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/command_manager.rb:147:in `process_args'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/command_manager.rb:117:in `run'
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/1.9.1/rubygems/gem_runner.rb:65:in `run'
/home/lzap/.rbenv/versions/1.9.3-p327/bin/gem:21:in `<main>'
I do see this:
/home/lzap/.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/tag_ripper.rb:53:in `on_const_path_ref': undefined method `flatten!' for nil:NilClass
After changing the on_const_path_ref to return nil, ripper-tags does generate TAGs file, but Vim says it is in bad format on particular line (the line looks ok to me).
After installed the ripper-tags (gem install ripper-tags), I got the following errors:
MacBook-Pro-de-Felipe:~ feliperama$ ripper-tags -R -V ~/rails/sample_app/
Error parsing /Users/feliperama/rails/sample_app//vendor/bundle/gems/builder-3.1.4/test/performance.rb
/Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:44:in throw': uncaught throw #<ArgumentError: invalid byte sequence in UTF-8> (ArgumentError) from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:44:in
rescue in block in read'
from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:34:in block in read' from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:29:in
each'
from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:29:in inject' from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:29:in
read'
from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:78:in <top (required)>' from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in
require'
from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in require' from /Users/feliperama/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/ripper-tags-0.1.2/bin/ripper-tags:7:in
<top (required)>'
from /Users/feliperama/.rbenv/versions/2.0.0-p247/bin/ripper-tags:23:in load' from /Users/feliperama/.rbenv/versions/2.0.0-p247/bin/ripper-tags:23:in
RipperTags::Parser.extract("module Test\n Myclass.class_eval do\n end\n end", "app/models/my_class_test.rb")
Is it possible to extract Myclass
for tags?
I am facing this issue as Myclass
is defined in gem
and I am overriding it in my codebase. Is there a way to add these entries to tags so that it generates tags for my_class_test.rb
file.
I tried it with Ruby Ripper and it just ignores class_evals
.
Given my Gemfile is
gem 'cucumber'
gem 'rest-client'
And I export gem paths using
bundle list --paths > gem_list
Then I get gem_list as
$ cat gem_list
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/builder-3.2.2
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/bundler-1.10.6
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/cucumber-2.1.0
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/cucumber-core-1.3.0
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/diff-lcs-1.2.5
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/domain_name-0.5.25
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/ffi-1.9.10-x86-mingw32
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/gherkin3-3.1.2
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/http-cookie-1.0.2
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/mime-types-1.25.1
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/multi_json-1.11.2
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/multi_test-0.1.2
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/netrc-0.11.0
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/rest-client-1.8.0-x86-mingw32
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf-0.1.4
H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf_ext-0.0.7.1-x86-mingw32
When I run ripper-tags using cat
ripper-tags -R `cat gem_list` -V
Then ripper-tags only processes the last gem path & then just stops
$ ripper-tags -R `cat gem_list` -V
Parsing file H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf_ext-0.0.7.1-x86-mingw32/ext/unf_ext/extconf.rb
Parsing file H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf_ext-0.0.7.1-x86-mingw32/lib/unf_ext/version.rb
Parsing file H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf_ext-0.0.7.1-x86-mingw32/lib/unf_ext.rb
Parsing file H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf_ext-0.0.7.1-x86-mingw32/test/helper.rb
Parsing file H:/ruby-2.2.3-i386-mingw32/lib/ruby/gems/2.2.0/gems/unf_ext-0.0.7.1-x86-mingw32/test/test_unf_ext.rb
Hi,
We have a large codebase and it takes ripper tags around 25 minutes to run through the whole codebase. Is there a way to make it faster?
Significant portion of the code doesn't change so when I re-run it, it's mostly duplicating the task.
Some thoughts:
I run it as
git ls-files | \
ripper-tags --tag-relative -L - -f"$dir/$$.tags" --exclude="*.js" --exclude="*.sql"
When encountering a scope
with an empty name, ripper-tags
crashes.
Example file
# foo.rb
scope '' do
get :foo
end
Command
ripper-tags --version
ripper-tags foo.rb -f -
ripper-tags 0.6.1
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase//home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/vim_formatter.rb:92:in `fetch': key not found: :name (KeyError) from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/vim_formatter.rb:92:in `format' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/vim_formatter.rb:33:in `write' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:210:in `block (2 levels) in run' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:160:in `block (2 levels) in each_tag' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:159:in `each' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:159:in `block in each_tag' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:66:in `resolve_file' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:99:in `block in each_file' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:112:in `each' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:112:in `each_input_file' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:98:in `each_file' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/data_reader.rb:150:in `each_tag' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:209:in `block in run' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/vim_formatter.rb:25:in `block in with_output' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/default_formatter.rb:47:in `with_output' from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags/vim_formatter.rb:22:in `with_output'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:208:in `run'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:190:in `call'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:190:in `block in process_args'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:172:in `block in option_parser'
from /home/mange/.rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/optparse.rb:1062:in `initialize'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:80:in `new'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:80:in `option_parser'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/lib/ripper-tags.rb:177:in `process_args'
from /home/mange/.rvm/gems/ruby-2.4.1/gems/ripper-tags-0.6.1/bin/ripper-tags:15:in `<top (required)>'
from /home/mange/.rvm/gems/ruby-2.4.1/bin/ripper-tags:23:in `load'
from /home/mange/.rvm/gems/ruby-2.4.1/bin/ripper-tags:23:in `<main>'
from /home/mange/.rvm/gems/ruby-2.4.1/bin/ruby_executable_hooks:15:in `eval'
from /home/mange/.rvm/gems/ruby-2.4.1/bin/ruby_executable_hooks:15:in `<main>'
lib/ripper-tags/vim_formatter.rb:92:in `fetch': key not found: :name (KeyError)
lib/ripper-tags/vim_formatter.rb:92:in `format'
lib/ripper-tags/vim_formatter.rb:33:in `write'
lib/ripper-tags.rb:210:in `block (2 levels) in run'
lib/ripper-tags/data_reader.rb:160:in `block (2 levels) in each_tag'
lib/ripper-tags/data_reader.rb:159:in `each'
lib/ripper-tags/data_reader.rb:159:in `block in each_tag'
lib/ripper-tags/data_reader.rb:66:in `resolve_file'
lib/ripper-tags/data_reader.rb:99:in `block in each_file'
lib/ripper-tags/data_reader.rb:112:in `each'
lib/ripper-tags/data_reader.rb:112:in `each_input_file'
lib/ripper-tags/data_reader.rb:98:in `each_file'
lib/ripper-tags/data_reader.rb:150:in `each_tag'
lib/ripper-tags.rb:209:in `block in run'
lib/ripper-tags/vim_formatter.rb:25:in `block in with_output'
lib/ripper-tags/default_formatter.rb:47:in `with_output'
lib/ripper-tags/vim_formatter.rb:22:in `with_output'
lib/ripper-tags.rb:208:in `run'
lib/ripper-tags.rb:190:in `call'
lib/ripper-tags.rb:190:in `block in process_args'
lib/ripper-tags.rb:172:in `block in option_parser'
ruby-2.4.1/lib/ruby/2.4.0/optparse.rb:1062:in `initialize'
lib/ripper-tags.rb:80:in `new'
lib/ripper-tags.rb:80:in `option_parser'
lib/ripper-tags.rb:177:in `process_args'
bin/ripper-tags:15:in `<top (required)>'
I vote for any Fedora approved license.
This is the MWE that I extracted from the gem:
class Mwe
delegate %i[
text
] => :symbol
end
When running ripper-tags
on it, I get the following exception:
/home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/parser.rb:277:in `block in on_delegate': undefined method `first' for nil:NilClass (NoMethodError)
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/parser.rb:277:in `map'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/parser.rb:277:in `on_delegate'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/parser.rb:79:in `on_command'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:156:in `parse'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:156:in `parse_file'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:164:in `tag_extractor'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:136:in `block in each_tag'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:69:in `resolve_file'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:85:in `block in each_file'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:98:in `each'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:98:in `each_input_file'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:84:in `each_file'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/data_reader.rb:133:in `each_tag'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:199:in `block in run'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/vim_formatter.rb:25:in `block in with_output'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/default_formatter.rb:53:in `block in with_output'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/default_formatter.rb:52:in `open'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/default_formatter.rb:52:in `with_output'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags/vim_formatter.rb:22:in `with_output'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:198:in `run'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:180:in `call'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:180:in `block in process_args'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:162:in `block in option_parser'
from /home/malina/.rvm/rubies/ruby-2.4.2/lib/ruby/2.4.0/optparse.rb:1062:in `initialize'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:73:in `new'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:73:in `option_parser'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/lib/ripper-tags.rb:167:in `process_args'
from /home/malina/.rvm/gems/ruby-2.4.2/gems/ripper-tags-0.4.0/bin/ripper-tags:15:in `<top (required)>'
from /home/malina/.rvm/gems/ruby-2.4.2/bin/ripper-tags:23:in `load'
from /home/malina/.rvm/gems/ruby-2.4.2/bin/ripper-tags:23:in `<main>'
from /home/malina/.rvm/gems/ruby-2.4.2/bin/ruby_executable_hooks:15:in `eval'
from /home/malina/.rvm/gems/ruby-2.4.2/bin/ruby_executable_hooks:15:in `<main>'
It's more of a question rather than an issue because I'm not sure if it's bug or limitation of ctags.
If I have a class defined like this:
class A::B
end
When I create tag file, there is entry for B
class so if I highlight A::B
in vim (in some other file), and try to jump to definition in vim it can not found it. It works only if I select B
.
Hello! I'm trying to generate tags with bash ripper-tags -R --exclude=vendor
as it's suggested in the repo what leads me to the following error:
$ ripper-tags -R --exclude=vendor
[#<Errno::ENOENT: No such file or directory - -R>, "-R"]
/home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:26:in `read': No such file or directory - -R (Errno::ENOENT)
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:26:in `block in <top (required)>'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:24:in `each'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:24:in `<top (required)>'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ripper-tags:23:in `load'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ripper-tags:23:in `<main>'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ruby_executable_hooks:15:in `eval'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ruby_executable_hooks:15:in `<main>'
and if first argument is a directory bash ripper-tags . -R
, than there is an another error
[#<Errno::EISDIR: Is a directory - .>, "."]
/home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:26:in `read': Is a directory - . (Errno::EISDIR)
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:26:in `block in <top (required)>'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:24:in `each'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/gems/ripper-tags-0.1.1/bin/ripper-tags:24:in `<top (required)>'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ripper-tags:23:in `load'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ripper-tags:23:in `<main>'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ruby_executable_hooks:15:in `eval'
from /home/lessless/.rvm/gems/ruby-2.0.0-p247/bin/ruby_executable_hooks:15:in `<main>'
I've got this warning:
Gem::Specification#has_rdoc= is deprecated with no replacement. It will be removed on or after 2018-12-01.
How to solve?
Thanks!
The "foo" method definition will get correctly picked up here:
C = Class.new do
def foo() end
end
but not here (notice the .new
in the end):
C = Class.new do
def foo() end
end.new
Ripper-tags currently ignores method definitions in block contexts, such as:
Class.new {
def foo() end # this gets ignored
}
included do
def foo() end # this gets ignored
end
def foo
def obj.bar() end # this gets ignored
end
It should pick up those definitions because they are common patterns of adding methods via metaprogramming.
If I have an RSpec test and define a method within it - the method is not picked up by the ripper-tags's parser.
% cat foo_spec.rb
RSpec.describe 'foo' do
it do
expect(helper).to eq('foo')
end
def helper
'foo'
end
end
% ripper-tags -f- foo_spec.rb
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
Is that due to a limitation in the parser that blocks cannot have methods defined within them?
Is this something we could support?
Defining these methods have been a common strategy in my experience.
Example code bases:
I am using a memoization library so some methods are defined like this:
memoize def foo
# ...
end
The problem is they are ignored. Can this be fixed somehow?
ctags supports an option
--extras=q
Include an extra class-qualified tag entry for each tag
which is a member of a class
Seems like a similar option would be useful for ripper-tags.
Or?
On emacs at least, the default tagname is fully qualified.
And in a project where identifiers are duplicated in different namespaces, quickly getting the fully-qualified name is highly desirable.
I'm trying to configure Vim that uses tags generated by ripper-tags.
My vim configuration is:
set tags=./tags;
if executable('ripper-tags')
let g:easytags_languages = {'ruby': {'cmd': 'ripper-tags -R --extra=q --exclude=vendor --exclude=.git --exclude=log'}}
endif
let g:easytags_async=1
let g:easytags_auto_highlight=0
let g:easytags_events = ['BufWritePost']
On project directory I run command ripper-tags -R --extra=q --exclude=vendor --exclude=.git --exclude=log
to generate tags.
Than for example I have following code:
class A
def hello
1
end
end
class B
def hello
2
end
end
B.new.hello
If set cursor on last line at word hello
and push Ctrl + ]
than cursor jumps to definition of hello in class A, instead of class B. Is it known issue or I'm doing something wrong?
Hi,
I've created the extension vscode-ruby-ctags to integrates vscode with the ripper-tags generator to generate the ctags for ruby projects and to navigate on the code too...
I'm working on a atom version of this extension and maybe for the sublime-text too...any help I'll be grateful!
Thanks!
Ruby 2.0.0-p353
/Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:287:in `on_module': wrong number of arguments (3 for 1..2) (ArgumentError)
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:252:in `process'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:248:in `block in process'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:248:in `each'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:248:in `process'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:281:in `on_module_or_class'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:288:in `on_module'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:252:in `process'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:248:in `block in process'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:248:in `each'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:248:in `process'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/parser.rb:228:in `initialize'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/data_reader.rb:122:in `new'
from /Users/mikep/.gem/ruby/2.0.0/gems/ripper-tags-0.1.3/lib/ripper-tags/data_reader.rb:122:in `tag_extractor'
Hi everyone,
First of all, this is more of an enhancement request then an actual bug.
I'm trying to integrate ripper-tags as an external parser into @fishman's ctags, which is currently the most active and consistently updated fork of ctags available. One of the new features the fork brings is the introduction of --<LANG>-xcmd
option which allows users to define external parser command for specific languages.
However, in order for the external parser to work, it needs to tell ctags a list of all tag kinds for that language. So, I've skimmed through ripper's code base, pulled out all required info and hard coded it into a simple shell wrapper:
c classes
f methods
m modules
F singleton methods
(Please correct me if any of this is wrong)
But, this approach is not ideal and prone to braking whenever ripper-tags adds support for new kinds. It would be much better/cleaner if ripper-tags supported --list-kinds
and/or --list-kinds=Ruby
option natively. Any chance this could be added?
PS: --<LANG>-xcmd
documentation can be found at https://github.com/fishman/ctags/blob/master/docs/xcmd.rst
I am the author of a brand new VS code extension called Bust A Gem - https://marketplace.visualstudio.com/items?itemName=gurgeous.bust-a-gem. Bust A Gem uses ripper-tags to create a TAGS file and power Go To Definition. Thanks for creating ripper-tags! I'm excited to see how people use the extension and ripper-tags together.
I have my first official report of ripper-tags crashing on input. Something in devise 4.4.1, see below. Let me know if you need more help diagnosing. One suggestion - would it be possible for ripper-tags to output a bit more information when it crashes, like the current file/position/line? I think that would be very helpful.
ripper-tags -f TAGS -R devise-4.4.1
Traceback (most recent call last):
43: from ruby/bin/ripper-tags:23:in `<main>'
42: from ruby/bin/ripper-tags:23:in `load'
41: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/bin/ripper-tags:15:in `<top (required)>'
40: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:177:in `process_args'
39: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:80:in `option_parser'
38: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:80:in `new'
37: from ruby/lib/ruby/2.5.0/optparse.rb:1062:in `initialize'
36: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:172:in `block in option_parser'
35: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:190:in `block in process_args'
34: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:190:in `call'
33: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:208:in `run'
32: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/emacs_formatter.rb:28:in `with_output'
31: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/default_formatter.rb:52:in `with_output'
30: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/default_formatter.rb:52:in `open'
29: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/default_formatter.rb:53:in `block in with_output'
28: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/emacs_formatter.rb:30:in `block in with_output'
27: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags.rb:209:in `block in run'
26: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:133:in `each_tag'
25: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:84:in `each_file'
24: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:98:in `each_input_file'
23: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:98:in `each'
22: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:85:in `block in each_file'
21: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `resolve_file'
20: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `each'
19: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:63:in `block in resolve_file'
18: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `resolve_file'
17: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `each'
16: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:63:in `block in resolve_file'
15: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `resolve_file'
14: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `each'
13: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:63:in `block in resolve_file'
12: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `resolve_file'
11: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `each'
10: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:63:in `block in resolve_file'
9: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `resolve_file'
8: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:59:in `each'
7: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:63:in `block in resolve_file'
6: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:69:in `resolve_file'
5: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:136:in `block in each_tag'
4: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:165:in `tag_extractor'
3: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/data_reader.rb:165:in `new'
2: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/parser.rb:322:in `initialize'
1: from ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/parser.rb:347:in `process'
ruby/lib/ruby/gems/2.5.0/gems/ripper-tags-0.5.1/lib/ripper-tags/parser.rb:444:in `on_defs': wrong number of arguments (given 4, expected 3) (ArgumentError)
Gnu Global has the very useful ability to list the usages of a tag. Could this be supported in a future release?
If I have a Ruby function with a question mark in the name, then I cannot jump to that function name using a TAGS file generated with ripper-tags.
unless 1
class C
def foo() end
end
end
Neither "C" nor "foo" tags will get generated here because of the unless
block.
Would be handy for compatibility with exuberant ctags and vim-guttentags :)
In some case in Ruby i use nested method same this:
# a.rb
class A
def testInstanceA
def testSubInstance
end
end
def self.testClassA
end
end
universal ctags make tag also for my nested method, but ripper-tgas no.
ctags --languages=ruby
A a.rb /^class A$/;" class line:8 language:Ruby
B b.rb /^class B$/;" class line:8 language:Ruby
testClassA a.rb /^ def self.testClassA$/;" singletonMethod line:14 language:Ruby class:A
testClassB b.rb /^ def self.testClassB$/;" singletonMethod line:12 language:Ruby class:B
testInstanceA a.rb /^ def testInstanceA$/;" method line:9 language:Ruby class:A
testInstanceB b.rb /^ def testInstanceB$/;" method line:9 language:Ruby class:B
testSubInstance a.rb /^ def testSubInstance$/;" method line:10 language:Ruby method:A.testInstanceA
ripper-tags -R
A a.rb /^class A$/;" c
B b.rb /^class B$/;" c
testClassA a.rb /^ def self.testClassA$/;" F class:A
testClassB b.rb /^ def self.testClassB$/;" F class:B
testInstanceA a.rb /^ def testInstanceA$/;" f class:A
testInstanceB b.rb /^ def testInstanceB$/;" f class:B
When we experience a parser error, we want to see the file.
That would be easier to investigate then.
This assignment:
A::B::C = 1
should define the "C" tag with class:A.B
namespace, but instead it defines the A::B::C
tag.
Please release 0.1.2! I'm using it from the source now, works great (y)
It looks like an Array of { key: value }
Hashes blows up the parser if the key: value
parts don't have { }
around them. It's valid Ruby either way, but the parser requires the braces.
To reproduce:
module MyModule
TEST_DATA = [
{ foo_id1: '1111' }, # Works
foo_id2: '2222', # Fails
]
end
ripper-tags PATH_TO_FILE_ABOVE
Thanks for adding --append, working well! One issue I've found is the following,
$ rm -f ./tags
$ ripper-tags --append ./lib/ripper-tags.rb
Will error with ripper-tags: No such file or directory @ rb_sysopen - ./tags
.
Hello
Does anyone know a way to found the ctags of a function define in a module.
I have this in a controller
def add_user
respond_to do |format|
format.js do
@group.add_user @user
end
end
end
when searching the tag of .add_user
it jump to first line but, add_user is define in a module.
module Abstracts::GroupRolesManagement
def add_user user
...
end
end
Trying with ripper tags doesn't solve my issue.
Thanks in advance
Consider this failing test:
def test_extract_access_by_symbol
tags = extract(<<-EOC)
module Test
def foo(); end
private_class_method :foo
end
EOC
pp tags
foo = tags.find { |t| t[:name] == 'foo' }
assert_equal 'private', foo[:access]
end
and its console output (from pp tags
, compacted slightly):
[{:kind=>"module", :line=>1, :language=>"Ruby", :path=>"(eval)",
:pattern=>" module Test", :full_name=>"Test", :name=>"Test"},
{:kind=>"method", :line=>2, :language=>"Ruby", :path=>"(eval)",
:pattern=>" def foo(); end", :name=>"foo", :full_name=>"Test#foo",
:class=>"Test"},
{:kind=>"method", :line=>3, :language=>"Ruby", :path=>"(eval)",
:pattern=>" private_class_method :foo",
:access=>"private",
:name=>3,
:full_name=>"Test#3",
:class=>"Test"}]
Problems:
foo
is defined twice: on lines 2 and 3The second problem is relatively easy to fix: when handling private_class_method
etc, handle the case where args[1]
doesn't start with a :def
symbol. In that case, args contains a list of method names to make private, so we can emit tags accordingly.
This won't fix the other problems, though. What should happen for line 3 is: update access on existing tag for method foo to private, in effect merging the two existing definitions.
When running ripper-tags with -R
it should failed and crash:
$ ripper-tags -r
/Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/parser.rb:303:in `on_assign': wrong number of arguments (6 for 3) (ArgumentError)
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/parser.rb:256:in `process'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/parser.rb:233:in `initialize'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:124:in `new'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:124:in `tag_extractor'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:95:in `block in each_tag'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:58:in `block in each_file'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:48:in `block (2 levels) in find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:48:in `block (2 levels) in find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:51:in `block in find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:42:in `each'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:42:in `find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:48:in `block in find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:42:in `each'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:42:in `find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:48:in `block in find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:42:in `each'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:42:in `find_files'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:58:in `each_file'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/data_reader.rb:92:in `each_tag'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:145:in `block in run'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/vim_formatter.rb:24:in `block in with_output'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/default_formatter.rb:37:in `block in with_output'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/default_formatter.rb:36:in `open'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/default_formatter.rb:36:in `with_output'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags/vim_formatter.rb:21:in `with_output'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:144:in `run'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:126:in `call'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:126:in `block in process_args'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:114:in `block in option_parser'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/optparse.rb:885:in `initialize'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:33:in `new'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:33:in `option_parser'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/lib/ripper-tags.rb:119:in `process_args'
from /Users/mlhamel/.gem/ruby/2.0.0/gems/ripper-tags-0.2.0/bin/ripper-tags:10:in `<top (required)>'
from /Users/mlhamel/.gem/ruby/2.0.0/bin/ripper-tags:23:in `load'
from /Users/mlhamel/.gem/ruby/2.0.0/bin/ripper-tags:23:in `<main>'
Specifically this file.
Error message is
/home/k3rni/.gem/ruby/2.4.3/gems/ripper-tags-0.5.0/lib/ripper-tags/parser.rb:331:in `emit_tag': undefined method `-' for nil:NilClass (NoMethodError)
The problem is triggered by line 33, where def_delegator
is called with its second argument not a symbol, but a name assigned two lines earlier. It is not flattened properly, and line number is nil. And this is what explodes. But simply unpacking that won't fix the problem, as using the name directly and not the symbol that is assigned to it will cause tags file to be wrong. Probably the safest way is to ignore such declarations entirely, maybe issue a warning.
Parse tree for this file below, problematic place marked with extra hashes.
[[:module,
["FaradayMiddleware", 4],
[[:class,
["OAuth", 23],
["Faraday::Middleware", 23],
[[:assign,
"AUTH_HEADER",
[:call, "Authorization", "freeze", nil, nil],
26],
[:assign,
"CONTENT_TYPE",
[:call, "Content-Type", "freeze", nil, nil],
27],
[:assign,
"TYPE_URLENCODED",
[:call, "application/x-www-form-urlencoded", "freeze", nil, nil],
28],
[:assign, "parser_method", ["parse_nested_query", 31], 31],
[:assign,
"parser_module",
[:call, "Faraday::Utils", "respond_to?", [["parser_method", 32]], nil],
32],
[:def, ["parser_method", 33], nil], ##############
[:def, "initialize", 35],
[:def, "call", 40],
[:def, "oauth_header", 45],
[:def, "sign_request?", 52],
[:def, "oauth_options", 56],
[:def, "body_params", 64],
[:def, "include_body_params?", 74],
[:def, "signature_params", 79]]]]],
[:assign, "Faraday::Request::OAuth", ["FaradayMiddleware::OAuth", 87], 87]]
While this is rather trivial for the gem's author to fix, Ripper should definitely not crash on this.
It would be nice to have --exclude option like in rsync.
some emacs package auto search the correct directory which TAGS
should
live in, and auto add -f /my/tags/file/path/default_tags_name
.
If we hardcode with -f ./TAGS
, will make this(auto search) function invalid.
So, I have to do is when update this gem, chanage tags_file_name
default value
to ./TAGS
manually to make emacs package to worked.
following is my emacs config:
(require 'ctags-update)
(setq ctags-update-command "ripper-tags"
ctags-update-delay-seconds 30
;; Here we could not specify -f arg. because it will broken this package.
ctags-update-other-options '("--exclude='*.elc'" "--exclude='*.class'" "--exclude='.git'"
"--exclude='.svn'" "--exclude='SCCS'" "--exclude='RCS'"
"--exclude='CVS'" "--exclude='EIFGEN'" "--exclude='vendor'"
"--force" "--extra=q" "-e")
)
Given a class like this in a project:
class A
private attr_reader :x
end
Running ripper-tags -R
will die in the Vim formatter with:
/var/lib/gems/2.7.0/gems/ripper-tags-0.9.0/lib/ripper-tags/vim_formatter.rb:104:in `fetch': key not found: :name (KeyError)
The tag object in question is missing the :name
property:
{
:kind=>"method",
:line=>2,
:language=>"Ruby",
:path=>"a.rb",
:pattern=>" private attr_reader :x",
:access=>"private",
:full_name=>"A#",
:class=>"A"
}
I thought this might be related to the version of Ruby that I'm using, but when I checked the AST returned by ripper
with a couple of different Ruby versions, it looks like they're very close to being the same (albeit not identical; see below). Additionally, I actually tried running ripper-tags
under both versions and got the same exception both times.
Here's Ruby 3.1.2 (ie. with pp Ripper.sexp('class A; private attr_reader :x; end')
):
[:program,
[[:class,
[:const_ref, [:@const, "A", [1, 6]]],
nil,
[:bodystmt,
[[:void_stmt],
[:command,
[:@ident, "private", [1, 9]],
[[:command,
[:@ident, "attr_reader", [1, 17]],
[:args_add_block, [[:symbol_literal, [:symbol, [:@ident, "x", [1, 30]]]]], false]]]]],
nil,
nil,
nil]]]]
vs Ruby 2.7.4 (ie. with pp Ripper.sexp('class A; private attr_reader :x; end')
):
[:program,
[[:class,
[:const_ref, [:@const, "A", [1, 6]]],
nil,
[:bodystmt,
[[:void_stmt],
[:command,
[:@ident, "private", [1, 9]],
[[:command,
[:@ident, "attr_reader", [1, 17]],
[:args_add_block,
[[:symbol_literal, [:symbol, [:@ident, "x", [1, 30]]]]],
false]]]]],
nil,
nil,
nil]]]]
The workaround for now is to rewrite the code, breaking it into distinct calls on separate lines:
class A
attr_reader :x
private :x
end
Somewhat tangentially, older Ruby only likes the rewritten form, because โ at least on 2.7.4 โ attr_reader
returns nil
and private
complains about being given nil
instead of a symbol or string, but it is still syntactically valid, at least insofar as ripper
accepts it. In 3.1.4 attr_reader
returns [:x]
and private
is happy with that.
gem-ctags recently started passing --tag-relative=yes
to ctags, which causes an exception needless argument: --tag-relative=yes (OptionParser::NeedlessArgument)
in ripper-tags (I'm using a ctags wrapper script that calls ripper-tags for Ruby files).
Can you add optional yes
and no
arguments?
Have to admit that I didn't realise the following was legal in Ruby (indeed I'm still not sure I fully get the semantics):
class EnsureTest
i = 5
ensure
i = 3
end
This is not gracefully handled by ripper-tags
(see stack trace at the end of this post)
The only place I've come across such code so far is syck/types.rb
back in Ruby 1.9.3
Can of course be worked around using a prudent --exclude
but I raise it for completeness sake
Running ripper-tags on /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/1.9.1
/home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:286:in `on_class': wrong number of arguments (4 for 3) (ArgumentError)
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:247:in `process'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:244:in `block in process'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:244:in `each'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:244:in `process'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:276:in `on_module_or_class'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:283:in `on_module'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:247:in `process'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:244:in `block in process'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:244:in `each'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:244:in `process'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/parser.rb:224:in `initialize'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:122:in `new'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:122:in `tag_extractor'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:93:in `block in each_tag'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:58:in `block in each_file'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:48:in `block (2 levels) in find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:48:in `block (2 levels) in find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:51:in `block in find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:42:in `each'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:42:in `find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:48:in `block in find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:42:in `each'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:42:in `find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:48:in `block in find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:42:in `each'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:42:in `find_files'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:58:in `each_file'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/data_reader.rb:90:in `each_tag'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:115:in `block in run'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/vim_formatter.rb:17:in `block in with_output'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/default_formatter.rb:20:in `block in with_output'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/default_formatter.rb:19:in `open'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/default_formatter.rb:19:in `with_output'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags/vim_formatter.rb:14:in `with_output'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:114:in `run'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:96:in `call'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:96:in `block in process_args'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:84:in `block in option_parser'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/optparse.rb:882:in `initialize'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:29:in `new'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:29:in `option_parser'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/lib/ripper-tags.rb:89:in `process_args'
from /home/myitcv/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/ripper-tags-0.1.2/bin/ripper-tags:10:in `<top (required)>'
from /home/myitcv/.rbenv/versions/1.9.3-p448/bin/ripper-tags:23:in `load'
from /home/myitcv/.rbenv/versions/1.9.3-p448/bin/ripper-tags:23:in `<main>'
Hi,
I was wondering if it would be possible to support --append
option.
I'm using universal ctags for creating tags
file for other languages than Ruby (JavaScript, CoffeeScript, etc.). Even though universal ctags has better support than exuberant ctags for Ruby (i.e. it support namespaced classes), it still can not handle --extra=q
option correctly.I would like to use ripper-tags just for ruby files and append ruby tags to ctags file created by universal tags.
I'm using ripper-tags for https://github.com/kwerle/ruby_language_server. THANKS! Though I may move away from it to get a little more control over how things work - mostly to get variable declarations included.
It makes me a little sad that the initialize method is reported as just a method, and not something magical like a constructor.
Hi I get an ArgumentError: invalid byte sequence in UTF-8
on my project when i execute ripper-tags -R
Any idea what might be the problem? It does not say which file has this invalid byte sequence
This is the stacktrace:
ArgumentError: invalid byte sequence in UTF-8
=== at org/jruby/RubyRegexp.java:1642
on_command at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/parser.rb:74
parse at org/jruby/ext/ripper/RubyRipper.java:306
parse_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:143
tag_extractor at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:151
each_tag at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:123
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:69
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:63
each at org/jruby/RubyArray.java:1613
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:59
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:63
each at org/jruby/RubyArray.java:1613
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:59
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:63
each at org/jruby/RubyArray.java:1613
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:59
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:63
each at org/jruby/RubyArray.java:1613
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:59
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:63
each at org/jruby/RubyArray.java:1613
resolve_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:59
each_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:85
each at org/jruby/RubyArray.java:1613
each_file at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:84
each_tag at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/data_reader.rb:120
run at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags.rb:145
with_output at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/vim_formatter.rb:24
with_output at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/default_formatter.rb:43
open at org/jruby/RubyIO.java:1181
with_output at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/default_formatter.rb:42
with_output at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags/vim_formatter.rb:21
run at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags.rb:144
call at org/jruby/RubyMethod.java:128
process_args at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags.rb:126
option_parser at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags.rb:114
initialize at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/1.9/optparse.rb:882
option_parser at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags.rb:33
process_args at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/lib/ripper-tags.rb:119
(root) at /home/dog/.rbenv/versions/jruby-1.7.15/lib/ruby/gems/shared/gems/ripper-tags-0.3.3/bin/ripper-tags:15
load at org/jruby/RubyKernel.java:1081
(root) at /home/dog/.rbenv/versions/jruby-1.7.15/bin/ripper-tags:23
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.