Lua 5.4.8 is here!

So it was, once again, time to build the NuGet package. To my surprise, building with Clang as tool chain unexpectedly failed:

C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\lib\clang\19\include\stdarg.h(22): warning RC4067: unexpected characters following '#if/#elif' directive; newline expected [D:\a\nuget-lua\nuget-lua\compiler\compiler.vcxproj] 
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\lib\clang\19\include\stdarg.h(22): warning RC4067: unexpected characters following '#if/#elif' directive; newline expected [D:\a\nuget-lua\nuget-lua\compiler\compiler.vcxproj] 
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\lib\clang\19\include\stddef.h(22): warning RC4067: unexpected characters following '#if/#elif' directive; newline expected [D:\a\nuget-lua\nuget-lua\compiler\compiler.vcxproj] 
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\lib\clang\19\include\stddef.h(22): warning RC4067: unexpected characters following '#if/#elif' directive; newline expected [D:\a\nuget-lua\nuget-lua\compiler\compiler.vcxproj] 
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\lib\clang\19\include\stddef.h(51): warning RC4067: unexpected characters following '#if/#elif' directive; newline expected [D:\a\nuget-lua\nuget-lua\compiler\compiler.vcxproj] 
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\lib\clang\19\include\stddef.h(51): warning RC4067: unexpected characters following '#if/#elif' directive; newline expected [D:\a\nuget-lua\nuget-lua\compiler\compiler.vcxproj] 

I searched online for the compiler errors and if there were recent changes to Clang or the visual studio integration or something. But I found nothing. I tried to build the previous version of Lua in my GitHub action, and that one failed as well.

And after some minutes, I finally noticed the important bit! Those are NOT c/cpp compiler errors! Those are RESOURCE COMPILER errors!

I build all binaries, i.e. the Lua compiler, the Lua interpreter, and the Lua dll version, with version information resourced built in. And the resource script for that includes the lua.h c-header to use the version information defined in that file. As it is a normal c-header as well, it, of course, includes further files, among them the stdarg.h and stddef.h triggering the bugs above.

I suspect there was some optimization introduced to those system headers and the Cpp compiler, which is not reflected in the resource compiler. And I don’t blame anyone for that, as the resource compiler is something exotic anyway, and one cannot really expect it to be fully compatible with cpp.

The versioninfo resource script for those projects is generated anyway. So, I fixed this problem by no longer including lua.h in the version info header, but by duplicating all required defines. Just in case you (or my forgetful future self 😉) run into similar issues in other projects as well.

And with this, also the new NuGet package of Lua is now available.

I came across that Nuget because I was writing WPF UI applications and I needed a folder picker. Someone in the internet suggests to use the WinForms dialogs. I sort of hate using two frameworks. And then another one brought up the Nuget WindowsAPICodePack.Shell with it’s class representation of the Windows Common Dialogs, including the capability of picking folders in the open dialog window.

So, I started using that. Then, at some point, a friend pointed out to me, that the Nuget package I was using did not look like an official Microsoft package, but a repackage someone did. That made me stop and think. I don’t assume any bad intent, but I found it very very strange. The official package vanished. And there is a huge load of packages which strange names:

I don’t like this. Even if there is no ill intent from any of the authors, I still don’t like this, as it reeks like fraught, phishing, and vulnerabilities. Sorry, but, no.

So, where is the official package? Seems to have disappeared, that’s why there are the repackages by community members. Why did it disappear? No idea. Maybe it got caught in a semi-automatic cleanup as it was orphaned. Someone suggestion it’s replaced by Microsoft.Windows.SDK.Contracts.

In the end, I replaced the code in my projects by either using the WinForms dialog, or by writing a very small p/invoke wrapper class calling the Win32 API directly. If you are interested, have a look:

https://github.com/sgrottel/open-here/commit/9de68198e35f0f6dec9386372cc71bada54c2f5b

The moral of the story is, a Nuget package is only as good as the people maintaining it. And, I mean people, not organizations. Because in the end, it’s whether or not individuals want to give their best.

Git has this cursed function to fuck up your files by doing unspeakable things to your line endings.

For example, from Githubs Documentation on Line Endings:

On Windows, you simply pass true to the configuration. For example:

$ git config –global core.autocrlf true

Please, never never never never never never never never never never never never do this!

THERE IS NO REASON TO DO IT!

Git is here to keep track of our files, NOT TO CHANGE OUR FILES IN ANY WAY.

So, please, just, never never never never never never never never never never never never do this! Leave my file endings alone!

Today I release a new version of my Checkouts Overview tool.

Version 1.1 is a feature release, improving the scanning of your hard disks searching for repository checkouts, and adding the ability to perform a git fetch while updating the entry status.

Some minor improvements to the UI also provide a more consistent look and feel.

Grab the release from Github: Release Feature Release v1.1 – Better Disk Scanning and Git Fetch · sgrottel/checkouts-overview (github.com)

Today I present you the Checkouts Overview tool.

https://github.com/sgrottel/checkouts-overview
https://go.grottel.net/checkouts-overview

What? Why? Because this little tool helps me.

In my private setup, I have a lot of smaller repos checked out, and work on them only occasionally. In addition, I got several repos to collect the history of some text documents. Some of those repos are synced against servers which are only occasionally online, partially for power saving or partially due to VPN and network connectivity stuff. As a result, I often keep losing track of the sync states of all the different repos.

Is everything checked in? — most times, yes. If the change was complete.

Is everything pushed? — maybe.

Am I on branches? — no idea.

You might not need this app, if you have a better structured work process with your stuff than I do. I don’t, so I need help by a tool, by this tool.

If you are interested, you find more info in the app’s github repository.

