HN user

alexpasmantier

28 karma
Posts7
Comments18
View on HN
[dead] 1 year ago

tv is a cross-platform, fast and extensible fuzzy finder for the terminal.

What's changing:

    Revamped channels: config, templating, shortcuts, live-reload

    Major CLI upgrades: layout flags, keybindings, previews, --watch

    UI polish: new status bar, portrait mode, inline mode, scrollbars

    Shell support: nushell, better completions, inline usage

    Other: mouse support, better testing, perf boost, bug fixes
Full notes: https://alexpasmantier.github.io/television/docs/Developers/...

I believe this is just a matter of framerate. You may increase it to make those jumps invisible to the human eye ('tv --frame-rate xx') but that inevitably comes with a cost in terms of cpu usage which tv tries to keep at a minimum.

This is primarily a matter of which tradeoff suits most users I guess :-)

Television is designed with a "framework-like" approach in mind. Here’s what makes it easy to extend (in a nutshell):

- Custom Cable Channels: You’re not limited to the built-in channels. You can create your own "cable channels"—essentially custom data sources—by tweaking a simple config file. As the project grows, the vision is for users to contribute their own channel recipes to the wiki, making it easy for others to pick and choose what suits their needs.

- Smart Shell Integration: Television integrates seamlessly with your shell, offering features like smart autocomplete and interactive piping of results. It’s also fully customizable, so you can tweak the smart autocomplete behavior or other features to match your workflow.

- Coming Soon: User-definable custom actions within cable channel recipes for an even more streamlined and tailored experience.

This probably doesn’t answer everything, but I’d be happy to dive into more details about any of the points above! :-)

tv isn’t intended to be a direct competitor to fzf, but since the two share similarities, here’s a quick breakdown of how tv differs:

- Batteries-included experience: tv is designed to work out of the box, with minimal setup.

- Smart shell integration: Autocomplete intelligently selects the right source for you.

- Interactive data source switching: You can change the data source on the fly without exiting the application.

- Centralized configuration: All settings are managed in one place, eliminating the need for custom shell scripts.

- Transitions feature: Enables interactive piping of results through multiple steps (e.g., git-repos > files > textual content in files).

- Built-in syntax-highlighted previews: More robust and integrated compared to configuring something like fzf --preview 'bat -n --color=always {0}'.

That said, tv is still an early-stage project (while fzf has been evolving for over 11 years). I’m also planning to draw inspiration from some of fzf’s excellent features in the future.

Author here—thanks for trying out tv and for sharing your feedback, I really appreciate it.

The preview window in tv is designed to compute its content asynchronously. This approach ensures smooth input handling and maintains overall UI responsiveness. You can test this yourself by using a custom preview command that simulates a delay, like so:

  tv --preview "sleep 1 && echo 'the preview'"
You'll notice that even with a delay, the UI remains responsive and doesn't block.

That said, I'm sure there's always room for improvement, and I'd be happy to hear your thoughts or suggestions if you're open to discussing it further.

[dead] 2 years ago

Seeking curious testers and enthusiastic contributors! :-)

Looking at inode metadata—specifically the number of links for directory nodes—might iteratively provide a one-step-ahead view of what's left to crawl, allowing for preemptive thread adjustments during recursion.

e.g. looking at the Links: 101 metadata on the `curl` codebase for src:

  $ stat -x src
  
    File: "src"
    Size: 3232         FileType: Directory
    Mode: (0755/drwxr-xr-x)         Uid: (  501/    alex)  Gid: (   20/   staff)
  Device: 1,22   Inode: 5857579    Links: 101
  Access: Tue Aug 27 22:21:23 2024
  Modify: Tue Aug 27 22:21:19 2024
  Change: Tue Aug 27 22:21:19 2024
   Birth: Tue Aug 27 22:21:19 2024
But then that still involves dynamically adjusting and might be kind of overkill for a relatively uncertain benefit...

Ahh! Great catch, and thanks for taking the time to put that in writing.

I did set gg to default to 4 threads, which seemed to be the optimal number on my machine for the typical repo sizes I navigate daily. Increasing the number of threads beyond that often results in unnecessary overhead for my personal use cases.

I appreciate you pointing out the heuristic used in the ripgrep project. From what I understand, it also uses a fixed, machine-dependent number of threads, predetermined regardless of the task at hand (except for single-file tasks).

This is something I was curious about while writing the code but couldn't fully answer due to my limited knowledge of the subject: could we potentially use a filesystem-specific heuristic to estimate the workload and dynamically adjust the number of threads accordingly?

What I mean is a method, perhaps within the ignore crate, to estimate the amount of data to process—such as the number of files, file sizes, or number of lines—based on easily and cheaply accessible filesystem metadata.

Posting this here as well for reference https://news.ycombinator.com/item?id=41380671

@burntsushi

Hi! First of all, thank you for taking the time to write this. I've been using ripgrep for quite some time, and it's an amazing piece of software. Having your comment here is truly an honor.

I'm not sure I totally get the motivation here to be honest

