From d664931113c7c48bbb4488c8e60c887e7f6d775f Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 7 Apr 2023 16:32:39 +0100 Subject: [PATCH] Initial version --- .gitignore | 1 + LICENSE | 2 +- README.md | 16 +++++++- example.gif | Bin 0 -> 23004 bytes go.mod | 8 ++++ go.sum | 4 ++ main.go | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++ my-recording | Bin 0 -> 1243 bytes 8 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 example.gif create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 my-recording diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61b11b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/missingnewline diff --git a/LICENSE b/LICENSE index d449d3e..1d4903c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) +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 diff --git a/README.md b/README.md index e8641c8..a8948f7 100644 --- a/README.md +++ b/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. \ No newline at end of file +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. + +![Example terminal session showing the problem of an unterminated command mixing with the shell prompt, and then the program correctly detecting the presence or absence of a non-newline-terminated output and using the "🚫" character appropriately.](example.gif) + +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 +``` diff --git a/example.gif b/example.gif new file mode 100644 index 0000000000000000000000000000000000000000..48688bafa4acff0e5d19d8d60c08af2f88d05476 GIT binary patch literal 23004 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 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 +} diff --git a/my-recording b/my-recording new file mode 100644 index 0000000000000000000000000000000000000000..5d5f0f965f547ea2a679b220a996d5cd6f9129c7 GIT binary patch literal 1243 zcmd7RF-RL>6bJB^#Ax!xFB0gM7LG$4w0ak79lSxuE~1l*q*dd^9OUjwlM*|$2&HSm zp-WMULx-Zfi_W60f-QVW*-gn&Gi5#NcB_59 z2#coMr&>MkKM&y1R&5)1IlF3r0PbQFEhD|!bMpy_<*R@%;==f zi;FnJ`;FMV1~o<~e+)5nLVRA`CrkLAs2okumt#EU6FTE(-qfU*LS@kC^!pn?QDeWR&udB$q z25$+TSuA?3eV`8wGBfEQZv^|{324#JcRBj8&YLdiu zDWQRr?Dfc-EfN~h=ik0ANJbxRg@y2PW#-&+NA3a^Rgyk^a7GDr4 jsPK1A+=fs7v>+Zt)JM3>tM>p2T=w=el)|2Nic;JF#a>$_ literal 0 HcmV?d00001