OXYGENHUB
# f902d5b8bfeb oxygenhub-vscode / src / refs.ts
1.8 KiB · last changed #N and @user completion, and hovers on #N (0.4.0) 1 month ago source blame history raw
f902d5b8 Andy McCall ↶ 1
// `#N` and `@user` in text the user is typing (spec §6.2): what is being
2
// completed at the cursor, and which reference a position sits on. No
3
// vscode imports, so it is tested with plain Node.
4
5
/** A reference being typed: `#12` (issue or proposal) or `@an` (a user). */
6
export type Typing = { kind: "number"; prefix: string; start: number } | { kind: "user"; prefix: string; start: number };
7
8
/**
9
 * What the text before the cursor is in the middle of typing, if anything.
10
 * A reference starts a word: after the line start, whitespace or an
11
 * opening bracket, so `a#1` and `mail@host` are not references.
12
 */
13
export function typingAt(before: string): Typing | undefined {
14
  const n = /(^|[\s([{])#(\d*)$/.exec(before);
15
  if (n) {
16
    return { kind: "number", prefix: n[2], start: before.length - n[2].length - 1 };
17
  }
18
  const u = /(^|[\s([{])@([A-Za-z0-9][A-Za-z0-9_-]*|)$/.exec(before);
19
  if (u) {
20
    return { kind: "user", prefix: u[2], start: before.length - u[2].length - 1 };
21
  }
22
  return undefined;
23
}
24
25
/** The `#N` reference covering `column` of `line`, with its span. */
26
export function numberAt(line: string, column: number): { number: number; start: number; end: number } | undefined {
27
  const re = /(^|[\s([{])#(\d+)\b/g;
28
  for (let m = re.exec(line); m; m = re.exec(line)) {
29
    const start = m.index + m[1].length;
30
    const end = start + 1 + m[2].length;
31
    if (column >= start && column <= end) {
32
      return { number: Number(m[2]), start, end };
33
    }
34
  }
35
  return undefined;
36
}
37
38
/** A repository root named by an SCM input box's URI query (`rootUri=file:///…`). */
39
export function rootFromScmQuery(query: string): string | undefined {
40
  const raw = new URLSearchParams(query).get("rootUri");
41
  if (!raw) {
42
    return undefined;
43
  }
44
  try {
45
    return decodeURIComponent(new URL(raw).pathname);
46
  } catch {
47
    return undefined;
48
  }
49
}