cocoapods / claide Goto Github PK
View Code? Open in Web Editor NEWA small command-line interface framework.
License: MIT License
A small command-line interface framework.
License: MIT License
$ pod try NAME_OR_URL
Downloads the Pod with the given NAME (or Git URL), install its dependencies if
needed and opens its demo project. If a Git URL is provided the head of the repo
something like: arguments = [[['NAME', 'URL'], :required]]
For example for a command with the $ bin PATH ELEMENT_OF_LIST
signature it could be something like:
def self.completion_for_argument(argument)
case argument
when 'PATH'
:path
when 'ELEMENT_OF_LIST'
'bin list-elements'
end
end
$ pod --version
0.32.1
$ pod --version --verbose
0.32.1
cocoapods-plugins: 0.1.1
cocoapods-try: 0.2.0
Prefer usage of def self.method
definition instead of class << self
syntax for class methods.
In the command class where many methods are mirrored is hard to tell wether one is looking to a class or to an instance method without scrolling.
/c @alloy
I am making a command from the CLAide.
This is my code:
def run
puts "please input your name:"
userInput = gets.chomp.delete(' ')
puts userInput
end
but ,I got an error.
please input your name:
bundler: failed to load command: bin/dj (bin/dj)
Errno::ENOENT: No such file or directory @ rb_sysopen - code
/Users/cw/Documents/Dy/tools/DYAutomate/lib/DYAutomate/Command/codeGenerate.rb:43:in `gets'
/Users/cw/Documents/Dy/tools/DYAutomate/lib/DYAutomate/Command/codeGenerate.rb:43:in `gets'
/Users/cw/Documents/Dy/tools/DYAutomate/lib/DYAutomate/Command/codeGenerate.rb:43:in `block in run'
/Users/cw/Documents/Dy/tools/DYAutomate/lib/DYAutomate/Command/codeGenerate.rb:43:in `noecho'
/Users/cw/Documents/Dy/tools/DYAutomate/lib/DYAutomate/Command/codeGenerate.rb:43:in `run'
/Users/cw/.rvm/gems/ruby-2.4.1/gems/claide-1.0.3/lib/claide/command.rb:334:in `run'
bin/dj:5:in `<top (required)>'
How can I do it?
So, this is the stack trace. Specifically when calling danger
, no bundle exec
.
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/specification.rb:1896:in `method_missing': undefined method `full_require_paths' for #<Gem::Specification:0x3fc3d501ba48 claide-plugins-0.9.0> (NoMethodError)
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command/plugin_manager.rb:59:in `block (2 levels) in plugins_involved_in_exception'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command/plugin_manager.rb:58:in `each'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command/plugin_manager.rb:58:in `any?'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command/plugin_manager.rb:58:in `block in plugins_involved_in_exception'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command/plugin_manager.rb:57:in `select'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command/plugin_manager.rb:57:in `plugins_involved_in_exception'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command.rb:415:in `report_error'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command.rb:396:in `handle_exception'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command.rb:337:in `rescue in run'
from /Users/Samantha/.gem/ruby/2.0.0/gems/claide-1.0.0/lib/claide/command.rb:325:in `run'
from /Users/Samantha/.gem/ruby/2.0.0/gems/danger-0.10.1/bin/danger:5:in `<top (required)>'
from /Users/Samantha/.gem/ruby/2.0.0/bin/danger:23:in `load'
from /Users/Samantha/.gem/ruby/2.0.0/bin/danger:23:in `<main>'
$ gem -v
= 2.0.14.1
It looks like full_require_paths
was added in Rubygems 2.2 - which isn't installed by default http://blog.rubygems.org/2013/12/26/2.2.0-released.html
https://github.com/CocoaPods/CLAide/blob/master/lib/claide/command/plugin_manager.rb#L59
This only happens when a plugin crashes, which is why we've probably not seen it in CocoaPods yet, probably cause there's real software engineering going on over there 💃
/cc @samdmarshall
This is about porting this fragment from CocoaPods.
def self.report_error(exception)
if exception.is_a?(Interrupt)
puts "[!] Cancelled".red
Config.instance.verbose? ? raise : exit(1)
else
raise exception
end
end
/c @alloy
Just like pod install
.
With the growing number of cocoapods plugins that will be published next, maybe we should think about having some repo or any place to list them all?
Sure is everyone respect the cocoapods-<pluginname>
naming convention, we can gem search -d cocoapods-
, but this won't only match the plugins (beginning with cocoapods-core
and cocoapods-downloader
for example which are obviously not a plugins) and the naming convention is not a requirement for plugins anyway
This may be as simple as a YAML file listing all the plugins with their name, simple description and URL. This may be a more elaborate solution. But I think that keeping track of all the plugins that will emerge like cocoapods-open
and cocoapods-docs
will be necessary anyway, so that everyone is aware of what extensions/plugins are available 😉
/Library/Ruby/Gems/2.0.0/gems/claide-0.6.1/lib/claide/command/validation_helper.rb:77:in prettify_validation_suggestion': undefined method
ansi' for nil:NilClass
The following works
xcake new hi
but this does not giving the error above
xcake new hi hi
and this is my class
module Xcake
class Command
class New < Command
include Generators
self.arguments = [
["GENERATOR", true]
]
self.summary = 'Scaffolds new project.'
def initialize(argv)
@generator = argv.shift_argument
@args = argv.remainder
super
end
def validate!
super
unless @generator
help! "You must specify a generator when creating a new project."
end
end
def run
Generators::invoke @generator, @args
end
end
end
end
$ pod --version
0.32.1
$ pod search --version
[!] Unknown arguments: --version
$ pod --version
[!] The specification of arguments as a string has been deprecated Pod::Command::Lib::Docstats: `NAME`
0.33.0
$ env
Apple_PubSub_Socket_Render=/tmp/launch-en5dW9/Render
CMD_DURATION=4.40s
COLORFGBG=7;0
DESTINATION=/var/folders/x3/rxbktkzx4xlf98p4bsn60p040000gn/T/iTerm 1.0.0.20140421 Update
EDITOR=vim
GEM_HOME=/Users/kylef/gems
HOME=/Users/kylef
ITERM_PROFILE=Default
ITERM_SESSION_ID=w2t0p0
LANG=en_GB.UTF-8
LOGNAME=kylef
LSCOLORS=Gxfxcxdxbxegedabagacad
PATH=/Users/kylef/gems/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
PIP_REQUIRE_VIRTUALENV=true
PWD=/Users/kylef/Projects/cocode/palaver
SHELL=/usr/local/bin/fish
SHLVL=1
SSH_AUTH_SOCK=/tmp/launch-2JXa9u/Listeners
TERM=xterm-256color
TERM_PROGRAM=iTerm.app
TMPDIR=/var/folders/x3/rxbktkzx4xlf98p4bsn60p040000gn/T/
USER=kylef
__CF_USER_TEXT_ENCODING=0x1F5:0:0
__CHECKFIX1436934=1
__fish_bin_dir=/usr/local/Cellar/fish/2.1.0/bin
__fish_datadir=/usr/local/Cellar/fish/2.1.0/share/fish
__fish_help_dir=/usr/local/Cellar/fish/2.1.0/share/doc/fish
__fish_sysconfdir=/usr/local/Cellar/fish/2.1.0/etc/fish
CLAide already allows declaring some of the attributes on the class itself as summary
, description
and more or less arguments
, while the latter is not fully exposed in a DSL. I think this is inconsistent.
Allowing that would make it also a lot easier defining reusable pieces of the CLI and share them across different subcommands.
CocoaPods uses currently modules for that, but as they have to overwrite the initializer that works only good once and gets messy after that.
This could look like below:
class CoffeeMaker < CLAide::Command
self.description = 'Make delicious coffee from the comfort of your terminal.'
self.option '--[no-]milk', :flag, 'Don’t add milk', default: true
# * parses `--milk` as `true`
# * parses `--no-milk` as `false`
# * defines an attribute accessor `milk?`
self.option ['--sweetner', '-s'], 'sugar|honey', 'Use one of the available sweetners', multivalued: true
# * parses `-s sugar -s honey` as `['sugar', 'milk']`
# * parses `--sweetner sugar` as `['sugar']`
# * defines an attribute accessor `sweetners`
end
This DSL syntax is inspired by Clamp.
This was originally logged in Cocoapods main issue list and in the rubygems list (where some great analysis took place, including a reference to the actual bisected commit that caused it)
Logging it here because the actual problem appears to be CLAide here using internals from RubyGems that were unsafe to touch, so an internal refactor of RubyGems for performance triggered a problem here, which transitively breaks cocoapods in combo with ruby-gems-3.3.x
A workaround for affected cocoapods users was posted on the cocoapods issue so users won't get stuck, but it seems to me (could be wrong) that the rubygems change was valid + desired from their perspective and the goal is to fix up CLAide here so it functions with new rubygems versions
That's the context. All technical details referenced out from one comment here: CocoaPods/CocoaPods#11134 (comment)
Examples:
$ pod trunk register [email protected] 'Eloy Durán' --description='Personal Laptop'
$ pod trunk register [email protected] --description='Work Laptop'
Currently to describe the arguments of a command the following approach is used
class Command
self.arguments = 'ARG_1 [ARG_2]'
def validate!
super
help! "The ARG_1 argument is required." unless @ arg_1
end
end
This proposal is about having a more structure approach:
class Command
self.arguments = [
['ARG_1', :required],
['ARG_2', :optional]
]
end
With this information CLAide would take care of:
A description for arguments (like is done for the the options) is considered not required because the description of the command should take care of explaining them and thus would result in a duplication of information.
The compatibility with the current behaviour should be kept for one version and should just split the arguments by the space characters to convert them in an array and mark all of them as optional. A warning should be printed if a string is passed.
Currently in CLAide there is a safe net for plugin errors caused while they are loaded. However a runtime error can be identified as caused by a plugin only inspecting the backtrace. User for this reason might think that a crash has been caused by the base gem adopting CLAide.
This would clearly differentiate subcommands from arguments:
For example, assuming a local
subcommands for the search
command. We would have the following signatures.
pod search QUERY
pod search local QUERY
The problem with the above is that local
could be a valid QUERY
. The following approach avoids this confusion:
pod search QUERY
pod search:local QUERY
This approach has other benefits like simplified integration for say an autocompletion script.
The concept is taken from the heroku command line tool:
$ heroku addons --help
Usage: heroku addons
list installed addons
Additional commands, type "heroku help COMMAND" for more details:
addons:add ADDON # install an addon
addons:docs ADDON # open an addon's documentation in your browser
addons:downgrade ADDON # downgrade an existing addon
addons:list # list all available addons
addons:open ADDON # open an addon's dashboard in your browser
addons:remove ADDON1 [ADDON2 ...] # uninstall one or more addons
addons:upgrade ADDON # upgrade an existing addon
It’s not used by all users or even developers that work on CLAide, so it’s quality cannot be guaranteed.
In addition it appears that it doesn’t fully work well, @AliSoftware can you comment on that?
All in all, it’s bloat and as such should be moved out of this library, possibly into a plugin, which could just be a CocoaPods plugin for now.
The bootstrap
task should not install bundler (see this line). Instead, we should check if bundler is not installed and ask the user to install it manually.
Inspiration:
task :bootstrap do
if system('which bundler')
...
else
puts red("\nPlease install bundler manually")
puts "$ [sudo] gem install bundler"
end
end
$ pod install help
An error should be displayed
An exception happened
CocoaPods : 0.33.1
Ruby : ruby 2.0.0p451 (2014-02-24 revision 45167) [universal.x86_64-darwin13]
RubyGems : 2.0.14
Host : Mac OS X 10.9.2 (13C1021)
Xcode : 5.1.1 (5B1008)
Ruby lib dir : /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ b947340d648f51d66a6df1cbd1b5f7d8cf5a6de0
NoMethodError - undefined method `ansi' for nil:NilClass
/Users/kylef/gems/gems/claide-0.6.1/lib/claide/command/validation_helper.rb:77:in `prettify_validation_suggestion'
/Users/kylef/gems/gems/claide-0.6.1/lib/claide/command/validation_helper.rb:21:in `argument_suggestion'
/Users/kylef/gems/gems/claide-0.6.1/lib/claide/command.rb:436:in `validate!'
/Users/kylef/gems/gems/claide-0.6.1/lib/claide/command.rb:280:in `run'
/Users/kylef/gems/gems/cocoapods-0.33.1/lib/cocoapods/command.rb:48:in `run'
/Users/kylef/gems/gems/cocoapods-0.33.1/bin/pod:33:in `<top (required)>'
/Users/kylef/gems/bin/pod:23:in `load'
/Users/kylef/gems/bin/pod:23:in `<main>'
Does this exist anymore ? The gem installed on my system with cocoapods doesn't have it.
This is CLAide 0.6.1.
If you call a command with --verbose
and --help
in combination, CLAide shows a stack trace at the end of the printed help text.
$ ruby examples/make.rb --help --verbose | sed -e "s|$(pwd)|INSTALL_PATH|g"
Usage:
$ make COMMAND
Make delicious beverages from the comfort of yourterminal.
Commands:
+ coffee Drink brewed from roasted coffee beans
+ tea Drink based on cured leaves
Options:
--no-milk Don’t add milk to the beverage
--sweetner=[sugar|honey] Use one of the available sweetners
--completion-script Print the auto-completion script
--version Show the version of the tool
--verbose Show more debugging information
--no-ansi Show output without ANSI codes
--help Show help banner of specified command
REPO/lib/claide/command.rb:338:in `help!'
REPO/lib/claide/command.rb:456:in `help!'
REPO/lib/claide/command.rb:424:in `validate!'
examples/make.rb:34:in `validate!'
REPO/lib/claide/command.rb:270:in `run'
examples/make.rb:143:in `<main>'
Command::Repo::Add.new(CLAide::ARGV.new([name, url])).run
-> Command::Repo::Add.invoke(name, url)
The implementation can be similar to git:
$ git checkouta
git: 'checkouta' is not a git command. See 'git --help'.
Did you mean this?
checkout
The fuzzy_match
gem provides great fuzzy matching and can be used for this purpose. See CocoaPods/Core@fc9ce9f#commitcomment-4536408.
I’m thinking an attribute like CLAide::InformativeError#wraps_exception
. When the user specifies the --verbose
flag, the informative error would include the wrapped error message in its output and possibly show the wrapped backtrace instead of the Informative one.
Thoughts?
From this recommendation it would be nice, probably even possible, to setup some generation for CocoaPods zsh completions. Here is the homebrew completion library, as you can see you can do pretty much anything in them, including piping output from other commands to the completion list.
I would gladly write this setup. I think that it could be built dynamically at least to the extent of the commands and flags assuming we could track those down somewhere. The homebrew completion also completes things like brew install gi<tab>
by searching all formula to this:
Although I'm not sure I can think of a place for this.
This is about implementing the functionality of the coloured
and of the colorized
gems directly in CLAide.
The support should be provided via two files which would be responsibility of the clients to include (so not interested clients would not be affected): claude/ansi
and claude/ansi-stub
. The latter would add empty methods to the String
class so clients can conveniently control from a single point wether ansi codes should be used (instead of doing this).
This approach would provide the benefit on not requiring an an external dependency for this functionality.
can I add a command with option take a value?
for example:
def self.options
[
['--page=0', 'Page to begin fetch, by default 0.'],
].concat(super)
end
Using argument --page=103
will failed with following error:
[!] Unknown arguments: --page=103
If you require 'claide'
and then run rspec with warnings, claide always has a circular require.
$ rspec --warnings
/Users/bootstraponline/.rbenv/versions/2.2.4/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:55: warning: loading in progress, circular require considered harmful - /Users/bootstraponline/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/claide-1.0.0.beta.3/lib/claide/ansi.rb
Related discussion in CocoaPods/cocoapods-plugins#13 here
CLAide::Command::options
and Pod::Command::options
set up some default options for the root command, which are usually concat
with specific subcommand options each time we subclass… but sometimes we have to reject
some too.
For example --verbose
and --help
are common both to root command and subcommands, but --silent
is not always meaningfull to all commands (especially to commands that are designed to only print output and do no other action, like pod search
).
As a result, we often see pattern like this:
def self.option
[
["--full", "Search by name, summary, and description"],
["--stats", "Show additional stats (like GitHub watchers and forks)"],
...
].concat(super.reject { |option, _| option == '--silent' })
There sure could be a better way to implement it and help us selecting which options in a root command are to be inherited by subcommands (maybe some only conditionally), and which are specific to that very command but not subcommands.
For example, sthg like separating def self.inheritable_options(printonly_command)
from def self.options
, or some other idea (open for discussion)
I recently copy and pasted the plugin system you use into Fastlane, it would be awesome if you could extract that into a separate library. :)
I.e. allow --help
to also be -h
(if the user so chooses)
CLAide is showing up in my rspec warnings list. 😭
/claide-1.0.0.beta.3/lib/claide/argv.rb:218:
warning: private attribute?
/claide-1.0.0.beta.3/lib/claide/informative_error.rb:17:
warning: method redefined; discarding old exit_status
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.