pop-os / launcher

Modular IPC-based desktop launcher service
Mozilla Public License 2.0
219 stars 42 forks source link

fix: clear should not remove data from other plugins #190

Open friedow opened 11 months ago

friedow commented 11 months ago

Behavior After this Change When a plugin calls "Clear", the search results of this specific plugin are cleared.

Behavior Before this Change When a plugin calls "Clear", the search results of all plugins are cleared.

jacobgkau commented 11 months ago

So far, I haven't been able to find anywhere where this changes behavior with the default plugins.

I do see some places where comments in the documentation or code might need to be updated to match this change?

https://github.com/pop-os/launcher/blob/0febac5c5985df1f977c58f928d7665c73e47a92/README.md?plain=1#L154

https://github.com/pop-os/launcher/blob/0febac5c5985df1f977c58f928d7665c73e47a92/src/lib.rs#L72

friedow commented 11 months ago

Oh, I'm sorry, I forgot add my motivation to fix this! First and foremost: this fix is not necessary to run the default plugins. In fact, most of the default plugins don't use the "Clear" command at all. The reason being that none of the default plugins provide data "proactively" instead plugins like the calc plugin provide data "reactively". They wait for a user input which clears the current list of items implicitly and invokes a "Search" command on the plugin which then adds search results.

This works well for most of the use cases. However, I implemented a clock plugin (which tells the current time, accurate to seconds) which needs to update data "proactively". It uses "Clear" to delete the old time entry and adds another one afterwards even if there was no user interaction at all.

Here is the source for that clock plugin: clock.nu (https://www.nushell.sh/ script. This should be kinda readable, if not feel free to ask anything :)

#!/usr/bin/env nu

def main [] {
  mut lastSearch = ""

  while true {
    let command = (bash -c "read -t 1 input; inputOrTimeout=${input:="Timeout"}; echo $inputOrTimeout" | from json)

    if $command == "Exit" {
      break
    }

    if $command == "Interrupt" {
      continue
    }

    if ($command | describe) starts-with "record" and  $command.Search? != null {
      $lastSearch = $command.Search
    }
    let searchString = $lastSearch

    mut entries = (getEntries)
    if ($searchString | str length ) > 0  {
      $entries = ($entries | filter {|entry| entryMatchesSearch $entry $searchString })
    }

    if $command == "Timeout" {
      print '"Clear"'
    }
    printEntries $entries
  }
}

def getEntries [] {
  let date = (date now)
  let currentTime = ($date | date format '%H:%M:%S')
  let currentDate = ($date | date format '%A, %d. %B %Y')

  let timeEntry = ($'
    Append:
      id: 0
      name: ($currentTime)
      description: Time
      icon:
        Name: accessories-clock
  ' | from yml)

  let dateEntry = ($'
    Append:
      id: 1
      name: ($currentDate)
      description: Date
      icon:
        Name: date
  ' | from yml)

  return [ $timeEntry, $dateEntry ]
}

def entryMatchesSearch [entry: record, searchString: string] {
  let searchTerms = ($searchString | str downcase | split words)

  let entryString = ($entry.Append.name + " " + $entry.Append.description)
  let entryTerms = ($entryString | str downcase | split words)

  for searchTerm in $searchTerms {
    for entryTerm in $entryTerms {
      if ($entryTerm | str distance $searchTerm | $in <= 2) {
        return true
      }

      if ($entryTerm | str contains $searchTerm) {
        return true
      }
    }
  }

  return false
}

def printEntries [entries: list] {
  for entry in $entries {
    print ($entry | to json -r)
  }
  print '"Finished"'
}

plugin.ron

(
    name: "Clock",
    description: "Shows the current time and date.",
    bin: (path: "clock.nu"),
    icon: Name("clock"),
    query: (history: false),
)

FYI: I'm currently migrating all my launcher plugins to pop-launcher and of course all of this is open source :>. https://github.com/friedow/dotfiles and plugins: https://github.com/friedow/dotfiles/tree/main/modules/onagre

mmstick commented 11 months ago

Wouldn't it be better for the plugin to store the time, and only give a search result when requested by a search?

friedow commented 11 months ago

Updating data proactively is an explicit design decision I made. I really like the reactive feel of it. The clock plugin is also just a simple example of this. Imagine plugins like system monitors, that show CPU or RAM usage. This is where the concept really shines ;).

I mean, its pretty cool :D onagre (please ignore the horrible theme :D)