Jump to content

gebeer

Members
  • Posts

    1,444
  • Joined

  • Last visited

  • Days Won

    41

Posts posted by gebeer

  1. 9 minutes ago, Ivan Gretsky said:

    The problems are often with drivers. Not all hardware is compatible. At least out of the box.

    Nvidia GPU in particular often causes problems. But their drivers have become much better. @kongondo since you chose Ubuntu, you might want to consider giving https://pop.system76.com/ a try. Their releases are quite stable and GPU support is great. Some of the high profile coders on YT use it. I tried it years ago and even back then it was a pleasant experience.

     

    • Like 2
  2. 45 minutes ago, kongondo said:

    So I decided to take the plunge. Laptop was having issues (Windows 11) and decided to try Ubuntu + Omakub! I had been trying this out for a few days. Had decided to run CapCut in a VM whenever I needed it. Omakub is amazing! Only annoying thing was my CAPSLOCK being bound to emojis! I changed this. Yesterday, I was preparing to post here to thank you guys for 're-introducing' me to Linux for the umpteenth time.. I was going to tell you I was even considering Ubuntu + Omakub for my main PC. I was going to tell you that, thanks to @bernhard, I have found DDEV (more on that later in this thread). Amazing! Meanwhile, a system update was running in the background. It was done before I could start my post. It asked to restart the machine. I wasn't expecting this; on Windows, yes, this was common place. I thought Linux doesn't need this? Anyway, I obliged and boom! It was all white after that! Crash! I mean, what??!!! 

    I AM THE SYS ADMIN!!! Suffice is to say I went to bed not happy!

    Googled a bit this morning, tried a few things, nothing worked! I always end up on this white screen! At least I learnt  Ctrl+Alt+F3!

    I don't think the error has anything to do with Omakub. It is crashing at some 'color.d' something from what I can see. Might be related to video/graphics.

    Help, anyone?

    If I cannot resolve, I'll try a fresh install. Otherwise, looks like back to Windows 11 we go. At least 'it works - mostly'.

    Thanks.

     

    Ubuntu 24.04.1 LTS

    Sad to hear about your bad experience with upgrading. Not that I don't want to help. But for these kinds of scenarios I found Claude or ChatGPT very helpful in many cases. Everyone's setup is different. You can go and debug with the help of AI, describing your specific scenario. Since you have a tty (Ctrl+Alt+F3) you can log on and use journalctl and dmesg to find the cause of the problem. The AI will tell you the right commands to find the errors (hopefully).

    I wish you success!

    • Like 1
  3. Introduction

    Automated PDF production is a quite common task for ProcessWire developers. PW does not offer core tools for that. There are some external modules that we can utilize. In this showcase I would like to share my considerations for the tool of choice and my experiences working with it.

    The task at hand

    PDF production for product pages on an existing ProcessWire installation

    acniti.com is a Japan based company that specializes in nanotechnology solutions for gases in water. They have developed technologies to create nanobubbles in water, which can change the properties of water and improve dissolved gas levels through super saturation. Their founder and CEO has chosen ProcessWire for his website and has developed the site himself. He tasked me to add functionality for creation of downloadable PDFs from available product data.
    The client was forwarded to me from Bernhard because of time constraints on his side. I really appreciate that.

    The core requirements in detail:

    • Produce separate PDF files for multiple languages, including LTR languages
    • Design a template: cover page, images page, content pages, specs pages
    • Cache PDFs
    • Minimal impact on existing template code

    Tool choice: RockPdf module

    I had done some PDF generation before, using mPDF library directly. While there are other options available for ProcessWire (Pages2PDF, MakePDF) I decided to use Bernhard's RockPdf module since it seems the most feature rich and well maintained one. It is also based on the quite popular mPDF library.

    Reasons for choosing RockPdf

    Auto-reloading of PDFs in concert with RockFrontend

    This can save a lot of time (and strain on the F5 key), since the PDF is automatically reloaded every time a code change is made. All it requires to achieve that is one line of code:

    $pdf->save(__DIR__ . "/tmp/{$filename}.pdf", preview: true);

    Easy font loading

    I needed to load different fonts depending on the content language. Here is, how I did that

    Spoiler
    // include fonts based on language
    
    // Latin
    
    if (in_array($lang, self::LATINLANGS)) {
    
    $pdf->addFont([
    
        'R' => dirname(__FILE__) . '/assets/fonts/Inter-Regular.ttf',
    
        'B' => dirname(__FILE__) . '/assets/fonts/Inter-Bold.ttf',
    
    ], 'inter', true);
    
    $pdf->addFont([
    
        'R' => dirname(__FILE__) . '/assets/fonts/itc-bauhaus-demi-1361514174.ttf',
    
        'B' => dirname(__FILE__) . '/assets/fonts/itc-bauhaus-demi-1361514174.ttf',
    
    ], 'itcbauhaus');
    
    }
    
    // Arabic
    
    if ($lang == 'arabic') {
    
    $pdf->addFont([
    
        'R' => dirname(__FILE__) . '/assets/fonts/UthmanicHafs_V22.ttf',
    
        'B' => dirname(__FILE__) . '/assets/fonts/UthmanicHafs_V22.ttf',
    
    ], 'inter', true);
    
    }
    
    // Farsi (Persian)
    
    if ($lang == 'farsi') {
    
    $pdf->addFont([
    
        'R' => dirname(__FILE__) . '/assets/fonts/B-NAZANIN.TTF',
    
        'B' => dirname(__FILE__) . '/assets/fonts/B-NAZANIN.TTF',
    
    ], 'inter', true);
    
    }
    
    // Japanese
    
    if ($lang == 'japanese') {
    
    $pdf->addFont([
    
        'R' => dirname(__FILE__) . '/assets/fonts/noto-sans-jp-v52-latin-regular.ttf',
    
        'B' => dirname(__FILE__) . '/assets/fonts/noto-sans-jp-v52-latin-700.ttf',
    
    ], 'inter', true);
    
    }
    
    
    // add Meiryo to all languages for character substitution of 〒 glyph (used for  postal code)
    
    $pdf->addFont([
    
        'R' => dirname(__FILE__) . '/assets/fonts/Meiryo.ttf',
    
        'B' => dirname(__FILE__) . '/assets/fonts/Meiryo.ttf',
    
    ], 'meiryo');

    RockPdf CSS utility classes

    They really came in handy, since they are specifically targeted at mPDF, using pt units. I could easily set some base colors with

    $pdf->setLessVars([
    
        'col-muted' => '#dddddd',
    
        'col-primary' => '#0b54a2',
    
    ]);

    The utility classes that I mostly used are those for widths, margins and paddings. They are quite handy for setting up the layout of the PDF.

    Easy file saving to PW field

    For caching the created PDFs I utilized a RockPdf convenience method to save the files to a field on the product page

    $pagefile = $pdf->saveToField(
    
        page: $page,
    
        field: self::PDF_FIELD,
    
        filename: $filename,
    
        append: true,
    
    );

    Implementation

    Modular approach for minimal impact on existing code

    I created two modules:

    Main module ProductPdf: non-autoload, holds all logic/templates for generating PDFs and required markup (download button)

    Module ProductPdfHooks: autoload, hooks:

    • Page(template=product)::render displays PDF for download
    • Pages::saved(template=product|product-type) creates PDFs in all languages and saves them to field for caching

       

    Re-usage of existing template logic

    There was quite a lot of logic (some of it rather complex) already available in the project that I wanted to utilize. Mainly for specs table creation. I had to do some minimal refactoring of original code. Then I was able to include that logic into my module without having to duplicate it. Benefits of this approach:

    • Minimal impact on existing code
    • Easier to maintain

    Challenges

    Limitations of mPDF library

    mPDF is not good at modern CSS features. It is quite limited in terms of CSS support. I had to do some workarounds to make it work with the layout I needed.

    Different approach to styling

    Although RockPdf's utility classes helped a lot, I still had to do some inline styling.

    Display of complex tables

    Display of tables in particular was a pain point since mPDF does a lot of automatic adjustments to column widths and distribution that I needed to disable in order to get the desired results:

    // Ensures that tables retain their original proportions
    $mpdf->keep_table_proportions = true;
    // And adding autosize="1" attribute to tables.

    Page headers, footers, margins and page breaks

    The RockPdf module docs have some great examples for setting up headers and footers, margins and page breaks. I used those to set up the layout of the PDF without having to read too much into the mPDF docs.

    Minimal impact on exisiting code base

    This was overcome by the modular approach I described earlier and it worked out really nice. The only addition to the original product template file for rendering the download button, was calling a static method from my module:

    <?= ProductPdf::renderDownloadbutton($page) ?>

    That button requests the page URL with a query parameter. The display of the PDF for download is handled through a Page::render hook

    Spoiler
    /**
    
    * Handles the post-render actions for product pages, specifically checking for a 'download' request
    
    * for the product's PDF. If such a request is detected, it attempts to retrieve the PDF file associated
    
    * with the current product page. If the file exists, it sends the file to the client without forcing a download.
    
    *
    
    * @param HookEvent $event The event object, from which the current page object is extracted.
    
    * @return void
    
    */
    
    public function afterRenderProduct(HookEvent $event)
    
    {
    
        $page = $event->object;
    
        if ($this->wire->input->get('ppdf', 'text') == 'download') {
    
    
    
        // full disk path to PDF
    
        $file = ProductPdf::getPDFFile($page);
    
    
    
        if (!is_file((string)$file)) return;
    
            $filename = basename($file);
    
            // show PDF in browser for manual download
    
            header('Content-Type: application/pdf');
    
            header('Content-Disposition: inline; filename="' . urlencode($filename) . '"');
    
            header('Expires: 0');
    
            header('Cache-Control: must-revalidate');
    
            header('Pragma: public');
    
            header('Content-Length: ' . filesize($file));
    
            readfile($file);
    
            exit;
        }
    
    }

    PHP DOM manipulation of existing markup necessary

    Since I reused existing logic for constructing specs tables, I needed to add some inline styles and change some URLs on the fly. I used native PHP DOMDocument for that.

    There is a feature in the RockFrontend module that offers DOM manipulation tools with a nice API. I would have loved to use those but at the the time of working on this project, I just was not aware of their existence.

    The result

    Product pages on acniti.com now have a download button that allows the user to download the PDF of the product page in their language.

    See it live here

    acniti-pdf-download-button.thumb.png.871479dbfcbba0f2baef5d023ec23428.png

    The PDF is loaded from the cache field on the page, which is updated every time a product is edited and saved. If no cache file exists, the PDF is created on-the-fly and cached for future use. It is presented to the user in a new browser tab for viewing and downloading.

    The PDFs feature a clean layout / design which corresponds to the acniti branding.

    Cover page: 
    acniti-minigalf-ultrafine_en_cover.thumb.jpg.fa730657d63ad7f354a6d6d57a537e5e.jpg

    Content pages:
    acniti-minigalf-ultrafine_en_content1.thumb.jpg.174ac5acdda866f71f2ecacf998a9a52.jpg
    acniti-minigalf-ultrafine_en_content2.thumb.jpg.514ecf76a4e8eac78b68512db37d53de.jpg

    Specs table:
    acniti-minigalf-ultrafine_en_specs.thumb.jpg.2e5b5c213b9268adc5e53ae7468190ed.jpg

    Feedback from the client

    The client has a lot of experience with ProcessWire which one can see from looking at their website at acniti.com. He gave me great feedback on the project:

    Quote

    My initial tought was to convert Processwire pages to adoc and produce pdf's that way but I didn't get my head around it. The power of asciiDoctor is it produces great manuals using strict rules and formatting. It lacks the flexibility like a Photoshop application. So i checked RockPDF got in contact with both of you (Bernard and myself) and i think we had a very smooth process implementing it. When starting the process we were not sure RTL was going to work? Japanese fonts going to work? I am very happy you could reuse my logic in the tables because their are a lot of calculations converting metric values to imperial values. To get those tables right in the past was quite time consuming so not having to go over this process again but reusing big bonus.

    At the end of the project RTL was smooth Japanese fonts went smooth.(...) Also in the project you never came to me and said impossible not going to work.

    I think pdf is just not an easy topic. We use dolibarr as our ERP system built in php. To produce the 1 page PDF invoice it goes through 1977 lines of code.

    Anyway I am very happy with the result and amazed by the amount of people that like to have a pdf.(...)

    Erik van Berkum, acniti LLC

    Lessons Learned and conclusion

    PDF creation in PHP is still not an easy task. The most popular library, mPDF, has some restrictions related to CSS that can make it tedious to work with. Especially when it comes to more complex layouts and tables.

    Using the RockPdf module for the task was a great choice. Its API is very well designed, offers a lot of conveniences and is well documented. Bernhard responded quickly to my questions and provided great support.

    In conclusion, the ProcessWire ecosystem offers great tooling for PDF creation that makes life for developers more enjoyable :-)

    Future considerations

    Would I use this approach again? Well, that depends mainly on the requirements. For this task the chosen tooling worked very well and I am happy with my choice.

    But for more complex layouts/designs that require modern CSS features, I would prefer rendering PDFs through Chromium browser using puppeteer or a self-hosted gotenberg service.

    • Like 9
    • Thanks 1
  4. 7 minutes ago, gebeer said:

    Since this extension comes from tailwindlabs, the creators of Tailwind, I would go with it.

    Not so sure about that. But the GH repo on the extension page links to tailwndlabs.
    EDIT: Actually I would not trust that extension since they are clearly not linking to their own GH repo and therefore pretending to come from tailwindlabs. 

    • Like 1
  5. 37 minutes ago, bernhard said:

    Real programmers write tailwindcss classes right from their brain.

    Then I'm not a real programmer :-)

    For me the extension is still working on Cursor
    Version: 0.40.1
    VSCode Version: 1.91.1
    Commit: 58b91712431381a1b75817cd3437cee35dddcb30
    Date: 2024-08-24T02:52:24.035Z
    Electron: 29.4.0
    ElectronBuildId: undefined
    Chromium: 122.0.6261.156
    Node.js: 20.9.0
    V8: 12.2.281.27-electron.0
    OS: Linux x64 6.10.6-zen1-1-zen

    But that is on Linux. I tried it on a project that I setup with your TW/UIKit profile, so there is LESS involved.

    37 minutes ago, bernhard said:

    Since this extension comes from tailwindlabs, the creators of Tailwind, I would go with it.

    • Like 1
  6. 22 hours ago, kongondo said:

    Any of you Linux folks use Visual Studio Code?

    Yes, using VSCodium. Running smoothly for the last 3 years or so. Prefer that over the original binary from Microsoft that comes with all their telemetry shenanigans. Only drawback is that some extensions from the official MS extensions store are not (yet) published at https://open-vsx.org/ which is the default extensions source in VSCodium. But you can still manually download the vsx file from the official store and install. Other than that, I'm very happy with my telemetry-free VSCode experience. Depending on your distribution, you can find the package in the official repos of your distro or in the AUR for Arch (which I'm on btw).

    10 hours ago, wbmnfktr said:

    VSCodium (Free/Libre version of VS Code) feels a bit different. A bit off.

    Cannot confirm that. On my end it feels ok. But then, I don't have the comparison with MS windows. Can only compare it to Cursor which (unfortunately) is only available as AppImage. And those are not as well integrated into your OS as native packages are.

    • Like 1
  7. On 7/22/2024 at 8:55 PM, bernhard said:

    Anybody using RockMigrations for automated deployments please check out v5.0.1 which changes the names of the release folders from "release-[deploy-id]-[commit-sha]" to "release-YYYYmmddHHiiss-[commit-sha]"

    The reason for this change is that yesterday suddenly my deployments broke and it turned out that the deploy-id made a jump from 999... to 100... which broke the logic that was used for renaming all release folders after each deployment. This should not happen any more now that we are using timestamps which are maybe more helpful anyhow.

    I don't think so but in case it does not work with the new version remove all old release folders and then deploy again.

    I can confirm that deployment worked for us after update to 5.0.1 only after removing the old release folders. When leaving them in place on the first deployment, the new release folder with new naming format did not get created. But current was symlinked to that non existing folder.

    • Thanks 1
  8. 50 minutes ago, szabesz said:

    How to initialize a "custom page" object has also been discussed here before: https://processwire.com/talk/topic/25342-custom-classes-for-page-objects-the-discussion/

    Actually that post is where I got to learn that we can use loaded() for initialisation. It is great that you discussed this in such detail there, especially the drawbacks.

    I thought, since the OP seems to have a lot of expertise in using page classes, I'd ask him if he had found a more elegant way than using loaded(). And putting everything together that I have learned about page classes, I will avoid initialisation of props using loaded() with DefaultPage going on from here ?

    • Like 2
  9. 24 minutes ago, FireWire said:

    My first reaction is that unexpected behaviors may indicate that there may be too much abstraction. My DefaultPage classes have traditionally been lightweight and stick to only containing what can be reliably counted on as valuable across all pages. One of the criticisms of OOP is that classes and inheritance can make for brittle code so it's something that I try to be mindful of. It may also be good to try an keep anything that executes automatically or hooks into the Page lifecycle to a minimum (maybe none at all) in DefaultPage since it spans the entire application.

    This was most likely what caused that behaviour. So yeah, we have to be very mindful there. Guess I needed to learn that the hard way ? Great suggestions here.

    And thanks for your thoughts on properties in page classes and the very well structured example you give.

    29 minutes ago, FireWire said:

    I actually haven't set a lot of instance variables in page classes.

    There might be a good reason to avoid them, since they add overhead to Page loading. And I haven't found other methods like init or ready that are suitable for attaching those properties. Since my main goal with them was to have sensibly named props that intellisense can discover, I might as well stick with methods.

    After having worked for some time with implementing those props via the loaded() method in the past, nowadays I avoid them for the reasons mentioned.

    • Like 1
  10. What a great writeup! Thank you for putting your time into this. It could be part of the official docs for page classes.

    I would be interested in your reasoning behind naming the base class BasePage. In the docs that you linked, Ryan suggests DefaultPage. In https://github.com/processwire/processwire/blob/3cc76cc886a49313b4bfb9a1a904bd88d11b7cb7/wire/config.php#L202 it says:
     

    Quote

    If you create a file named /site/classes/DefaultPage.php with a DefaultPage class within
     it (that extends Page), then it will be used for all pages that would otherwise use the 
     `Page` class.

    So are you using BasePage to not have every Page be based automatically on DefaultPage?

    I'm asking this, because I am using the DefaultPage class quite a lot and in some cases it caused some minor unexpected behaviours because the class is used for every Page.

    On 6/23/2024 at 2:50 AM, FireWire said:

    page classes will extend this class instead of Page and benefit from having access to universal methods and properties

    Would love to see how you implement properties in your base page class. Specifically how and where do you assign them?

    I utilize the loaded() method to assign those properties and found that it added lots of overhead because loaded() is called for every page that is loaded in a PW lifecycle when using it on the DefaultPage class. And that seemed a bit expensive to me, especially if construction of some properties requires more complex and expensive logic.

    Here's an example on how I implement custom properties on runtime

    class DefaultPage extends Page
    {
        // trait that provides methods for responsive images
        use ResponsiveImages;
    
        // define statuses that should be excluded from loadingcustom properties
        const excludeStatuses = array(
            Page::statusTrash,
            Page::statusUnpublished,
            Page::statusDraft,
        );
    
        public $introTitle;
        public $introText;
    
        // set custom properties in loaded
        public function loaded()
        {
            // load custom properties only for allowed statuses
            if (!empty(array_intersect(array_keys($this->status(true)), self::excludeStatuses))) return;
    
            $this->set('introTitle', $this->text);
            $this->set('introText', nl2br($this->textarea));
        }
    
    }

    I found that loaded() is called for every page regardless of their status. So I prevent loaded() from assigning properties for some statuses where the properties are not needed.

    Why I want to have custom properties in the first place? Almost all fields in my PW installations get very generic names like text, textarea, rte, image, text2 etc. I am using those fields in different templates for different purposes. Custom properties are a nice way to access those generic fields in a more meaningful manner and have them available in intellisense.

     

    • Thanks 1
  11. 1 hour ago, MarkE said:

    That doesn't work as it needs the permission to load the module with noPermissionCheck ?. It just results in "You do not have permission to execute this module..." without even any debugging!

    Thanks for clarifying this. I hadn't tested it before suggesting it as potential solution. But I had some cases in the past where this resolved my module permission issues.

  12. 3 hours ago, wbmnfktr said:

    might get the pro for Claude Sonnet 3.5 support in the chat as that models is a true banger.

    I get better results with Claude Sonnet than with GPT4o. Been using 3.5 Sonnet since it came out. Currently using it through Anthropic API with https://www.continue.dev/. In continue config I disabled the autocomplete and use Supermaven for that. The continue chat interface integrates nice and I could choose from more models if I desired to do so. With the Supermaven pro plan, you get 5$ of monthly credits for the chat models. Don't know about pricing for additional chat requests above that. Couldn't find it on Supermavens website. When going through Anthropic API, the usage cost is very detailed and transparent.

    Anyways, exciting to see so much going on in the AI assistant space and great to have so many options.

    • Like 1
  13. To simply hide the Add button of the PageListSelectMultiple field for non-superusers or for all, you can use some custom JS.

    Example:

    JS in site/templates/scripts/admin-custom.js

    // custom admin script
    
    console.log("admin-custom.js loaded");
    
    /**
     * Hides the "Add" button for the Inputfield Page List Select Multiple field with given fieldName.
     * This function is intended to restrict access to adding existing items for non-superuser roles.
     */
    function hideAddButtonForInputfieldPagelistSelectMultiple(fieldName) {
      // Uncomment the following line to also hide for superusers
      // config object is globally available in the admin and contains user objecyt with roles array
      // if (config.user.roles.includes('superuser')) return;
    
      const wrapper = document.getElementById('wrap_Inputfield_' + fieldName);
      if (!wrapper) return;
    
      const start = wrapper.querySelector('a.PageListSelectActionToggleStart');
    
      if (start) {
        start.style.display = 'none';
      }
    }
    
    window.onload = function () {
      hideAddButtonForInputfieldPagelistSelectMultiple('my_pagelist_select_multiple'); // pass in your field name here
    };

    To load that script in site/templates/admin.php

    ...
    // load site/templates/admin-custom.js
    $config->scripts->add($config->urls->templates . 'scripts/admin-custom.js');
    
    /** @var Config $config */
    require($config->paths->core . "admin.php");

    You could do this with custom CSS. But there you don't have the user role available.

    EDIT: or you do it with CSS and load it depending on user role in admin.php ?

    site/templates/admin.php

    // load site/templates/admin-custom.css for non superusers
    if(!$user->isSuperuser()) $config->styles->add($config->urls->templates . 'styles/admin-custom.css');
    ...

    site/templates/styles/admin-custom.css

    /* Hides the "Add" button for the Inputfield Page List Select Multiple field with name "my_pagelist_select_multiple" */
    #wrap_Inputfield_my_pagelist_select_multiple a.PageListSelectActionToggleStart {
      display: none;
    }

    Hope this helps.

    • Like 3
  14. IMO your solution seems a bit hacky.

    Don't know enough about the structure of your module and how you load it in your Page Classes. But here are 2 ways you could approach it.

    You could use https://processwire.com/api/ref/modules/get-module/ which has an option noPermissionCheck which lets you load the module regardless of the current users permissions.

    It seems that you have already isolated the required methods into _motif_include.php. You could refactor and put them in their own module (which depends on the main module and gets installed by it). That module could then have different permission settings. That would be a much cleaner approach IMO.

    • Like 1
  15. 10 hours ago, wbmnfktr said:

    Out of curiosity, I installed Supermaven yesterday, even though I was quite happy with Codeium, and started playing around with it since then.

    For now, I am super impressed by its speed, accuracy, and knowledge. While Codeium is more on the PHP side of things, Supermaven seems to know more about or even understands ProcessWire.

     

    Same for me. Installed it yesterday and went straight for the trial of pro plan because of the insane context window of 1 million tokens. If the model sees that much of your codebase it can make much better suggestions. Even on the free plan you get 300.000 tokens context which is way more than any of the other autocomplete models can digest. The speed is absolutely amazing. Guess I will switch from Codeium.

    • Like 1
  16. 54 minutes ago, cpx3 said:

    Hi @kongondo, as you ignore all the mails, I try it here: I bought the current version of Mediamanager which turned out quite useless as your "Coming soon" documentation is more than ridiculous. Is there any chance that there will be a documentation for that paid product that helps me use it?

    Thanks in advance,
    Cpx3

    I am running the current ("old") version of MM. The documentation at https://mediamanager.kongondo.com/documentation/ used to be for that version.

    Checking the docs, I just realized that they are work in progress. Where has the documentation for the current ("old") version gone? It would be useful (not only for new users of your module) if they still could access the documentation for the current version. This would certainly help to avoid frustration ?

    When MM Next is out, there should still be documentation for the old version alongside the new one.

    • Like 1
  17. 1 hour ago, Tiberium said:

    I test supermaven and codeium at the moment. What I like about supermaven, it is superfast. I don't develop that "Copilot pause" on my typing. Codium feels slower as supermaven, but also faster as Copilot.

    On codeium, my problem is, that the context of the project is only avaible in the chat, not really in the inline mode (in my testing). So that is something, where I tend more to supermaven at the moment.

     

    (Maybe it is a limitation of the neovim plugin)

    Thank you for the insight. Just today I had the clear proof that Codeium autocomplete was well aware of the context. At least the last edited file (like they say in their docs). Can't say for sure that it also has context from the whole codebase. Need to check that.

    Will also give Supermaven a try and see how it compares.

  18. Interesting. I watched Theo's video but haven't tried it yet. Mainly because I'm very happy with https://codeium.com/. Also very fast and quite good completions. Been using this for almost a year now and it has made much progress in quality and features. In addition to code completion you get AI chat, DocBlock Creation, Refactoring and much more. It seems to very intelligently grasp the context it needs to provide good completions without you having to configure anything. You can even improve performance by fine tuning some settings.

    I am using this inside the Cursor editor instead of their Copilot++ feature.

  19. Ever so often when working with JS, we need the good old console.log(). It is really tedious and time consuming having to type that out manually. Also, I like descriptive logs.

    Here's a little keybinding which addresses that and saved me a tons of time. I have it in the User keybindings.json

      {
        "key": "ctrl+shift+m",
        "command": "runCommands",
        "args": {
          "commands": [
            {
              "command": "editor.action.clipboardCopyAction"
            },
            {
              "command": "cursorLineEnd"
            },
            {
              "command": "lineBreakInsert"
            },
            {
              "command": "cursorDown"
            },
            {
              "command": "editor.action.insertSnippet",
              "args": {
                "snippet": "console.log(\"${CLIPBOARD}\", ${CLIPBOARD});"
              }
            }
          ]
        },
        "when": "editorTextFocus && editorHasSelection"
      }
    

    What it does:
    You select the var you want to log, press Ctrl+Shift+m (or any combination you prefer). This will go to the end of the current line, insert a line break, move down to the new line and insert the console.log() statement.

    Example:

    before with marked var:
    cl-before.png.8da7f220647476c34287a55de5d2ac49.png

    after with log statement:
    cl-after.png.5545630a0a556f06ca002da0d5592fa3.png

    Hope someone will find this useful ?

    • Like 3
  20. 12 hours ago, FireWire said:

    Mad respect. I wish I could live on this level of bleeding edge. Feels like I'm watching a someone drive by in a Porsche 911 GT2 from behind the fence at a daycare playground ?

    It is actually not that wild. Once you got the hang of the terminology, config file structure and basics of nix lang, it is fun setting up your machine. And in the case I had to move to a different machine quickly, all is setup exactly as I need it with copying over the config files and issueing one command.

    • Like 2
  21. 12 hours ago, Jonathan Lahijani said:

    As for TUI and CLI apps, one route I've long considered is switching to terminal-based apps for almost everything and being as mouseless as possible.  Before I do that though, I would first want to become comfortable with Neovim and Vim-style key bindings.  The problem with that however is I don't type "correctly" (fingers on home row, etc.) so fixing that after 30 years of typign my own way will be... fun.

    Having exactly the same experience with vim keybinds. Haven't really bothered switching. As for terminal filemanagers, the keybinds are fully configurable. And yazi comes out of the box with hjkl and arrow keys.

    11 hours ago, wbmnfktr said:

    For me arrow keys win most of the time. I didn't feel the need to learn HJKL. I know about it, that's enough

    same here ?

    12 hours ago, Jonathan Lahijani said:

    The larger picture of why I'm doing this is to overall De-Google, De-Microsoft and De-Apple my life as much as possible

    I'm on the same path there. But it is really hard. Especially getting away from Google. So many websites that offer easy login, some map API keys for my clients etc. But on the Smartphone, I'm running Lineage for MicroG for about 1 year now. It is pretty great. Some apps, like OpenAI and one of my banking apps, are not installable though, due to them requiring Play Secure or some BS service from the playstore. Might work with the next upgrade of the OS...  

     

    • Like 2
  22. 1 minute ago, bernhard said:

    I'd make the offcanvas white bg + black text and for the second offcanvas i'd use tailwind bg-black + text-white.

    Given that you are using your UIKit+Tailwind combination, this sounds like a viable solution. Not sure though if text-white on the container will override input text and placeholder colors as welll as icon colors. So it would be still kind of a mess.

    I'd prefer to do this with uk classes if possible since I'm on a pure UIKit project. But given that you work way more with UIKit than me, there doesn't seem to be an easy solution. I'll wait what the client ays to the dark search bar before I get my hands dirty. Hopefully they like it ?

×
×
  • Create New...