This is primarily a small project I started to familiarize myself with Rust. I thought that exploring the basics of ripgrep and attempting to build something similar would be a good way to get started.

Also, the flags that it does support are overriding long-held custom that are likely to be confusing to users

Noted. I'll consider making these changes to avoid potentially confusing anyone.

It's also pretty annoying to share screenshots of benchmarks instead of just showing a simple copyable command with a paste of the results.

I've updated the documentation with the actual commands and included a copy of the results.

I also can't quite reproduce at least the curl benchmark

I just ran the curl benchmark again on the same machine (my work laptop, an M3 Apple MacBook), and here are the results:

  $ hyperfine "rg '[A-Z]+_NOBODY' ." "gg '[A-Z]+_NOBODY'" "ggrep -rE '[A-Z]+_NOBODY' ."

  Benchmark 1: rg '[A-Z]+_NOBODY' .
     Time (mean ± σ):      38.5 ms ±   2.2 ms    [User: 18.1 ms, System: 207.3 ms]
     Range (min … max):    33.8 ms …  42.8 ms    72 runs
  
  Benchmark 2: gg '[A-Z]+_NOBODY'
     Time (mean ± σ):      21.8 ms ±   0.8 ms    [User: 15.4 ms, System: 53.1 ms]
     Range (min … max):    20.2 ms …  23.8 ms    115 runs
  
  Benchmark 3: ggrep -rE '[A-Z]+_NOBODY' .
     Time (mean ± σ):      73.3 ms ±   0.9 ms    [User: 26.5 ms, System: 45.7 ms]
     Range (min … max):    70.8 ms …  75.6 ms    41 runs
  
  Summary
     gg '[A-Z]+_NOBODY' ran
       1.77 ± 0.12 times faster than rg '[A-Z]+_NOBODY' .
       3.36 ± 0.13 times faster than ggrep -rE '[A-Z]+_NOBODY' .
> It looks like it's assuming that the `ArrayQueue` it uses is never full?

I used a default maximum size for the queue (configurable via the --max-results argument) to pre-allocate it, as I thought this might improve performance. However, I'm currently not handling errors properly and just allowing the program to panic when the number of results exceeds the set limit.

So why doesn't it have the same performance profile as ripgrep?

Given the differences in execution times between our benchmarks, I suspect that because ripgrep's (and, by extension, gg's) performance bottleneck is primarily disk I/O, variations in filesystems and underlying storage hardware could explain the significantly different results we're observing. What do you think?

@burntsushi

Hi! First of all, thank you for taking the time to write this. I've been using ripgrep for quite some time, and it's an amazing piece of software. Having your comment here is truly an honor.

I'm not sure I totally get the motivation here to be honest

This is primarily a small project I started to familiarize myself with Rust. I thought that exploring the basics of ripgrep and attempting to build something similar would be a good way to get started.

Also, the flags that it does support are overriding long-held custom that are likely to be confusing to users

Noted. I'll consider making these changes to avoid potentially confusing anyone.

It's also pretty annoying to share screenshots of benchmarks instead of just showing a simple copyable command with a paste of the results.

I've updated the documentation with the actual commands and included a copy of the results.

I also can't quite reproduce at least the curl benchmark

I just ran the curl benchmark again on the same machine (my work laptop, an M3 Apple MacBook), and here are the results:

  $ hyperfine "rg '[A-Z]+_NOBODY' ." "gg '[A-Z]+_NOBODY'" "ggrep -rE '[A-Z]+_NOBODY' ."

  Benchmark 1: rg '[A-Z]+_NOBODY' .
     Time (mean ± σ):      38.5 ms ±   2.2 ms    [User: 18.1 ms, System: 207.3 ms]
     Range (min … max):    33.8 ms …  42.8 ms    72 runs
  
  Benchmark 2: gg '[A-Z]+_NOBODY'
     Time (mean ± σ):      21.8 ms ±   0.8 ms    [User: 15.4 ms, System: 53.1 ms]
     Range (min … max):    20.2 ms …  23.8 ms    115 runs
  
  Benchmark 3: ggrep -rE '[A-Z]+_NOBODY' .
     Time (mean ± σ):      73.3 ms ±   0.9 ms    [User: 26.5 ms, System: 45.7 ms]
     Range (min … max):    70.8 ms …  75.6 ms    41 runs
  
  Summary
     gg '[A-Z]+_NOBODY' ran
       1.77 ± 0.12 times faster than rg '[A-Z]+_NOBODY' .
       3.36 ± 0.13 times faster than ggrep -rE '[A-Z]+_NOBODY' .
> It looks like it's assuming that the `ArrayQueue` it uses is never full?

I used a default maximum size for the queue (configurable via the --max-results argument) to pre-allocate it, as I thought this might improve performance. However, I'm currently not handling errors properly and just allowing the program to panic when the number of results exceeds the set limit.

So why doesn't it have the same performance profile as ripgrep?

Given the differences in execution times between our benchmarks, I suspect that because ripgrep's (and, by extension, gg's) performance bottleneck is primarily disk I/O, variations in filesystems and underlying storage hardware could explain the significantly different results we're observing. What do you think?