Added a script - cvgitout2line.py
Description
It takes git status lines and converts it to a string with no line feeds, and then adds it to the clipboard for easy copying.
What it solved
This has been a issue with using git when you don't want to have to do a git add .
command. Grid has added to it, as I usually have a teamsite directory in my git downstream that I never want to check in, so ...
This makes it so that I can highlight/copy the lines from git, run this script, and then have a line that I can paste after a git command, like git add <paste>
. I usually do this by hand, which gets annoying and tedious, so ... Today, I figured that I would write a tool for myself that would fix this for me.
Code or Examples
The file cvgitout2line.py
is in my .mike/my_setup/bin directory (see code snippet below). I have an alias set up like so (that uses another alias called mybin
) so I don't have to remember much.
You have to remember to copy the git lines into the clipboard so it has something to operate on. It will print the basename of the path given (to give you an idea of what is going to be in the string) but does NOT print out the whole path. If you want that (other than in the clipboard) you can look at the git output.
If it doesn't find the type of lines it needs (really simple right now -- it splits each line on the ":" and if there aren't two parts -- no more or less, then it uses the second part as the file name to append -- this could be modified so that it is more air-tight, but for now, I think it will be fine).
If, at the end of the lines to process, the output is still empty, it will not copy anything to the clipboard and print a message to that affect. Otherwise, it will copy each file, separated by a space, into the clipboard.
Here is the alias:
alias cvg="mybin cvgitout2line.py"
The mybin
alias automatically adds my bin directory before the argument I pass it, so I don't have to type in my directory name, but it's almost like it being in my PATH environment variable.
If I was going to call it directly, it would look something like this:
#### for full path to the script to run it
~/.mike/my_setup/bin/cvgitout2line.py
#### using my `mybin` alias
mybin cvgitout2line.py
#### using the alias that I defined above
cvg
Simple and easy.
Here is the code for the file:
#!/usr/bin/env python
import subprocess
from rich.console import Console
import clipboard
# ---------------------------------------
# from https://stackoverflow.com/questions/8384737/extract-file-name-from-path-no-matter-what-the-os-path-format
# using answer from Lauritz V. Thaulow
# the ntpath module (which is equivalent to os.path when running on windows) will
# work for all(1) paths on all platforms.
import ntpath
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
# ---------------------------------------
console = Console()
# ---------------------------------------
def processClipboardInput():
gitOutput = clipboard.read_from_clipboard()
filesToAdd = ""
rptFiles = []
for line in gitOutput.split("\n"):
keep, fToAdd = shouldAddFile(line)
if not keep:
continue
rptFiles.append(f" [green]{path_leaf(fToAdd)}[/green]")
filesToAdd += " " + fToAdd
rptStr = "\n".join(rptFiles)
return (filesToAdd, rptStr)
def shouldAddFile(line):
# make it slightly better in that it checks the first
# value (status) to make sure it's one of the expected
# git values. These are (from git status docs):
# status action
# ------------ -----------------------
# unmodified throw
# modified keep
# added keep
# deleted throw
# renamed keep
# copied keep
# updated keep
# untracked throw
# ignored throw
keepStatus = ["modified", "added", "renamed", "copied", "updated", "new file"]
items = line.split(":")
if len(items) != 2:
return (False, "")
file = items[1].strip()
if file == "":
return (False, "")
status = items[0].strip()
if status not in keepStatus:
return (False, "")
return (True, file)
def success(filesToAdd, rptStr):
clipboard.write_to_clipboard(filesToAdd)
msg = "The following files (and their paths, as given by git) will " \
"be concatenated to a single string in the clipboard, ready to " \
"be pasted into a 'git add <paste>' command."
divider = "=========================================="
console.print(f"[white]{msg}[/white]\n[yellow]{divider}[/yellow]")
console.print(rptStr)
console.print(f"[yellow]{divider}[/yellow]")
console.print("[blue]The file(s) were copied to the clipboard.[/blue]\n")
def noFilesFound():
msg = "No files detected in clipboard, so NOT overwritting the clipboard. \n"
console.print("[red]!!!NOTE!!![/red]")
console.print(f"[yellow]{msg}[/yellow]")
# ---------------------------------------
def main():
console.print("\n\nConvert git output to single line")
console.print("----------------------------------------")
filesToAdd, rptStr = processClipboardInput()
if len(filesToAdd) <= 0:
noFilesFound()
return
success(filesToAdd, rptStr)
# ---------------------------------------
if __name__ == "__main__":
main()
# ---------------------------------------
exampleClipboardText = """
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: rtq/common.ftl
modified: rtq/determinationQuestions.ftl
modified: rtq/subscriptionAgreementNonprofessional.ftl
modified: rtq/subscriptionAgreementProfessional.ftl
deleted: rtq/notNeededNow.js
added: rtq/betterNamedFile.js
renamed: rtq/renamedAndNeededNow.js
copied: rtq/keep/someCopyOfFile.styl
madeUp: rtq/doesNotMatter.xml
add: rtq/alsoNotNotedOrMatters.yaml
Untracked files:
(use "git add <file>..." to include in what will be committed)
teamsite/
fred/abc.123
"""