You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: plugin_install.go
    path of file: ./repos/steampipe/pkg/display
    
    the code of the file until where you have to start completion: package display

import (
	"fmt"
	"sort"
	"strings"

	"github.com/turbot/steampipe/pkg/constants"
	"github.com/turbot/steampipe/pkg/ociinstaller"
	"github.com/turbot/steampipe/pkg/utils"
)

type PluginInstallReports []*PluginInstallReport

// making the type compatible with sort.Interface so that we can use the sort package utilities
func 
    
func PrintInstallReports(reports PluginInstallReports, isUpdateReport bool) {
	installedOrUpdated := PluginInstallReports{}
	canBeInstalled := PluginInstallReports{}
	canBeUpdated := PluginInstallReports{}
	notFound := PluginInstallReports{}

	for _, report := range reports {
		report.IsUpdateReport = isUpdateReport
		if !report.Skipped {
			installedOrUpdated = append(installedOrUpdated, report)
		} else if report.SkipReason == constants.InstallMessagePluginNotInstalled {
			canBeInstalled = append(canBeInstalled, report)
		} else if report.SkipReason == constants.InstallMessagePluginAlreadyInstalled {
			canBeUpdated = append(canBeUpdated, report)
		} else if report.SkipReason == constants.InstallMessagePluginNotFound {
			notFound = append(notFound, report)
		}
	}

	// sort the report
	sort.Stable(reports)
	// sort the individual chunks
	sort.Stable(installedOrUpdated)
	sort.Stable(canBeInstalled)
	sort.Stable(canBeUpdated)
	sort.Stable(notFound)

	if len(installedOrUpdated) > 0 {
		fmt.Println()
		asString := []string{}
		for _, report := range installedOrUpdated {
			asString = append(asString, report.installString())
		}
		fmt.Println(strings.Join(asString, "\n\n"))
	}

	if len(installedOrUpdated) < len(reports) {
		installSkipReports := []string{}
		for _, report := range reports {
			showReport := true
			if report.SkipReason == constants.InstallMessagePluginAlreadyInstalled || report.SkipReason == constants.InstallMessagePluginLatestAlreadyInstalled {
				showReport = false
			}
			if report.Skipped && showReport {
				installSkipReports = append(installSkipReports, report.skipString())
			}
		}

		skipCount := len(installSkipReports)
		if (len(installSkipReports)) > 0 {
			fmt.Printf(
				"\nSkipped the following %s:\n\n%s\n",
				utils.Pluralize("plugin", skipCount),
				strings.Join(installSkipReports, "\n\n"),
			)
		}

		if len(canBeInstalled) > 0 {
			pluginList := []string{}
			for _, r := range canBeInstalled {
				pluginList = append(pluginList, r.Plugin)
			}
			fmt.Println()
			fmt.Printf(
				"To install %s which %s not installed, please run %s\n",
				utils.Pluralize("plugin", len(canBeInstalled)),
				utils.Pluralize("is", len(canBeInstalled)),
				constants.Bold(fmt.Sprintf(
					"steampipe plugin install %s",
					strings.Join(pluginList, " "),
				)),
			)
		}

		if len(canBeUpdated) > 0 {
			pluginList := []string{}
			for _, r := range canBeUpdated {
				pluginList = append(pluginList, r.Plugin)
			}
			fmt.Println()
			fmt.Printf(
				"To update %s %s: %s\nTo update all plugins: %s",
				utils.Pluralize("this", len(pluginList)),
				utils.Pluralize("plugin", len(pluginList)),
				constants.Bold(fmt.Sprintf("steampipe plugin update %s", strings.Join(pluginList, " "))),
				constants.Bold(fmt.Sprintln("steampipe plugin update --all")),
			)
		}
	}
}