main

mattermost/focalboard

Last updated at: 29/12/2023 09:47

extract.go

TLDR

This file contains a Go package notifymentions that provides functionality for extracting a subset of text based on mentions within the text.

Methods

extractText

This method takes in a string s, a mention string, and a set of limits. It finds the position of the mention within the text and returns a subset of the text based on the number of lines preceding and following the mention, as well as the maximum number of characters before and after the mention.

safeConcat

This method takes in an array of strings lines, a start index, and an end index. It concatenates a subset of the lines delimited by the start and end indices, handling empty lines properly.

safeSubstr

This method takes in a string s, a start index, and an end index. It returns a substring of s delimited by the start and end indices.

min

This method takes in two integers a and b and returns the minimum value between them.

max

This method takes in two integers a and b and returns the maximum value between them.

Functions

newLimits

This function returns a limits struct with default values for the number of prefix lines, maximum prefix characters, suffix lines, and maximum suffix characters.

Constants

  • defPrefixLines: The default number of lines preceding the mention to include in the extracted text.
  • defPrefixMaxChars: The default maximum number of characters before the mention to include in the extracted text.
  • defSuffixLines: The default number of lines following the mention to include in the extracted text.
  • defSuffixMaxChars: The default maximum number of characters after the mention to include in the extracted text.
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

package notifymentions

import "strings"

const (
	defPrefixLines    = 2
	defPrefixMaxChars = 100
	defSuffixLines    = 2
	defSuffixMaxChars = 100
)

type limits struct {
	prefixLines    int
	prefixMaxChars int
	suffixLines    int
	suffixMaxChars int
}

func newLimits() limits {
	return limits{
		prefixLines:    defPrefixLines,
		prefixMaxChars: defPrefixMaxChars,
		suffixLines:    defSuffixLines,
		suffixMaxChars: defSuffixMaxChars,
	}
}

// extractText returns all or a subset of the input string, such that
// no more than `prefixLines` lines preceding the mention and `suffixLines`
// lines after the mention are returned, and no more than approx
// prefixMaxChars+suffixMaxChars are returned.
func extractText(s string, mention string, limits limits) string {
	if !strings.HasPrefix(mention, "@") {
		mention = "@" + mention
	}
	lines := strings.Split(s, "\n")

	// find first line with mention
	found := -1
	for i, l := range lines {
		if strings.Contains(l, mention) {
			found = i
			break
		}
	}
	if found == -1 {
		return ""
	}

	prefix := safeConcat(lines, found-limits.prefixLines, found)
	suffix := safeConcat(lines, found+1, found+limits.suffixLines+1)
	combined := strings.TrimSpace(strings.Join([]string{prefix, lines[found], suffix}, "\n"))

	// find mention position within
	pos := strings.Index(combined, mention)
	pos = max(pos, 0)

	return safeSubstr(combined, pos-limits.prefixMaxChars, pos+limits.suffixMaxChars)
}

func safeConcat(lines []string, start int, end int) string {
	count := len(lines)
	start = min(max(start, 0), count)
	end = min(max(end, start), count)

	var sb strings.Builder
	for i := start; i < end; i++ {
		if lines[i] != "" {
			sb.WriteString(lines[i])
			sb.WriteByte('\n')
		}
	}
	return strings.TrimSpace(sb.String())
}

func safeSubstr(s string, start int, end int) string {
	count := len(s)
	start = min(max(start, 0), count)
	end = min(max(end, start), count)
	return s[start:end]
}

func min(a int, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a int, b int) int {
	if a > b {
		return a
	}
	return b
}