Note: and as for the app’s icon, it’s about (repository) clones, right.

Yes, I am still using AntTweakBar. As you might know, the development of AntTweakBar is discontinued. At some point in the future, I will switch. Currently, I consider imgui the best successor. But I haven’t had time to look into imgui. So, when I resurrected an old small tool of mine, it still used ATB, and I did not want to recode all of this. But out of “because-I-can,” I decided  to update all dependencies to their newest versions. As a result the ATB integration with GLFW 3 did not work any longer. A couple of callback functions where changed between GLFW 2 and GLFW 3. I ended up rewriting my glue code between those two libraries.

Here it is, if any of you ever come across the same issue. First the callbacks:

static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
#ifdef HAS_ANTTWEAK_BAR
  if (action == GLFW_PRESS || action == GLFW_REPEAT)
  {
    int twMod = 0;
    bool ctrl;
    if (mods & GLFW_MOD_SHIFT) twMod |= TW_KMOD_SHIFT;
    if (ctrl = (mods & GLFW_MOD_CONTROL)) twMod |= TW_KMOD_CTRL;
    if (mods & GLFW_MOD_ALT) twMod |= TW_KMOD_ALT;

    int twKey = 0;
    switch (key)
    {
    case GLFW_KEY_BACKSPACE: twKey = TW_KEY_BACKSPACE; break;
    case GLFW_KEY_TAB: twKey = TW_KEY_TAB; break;
    //case GLFW_KEY_???: twKey = TW_KEY_CLEAR; break;
    case GLFW_KEY_ENTER: twKey = TW_KEY_RETURN; break;
    case GLFW_KEY_PAUSE: twKey = TW_KEY_PAUSE; break;
    case GLFW_KEY_ESCAPE: twKey = TW_KEY_ESCAPE; break;
    case GLFW_KEY_SPACE: twKey = TW_KEY_SPACE; break;
    case GLFW_KEY_DELETE: twKey = TW_KEY_DELETE; break;
    case GLFW_KEY_UP: twKey = TW_KEY_UP; break;
    case GLFW_KEY_DOWN: twKey = TW_KEY_DOWN; break;
    case GLFW_KEY_RIGHT: twKey = TW_KEY_RIGHT; break;
    case GLFW_KEY_LEFT: twKey = TW_KEY_LEFT; break;
    case GLFW_KEY_INSERT: twKey = TW_KEY_INSERT; break;
    case GLFW_KEY_HOME: twKey = TW_KEY_HOME; break;
    case GLFW_KEY_END: twKey = TW_KEY_END; break;
    case GLFW_KEY_PAGE_UP: twKey = TW_KEY_PAGE_UP; break;
    case GLFW_KEY_PAGE_DOWN: twKey = TW_KEY_PAGE_DOWN; break;
    case GLFW_KEY_F1: twKey = TW_KEY_F1; break;
    case GLFW_KEY_F2: twKey = TW_KEY_F2; break;
    case GLFW_KEY_F3: twKey = TW_KEY_F3; break;
    case GLFW_KEY_F4: twKey = TW_KEY_F4; break;
    case GLFW_KEY_F5: twKey = TW_KEY_F5; break;
    case GLFW_KEY_F6: twKey = TW_KEY_F6; break;
    case GLFW_KEY_F7: twKey = TW_KEY_F7; break;
    case GLFW_KEY_F8: twKey = TW_KEY_F8; break;
    case GLFW_KEY_F9: twKey = TW_KEY_F9; break;
    case GLFW_KEY_F10: twKey = TW_KEY_F10; break;
    case GLFW_KEY_F11: twKey = TW_KEY_F11; break;
    case GLFW_KEY_F12: twKey = TW_KEY_F12; break;
    case GLFW_KEY_F13: twKey = TW_KEY_F13; break;
    case GLFW_KEY_F14: twKey = TW_KEY_F14; break;
    case GLFW_KEY_F15: twKey = TW_KEY_F15; break;
    }
    if (twKey == 0 && ctrl && key < 128)
    {
      twKey = key;
    }
    if (twKey != 0)
    {
      if (::TwKeyPressed(twKey, twMod)) return;
    }
  }
#endif
}

static void charCallback(GLFWwindow* window, unsigned int key)
{
#ifdef HAS_ANTTWEAK_BAR
  if (::TwKeyPressed(key, 0)) return;
#endif
}

static void mousebuttonCallback(GLFWwindow* window, int button, int action, int mods)
{
#ifdef HAS_ANTTWEAK_BAR
  if (::TwEventMouseButtonGLFW(button, action)) return;
#endif
}

static void mousePosCallback(GLFWwindow* window, double xpos, double ypos)
{
#ifdef HAS_ANTTWEAK_BAR
  if (::TwEventMousePosGLFW((int)xpos, (int)ypos)) return;
#endif
}

static void mouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
#ifdef HAS_ANTTWEAK_BAR
  static double pos = 0;
  pos += yoffset;
  if (::TwEventMouseWheelGLFW((int)pos)) return;
#endif
}

static void resizeCallback(GLFWwindow* window, int width, int height)
{
#ifdef HAS_ANTTWEAK_BAR
  ::TwWindowSize(width, height);
#endif
}

Of course, you can omit the #ifdefs if you don’t care. Add your own codes to the functions after ATB has been handled.

Then, it’s just your typical initialization of GLFW callbacks:

::glfwSetKeyCallback(window, keyCallback);
::glfwSetCharCallback(window, charCallback);
::glfwSetMouseButtonCallback(window, mousebuttonCallback);
::glfwSetCursorPosCallback(window, mousePosCallback);
::glfwSetScrollCallback(window, mouseScrollCallback);
::glfwSetWindowSizeCallback(window, resizeCallback);