Quellcode durchsuchen

Refactored cmd/yay

Jguer vor 8 Jahren
Ursprung
Commit
38617c2781
6 geänderte Dateien mit 437 neuen und 415 gelöschten Zeilen
  1. 1 275
      actions.go
  2. 0 139
      cmd/yay/yay.go
  3. 97 0
      query.go
  4. 2 1
      util/util.go
  5. 103 0
      utils.go
  6. 234 0
      yay.go

+ 1 - 275
actions.go

@@ -1,112 +1,14 @@
-package yay
+package main
 
 import (
-	"bufio"
 	"fmt"
-	"io"
-	"math"
 	"os"
-	"os/exec"
-	"strconv"
-	"strings"
-	"time"
 
 	aur "github.com/jguer/yay/aur"
 	pac "github.com/jguer/yay/pacman"
 	"github.com/jguer/yay/util"
 )
 
-// NumberMenu presents a CLI for selecting packages to install.
-func NumberMenu(pkgS []string, flags []string) (err error) {
-	var num int
-
-	aq, numaq, err := aur.Search(pkgS, true)
-	if err != nil {
-		fmt.Println("Error during AUR search:", err)
-	}
-	pq, numpq, err := pac.Search(pkgS)
-	if err != nil {
-		return
-	}
-
-	if numpq == 0 && numaq == 0 {
-		return fmt.Errorf("no packages match search")
-	}
-
-	if util.SortMode == util.BottomUp {
-		aq.PrintSearch(numpq)
-		pq.PrintSearch()
-	} else {
-		pq.PrintSearch()
-		aq.PrintSearch(numpq)
-	}
-
-	fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.")
-	reader := bufio.NewReader(os.Stdin)
-	numberBuf, overflow, err := reader.ReadLine()
-	if err != nil || overflow {
-		fmt.Println(err)
-		return
-	}
-
-	numberString := string(numberBuf)
-	var aurInstall []string
-	var repoInstall []string
-	result := strings.Fields(numberString)
-	for _, numS := range result {
-		num, err = strconv.Atoi(numS)
-		if err != nil {
-			continue
-		}
-
-		// Install package
-		if num > numaq+numpq-1 || num < 0 {
-			continue
-		} else if num > numpq-1 {
-			if util.SortMode == util.BottomUp {
-				aurInstall = append(aurInstall, aq[numaq+numpq-num-1].Name)
-			} else {
-				aurInstall = append(aurInstall, aq[num-numpq].Name)
-			}
-		} else {
-			if util.SortMode == util.BottomUp {
-				repoInstall = append(repoInstall, pq[numpq-num-1].Name)
-			} else {
-				repoInstall = append(repoInstall, pq[num].Name)
-			}
-		}
-	}
-
-	if len(repoInstall) != 0 {
-		pac.Install(repoInstall, flags)
-	}
-
-	if len(aurInstall) != 0 {
-		q, n, err := aur.MultiInfo(aurInstall)
-		if err != nil {
-			return err
-		} else if n != len(aurInstall) {
-			q.MissingPackage(aurInstall)
-		}
-
-		var finalrm []string
-		for _, aurpkg := range q {
-			finalmdeps, err := aurpkg.Install(flags)
-			finalrm = append(finalrm, finalmdeps...)
-			if err != nil {
-				// Do not abandon program, we might still be able to install the rest
-				fmt.Println(err)
-			}
-		}
-
-		if len(finalrm) != 0 {
-			aur.RemoveMakeDeps(finalrm)
-		}
-	}
-
-	return nil
-}
-
 // Install handles package installs
 func Install(pkgs []string, flags []string) error {
 	aurs, repos, _ := pac.PackageSlices(pkgs)
@@ -149,151 +51,6 @@ func Upgrade(flags []string) error {
 	return erra
 }
 
-// SyncSearch presents a query to the local repos and to the AUR.
-func SyncSearch(pkgS []string) (err error) {
-	aq, _, err := aur.Search(pkgS, true)
-	if err != nil {
-		return err
-	}
-	pq, _, err := pac.Search(pkgS)
-	if err != nil {
-		return err
-	}
-
-	if util.SortMode == util.BottomUp {
-		aq.PrintSearch(0)
-		pq.PrintSearch()
-	} else {
-		pq.PrintSearch()
-		aq.PrintSearch(0)
-	}
-
-	return nil
-}
-
-// SyncInfo serves as a pacman -Si for repo packages and AUR packages.
-func SyncInfo(pkgS []string, flags []string) (err error) {
-	aurS, repoS, err := pac.PackageSlices(pkgS)
-	if err != nil {
-		return
-	}
-
-	q, _, err := aur.MultiInfo(aurS)
-	if err != nil {
-		fmt.Println(err)
-	}
-
-	for _, aurP := range q {
-		aurP.PrintInfo()
-	}
-
-	if len(repoS) != 0 {
-		err = PassToPacman("-Si", repoS, flags)
-	}
-
-	return
-}
-
-// LocalStatistics returns installed packages statistics.
-func LocalStatistics(version string) error {
-	info, err := pac.Statistics()
-	if err != nil {
-		return err
-	}
-
-	foreignS, foreign, _ := pac.ForeignPackages()
-
-	fmt.Printf("\n Yay version r%s\n", version)
-	fmt.Println("\x1B[1;34m===========================================\x1B[0m")
-	fmt.Printf("\x1B[1;32mTotal installed packages: \x1B[0;33m%d\x1B[0m\n", info.Totaln)
-	fmt.Printf("\x1B[1;32mTotal foreign installed packages: \x1B[0;33m%d\x1B[0m\n", foreign)
-	fmt.Printf("\x1B[1;32mExplicitly installed packages: \x1B[0;33m%d\x1B[0m\n", info.Expln)
-	fmt.Printf("\x1B[1;32mTotal Size occupied by packages: \x1B[0;33m%s\x1B[0m\n", size(info.TotalSize))
-	fmt.Println("\x1B[1;34m===========================================\x1B[0m")
-	fmt.Println("\x1B[1;32mTen biggest packages\x1B[0m")
-	pac.BiggestPackages()
-	fmt.Println("\x1B[1;34m===========================================\x1B[0m")
-
-	keys := make([]string, len(foreignS))
-	i := 0
-	for k := range foreignS {
-		keys[i] = k
-		i++
-	}
-	q, _, err := aur.MultiInfo(keys)
-	if err != nil {
-		return err
-	}
-
-	for _, res := range q {
-		if res.Maintainer == "" {
-			fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;37;40m is orphaned.\x1b[0m\n", res.Name)
-		}
-		if res.OutOfDate != 0 {
-			fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;37;40m is out-of-date in AUR.\x1b[0m\n", res.Name)
-		}
-	}
-
-	return nil
-}
-
-// Function by pyk https://github.com/pyk/byten
-func index(s int64) float64 {
-	x := math.Log(float64(s)) / math.Log(1024)
-	return math.Floor(x)
-}
-
-// Function by pyk https://github.com/pyk/byten
-func countSize(s int64, i float64) float64 {
-	return float64(s) / math.Pow(1024, math.Floor(i))
-}
-
-// Size return a formated string from file size
-// Function by pyk https://github.com/pyk/byten
-func size(s int64) string {
-
-	symbols := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
-	i := index(s)
-	if s < 10 {
-		return fmt.Sprintf("%dB", s)
-	}
-	size := countSize(s, i)
-	format := "%.0f"
-	if size < 10 {
-		format = "%.1f"
-	}
-
-	return fmt.Sprintf(format+"%s", size, symbols[int(i)])
-}
-
-// PassToPacman outsorces execution to pacman binary without modifications.
-func PassToPacman(op string, pkgs []string, flags []string) error {
-	var cmd *exec.Cmd
-	var args []string
-
-	args = append(args, op)
-	if len(pkgs) != 0 {
-		args = append(args, pkgs...)
-	}
-
-	if len(flags) != 0 {
-		args = append(args, flags...)
-	}
-
-	if strings.Contains(op, "-Q") || op == "-Si" {
-		cmd = exec.Command("pacman", args...)
-	} else {
-		args = append([]string{"pacman"}, args...)
-		cmd = exec.Command("sudo", args...)
-	}
-
-	cmd.Stdout = os.Stdout
-	cmd.Stdin = os.Stdin
-	cmd.Stderr = os.Stderr
-	err := cmd.Run()
-	return err
-}
-
 // CleanDependencies removels all dangling dependencies in system
 func CleanDependencies(pkgs []string) error {
 	hanging, err := pac.HangingPackages()
@@ -327,34 +84,3 @@ func GetPkgbuild(pkg string) (err error) {
 	err = aur.GetPkgbuild(pkg, wd)
 	return
 }
-
-// Complete provides completion info for shells
-func Complete() (err error) {
-	path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache"
-
-	if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 {
-		os.MkdirAll(os.Getenv("HOME")+"/.cache/yay", 0755)
-
-		out, err := os.Create(path)
-		if err != nil {
-			return err
-		}
-
-		if aur.CreateAURList(out) != nil {
-			defer os.Remove(path)
-		}
-		err = pac.CreatePackageList(out)
-
-		out.Close()
-		return err
-	}
-
-	in, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)
-	if err != nil {
-		return err
-	}
-	defer in.Close()
-
-	_, err = io.Copy(os.Stdout, in)
-	return err
-}

+ 0 - 139
cmd/yay/yay.go

@@ -1,139 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"os"
-
-	"github.com/jguer/yay"
-	"github.com/jguer/yay/util"
-)
-
-func usage() {
-	fmt.Println(`usage:  yay <operation> [...]
-    operations:
-    yay {-h --help}
-    yay {-V --version}
-    yay {-D --database} <options> <package(s)>
-    yay {-F --files}    [options] [package(s)]
-    yay {-Q --query}    [options] [package(s)]
-    yay {-R --remove}   [options] <package(s)>
-    yay {-S --sync}     [options] [package(s)]
-    yay {-T --deptest}  [options] [package(s)]
-    yay {-U --upgrade}  [options] <file(s)>
-
-    New operations:
-    yay -Qstats          displays system information
-    yay -Cd              remove unneeded dependencies
-    yay -G [package(s)]  get pkgbuild from ABS or AUR
-
-    New options:
-    --topdown            shows repository's packages first and then aur's
-    --bottomup           shows aur's packages first and then repository's
-    --noconfirm          skip user input on package install
-`)
-}
-
-var version = "1.100"
-
-func parser() (op string, options []string, packages []string, err error) {
-	if len(os.Args) < 2 {
-		err = fmt.Errorf("no operation specified")
-		return
-	}
-	op = "yogurt"
-
-	for _, arg := range os.Args[1:] {
-		if arg[0] == '-' && arg[1] != '-' {
-			switch arg {
-			case "-b":
-				util.Build = true
-			default:
-				op = arg
-			}
-			continue
-		}
-
-		if arg[0] == '-' && arg[1] == '-' {
-			switch arg {
-			case "--build":
-				util.Build = true
-			case "--bottomup":
-				util.SortMode = util.BottomUp
-			case "--topdown":
-				util.SortMode = util.TopDown
-
-			case "--complete":
-				util.Shell = "sh"
-				yay.Complete()
-				os.Exit(0)
-			case "--fcomplete":
-				util.Shell = "fish"
-				yay.Complete()
-				os.Exit(0)
-			case "--help":
-				usage()
-				os.Exit(0)
-			case "--noconfirm":
-				util.NoConfirm = true
-				fallthrough
-			default:
-				options = append(options, arg)
-			}
-			continue
-		}
-
-		packages = append(packages, arg)
-	}
-	return
-}
-
-func main() {
-	op, options, pkgs, err := parser()
-	if err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-
-	switch op {
-	case "-Cd":
-		err = yay.CleanDependencies(pkgs)
-	case "-G":
-		for _, pkg := range pkgs {
-			err = yay.GetPkgbuild(pkg)
-			if err != nil {
-				fmt.Println(pkg+":", err)
-			}
-		}
-	case "-Qstats":
-		err = yay.LocalStatistics(version)
-	case "-Ss", "-Ssq", "-Sqs":
-		if op == "-Ss" {
-			util.SearchVerbosity = util.Detailed
-		} else {
-			util.SearchVerbosity = util.Minimal
-		}
-
-		if pkgs != nil {
-			err = yay.SyncSearch(pkgs)
-		}
-	case "-S":
-		err = yay.Install(pkgs, options)
-	case "-Syu", "-Suy":
-		err = yay.Upgrade(options)
-	case "-Si":
-		err = yay.SyncInfo(pkgs, options)
-	case "yogurt":
-		util.SearchVerbosity = util.NumberMenu
-
-		if pkgs != nil {
-			err = yay.NumberMenu(pkgs, options)
-		}
-	default:
-		err = yay.PassToPacman(op, pkgs, options)
-	}
-
-	if err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-}

+ 97 - 0
query.go

@@ -0,0 +1,97 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/jguer/yay/aur"
+	pac "github.com/jguer/yay/pacman"
+	"github.com/jguer/yay/util"
+)
+
+// SyncSearch presents a query to the local repos and to the AUR.
+func SyncSearch(pkgS []string) (err error) {
+	aq, _, err := aur.Search(pkgS, true)
+	if err != nil {
+		return err
+	}
+	pq, _, err := pac.Search(pkgS)
+	if err != nil {
+		return err
+	}
+
+	if util.SortMode == util.BottomUp {
+		aq.PrintSearch(0)
+		pq.PrintSearch()
+	} else {
+		pq.PrintSearch()
+		aq.PrintSearch(0)
+	}
+
+	return nil
+}
+
+// SyncInfo serves as a pacman -Si for repo packages and AUR packages.
+func SyncInfo(pkgS []string, flags []string) (err error) {
+	aurS, repoS, err := pac.PackageSlices(pkgS)
+	if err != nil {
+		return
+	}
+
+	q, _, err := aur.MultiInfo(aurS)
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	for _, aurP := range q {
+		aurP.PrintInfo()
+	}
+
+	if len(repoS) != 0 {
+		err = PassToPacman("-Si", repoS, flags)
+	}
+
+	return
+}
+
+// LocalStatistics returns installed packages statistics.
+func LocalStatistics(version string) error {
+	info, err := pac.Statistics()
+	if err != nil {
+		return err
+	}
+
+	foreignS, foreign, _ := pac.ForeignPackages()
+
+	fmt.Printf("\n Yay version r%s\n", version)
+	fmt.Println("\x1B[1;34m===========================================\x1B[0m")
+	fmt.Printf("\x1B[1;32mTotal installed packages: \x1B[0;33m%d\x1B[0m\n", info.Totaln)
+	fmt.Printf("\x1B[1;32mTotal foreign installed packages: \x1B[0;33m%d\x1B[0m\n", foreign)
+	fmt.Printf("\x1B[1;32mExplicitly installed packages: \x1B[0;33m%d\x1B[0m\n", info.Expln)
+	fmt.Printf("\x1B[1;32mTotal Size occupied by packages: \x1B[0;33m%s\x1B[0m\n", size(info.TotalSize))
+	fmt.Println("\x1B[1;34m===========================================\x1B[0m")
+	fmt.Println("\x1B[1;32mTen biggest packages\x1B[0m")
+	pac.BiggestPackages()
+	fmt.Println("\x1B[1;34m===========================================\x1B[0m")
+
+	keys := make([]string, len(foreignS))
+	i := 0
+	for k := range foreignS {
+		keys[i] = k
+		i++
+	}
+	q, _, err := aur.MultiInfo(keys)
+	if err != nil {
+		return err
+	}
+
+	for _, res := range q {
+		if res.Maintainer == "" {
+			fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;37;40m is orphaned.\x1b[0m\n", res.Name)
+		}
+		if res.OutOfDate != 0 {
+			fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;37;40m is out-of-date in AUR.\x1b[0m\n", res.Name)
+		}
+	}
+
+	return nil
+}

+ 2 - 1
util/util.go

@@ -25,6 +25,7 @@ const (
 	Minimal
 )
 
+// Shell describes the default user shell
 var Shell = "fish"
 
 // Build controls if packages will be built from ABS.
@@ -122,7 +123,7 @@ func DownloadAndUnpack(url string, path string, trim bool) (err error) {
 	return
 }
 
-// Editor returns the prefered system editor.
+// Editor returns the preferred system editor.
 func Editor() string {
 	if os.Getenv("EDITOR") != "" {
 		return os.Getenv("EDITOR")

+ 103 - 0
utils.go

@@ -0,0 +1,103 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"math"
+	"os"
+	"os/exec"
+	"strings"
+	"time"
+
+	"github.com/jguer/yay/aur"
+	pac "github.com/jguer/yay/pacman"
+	"github.com/jguer/yay/util"
+)
+
+// PassToPacman outsorces execution to pacman binary without modifications.
+func PassToPacman(op string, pkgs []string, flags []string) error {
+	var cmd *exec.Cmd
+	var args []string
+
+	args = append(args, op)
+	if len(pkgs) != 0 {
+		args = append(args, pkgs...)
+	}
+
+	if len(flags) != 0 {
+		args = append(args, flags...)
+	}
+
+	if strings.Contains(op, "-Q") {
+		cmd = exec.Command("pacman", args...)
+	} else {
+		args = append([]string{"pacman"}, args...)
+		cmd = exec.Command("sudo", args...)
+	}
+
+	cmd.Stdout = os.Stdout
+	cmd.Stdin = os.Stdin
+	cmd.Stderr = os.Stderr
+	err := cmd.Run()
+	return err
+}
+
+// Complete provides completion info for shells
+func Complete() (err error) {
+	path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache"
+
+	if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 {
+		os.MkdirAll(os.Getenv("HOME")+"/.cache/yay", 0755)
+
+		out, err := os.Create(path)
+		if err != nil {
+			return err
+		}
+
+		if aur.CreateAURList(out) != nil {
+			defer os.Remove(path)
+		}
+		err = pac.CreatePackageList(out)
+
+		out.Close()
+		return err
+	}
+
+	in, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)
+	if err != nil {
+		return err
+	}
+	defer in.Close()
+
+	_, err = io.Copy(os.Stdout, in)
+	return err
+}
+
+// Function by pyk https://github.com/pyk/byten
+func index(s int64) float64 {
+	x := math.Log(float64(s)) / math.Log(1024)
+	return math.Floor(x)
+}
+
+// Function by pyk https://github.com/pyk/byten
+func countSize(s int64, i float64) float64 {
+	return float64(s) / math.Pow(1024, math.Floor(i))
+}
+
+// Size return a formated string from file size
+// Function by pyk https://github.com/pyk/byten
+func size(s int64) string {
+
+	symbols := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
+	i := index(s)
+	if s < 10 {
+		return fmt.Sprintf("%dB", s)
+	}
+	size := countSize(s, i)
+	format := "%.0f"
+	if size < 10 {
+		format = "%.1f"
+	}
+
+	return fmt.Sprintf(format+"%s", size, symbols[int(i)])
+}

+ 234 - 0
yay.go

@@ -0,0 +1,234 @@
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/jguer/yay/aur"
+	pac "github.com/jguer/yay/pacman"
+	"github.com/jguer/yay/util"
+)
+
+func usage() {
+	fmt.Println(`usage:  yay <operation> [...]
+    operations:
+    yay {-h --help}
+    yay {-V --version}
+    yay {-D --database} <options> <package(s)>
+    yay {-F --files}    [options] [package(s)]
+    yay {-Q --query}    [options] [package(s)]
+    yay {-R --remove}   [options] <package(s)>
+    yay {-S --sync}     [options] [package(s)]
+    yay {-T --deptest}  [options] [package(s)]
+    yay {-U --upgrade}  [options] <file(s)>
+
+    New operations:
+    yay -Qstats          displays system information
+    yay -Cd              remove unneeded dependencies
+    yay -G [package(s)]  get pkgbuild from ABS or AUR
+
+    New options:
+    --topdown            shows repository's packages first and then aur's
+    --bottomup           shows aur's packages first and then repository's
+    --noconfirm          skip user input on package install
+`)
+}
+
+var version = "1.116"
+
+func parser() (op string, options []string, packages []string, err error) {
+	if len(os.Args) < 2 {
+		err = fmt.Errorf("no operation specified")
+		return
+	}
+	op = "yogurt"
+
+	for _, arg := range os.Args[1:] {
+		if arg[0] == '-' && arg[1] != '-' {
+			switch arg {
+			case "-b":
+				util.Build = true
+			default:
+				op = arg
+			}
+			continue
+		}
+
+		if arg[0] == '-' && arg[1] == '-' {
+			switch arg {
+			case "--build":
+				util.Build = true
+			case "--bottomup":
+				util.SortMode = util.BottomUp
+			case "--topdown":
+				util.SortMode = util.TopDown
+
+			case "--complete":
+				util.Shell = "sh"
+				Complete()
+				os.Exit(0)
+			case "--fcomplete":
+				util.Shell = "fish"
+				Complete()
+				os.Exit(0)
+			case "--help":
+				usage()
+				os.Exit(0)
+			case "--noconfirm":
+				util.NoConfirm = true
+				fallthrough
+			default:
+				options = append(options, arg)
+			}
+			continue
+		}
+
+		packages = append(packages, arg)
+	}
+	return
+}
+
+func main() {
+	op, options, pkgs, err := parser()
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+
+	switch op {
+	case "-Cd":
+		err = CleanDependencies(pkgs)
+	case "-G":
+		for _, pkg := range pkgs {
+			err = GetPkgbuild(pkg)
+			if err != nil {
+				fmt.Println(pkg+":", err)
+			}
+		}
+	case "-Qstats":
+		err = LocalStatistics(version)
+	case "-Ss", "-Ssq", "-Sqs":
+		if op == "-Ss" {
+			util.SearchVerbosity = util.Detailed
+		} else {
+			util.SearchVerbosity = util.Minimal
+		}
+
+		if pkgs != nil {
+			err = SyncSearch(pkgs)
+		}
+	case "-S":
+		err = Install(pkgs, options)
+	case "-Syu", "-Suy":
+		err = Upgrade(options)
+	case "-Si":
+		err = SyncInfo(pkgs, options)
+	case "yogurt":
+		util.SearchVerbosity = util.NumberMenu
+
+		if pkgs != nil {
+			err = numberMenu(pkgs, options)
+		}
+	default:
+		err = PassToPacman(op, pkgs, options)
+	}
+
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+}
+
+// NumberMenu presents a CLI for selecting packages to install.
+func numberMenu(pkgS []string, flags []string) (err error) {
+	var num int
+
+	aq, numaq, err := aur.Search(pkgS, true)
+	if err != nil {
+		fmt.Println("Error during AUR search:", err)
+	}
+	pq, numpq, err := pac.Search(pkgS)
+	if err != nil {
+		return
+	}
+
+	if numpq == 0 && numaq == 0 {
+		return fmt.Errorf("no packages match search")
+	}
+
+	if util.SortMode == util.BottomUp {
+		aq.PrintSearch(numpq)
+		pq.PrintSearch()
+	} else {
+		pq.PrintSearch()
+		aq.PrintSearch(numpq)
+	}
+
+	fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.")
+	reader := bufio.NewReader(os.Stdin)
+	numberBuf, overflow, err := reader.ReadLine()
+	if err != nil || overflow {
+		fmt.Println(err)
+		return
+	}
+
+	numberString := string(numberBuf)
+	var aurInstall []string
+	var repoInstall []string
+	result := strings.Fields(numberString)
+	for _, numS := range result {
+		num, err = strconv.Atoi(numS)
+		if err != nil {
+			continue
+		}
+
+		// Install package
+		if num > numaq+numpq-1 || num < 0 {
+			continue
+		} else if num > numpq-1 {
+			if util.SortMode == util.BottomUp {
+				aurInstall = append(aurInstall, aq[numaq+numpq-num-1].Name)
+			} else {
+				aurInstall = append(aurInstall, aq[num-numpq].Name)
+			}
+		} else {
+			if util.SortMode == util.BottomUp {
+				repoInstall = append(repoInstall, pq[numpq-num-1].Name)
+			} else {
+				repoInstall = append(repoInstall, pq[num].Name)
+			}
+		}
+	}
+
+	if len(repoInstall) != 0 {
+		pac.Install(repoInstall, flags)
+	}
+
+	if len(aurInstall) != 0 {
+		q, n, err := aur.MultiInfo(aurInstall)
+		if err != nil {
+			return err
+		} else if n != len(aurInstall) {
+			q.MissingPackage(aurInstall)
+		}
+
+		var finalrm []string
+		for _, aurpkg := range q {
+			finalmdeps, err := aurpkg.Install(flags)
+			finalrm = append(finalrm, finalmdeps...)
+			if err != nil {
+				// Do not abandon program, we might still be able to install the rest
+				fmt.Println(err)
+			}
+		}
+
+		if len(finalrm) != 0 {
+			aur.RemoveMakeDeps(finalrm)
+		}
+	}
+
+	return nil
+}