pkulchenko / ZeroBraneStudio

Lightweight Lua-based IDE for Lua with code completion, syntax highlighting, live coding, remote debugger, and code analyzer; supports Lua 5.1, 5.2, 5.3, 5.4, LuaJIT and other Lua interpreters on Windows, macOS, and Linux
http://studio.zerobrane.com/
Other
2.61k stars 519 forks source link

Drop CWD hack, stay in user's current directory #1040

Open alerque opened 4 years ago

alerque commented 4 years ago

The current wrapper script hack that cds into the app's source directory is really obnoxious to use. Even simple things like the File→Open not being in the home directory are unexpected.

The solution would be to prepend all the Lua related paths with the app directory so that it understands how to require() stuff from there properly even though the CWD may be anywhere on the system.

We've implemented this for SILE and while it's a bit of a mind bender to get right, it can and does work.

If you assign this issue to me at some point (not soon maybe, but sometime!) I'll mess around with it and try to contribute an equivalent bit of code that fixes up the paths.

See also #1039.

pkulchenko commented 4 years ago

The solution would be to prepend all the Lua related paths with the app directory so that it understands how to require() stuff from there properly even though the CWD may be anywhere on the system.

@alerque, can you point me to how it's done in SILE? The current approach is a bit ugly, but so far it covers all the use cases that the users care about, including launching the ide from another location using a relative or absolute path. Why are you trying to change this (other than making it less ugly)?

File>Open should work, as the file is opened from the current project directory, which is set most of the time. Are you thinking about a situation when a project directory is not yet set? Even in that case, File>Open works in a system-dependent way for me, as on Windows it shows the last directory used and is not related to the current folder (as none is set).

alerque commented 4 years ago

When I start a clean launch of zbs (no open project, as in first run) then look at File→Open it is in /usr/bin/zbstudio. That's the first problem I was thinking to fix. I realize it could be fixed by adding more and more shims to work around the fact that the main process's cwd is elsewhere, but I think long term the best solution is actually to let the process's cwd be where the user actually things they are and add the "fixes" to zbs's internal understanding of itself. The model is just backwards.

In SILE's case most of the heavy lifting is here:

https://github.com/sile-typesetter/sile/blob/c4e040c1b4d643015ba3888ce5cff7094a3aaf1c/sile.in#L1-L34

Obviously it gets some help from GNU Autoconf (./configure) at build time to know about the system's Lua path, what prefix we expect to be installed under (i.e. /usr/share/sile). From there it knows where it will be, and prepends it's own app-relative Lua include paths. In our case we also prepend the main process's PWD (.) to the include path so that relative paths work relative to where the user actually is in priority to everything else. That leaves the default Lua paths last in the list.

You can see this in action on my system's installed version of SILE here:

$ sile -e 'require("bogus")'
This is SILE v0.10.3.r2-gea81598
/usr/bin/lua: ./core/sile.lua:86: [string "require("bogus")"]:1: module 'bogus' not found:
        no field package.preload['bogus']
        no file './bogus.lua'
        no file './bogus/init.lua'
        no file './lua-libraries/bogus.lua'
        no file './lua-libraries/bogus/init.lua'
        no file '/usr/bin//bogus.lua'
        no file '/usr/bin//bogus/init.lua'
        no file '/usr/bin//lua-libraries/bogus.lua'
        no file '/usr/bin//lua-libraries/bogus/init.lua'
        no file '/usr/lib/sile/bogus.lua'
        no file '/usr/lib/sile/bogus/init.lua'
        no file '/usr/lib/sile/lua-libraries/bogus.lua'
        no file '/usr/lib/sile/lua-libraries/bogus/init.lua'
        no file '/usr/share/sile/bogus.lua'
        no file '/usr/share/sile/bogus/init.lua'
        no file '/usr/share/sile/lua-libraries/bogus.lua'
        no file '/usr/share/sile/lua-libraries/bogus/init.lua'
        no file '/usr/share/lua/5.3/bogus.lua'
        no file '/usr/share/lua/5.3/bogus/init.lua'
        no file '/usr/lib/lua/5.3/bogus.lua'
        no file '/usr/lib/lua/5.3/bogus/init.lua'
        no file './bogus.lua'
        no file './bogus/init.lua'
        no file './bogus.so'
        no file './core/bogus.so'
        no file '/usr/bin//bogus.so'
        no file '/usr/bin//core/bogus.so'
        no file '/usr/lib/sile/bogus.so'
        no file '/usr/lib/sile/core/bogus.so'
        no file '/usr/share/sile/bogus.so'
        no file '/usr/share/sile/core/bogus.so'
        no file '/usr/lib/lua/5.3/bogus.so'
        no file '/usr/lib/lua/5.3/loadall.so'
        no file './bogus.so'

Looking at that now I'm actually not sure why the LUA_CPATH is lower precedence than the LUA_PATH, but you get the general idea. First ./ and friends, then <sile app dir>/ and friends, then <system paths>

pkulchenko commented 4 years ago

When I start a clean launch of zbs (no open project, as in first run) then look at File→Open it is in /usr/bin/zbstudio. That's the first problem I was thinking to fix. I realize it could be fixed by adding more and more shims to work around the fact that the main process's cwd is elsewhere, but I think long term the best solution is actually to let the process's cwd be where the user actually things they are and add the "fixes" to zbs's internal understanding of itself. The model is just backwards.

I kind of agree, but I think we need to take into consideration that the IDE can be launched in multiple ways that need to be handled: (1) from a repository clone/snapshot, (2) from an installation package, (3) from a portable configuration, (4) from a macOS app/bundle. Each method has to work on all supported platforms with both zbstudio and bin/lua src/main.lua methods working (including parameter handling for files and directories). It's definitely possible to make it work while staying in the current folder, but it was simple to have one way to do this in the IDE code and have system-specific wrappers that set up proper environment to launch (which is what zbstudio.sh and zbstudio executable do). It does look a bit kludgy, but it covers all the listed scenarios (or at least I expect it to).

I think File>Open issue should be handled with the following ("more shims"):

diff --git a/src/editor/commands.lua b/src/editor/commands.lua
index f9fae6c9..ac7adae3 100644
--- a/src/editor/commands.lua
+++ b/src/editor/commands.lua
@@ -257,7 +257,7 @@ function OpenFile(event)
   local editor = ide:GetEditor()
   local path = editor and ide:GetDocument(editor):GetFilePath() or nil
   local fileDialog = wx.wxFileDialog(ide.frame, TR("Open file"),
-    (path and GetPathWithSep(path) or ide:GetProject() or ""),
+    (path and GetPathWithSep(path) or ide:GetProject() or ide.cwd or ""),
     "",
     getExtsString(editor),
     wx.wxFD_OPEN + wx.wxFD_FILE_MUST_EXIST + wx.wxFD_MULTIPLE)

Obviously it gets some help from GNU Autoconf (./configure) at build time to know about the system's Lua path, what prefix we expect to be installed under (i.e. /usr/share/sile).

Right; without autoconf help (which sets SILE_LIB_PATH and SILE_PATH), SILE is in the same position as ZBS (except that I also need to make it run from a repo clone and a portable install).

I'm not in favor of kludges, but I went through several iterations of improvements (#157, #829, #830, and likely others) and the current mechanism looks to be the most convenient out of those that we tried.

alerque commented 4 years ago

The example I showed actually supports all four of those scenarios (and a couple more) already.

pkulchenko commented 4 years ago

Without setting SILE_LIB_PATH? I'll take another look...