How to use completions when prefixing a command with bundle exec? - ruby

When I try to run a command like cap with bundle exec cap my completions for cap tasks do not work. Instead I get a directory listing:
> bundle exec cap -T
app/ config.ru Gemfile.lock package-lock.json reference/ yarn.lock
babel.config.js config/ Guardfile postcss.config.js spec/
bin/ db/ lib/ public/ ted_app_meta_data.yml
build/ doc/ log/ Rakefile tmp/
Capfile Gemfile package.json README.md vendor/
> cap -T
airbrake:deploy (Capistrano task) deploy:finishing_rollback (Capistrano task) deploy:updating (Capistrano task) git:ini-1.3.8 (Capistrano task) unicorn:graceful_restart (Capistrano task)
It seems like fish can distinguish prefixing a command with sudo
> sudo cap
airbrake:deploy (Capistrano task) deploy:finishing_rollback
So my question is, how do I get the behavior of bundle exec to mirror sudo for the purpose of summoning completions with Tab?

You can see how sudo does it here. It adds a completion which strips sudo and sudo-specific options from the command line, and then reinvokes complete -C to generate completions for this subcommand.
One way to get this working with bundle would be:
Start with that sudo.fish file, copying it into ~/.config/fish/completions/bundle.fish.
Edit that file to replace references to sudo with bundle.
Remove sudo-specific arguments and add any you want for bundle.
The sudo.fish file is probably already installed at /usr/local/share/fish/completions/sudo.fish or you may download it from GitHub.
The docs on writing your own completions are a good reference.

Related

Make: Run a target based on a directory status

How can I check if a directory doesn't exists or empty then run a target?
Example:
.PHONY: all
all: build
build: install
# ...
# ...
install:
git submodule update --recursive --remote
bash install.sh
basically, I need to check for the lib/ directory. If it exists and not empty, do nothing. If it doesn't exists or empty, run the install target.
I'd go for something like this (untested):
# if lib is empty, run install
ifeq ($(wildcard lib/*),)
git submodule update --recursive --remote
bash install.sh
endif
It's not technically running a target, but I reckon it's what you ask for.
For running an actual target you'd setup prerequisites accordingly:
# some program using something in lib/
program: lib/libhello.a
# "making" the lib
lib/libhello.a:
git submodule update --recursive --remote
bash install.sh
Not sure I understand the role of the build target. Let's assume it is another intermediate phony target. Let's also assume that your default goal is all, and you want all to fire build, that itself fires install if and only if lib does not exist or is empty. Finally, let's assume that it is:
git submodule update --recursive --remote
bash install.sh
that creates lib and populates it. You could use a dummy empty file to mark that the lib directory exists and is not empty. Example:
.PHONY: all build install
all: build
build: install
# ...
# ...
install: lib/.exists
lib/.exists:
git submodule update --recursive --remote
bash install.sh
touch "$#"

Questions related to 'npm install' and 'node_modules'

When executing the 'npm install' command in a node project,
Is there a way to prevent certain directories (packages) in the node_modules directory from being updated?
In other words, is there a way to avoid touching the specific directory (package) itself in node_modules?
(I'm using a package that is not defined in the 'package.json file' content by manually putting it inside the 'node_modules directory'. I hope the package is not deleted when commanding 'npm install'.)
This situation is little complicated but you can try creating your private package.
the below test works, you can give it a try:
I have created a dummy package "foo" with:
"name": "#my-private-namespace/foo",
I created a folder:
$ npm init -y
...
$ npm install ../foo
...
$ ls node_modules/\#my-private-namespace/
foo
$ npm install n
...
$ ls node_modules/\#my-private-namespace/
foo

graphql-codegen not running with config file

In my package.json file I've got script entry that runs graphql-codegen but it complains that the --config argument is invalid:
$> yarn gen
yarn run v1.21.1
$ graphql-codegen --config codegen.yml
Error: Unknown argument: config
...
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Since I believe the default file name is codegen.yml anyway, I try to run it with out that argument and nothing gets generated:
$> yarn graphql-codegen
yarn run v1.21.1
$ /home/aaron/projects/my_app/node_modules/.bin/graphql-codegen
Done in 0.17s.
Any ideas?
for me this solved the issue
Yarn
yarn add -D #graphql-codegen/cli
npm
npm i -D #graphql-codegen/cli
installation guide doc
Ok, I'm not sure exactly what I did to fix this. I believe that I had also installed graphql-codegen globally and tried to uninstall it with sudo npm uninstall graphql-codegen which removed a bunch of packages but the executable still exists:
$>which graphql-codegen
/usr/bin/graphql-codegen
However I decided to run yarn graphql-codegen init on a whim to see if init was valid and because I couldn't remember if I hadn't tried that already. I got the set up questions like normal so I ctrl+C'ed and just ran yarn graphql-codegen and it worked! Then I ran yarn graphql-codegen --watch to test that it took options and that also worked.
If anyone gets this issue, I hope these tips help you.
Try it: rm -rf ./node_modules && npm install
rm http://manpages.ubuntu.com/manpages/trusty/man1/rm.1.html
remove files or directories
-f, --force ignore nonexistent files and arguments, never prompt
-r, -R, --recursive remove directories and their contents recursively
node_modules https://docs.npmjs.com/cli/v7/configuring-npm/folders
You can think of the node_modules folder like a cache
for the external modules that your project depends upon. When you npm
install them, they are downloaded from the web and copied into the
node_modules folder and nodejs is trained to look for them there when
you import them (without a specific path).
npm install https://docs.npmjs.com/cli/install/
This command installs a package and any packages that it depends on.
If the package has a package-lock, or an npm shrinkwrap file, or a
yarn lock file, the installation of dependencies will be driven by
that, respecting the following order of precedence:
npm-shrinkwrap.json
package-lock.json
yarn.lock
Might also be that you have apollo's graphql-codegen package installed, which also exposes a binary called graphql-codegen, which accepts args schema and output, but not config.
For me the solution was to install #graphql-codegen/cli.
graphql.config.yml
schema: http://localhost:8081/graphql
extensions:
codegen:
generates:
./schema.graphql:
- schema-ast
package.json
{
"codegen": "graphql codegen --config graphql.config.yml"
}
I've fixed the problem by using graphql-code-generator instead:
"scripts": {
"graphql:generate": "graphql-code-generator"
}

Docker file, symlink disappears mid build

I have the following docker file (at the bottom). I am using another image to grab a precompiled library (utilities) and copying it into the route of a new image. I then need to symlink that directory into my node_modules directory. This works fine, I have 3 places where I prove the issue.
Check for the existence of the original root directory /utilities. This works, I can see the files
Then I create the symlink: ln -sf ...
I think check to see the contents at the location of the symlink. This works, I can see the files.
I go on to create the rest of the image
At the end I again list out the files, and now I get
ls: /usr/src/app/node_modules/#boiler/utilities: No such file or directory
It's like the symlink doesn't persist. If I run the container with shell: docker run -it --entrypoint=sh backend:latest and create the symlink it works.
Any thoughts as to where my symlink is going?
FROM utilities-setup:latest as build
FROM node:8.5.0-alpine
COPY --from=build /utilities /utilities
RUN ls -l /utilities <-- 1. THIS WORKS, FILES EXIST
#setup directories
RUN mkdir -p /usr/src/app/node_modules/#boiler/
WORKDIR /usr/src/app
#create symlink to the utilities module into the boiler module
RUN ln -sf /utilities /usr/src/app/node_modules/#boiler/
RUN ls /usr/src/app/node_modules/#boiler/utilities <-- 2. THIS WORKS, FILES EXIST
#copy the content of the backend to the current direcotry
COPY . .
RUN yarn install
RUN ls /usr/src/app/node_modules/#boiler/utilities <-- 3. THIS FAILS, NO MODULE
RUN ["chmod", "+x", "./scripts/prod.sh"]
EXPOSE 8080
ENTRYPOINT ["/usr/src/app/scripts/prod.sh"]
[see comment] I clocked the problem.
What was happening was the yarn install was recreating the node_modules directory, so you have to create the symlink after all other modules are installed. Makes sense I suppose, but I thought it would just write to the directory if it already existed

Is there any bundler *after* hook?

I would like to have ctags generate a TAGS file of all my bundled gems or all the gems under the rvm gemset directory bundler installs its gems. Ideally, a bundle install or bundle update should generate a TAGS file at the last step using a ruby script I'll provide. Afterthat emacs joy.
Is there any kind of a bundler after hook I can use?
You could look at what Tim Pope does in his Hookup project:
https://github.com/tpope/hookup
I'd imagine it wouldn't be too hard to an an extra step after the bundler run.
Personally I just have a good old Makefile in my Ruby project:
.PHONY: tags
tags:
ETAGS=ctags
rm -rf TAGS
ctags -a -e -f TAGS --tag-relative -R app lib vendor
I have a shell script I run in the morning which sets up my dev environment which also runs make tags.
According to https://github.com/bundler/bundler/blob/dd1e11d8f8e869ffab4fc68d4854b27e1f486de4/lib/bundler/source/path.rb, there is the ability to run 'post_install' hooks. It uses meta-programming to deduce the method name, and the gem is supposed to implement that method. Will try and check if this works
My approach has been two pronged:
1) Put a rake task in place that generates tags for all code in the project as well as all required gems:
desc 'Create ctags'
task :tags do
system "ctags -R --language-force=ruby app config lib `rvm gemdir`/gems"
end
2) Using the excellent "foreman" gem (which I was using anyway) to run inotifywait and fire off the rake task if a file changes:
tags: while inotifywait -q -r -e MODIFY --exclude swp$ app/ config/ lib/ ; do bundle exec rake tags; done
If you are not using foreman you can of course just run that line without the first "tags:" part manually in a shell.

Resources