Repository: dundee/gdu
Pull request #230 (2023-03-18 10:43:35)

implement #229 always (try to) change directory
tried to implement #229 always (try to) change directory

codecov[bot]: ## [Codecov](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde) Report
Patch coverage: **`100.00`**% and project coverage change: **`-0.23`** :warning:
> Comparison is base [(`5475655`)](https://codecov.io/gh/dundee/gdu/commit/5475655f0c901b40ce04abd1d6e2b824026aca90?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde) 94.10% compared to head [(`9905bbc`)](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde) 93.88%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #230      +/-   ##
==========================================
- Coverage   94.10%   93.88%   -0.23%     
==========================================
  Files          29       29              
  Lines        2733     2746      +13     
==========================================
+ Hits         2572     2578       +6     
- Misses        123      128       +5     
- Partials       38       40       +2     
```


| [Impacted Files](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde) | Coverage Δ | |
|---|---|---|
| [cmd/gdu/app/app.go](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde#diff-Y21kL2dkdS9hcHAvYXBwLmdv) | `91.97% <100.00%> (+0.17%)` | :arrow_up: |
| [tui/show.go](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde#diff-dHVpL3Nob3cuZ28=) | `98.50% <100.00%> (+0.05%)` | :arrow_up: |
| [tui/tui.go](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde#diff-dHVpL3R1aS5nbw==) | `90.90% <100.00%> (+0.09%)` | :arrow_up: |

... and [1 file with indirect coverage changes](https://codecov.io/gh/dundee/gdu/pull/230/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde)

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde)

</details>

[:umbrella: View full report in Codecov by Sentry](https://codecov.io/gh/dundee/gdu/pull/230?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Daniel+Milde).


Patch:
diff --git a/README.md b/README.md
index f29b4f7..07eb99b 100644
--- a/README.md
+++ b/README.md
@@ -159,7 +159,7 @@ Gdu can read (and write) YAML configuration file.
 * To configure gdu to permanently run in gray-scale color mode:
 
 ```
-echo "no-color: true" > ~/.gdu.yaml
+echo "no-color: true" >> ~/.gdu.yaml
 ```
 
 * To set default sorting in configuration file:
@@ -170,6 +170,12 @@ sorting:
     order: desc
 ```
 
+* To configure gdu to set CWD variable when browsing directories:
+
+```
+echo "change-cwd: true" >> ~/.gdu.yaml
+```
+
 * To save the current configuration
 
 ```
diff --git a/cmd/gdu/app/app.go b/cmd/gdu/app/app.go
index 63afcd8..445d667 100644
--- a/cmd/gdu/app/app.go
+++ b/cmd/gdu/app/app.go
@@ -65,6 +65,7 @@ type Flags struct {
 	UseSIPrefix       bool     `yaml:"use-si-prefix"`
 	NoPrefix          bool     `yaml:"no-prefix"`
 	WriteConfig       bool     `yaml:"-"`
+	ChangeCwd         bool     `yaml:"change-cwd"`
 	Style             Style    `yaml:"style"`
 	Sorting           Sorting  `yaml:"sorting"`
 }
@@ -240,6 +241,11 @@ func (a *App) createUI() (UI, error) {
 				ui.SetDefaultSorting(a.Flags.Sorting.By, a.Flags.Sorting.Order)
 			})
 		}
+		if a.Flags.ChangeCwd != false {
+			opts = append(opts, func(ui *tui.UI) {
+				ui.SetChangeCwdFn(os.Chdir)
+			})
+		}
 
 		ui = tui.CreateUI(
 			a.TermApp,
diff --git a/tui/show.go b/tui/show.go
index a896940..7dcbd8c 100644
--- a/tui/show.go
+++ b/tui/show.go
@@ -4,9 +4,11 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/dundee/gdu/v5/build"
 	"github.com/gdamore/tcell/v2"
 	"github.com/rivo/tview"
+	log "github.com/sirupsen/logrus"
+
+	"github.com/dundee/gdu/v5/build"
 )
 
 const helpText = `     [::b]up/down, k/j    [white:black:-]Move cursor up/down
@@ -48,6 +50,15 @@ func (ui *UI) showDir() {
 	)
 
 	ui.currentDirPath = ui.currentDir.GetPath()
+
+	if ui.changeCwdFn != nil {
+		err := ui.changeCwdFn(ui.currentDirPath)
+		if err != nil {
+			log.Printf("error setting cwd: %s", err.Error())
+		}
+		log.Printf("changing cwd to %s", ui.currentDirPath)
+	}
+
 	ui.currentDirLabel.SetText("[::b] --- " +
 		tview.Escape(
 			strings.TrimPrefix(ui.currentDirPath, build.RootPathPrefix),
diff --git a/tui/tui.go b/tui/tui.go
index d82379f..a2186eb 100644
--- a/tui/tui.go
+++ b/tui/tui.go
@@ -45,6 +45,7 @@ type UI struct {
 	emptier                 func(fs.Item, fs.Item) error
 	getter                  device.DevicesInfoGetter
 	exec                    func(argv0 string, argv []string, envv []string) error
+	changeCwdFn             func(string) error
 	linkedItems             fs.HardLinkedItems
 	selectedTextColor       tcell.Color
 	selectedBackgroundColor tcell.Color
@@ -179,6 +180,12 @@ func (ui *UI) SetCurrentItemNameMaxLen(len int) {
 	ui.currentItemNameMaxLen = len
 }
 
+// SetChangeCwdFn sets function that can be used to change current working dir
+// during dir browsing
+func (ui *UI) SetChangeCwdFn(fn func(string) error) {
+	ui.changeCwdFn = fn
+}
+
 // StartUILoop starts tview application
 func (ui *UI) StartUILoop() error {
 	return ui.app.Run()


Test patch:
diff --git a/cmd/gdu/app/app_test.go b/cmd/gdu/app/app_test.go
index 947f453..2aa5cf1 100644
--- a/cmd/gdu/app/app_test.go
+++ b/cmd/gdu/app/app_test.go
@@ -214,6 +214,24 @@ func TestAnalyzePathWithExport(t *testing.T) {
 	assert.Nil(t, err)
 }
 
+func TestAnalyzePathWithChdir(t *testing.T) {
+	fin := testdir.CreateTestDir()
+	defer fin()
+
+	out, err := runApp(
+		&Flags{
+			LogFile:   "/dev/null",
+			ChangeCwd: true,
+		},
+		[]string{"test_dir"},
+		true,
+		testdev.DevicesInfoGetterMock{},
+	)
+
+	assert.Empty(t, out)
+	assert.Nil(t, err)
+}
+
 func TestReadAnalysisFromFile(t *testing.T) {
 	out, err := runApp(
 		&Flags{LogFile: "/dev/null", InputFile: "../../../internal/testdata/test.json"},
diff --git a/tui/actions_test.go b/tui/actions_test.go
index 325c71f..86e82fc 100644
--- a/tui/actions_test.go
+++ b/tui/actions_test.go
@@ -2,6 +2,7 @@ package tui
 
 import (
 	"bytes"
+	"errors"
 	"os"
 	"testing"
 
@@ -271,6 +272,76 @@ func TestViewFile(t *testing.T) {
 	assert.Equal(t, 'j', event.Rune())
 }
 
+func TestChangeCwd(t *testing.T) {
+	fin := testdir.CreateTestDir()
+	defer fin()
+	simScreen := testapp.CreateSimScreen(50, 50)
+	defer simScreen.Fini()
+	cwd := ""
+
+	opt := func(ui *UI) {
+		ui.SetChangeCwdFn(func(p string) error {
+			cwd = p
+			return nil
+		})
+	}
+	app := testapp.CreateMockedApp(true)
+	ui := CreateUI(app, simScreen, &bytes.Buffer{}, false, true, false, false, false, opt)
+	ui.done = make(chan struct{})
+	err := ui.AnalyzePath("test_dir", nil)
+	assert.Nil(t, err)
+
+	<-ui.done // wait for analyzer
+
+	for _, f := range ui.app.(*testapp.MockedApp).GetUpdateDraws() {
+		f()
+	}
+
+	assert.Equal(t, "test_dir", ui.currentDir.GetName())
+
+	ui.table.Select(0, 0)
+	ui.keyPressed(tcell.NewEventKey(tcell.KeyRight, 'l', 0))
+	ui.table.Select(1, 0)
+	ui.keyPressed(tcell.NewEventKey(tcell.KeyRight, 'l', 0))
+
+	assert.Equal(t, cwd, "test_dir/nested/subnested")
+}
+
+func TestChangeCwdWithErr(t *testing.T) {
+	fin := testdir.CreateTestDir()
+	defer fin()
+	simScreen := testapp.CreateSimScreen(50, 50)
+	defer simScreen.Fini()
+	cwd := ""
+
+	opt := func(ui *UI) {
+		ui.SetChangeCwdFn(func(p string) error {
+			cwd = p
+			return errors.New("failed")
+		})
+	}
+	app := testapp.CreateMockedApp(true)
+	ui := CreateUI(app, simScreen, &bytes.Buffer{}, false, true, false, false, false, opt)
+	ui.done = make(chan struct{})
+	err := ui.AnalyzePath("test_dir", nil)
+	assert.Nil(t, err)
+
+	<-ui.done // wait for analyzer
+
+	for _, f := range ui.app.(*testapp.MockedApp).GetUpdateDraws() {
+		f()
+	}
+
+	assert.Equal(t, "test_dir", ui.currentDir.GetName())
+
+	ui.table.Select(0, 0)
+	ui.keyPressed(tcell.NewEventKey(tcell.KeyRight, 'l', 0))
+	ui.table.Select(1, 0)
+	ui.keyPressed(tcell.NewEventKey(tcell.KeyRight, 'l', 0))
+
+	assert.Equal(t, cwd, "test_dir/nested/subnested")
+}
+
 func TestShowInfo(t *testing.T) {
 	fin := testdir.CreateTestDir()
 	defer fin()