2

As a project for my school, we need to do an ascii art text version. By this, i mean to use this command :

go run . "Hello World!" standard --output="banner.txt"

Where's standard is the figlet use for the ascii art, and output to put my result in a file call banner.txt.

For now, (and my code is very ugly) i got this :

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func main() {

    if len(os.Args) == 4 {
        args := os.Args
        arg3 := os.Args[3]
        arg4 := strings.Split(arg3, "=")

        if arg4[0] == "--output" {
            file, err := os.Create(arg4[1])

            if err != nil {
                fmt.Println(err)
                return
            }
            defer file.Close()

            police := ""
            if args != nil && len(args) > 1 {
                arg2 := os.Args[2]
                if arg2 == "standard" {
                    police = "standard.txt"
                } else if arg2 == "shadow" {
                    police = "shadow.txt"
                } else if arg2 == "thinkertoy" {
                    police = "thinkertoy.txt"
                } else if arg2 == "graffiti" {
                    police = "graffiti.txt"
                } else {
                    fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                    fmt.Println("   Figlet name invalid. Available : ")
                    fmt.Println("       - graffiti")
                    fmt.Println("       - standard")
                    fmt.Println("       - shadow")
                    fmt.Println("       - thinkertoy")
                }
            }
            fichier, err := os.Open(police)

            if err != nil {
                fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                return
            }

            scanner := bufio.NewScanner(fichier) // Scan le fichier

            scanner.Split(bufio.ScanLines) // split le scan en lignes

            var lignes []string // englobe toutes les lignes
            for scanner.Scan() {
                lignes = append(lignes, scanner.Text())
            }

            asciiChrs := make(map[int][]string) // mise en place de la map (vide pour l'instant)

            dec := 31 // correspond a la case zero de la map

            for _, ligne := range lignes { //ligne = une/chaques ligne dans l'intervalle lignes du fichier txt
                if ligne == "" {
                    dec++
                } else {
                    asciiChrs[dec] = append(asciiChrs[dec], ligne)
                }
            }
            userInput := os.Args[1]
            invCharCount := 0

            for _, invalidChar := range userInput {

                if invalidChar < 31 || invalidChar > 126 {
                    invCharCount++
                    fmt.Println("Caractère non supporté: ", string(invalidChar))

                }
            }

            if invCharCount > 0 {
                fmt.Println("Try Again")
                os.Exit(0)
            } else if userInput == "\\n" {
                fmt.Print("\n")
                return
            } else if userInput == "" {
                return
            } else {
                Newline(userInput, asciiChrs)

            }
        } else {
            fmt.Println("Usage: go run . [STRING] [BANNER]\n\nEX: go run . something standard")

        }

    }

}

func Newline(n string, y map[int][]string) {
    replaceNewline := strings.Replace(n, "\\n", "\n", -1)

    wordsSlice := strings.Split(replaceNewline, "\n")
    slice := []string{}
    slice2 := []string{}
    slice3 := []string{}
    slice4 := []string{}
    slice5 := []string{}
    slice6 := []string{}
    slice7 := []string{}
    slice8 := []string{}

    for _, mot := range wordsSlice {
        //for j := 0; j < 8; /*lignes*/ j++ {
        for _, lettre := range mot {
            //fmt.Print(y[int(lettre)][j])
            slice = append(slice, (y[int(lettre)][0]))
            slice2 = append(slice2, (y[int(lettre)][1]))
            slice3 = append(slice3, (y[int(lettre)][2]))
            slice4 = append(slice4, (y[int(lettre)][3]))
            slice5 = append(slice5, (y[int(lettre)][4]))
            slice6 = append(slice6, (y[int(lettre)][5]))
            slice7 = append(slice7, (y[int(lettre)][6]))
            slice8 = append(slice8, (y[int(lettre)][7]))
        }
        fmt.Println()
        //  }
    }
    f, err := os.OpenFile("banner.txt", os.O_APPEND|os.O_WRONLY, 0600)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    outpout := strings.Join(slice, "")
    outpout2 := strings.Join(slice2, "")
    outpout3 := strings.Join(slice3, "")
    outpout4 := strings.Join(slice4, "")
    outpout5 := strings.Join(slice5, "")
    outpout6 := strings.Join(slice6, "")
    outpout7 := strings.Join(slice7, "")
    outpout8 := strings.Join(slice8, "")

    if _, err = f.WriteString(outpout); err != nil {
        panic(err)
    }

    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout2); err != nil {
        panic(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout3); err != nil {
        panic(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout4); err != nil {
        panic(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout5); err != nil {
        panic(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout6); err != nil {
        panic(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout7); err != nil {
        panic(err)
    }
    if _, err = f.WriteString("\n"); err != nil {
        panic(err)
    }
    if _, err = f.WriteString(outpout8); err != nil {
        panic(err)
    }

}

So, my biggest problem here is whenever i type something like this :

go run . "Hello\nThere" standard --output="banner.txt"

The \n don't count as a \n and do nothing.

I hope someone can help me for this ! And if you got any question just tell me :)

lemon_42
  • 21
  • 1
  • Does this answer your question? [bash - How to pass a line feed to a script?](https://stackoverflow.com/questions/38642312/bash-how-to-pass-a-line-feed-to-a-script) – Peter Jun 24 '22 at 14:49
  • Shells don't interpret escape sequence in double quoted strings. Try `go run . $'Hello\nthere'` (This is for bash. If you use some other shell the syntax may be different). – Peter Jun 24 '22 at 14:50
  • FYI, Go provies the `flags` package to handle command line flags. The way you're handling them manually right now is very brittle and won't work the way people expect flags to work (ie, the position of `--output` shouldn't matter). – user229044 Jun 24 '22 at 15:15

1 Answers1

1

This is a bit tricky, because the shell does not interpret escape sequences (as clarified by Peter in his comment).

A way to solve that is passing the parameter as \\n so, for example:

go run . "Hello\\nThere" standard --output="banner.txt"

and then, in your code, you can use the Replace function from the strings package as follows on each parameter whose newline characters need to be considered:

output := strings.Replace(os.Args[1], "\\n", "\n", -1)

It is not a super clean solution but it does the job.

canta2899
  • 394
  • 1
  • 7
  • This has nothing to do with Go (and it certainly doesn't "escape command line parameters"). The shell doesn't interpret escape sequences, that's all, so the argument contains the two bytes '\' and 'n' instead of the single byte 0x0a. – Peter Jun 24 '22 at 14:51
  • Thank you for the clarification, I'm going to update my answer! – canta2899 Jun 24 '22 at 15:11