Lua 5.4.8 ist hier!

Und so war es also wieder einmal an der Zeit, das NuGet-Paket zu bauen. Zu meiner Überraschung schlug die Erstellung mit Clang als Werkzeugkette unerwartet fehl:

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] 

Ich suchte online nach den Compilerfehlern und ob es kürzlich Änderungen an Clang oder der Visual Studio Integration oder so etwas gab. Aber ich fand nichts. Ich habe versucht, die vorherige Version von Lua in meiner GitHub-Aktion zu bauen, und das ist auch fehlgeschlagen.

Und nach einigen Minuten habe ich endlich den wichtigen Teil bemerkt! Das sind KEINE c/cpp-Compiler-Fehler! Das sind RESOURCE COMPILER-Fehler!

Ich baue alle Binärdateien, d.h. den Lua-Compiler, den Lua-Interpreter und die Lua-DLL-Version, mit eingebauten Versionsinformationen. Und das Ressourcenskript dafür enthält den c-Header lua.h, um die in dieser Datei definierten Versionsinformationen zu verwenden. Da es sich auch um einen normalen c-Header handelt, enthält er natürlich weitere Dateien, darunter die stdarg.h und stddef.h, die die obigen Fehler auslösen.

Ich vermute, dass in diesen Systemheadern und im Cpp-Compiler einige Optimierungen vorgenommen wurden, die sich im Resource-Compiler nicht widerspiegeln. Und ich mache niemandem einen Vorwurf daraus, da der Ressource-Compiler ohnehin etwas Exotisches ist und man nicht wirklich erwarten kann, dass er vollständig mit Cpp kompatibel ist.

Das Skript für die Versionsinfo-Ressourcen wird für diese Projekte trotzdem generiert. Ich habe dieses Problem also behoben, indem ich lua.h nicht mehr in den Versionsinfo-Header aufgenommen habe, sondern alle benötigten Defines dupliziert habe. Nur für den Fall, dass Sie (oder mein vergessliches zukünftiges Ich 😉) auch bei anderen Projekten auf ähnliche Probleme stoßen.

Und so gibt es nun auch das neue NuGet-Paket von Lua.

Ich bin auf dieses Nuget gestoßen, weil ich WPF-UI-Anwendungen geschrieben habe und einen Folder-Picker brauchte. Irgendwer im Internet schlug vor, die WinForms-Dialoge zu verwenden. Ich hasse es irgendwie, zwei Frameworks zu verwenden. Und dann brachte jemand anderes das Nuget WindowsAPICodePack.Shell ins Spiel, mit seinen Klassen der Windows Common Dialogs, einschließlich der Möglichkeit zur Auswahl von Ordnern im File-Öffnen-Dialogfenster.

Also fing ich an, das Nuget zu benutzen. Irgendwann wies mich ein Freund darauf hin, dass das Nuget-Paket gar nicht wie ein offizielles Microsoft-Paket aussah, sondern wie ein Repackage, das irgendjemand gemacht hatte. Das brachte mich zum Nachdenken. Ich unterstelle niemandem böse Absichten, aber ich fand es sehr, sehr seltsam. Das offizielle Paket war . Und es gibt eine ganze Reihe von Paketen mit seltsamen Namen:

Ich mag das nicht. Selbst wenn keiner der Autoren böse Absichten hegt, gefällt mir das nicht, denn es riecht nach Betrug, Phishing und Schwachstellen. Tut mir leid, aber nein.

Also, wo ist das offizielle Paket? Es scheint verschwunden zu sein, deshalb gibt es die Repackages von Community-Mitgliedern. Warum ist es verschwunden? Keine Ahnung. Vielleicht wurde es bei einer halbautomatischen Bereinigung erwischt, da es verwaist war. Jemand behauptet es wäre Microsoft.Windows.SDK.Contracts ersetzt worden.

Letztendlich habe ich den Code in meinen Projekten ersetzt, indem ich entweder doch den WinForms-Dialog verwendet oder eine sehr kleine P/Invoke-Wrapper-Klasse geschrieben habe, die die Win32-API-Funktion direkt aufruft. Wen es interessiert, der kann sie sich gerne anschauen:

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

Die Moral von der Geschichte ist, dass ein Nuget-Paket nur so gut ist wie die Menschen, die es pflegen. Und ich meine Menschen, nicht Organisationen. Denn am Ende kommt es darauf an, ob eine einzelne Person dahinter steht und ihr Bestes geben will oder nicht.

Dieser Artikel is nur auf Englisch verfügbar.

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!

Heute habe ich eine neue Version meines Checkouts-Overview-Tools veröffentlicht.

Version 1.1 bringt neue Funktionen, Verbesserung des Scannens der Festplatten zum Finden neuer Repository-Checkouts und die Möglichkeit beim Update von Entry-Status-Informationen auch ein git fetch durchzuführen.

Ein paar kleinere Verbesserungen der Benutzeroberfläche erzeugen ein konsistenteres Aussehen.

Ladet den neue Release von Github herunter: Release Feature Release v1.1 – Better Disk Scanning and Git Fetch · sgrottel/checkouts-overview (github.com)

Heute stelle ich euch das Tool Checkouts Overview vor.

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

Was? Warum? Weil mir dieses kleine Tool hilft.

In meinem privaten Setup habe ich eine Menge kleinerer Repos ausgecheckt, mit denen ich nur hin und wieder arbeite. Außerdem habe ich mehrere Repos, die einige Textdokumente und deren Historie verwalten. Manche dieser Repos werden mit Servern synchronisiert, die nur gelegentlich online sind, teils um Strom zu sparen, teils aufgrund von VPN- und Netzwerkverbindungsgeschichten. Und so verliere ich oft den Überblick über den Status der Synchronisierung dieser verschiedenen Repos.

Ist alles eingecheckt? — Meistens, ja. Wenn meine Änderungen schon vollständig war.

Ist alles gepusht? — vielleicht.

Sind Branches aktiv? — keine Ahnung.

Ihr braucht diese Anwendung vielleicht nicht, wenn Ihr einen besser strukturierten Arbeitsablauf habt als ich. Meiner ist chaotisch, also brauche ich die Hilfe eines Tools, dieses Tools.

Wenn Ihr interessiert seid, findet Ihr weitere Informationen im Github-Repository der App.

Hinweis: Und was das Icon der App angeht, es geht um (Repository-)Klone, richtig.

Dieser Artikel is nur auf Englisch verfügbar.

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);