Preface:
I know this is totally unecessary and probably entirely useless for most people, but...

I've recently installed NetBSD-Current on a spare disk on my Desktop machine and am slowly getting used to building everything from source. I am quite fond or the fuzzypkg script on Void linux, a wrapper for use with xbps. So I wondered if something similar could work for pkgsrc.

Disclaimer:
This script is currently untested and was written by ChatGPT in collaboration with Google's Gemini AI. I basically played pong with ChatGPT and Gemini until I was happy most things were covered. I have no idea if this particular script will work, but I like the idea behind it.

#!/bin/sh

# Check if fzf is installed
if ! command -v fzf >/dev/null 2>&1; then
  echo "Error: fzf is required. Please install it first." >&2
  exit 1
fi

# Check if bat is installed (optional, for package description previews)
if ! command -v bat >/dev/null 2>&1; then
  echo "Warning: bat is not installed. Package description previews won't be available." >&2
fi

# Path to the user's pkgsrc directory (replace with your actual path)
PKGSRCDIR="$HOME/pkgsrc"

# Check if the pkgsrc directory exists
if [ ! -d "$PKGSRCDIR" ]; then
  echo "Error: $PKGSRCDIR directory not found. Please create it and place your pkgsrc directory inside." >&2
  exit 1
fi

# Find available packages and store them in a variable
pkgs=$(find "$PKGSRCDIR" -mindepth 2 -maxdepth 2 -type f -name 'Makefile' -exec dirname {} \; | sort)

# Use fzf for user selection with bat for previews
selected_pkg=$(fzf --preview 'cat $PKGSRCDIR/{}/DESCR' <<< "$pkgs")

# Check if a package was selected
if [ -z "$selected_pkg" ]; then
  echo "No package selected"
  exit 1
fi

# Change directory to the selected package
cd "$PKGSRCDIR/$selected_pkg" || exit 1

# Build and install the package
echo "Building and installing $selected_pkg..."
make install clean clean-depends distclean

Explanation:

1. Dependency Checks: The script starts by verifying if fzf and bat are installed. If not, it displays an error message and exits.

2. pkgsrc Directory: It defines the path to the user's pkgsrc directory. Replace $HOME/pkgsrc with the actual location on your system.


3. Directory Existence Check: It checks if the specified pkgsrc directory exists. If not, it displays an error message and exits.


4. Finding Packages: The script uses find to search within the pkgsrc directory for directories containing a file named Makefile. It then extracts directory names and sorts them for presentation.


5. Interactive Selection: This is where the magic happens:
- The script stores the list of packages (pkgs) in a variable.
- It uses fzf to create an interactive menu displaying the available packages.
- Instead of cat, it uses bat in the preview command --preview 'bat $PKGSRCDIR/{}/DESCR'. This assumes you have bat installed, a syntax highlighter for better code and text rendering. It displays a preview of the package DESCR file when hovering over a package in the fzf menu. Of course you could use cat if you prefer.


6. Selection Validation: After user interaction, it checks if a package was actually selected. If not, it displays a message and exits.


7. Directory Change: It navigates to the directory of the chosen package within the pkgsrc directory structure.


8. Build and Install: Finally, the script uses make install clean clean-depends distclean to build and install the selected package.
- make install: Performs the installation process.
- clean: Removes temporary build files after installation.
- clean-depends: Cleans up downloaded dependency files.
- distclean: Removes everything related to the build process, including downloaded archives.

Summary:

