My issues is about how I should arrange the files and folders of my source code, utilizing Nim's module system. I am just starting with Nim and am coming from C++ where I used to duct tape everything together using include statements.
Let's say that my project consists of three main components: a platform layer, a game engine layer, and a game logic layer. Not sure if it's relevant, but here is some more background on how these layers are interacting with each other (very simplified): platform passes input to game -> game asks engine to render stuff and playback audio -> engine writes audio and bitmap data to buffers for platform layer -> and we go again.
Now my first thought would be to treat those three components as modules. Assuming that this makes any sense, how would you suggest to arrange them in terms of folders and files? Each of them will be pretty large and certainly span across several files for sanity. So I created folders for them:
- source
- platform
- engine
- game
I went ahead and created main.nim files for every component, and also a file entry.nim in the root that imports the three modules and provides the main loop.
- source
- entry.nim (imports platform/main, engine/main, game/main)
- platform
- main.nim (includes other platform files)
- other platform files
- engine
- main.nim (includes other engine files)
- other engine files
- game
- main.nim (includes other game files)
- other game files
I kind of imagine the main.nim files like index files a web page or entry points for modules in an web CMS. Apparently though, the creators of the Nim module system had something very different in mind since I had to learn that it is not possible to import several modules of the same file name, even when assigning different names to them using the as keyword.
so here's another approach:
- source
- entry.nim (imports platform.nim, engine.nim, game.nim)
- platform.nim (includes platform files)
- engine.nim (includes engine files)
- game.nim (includes game files)
- platform
- platform files
- engine
- engine files
- game
- engine files
However, I really dislike this approach since now, I have two items of equal name (one file and one folder) for every component in the root of my source. I feel like that this will get very messy in the future and it just looks confusing as it messes up the entire idea behind folders in a file system.
There's one more solution that comes to mind, but that one to me is even uglier than the previous one:
- source
- entry.nim (imports platform/platform, engine/engine, game/game)
- platform
- platform.nim (includes other platform files)
- other platform files
- engine
- engine.nim (includes other engine files)
- other engine files
- game
- game.nim (includes other game files)
- other game files
I cannot have something like import game/game in my source. That just goes against every fiber of my being. The same goes for import gameModule/game or import game/main1, import engine/main2, ...
TL;DR: When a large module is split into several files that are grouped by using a folder that has the name of that module, how should I call the "entry point" of that module without using a generic name and without re-using the name that's already been given to its containing folder? I am clueless. Have I maybe utterly failed to grasp the module system to fail at something so trivial?
Yes, nimsuggest works really not bad now. For example I can investigate tables.nim fine, jumping to impl works also. One problem are still the generic procs, that symbols seems to be inactive, I guess there is already an hard issue in bug tracker.
Now I consider supporting the outline and highlight commands also. Seems that these send always info for the full file, which can be some thousand lines. And format for both commands is very different currently:
highlight skConst 1108 8 5
highlight skConst 1123 5 12
> outline engine.nim:engine.nim:120:0
outline skVar engine.ENDG /home/stefan/nim-chess2/engine.nim 13 4 "" 100
outline skProc engine.deleteIf /home/stefan/nim-chess2/engine.nim 15 5 "" 100
Testing should be easy, so maybe I will do. But processing thousand of lines for each keystroke may be a bit slow :-)
Well for me it simply does not work at all. I tried out both emacs and VS-Code with this file here from my project:
Emacs shows a lot of error messages for unknown symbols. The same was for the VS-Code editor. I did not try other editors. Do you know an editor that works?
EDIT: I now did find the documentation about nimsuggest.
@Stefan_Salewsk Well that file is included like all other files from the includes folder from the main nim file, here: https://github.com/krux02/opengl-sandbox/blob/master/fancygl.nim
The entire discussion is about autodetecting this root of the compilation.
Yes I understand. What I generally would do is first open the main file fancygl.nim, and jump from there to other symbols (Ctrl W for my editor). Explicitely opening additional related files should work as well. But when I additional open shadingDsl.nim nimsuggest does not work properly any more.
That may be related to gl module, see my first reply here:
https://github.com/nim-lang/nimsuggest/issues/55
With my minimal test example all was working well, but when I jumped to definition of other symbols in other gl files with CTRL W I got that "recursive module dependency: /home/stefan/.nimble/pkgs/opengl-1.1.0/opengl.nim imports /tmp/hhh/h.nimx0A/tmp/hhh/h.nim imports /home/stefan/.nimble/pkgs/opengl-1.1.0/opengl.nim" message, which is obviously wrong.
I have never observed that problem with other modules with includes, all my test with the modules shipped with Nim (which have many includes) does not show this problem for me. As I wrote in the bugtracker, that problem may be special to opengl module, and I have no idea how to show that problem to Araq when nimsuggest is called from the command line for testing.
What I get for testing is only:
$ cat h.nim
import opengl
proc main =
var b: ptr GLuint
var i: GLsizei
echo "entering main"
glGenBuffers(i, b) # line X
#glGenBuffers(
main()
$ nimsuggest --v2 --stdin h.nim
Hint: used config file '/home/stefan/Nim/config/nim.cfg' [Conf]
usage: sug|con|def|use|dus|chk|mod|highlight|outline|known file.nim[;dirtyfile.nim]:line:col
type 'quit' to quit
type 'debug' to toggle debug mode on/off
type 'terse' to toggle terse mode on/off
> chk h.nim:0:0
chk skUnknown Hint ??? -1 -1 "h [Processing]" 0
> chk opengl.nim:0:0
chk skUnknown Error ??? -1 -1 "invalid module name: \'\'" 0
chk skUnknown Hint ??? -1 -1 " [Processing]" 0
chk skUnknown Error ??? -1 -1 "cannot open \'\'" 0
looks like NimLime for Sublime doesn't invoke it properly then? :(