diff --git a/localio/localio.go b/localio/localio.go index b282fb9..e51c06a 100644 --- a/localio/localio.go +++ b/localio/localio.go @@ -275,7 +275,7 @@ func EmbedFileCopy(dst string, src fs.File) error { // EmbedFileStringAppendToDest takes a slice of bytes and writes it as a string to dest file path func EmbedFileStringAppendToDest(data []byte, dest string) error { - fmt.Printf("[+] Appending: \n%s\n -> %s\n", string(data), dest) + fmt.Printf("[+] Appending: \n%s\n-> %s\n", string(data), dest) fileDest, err := ResolveAbsPath(dest) if err != nil { return err @@ -294,6 +294,98 @@ func EmbedFileStringAppendToDest(data []byte, dest string) error { return nil } +// EmbedFileStringPrependToDest takes a slice of bytes and prepend writes it as a string +// to the beginning of the dest file path +func EmbedFileStringPrependToDest(data []byte, dest string) error { + fmt.Printf("[+] Prepending: \n%s\n-> %s\n", string(data), dest) + fileDest, err := ResolveAbsPath(dest) + if err != nil { + return err + } + + if err = NewRecord(fileDest).PrependStringToFile(string(data)); err != nil { + return err + } + + return nil +} + +// Record is a type for prepending string text to a file +type Record struct { + Filename string + Contents []string +} + +// NewRecord returns the Record type +func NewRecord(filename string) *Record { + return &Record{ + Filename: filename, + Contents: make([]string, 0), + } +} + +// readLines reads the lines of a file and appends them to Record.Contents +func (r *Record) readLines() error { + if _, err := os.Stat(r.Filename); err != nil { + return err + } + + f, err := os.OpenFile(r.Filename, os.O_RDONLY, 0600) + if err != nil { + return err + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + + if len(strings.TrimSpace(line)) != 0 { + r.Contents = append(r.Contents, line) + continue + } + + if len(r.Contents) != 0 { + r.Contents = append(r.Contents, line) + } + } + + return nil +} + +// PrependStringToFile prepends a given string to an existing file while preserving the original formatting +func (r *Record) PrependStringToFile(content string) error { + err := r.readLines() + if err != nil { + return err + } + + f, err := os.OpenFile(r.Filename, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + return err + } + defer f.Close() + + writer := bufio.NewWriter(f) + + _, err = writer.WriteString(fmt.Sprintf("%s\n", content)) + if err != nil { + return err + } + for _, line := range r.Contents { + _, err = writer.WriteString(fmt.Sprintf("%s\n", line)) + if err != nil { + return err + } + } + + if err = writer.Flush(); err != nil { + return err + } + + return nil +} + // ExecCMD Execute a command func ExecCMD(command string) (string, error) { fmt.Printf("[+] %s\n", command) diff --git a/localio/localio_test.go b/localio/localio_test.go index cfcc3e7..d2fd4ff 100644 --- a/localio/localio_test.go +++ b/localio/localio_test.go @@ -67,11 +67,11 @@ func TestEmbedFileStringAppendToDest(t *testing.T) { {name: "TestEmbedFileStringAppendToDest 1", args: args{ data: testConfig, dest: "test/zshrc-test-append-to-file.zshrc", - }}, + }, wantErr: false}, {name: "TestEmbedFileStringAppendToDest 1", args: args{ data: testConfig, dest: "test/copy-embed-file-test.zshrc", - }}, + }, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -89,6 +89,34 @@ func TestEmbedFileStringAppendToDest(t *testing.T) { }) } +func TestEmbedFileStringPrependToDest(t *testing.T) { + testConfig, err := testEmbedFiles.ReadFile("test/zshrc_test_extra_prepend.zsh") + if err != nil { + t.Errorf("EmbedFileStringAppendToDest() error = %v", err) + } + type args struct { + data []byte + dest string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "TestEmbedFileStringPrependToDest 1", args: args{ + data: testConfig, + dest: "test/zshrc-test-prepend-to-file.zshrc", + }, wantErr: false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := EmbedFileStringPrependToDest(tt.args.data, tt.args.dest); (err != nil) != tt.wantErr { + t.Errorf("EmbedFileStringPrependToDest() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + func TestDownloadAndInstallLatestVersionOfGolang(t *testing.T) { dirs, err := NewDirectories() if err != nil { diff --git a/localio/test/zshrc-test-prepend-to-file.zshrc b/localio/test/zshrc-test-prepend-to-file.zshrc new file mode 100644 index 0000000..146ed09 --- /dev/null +++ b/localio/test/zshrc-test-prepend-to-file.zshrc @@ -0,0 +1,18 @@ +# export PATH=$HOME/bin:/usr/local/bin:$PATH + +# Path to your oh-my-zsh installation. +export ZSH=$HOME/.oh-my-zsh + +# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes +ZSH_THEME="robbyrussell" + +# Uncomment the following line to use case-sensitive completion. +# CASE_SENSITIVE="true" + +plugins=(git) + +source $ZSH/oh-my-zsh.sh + +# User configuration + +# export MANPATH="/usr/local/man:$MANPATH" diff --git a/localio/test/zshrc_test_extra_prepend.zsh b/localio/test/zshrc_test_extra_prepend.zsh new file mode 100644 index 0000000..d657c48 --- /dev/null +++ b/localio/test/zshrc_test_extra_prepend.zsh @@ -0,0 +1,6 @@ +# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. +# Initialization code that may require console input (password prompts, [y/n] +# confirmations, etc.) must go above this block; everything else may go below. +if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then + source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" +fi diff --git a/zsh/templates/linux/aliases.zsh b/zsh/templates/linux/aliases.zsh index 44953ed..318422c 100644 --- a/zsh/templates/linux/aliases.zsh +++ b/zsh/templates/linux/aliases.zsh @@ -10,5 +10,5 @@ alias gcmsg='git commit -m ' alias gl="git log --all --graph --pretty=tformat:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --date=short" alias gll="git log --all --stat --pretty=tformat:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative" alias gln="git --no-pager log --all --stat --pretty=tformat:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative -n 10" -alias clp="pbcopy < $1" +alias clp="xclip -selection c -r" alias fzfbat="fzf --preview 'batcat --style numbers,changes --color=always {}' | head -500" diff --git a/zsh/templates/zshrc_extra_prepend.zsh b/zsh/templates/zshrc_extra_prepend.zsh new file mode 100644 index 0000000..d657c48 --- /dev/null +++ b/zsh/templates/zshrc_extra_prepend.zsh @@ -0,0 +1,6 @@ +# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. +# Initialization code that may require console input (password prompts, [y/n] +# confirmations, etc.) must go above this block; everything else may go below. +if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then + source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" +fi diff --git a/zsh/zsh.go b/zsh/zsh.go index 74990cf..e62bf48 100644 --- a/zsh/zsh.go +++ b/zsh/zsh.go @@ -49,6 +49,8 @@ func updateZSHPlugins(zshrcPath string) error { return nil } +const zshExtraConfigPrependTemplate = "templates/zshrc_extra_prepend.zsh" + // InstallOhMyZsh ... func InstallOhMyZsh(osType string, dirs *localio.Directories) error { // install ohmyzsh if not already installed @@ -132,7 +134,7 @@ func InstallOhMyZsh(osType string, dirs *localio.Directories) error { return err } - if err := localio.EmbedFileCopy("~/.oh-my-zsh/tools/upgrade.zsh", upgradeScript); err != nil { + if err = localio.EmbedFileCopy("~/.oh-my-zsh/tools/upgrade.zsh", upgradeScript); err != nil { return err } @@ -148,12 +150,21 @@ func InstallOhMyZsh(osType string, dirs *localio.Directories) error { return err } - if err := localio.EmbedFileCopy("~/.p10k.zsh", p10kConfig); err != nil { + if err = localio.EmbedFileCopy("~/.p10k.zsh", p10kConfig); err != nil { return err } fmt.Println("[+] Setting Powerlevel10k Theme") - if err := localio.SetVariableValue("ZSH_THEME", "powerlevel10k\\/powerlevel10k", osType, "~/.zshrc"); err != nil { + if err = localio.SetVariableValue("ZSH_THEME", "powerlevel10k\\/powerlevel10k", osType, "~/.zshrc"); err != nil { + return err + } + + zshExtraPrependConfig, err := zshConfigs.ReadFile(zshExtraConfigPrependTemplate) + if err != nil { + return err + } + + if err := localio.EmbedFileStringPrependToDest(zshExtraPrependConfig, "~/.zshrc"); err != nil { return err }