github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/man/summary_unix.go (about)

     1  //go:build !windows
     2  // +build !windows
     3  
     4  package man
     5  
     6  import (
     7  	"bufio"
     8  	"compress/gzip"
     9  	"io"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/lmorg/murex/utils/cache"
    14  )
    15  
    16  // ParseSummary runs the parser to locate a summary
    17  func ParseSummary(paths []string) string {
    18  	var summary string
    19  	for i := range paths {
    20  		if !rxMatchManSection.MatchString(paths[i]) {
    21  			continue
    22  		}
    23  
    24  		if cache.Read(cache.MAN_SUMMARY, paths[i], &summary) {
    25  			return summary
    26  		}
    27  
    28  		summary = parseSummary(paths[i])
    29  		if summary != "" {
    30  			cache.Write(cache.MAN_SUMMARY, paths[i], summary, cache.Days(30))
    31  			return summary
    32  		}
    33  	}
    34  
    35  	return ""
    36  }
    37  
    38  func parseSummary(filename string) string {
    39  	file, err := os.Open(filename)
    40  	if err != nil {
    41  		return ""
    42  	}
    43  	defer file.Close()
    44  
    45  	if len(filename) > 3 && filename[len(filename)-3:] == ".gz" {
    46  		gz, err := gzip.NewReader(file)
    47  		if err != nil {
    48  			return ""
    49  		}
    50  		defer gz.Close()
    51  
    52  		return parseSummaryFile(gz)
    53  	}
    54  
    55  	return parseSummaryFile(file)
    56  }
    57  
    58  func parseSummaryFile(file io.Reader) string {
    59  	scanner := bufio.NewScanner(file)
    60  
    61  	var (
    62  		read bool
    63  		desc string
    64  	)
    65  
    66  	for scanner.Scan() {
    67  		s := scanner.Text()
    68  
    69  		if strings.Contains(s, "SYNOPSIS") {
    70  			if len(desc) > 0 && desc[len(desc)-1] == '-' {
    71  				desc = desc[:len(desc)-1]
    72  			}
    73  			return strings.TrimSpace(desc)
    74  		}
    75  
    76  		if read {
    77  			// Tidy up man pages generated from reStructuredText
    78  			if strings.HasPrefix(s, `\\n[rst2man-indent`) ||
    79  				strings.HasPrefix(s, `\\$1 \\n`) ||
    80  				strings.HasPrefix(s, `level \\n`) ||
    81  				strings.HasPrefix(s, `level margin: \\n`) {
    82  				continue
    83  			}
    84  
    85  			s = strings.Replace(s, ".Nd ", " - ", -1)
    86  			s = strings.Replace(s, "\\(em ", " - ", -1)
    87  			s = strings.Replace(s, " , ", ", ", -1)
    88  			s = strings.Replace(s, "\\fB", "", -1)
    89  			s = strings.Replace(s, "\\fR", "", -1)
    90  			if strings.HasSuffix(s, " ,") {
    91  				s = s[:len(s)-2] + ", "
    92  			}
    93  			s = rxReplaceMarkup.ReplaceAllString(s, "")
    94  			s = strings.Replace(s, "\\", "", -1)
    95  
    96  			if strings.HasPrefix(s, `.`) {
    97  				continue
    98  			}
    99  
   100  			desc += s
   101  		}
   102  
   103  		if strings.Contains(s, "NAME") {
   104  			read = true
   105  		}
   106  	}
   107  
   108  	return ""
   109  }