Commit 83c03445 authored by Jonathan Hanks's avatar Jonathan Hanks

LIGO channel name completion, initially targeting bash.

parents
Language: Cpp
# BasedOnStyle: WebKit
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: true
AlignEscapedNewlinesLeft: false
AlignOperands: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: AllDefinitions
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: true
SpacesBeforeTrailingComments: 1
SpacesInAngles: true
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: true
SpacesInSquareBrackets: true
Standard: Cpp03
TabWidth: 8
UseTab: Never
*~
*bak
*.o
cmake-*
.idea
*swp
\ No newline at end of file
cmake_minimum_required(VERSION 3.0)
project(complete_chan)
# work even on old cmake.
# most of this goes away at cmake 3.1+
INCLUDE(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-std=c++0x HAS_CXX_0X)
CHECK_CXX_COMPILER_FLAG(-std=c++11 HAS_CXX_11)
if (${HAS_CXX_11})
set(CPP11_FLAG "-std=c++11")
else (${HAS_CXX_11})
if (${HAS_CXX_0X})
set(CPP11_FLAG "-std=c++0x")
else (${HAS_CXX_0X})
set(CPP11_FLAG "")
endif (${HAS_CXX_0X})
endif (${HAS_CXX_11})
macro(target_requires_cpp11 target mode)
if (${CMAKE_VERSION} VERSION_GREATER "3.0.99")
target_compile_features(${target} ${mode} cxx_auto_type)
else (${CMAKE_VERSION} VERSION_GREATER "3.0.99")
target_compile_options(${target} ${mode} ${CPP11_FLAG})
endif (${CMAKE_VERSION} VERSION_GREATER "3.0.99")
endmacro()
add_subdirectory(bash)
add_executable(channel_completion channel_completion.cpp)
target_requires_cpp11(channel_completion PUBLIC)
install(TARGETS channel_completion DESTINATION bin)
\ No newline at end of file
This diff is collapsed.
LIGO channel name completion tools
Copyright (C) 2019 California Institute of Technology
This program is free software and is distributed in the hope that it will be useful; you may redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (http://www.gnu.org/licenses); version 2 (GPLv2) of the License or at your discretion, any later version (i.e GPLv3).
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Neither the names of the California Institute of Technology (Caltech), The Massachusetts Institute of Technology (M.I.T), The Laser Interferometer Gravitational-Wave Observatory (LIGO), nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
You should have received a copy of the licensing terms for this software included in the file LICENSE located in the top-level directory of this package. If you did not, you can view a copy at http://dcc.ligo.org/M1500244/LICENSE.txt
You should have received a copy of the GNU General Public License
along with this program, (in the COPYING-GPL-2.txt file in this
directory). If not, see http://www.gnu.org/licenses/
A bash (and soon other) completion for LIGO channel names.
This provides a bash completion script along with a channel completion program.
A channel database is required. The database is a simple flat text file where
every line is a single channel name. The file must be sorted. The path to the
file is set via the 'CHAN_LIST' environment variable.
If you have a list of channels you can have the application sort it for you
<pre>
# assuming that the channel database is
# located at a path specified by the
# CHAN_LIST environment variable
channel_completion -r > tmpfile
mv tmpfile "$CHAN_LIST"
</pre>
Requirements:
* A C++11 compliant compiler.
* CMake 3+
Debian requirements:
* build-essential
* bash-completion
Tested on:
* Debian 8 & 9
Building:
* create a build area
* run cmake
* install
Example (starting from the source directory)
<pre>
mkdir build
cd build
cmake ..
make
make install
</pre>
After the install is successful, start a new bash shell and use the channel completion.
<pre>
$ ndscope H&lt;tab&gt;
H0:FMC H1:AOS H1:CDS H1:HPI H1:ISI H1:OMC H1:SQZ H1:VID
H0:SAF H1:ASC H1:DAQ H1:IMC H1:LSC H1:PEM H1:SUS
H0:VAC H1:AWC H1:FEC H1:IOP H1:OAF H1:PSL H1:SYS
H1:ALS H1:CAL H1:GRD H1:ISC H1:ODC H1:SEI H1:TCS
</pre>
\ No newline at end of file
configure_file(channel_completion ${CMAKE_CURRENT_BINARY_DIR}/channel_completion @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/channel_completion"
DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/etc/bash_completion.d )
\ No newline at end of file
# Copyright 2019 California Institute of Technology.
# You should have received a copy of the licensing terms for this
# software included in the file “LICENSE” located in the top-level
# directory of this package. If you did not, you can view a copy at
# http://dcc.ligo.org/M1500244/LICENSE.txt
_channel_completion()
{
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
# see https://stackoverflow.com/questions/10528695/how-to-reset-comp-wordbreaks-without-affecting-other-completion-script/12495480#12495480
_get_comp_words_by_ref -n : cur
COMPREPLY=( $(@CMAKE_INSTALL_PREFIX@/bin/channel_completion "${cur}") )
__ltrim_colon_completions "$cur"
return 0
}
complete -F _channel_completion ndscope
complete -F _channel_completion cdsutils
// Copyright 2019 California Institute of Technology.
// You should have received a copy of the licensing terms for this
// software included in the file “LICENSE” located in the top-level
// directory of this package. If you did not, you can view a copy at
// http://dcc.ligo.org/M1500244/LICENSE.txt
#include <algorithm>
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
static const char CHAN_LIST_ENV[] = "CHAN_LIST";
typedef std::vector< std::string > string_list;
struct Database
{
std::vector< std::string > channels;
};
bool
simple_comparison( const std::string& a, const std::string& b )
{
return std::strcmp( a.c_str( ), b.c_str( ) ) < 0;
}
bool
key_comparison( const std::string& key, const std::string& element )
{
int result = std::strncmp( key.c_str( ), element.c_str( ), key.size( ) );
return result < 0;
}
Database
load_database( const std::string& path )
{
Database db;
std::ifstream input( path.c_str( ) );
std::string line;
while ( std::getline( input, line ) )
{
db.channels.emplace_back( line );
}
return db;
}
string_list
search( const Database& db, const std::string& key )
{
string_list results;
auto lower = std::lower_bound(
db.channels.begin( ), db.channels.end( ), key, key_comparison );
auto upper =
std::upper_bound( lower, db.channels.end( ), key, key_comparison );
auto key_size = key.size( );
std::for_each(
lower, upper, [key_size, &results]( const std::string& entry ) {
static const std::string delimiters( "-_" );
auto pos = entry.find_first_of( delimiters, key_size );
if ( pos == key_size )
{
pos = entry.find_first_of( delimiters, key_size + 1 );
}
if ( pos != std::string::npos )
{
if ( results.empty( ) ||
std::strncmp(
results.back( ).c_str( ), entry.c_str( ), pos ) != 0 )
{
results.emplace_back( entry.c_str( ), pos );
}
}
else
{
results.emplace_back( entry );
}
} );
return results;
}
std::string
get_environment( const char* key )
{
std::string result;
const char* e = std::getenv( key );
return result = ( e ? e : "" );
}
struct option_t
{
option_t( ) : key( "" ), search( true ), resort( false ), abort( false )
{
}
std::string key;
bool search;
bool resort;
bool abort;
};
void
show_help( const char* prog )
{
std::cerr << "Usage " << prog << " option\n";
std::cerr << "Where option is one of:\n";
std::cerr << "\t-h - this help.\n";
std::cerr << "\t-r - sort the database, dump results to stdout.\n";
std::cerr << "\t<search param> - search for the completion following the "
"given text.\n";
std::cerr << "\n\nNote: The environment variable CHAN_LIST must be set to "
"the path to text file\n";
std::cerr << "containing a sort list of channels. This is the channel "
"database used to do completions.\n";
}
option_t
parse_options( int argc, char* argv[] )
{
option_t opts;
if ( argc > 1 )
{
if ( argc > 2 || std::strcmp( argv[ 1 ], "-h" ) == 0 )
{
show_help( argv[ 0 ] );
opts.abort = true;
}
else if ( std::strcmp( argv[ 1 ], "-r" ) == 0 )
{
opts.resort = true;
opts.search = false;
}
else
{
opts.key = argv[ 1 ];
}
}
return opts;
}
int
main( int argc, char* argv[] )
{
option_t opts = parse_options( argc, argv );
if ( opts.abort )
{
exit( 1 );
}
std::string channel_db_path = get_environment( CHAN_LIST_ENV );
if ( channel_db_path.empty( ) )
{
exit( 1 );
}
Database db = load_database( channel_db_path );
if ( opts.search )
{
auto choices = search( db, opts.key );
std::copy( choices.begin( ),
choices.end( ),
std::ostream_iterator< std::string >( std::cout, "\n" ) );
}
else if ( opts.resort )
{
std::sort(
db.channels.begin( ), db.channels.end( ), simple_comparison );
std::copy( db.channels.begin( ),
db.channels.end( ),
std::ostream_iterator< std::string >( std::cout, "\n" ) );
}
return 0;
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment