Skip to content
Snippets Groups Projects
Commit 92943224 authored by Giovanni Bussi's avatar Giovanni Bussi
Browse files

Merge branch 'v2.4-completion' into completion

parents 93c67abd e2fbc6fe
No related branches found
No related tags found
No related merge requests found
......@@ -75,6 +75,7 @@ do
(--list-engines|-l) test -n "$action" && multiple_actions=yes ; action=list ;;
(--info|-i) test -n "$action" && multiple_actions=yes ; action=info ;;
(--new=*) test -n "$action" && multiple_actions=yes ; action=new ; newpatch="${prefix_option#--new=}" ;;
(--options) test -n "$action" && multiple_actions=yes ; action=options ;;
(--description) echo "patch an MD engine" ; exit ;;
(--engine=*) engine="${prefix_option#--engine=}" ;;
(--mdroot=*) mdroot="${prefix_option#--mdroot=}" ;;
......@@ -114,6 +115,11 @@ if [ -z "$action" ] ; then
exit
fi
if [ "$action" = options ] ; then
echo "--help -h --patch -p --save -s --save-originals --revert -R -r --list-engines -l --info -i --new --options --description --engine --mdroot --mode --diff --engine -e --mdroot --root --diff -d --mode -m --new -n --static --shared --runtime --force -f --quiet -q"
exit 0
fi
test -n "$quiet" || echo "PLUMED patching tool"
test -n "$quiet" || echo
if [ -z "$PLUMED_ROOT" ]
......
......@@ -42,6 +42,10 @@ do
echo "inquire plumed about how it was configure"
exit 0
;;
(--options)
echo "--help -h --description --options --quiet -q --version -v show has module mpiexec makefile_conf"
exit 0
;;
(--quiet|-q) quiet=yes ;;
(--version|-v) action=version ;;
(show)
......
#! /bin/bash
source "$PLUMED_ROOT"/src/config/compile_options.sh
if [ "$1" = --description ] ; then
echo "compile a .cpp file into a shared library"
exit 0
fi
if [ "$1" = --options ] ; then
echo "--description"
exit 0
fi
source "$PLUMED_ROOT"/src/config/compile_options.sh
if [ $# != 1 ] || [[ "$1" != *.cpp ]] ;
then
echo "ERROR"
......
......@@ -5,6 +5,11 @@ if [ "$1" = --description ] ; then
exit 0
fi
if [ "$1" = --options ] ; then
echo "--description"
exit 0
fi
if [ $# != 2 ] ;
then
echo "ERROR"
......
......@@ -4,6 +4,11 @@ if [ "$1" = --description ] ; then
exit 0
fi
if [ "$1" = --options ] ; then
echo "--description --gromacs4 --help -h"
exit 0
fi
if [ "$1" = --help ] || [ "$1" = -h ] ; then
cat <<EOF
Usage:
......
......@@ -7,6 +7,11 @@ if [ "$1" = --description ] ; then
exit 0
fi
if [ "$1" = --options ] ; then
echo "--description --options --annotate-syntax --pdf --crop --fs --colors"
exit 0
fi
if [ "$1" = --help ] ; then
cat << EOF
Usage:
......
......@@ -7,3 +7,4 @@
!/Makefile
!/README
!/module.type
!/*.sh
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 2018 The plumed team
(see the PEOPLE file at the root of the distribution for a list of names)
See http://www.plumed.org for more information.
This file is part of plumed, version 2.
plumed is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
plumed is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with plumed. If not, see <http://www.gnu.org/licenses/>.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
#include "CLTool.h"
#include "CLToolRegister.h"
#include "tools/Tools.h"
#include "config/Config.h"
#include "core/ActionRegister.h"
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
namespace PLMD {
namespace cltools {
//+PLUMEDOC TOOLS completion
/*
Dumps the body of a bash function to be used for autocompletion.
Users will typically not need this command.
See more at \ref BashAutocompletion
\par Examples
\verbatim
plumed completion
\endverbatim
*/
//+ENDPLUMEDOC
class Completion:
public CLTool
{
public:
static void registerKeywords( Keywords& keys );
explicit Completion(const CLToolOptions& co );
int main(FILE* in, FILE*out,Communicator& pc);
string description()const {
return "dump a function usable for programmable completion";
}
};
PLUMED_REGISTER_CLTOOL(Completion,"completion")
void Completion::registerKeywords( Keywords& keys ) {
CLTool::registerKeywords( keys );
}
Completion::Completion(const CLToolOptions& co ):
CLTool(co)
{
inputdata=commandline;
}
int Completion::main(FILE* in, FILE*out,Communicator& pc) {
static const char completion [] = {
#include "completion.xxd"
, 0x00
};
fprintf(out,"local cmds=\"help -h --help");
// Build list of available C++ tools:
std::vector<string> availableCxx=cltoolRegister().list();
// Build list of available shell tools:
vector<string> tmp=Tools::ls(string(config::getPlumedRoot()+"/scripts"));
for(unsigned j=0; j<tmp.size(); ++j) {
size_t ff=tmp[j].find(".sh");
if(ff==string::npos) tmp[j].erase();
else tmp[j].erase(ff);
}
for(unsigned j=0; j<availableCxx.size(); j++) fprintf(out," %s",availableCxx[j].c_str());
for(unsigned j=0; j<tmp.size(); ++j) if(tmp[j].length()>0) fprintf(out," %s",tmp[j].c_str());
fprintf(out,"\"\n");
for(unsigned j=0; j<availableCxx.size(); j++) {
std::string s=availableCxx[j];
// handle - sign (convert to underscore)
for(;;) {
size_t n=s.find("-");
if(n==std::string::npos) break;
s[n]='_';
}
fprintf(out,"local cmd_keys_%s=\"",s.c_str());
std::vector<std::string> keys=cltoolRegister().getKeys(availableCxx[j]);
for(unsigned k=0; k<keys.size(); k++) {
// handle --help/-h
std::string s=keys[k];
for(;;) {
size_t n=s.find("/");
if(n==std::string::npos) break;
s[n]=' ';
}
fprintf(out," %s",s.c_str());
}
fprintf(out,"\"\n");
}
//// ALTERNATIVE IMPLEMENTATION
//// checking tools on the fly
//// for(unsigned j=0; j<tmp.size(); j++) {
//// std::string s=tmp[j];
//// // handle - sign (convert to underscore)
//// for(;;) {
//// size_t n=s.find("-");
//// if(n==std::string::npos) break;
//// s[n]='_';
//// }
//// fprintf(out,"local cmd_keys_%s=\"",s.c_str());
//// std::string cmd=config::getEnvCommand()+" \""+config::getPlumedRoot()+"/scripts/"+s+".sh\" --options";
//// FILE *fp=popen(cmd.c_str(),"r");
//// std::string line,manual;
//// while(Tools::getline(fp,line))manual+=line;
//// pclose(fp);
//// std::vector<std::string> keys=Tools::getWords(manual);
//// for(unsigned k=0; k<keys.size(); k++) {
//// // handle --help/-h
//// std::string s=keys[k];
//// for(;;) {
//// size_t n=s.find("/");
//// if(n==std::string::npos) break;
//// s[n]=' ';
//// }
//// fprintf(out," %s",s.c_str());
//// }
//// fprintf(out,"\"\n");
//// }
fprintf(out,"%s\n",completion);
std::string name=config::getPlumedProgramName();
fprintf(out,
"############################################\n"
"## ADD THESE COMMANDS TO YOUR .bashrc FILE:\n"
"############################################\n"
"# _%s() { eval \"$(%s --no-mpi completion 2>/dev/null)\";}\n"
"# complete -F _%s -o default %s\n"
"############################################\n",
name.c_str(),name.c_str(),name.c_str(),name.c_str());
return 0;
}
} // End of namespace
}
......@@ -3,3 +3,8 @@ USE=core wrapper config tools molfile
# generic makefile
include ../maketools/make.module
Completion.o: completion.xxd
completion.xxd: completion.sh ../../scripts/*.sh ../../patches/*.sh
{ ../maketools/make-scripts-options.sh ; cat completion.sh ; }| xxd -i > completion.xxd
# Experimental script for bash completion. Just "source" it.
# In perspective, this script should be generated automatically by the plumed
# executable on the basis of the implemented CLTools.
#
_plumed()
{
local cur prev opts cmds
local cur prev opts
shopt -s extglob
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
# these options can be combined with other commands
opts="--load"
# only one of these commands should be used
cmds="help driver info manual simplemd mklib newcv patch -h --help --has-mpi"
# this option should be the first
if((COMP_CWORD==1)) ; then
opts="$opts --no-mpi --mpi"
fi
local cmd_found i cmd_test
......@@ -21,18 +18,22 @@ _plumed()
cmd_found=""
for cmd_test in $cmds ; do
if [[ "$cmd_test" == "${COMP_WORDS[i]}" ]] ; then
COMPREPLY=( $(compgen -f -- $cur ) )
eval "local comp=\"\$cmd_keys_${cmd_test//-/_}\""
case "$cur" in
(-*) COMPREPLY=( $(compgen -W "$comp" -- $cur ) ) ;;
(*) COMPREPLY=( $(compgen -o bashdefault -- ${cur}) ) ;;
esac
return 0
fi
done
if [[ $cmd_found == 1 ]]; then
if [[ "$cmd_found" == 1 ]]; then
break
fi
done
# if previous is --load, autocomplete with dynamic library
if [[ "${prev}" == --load ]] ; then
COMPREPLY=( $(compgen -f -X '!*.@(dylib|so)' -- $cur ) )
COMPREPLY=( $(compgen -X '!*.@(dylib|so)' -- $cur ) )
return 0
fi
......@@ -43,5 +44,3 @@ _plumed()
(*) COMPREPLY=( $(compgen -W "${cmds}" -- ${cur}) ) ;;
esac
return 0
}
complete -d -F _plumed plumed
......@@ -61,7 +61,7 @@ void CLToolRegister::add(string key,creator_pointer f,keywords_pointer kf) {
};
}
bool CLToolRegister::check(string key) {
bool CLToolRegister::check(string key)const {
if(m.count(key)>0) return true;
return false;
}
......@@ -101,6 +101,16 @@ bool CLToolRegister::printManual( const std::string& cltool ) {
}
}
std::vector<std::string> CLToolRegister::getKeys(const std::string& cltool)const {
if ( check(cltool) ) {
return mk.find(cltool)->second.getKeys();
} else {
std::vector<std::string> empty;
return empty;
}
}
vector<string> CLToolRegister::list()const {
vector<string> s;
for(const auto & it : m) s.push_back(it.first);
......
......@@ -56,7 +56,7 @@ public:
/// \param kp A pointer to a function which returns the allowed keywords
void add(std::string key,creator_pointer cp,keywords_pointer kp);
/// Verify if a directive is present in the register
bool check(std::string cltool);
bool check(std::string cltool)const;
/// Create an CLTool of the type indicated in the options
/// \param ao object containing information for initialization, such as the full input line, a pointer to PlumedMain, etc
std::unique_ptr<CLTool> create(const CLToolOptions&ao);
......@@ -66,6 +66,8 @@ public:
std::vector<std::string> list()const;
/// Print out the instructions for using the tool in html ready for input into the manual
bool printManual(const std::string& cltool);
/// Return all the keys of this cltool
std::vector<std::string> getKeys(const std::string& cltool)const;
};
/// Function returning a reference to the CLToolRegister.
......
#! /bin/bash
for file in ../../scripts/*.sh
do
name=${file##*/}
name=${name%.sh}
name=${name//-/_}
echo -n "local cmd_keys_${name}=\""
echo -n $(PLUMED_ROOT=../../ $file --options)
echo "\""
done
......@@ -154,6 +154,8 @@ public:
void addOutputComponent( const std::string& name, const std::string& key, const std::string& descr );
/// Has a component with this name been added?
bool outputComponentExists( const std::string& name, const bool& custom ) const ;
/// Reference to keys
std::vector<std::string> getKeys() const { return keys; }
};
}
......
......@@ -3,6 +3,7 @@
- \subpage comments
- \subpage ContinuationLines
- \subpage VimSyntax
- \subpage BashAutocompletion
- \subpage includes
- \subpage load
- \subpage degub
......@@ -93,6 +94,71 @@ dist: DISTANCES ...
...
\endplumedfile
\page BashAutocompletion Using bash autocompletion
For the impatients, just add the following to your .bashrc file:
\verbatim
_plumed() { eval "$(plumed --no-mpi completion 2>/dev/null)";}
complete -F _plumed -o default plumed
\endverbatim
and enjoy bash autocompletion.
\par Effect
When typing on the the shell you should observe the following behavior.
\verbatim
> plumed <TAB>
\endverbatim
will autocomplete with the names of the available PLUMED commands (e.g. `driver`, `help`, etc).
\verbatim
> plumed -<TAB>
\endverbatim
will autocomplete with the available PLUMED options (e.g. `--no-mpi`, etc).
PLUMED also knows which are the options available for each command
(e.g. `plumed driver --natoms`). So, the following
\verbatim
> plumed driver -<TAB>
\endverbatim
(notice the `-`) will autocomplete to the options of `plumed driver`. On the contrary
\verbatim
> plumed driver --ixtc <TAB>
\endverbatim
(notice the there is no `-` before `<TAB>`) will autocomplete to the files in the current directory.
Also notice that every time you use the `<TAB>` key to autocomplete the command `plumed` will be invoked.
This should allow the correct commands and options to be reported depending on the exact `plumed` command
in the current execution path. For instance, if you have multiple PLUMED versions installed with
env modules, you should be able to see the commands available in the currently loaded version.
Clearly, this feature will only be available if `plumed` can run on this machine (that is: will not work
if you are cross compiling). This is not a problem since you are not expecting to run the `plumed` command
in this specific case.
\par Technicalities
The command `plumed completion` just writes on its standard output the body of a bash function.
Now look at these lines:
\verbatim
_plumed() { eval "$(plumed --no-mpi completion 2>/dev/null)";}
complete -F _plumed -o default plumed
\endverbatim
The `-o default` options will make sure that if `plumed --no-mpi completion` returns an error the default bash completion
will be used. This is what will happen if you load an older PLUMED version for which the `completion` command is not available yet.
In future PLUMED versions the `plumed completion` command might return more sophisticated functions. You should
be able to benefit of these features without ever changing your bash configuration file again.
\par Multiple versions and suffixes
In case you have multiple versions of PLUMED installed in separate env modules there is nothing more to do.
However, if you have have multiple versions of PLUMED installed with different suffixes you should
consistently add more lines to your profile file. For instance, if you installed executables named
`plumed` and `plumed_mpi` your configuration file should look like:
\verbatim
_plumed() { eval "$(plumed --no-mpi completion 2>/dev/null)";}
complete -F _plumed -o default plumed
_plumed_mpi() { eval "$(plumed_mpi --no-mpi completion 2>/dev/null)";}
complete -F _plumed_mpi -o default plumed_mpi
\endverbatim
\page VimSyntax Using VIM syntax file
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment