Add auto-completion for DRC rule function calls.

This commit is contained in:
Jeff Young 2020-07-22 21:27:38 +01:00
parent 70b98c3b49
commit 86c9adbcba
4 changed files with 90 additions and 79 deletions

View File

@ -24,6 +24,7 @@
#include <fctsys.h> #include <fctsys.h>
#include <scintilla_tricks.h> #include <scintilla_tricks.h>
#include <wx/stc/stc.h>
#include <gal/color4d.h> #include <gal/color4d.h>
#include <dialog_shim.h> #include <dialog_shim.h>
@ -190,7 +191,10 @@ void SCINTILLA_TRICKS::DoAutocomplete( const wxString& aPartial, const wxArraySt
{ {
// NB: tokens MUST be in alphabetical order because the Scintilla engine is going // NB: tokens MUST be in alphabetical order because the Scintilla engine is going
// to do a binary search on them // to do a binary search on them
matchedTokens.Sort(); matchedTokens.Sort( []( const wxString& first, const wxString& second ) -> int
{
return first.CmpNoCase( second );
});
m_te->AutoCompShow( aPartial.size(), wxJoin( matchedTokens, ' ' ) ); m_te->AutoCompShow( aPartial.size(), wxJoin( matchedTokens, ' ' ) );
} }

View File

@ -23,6 +23,7 @@
#include <widgets/paged_dialog.h> #include <widgets/paged_dialog.h>
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <pcb_expr_evaluator.h>
#include <project.h> #include <project.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <drc/drc.h> #include <drc/drc.h>
@ -31,6 +32,7 @@
#include <scintilla_tricks.h> #include <scintilla_tricks.h>
#include <drc/drc_rule_parser.h> #include <drc/drc_rule_parser.h>
PANEL_SETUP_RULES::PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFrame ) : PANEL_SETUP_RULES::PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFrame ) :
PANEL_SETUP_RULES_BASE( aParent->GetTreebook() ), PANEL_SETUP_RULES_BASE( aParent->GetTreebook() ),
m_Parent( aParent ), m_Parent( aParent ),
@ -46,6 +48,7 @@ PANEL_SETUP_RULES::PANEL_SETUP_RULES( PAGED_DIALOG* aParent, PCB_EDIT_FRAME* aFr
m_textEditor->StyleSetFont( i, fixedFont ); m_textEditor->StyleSetFont( i, fixedFont );
m_textEditor->Bind( wxEVT_STC_CHARADDED, &PANEL_SETUP_RULES::onScintillaCharAdded, this ); m_textEditor->Bind( wxEVT_STC_CHARADDED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
m_textEditor->Bind( wxEVT_STC_AUTOCOMP_CHAR_DELETED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
} }
@ -205,6 +208,11 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
for( const wxString& propName : propNames ) for( const wxString& propName : propNames )
tokens += " " + propName; tokens += " " + propName;
PCB_EXPR_BUILTIN_FUNCTIONS& functions = PCB_EXPR_BUILTIN_FUNCTIONS::Instance();
for( const wxString& funcSig : functions.GetSignatures() )
tokens += " " + funcSig;
} }
} }

View File

@ -28,91 +28,66 @@
#include "class_board.h" #include "class_board.h"
#include "pcb_expr_evaluator.h" #include "pcb_expr_evaluator.h"
class PCB_EXPR_BUILTIN_FUNCTIONS
static void onLayer( LIBEVAL::UCODE* aUcode, LIBEVAL::CONTEXT* aCtx, void *self )
{ {
public: LIBEVAL::VALUE* arg = aCtx->Pop();
LIBEVAL::VALUE* result = aCtx->AllocValue();
using FPTR = LIBEVAL::UCODE::FUNC_PTR; result->Set( 0.0 );
aCtx->Push( result );
PCB_EXPR_BUILTIN_FUNCTIONS(); if( !arg )
static PCB_EXPR_BUILTIN_FUNCTIONS& Instance()
{ {
static PCB_EXPR_BUILTIN_FUNCTIONS self; aCtx->ReportError( _( "Missing argument to 'onLayer()'" ) );
return self; return;
} }
std::string tolower( const std::string& str ) const wxString layerName = arg->AsString();
PCB_LAYER_ID layer = ENUM_MAP<PCB_LAYER_ID>::Instance().ToEnum( layerName );
if( layer == UNDEFINED_LAYER )
{ {
std::string rv; aCtx->ReportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) );
std::transform( str.begin(), str.end(), rv.begin(), ::tolower ); return;
return rv;
} }
FPTR Get( const std::string &name ) const PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
{ BOARD_ITEM* item = vref ? vref->GetObject( aUcode ) : nullptr;
auto it = m_funcs.find( name );
if( it == m_funcs.end() ) if( item && item->IsOnLayer( layer ) )
return nullptr; result->Set( 1.0 );
}
return it->second;
}
private: static void isPlated( LIBEVAL::UCODE* aUcode, LIBEVAL::CONTEXT* aCtx, void *self )
std::map<std::string, FPTR> m_funcs; {
LIBEVAL::VALUE* result = aCtx->AllocValue();
static void onLayer( LIBEVAL::UCODE* aUcode, LIBEVAL::CONTEXT* aCtx, void *self ) result->Set( 0.0 );
{ aCtx->Push( result );
LIBEVAL::VALUE* arg = aCtx->Pop();
LIBEVAL::VALUE* result = aCtx->AllocValue();
result->Set( 0.0 ); PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
aCtx->Push( result ); BOARD_ITEM* item = vref ? vref->GetObject( aUcode ) : nullptr;
D_PAD* pad = dynamic_cast<D_PAD*>( item );
if( !arg ) if( pad && pad->GetAttribute() == PAD_ATTRIB_STANDARD )
{ result->Set( 1.0 );
aCtx->ReportError( _( "Missing argument to 'onLayer()'" ) ); }
return;
}
wxString layerName = arg->AsString();
PCB_LAYER_ID layer = ENUM_MAP<PCB_LAYER_ID>::Instance().ToEnum( layerName );
if( layer == UNDEFINED_LAYER )
{
aCtx->ReportError( wxString::Format( _( "Unrecognized layer '%s' " ), layerName ) );
return;
}
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
BOARD_ITEM* item = vref ? vref->GetObject( aUcode ) : nullptr;
if( item && item->IsOnLayer( layer ) )
result->Set( 1.0 );
}
static void isPlated( LIBEVAL::UCODE* aUcode, LIBEVAL::CONTEXT* aCtx, void *self )
{
LIBEVAL::VALUE* result = aCtx->AllocValue();
result->Set( 0.0 );
aCtx->Push( result );
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
BOARD_ITEM* item = vref ? vref->GetObject( aUcode ) : nullptr;
D_PAD* pad = dynamic_cast<D_PAD*>( item );
if( pad && pad->GetAttribute() == PAD_ATTRIB_STANDARD )
result->Set( 1.0 );
}
};
PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS() PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
{ {
m_funcs[ "onlayer" ] = onLayer; auto registerFunc = [&]( const wxString& funcSignature, FPTR funcPtr )
m_funcs[ "isplated" ] = isPlated; {
wxString funcName = funcSignature.BeforeFirst( '(' );
m_funcs[ std::string( funcName.Lower() ) ] = std::move( funcPtr );
m_funcSigs.Add( funcSignature );
};
registerFunc( "onLayer('x')", onLayer );
registerFunc( "isPlated()", isPlated );
} }

View File

@ -41,9 +41,11 @@ class PCB_EXPR_UCODE : public LIBEVAL::UCODE
{ {
public: public:
virtual LIBEVAL::VAR_REF* createVarRef( LIBEVAL::COMPILER *aCompiler, virtual LIBEVAL::VAR_REF* createVarRef( LIBEVAL::COMPILER *aCompiler,
const std::string& aVar, const std::string& aField ) override; const std::string& aVar,
const std::string& aField ) override;
virtual FUNC_PTR createFuncCall( LIBEVAL::COMPILER* aCompiler, const std::string& name ) override; virtual FUNC_PTR createFuncCall( LIBEVAL::COMPILER* aCompiler,
const std::string& name ) override;
void SetItems( BOARD_ITEM* a, BOARD_ITEM* b = nullptr ) void SetItems( BOARD_ITEM* a, BOARD_ITEM* b = nullptr )
{ {
@ -75,24 +77,16 @@ public:
void SetIsEnum( bool s ) { m_isEnum = s; } void SetIsEnum( bool s ) { m_isEnum = s; }
bool IsEnum() const { return m_isEnum; } bool IsEnum() const { return m_isEnum; }
void SetType( LIBEVAL::VAR_TYPE_T type ) void SetType( LIBEVAL::VAR_TYPE_T type ) { m_type = type; }
{ LIBEVAL::VAR_TYPE_T GetType() override { return m_type; }
m_type = type;
}
void AddAllowedClass( TYPE_ID type_hash, PROPERTY_BASE* prop ) void AddAllowedClass( TYPE_ID type_hash, PROPERTY_BASE* prop )
{ {
m_matchingTypes[type_hash] = prop; m_matchingTypes[type_hash] = prop;
} }
virtual LIBEVAL::VAR_TYPE_T GetType() override
{
return m_type;
}
virtual LIBEVAL::VALUE GetValue( LIBEVAL::CONTEXT* aCtx, LIBEVAL::UCODE* aUcode ) override; virtual LIBEVAL::VALUE GetValue( LIBEVAL::CONTEXT* aCtx, LIBEVAL::UCODE* aUcode ) override;
BOARD_ITEM* GetObject( LIBEVAL::UCODE* aUcode ) const; BOARD_ITEM* GetObject( LIBEVAL::UCODE* aUcode ) const;
private: private:
@ -103,6 +97,36 @@ private:
}; };
class PCB_EXPR_BUILTIN_FUNCTIONS
{
public:
using FPTR = LIBEVAL::UCODE::FUNC_PTR;
PCB_EXPR_BUILTIN_FUNCTIONS();
static PCB_EXPR_BUILTIN_FUNCTIONS& Instance()
{
static PCB_EXPR_BUILTIN_FUNCTIONS self;
return self;
}
LIBEVAL::UCODE::FUNC_PTR Get( const std::string &name )
{
return m_funcs[ name ];
}
const wxArrayString GetSignatures() const
{
return m_funcSigs;
}
private:
std::map<std::string, LIBEVAL::UCODE::FUNC_PTR> m_funcs;
wxArrayString m_funcSigs;
};
class PCB_EXPR_COMPILER : public LIBEVAL::COMPILER class PCB_EXPR_COMPILER : public LIBEVAL::COMPILER
{ {
public: public: