sebastiancarlos

joined 1 year ago
 
115
submitted 1 month ago* (last edited 1 month ago) by sebastiancarlos@lemmy.sdf.org to c/linux@lemmy.ml
 

Either self-hosted or cloud, I assume many of you keep a server around for personal things. And I'm curious about the cool stuff you've got running on your personal servers.

What services do you host? Any unique stuff? Do you interact with it through ssh, termux, web server?

 

Hey,

As an avid CLI user, I always aimed to master non-interactive tools to perform most of my work, given that they are easy to use, create, extend, and connect.

However, I found myself dealing with software projects with many files (mostly under the yoke of corporate oppression; an ordeal which I endure to sustain myself, as most of those reading me do, and therefore I will not go further into this topic) and started to hit the limits of non-interactive tools to find and edit files. Indeed, I could go faster if I followed the temptation of monstrous IDEs, as I did in my innocent past.

I did not despair, as naturally I heard of the usefulness of interactive fuzzy finders such as fzf. After spending an afternoon evaluating the tool, I concluded that it indeed increases the complexity of my workflow. Still, this complexity is managed in a sensible way that follows the UNIX tradition.

I now ask you two general questions:

  • Did you reach similar conclusions to me and decide to use interactive fuzzy finders to solve working on software projects with many files?
  • If you use fzf or similar tools, what can you tell me about your workflow? Any other third-party tools? Do you integrate it into your scripts? Any advice that you can give me out of a long time of experience using the tool that is not easily conveyed by the documentation?

I also ask this very specific question:

  • The one part of fzf which I found missing was a way to interact with the results of grep, and to automatically place the selected file(s) in the prompt or an editor. For that, I created the following two commands. Do you have a similar workflow when you want to bring the speed of fuzzy finding to grep?
#! /usr/bin/env bash

# gf: grep + fzf
# basically a wrapper for 'grep <ARGS> | fzf | cut -f 1 -d:'

# print usage on -h/--help
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
    echo "Usage: gf <grep-args>"
    echo
    echo "~~~ that feel when no 'gf' ~~~"
    echo
    echo "- Basically a wrapper for 'grep <ARGS> | fzf | cut -f 1 -d:'"
    echo "- Opens fzf with grep results, and prints the selected filename(s)"
    echo "- Note: As this is meant to search files, it already adds the -r flag"
    echo
    echo "Example:"
    echo "  $ nvim \`gf foobar\`"
    echo "  $ gf foobar | xargs nvim"
    exit 0
fi

# run grep with arguments, pipe to fzf, and print the filename(s) selected
custom_grep () {
    grep -E --color=always --binary-files=without-match --recursive "$@"
}
remove_color () {
    sed -E 's/\x1b\[[0-9;]*[mK]//g'
}
custom_fzf () {
    fzf --ansi --height ~98%
}
grep_output=$(custom_grep "$@")
if [[ "$?" -ne 0 ]]; then
    exit 1
else
    echo "$grep_output" | custom_fzf | remove_color | cut -f 1 -d:
fi
#! /usr/bin/env bash

# ge: grep + fzf + editor
# basically a wrapper for 'grep <ARGS> | fzf | cut -f 1 -d: | $EDITOR'

# print usage on -h/--help
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
    echo "Usage: ge <grep-args>"
    echo
    echo "- Basically a wrapper for 'grep <ARGS> | fzf | cut -f 1 -d: | \$EDITOR'"
    echo "- Opens fzf with grep results, and edits the selected file(s)"
    echo "- Note: As this is meant to search files, it already adds the -r flag"
    echo "- Note: Internally, it uses the 'gf' command"
    echo
    echo "Example:"
    echo "  $ ge foobar"
    exit 0
fi

# takes output from 'gf' and opens it in $EDITOR
grep_fzf_output=$(gf "$@")
if [[ -n "$grep_fzf_output" ]]; then
  $EDITOR "$grep_fzf_output"
fi

Have a wonderful day, you CLI cowboys.

[–] sebastiancarlos@lemmy.sdf.org 1 points 2 months ago* (last edited 2 months ago)

Cool project! I'll check it out.

Regarding userscripting, from the F.A.Q.:

Why use an external automation tool (Playwright) instead of a browser extension?

While Beachpatrol allows to control the browser from both the OS and from a browser extension, our priority was the OS. Therefore, something like Playwright was the natural choice.

Furthermore, while controlling the browser from an extensions is possible, Manifest v3 removed the ability to execute third-party strings of code. Popular automation extensions like Greasemonkey and Tampermonkey could also be affected by Manifest v3. The alternative is to embed the code into the extension, but that would requires re-bundling the extensions after every change. Other tricks do exist to make this approach work, and there is some hope for future Manifest v3 solutions, but this path is certainly tricky.

It is more likely that Selenium and related tools will continue to work in the foreseeable future given the business demand for traditional browser testing.

 
 
 

Source code

#!/usr/bin/env bash

# colorcat
# - cats a file, but if any line contains N hex colors, it appends the colors
#   (rendered as ansi escape sequences) to the end of the line.
# - input can be stdin, a file, or a hex color in plain text
if [[ "$#" -eq 1 &amp;&amp; ! -f "$1" ]]; then
  echo "$1"
else
  cat "$@"
fi | while read -r line; do
  colors=""
  for word in $line; do
    if [[ "$word" =~ ^[^A-Fa-f0-9]*#?([A-Fa-f0-9]{6})[^A-Fa-f0-9]*$ ]]; then
      hex=${BASH_REMATCH[1]}
      r=$((16#${hex:0:2}))
      g=$((16#${hex:2:2}))
      b=$((16#${hex:4:2}))
      truecolor="\033[48;2;${r};${g};${b}m"
      reset="\033[0m"
      colors="${colors}${truecolor}  ${reset} "
    fi
  done
    echo -e "$line $colors" 
done
 

Source code:

# source of truth for URL aliases
# - used by url-alias-setup and url-alias
# - can be modified to add new aliases
declare -A __url_alias=(
  ["g"]="https://google.com"
  ["r"]="https://reddit.com"
  ["h"]="https://news.ycombinator.com"
)

# url-alias
# - print the current URL aliases
function url-alias () {
  local green="\033[32m"
  local cyan="\033[36m"
  local reset="\033[0m"

  echo "${green}URL aliases:${reset}"
  for alias in "${!__url_alias[@]}"; do
    echo "${cyan}${alias}${reset} -> ${__url_alias[${alias}]}"
  done

  echo "${green}To add new aliases, edit the ${cyan}__url_alias${green} array and run ${cyan}url-alias-setup${reset}"
}

# return either 'linux' or 'macos'
function get_platform () {
  case "$(uname -s)" in
    Darwin)
      echo "macos"
      ;;
    Linux)
      echo "linux"
      ;;
    *)
      echo "unsupported platform"
      exit 1
      ;;
  esac
}
platform=$(get_platform)

# url-alias-setup
# - sets up URL aliases
# - this is done by modifying the /etc/hosts file and the nginx configuration
# - if changes are made, nginx is (re)started
function url-alias-setup () {
  # nginx config (platform dependent) 
  if [[ "$platform" == "macos" ]]; then
    local nginx_config="/usr/local/etc/nginx/nginx.conf"
  else
    local nginx_config="/etc/nginx/nginx.conf"
  fi

  # create new nginx config and hosts file
  local new_hosts=""
  read -r -d '' new_nginx_config &lt;&lt; 'EOF'
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
EOF
  
  for alias in "${!__url_alias[@]}"; do
    local url="${__url_alias[$alias]}"

    new_hosts="${new_hosts}\n127.0.0.1 ${alias}"

    read -r -d '' server_blocks &lt;&lt; EOF
    server {
        listen       80;
        server_name  ${alias};
        location / {
          rewrite ^ ${url} permanent;
        }
    }
EOF
    new_nginx_config="${new_nginx_config}\n    ${server_blocks}"
  done
  new_nginx_config="${new_nginx_config}\n}"
  
  # replace files
  # if file already exists, prompt user to overwrite
  echo "Saving new nginx config and hosts file..."
  if [[ -f "${nginx_config}" ]]; then
    echo "File ${nginx_config} already exists. Overwrite? (y/n)"
    read -r overwrite
    if [[ "${overwrite}" != "y" ]]; then
      echo "Aborting..."
      return 1
    fi
  fi
  echo -e "${new_nginx_config}" | sudo tee "${nginx_config}" > /dev/null
  if [[ -f "/etc/hosts" ]]; then
    echo "File /etc/hosts already exists. Overwrite? (y/n)"
    read -r overwrite
    if [[ "${overwrite}" != "y" ]]; then
      echo "Aborting..."
      return 1
    fi
  fi
  echo -e "${new_hosts}" | sudo tee /etc/hosts > /dev/null

  # start or restart nginx
  echo "Restarting nginx..."
  if [[ "$platform" == "macos" ]]; then
    nginx -s reload
  else
    sudo systemctl restart nginx
  fi
}
 
view more: next ›