Re: failing to read xml
I found that if I don't go into child nodes then it doesn't assert: but then it doesn't go through the XML file either! Here's a modified `write` that still asserts: proc write(file: File, node: XmlNode, indent: int) = if indent > 0: file.write(spaces(indent)) file.write(&"<{node.tag}") let attrs = node.attrs() if attrs != nil: for (key, value) in attrs.pairs(): file.write(&" {key}=\"{value}\"") file.write(">") if node.kind != xnElement and node.text != "": file.write(node.text) if len(node) > 0: for child in node: write(file, child, indent + INDENT) file.write(&"\n") Run I tried commenting out the attrs code and the node.text code but that didn't help. SOLVED: The problem was with the signature. Even though I don't (knowingly) modify any nodes, changing the signature's `node: XmlNode` to `node: var XmlNode` cured the assertion error.
Re: failing to read xml
I modified the `write` proc as suggested but it doesn't help: if node.kind in {xnText, xnCData, xnEntity, xnComment} and node.text != "": file.write(node.text) Run Assert: fatal.nim(39)sysFatal Error: unhandled exception: xmltree.nim(213, 10) `n.k == xnElement` [AssertionError] Run I also tried: if node.kind != xnElement and node.text != "": file.write(node.text) Run And that also asserted with the same message. And just to be sure I then commented out the `if` statement so that I _never_ use `node.text`; and it still gives exactly the same assertion.
failing to read xml
I'm trying to learn nim's `xmlparser` and `xmltree` modules. To do this I'm writing a program that will (eventually) pretty-print XML. But unfortunately, it asserts on every XML file I've tried to run it with. The code and the smallest possible XML file I could make that asserts and the assert itself are as follows: # xml2xml.nim {.experimental: "codeReordering".} import os import strformat import strtabs import strutils import xmlparser import xmltree const INDENT = 4 main() proc main() = let args = commandLineParams() if len(args) == 0 or args[0] in ["/?", "-h", "--help"]: let appname = lastPathPart(getAppFilename()) quit(&"usage: {appname} file.xml [file2.xml ...]") for arg in args: pretty(arg) proc pretty(infilename: string) = let i = infilename.rfind('.') let outfilename = infilename[0 ..< i] & "#.xml" var errors = newSeq[string]() let root = loadXml(infilename, errors) if len(errors) > 0: for error in errors: echo(&"Error: {error}") try: var file = open(outfilename, fmWrite) defer: file.close() file.write(xmlHeader) write(file, root, 0) except IOError as err: echo(&"Failed to write to \"{outfilename}\": {err.msg}") proc write(file: File, node: XmlNode, indent: int) = if indent > 0: file.write(spaces(indent)) file.write(&"<{node.tag}") let attrs = node.attrs() if attrs != nil: for (key, value) in attrs.pairs(): file.write(&" {key}=\"{value}\"") file.write(">") if node.text != "": file.write(node.text) for child in node: write(file, child, indent + INDENT) file.write(&"\n") Run The simpletest XML file I could make (`meta.xml`): Run The runtime assertion error: /home/mark/app/nim/xml2xml/xml2xml.nim(16) xml2xml /home/mark/app/nim/xml2xml/xml2xml.nim(24) main /home/mark/app/nim/xml2xml/xml2xml.nim(38) pretty /home/mark/app/nim/xml2xml/xml2xml.nim(51) write /home/mark/opt/nim/lib/pure/xmltree.nim(176) text /home/mark/opt/nim/lib/system/assertions.nim(27) failedAssertImpl /home/mark/opt/nim/lib/system/assertions.nim(20) raiseAssert /home/mark/opt/nim/lib/system/fatal.nim(39) sysFatal Error: unhandled exception: /home/mark/opt/nim/lib/pure/xmltree.nim(176, 10) `n.k in {xnText, xnComment, xnCData, xnEntity}` [AssertionError] Run The problem could, of course, be with my own code: maybe I don't understand how to use `xmltree` and `XmlNode`'s properly yet.
Re: A path commonPrefix function
Using your `for j in 1 .. paths.high()` is _much_ faster than my `for s in paths[1 .. ^1]`, but for me my `foldl` is much faster than your `maxLen`. (My test data isn't great though, a dozen calls, eleven with common prefixes, repeated 100K times.) Maybe a common prefix algorithm should be in the std. lib., perhaps with one version that is "raw" and another which does prefixes only at a given separator?
Re: A path commonPrefix function
I tried the binary search approach but it was still much slower than my best version on my test data. For reference, here's what I tried: proc commonPrefix*(paths: openArray[string], sep = "/"): string = if len(paths) < 1: return "" let first = paths[0] if len(first) < 2: return first var lo = 0 var hi = foldl(paths.mapIt(len(it)), min(a, b)) - 1 # min len while lo <= hi: let mid = lo + (hi - lo) div 2 var ok = true block loop: for s in paths[1 .. ^1]: for i in lo .. mid: if s[i] != first[i]: ok = false break loop if ok: result.add(first[lo .. mid]) lo = mid + 1 else: hi = mid - 1 Run
Re: A path commonPrefix function
This is the fastest and best so far: proc commonPrefix*(paths: openArray[string], sep = "/"): string = if len(paths) == 0: return "" let first = paths[0] var index = -1 block loop: for i in 0 ..< len(first): for j in 1 .. paths.high(): let path = paths[j] if i < len(path) and first[i] != path[i]: break loop index = i if index == -1: return "" else: return first[0 .. first.rfind(sep, 0, index)] Run
Re: A path commonPrefix function
Thanks for that. I discovered that my new version is 4x faster than the original..
Re: A path commonPrefix function
This version walks forward char by char. Is there a nim equivalent to Python's `timeit` module for timing snippets? proc commonPrefix*(paths: openArray[string], sep = "/"): string = if len(paths) == 0: return "" result = paths[0] var index = 0 var ok = false for path in paths[1 .. ^1]: while index < len(path) and index < len(result) and result[index] == path[index]: inc index ok = true result = if not ok: "" else: result[0 .. result.rfind(sep, 0, index)] Run
A path commonPrefix function
I have the following `commonPrefix()` function (for whole paths) which works fine on Linux (and Windows), but wondering if it could be shorter and/or more efficient? proc commonPrefix*(paths: openArray[string], sep = "/"): string = if len(paths) == 0: return "" result = paths[0] for path in paths[1 .. ^1]: while not path.startsWith(result) and len(result) > 0: result = result[0 .. ^2] result = result[0 .. result.rfind(sep)] Run Tests: test "commonPrefix": check(commonPrefix(["/tmp/test1", "/tmp/data.dat"]) == "/tmp/") check(commonPrefix(["/home/mark/test1", "/tmp/data.dat"]) == "/") check(commonPrefix(["/home/mark/test1", "local/data.dat"]) == "") Run
Re: can use zip library on Linux but not on Windows
That link is helpful, thank you. For anyone else who hits this, I added these two lines after the imports: when defined(windows): {.passl: "-lz".} Run It now compiles & runs & lists zip contents on Windows and Linux. And the executable doesn't seem to depend on any separate shared libs, so is conveniently stand-alone.
can use zip library on Linux but not on Windows
On both Linux and Windows `nimble list -i`'s output includes: `zip [0.2.1]`. On Linux the program listed below compiles & runs & lists a zip file. On Windows I just get error messages (shown after the program). nzip.nim {.experimental: "codeReordering".} import os import strformat import strutils import unicode import zip/zipfiles type Action = enum actCreate, actExtract, actList main() proc main() = let (action, infilename, files) = readCommandLine() # May not return case action of actCreate: echo("TODO create") of actExtract: echo("TODO extract") of actList: listFiles(infilename) proc readCommandLine(): (Action, string, seq[string]) = var action = actList var infilename = "" var files = newSeq[string]() let args = commandLineParams() if len(args) == 0 or args[0] == "-h" or args[0] == "--help": echo(&"usage: {lastPathPart(getAppFilename())} " & "[-c|--create] " & "[-e|-x|--extract] " & "[-l|-t|--list] file.zip \n" & "(Hyphen prefixes are not required.)") quit() for arg in args: case arg of "c", "-c", "--create", "create": action = actCreate of "l", "t", "-l", "-t", "--list", "list": action = actList of "e", "x", "-e", "-x", "--extract", "extract": action = actExtract else: if infilename == "" and arg.toLower().endsWith(".zip"): infilename = arg else: files.add(arg) (action, infilename, files) proc listFiles(infilename: string) = var archive: ZipArchive if open(archive, infilename): defer: archive.close() for name in archive.walkFiles(): echo(name) else: echo(&"failed to open \"{infilename}\"") Run Errors on Windows: Hint: used config file 'C:\bin\nim\config\nim.cfg' [Conf] R:\nim\nzip\nzip.nim(18, 28) Hint: 'files' is declared but not used [XDeclaredButNotUsed] Hint: [Link] C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x2c3): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x33e): undefined reference to `deflateInit2_' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x366): undefined reference to `deflate' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x416): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x426): undefined reference to `deflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x4c1): undefined reference to `deflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x16f4): undefined reference to `zError' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x371f): undefined reference to `zError' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x37c3): undefined reference to `inflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x38a4): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x38de): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x39c5): undefined reference to `zError' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x3fc3): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x406e): undefined reference to `inflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x4250): undefined reference to `inflateInit2_' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x4270): undefined reference to `inflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x431a): undefined reference to `inflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x63c6): undefined reference to `inflate' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x6426): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x6606): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x670d): undefined reference to `inflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x680f): undefined reference to `inflateEnd' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x6956): undefined reference to `inflate' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x69ad): undefined reference to `crc32' C:\Users\mark\nimcache\nzip_r\libzip_all.c.o:libzip_all.c:(.text+0x6b35): undefined reference to `crc32'
File and directory structure for a hybrid project
I have a project that consists of a library (that will be split over several files but will have a single file as its entry point) and an executable that uses the library but which doesn't share its name. At the moment I have this layout: src/myexe.nim src/mypkg/mypkg.nim src/mypkg/support1.nim Run but when I run `nimble test` I get a warning about the structure. So, what should the structure be?
An overview of nimble.packages
I wanted to get an overview of the nimble packages but there isn't a browse function, so I wrote the nim program below. To use it you need to download `packages.json` from [nimble.packages](https://github.com/nim-lang/packages/). {.experimental: "codeReordering".} # TODO download the JSON file if mtime is older than today import algorithm import json import os import sequtils import strformat import strutils except escape import sugar import unicode import xmltree const Outfile = "nimble-packages.html" type Entry = object name: string url: string tags: seq[string] description: string license: string web: string main() proc main() = let filename = getFilename() # May not return let entries = entryItems(filename) writeHtmlTable(entries) proc getFilename(): string = let args = commandLineParams() if len(args) == 0 or args[0] == "-h" or args[0] == "--help": echo("usage: ", lastPathPart(getAppFilename()), " /path/to/nimble.packages.json") quit() args[0] proc entryItems(filename: string): seq[Entry] = for item in parseJson(readFile(filename)): var entry: Entry try: entry = to(item, Entry) except KeyError: for tag in ["name", "url", "description", "license", "web"]: try: let node = item[tag] let text = node.getStr() case tag of "name": entry.name = text of "url": entry.url = text of "description": entry.description = text of "license": entry.license = text of "web": entry.web = text except KeyError: discard # ignore missing for now try: let node = item["tags"] if node.kind == JArray: var tags = newSeq[string]() for element in node.getElems(): tags.add(element.getStr()) entry.tags = tags except KeyError: discard # no tags if entry.name == "": continue entry.tags = sorted(entry.tags.mapIt(it.toLower())) result.add(entry) if entry.url == "": entry.url = entry.web result.sort((a, b) => cmpIgnoreCase(a.name, b.name)) proc writeHtmlTable(entries: seq[Entry]) = var file = open(Outfile, fmWrite) defer: close(file) file.write("\n") file.write("Name/LinkDescriptionTags" & "License\n") for entry in entries: let name = &"{escape(entry.name)}" let description = escape(entry.description) let tags = escape(join(entry.tags, ", ")) let license = escape(entry.license) file.write(&"{name}{description}" & &"{tags}{license}\n") file.write("\n") file.write(&"{len(entries)} packages.\n") Run
Re: How to make a new lib work for nimble.packages?
I normally use mercurial so now have both in that directory. I added a tag and did `git push origin --tags` so hopefully that helped.
How to make a new lib work for nimble.packages?
I created a new package using `nimble init` and once it was ready `nimble publish` and put it on github: [diff](https://github.com/mark-summerfield/diff) but on the [nimble directory](https://nimble.directory/pkg/diff) it is listed as "no version" and "install test failing", and the link to "Hosted docs" leads to an empty page. How do I fix these things?
Re: diff lib
I think we're doing two different kinds of diff. My library takes sequences `a` and `b` and returns a sequence of "spans" (i.e., insert/delete/replace a from to, b from to) that if applied to `a` would transform it into `b`. This is explained in the Python [difflib docs](https://docs.python.org/3/library/difflib.html).
diff lib
I've ported Python's difflib's sequence matcher to pure Nim: [diff](https://github.com/mark-summerfield/diff). It can be used to see the differences between any two sequences of items that support `==` and `hash()` (string, char, or any custom item type with the necessary support).
Re: Is it possible to browse the nimble.directory?
Search is great if you know what you're looking for. But it is useless for getting an overview of what's available. And an overview of the third-party libraries is what I want when starting with a new language.
Re: how to create a generic type with constraints?
Thanks. I think I'll do without concepts for now.
how to create a generic type with constraints?
I'm trying to port Python's difflib's sequence matcher to nim. I want to be able to compare any two sequences of the same types, not just strings. I have this type: type Diff[T] = object a: seq[T] b: seq[T] b2j: Table[T, seq[int]] Run How can I say that type `T` must support `==` and `hash()`?
Re: A pure nim GUI game for Linux & Windows
`shuffle()` is in-place but it did save me one line: var colors = gameColors # gameColors is a const seq[Color] shuffle(colors) colors = colors[0 ..< game.maxColors] Run It is true that NiGui uses Gtk on Linux, but Gtk is pretty well always on desktop/laptop systems even KDE ones, since there're bound to be apps that depend on it. Nim could certainly do with a really good book -- I'd certainly like to read one. (I've dipped into Nim in Action, but I felt it was too close to the docs, the main examples didn't appeal to me, and it isn't Nim 1.0.) As for writing a Nim book: (1) I'd need to have done a lot more Nim programming -- which I'm in the process of doing; (2) I'd need to have at least one core dev willing to read and give feedback on all the examples _and_ on the text -- over a 12-18 month period; (3) I'd need to interest my -- or another -- publisher; (4) I'd need to feel motivated to spend at least a year working on a book that's likely to sell only a few thousand copies and so be a labor of love rather than economically viable. So I'm hoping someone else does it:-)
Re: A pure nim GUI game for Linux & Windows
I can't find outplace (at least not in 1.0.4 or 'latest' on the Nim playground). However, I'll have another go with shuffle which I already use elsewhere. I'm sure there are other Nim libs that support NiGui's missing features -- but don't all of them depend on SDL or OpenGL or other third party libs? As for github, I have an a/c there to contribute, but I don't put my own projects there. My gravitate packages include the full source.
A pure nim GUI game for Linux & Windows
As part of the process of learning Nim, I've ported my game _Gravitate_ (a variation of TileFall or the SameGame), to Nim. I used the [NiGui](https://github.com/trustable-code/NiGui) library, so no third party `.so`'s or `.dll`'s are needed. Although I've tried to make the most of Nim and to be as idiomatic as possible, I'm sure there's room for improvement. So I hope that some Nim experts will review the source and give me feedback -- or just edited `.nim` files -- to help me improve my code. (For example, in the `game.nim` file's `start()` function it takes me 4 lines to choose 4 unique random colors from a sequence of 17; surely it can be done in less code?) There are two archives available from the game's [home page](http://www.qtrac.eu/gravitate.html). The direct downloads (both including 64-bit executables and full source code <1 KLOC) are [Windows](http://www.qtrac.eu/gravitate-1.0.0.zip) and [Linux](http://www.qtrac.eu/gravitate-1.0.0.tar.gz). Things I couldn't do because either I can't figure out how or because NiGui doesn't support them: * Underline keyboard accelerator letters, e.g., the New game button shows "New", but I'd like the 'N' underlined. * Include icons in the buttons and to set the executable's icon all in code (e.g., by reading base64-encoded text from a file at compile time). * Show tool tips. * Do gradient fills. * Control focus, e.g., stop the buttons getting focus so you can "click" a tile with the Spacebar. (The current workaround is to press 'd' for delete tile.) * Enable/disable buttons, e.g., disable the Options dialog's OK button if any option is invalid. Despite the above, given how small and convenient NiGui is, and how it can be used to create stand-alone GUI executables, I think it is a superb library. And I'm also enjoying learning Nim very much!
Re: indentation
I converted my nim files to 2 spaces using nimpretty. However, I found it will only do one file at a time!
indentation
In an earlier post I wrote: _" PS I use 4 spaces for indents because I read years ago in Code Complete that comparative studies had shown that a minimum of 3 is needed for clarity, and I'm used to 4 from Python;-}"_ I rechecked the reference and found that my note above was **incorrect**. According to _Code Complete_ second edition (page 737): * _" Indentation has been shown to be correlated to increased programmer comprehension."_ (and he quotes the study) * _" The study concluded that two-to-four space indentation was optimal."_ So, from now on, for Nim I'll use the Nim standard of two spaces.
Why inherit RootObj?
According to the manual [https://nim-lang.org/docs/system.html#RootObj](https://nim-lang.org/docs/system.html#RootObj) "Objects should inherit from RootObj or one of its descendants." Why is this? The next sentence is: "However, objects that have no ancestor are also allowed." I've been doing this without problems.
Re: What does "cannot be captured as it would violate memory safety" mean?
The variable is sent as a var to a proc where it works fine. But I then in that proc I pass it to another proc and in that one I get the error. I've also tried passing it to the other proc without var (since in that data is only read) but get the same error. Is there an alternative to var that would work?
What does "cannot be captured as it would violate memory safety" mean?
In some situations I get the error message _" cannot be captured as it would violate memory safety"_. I understand that this means nim is trying to stop me shooting myself in the foot, but is there anywhere I can read an explanation and if it is possible to do what I want without triggering this error?
Re: Recommended GUI library?
OK, thanks. Docs ought to mention that.
Re: Recommended GUI library?
QML depends on Qt which is big (like wx) compared to, say NiGui. Also Qt's mutli-license is a problem for some people.
Re: Recommended GUI library?
I tried your hello example on Linux and it works fine. But on Windows the same code gives this error: `could not load: SDL2.dll`. My nim bin folder (containing the SDL*.dlls) in on my PATH. I then copied SDL2*.dll from nim's bin folder to the same folder as the hello.nim but it still gave the same error.
NiGui examples?
Has anyone built any NiGui apps that are bigger & more realistic than the examples? If so and they're FOSS, could you provide some links so I can study them? All the examples use global vars to maintain state across controls. But this doesn't scale well or work well with large apps. * how do you subclass correctly -- or if this goes against the grain for NiGui, what is the correct approach to use instead? * how do you communicate between controls or maintain state without globals?
Re: Recommended GUI library?
I'm starting to experiment with NiGui. I'm trying to create "widgets" that maintain some state and that can communicate events between the child widgets they contain. I also want to modularise the code into separate functions and objects. Here's my first hack on your example 10 (see also a question in the code & notes after the code): {.experimental: "codeReordering".} import nigui type MainWindow = object window: Window statusLabel: Label CustomControl = object control: Control proc main(): void = app.init() var mainWindow = newMainWindow("Test #2") mainWindow.statusLabel.text = "Click..." mainWindow.window.show() app.run() proc newMainWindow(title: string): MainWindow = result.window = newWindow(title) result.window.width = 500 result.window.height = 500 var vbox = newLayoutContainer(LayoutVertical) result.window.add(vbox) result.statusLabel = newLabel() vbox.add(result.statusLabel) # pass in the label so that the new control can "talk: to it: is there a better way? var control = newCustomControl(result.statusLabel) control.control.width = 400 control.control.height = 400 vbox.add(control.control) control.control.widthMode = WidthMode_Fill control.control.heightMode = HeightMode_Fill proc newCustomControl(label: Label): CustomControl = result.control = newControl() result.control.onDraw = proc (event: DrawEvent) = let canvas = event.control.canvas canvas.areaColor = rgb(30, 30, 30) # dark grey canvas.fill() canvas.setPixel(0, 0, rgb(255, 0, 0)) canvas.areaColor = rgb(255, 0, 0) # red canvas.drawRectArea(10, 10, 30, 30) canvas.lineColor = rgb(255, 0, 0) # red canvas.drawLine(60, 10, 110, 40) let text = "Hello World!" canvas.textColor = rgb(0, 255, 0) # lime canvas.fontSize = 20 canvas.fontFamily = "Arial" canvas.drawText(text, 10, 70) canvas.drawRectOutline(10, 70, canvas.getTextWidth(text), canvas.getTextLineHeight()) result.control.onMouseButtonDown = proc (event: MouseEvent) = label.text = $event.button & " (" & $event.x & ", " & $event.y & ")" # Shows where the mouse is clicked in control-relative coordinates main() Run You'll notice that I had to drop the images since I couldn't get them to work (even though they work fine in your original example). Oh, and this runs fine on Windows & Linux:-) PS I use 4 spaces for indents because I read years ago in _Code Complete_ that comparative studies had shown that a minimum of 3 is needed for clarity, and I'm used to 4 from Python;-}
Re: Recommended GUI library?
I didn't even know there was a wxWidgets port. When I searched the nimble package site for "gui" it didn't find it (maybe it isn't there) and nor is it mentioned in the Curated Packages. Probably good if you put it in one or both those places so people could find it:-) Also might help if you list the .so's, .dylib's and .DLLs that need to be distributed with an nim executable. Anyway, I'll give it a try!
Re: Recommended GUI library?
I've now tried the "hello world" program for all those that claim to be cross-platform (at least Linux & Windows). Most don't actually work on Windows, and all but one requires at least one `.so` or `.dll`. The one exception is [NiGui](https://github.com/trustable-code/NiGui). This is pure Nim so doesn't need any extra shared libraries. Also, I found it worked fine on both Linux and Windows. I haven't tested it for performance or for comprehensiveness, and the documentation is rather sparse. However, it comes with a whole bunch of examples which are small enough to study and learn from. I really hope that _NiGUI_ gets the support it needs. For example, after decades, Python still has no native GUI library (although there have been many attempts, e.g., _PyGUI_ ). This makes it much harder to deploy Python GUI apps. Yet with _NiGUI_ deployment is easy since it is built right into the executable with no separate libraries.
Recommended GUI library?
Is there a recommended GUI library for nim? I notice that with a Windows install one of the DLLs is libui.dll, but there're also SDL2 DLLs. I'm looking for a GUI library that I can use to build apps on Linux and Windows (don't need macOS).
Nim 1.1+ roadmap?
Did a Nim 1.1+ roadmap get published? I can't see one in the blog and don't know where else to look. Is the experimental _codeReordering_ likely to be adopted; I've just started to use it and find it very useful.
Re: Manual query "deviated" ?
OK, I've done two patches (since two files needed to be changed --- I'm not much of a github user). [https://github.com/nim-lang/Nim/pull/12845](https://github.com/nim-lang/Nim/pull/12845) [https://github.com/nim-lang/Nim/pull/12846](https://github.com/nim-lang/Nim/pull/12846) If I see other typos or problems with English I'll try to do PRs for them in future.
Manual suggestion re exceptions
In the manual it doesn't say that you can create your own custom exceptions. Personally, I prefer to create my own so that I am clear whether it is from nim's code or mine. Someone has shown how to create custom exceptions: [https://forum.nim-lang.org/t/2863#17814](https://forum.nim-lang.org/t/2863#17814) I think something like this ought to be in the Exceptions section of the manual.
Re: Manual query "deviated" ?
"derived" kind of means or imlies "inherited", so if you don't like "determined by", I'd suggest one of these: * " ok, based on the first parameter" * " ok, based on the type of the first parameter" * " ok, based on the first parameter's type" Plus, of course, similar changes to the text in the preceding para.
Manual query "deviated" ?
In the manual there's this example: proc forward[T](x: var T): var T = result = x # ok, deviated from the first parameter. Run The word _deviated_ is also used in the text above. But these uses all seem wrong to me. I _think_ the above comment ought to be `# ok, determined from ...` or `# ok, determined by ...`, and similarly in the text?
Re: Is it possible to browse the nimble.directory?
Thanks for your helpful replies: and to the others who've replied to my other questions.
Is it possible to browse the nimble.directory?
The [https://nimble.directory](https://nimble.directory)/ has a good search function, but in reaquainting myself with nim I'd like to be able to see categories and browse. Is this possible?
What are the compiler defaults? etc...
* In [https://nim-lang.org/docs/nimc.html](https://nim-lang.org/docs/nimc.html) it shows all the compiler options, but it doesn't seem to show the defaults. How can I find out what they are? * Is there a pragma that would force names to be fixed? For example, if I do _import mod_ and get **afunc** in my namespace, what I also get in effect is **aFUNC** , **aFunc** , etc., whereas I'd prefer just one. (I realise this is unlikely to be available or even possible.) * Is there any _runtime_ cost in doing _import mod_ compared with _from mod import foo, bar_? Is _import mod_ recommended rather than _from mod import ..._? * On Windows I used the prebuilt .zip but on Linux I built it myself. I think it might be worth adding to the instructions to run _. /koch nimble_ since _. /koch tools_ doesn't seem to build nimble. * Incidentally I tried nim a couple of years ago and gave up mainly because I couldn't get it to reliably install on Windows. Now I've installed on Linux and Windows and _finish.exe_ works fine. It gave an error when it came to fetch mingw but instead of giving up it offered to get it from nim's site and when I said yes it "just worked". What I'm looking for is a language as convenient and fast to develop with as Python but with static typing, easy deployment (single executable), and C-speed runtime. Which is why I'm trying nim again.
Which is the preferred style: call(x) or call x
I've found that when I have a call with a single argument, say, myfunc(x), I can change it to myfunc x. This surprised me since coming from Python I'd have thought myfunc is a reference to the function, but clearly that's not the case with nim. (So, how do you get a function reference?) But out of the two call syntaxes, which is to be preferred?