KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bom_plugins.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 3
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "bom_plugins.h"
23#include <config.h>
24#include <paths.h>
25#include <wx/ffile.h>
26#include <wx/log.h>
27
28
29const wxChar BOM_TRACE[] = wxT( "BOM_GENERATORS" );
30
31
33 : m_storedPath( aFile )
34{
35 m_isOk = false;
36 m_file = wxFileName( aFile );
37
38 if( !wxFile::Exists( m_file.GetFullPath() ) )
40
41 if( !wxFile::Exists( m_file.GetFullPath() ) )
42 {
43 m_info.Printf( _("Script file:\n%s\nnot found. Script not available."), aFile );
44 return;
45 }
46
47 m_isOk = true;
48
49 m_name = m_file.GetName();
50 wxString extension = m_file.GetExt().Lower();
51
52 // Important note:
53 // On Windows the right command command to run a python script is:
54 // python <script_path>/script.py
55 // and *not* python <script_path>\script.py
56 // Otherwise the script does not find some auxiliary pythons scripts needed by this script
57 if( extension == wxS( "xsl" ) )
58 {
59 m_info = readHeader( wxS( "-->" ) );
60 m_cmd = wxString::Format( wxS( "xsltproc -o \"%%O%s\" \"%s\" \"%%I\"" ),
62 m_file.GetFullPath() );
63 }
64 else if( extension == wxS( "py" ) )
65 {
66 m_info = readHeader( wxS( "\"\"\"" ) );
67#ifdef __WINDOWS__
68 m_cmd = wxString::Format( "python \"%s/%s\" \"%%I\" \"%%O%s\"",
69 m_file.GetPath(),
70 m_file.GetFullName(),
72#else
73 wxString interpreter = wxString::FromUTF8Unchecked( PYTHON_EXECUTABLE );
74
75 if( interpreter.IsEmpty() )
76 interpreter = wxT( "python" );
77
78 m_cmd = wxString::Format( "%s \"%s\" \"%%I\" \"%%O%s\"",
79 interpreter,
80 m_file.GetFullPath(),
82#endif
83 }
84#ifdef __WINDOWS__
85 else if( extension == wxS( "pyw" ) )
86 {
87 m_info = readHeader( wxS( "\"\"\"" ) );
88 m_cmd = wxString::Format( wxS( "pythonw \"%s/%s\" \"%%I\" \"%%O%s\"" ),
89 m_file.GetPath(),
90 m_file.GetFullName(),
92 }
93#endif /* __WINDOWS__ */
94 else // fallback
95 {
96 m_cmd = m_file.GetFullPath();
97 }
98
99 wxLogTrace( BOM_TRACE, wxS( "%s: extracted command line %s" ), m_name, m_cmd );
100}
101
102
103bool BOM_GENERATOR_HANDLER::IsValidGenerator( const wxString& aFile )
104{
105 wxFileName fn( aFile );
106 wxString ext = fn.GetExt().Lower();
107
108 for( const auto& pluginExt : { wxS( "xsl" ), wxS( "py" ), wxS( "pyw" ) } )
109 {
110 if( pluginExt == ext )
111 return true;
112 }
113
114 return false;
115}
116
117
118wxString BOM_GENERATOR_HANDLER::readHeader( const wxString& aEndSection )
119{
120 if( aEndSection.IsEmpty() )
121 return wxEmptyString;
122
123 wxFFile fdata( m_file.GetFullPath(), wxS( "rb" ) ); // dtor will close the file
124 wxString data;
125
126 if( !fdata.ReadAll( &data ) )
127 return wxEmptyString;
128
129 const wxString header( wxS( "@package" ) );
130
131 // Extract substring between @package and endsection
132 size_t strstart = data.find( header );
133
134 if( strstart == wxString::npos )
135 return wxEmptyString;
136
137 strstart += header.Length();
138 size_t strend = data.find( aEndSection, strstart );
139
140 if( strend == wxString::npos )
141 return wxEmptyString;
142
143 // Remove empty line if any
144 while( data[strstart] < ' ' )
145 strstart++;
146
147 return data.SubString( strstart, strend - 1 );
148}
149
150
151wxString BOM_GENERATOR_HANDLER::getOutputExtension( const wxString& aHeader )
152{
153 // search header for extension after %O (extension includes '.')
154 // looks for output argument of the form `"%O.extension"`
155 const wxString outputarg( wxS( "\"%O" ) );
156
157 size_t strstart = aHeader.find( outputarg );
158
159 if( strstart == wxString::npos )
160 return wxEmptyString;
161
162 strstart += outputarg.Length();
163 size_t strend = aHeader.find( wxS( "\"" ), strstart );
164
165 if( strend == wxString::npos )
166 return wxEmptyString;
167
168 return aHeader.SubString( strstart, strend - 1 );
169}
170
171
173{
174 if( m_file.IsAbsolute() && m_file.Exists( wxFILE_EXISTS_REGULAR ) )
175 {
176 wxLogTrace( BOM_TRACE, wxS( "%s found directly" ), m_file.GetFullPath() );
177 return m_file;
178 }
179
180 wxFileName test( PATHS::GetUserPluginsPath(), m_file.GetName(), m_file.GetExt() );
181
182 if( test.Exists( wxFILE_EXISTS_REGULAR ) )
183 {
184 wxLogTrace( BOM_TRACE, wxS( "%s found in user plugins path %s" ), m_file.GetFullName(),
186 return test;
187 }
188
189 test = wxFileName( PATHS::GetStockPluginsPath(), m_file.GetName(), m_file.GetExt() );
190
191 if( test.Exists( wxFILE_EXISTS_REGULAR ) )
192 {
193 wxLogTrace( BOM_TRACE, wxS( "%s found in stock plugins path %s" ), m_file.GetFullName(),
195 return test;
196 }
197
198 wxLogTrace( BOM_TRACE, wxS( "Could not find %s (checked %s, %s)" ), m_file.GetFullName(),
200
201 return m_file;
202}
const wxChar BOM_TRACE[]
const wxChar BOM_TRACE[]
wxString m_name
Command to execute the plugin.
static bool IsValidGenerator(const wxString &aFile)
Return true if a file name matches a recognized plugin format.
wxString readHeader(const wxString &aEndSection)
Read the plugin file header.
bool m_isOk
Path to the plugin.
BOM_GENERATOR_HANDLER(const wxString &aFile)
wxString m_info
Plugin specific options.
wxFileName m_file
Path to the plugin stored in config (can be absolute or just a filename)
const wxString m_storedPath
User customisable name.
wxString m_cmd
Description of the plugin (normally from the plugin header)
wxFileName FindFilePath() const
Returns the calculated path to the plugin: if the path is already absolute and exists,...
static wxString getOutputExtension(const wxString &aHeader)
Extracts the output BOM file's extension, including the '.
static wxString GetUserPluginsPath()
Gets the user path for plugins.
Definition paths.cpp:49
static wxString GetStockPluginsPath()
Gets the stock (install) plugins path.
Definition paths.cpp:377
#define _(s)
std::vector< std::string > header