1package main
2
3import (
4	"path/filepath"
5	"strconv"
6	"strings"
7)
8
9type (
10	// LineNumber is a number from 1 to the last line (counts lines from 1)
11	LineNumber int
12
13	// LineIndex is a number from 0 to the last line (counts lines from 0)
14	LineIndex int
15
16	// CharacterPosition is a number from 0 to the last character (counts characters from 0)
17	CharacterPosition int
18
19	// ColNumber is a number from 1 and up (counts columns from 1)
20	ColNumber int
21
22	// ColIndex is a number from 0 and up (counts lines from 0)
23	ColIndex int
24)
25
26// String converts a LineNumber to a string
27func (ln LineNumber) String() string {
28	return strconv.Itoa(int(ln))
29}
30
31// String converts a LineIndex to a string
32func (li LineIndex) String() string {
33	return strconv.Itoa(int(li))
34}
35
36// String converts a ColIndex to a string
37func (ci ColIndex) String() string {
38	return strconv.Itoa(int(ci))
39}
40
41// LineIndex converts a LineNumber to a LineIndex by subtracting 1
42func (ln LineNumber) LineIndex() LineIndex {
43	return LineIndex(ln - 1)
44}
45
46// ColIndex converts a ColNumber to a ColIndex by subtracting 1
47func (cn ColNumber) ColIndex() ColIndex {
48	return ColIndex(cn - 1)
49}
50
51// LineNumber converts a LineIndex to a LineNumber by adding 1
52func (li LineIndex) LineNumber() LineNumber {
53	return LineNumber(li + 1)
54}
55
56// ColNumber converts a ColIndex to a ColNumber by adding 1
57func (ci ColIndex) ColNumber() ColNumber {
58	return ColNumber(ci + 1)
59}
60
61// FilenameAndLineNumberAndColNumber will take the first two arguments and return a filename and a line number (can be 0)
62// If the second argument is a number, that will be used as the line number. Or:
63// If the second argument is a number prefixed with a "+", that will be used as the line number. Or:
64// If the filename ends with a ":" and a number, that will be used as the line number.
65func FilenameAndLineNumberAndColNumber(filename, lineNumberString, colNumberString string) (string, LineNumber, ColNumber) {
66	lineNumber := 0
67	colNumber := 0
68	if lineNumberConverted, err := strconv.Atoi(lineNumberString); err == nil { // no error
69		lineNumber = lineNumberConverted
70	} else if strings.HasPrefix(lineNumberString, "+") {
71		if lineNumberConverted, err := strconv.Atoi(lineNumberString[1:]); err == nil { // no error
72			lineNumber = lineNumberConverted
73		}
74	} else if strings.Contains(filepath.Base(filename), ":") {
75		fields := strings.SplitN(filename, ":", 2)
76		if lineNumberConverted, err := strconv.Atoi(fields[1]); err == nil { // no error
77			lineNumber = lineNumberConverted
78			filename = fields[0]
79		}
80	} else if strings.Contains(filepath.Base(filename), "+") {
81		fields := strings.SplitN(filename, "+", 2)
82		if lineNumberConverted, err := strconv.Atoi(fields[1]); err == nil { // no error
83			lineNumber = lineNumberConverted
84			filename = fields[0]
85		}
86	}
87	if colNumberConverted, err := strconv.Atoi(colNumberString); err == nil { // no error
88		colNumber = colNumberConverted
89	} else if strings.HasPrefix(colNumberString, "+") {
90		if colNumberConverted, err := strconv.Atoi(colNumberString[1:]); err == nil { // no error
91			colNumber = colNumberConverted
92		}
93	}
94	return filename, LineNumber(lineNumber), ColNumber(colNumber)
95}
96