Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added statcmd option to run external commands for file stats #1347

Closed
wants to merge 1 commit into from

Conversation

SPFabGerman
Copy link
Contributor

I prefer to run exa for the file stats, since I find it's output more visually appealing than anything I could get with the statfmt option. Until now however, lf had no built in support to do something like that. (I used a workaround by mapping my movement keys to a %-shell command, which would then display the output from exa in the status line. This however did not work flawlessly in all cases and produced some screen flickering in the status line.)

To fix this, I added a new expansion character %C to the statfmt option, that runs the command in the new statcmd option and displays it's output. Therefor I can achieve my desired behaviour by setting statfmt to %C and statcmd to my desired exa command. But this statcmd has much more use cases, for example to display version control info of the current file.

The only downside is, that lf waits for the command to finish, so the user has to ensure that the command finished relatively quickly, as otherwise lf becomes very laggy.

@joelim-work joelim-work self-requested a review July 18, 2023 02:23
Copy link
Collaborator

@joelim-work joelim-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The potential lag from running external commands synchronously every time the UI needs to be updated is a concern. This has actually been discussed before when working on customizing the statfmt (#1288) and ruler (#1257), and in both cases we ended up deciding against providing a hook for an external command.

Just out of interest, does using the on-select hook not work sufficiently for you? Adapted from #1288 (comment):

set statfmt ''

cmd on-select %{{
    exa -ld --color=always "$f"
}}

If not, then we could keep this PR under consideration, but I am sort of hesitant to add a feature that could potentially be problematic, at least not without marking it as experimental.

@SPFabGerman
Copy link
Contributor Author

@joelim-work Thanks for your feedback. Yes the potential lag was also one of my concerns, but I figured the same concern persists with almost every shell based solution. (Like your on-select solution, which also causes lf to hang, if the command takes a long time.)

Thank you for your suggestion with the on-select function. I did not use that solution earlier, since I misunderstood the purpose of the on-select function (I thouhgt it triggered only when I toggle the "selection-state" of a file, not when I just move the cursor). The documentation does not make that entirely clear in my oppinion and could probably be improved. My misuderstanding comes mainly from the fact, that the term "select" is used to reffer to different actions throughout lf. (For example the commands select which moves the cursor and glob-select or unselect which changes the "marked" files.)

The problem with your proposed solution is, that on-select causes some flickering every time I move the cursor, which I find slightly unappealing. It also does not trigger in every case (for example, after a command finishes, where only the normal statfmt is printed).

I was however able to improve your solution to the following (based on the promptfmt and on-cd solution from the documentation):

cmd on-select &{{
    lf -remote "send $id set statfmt \"$(exa -ld --color=always "$f")\""
}}

This works very well in my case and without any problems. (Maybe something like this should be added to the wiki, where it can be found more easily by other people?) I'm fine with this solution, and will therfor close this PR.

@joelim-work
Copy link
Collaborator

@SPFabGerman If there's anything you find unclear about the documentation, you're more than welcome to fix it up and submit a PR.

Anyway I have now added your example config as an integration in the wiki, and hopefully other users will be able to benefit from it. Thanks for your help on this!

@gokcehan
Copy link
Owner

I have nothing useful to add, though I can't help but leave a comment here.

I should say that it was kind of sad to see this discussion. I thought the main purpose of adding statfmt option was to make it possible to customize the status line. It seems that the current functionality was not enough for some users so the mission is failed, at least partially. We already have a somewhat complicated mechanism for the configuration (i.e. with optional fields that I have not seen in another program before), and making it more capable would likely be a breaking change in the future.

@SPFabGerman I'm glad to see you found a solution that works for you, and I hope you don't take offense in me saying this, but I personally find this solution horrifying. Juggling through the list of files could mean spawning hundreds of processes with this solution. At this point, I don't even know why we added a hook for on-select. In most cases, this would act like a mini forkbomb. In the past, people used to switch from ranger to lf for its performance. Nowadays, it seems that they come instead for the features using our terrible design choices to provide similar functionalities.

Anyway, it is just me rambling again as I feel more alienated towards lf every day.

@SPFabGerman
Copy link
Contributor Author

@gokcehan I don't exactly understand what about the solution you find horrifying. Every "feature" that wants to excess external information (information not provided by lf, but instead by an external command) has to rely on spawning shell processes, in some way or another. Therefor every "feature" that wants some external information for potentially every file will spawn a lot of processes, simply by it's very nature. The amount of spawned processes is not really a nature of the specific solution, but inherent to the problem I wanted to solve. The solution I use now is also not really more expansive than my orignal PR (3 vs 2 spawned processes per file).
The only possible solutions that would be more performant (in terms of number of processes spawned) would have to either rely on some kind of background server / daemon that provides the information via sockets / fifos or somehow combining multiple calls of the command into one call and utilising a cache (that would than have to be kept up to date somehow). But both solutions would be totally overengineered for such a simple problem.

Also there are a lot of other things in lf that could act as mini-forkbombs, if configured incorrectly. For example the preview script or (in parts) the on-cd command. Unless you want to strip out every single feature that makes use of shell commands (which would also mean to remove some very essential features) mini-forkbombs will always be a possibility.
I don't think it is (or should be) our (the developers) responsibility to ensure the user does not excedentally introduce a mini-forkbomb into their configuration. How the user configures lf and what impact that configuration has on the performance is ultimatly the users responsibility. All we can do is give the users the tools to make configuring lf in a way they want to as easy as possible, so accidents don't happen easily and are quick to spot.

Also a note on performance: It sounds to me as if you think lf is getting more imperformant. I don't think that is the case. The base configuration of lf (so without additional user configuration) is still very fast and in all my time I have used lf, I never had a performance problem. Even with a lot of user configuration, lf remains very fast. One would have to seriously mess up the configuration to notice a performance impact on lf. We have to keep in mind that lf is a GUI / TUI application, and fast enough that the user does not notice an impact in everyday use (so the programm responds immediatly) is generally good enough performance. Any more improvements are more or less unnecessary, as the user will not notice them anyway.
Also I don't see the problem with user coming to lf for the features it provides. In the end, lf tries to be a file manager for a lot of different users, so there really is not a single good design philosophy, that fits every single use case.

@gokcehan
Copy link
Owner

@SPFabGerman I think there is a big conceptual difference between on-select and on-cd in my mind as I expect the former to be much more frequent than the latter. But to be honest, I forgot all about the previewer mechanism when I said that, which also spawns a process at each selection change, so I guess it invalidates my whole point.

But then again, if there is no problem with spawning a new process to show the status line, why do we bother with statfmt option in the first place? Example with on-select provided here is already working and it is more capable than the statfmt option. Even if we had no statfmt option, one could use the echo command instead:

cmd on-select &{{
    lf -remote "send $id echo \"$(ls -ld --color=always "$f")\""
}}

I'm aware that the behavior with echo is slightly different than statfmt though one could argue it is for the better (i.e. showing the information of the previous file until the command is finished vs showing the default status line). Or maybe instead of statfmt option, why haven't we simply considered a statcmd option as you proposed here with an async implementation? It might have been more consistent with the previewer option (i.e. provide something by default and leave the customization to an external program/script).

@joelim-work
Copy link
Collaborator

@gokcehan statfmt uses the same design as the existing promptfmt and ruler options, which means it inherently has the same set of tradeoffs - in particular, flexibility in configuration is sacrificed in exchange for performance. Although statfmt is currently quite powerful already (it can almost replicate exa if a placeholder for the filename is added), it cannot reasonably satisfy every single user and their (potentially unique) use cases.

I don't think it makes sense to invent a mini-language (as mentioned in #1282 (reply in thread)) just to customize statfmt, so if we really want to allow for unlimited customization, then the only reasonable solution would be to delegate this behavior to an external program/script. The reason why I did not choose this approach initially was because of concerns about performance and process creation - this has been mentioned before in comments like #112 (comment), and even you mentioned it yourself in #1347 (comment).

I wouldn't mind revisiting this as it's my fault statfmt exists, but we still need a way to implement set statfmt '' or somehow prevent the stat info from being drawn. Simply calling echo in on-select as shown above will mean that the stat info is being displayed for a short amount of time before being replaced, which creates a noticeable flicker.

Please let me know what you would prefer, I would like to address this issue before too many people find out about statfmt, and certainly before a new release is made.

@joelim-work
Copy link
Collaborator

BTW I was playing around with this a bit more, a naive implementation of statcmd would look something like this:

func (ui *ui) loadFileInfo(nav *nav) {
	if !nav.init {
		return
	}

	if gOpts.statcmd != "" {
		nav.exportFiles()
		ui.exportSizes()
		exportOpts()
		cmd := shellCommand(gOpts.statcmd, nil)
		go func() {
			out, err := cmd.Output()
			if err != nil {
				ui.echoerrf("statcmd: %s", err)
				return
			}
			ui.exprChan <- &callExpr{"echo", []string{string(out)}, 1}
		}()
		return
	}

	// default implementation below
}

This appears to work fine in practice, but theoretically there's a race condition when previewing multiple files in succession, where the thread that finishes last will have its output prevail. The on-select hook would also have the same problem.

We might have to instead implement this as a separate thread listening over a channel for updates, similar to what is done for custom previews.

@joelim-work
Copy link
Collaborator

OK so I wrote a basic implementation for a statcmd thread, based off commit 59f3219 (just before statfmt was added):

Click to show diff
diff --git a/app.go b/app.go
index 57936b4..72e620b 100644
--- a/app.go
+++ b/app.go
@@ -243,6 +243,7 @@ func (app *app) writeHistory() error {
 func (app *app) loop() {
 	go app.nav.previewLoop(app.ui)
 	go app.nav.dirPreviewLoop(app.ui)
+	go app.ui.statLoop()
 
 	var serverChan <-chan expr
 	if !gSingleMode {
diff --git a/complete.go b/complete.go
index 024da3a..a57fcdf 100644
--- a/complete.go
+++ b/complete.go
@@ -211,6 +211,7 @@ var (
 		"shellflag",
 		"shellopts",
 		"sortby",
+		"statcmd",
 		"timefmt",
 		"tempmarks",
 		"tagfmt",
diff --git a/eval.go b/eval.go
index 863d4f0..cdddda1 100644
--- a/eval.go
+++ b/eval.go
@@ -801,6 +801,8 @@ func (e *setExpr) eval(app *app, args []string) {
 		}
 		app.nav.sort()
 		app.ui.sort()
+	case "statcmd":
+		gOpts.statcmd = e.val
 	case "tabstop":
 		n, err := strconv.Atoi(e.val)
 		if err != nil {
diff --git a/opts.go b/opts.go
index 58c1532..f092de2 100644
--- a/opts.go
+++ b/opts.go
@@ -67,6 +67,7 @@ var gOpts struct {
 	selmode          string
 	shell            string
 	shellflag        string
+	statcmd          string
 	timefmt          string
 	infotimefmtnew   string
 	infotimefmtold   string
@@ -128,6 +129,7 @@ func init() {
 	gOpts.selmode = "all"
 	gOpts.shell = gDefaultShell
 	gOpts.shellflag = gDefaultShellFlag
+	gOpts.statcmd = ""
 	gOpts.timefmt = time.ANSIC
 	gOpts.infotimefmtnew = "Jan _2 15:04"
 	gOpts.infotimefmtold = "Jan _2  2006"
diff --git a/ui.go b/ui.go
index 1f8af2c..6299fe3 100644
--- a/ui.go
+++ b/ui.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"sort"
 	"strconv"
@@ -553,6 +554,11 @@ func getWins(screen tcell.Screen) []*win {
 	return wins
 }
 
+type statChanMsg struct {
+	cmd  string
+	path string
+}
+
 type ui struct {
 	screen      tcell.Screen
 	polling     bool
@@ -567,6 +573,7 @@ type ui struct {
 	keyChan     chan string
 	tevChan     chan tcell.Event
 	evChan      chan tcell.Event
+	statChan    chan statChanMsg
 	menuBuf     *bytes.Buffer
 	cmdPrefix   string
 	cmdAccLeft  []rune
@@ -594,6 +601,7 @@ func newUI(screen tcell.Screen) *ui {
 		keyChan:     make(chan string, 1000),
 		tevChan:     make(chan tcell.Event, 1000),
 		evChan:      make(chan tcell.Event, 1000),
+		statChan:    make(chan statChanMsg, 1000),
 		styles:      parseStyles(),
 		icons:       parseIcons(),
 		currentFile: "",
@@ -722,6 +730,11 @@ func (ui *ui) loadFileInfo(nav *nav) {
 		return
 	}
 
+	if gOpts.statcmd != "" {
+		ui.statChan <- statChanMsg{gOpts.statcmd, curr.path}
+		return
+	}
+
 	var linkTarget string
 	if curr.linkTarget != "" {
 		linkTarget = " -> " + curr.linkTarget
@@ -737,6 +750,25 @@ func (ui *ui) loadFileInfo(nav *nav) {
 		linkTarget)
 }
 
+func (ui *ui) statLoop() {
+	for msg := range ui.statChan {
+	loop:
+		for {
+			select {
+			case msg = <-ui.statChan:
+			default:
+				break loop
+			}
+		}
+		out, err := exec.Command(msg.cmd, msg.path).Output()
+		if err != nil {
+			ui.echoerrf("statcmd: %s", err)
+			continue
+		}
+		ui.exprChan <- &callExpr{"echo", []string{string(out)}, 1}
+	}
+}
+
 func (ui *ui) drawPromptLine(nav *nav) {
 	st := tcell.StyleDefault

lfrc:

set statcmd lfstatcmd

lfstatcmd:

#!/bin/sh

exa -ld --color=always "$1"

It looks like exa is sufficiently fast enough that I don't notice any kind of delay. @SPFabGerman you're welcome to try it out.

I will also re-open this PR for the time being as this discussion is still in progress.

@joelim-work joelim-work reopened this Jul 23, 2023
@gokcehan
Copy link
Owner

@joelim-work Sorry for pinging you with this and thanks for having a look at it again. I tried your patch and it seems to work well without any performance issues. There could be a race as you mention but I haven't encountered myself. Maybe the proper way to handle this could be to implement something like the previewer mechanism though it might be an overkill for this. It would also require dealing with the outdated information and I expect there will still be complaints no matter what mechanism we have (e.g. flicker with a loading or empty message vs show outdated information).

To be honest, I was just rambling for no reason so don't take me too seriously. Feel free to decide what to do about this yourself. The best option might just be to leave this as it is since there is no real issue here. In retrospect, I should have hold myself to drop a comment since it does not effect me in any way. At this point, I haven't really worked on anything for months so I don't deserve giving feedback. There is certainly not a "fault" in here as you expressed it and we all appreciate your involvement in the project.

@joelim-work
Copy link
Collaborator

@gokcehan On the contrary, I appreciate your feedback very much - even if the feedback is negative, provided that it is truthful and constructive, I would prefer it over feedback that is positive but skates over potential problems. Actually, the approach of not commenting just because it "does not affect me in any way" can lead to degrading the quality of the project in the long term, especially if contributors continue to work on features for their own benefit without considering how it fits into the overall design.

In particular with this PR, the suggestion of providing an additional statcmd option to enhance the existing statfmt option does not feel like a good design decision to me, and instead I see it as a workaround to deal with the limitations of the existing design.

You are correct that the intention of statfmt is so that users would simply be able to supply a single static value, and not have to override it dynamically using methods like on-select. By nature, this kind of approach can only cater for common use cases, at the expense of users who wish to implement custom logic to satisfy their own niche preferences (e.g. different colors for permission flags like exa, displaying a different format for certain types of files, the list goes on). The problem is that when I make such a decision, there's no way for me to effectively gauge how well the feature is received - there may be 1000 users that are satisfied, or there may be none, but only users that actually have complaints will provide any feedback at all.


On the topic of race conditions, if you press j and scroll through the files, a process will be spawned for each file. Not only is this inefficient, it also means that whichever process finishes last will have its output prevail. This can be simulated very easily by adding a random sleep to your example:

cmd on-select &{{
    sleep $((RANDOM % 5))
    lf -remote "send $id echo \"$(ls -ld --color=always "$f")\""
}}

You are correct that it would be better to implement this in a way similar to the previewer, which is what I have already done in #1347 (comment).


Given that statfmt is still a very new feature and hasn't officially been released, I am leaning towards scrapping it in favor of just having statcmd, where users will have virtually unlimited power to customize the stat info. For users that don't like exa, the stat command also be used to generate output (with the help of numfmt and date for custom formatting) - below is an example that practically equivalent to the default behavior:

#!/bin/sh

if target=$(readlink "$1"); then
    set "$target"
    target="-> $target"
fi

size=$(numfmt --to=si --round=down "$(stat -c '%s' "$1")")
time=$(date -d @"$(stat -c '%Y' "$1")" '+%a %b %e %X %Y')
stat -c "%A %h %U %G $size $time $target" "$1"

Delegating the customization to an external command would also solve other issues like #1098 (use binary sizes instead of metric sizes), and even render the timefmt obsolete, though it is probably too late to remove it.

@SPFabGerman What are your thoughts on this? I'm not sure who else to ping regarding this, but the more feedback I get the better.

@gokcehan
Copy link
Owner

@joelim-work I have taken a look at the patch again and I understand how it works now. Everything seems to be ordered properly using the channel so I don't see any race here. Not only that, but I also see how it avoids running redundant processes, which is very nice. 👏

Just to ping a few more people in case they are interested in the discussion:

@Lassebq as the most recent proposer of this feature in #1282

@tex and @og900aero as the participants of discussion in #1330 (If I'm not mistaken, @og900aero 's final comment led to the optional field patch in #1337).

@SPFabGerman
Copy link
Contributor Author

@joelim-work Sorry for the late reply, but I was somewhat busy today. I have tried out your suggested patch and have also noticed no drawbacks. As far as I can tell, it works very much like my own original PR, just utilising background processes instead. I was very supprised that I did not notice any kind of flickering. (That concern was the main reason I originally used a syncronous approach, rather than an asyncronous one.)

The main concern that I have with removing the statfmt option in favor of statcmd is that it makes the configuration a lot more complicated. Especially if you are (unlike me) only interested in some small adjustments to the default. The need to have an additional script to do any kind of configuration (even just small color adjustments) seems very overblown to me. Maybe this can be somewhat compensated by allowing the statcmd option to have more complex commands, so that you for example can pass the exa command directly to statcmd instead of using a script. (I achieved that by using the shellCommand function, which already takes care of all the necessary parsing. I recommend we do the same here.)

Though I have to admit I don't really see the practical benefit for your solution compared to the on-select solution. It is essentially using the same design as the on-cd and promptfmt solution for custom prompts that we have been using for a long time now (possibly a few years?) and (as far as I can tell) that has never been a problem or a cause for concern or debate. If that is not a problematic solution, than why is the combination of on-select and statfmt? If we want to improve the statfmt / statcmd solution we should probably think of a solution that can be applied to promptfmt (and possibly other things?) too. In my opinion, the current solution is a very good middle ground: we have the simple statfmt that allows easy customization for users who only want small changes; but that can nonetheless be easily enhanced with the on-select command for more advanced use cases (like mine). That seems to me like it is offering the best of both worlds. Though I have to admit that possible race conditions are a concern that we should think about. (Though I believe such race conditions should rarely happen in practice, since we only spawn commands as fast as we can scroll anyway and that alone does not seem fast enough to cause race conditions for fast running commands like exa.)

@tex
Copy link

tex commented Jul 24, 2023

on-select doesn't work on last file in list...

@joelim-work
Copy link
Collaborator

@SPFabGerman You do raise a good point about statcmd making the configuration more complicated for simple use cases. To me this resembles the typical tradeoff between high-level and low-level designs.

  • statfmt is a high-level configuration design where users can conveniently write out the desired format, and lf provides support for substituting all the placeholders and dealing with optional fields. It works well for simple use cases like coloring certain fields, but is also limited to the model provided by lf - any kind of customization outside of that is practically impossible to achieve. This kind of design makes configuration easy for the majority of users with simple use cases, but does not satisfy users with more advanced use cases.
  • statcmd is a low-level configuration design where users can implement any kind of desired logic using a shell script, but there is no longer the convenience of writing the configuration as a single string with placeholders to be filled in by lf. This kind of design can satisfy all users, at the cost of making the configuration process somewhat cumbersome (much like image previews).

It's also possible to have a hybrid design (e.g. statfmt combined with on-select), which can satisfy both basic and advanced use cases, but this ends up with additional maintenance burden if we have to support both approaches, and also conflicts with the design goal of lf being a minimalistic program (I don't even know if this is still true, but I would prefer to keep this mindset).

To be clear, I don't have a strong opinion on any of the solutions. To me they all have pros and cons, and I think it's not possible to satisfy everyone including both users and maintainers.


Regarding on-select, it does appear to work just as well as statcmd on the surface. Although race conditions are proven to be a possibility (e.g. by adding a random sleep), I agree that it is unlikely to happen in practice since exa runs quite fast. However, I have also found that on-select may not be a perfect substitute, as it is only called when the cursor moves to a different file. This means that the custom statline will not be shown for all the cases where loadFileInfo is called, but loadFile is either not called or the current file hasn't changed, for example entering a command on the command line like set number.

Because of the differences in timing between loadFileInfo and on-select, I'm not entirely sure whether it's a good idea to continue recommending the use of on-select here, or to provide statcmd or similar which will actually hook from the loadFileInfo function. For reference, on-select was added in #864 just over a year ago - it looks like the use case was to update some kind of external preview and had nothing to do with the statline.


It is also good that you mentioned promptfmt here as well. TBH I'm not sure why there has been less discussion/issues about promptfmt, although perhaps it's because most users only require simple use cases (selecting certain fields and adding some color), and anything complex like displaying the Git branch can be handled by dynamically setting promptfmt as shown in the documentation. I guess it's also worth mentioning that the distinction where the prompt does not get wiped out by anything else, whereas the statline does because it has to share the space with the command line and error messages.

I was also surprised that there hasn't been much requests for customizing the ruler, but that might just be because it's a relatively new feature and not many users are aware of it, or maybe the default setting is already very good.

Either way, I'm not sure whether it's worth considering the design of promptfmt or ruler now. There hasn't been much issues from users lately about these options, and furthermore they work differently to statfmt in terms of timing, as they are evaluated when drawing everything at the end of the event loop, and not whenever loadFileInfo is called.

@tex
Copy link

tex commented Jul 25, 2023

Thanks for mentioning the ruler. I am 100% satisfied with user variable and rule with lf_

set ruler acc:progress:filter:ind:selection:lf_user_selected_size
cmd on-select &{{
    s=$(find $fx -type f -maxdepth 1 -ls | awk '{total += $7} END {print total}' | numfmt --to=iec --format='%.2fB')
    lf -remote "send set user_selected_size $s"
}}

map <space> :toggle; on-select; down;
map v :invert; on-select;

@og900aero
Copy link

Thanks for mentioning the ruler. I am 100% satisfied with user variable and rule with lf_

set ruler acc:progress:filter:ind:selection:lf_user_selected_size
cmd on-select &{{
    s=$(find $fx -type f -maxdepth 1 -ls | awk '{total += $7} END {print total}' | numfmt --to=iec --format='%.2fB')
    lf -remote "send set user_selected_size $s"
}}

map <space> :toggle; on-select; down;
map v :invert; on-select;

Its not bad, but doesnt good for directory.
Its better for directory and files to in my opinion:
s=$(du -ch $fx | tail -n 1 | cut -f 1)

@tex
Copy link

tex commented Jul 26, 2023

Thanks for mentioning the ruler. I am 100% satisfied with user variable and rule with lf_

set ruler acc:progress:filter:ind:selection:lf_user_selected_size
cmd on-select &{{
    s=$(find $fx -type f -maxdepth 1 -ls | awk '{total += $7} END {print total}' | numfmt --to=iec --format='%.2fB')
    lf -remote "send set user_selected_size $s"
}}

map <space> :toggle; on-select; down;
map v :invert; on-select;

Its not bad, but doesnt good for directory. Its better for directory and files to in my opinion: s=$(du -ch $fx | tail -n 1 | cut -f 1)

That is on purpose. I often browse a network folders (nfs or sshfs) and I do not want to be slowed down just because I move cursor over some folder (deep folder, many files, it would take ages to compute the sizes). It is kind of balance between usability and slowness.

(but I found now that du supports maxdepth so I could avoid use of awk and numfmt)

@og900aero
Copy link

Thanks for mentioning the ruler. I am 100% satisfied with user variable and rule with lf_

set ruler acc:progress:filter:ind:selection:lf_user_selected_size
cmd on-select &{{
    s=$(find $fx -type f -maxdepth 1 -ls | awk '{total += $7} END {print total}' | numfmt --to=iec --format='%.2fB')
    lf -remote "send set user_selected_size $s"
}}

map <space> :toggle; on-select; down;
map v :invert; on-select;

Its not bad, but doesnt good for directory. Its better for directory and files to in my opinion: s=$(du -ch $fx | tail -n 1 | cut -f 1)

That is on purpose. I often browse a network folders (nfs or sshfs) and I do not want to be slowed down just because I move cursor over some folder (deep folder, many files, it would take ages to compute the sizes). It is kind of balance between usability and slowness.

(but I found now that du supports maxdepth so I could avoid use of awk and numfmt)

Of course. U can use maxdepth with du. But anyway, the fact is that I only use the code I entered when I select a folder or file, because anyway I see the size of the file by default during browsing

@gokcehan
Copy link
Owner

It's also possible to have a hybrid design (e.g. statfmt combined with on-select), which can satisfy both basic and advanced use cases, but this ends up with additional maintenance burden if we have to support both approaches, and also conflicts with the design goal of lf being a minimalistic program (I don't even know if this is still true, but I would prefer to keep this mindset).

@joelim-work I think maybe you meant statfmt combined with statcmd. In any case, I think I agree it might be too much for lf. I guess the general consensus here (including me at this point) seems to be in favor of keeping the current behavior so feel free to close this PR if you like. Thank you again for working through the alternatives.

@joelim-work joelim-work closed this Aug 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants