package trans import ( "fmt" "os/exec" "strings" "regexp" ) type Translation struct { job TransJob Executor func(TransJob) ([]byte, error) } type TransJob struct { word string fromLang string toLang string } func New(word, fromLang, toLang string) Translation { return Translation{ job: TransJob{ word: word, fromLang: fromLang, toLang: toLang, }, Executor: executeTransShell, } } func executeTransShell(tj TransJob) ([]byte, error) { config := []string{ "-no-ansi", "-show-original", "n", "-show-original-phonetics", "n", "-show-dictionary", "y", "-show-languages", "n", "-show-prompt-message", "n", fmt.Sprintf("%s:%s", tj.fromLang, tj.toLang), tj.word, } return exec.Command("trans", config...).Output() } func (t Translation) Translate() []string { outBytes, err := t.Executor(t.job) if err != nil { panic(err) } return uniqueSlice(parseTransOutput(string(outBytes))) } func parseTransOutput(out string) []string { re := regexp.MustCompile(`(?m)^\s{4}\w.*$`) lineMatches := re.FindAllString(out, -1) results := []string{strings.Split(out, "\n")[0]} for _, line := range lineMatches { for _, word := range strings.Split(strings.TrimSpace(line), ",") { results = append(results, strings.TrimSpace(word)) } } return results } func uniqueSlice(items []string) []string { encountered := map[string]bool{} uniqueSlice := []string{} for _, item := range items { if !encountered[item] { encountered[item] = true uniqueSlice = append(uniqueSlice, item) } } return uniqueSlice }