This script empowers you to easily search, select, build, and install packages from your pkgsrc source directory on NetBSD Current. It offers user-friendly features like fzf for selection and leverages bat for enhanced previews (assuming it's installed) to help you choose the right package. Remember to adjust the PKGSRCDIR path if your pkgsrc directory is located elsewhere.

  • rvp and pin replied to this.
  • Jay likes this.
    • Best Answerset by pfr

    pfr This any better?

    Makes my eyes glaze. I think A.I. should stick to writing milquetoast press-releases. Doesn't mean we can't teach it any better:

    (warning: untested, since I don't have fzf nor bat installed)

    #!/bin/sh
    
    set -eu
    
    die() {
    	echo >&2 "$0: $*"
    	exit 1
    }
    getkey() {
    	local orig=$(stty -f /dev/tty -g)
    	stty -f /dev/tty -icanon min 0 time 20		# 2 secs.
    	key=$(dd if=/dev/tty bs=1 count=1 2>/dev/null)
    	stty -f /dev/tty "$orig"
    	echo "$key"
    }
    
    for C in fzf bat
    do	command -v "$C" >/dev/null || die "$C: reqd. cmd. not found"
    done
    
    D="$HOME/pkgsrc"
    cd "$D"		# || exit 1
    
    # Only category/package considered
    #
    P=$(printf '%s\n' */*/Makefile | sed 's;/Makefile$;;')
    [ "$P" = "*/*" ] && die "$D: not a pkgsrc base dir."
    
    for P in $(echo "$P" | fzf --preview 'bat {}/DESCR')
    do	echo "====> Going to build & install: $P (q to QUIT)"
    	[ "$(getkey)" = q ] && break
    	make -C "$P" install clean
    done

    Learn, little A.I., learn!

    pfr This script empowers you [...]

    "Empowers you ..."?! Empowers -- Aw, @Jay-sus H!

    #!/bin/sh
    [...]
    selected_pkg=$(fzf --preview 'cat $PKGSRCDIR/{}/DESCR' <<< "$pkgs")

    So, A.I., all /bin/shs understand here-strings, eh? Empowers, my furry POSIX ...!

      pfr distclean: Removes everything related to the build process, including downloaded archives.

      Wrong, it cleans only downloaded stuff for the package currently being built. It doesn't clean downloaded files for any of the built dependencies.

      Also, stupid to do if you're building things that are separated packages from the same source. For example, LLVM contains libunwind, libcxx and libcxxabi, as well as local copy of cmake. This means that, if you run distclean after building LLVM and then you want to build libunwind, it will simply have to fetch the sources again, as you just removed them.

      Note, I have nothing against you trying to automate the process but, I would recommend learning a bit further before doing so. It will save you future headaches when the automation fails and you have no clue why.

      Or, maybe ignorance is bliss after all.

      • pfr replied to this.

        rvp "Empowers you ..."?!

        The bots do like to exaggerate! (these aren't my words)

        rvp

        #!/bin/sh
        [...]
        selected_pkg=$(fzf --preview 'cat $PKGSRCDIR/{}/DESCR' <<< "$pkgs")

        So, A.I., all /bin/shs understand here-strings, eh?

        Can you elaborate on what is wrong here? Will this not work under /bin/sh? Is there a more POSIX way of writing this part?

        pin Note, I have nothing against you trying to automate the process but, I would recommend learning a bit further before doing so. It will save you future headaches when the automation fails and you have no clue why.

        I agree, hence why I posted it here first instead of blindly running this script. I acknowledge the potential for issues when doing these types of things, and as @rvp has already pointed out, the LLM's are great at seeming like they're always correct but often aren't.

        • rvp replied to this.

          pfr Is there a more POSIX way of writing this part?

          Let's see if the A.I. can do it first. Tell it that a) <<< is not POSIX, and b) you'd like it to handle the case of fzf returning multiple selections for steps 7. & 8.

          • pfr replied to this.
          • pfr likes this.

            rvp

            This any better?

            #!/bin/sh
            
            # Check if fzf is installed
            if ! command -v fzf >/dev/null 2>&1; then
              echo "Error: fzf is required. Please install it first." >&2
              exit 1
            fi
            
            # Check if fd-find is installed
            if ! command -v fd >/dev/null 2>&1; then
              echo "Error: fd-find (fd) is required. Please install it first." >&2
              exit 1
            fi
            
            # Check if bat is installed
            if ! command -v bat >/dev/null 2>&1; then
              echo "Error: bat is required. Please install it first." >&2
              exit 1
            fi
            
            # Path to the user's pkgsrc directory
            PKGSRCDIR="$HOME/pkgsrc"
            
            # Check if the pkgsrc directory exists
            if [ ! -d "$PKGSRCDIR" ]; then
              echo "Error: $PKGSRCDIR directory not found. Please create it and place your pkgsrc directory inside." >&2
              exit 1
            fi
            
            # Function to show package description
            show_description() {
              pkg="$1"
              descr_file="$PKGSRCDIR/$(dirname {})/$pkg/DESCR"
              if [ -f "$descr_file" ]; then
                bat "$descr_file"
              else
                echo "No description available for $pkg"
              fi
            }
            
            # Find available packages recursively in all category directories and display selection menu
            pkgs=$(fd --type d --min-depth 4 --max-depth 4 'Makefile' "$PKGSRCDIR" | xargs -I{} basename {})
            selected_pkg=$(printf '%s\n' "$pkgs" | fzf --preview 'show_description {}' --preview-window=right:70% --prompt="Select a package: ")
            
            # Check if a package was selected
            if [ -n "$selected_pkg" ]; then
              # Display package description and install
              show_description "$selected_pkg"
              cd "$PKGSRCDIR/$(dirname {})/$selected_pkg" && make clean install
            else
              echo "No package selected"
              exit 1
            fi
            • rvp replied to this.

              Is that again made by ChatGPT? I wonder what's up with all those {}. What's the point in something like basename {} and the $(dirname {}) part (which i think just statically expands to .) of the directory being switched to seemingly makes even less sense (not to mention that make has a -C switch, which could fully avoid the need to cd).

              No offense but in my opinion trying to get those language models to program stuff is not that great of an idea. They don't really know what they are doing and even if they might get it right sometimes picking out the subtle errors of some source one isn't familiar with is almost worse than just writing the whole thing from scratch.

              Edit: I also don't understand why it insists on using fd instead of boring old find which seemingly would do pretty much the same thing and likely could also avoid xargs entirely.

                • Edited
                • Best Answerset by pfr

                pfr This any better?

                Makes my eyes glaze. I think A.I. should stick to writing milquetoast press-releases. Doesn't mean we can't teach it any better:

                (warning: untested, since I don't have fzf nor bat installed)

                #!/bin/sh
                
                set -eu
                
                die() {
                	echo >&2 "$0: $*"
                	exit 1
                }
                getkey() {
                	local orig=$(stty -f /dev/tty -g)
                	stty -f /dev/tty -icanon min 0 time 20		# 2 secs.
                	key=$(dd if=/dev/tty bs=1 count=1 2>/dev/null)
                	stty -f /dev/tty "$orig"
                	echo "$key"
                }
                
                for C in fzf bat
                do	command -v "$C" >/dev/null || die "$C: reqd. cmd. not found"
                done
                
                D="$HOME/pkgsrc"
                cd "$D"		# || exit 1
                
                # Only category/package considered
                #
                P=$(printf '%s\n' */*/Makefile | sed 's;/Makefile$;;')
                [ "$P" = "*/*" ] && die "$D: not a pkgsrc base dir."
                
                for P in $(echo "$P" | fzf --preview 'bat {}/DESCR')
                do	echo "====> Going to build & install: $P (q to QUIT)"
                	[ "$(getkey)" = q ] && break
                	make -C "$P" install clean
                done

                Learn, little A.I., learn!

                  nettester Is that again made by ChatGPT? I wonder what's up with all those {}.

                  Imposter syndrome is very real, isn't it?
                  Pre-ChatGPT, new coders climbed Mount Stupid, fell off that mountain, and found their path to enlightment.
                  Post-ChatJeopardy, new coders climb Mount Stupid, and get stuck on there forever.

                  rvp Learn, little A.I., learn!

                  Let's call it for what it really is.
                  It's not an AI, but a bullshit generator.

                    remiliascarlet I always call it Fake Intelligence but you might have it better.

                    I think it should be called Deception Mastered, or Mastered Deception. But that just doesn't sound as nice.

                    nettester I laughed way too hard at that. But who calls a knight a horse? 🤣🤣

                    BTW what happened to my previous reply? 😳

                      kc9udx I'm not sure what's customary in this regard in English (probably quite obviously not a native speaker) but at least in German calling the Knight Pferd (horse) is not that uncommon. Actually the term Ritter (which would be the direct translation of Knight) is not used at all and it's rather called Springer (jumper). I don't know the guy but i guess if he isn't a native speaker and would usually speak a language where using horse is common getting carried away and forgetting to adjust the term to English probably could happen quite easily.

                      Historically, the word knight is actually the word Knecht 🙂 (German to Old English and then corrupted over time). I sometimes call it that. But then I often call jacks Knaves, too.

                      BTW I often hear novices calling them "horsey". But didn't expect "horse" from someone really serious.

                      I wonder who can delete my erroneous extraneous replies above.

                        kc9udx I wonder who can delete my erroneous extraneous replies above.

                        Fixed 😉

                        remiliascarlet It's not an AI, but a bullshit generator.

                        Recalls to mind Frankfurt's distinction between liars and bullshitters: Liars have to care about the truth (in order to lie better), whereas bullshitters just don't care.

                        A.I.s, at present, are distinctly nearer to the smelly side of that line.

                        I think that part of the reason for this tendency to bullshit is simply due to the way A.I.s work right now: They start at the base (the initial try at a "goal") then always work up the "tree" of possibilities when you say "Fail! Try again!", instead of returning to the base of the tree to make a fresh cast--like a human would after a period of failures. Maybe it just doesn't want to throw away all the "data" it has accumulated along its search path. That would account for what we saw just now with this script: the more you push it, the more unmoored from reality it got (compare the initial offering with the final script).

                        • pfr replied to this.
                        • pfr likes this.

                          rvp I presented your working script back to it and rather than admit defeat, it once again attempted to improve on it by simply regurgitating nearly the exact same script or had given me previously, which was still miles away from actually working.

                          I told it, this script right here, it works, learn from it. And it assured me it would 🤣

                          • rvp replied to this.

                            pfr Maybe using chatbot A.I.s to write shell-scripts is an inherently silly idea (other than for the lulz)... just like using it to play chess (as a chess IM, surely GothamChess has heard of AlphaZero).

                              rvp The problem is that a lot of people are using it that way while being 100% oblivious to the fact that it's inherently silly. The defense i usually hear is something along the lines of "I'm just using it to get a general idea of how a solution would look like." which doesn't hold water in my opinion as the time spent on figuring out if or how far whatever the AI comes up with is actually valid would usually also suffice to just read the relevant documentation or research actual examples that are proven to be valid or at least have a high likelihood of that.

                              To make matters worse people going at it this way often times also flat out lack the capability to fact check the result. I predict that technicians of the not to far future will have to deal with quite bit of bizarre errors introduced by AI written code/configuration that managed to superficially work but was still broken overall.

                              • rvp replied to this.