discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Re: [OpenSCAD] Light source and default camera position different on command line

NH
nop head
Mon, Sep 24, 2018 6:29 PM

Actually QCoreApplication::applicationDirPath() is static so I don't need
an instance.

On 24 September 2018 at 19:27, nop head nop.head@gmail.com wrote:

The way it currently works is if it runs the GUI then it gets the
application path from the OpenSCADApp instance. If it runs the command line
version it instantiates a QCoreApplication app and uses that. Only if it is
compiled without QT does it use the boost version.

To get the color schemes in the command line description it needs the app
path before it has processed the command line. I bodged it by always
creating a QCoreApplicationapp on the heap, using it to get the app path
and then deleting it. That seems to fix the problem and still uses QT if
compiled with QT.

#ifdef OPENSCAD_QTGUI
QCoreApplication *app = new QCoreApplication(argc, argv);
const std::string application_path = QCoreApplication::instance()->
applicationDirPath().toLocal8Bit().constData();
delete app;
#else
const std::string application_path = fs::absolute(boost::
filesystem::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Can anybody see a problem with this hack?

On 24 September 2018 at 18:28, Torsten Paul Torsten.Paul@gmx.de wrote:

On 09/24/2018 04:03 PM, nop head wrote:

Having two QT app instances seems to be a problem, no surprise there!
Is there a reason for preferring the QT version? The boost version
produces the same path on my system so using that solves the problem.

The current code might be just for legacy reasons, but there are various

issues with boost on Windows regarding hard-links and non-ascii path.
I don't know if the toLocal8Bit() from Qt is better, but it might actually
help in those cases. Otherwise it would be nicer to just have a single
way to determine the path.

The command line help change looks very nice. I think that using the
generated version is much better as this pretty much removes the risk
of information missing in the output in case of future changes to the
options.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Actually QCoreApplication::applicationDirPath() is static so I don't need an instance. On 24 September 2018 at 19:27, nop head <nop.head@gmail.com> wrote: > The way it currently works is if it runs the GUI then it gets the > application path from the OpenSCADApp instance. If it runs the command line > version it instantiates a QCoreApplication app and uses that. Only if it is > compiled without QT does it use the boost version. > > To get the color schemes in the command line description it needs the app > path before it has processed the command line. I bodged it by always > creating a QCoreApplicationapp on the heap, using it to get the app path > and then deleting it. That seems to fix the problem and still uses QT if > compiled with QT. > > #ifdef OPENSCAD_QTGUI > QCoreApplication *app = new QCoreApplication(argc, argv); > const std::string application_path = QCoreApplication::instance()-> > applicationDirPath().toLocal8Bit().constData(); > delete app; > #else > const std::string application_path = fs::absolute(boost:: > filesystem::path(argv[0]).parent_path()).generic_string(); > #endif > PlatformUtils::registerApplicationPath(application_path); > > Can anybody see a problem with this hack? > > > On 24 September 2018 at 18:28, Torsten Paul <Torsten.Paul@gmx.de> wrote: > >> On 09/24/2018 04:03 PM, nop head wrote: >> >>> Having two QT app instances seems to be a problem, no surprise there! >>> Is there a reason for preferring the QT version? The boost version >>> produces the same path on my system so using that solves the problem. >>> >>> The current code might be just for legacy reasons, but there are various >> issues with boost on Windows regarding hard-links and non-ascii path. >> I don't know if the toLocal8Bit() from Qt is better, but it might actually >> help in those cases. Otherwise it would be nicer to just have a single >> way to determine the path. >> >> The command line help change looks very nice. I think that using the >> generated version is much better as this pretty much removes the risk >> of information missing in the output in case of future changes to the >> options. >> >> ciao, >> Torsten. >> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > >
NH
nop head
Mon, Sep 24, 2018 6:33 PM

#ifdef OPENSCAD_QTGUI
const std::string application_path =
QCoreApplication::applicationDirPath().toLocal8Bit().constData();
#else
const std::string application_path =
fs::absolute(boost::filesystem::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Much nicer!

On 24 September 2018 at 19:29, nop head nop.head@gmail.com wrote:

Actually QCoreApplication::applicationDirPath() is static so I don't need
an instance.

On 24 September 2018 at 19:27, nop head nop.head@gmail.com wrote:

The way it currently works is if it runs the GUI then it gets the
application path from the OpenSCADApp instance. If it runs the command line
version it instantiates a QCoreApplication app and uses that. Only if it is
compiled without QT does it use the boost version.

To get the color schemes in the command line description it needs the app
path before it has processed the command line. I bodged it by always
creating a QCoreApplicationapp on the heap, using it to get the app path
and then deleting it. That seems to fix the problem and still uses QT if
compiled with QT.

#ifdef OPENSCAD_QTGUI
QCoreApplication *app = new QCoreApplication(argc, argv);
const std::string application_path = QCoreApplication::instance()->
applicationDirPath().toLocal8Bit().constData();
delete app;
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Can anybody see a problem with this hack?

On 24 September 2018 at 18:28, Torsten Paul Torsten.Paul@gmx.de wrote:

On 09/24/2018 04:03 PM, nop head wrote:

Having two QT app instances seems to be a problem, no surprise there!
Is there a reason for preferring the QT version? The boost version
produces the same path on my system so using that solves the problem.

The current code might be just for legacy reasons, but there are various

issues with boost on Windows regarding hard-links and non-ascii path.
I don't know if the toLocal8Bit() from Qt is better, but it might
actually
help in those cases. Otherwise it would be nicer to just have a single
way to determine the path.

The command line help change looks very nice. I think that using the
generated version is much better as this pretty much removes the risk
of information missing in the output in case of future changes to the
options.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

#ifdef OPENSCAD_QTGUI const std::string application_path = QCoreApplication::applicationDirPath().toLocal8Bit().constData(); #else const std::string application_path = fs::absolute(boost::filesystem::path(argv[0]).parent_path()).generic_string(); #endif PlatformUtils::registerApplicationPath(application_path); Much nicer! On 24 September 2018 at 19:29, nop head <nop.head@gmail.com> wrote: > Actually QCoreApplication::applicationDirPath() is static so I don't need > an instance. > > On 24 September 2018 at 19:27, nop head <nop.head@gmail.com> wrote: > >> The way it currently works is if it runs the GUI then it gets the >> application path from the OpenSCADApp instance. If it runs the command line >> version it instantiates a QCoreApplication app and uses that. Only if it is >> compiled without QT does it use the boost version. >> >> To get the color schemes in the command line description it needs the app >> path before it has processed the command line. I bodged it by always >> creating a QCoreApplicationapp on the heap, using it to get the app path >> and then deleting it. That seems to fix the problem and still uses QT if >> compiled with QT. >> >> #ifdef OPENSCAD_QTGUI >> QCoreApplication *app = new QCoreApplication(argc, argv); >> const std::string application_path = QCoreApplication::instance()-> >> applicationDirPath().toLocal8Bit().constData(); >> delete app; >> #else >> const std::string application_path = fs::absolute(boost::filesystem >> ::path(argv[0]).parent_path()).generic_string(); >> #endif >> PlatformUtils::registerApplicationPath(application_path); >> >> Can anybody see a problem with this hack? >> >> >> On 24 September 2018 at 18:28, Torsten Paul <Torsten.Paul@gmx.de> wrote: >> >>> On 09/24/2018 04:03 PM, nop head wrote: >>> >>>> Having two QT app instances seems to be a problem, no surprise there! >>>> Is there a reason for preferring the QT version? The boost version >>>> produces the same path on my system so using that solves the problem. >>>> >>>> The current code might be just for legacy reasons, but there are various >>> issues with boost on Windows regarding hard-links and non-ascii path. >>> I don't know if the toLocal8Bit() from Qt is better, but it might >>> actually >>> help in those cases. Otherwise it would be nicer to just have a single >>> way to determine the path. >>> >>> The command line help change looks very nice. I think that using the >>> generated version is much better as this pretty much removes the risk >>> of information missing in the output in case of future changes to the >>> options. >>> >>> ciao, >>> Torsten. >>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >> >> >
NH
nop head
Mon, Sep 24, 2018 7:10 PM

A bit more re-ordering, some blank line separators and a list of
experimental features available. Anybody got any suggestions before I make
a PR.

Usage: openscad.exe [options] file.scad
Allowed options:
-o [ --o ] arg        out_file -output a file instead of running the GUI,
the
file extension specifies the type: stl, off, amf,
csg,
dxf, svg, png, echo, ast, term, nef3, nefdbg
-D [ --D ] arg        var=val -pre-define variables
-p [ --p ] arg        customizer parameter file
-P [ --P ] arg        customizer parameter set
--enable arg          enable experimental features: assert | echo |
lc-each |
lc-else | lc-for-c | amf-import | svg-import |
customizer
-h [ --help ]        print this help message and exit
-v [ --version ]      print the version

--camera arg          camera parameters when exporting png:
translate_x,y,z,rot_x,y,z,dist or
eye_x,y,z,center_x,y,z
--autocenter          adjust camera to look at object center
--viewall            adjust camera to fit object
--imgsize arg        =width,height for exporting png
--render arg          if exporting a png image, do a full geometry
evaluation
--preview arg        if exporting a png image, do an OpenCSG(default) or
ThrownTogether preview
--projection arg      (o)rtho or (p)erspective when exporting png
--colorscheme arg    colorscheme: *Cornfield | Metallic | Sunset |
Starnight
| BeforeDawn | Nature | DeepOcean | Solarized |
Tomorrow | Tomorrow Night | Monotone
--csglimit arg        if exporting a png image, stop rendering at the
given
number of CSG elements

-d [ --d ] arg        deps_file -generate a dependency file for make
-m [ --m ] arg        make_cmd -runs make_cmd file if file is missing
--info                print information about the build process
--debug arg          special debug info
-q [ --quiet ]        quiet mode (don't print anything except errors)
-s [ --s ] arg        stl-file deprecated, use -o
-x [ --x ] arg        dxf-file deprecated, use -o

On 24 September 2018 at 19:33, nop head nop.head@gmail.com wrote:

#ifdef OPENSCAD_QTGUI
const std::string application_path = QCoreApplication::
applicationDirPath().toLocal8Bit().constData();
#else
const std::string application_path = fs::absolute(boost::
filesystem::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Much nicer!

On 24 September 2018 at 19:29, nop head nop.head@gmail.com wrote:

Actually QCoreApplication::applicationDirPath() is static so I don't
need an instance.

On 24 September 2018 at 19:27, nop head nop.head@gmail.com wrote:

The way it currently works is if it runs the GUI then it gets the
application path from the OpenSCADApp instance. If it runs the command line
version it instantiates a QCoreApplication app and uses that. Only if it is
compiled without QT does it use the boost version.

To get the color schemes in the command line description it needs the
app path before it has processed the command line. I bodged it by always
creating a QCoreApplicationapp on the heap, using it to get the app path
and then deleting it. That seems to fix the problem and still uses QT if
compiled with QT.

#ifdef OPENSCAD_QTGUI
QCoreApplication *app = new QCoreApplication(argc, argv);
const std::string application_path = QCoreApplication::instance()->
applicationDirPath().toLocal8Bit().constData();
delete app;
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Can anybody see a problem with this hack?

On 24 September 2018 at 18:28, Torsten Paul Torsten.Paul@gmx.de wrote:

On 09/24/2018 04:03 PM, nop head wrote:

Having two QT app instances seems to be a problem, no surprise there!
Is there a reason for preferring the QT version? The boost version
produces the same path on my system so using that solves the problem.

The current code might be just for legacy reasons, but there are

various
issues with boost on Windows regarding hard-links and non-ascii path.
I don't know if the toLocal8Bit() from Qt is better, but it might
actually
help in those cases. Otherwise it would be nicer to just have a single
way to determine the path.

The command line help change looks very nice. I think that using the
generated version is much better as this pretty much removes the risk
of information missing in the output in case of future changes to the
options.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

A bit more re-ordering, some blank line separators and a list of experimental features available. Anybody got any suggestions before I make a PR. Usage: openscad.exe [options] file.scad Allowed options: -o [ --o ] arg out_file -output a file instead of running the GUI, the file extension specifies the type: stl, off, amf, csg, dxf, svg, png, echo, ast, term, nef3, nefdbg -D [ --D ] arg var=val -pre-define variables -p [ --p ] arg customizer parameter file -P [ --P ] arg customizer parameter set --enable arg enable experimental features: assert | echo | lc-each | lc-else | lc-for-c | amf-import | svg-import | customizer -h [ --help ] print this help message and exit -v [ --version ] print the version --camera arg camera parameters when exporting png: translate_x,y,z,rot_x,y,z,dist or eye_x,y,z,center_x,y,z --autocenter adjust camera to look at object center --viewall adjust camera to fit object --imgsize arg =width,height for exporting png --render arg if exporting a png image, do a full geometry evaluation --preview arg if exporting a png image, do an OpenCSG(default) or ThrownTogether preview --projection arg (o)rtho or (p)erspective when exporting png --colorscheme arg colorscheme: *Cornfield | Metallic | Sunset | Starnight | BeforeDawn | Nature | DeepOcean | Solarized | Tomorrow | Tomorrow Night | Monotone --csglimit arg if exporting a png image, stop rendering at the given number of CSG elements -d [ --d ] arg deps_file -generate a dependency file for make -m [ --m ] arg make_cmd -runs make_cmd file if file is missing --info print information about the build process --debug arg special debug info -q [ --quiet ] quiet mode (don't print anything *except* errors) -s [ --s ] arg stl-file deprecated, use -o -x [ --x ] arg dxf-file deprecated, use -o On 24 September 2018 at 19:33, nop head <nop.head@gmail.com> wrote: > #ifdef OPENSCAD_QTGUI > const std::string application_path = QCoreApplication:: > applicationDirPath().toLocal8Bit().constData(); > #else > const std::string application_path = fs::absolute(boost:: > filesystem::path(argv[0]).parent_path()).generic_string(); > #endif > PlatformUtils::registerApplicationPath(application_path); > > Much nicer! > > On 24 September 2018 at 19:29, nop head <nop.head@gmail.com> wrote: > >> Actually QCoreApplication::applicationDirPath() is static so I don't >> need an instance. >> >> On 24 September 2018 at 19:27, nop head <nop.head@gmail.com> wrote: >> >>> The way it currently works is if it runs the GUI then it gets the >>> application path from the OpenSCADApp instance. If it runs the command line >>> version it instantiates a QCoreApplication app and uses that. Only if it is >>> compiled without QT does it use the boost version. >>> >>> To get the color schemes in the command line description it needs the >>> app path before it has processed the command line. I bodged it by always >>> creating a QCoreApplicationapp on the heap, using it to get the app path >>> and then deleting it. That seems to fix the problem and still uses QT if >>> compiled with QT. >>> >>> #ifdef OPENSCAD_QTGUI >>> QCoreApplication *app = new QCoreApplication(argc, argv); >>> const std::string application_path = QCoreApplication::instance()-> >>> applicationDirPath().toLocal8Bit().constData(); >>> delete app; >>> #else >>> const std::string application_path = fs::absolute(boost::filesystem >>> ::path(argv[0]).parent_path()).generic_string(); >>> #endif >>> PlatformUtils::registerApplicationPath(application_path); >>> >>> Can anybody see a problem with this hack? >>> >>> >>> On 24 September 2018 at 18:28, Torsten Paul <Torsten.Paul@gmx.de> wrote: >>> >>>> On 09/24/2018 04:03 PM, nop head wrote: >>>> >>>>> Having two QT app instances seems to be a problem, no surprise there! >>>>> Is there a reason for preferring the QT version? The boost version >>>>> produces the same path on my system so using that solves the problem. >>>>> >>>>> The current code might be just for legacy reasons, but there are >>>> various >>>> issues with boost on Windows regarding hard-links and non-ascii path. >>>> I don't know if the toLocal8Bit() from Qt is better, but it might >>>> actually >>>> help in those cases. Otherwise it would be nicer to just have a single >>>> way to determine the path. >>>> >>>> The command line help change looks very nice. I think that using the >>>> generated version is much better as this pretty much removes the risk >>>> of information missing in the output in case of future changes to the >>>> options. >>>> >>>> ciao, >>>> Torsten. >>>> >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> Discuss@lists.openscad.org >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>> >>> >>> >> >
DM
doug moen
Mon, Sep 24, 2018 7:23 PM

const std::string application_path = fs::absolute(boost::
filesystem::path(argv[0]).parent_path()).generic_string();

This code won't work. Suppose that you git clone the OpenSCAD repository,
build it, and install it in some place like /usr/local/bin. Then, when you
type 'openscad' from a bash prompt, then argv[0] will just be the string
"openscad", with no directory component. application_path should be set to
"/usr/local/bin", but this code won't return the correct directory.

I have a function called 'progdir()' which computes the application
directory, portable between Linux and MacOS. However, I've never tested my
code on Windows. You can have the code if you want it. progdir() works by
searching the PATH environment variable, when necessary, to determine the
application path.

How important is it for OpenSCAD to work correctly if it is built without
linking to Qt?

On 24 September 2018 at 14:33, nop head nop.head@gmail.com wrote:

#ifdef OPENSCAD_QTGUI
const std::string application_path = QCoreApplication::
applicationDirPath().toLocal8Bit().constData();
#else
const std::string application_path = fs::absolute(boost::
filesystem::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Much nicer!

On 24 September 2018 at 19:29, nop head nop.head@gmail.com wrote:

Actually QCoreApplication::applicationDirPath() is static so I don't
need an instance.

On 24 September 2018 at 19:27, nop head nop.head@gmail.com wrote:

The way it currently works is if it runs the GUI then it gets the
application path from the OpenSCADApp instance. If it runs the command line
version it instantiates a QCoreApplication app and uses that. Only if it is
compiled without QT does it use the boost version.

To get the color schemes in the command line description it needs the
app path before it has processed the command line. I bodged it by always
creating a QCoreApplicationapp on the heap, using it to get the app path
and then deleting it. That seems to fix the problem and still uses QT if
compiled with QT.

#ifdef OPENSCAD_QTGUI
QCoreApplication *app = new QCoreApplication(argc, argv);
const std::string application_path = QCoreApplication::instance()->
applicationDirPath().toLocal8Bit().constData();
delete app;
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Can anybody see a problem with this hack?

On 24 September 2018 at 18:28, Torsten Paul Torsten.Paul@gmx.de wrote:

On 09/24/2018 04:03 PM, nop head wrote:

Having two QT app instances seems to be a problem, no surprise there!
Is there a reason for preferring the QT version? The boost version
produces the same path on my system so using that solves the problem.

The current code might be just for legacy reasons, but there are

various
issues with boost on Windows regarding hard-links and non-ascii path.
I don't know if the toLocal8Bit() from Qt is better, but it might
actually
help in those cases. Otherwise it would be nicer to just have a single
way to determine the path.

The command line help change looks very nice. I think that using the
generated version is much better as this pretty much removes the risk
of information missing in the output in case of future changes to the
options.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

const std::string application_path = fs::absolute(boost:: filesystem::path(argv[0]).parent_path()).generic_string(); This code won't work. Suppose that you git clone the OpenSCAD repository, build it, and install it in some place like /usr/local/bin. Then, when you type 'openscad' from a bash prompt, then argv[0] will just be the string "openscad", with no directory component. application_path should be set to "/usr/local/bin", but this code won't return the correct directory. I have a function called 'progdir()' which computes the application directory, portable between Linux and MacOS. However, I've never tested my code on Windows. You can have the code if you want it. progdir() works by searching the PATH environment variable, when necessary, to determine the application path. How important is it for OpenSCAD to work correctly if it is built without linking to Qt? On 24 September 2018 at 14:33, nop head <nop.head@gmail.com> wrote: > #ifdef OPENSCAD_QTGUI > const std::string application_path = QCoreApplication:: > applicationDirPath().toLocal8Bit().constData(); > #else > const std::string application_path = fs::absolute(boost:: > filesystem::path(argv[0]).parent_path()).generic_string(); > #endif > PlatformUtils::registerApplicationPath(application_path); > > Much nicer! > > On 24 September 2018 at 19:29, nop head <nop.head@gmail.com> wrote: > >> Actually QCoreApplication::applicationDirPath() is static so I don't >> need an instance. >> >> On 24 September 2018 at 19:27, nop head <nop.head@gmail.com> wrote: >> >>> The way it currently works is if it runs the GUI then it gets the >>> application path from the OpenSCADApp instance. If it runs the command line >>> version it instantiates a QCoreApplication app and uses that. Only if it is >>> compiled without QT does it use the boost version. >>> >>> To get the color schemes in the command line description it needs the >>> app path before it has processed the command line. I bodged it by always >>> creating a QCoreApplicationapp on the heap, using it to get the app path >>> and then deleting it. That seems to fix the problem and still uses QT if >>> compiled with QT. >>> >>> #ifdef OPENSCAD_QTGUI >>> QCoreApplication *app = new QCoreApplication(argc, argv); >>> const std::string application_path = QCoreApplication::instance()-> >>> applicationDirPath().toLocal8Bit().constData(); >>> delete app; >>> #else >>> const std::string application_path = fs::absolute(boost::filesystem >>> ::path(argv[0]).parent_path()).generic_string(); >>> #endif >>> PlatformUtils::registerApplicationPath(application_path); >>> >>> Can anybody see a problem with this hack? >>> >>> >>> On 24 September 2018 at 18:28, Torsten Paul <Torsten.Paul@gmx.de> wrote: >>> >>>> On 09/24/2018 04:03 PM, nop head wrote: >>>> >>>>> Having two QT app instances seems to be a problem, no surprise there! >>>>> Is there a reason for preferring the QT version? The boost version >>>>> produces the same path on my system so using that solves the problem. >>>>> >>>>> The current code might be just for legacy reasons, but there are >>>> various >>>> issues with boost on Windows regarding hard-links and non-ascii path. >>>> I don't know if the toLocal8Bit() from Qt is better, but it might >>>> actually >>>> help in those cases. Otherwise it would be nicer to just have a single >>>> way to determine the path. >>>> >>>> The command line help change looks very nice. I think that using the >>>> generated version is much better as this pretty much removes the risk >>>> of information missing in the output in case of future changes to the >>>> options. >>>> >>>> ciao, >>>> Torsten. >>>> >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> Discuss@lists.openscad.org >>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>> >>> >>> >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
NH
nop head
Mon, Sep 24, 2018 7:45 PM

I think argv[0] is the full path of the executable on Windows, regardless
of what you type, but on Linux it is just what you typed. Does your code
cope with it being a full path like
C:/msys64/home/ChrisP/openscad/release/openscad.exe?

On 24 September 2018 at 20:23, doug moen doug@moens.org wrote:

const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();

This code won't work. Suppose that you git clone the OpenSCAD repository,
build it, and install it in some place like /usr/local/bin. Then, when you
type 'openscad' from a bash prompt, then argv[0] will just be the string
"openscad", with no directory component. application_path should be set to
"/usr/local/bin", but this code won't return the correct directory.

I have a function called 'progdir()' which computes the application
directory, portable between Linux and MacOS. However, I've never tested my
code on Windows. You can have the code if you want it. progdir() works by
searching the PATH environment variable, when necessary, to determine the
application path.

How important is it for OpenSCAD to work correctly if it is built without
linking to Qt?

On 24 September 2018 at 14:33, nop head nop.head@gmail.com wrote:

#ifdef OPENSCAD_QTGUI
const std::string application_path = QCoreApplication::applicationD
irPath().toLocal8Bit().constData();
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Much nicer!

On 24 September 2018 at 19:29, nop head nop.head@gmail.com wrote:

Actually QCoreApplication::applicationDirPath() is static so I don't
need an instance.

On 24 September 2018 at 19:27, nop head nop.head@gmail.com wrote:

The way it currently works is if it runs the GUI then it gets the
application path from the OpenSCADApp instance. If it runs the command line
version it instantiates a QCoreApplication app and uses that. Only if it is
compiled without QT does it use the boost version.

To get the color schemes in the command line description it needs the
app path before it has processed the command line. I bodged it by always
creating a QCoreApplicationapp on the heap, using it to get the app path
and then deleting it. That seems to fix the problem and still uses QT if
compiled with QT.

#ifdef OPENSCAD_QTGUI
QCoreApplication *app = new QCoreApplication(argc, argv);
const std::string application_path = QCoreApplication::instance()->
applicationDirPath().toLocal8Bit().constData();
delete app;
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Can anybody see a problem with this hack?

On 24 September 2018 at 18:28, Torsten Paul Torsten.Paul@gmx.de
wrote:

On 09/24/2018 04:03 PM, nop head wrote:

Having two QT app instances seems to be a problem, no surprise there!
Is there a reason for preferring the QT version? The boost version
produces the same path on my system so using that solves the problem.

The current code might be just for legacy reasons, but there are

various
issues with boost on Windows regarding hard-links and non-ascii path.
I don't know if the toLocal8Bit() from Qt is better, but it might
actually
help in those cases. Otherwise it would be nicer to just have a single
way to determine the path.

The command line help change looks very nice. I think that using the
generated version is much better as this pretty much removes the risk
of information missing in the output in case of future changes to the
options.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I think argv[0] is the full path of the executable on Windows, regardless of what you type, but on Linux it is just what you typed. Does your code cope with it being a full path like C:/msys64/home/ChrisP/openscad/release/openscad.exe? On 24 September 2018 at 20:23, doug moen <doug@moens.org> wrote: > const std::string application_path = fs::absolute(boost::filesystem > ::path(argv[0]).parent_path()).generic_string(); > > This code won't work. Suppose that you git clone the OpenSCAD repository, > build it, and install it in some place like /usr/local/bin. Then, when you > type 'openscad' from a bash prompt, then argv[0] will just be the string > "openscad", with no directory component. application_path should be set to > "/usr/local/bin", but this code won't return the correct directory. > > I have a function called 'progdir()' which computes the application > directory, portable between Linux and MacOS. However, I've never tested my > code on Windows. You can have the code if you want it. progdir() works by > searching the PATH environment variable, when necessary, to determine the > application path. > > How important is it for OpenSCAD to work correctly if it is built without > linking to Qt? > > On 24 September 2018 at 14:33, nop head <nop.head@gmail.com> wrote: > >> #ifdef OPENSCAD_QTGUI >> const std::string application_path = QCoreApplication::applicationD >> irPath().toLocal8Bit().constData(); >> #else >> const std::string application_path = fs::absolute(boost::filesystem >> ::path(argv[0]).parent_path()).generic_string(); >> #endif >> PlatformUtils::registerApplicationPath(application_path); >> >> Much nicer! >> >> On 24 September 2018 at 19:29, nop head <nop.head@gmail.com> wrote: >> >>> Actually QCoreApplication::applicationDirPath() is static so I don't >>> need an instance. >>> >>> On 24 September 2018 at 19:27, nop head <nop.head@gmail.com> wrote: >>> >>>> The way it currently works is if it runs the GUI then it gets the >>>> application path from the OpenSCADApp instance. If it runs the command line >>>> version it instantiates a QCoreApplication app and uses that. Only if it is >>>> compiled without QT does it use the boost version. >>>> >>>> To get the color schemes in the command line description it needs the >>>> app path before it has processed the command line. I bodged it by always >>>> creating a QCoreApplicationapp on the heap, using it to get the app path >>>> and then deleting it. That seems to fix the problem and still uses QT if >>>> compiled with QT. >>>> >>>> #ifdef OPENSCAD_QTGUI >>>> QCoreApplication *app = new QCoreApplication(argc, argv); >>>> const std::string application_path = QCoreApplication::instance()-> >>>> applicationDirPath().toLocal8Bit().constData(); >>>> delete app; >>>> #else >>>> const std::string application_path = fs::absolute(boost::filesystem >>>> ::path(argv[0]).parent_path()).generic_string(); >>>> #endif >>>> PlatformUtils::registerApplicationPath(application_path); >>>> >>>> Can anybody see a problem with this hack? >>>> >>>> >>>> On 24 September 2018 at 18:28, Torsten Paul <Torsten.Paul@gmx.de> >>>> wrote: >>>> >>>>> On 09/24/2018 04:03 PM, nop head wrote: >>>>> >>>>>> Having two QT app instances seems to be a problem, no surprise there! >>>>>> Is there a reason for preferring the QT version? The boost version >>>>>> produces the same path on my system so using that solves the problem. >>>>>> >>>>>> The current code might be just for legacy reasons, but there are >>>>> various >>>>> issues with boost on Windows regarding hard-links and non-ascii path. >>>>> I don't know if the toLocal8Bit() from Qt is better, but it might >>>>> actually >>>>> help in those cases. Otherwise it would be nicer to just have a single >>>>> way to determine the path. >>>>> >>>>> The command line help change looks very nice. I think that using the >>>>> generated version is much better as this pretty much removes the risk >>>>> of information missing in the output in case of future changes to the >>>>> options. >>>>> >>>>> ciao, >>>>> Torsten. >>>>> >>>>> >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> Discuss@lists.openscad.org >>>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>>> >>>> >>>> >>> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
DM
doug moen
Mon, Sep 24, 2018 8:25 PM

Okay, here is my code. It's based on boost::filesystem, which OpenSCAD
already uses. It also uses my custom curv::Exception class, but you can
easily replace that part.

I think the only part of this that won't work on Windows is the part where
it splits the PATH variable at ':' characters. I think that should be a ';'
character on Windows, but I don't have a Windows dev environment to test
on. The licence can be replaced by GPL2, but keep the copyright notice.

Actually, here's another possible Windows dependency. If 'openscad.exe'
exists in the current directory, and you type 'openscad', then what
happens? If the existence of openscad.exe in the current directory
overrides the PATH search on Windows, and if argv[0] is set to "openscad"
in that case, then extra code would be required.

// Copyright 2016-2018 Doug Moen
// Licensed under the Apache License, version 2.0
// See https://www.apache.org/licenses/LICENSE-2.0

extern "C" {
#include <stdlib.h>
#include <string.h>
}
#include <libcurv/exception.h>
#include "progdir.h"
namespace fs = boost::filesystem;

/*

  • Compute the absolute pathname of the directory

  • containing the program executable.

  • The storage for the result string is dynamically allocated.

  • argv0 is argv[0] of the argv passed to main().

  • ,,, Unix specific, right now.
    */
    fs::path
    progdir(const char *argv0)
    {
    fs::path cmd(argv0);

    if (cmd.is_absolute())
    return cmd.parent_path();

    if (cmd.has_parent_path())
    return fs::current_path() / cmd.parent_path();

    const char* PATH = getenv("PATH");
    if (PATH == NULL) {
    throw curv::Exception_Base(curv::stringify(
    "Can't determine directory of program ", argv0,
    ": PATH not defined"));
    }

    const char* p = PATH;
    const char* pend = PATH + strlen(PATH);
    while (p < pend) {
    const char* q = strchr(p, ':');
    if (q == nullptr)
    q = pend;
    fs::path file(p, q);
    file /= argv0;
    if (fs::exists(fs::status(file)))
    return file.parent_path();
    p = (q < pend ? q + 1 : pend);
    }

    throw curv::Exception_Base(curv::stringify(
    "Can't determine directory of program ", argv0,
    ": can't find ", argv0, " in $PATH"));
    }

On 24 September 2018 at 15:45, nop head nop.head@gmail.com wrote:

I think argv[0] is the full path of the executable on Windows, regardless
of what you type, but on Linux it is just what you typed. Does your code
cope with it being a full path like C:/msys64/home/ChrisP/
openscad/release/openscad.exe?

On 24 September 2018 at 20:23, doug moen doug@moens.org wrote:

const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();

This code won't work. Suppose that you git clone the OpenSCAD repository,
build it, and install it in some place like /usr/local/bin. Then, when you
type 'openscad' from a bash prompt, then argv[0] will just be the string
"openscad", with no directory component. application_path should be set to
"/usr/local/bin", but this code won't return the correct directory.

I have a function called 'progdir()' which computes the application
directory, portable between Linux and MacOS. However, I've never tested my
code on Windows. You can have the code if you want it. progdir() works by
searching the PATH environment variable, when necessary, to determine the
application path.

How important is it for OpenSCAD to work correctly if it is built without
linking to Qt?

On 24 September 2018 at 14:33, nop head nop.head@gmail.com wrote:

#ifdef OPENSCAD_QTGUI
const std::string application_path = QCoreApplication::applicationD
irPath().toLocal8Bit().constData();
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Much nicer!

On 24 September 2018 at 19:29, nop head nop.head@gmail.com wrote:

Actually QCoreApplication::applicationDirPath() is static so I don't
need an instance.

On 24 September 2018 at 19:27, nop head nop.head@gmail.com wrote:

The way it currently works is if it runs the GUI then it gets the
application path from the OpenSCADApp instance. If it runs the command line
version it instantiates a QCoreApplication app and uses that. Only if it is
compiled without QT does it use the boost version.

To get the color schemes in the command line description it needs the
app path before it has processed the command line. I bodged it by always
creating a QCoreApplicationapp on the heap, using it to get the app path
and then deleting it. That seems to fix the problem and still uses QT if
compiled with QT.

#ifdef OPENSCAD_QTGUI
QCoreApplication *app = new QCoreApplication(argc, argv);
const std::string application_path = QCoreApplication::instance()->
applicationDirPath().toLocal8Bit().constData();
delete app;
#else
const std::string application_path = fs::absolute(boost::filesystem
::path(argv[0]).parent_path()).generic_string();
#endif
PlatformUtils::registerApplicationPath(application_path);

Can anybody see a problem with this hack?

On 24 September 2018 at 18:28, Torsten Paul Torsten.Paul@gmx.de
wrote:

On 09/24/2018 04:03 PM, nop head wrote:

Having two QT app instances seems to be a problem, no surprise there!
Is there a reason for preferring the QT version? The boost version
produces the same path on my system so using that solves the problem.

The current code might be just for legacy reasons, but there are

various
issues with boost on Windows regarding hard-links and non-ascii path.
I don't know if the toLocal8Bit() from Qt is better, but it might
actually
help in those cases. Otherwise it would be nicer to just have a single
way to determine the path.

The command line help change looks very nice. I think that using the
generated version is much better as this pretty much removes the risk
of information missing in the output in case of future changes to the
options.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Okay, here is my code. It's based on boost::filesystem, which OpenSCAD already uses. It also uses my custom curv::Exception class, but you can easily replace that part. I think the only part of this that won't work on Windows is the part where it splits the PATH variable at ':' characters. I think that should be a ';' character on Windows, but I don't have a Windows dev environment to test on. The licence can be replaced by GPL2, but keep the copyright notice. Actually, here's another possible Windows dependency. If 'openscad.exe' exists in the current directory, and you type 'openscad', then what happens? If the existence of openscad.exe in the current directory overrides the PATH search on Windows, and if argv[0] is set to "openscad" in that case, then extra code would be required. // Copyright 2016-2018 Doug Moen // Licensed under the Apache License, version 2.0 // See https://www.apache.org/licenses/LICENSE-2.0 extern "C" { #include <stdlib.h> #include <string.h> } #include <libcurv/exception.h> #include "progdir.h" namespace fs = boost::filesystem; /* * Compute the absolute pathname of the directory * containing the program executable. * The storage for the result string is dynamically allocated. * argv0 is argv[0] of the argv passed to main(). * ,,, Unix specific, right now. */ fs::path progdir(const char *argv0) { fs::path cmd(argv0); if (cmd.is_absolute()) return cmd.parent_path(); if (cmd.has_parent_path()) return fs::current_path() / cmd.parent_path(); const char* PATH = getenv("PATH"); if (PATH == NULL) { throw curv::Exception_Base(curv::stringify( "Can't determine directory of program ", argv0, ": PATH not defined")); } const char* p = PATH; const char* pend = PATH + strlen(PATH); while (p < pend) { const char* q = strchr(p, ':'); if (q == nullptr) q = pend; fs::path file(p, q); file /= argv0; if (fs::exists(fs::status(file))) return file.parent_path(); p = (q < pend ? q + 1 : pend); } throw curv::Exception_Base(curv::stringify( "Can't determine directory of program ", argv0, ": can't find ", argv0, " in $PATH")); } On 24 September 2018 at 15:45, nop head <nop.head@gmail.com> wrote: > I think argv[0] is the full path of the executable on Windows, regardless > of what you type, but on Linux it is just what you typed. Does your code > cope with it being a full path like C:/msys64/home/ChrisP/ > openscad/release/openscad.exe? > > On 24 September 2018 at 20:23, doug moen <doug@moens.org> wrote: > >> const std::string application_path = fs::absolute(boost::filesystem >> ::path(argv[0]).parent_path()).generic_string(); >> >> This code won't work. Suppose that you git clone the OpenSCAD repository, >> build it, and install it in some place like /usr/local/bin. Then, when you >> type 'openscad' from a bash prompt, then argv[0] will just be the string >> "openscad", with no directory component. application_path should be set to >> "/usr/local/bin", but this code won't return the correct directory. >> >> I have a function called 'progdir()' which computes the application >> directory, portable between Linux and MacOS. However, I've never tested my >> code on Windows. You can have the code if you want it. progdir() works by >> searching the PATH environment variable, when necessary, to determine the >> application path. >> >> How important is it for OpenSCAD to work correctly if it is built without >> linking to Qt? >> >> On 24 September 2018 at 14:33, nop head <nop.head@gmail.com> wrote: >> >>> #ifdef OPENSCAD_QTGUI >>> const std::string application_path = QCoreApplication::applicationD >>> irPath().toLocal8Bit().constData(); >>> #else >>> const std::string application_path = fs::absolute(boost::filesystem >>> ::path(argv[0]).parent_path()).generic_string(); >>> #endif >>> PlatformUtils::registerApplicationPath(application_path); >>> >>> Much nicer! >>> >>> On 24 September 2018 at 19:29, nop head <nop.head@gmail.com> wrote: >>> >>>> Actually QCoreApplication::applicationDirPath() is static so I don't >>>> need an instance. >>>> >>>> On 24 September 2018 at 19:27, nop head <nop.head@gmail.com> wrote: >>>> >>>>> The way it currently works is if it runs the GUI then it gets the >>>>> application path from the OpenSCADApp instance. If it runs the command line >>>>> version it instantiates a QCoreApplication app and uses that. Only if it is >>>>> compiled without QT does it use the boost version. >>>>> >>>>> To get the color schemes in the command line description it needs the >>>>> app path before it has processed the command line. I bodged it by always >>>>> creating a QCoreApplicationapp on the heap, using it to get the app path >>>>> and then deleting it. That seems to fix the problem and still uses QT if >>>>> compiled with QT. >>>>> >>>>> #ifdef OPENSCAD_QTGUI >>>>> QCoreApplication *app = new QCoreApplication(argc, argv); >>>>> const std::string application_path = QCoreApplication::instance()-> >>>>> applicationDirPath().toLocal8Bit().constData(); >>>>> delete app; >>>>> #else >>>>> const std::string application_path = fs::absolute(boost::filesystem >>>>> ::path(argv[0]).parent_path()).generic_string(); >>>>> #endif >>>>> PlatformUtils::registerApplicationPath(application_path); >>>>> >>>>> Can anybody see a problem with this hack? >>>>> >>>>> >>>>> On 24 September 2018 at 18:28, Torsten Paul <Torsten.Paul@gmx.de> >>>>> wrote: >>>>> >>>>>> On 09/24/2018 04:03 PM, nop head wrote: >>>>>> >>>>>>> Having two QT app instances seems to be a problem, no surprise there! >>>>>>> Is there a reason for preferring the QT version? The boost version >>>>>>> produces the same path on my system so using that solves the problem. >>>>>>> >>>>>>> The current code might be just for legacy reasons, but there are >>>>>> various >>>>>> issues with boost on Windows regarding hard-links and non-ascii path. >>>>>> I don't know if the toLocal8Bit() from Qt is better, but it might >>>>>> actually >>>>>> help in those cases. Otherwise it would be nicer to just have a single >>>>>> way to determine the path. >>>>>> >>>>>> The command line help change looks very nice. I think that using the >>>>>> generated version is much better as this pretty much removes the risk >>>>>> of information missing in the output in case of future changes to the >>>>>> options. >>>>>> >>>>>> ciao, >>>>>> Torsten. >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> OpenSCAD mailing list >>>>>> Discuss@lists.openscad.org >>>>>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>>>>> >>>>> >>>>> >>>> >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >>> >>> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
TP
Torsten Paul
Mon, Sep 24, 2018 9:32 PM

Just a note on licensing, OpenSCAD code requires to be GPL2+,
including the "or (at your option) any later version" clause.
Otherwise it would not be possible to distribute OpenSCAD
anymore.

ciao,
Torsten.

Just a note on licensing, OpenSCAD code requires to be GPL2+, including the "or (at your option) any later version" clause. Otherwise it would not be possible to distribute OpenSCAD anymore. ciao, Torsten.
DM
doug moen
Mon, Sep 24, 2018 9:37 PM

You can relicense this particular code with any open source licence you
wish. GPL2+ is fine, I didn't intend to exclude that.

On 24 September 2018 at 17:32, Torsten Paul Torsten.Paul@gmx.de wrote:

Just a note on licensing, OpenSCAD code requires to be GPL2+,
including the "or (at your option) any later version" clause.
Otherwise it would not be possible to distribute OpenSCAD
anymore.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

You can relicense this particular code with any open source licence you wish. GPL2+ is fine, I didn't intend to exclude that. On 24 September 2018 at 17:32, Torsten Paul <Torsten.Paul@gmx.de> wrote: > Just a note on licensing, OpenSCAD code requires to be GPL2+, > including the "or (at your option) any later version" clause. > Otherwise it would not be possible to distribute OpenSCAD > anymore. > > > ciao, > Torsten. > > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
TP
Torsten Paul
Mon, Sep 24, 2018 9:43 PM

On 09/24/2018 11:37 PM, doug moen wrote:

You can relicense this particular code with any open source
licence you wish. GPL2+ is fine, I didn't intend to exclude
that.

Great, thanks, as (due to CGAL) the final application is GPL3+
anyway, it would work with Apache-2.0, I think. Having both
options is  even better :-).

ciao,
Torsten.

On 09/24/2018 11:37 PM, doug moen wrote: > You can relicense this particular code with any open source > licence you wish. GPL2+ is fine, I didn't intend to exclude > that. > Great, thanks, as (due to CGAL) the final application is GPL3+ anyway, it would work with Apache-2.0, I think. Having both options is even better :-). ciao, Torsten.
NH
nop head
Mon, Sep 24, 2018 11:19 PM

If 'openscad.exe' exists in the current directory, and you type
'openscad', then what happens?

Win7 cmd.exe runs it. MSYS2's bash doesn't run unless you prepend ./

I wrote a win32 console program in a very old version of Visual studio and
found argv[0] is what you type, like Unix when run from CMD.EXE. However if
I run it in MSYS2's bash it is always the full path regardless. Also when
launched from the Desktop GUI then it is always the full path.

So when a program is run from CMD I think you have to look in the current
directory and then the path.

On 24 September 2018 at 22:43, Torsten Paul Torsten.Paul@gmx.de wrote:

On 09/24/2018 11:37 PM, doug moen wrote:

You can relicense this particular code with any open source
licence you wish. GPL2+ is fine, I didn't intend to exclude
that.

Great, thanks, as (due to CGAL) the final application is GPL3+

anyway, it would work with Apache-2.0, I think. Having both
options is  even better :-).

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

> > If 'openscad.exe' exists in the current directory, and you type > 'openscad', then what happens? > Win7 cmd.exe runs it. MSYS2's bash doesn't run unless you prepend ./ I wrote a win32 console program in a very old version of Visual studio and found argv[0] is what you type, like Unix when run from CMD.EXE. However if I run it in MSYS2's bash it is always the full path regardless. Also when launched from the Desktop GUI then it is always the full path. So when a program is run from CMD I think you have to look in the current directory and then the path. On 24 September 2018 at 22:43, Torsten Paul <Torsten.Paul@gmx.de> wrote: > On 09/24/2018 11:37 PM, doug moen wrote: > >> You can relicense this particular code with any open source >> licence you wish. GPL2+ is fine, I didn't intend to exclude >> that. >> >> Great, thanks, as (due to CGAL) the final application is GPL3+ > anyway, it would work with Apache-2.0, I think. Having both > options is even better :-). > > > ciao, > Torsten. > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >