Initial version
This commit is contained in:
		
							parent
							
								
									380cb01dc1
								
							
						
					
					
						commit
						d664931113
					
				| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
/missingnewline
 | 
			
		||||
							
								
								
									
										2
									
								
								LICENSE
								
								
								
								
							
							
						
						
									
										2
									
								
								LICENSE
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) <year> <copyright holders>
 | 
			
		||||
Copyright (c) 2023 Laurence Withers.
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								README.md
								
								
								
								
							
							
						
						
									
										16
									
								
								README.md
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,17 @@
 | 
			
		|||
# missingnewline
 | 
			
		||||
 | 
			
		||||
Prints a "🚫" character and adds a newline if the cursor is not in column 1. You can use it in your shell prompt to tidy up after commands that output some text without a trailing newline.
 | 
			
		||||
Prints a "🚫" character and adds a newline if the cursor is not in column 1.
 | 
			
		||||
You can use it in your shell prompt to tidy up after commands that output some
 | 
			
		||||
text without a trailing newline.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
You can install this into your `~/.bashrc`, for example:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
declare -a PROMPT_COMMAND
 | 
			
		||||
if [ -x "${HOME}/go/bin/missingnewline" ]
 | 
			
		||||
then
 | 
			
		||||
  PROMPT_COMMAND+=("${HOME}/go/bin/missingnewline")
 | 
			
		||||
fi
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 22 KiB  | 
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
module src.lwithers.me.uk/go/missingnewline
 | 
			
		||||
 | 
			
		||||
go 1.20
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	golang.org/x/sys v0.7.0
 | 
			
		||||
	golang.org/x/term v0.7.0
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
 | 
			
		||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
 | 
			
		||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,106 @@
 | 
			
		|||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
	"golang.org/x/term"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	st, err := term.MakeRaw(0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var column int
 | 
			
		||||
	select {
 | 
			
		||||
	case <-time.After(100 * time.Millisecond):
 | 
			
		||||
	case column = <-awaitColumn():
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	term.Restore(0, st)
 | 
			
		||||
	if column > 1 {
 | 
			
		||||
		unix.Write(1, []byte("🚫\n")) // U+1F6AB
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func awaitColumn() <-chan int {
 | 
			
		||||
	ch := make(chan int)
 | 
			
		||||
	go func() {
 | 
			
		||||
		row, col := readDSR()
 | 
			
		||||
		_ = row
 | 
			
		||||
		ch <- col
 | 
			
		||||
	}()
 | 
			
		||||
	return ch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readDSR() (row, col int) {
 | 
			
		||||
	unix.Write(1, []byte{
 | 
			
		||||
		'\033', '[', // ANSI escape code: CSI
 | 
			
		||||
		'6', 'n', // DSR / device status report
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	buf := make([]byte, 64)
 | 
			
		||||
	n, err := unix.Read(0, buf)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0
 | 
			
		||||
	}
 | 
			
		||||
	buf = buf[:n]
 | 
			
		||||
 | 
			
		||||
	if len(buf) < 6 || buf[0] != '\033' || buf[1] != '[' || buf[len(buf)-1] != 'R' {
 | 
			
		||||
		return 0, 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s := string(buf[2 : len(buf)-1])
 | 
			
		||||
	pos := strings.IndexByte(s, ';')
 | 
			
		||||
	if pos == -1 {
 | 
			
		||||
		return 0, 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	row, err = strconv.Atoi(s[:pos])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0
 | 
			
		||||
	}
 | 
			
		||||
	col, err = strconv.Atoi(s[pos+1:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0
 | 
			
		||||
	}
 | 
			
		||||
	return row, col
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func processit(b []byte) {
 | 
			
		||||
	if !bytes.HasPrefix(b, []byte{'\033', '['}) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !bytes.HasSuffix(b, []byte{'R'}) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	s := string(b[2 : len(b)-1])
 | 
			
		||||
	pos := strings.IndexByte(s, ';')
 | 
			
		||||
	if pos == -1 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	x, err := strconv.Atoi(s[pos+1:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if x != 1 {
 | 
			
		||||
		fmt.Println("🚫") // U+1F6AB
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readit() chan []byte {
 | 
			
		||||
	q := make(chan []byte)
 | 
			
		||||
	go func() {
 | 
			
		||||
		b := make([]byte, 1024)
 | 
			
		||||
		n, _ := os.Stdin.Read(b)
 | 
			
		||||
		q <- b[:n]
 | 
			
		||||
	}()
 | 
			
		||||
	return q
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue