Repository: gohugoio/hugo (language: go)

Issue:
For Hugo server command, always add server address at end of output for convenience
When you start the Hugo server you see this output in the terminal:

```
Environment: "development"
Serving pages from disk
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1) 
Press Ctrl+C to stop
```

Command clicking `http://localhost:1313/` (on macOS) open the address in a new browser tab.

You then work on the site and the terminal will show a lot of output. The server address is soon not visible anymore (unless you scroll of course).

I commonly work on multiple sites and keep the servers running for days, if not weeks.

I also work a lot with Django and its server adds the server address after each output. This way you always have quick access to it at the bottom of the terminal window. I find this very convenient.

Would it be possible to add this feature to Hugo as well?


Discussion / hints:
I guess this makes sense. I suggest we add it before the "Total in ..." so it becomes:

```
Change detected, rebuilding site (#1).
2024-04-11 09:12:35.997 +0200
Source changed /documentation.md
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Total in 30 ms
```
Do we do the same thing with a multihost site?

```text
[languages.en]
baseURL = 'https://en.example.org/'
weight = 1

[languages.de]
baseURL = 'https://de.example.org/'
weight = 2

[languages.fr]
baseURL = 'https://fr.example.org/'
weight = 3

[languages.es]
baseURL = 'https://es.example.org/'
weight = 4
```

```
Change detected, rebuilding site (#1).
2024-04-11 09:12:35.997 +0200
Source changed /documentation.md
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1) en
Web Server is available at http://localhost:1314/ (bind address 127.0.0.1) de
Web Server is available at http://localhost:1315/ (bind address 127.0.0.1) fr
Web Server is available at http://localhost:1316/ (bind address 127.0.0.1) es
Total in 30 ms
```

Fix patch:
diff --git a/commands/server.go b/commands/server.go
index 09fb4e79f7e..ccd2bde7d75 100644
--- a/commands/server.go
+++ b/commands/server.go
@@ -237,9 +237,8 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
 	listener := f.c.serverPorts[i].ln
 	logger := f.c.r.logger
 
-	r.Printf("Environment: %q\n", f.c.hugoTry().Deps.Site.Hugo().Environment)
-
 	if i == 0 {
+		r.Printf("Environment: %q\n", f.c.hugoTry().Deps.Site.Hugo().Environment)
 		mainTarget := "disk"
 		if f.c.r.renderToMemory {
 			mainTarget = "memory"
@@ -569,7 +568,7 @@ func (c *serverCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
 				}
 			}
 
-			if err := c.setBaseURLsInConfig(); err != nil {
+			if err := c.setServerInfoInConfig(); err != nil {
 				return err
 			}
 
@@ -614,7 +613,7 @@ func (c *serverCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
 	return nil
 }
 
-func (c *serverCommand) setBaseURLsInConfig() error {
+func (c *serverCommand) setServerInfoInConfig() error {
 	if len(c.serverPorts) == 0 {
 		panic("no server ports set")
 	}
@@ -641,7 +640,8 @@ func (c *serverCommand) setBaseURLsInConfig() error {
 			if c.liveReloadPort != -1 {
 				baseURLLiveReload, _ = baseURLLiveReload.WithPort(c.liveReloadPort)
 			}
-			langConfig.C.SetBaseURL(baseURL, baseURLLiveReload)
+			langConfig.C.SetServerInfo(baseURL, baseURLLiveReload, c.serverInterface)
+
 		}
 		return nil
 	})
diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go
index f0e72dabc06..d5d3dc4e7fa 100644
--- a/config/allconfig/allconfig.go
+++ b/config/allconfig/allconfig.go
@@ -400,6 +400,7 @@ type ConfigCompiled struct {
 	Timeout           time.Duration
 	BaseURL           urls.BaseURL
 	BaseURLLiveReload urls.BaseURL
+	ServerInterface   string
 	KindOutputFormats map[string]output.Formats
 	DisabledKinds     map[string]bool
 	DisabledLanguages map[string]bool
@@ -434,9 +435,10 @@ func (c *ConfigCompiled) IsMainSectionsSet() bool {
 }
 
 // This is set after the config is compiled by the server command.
-func (c *ConfigCompiled) SetBaseURL(baseURL, baseURLLiveReload urls.BaseURL) {
+func (c *ConfigCompiled) SetServerInfo(baseURL, baseURLLiveReload urls.BaseURL, serverInterface string) {
 	c.BaseURL = baseURL
 	c.BaseURLLiveReload = baseURLLiveReload
+	c.ServerInterface = serverInterface
 }
 
 // RootConfig holds all the top-level configuration options in Hugo
diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go
index 1399e22d2a4..a77900e2753 100644
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -919,9 +919,22 @@ func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, conf
 		}
 	}
 
+	h.logServerAddresses()
+
 	return nil
 }
 
+func (h *HugoSites) logServerAddresses() {
+	if h.hugoInfo.IsMultihost() {
+		for _, s := range h.Sites {
+			h.Log.Printf("Web Server is available at %s (bind address %s) %s\n", s.conf.C.BaseURL, s.conf.C.ServerInterface, s.Language().Lang)
+		}
+	} else {
+		s := h.Sites[0]
+		h.Log.Printf("Web Server is available at %s (bind address %s)\n", s.conf.C.BaseURL, s.conf.C.ServerInterface)
+	}
+}
+
 func (h *HugoSites) processFull(ctx context.Context, l logg.LevelLogger, config BuildCfg) (err error) {
 	if err = h.processFiles(ctx, l, config); err != nil {
 		err = fmt.Errorf("readAndProcessContent: %w", err)


Test patch: