mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 10:47:27 +08:00 
			
		
		
		
	terminal: use exact window size for pager (#3249)
Instead of using a fixed 100x30 window size query the operating system for the exact size, also fixes a bug where the last line before calling the pager is repeated twice.
This commit is contained in:
		 Alessandro Arzilli
					Alessandro Arzilli
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							58fc3931e8
						
					
				
				
					commit
					2be9cf1fab
				
			| @ -100,6 +100,8 @@ type pagingWriter struct { | |||||||
| 	pager    string | 	pager    string | ||||||
| 	lastnl   bool | 	lastnl   bool | ||||||
| 	cancel   func() | 	cancel   func() | ||||||
|  |  | ||||||
|  | 	lines, columns int | ||||||
| } | } | ||||||
|  |  | ||||||
| type pagingWriterMode uint8 | type pagingWriterMode uint8 | ||||||
| @ -108,9 +110,6 @@ const ( | |||||||
| 	pagingWriterNormal pagingWriterMode = iota | 	pagingWriterNormal pagingWriterMode = iota | ||||||
| 	pagingWriterMaybe | 	pagingWriterMaybe | ||||||
| 	pagingWriterPaging | 	pagingWriterPaging | ||||||
|  |  | ||||||
| 	pagingWriterMaxLines    = 30 |  | ||||||
| 	pagingWriterColsPerLine = 100 |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (w *pagingWriter) Write(p []byte) (nn int, err error) { | func (w *pagingWriter) Write(p []byte) (nn int, err error) { | ||||||
| @ -141,7 +140,7 @@ func (w *pagingWriter) Write(p []byte) (nn int, err error) { | |||||||
| 			w.cmdStdin.Write(w.buf) | 			w.cmdStdin.Write(w.buf) | ||||||
| 			w.buf = nil | 			w.buf = nil | ||||||
| 			w.mode = pagingWriterPaging | 			w.mode = pagingWriterPaging | ||||||
| 			return w.cmdStdin.Write(p) | 			return len(p), nil | ||||||
| 		} else { | 		} else { | ||||||
| 			if len(p) > 0 { | 			if len(p) > 0 { | ||||||
| 				w.lastnl = p[len(p)-1] == '\n' | 				w.lastnl = p[len(p)-1] == '\n' | ||||||
| @ -202,17 +201,17 @@ func (w *pagingWriter) PageMaybe(cancel func()) { | |||||||
| 	} | 	} | ||||||
| 	w.lastnl = true | 	w.lastnl = true | ||||||
| 	w.cancel = cancel | 	w.cancel = cancel | ||||||
|  | 	w.getWindowSize() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (w *pagingWriter) largeOutput() bool { | func (w *pagingWriter) largeOutput() bool { | ||||||
| 	if len(w.buf) > pagingWriterMaxLines*pagingWriterColsPerLine { | 	lines := 0 | ||||||
| 		return true | 	lineStart := 0 | ||||||
| 	} |  | ||||||
| 	nl := 0 |  | ||||||
| 	for i := range w.buf { | 	for i := range w.buf { | ||||||
| 		if w.buf[i] == '\n' { | 		if i-lineStart > w.columns || w.buf[i] == '\n' { | ||||||
| 			nl++ | 			lineStart = i | ||||||
| 			if nl > pagingWriterMaxLines { | 			lines++ | ||||||
|  | 			if lines > w.lines { | ||||||
| 				return true | 				return true | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								pkg/terminal/out_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								pkg/terminal/out_unix.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | //go:build linux || darwin || freebsd | ||||||
|  | // +build linux darwin freebsd | ||||||
|  |  | ||||||
|  | package terminal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"syscall" | ||||||
|  | 	"unsafe" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type winSize struct { | ||||||
|  | 	row, col       uint16 | ||||||
|  | 	xpixel, ypixel uint16 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *pagingWriter) getWindowSize() { | ||||||
|  | 	var ws winSize | ||||||
|  | 	ok, _, _ := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdout), syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))) | ||||||
|  | 	if int(ok) < 0 { | ||||||
|  | 		w.mode = pagingWriterNormal | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	w.lines = int(ws.row) | ||||||
|  | 	w.columns = int(ws.col) | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								pkg/terminal/out_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								pkg/terminal/out_windows.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | package terminal | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"syscall" | ||||||
|  | 	"unsafe" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	kernel32                       = syscall.NewLazyDLL("kernel32.dll") | ||||||
|  | 	procGetStdHandle               = kernel32.NewProc("GetStdHandle") | ||||||
|  | 	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type coord struct { | ||||||
|  | 	x, y int16 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type smallRect struct { | ||||||
|  | 	left, top, right, bottom int16 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type consoleScreenBufferInfo struct { | ||||||
|  | 	dwSize              coord | ||||||
|  | 	dwCursorPosition    coord | ||||||
|  | 	wAttributes         int16 | ||||||
|  | 	srWindow            smallRect | ||||||
|  | 	dwMaximumWindowSize coord | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (w *pagingWriter) getWindowSize() { | ||||||
|  | 	hout, _, err := procGetStdHandle.Call(uintptr(uint32(-12 & 0xFFFFFFFF))) // stdout handle | ||||||
|  | 	if err != syscall.Errno(0) { | ||||||
|  | 		w.mode = pagingWriterNormal | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	var sbi consoleScreenBufferInfo | ||||||
|  | 	_, _, err = procGetConsoleScreenBufferInfo.Call(uintptr(hout), uintptr(unsafe.Pointer(&sbi))) | ||||||
|  | 	if err != syscall.Errno(0) { | ||||||
|  | 		w.mode = pagingWriterNormal | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	w.columns = int(sbi.srWindow.right - sbi.srWindow.left + 1) | ||||||
|  | 	w.lines = int(sbi.srWindow.bottom - sbi.srWindow.top + 1) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user