Skip to content

Commit 5b487de

Browse files
Merge pull request #1 from brian-pickens/implement-more-spec-codes
Implement more spec codes
2 parents 31a2dd3 + 8abb939 commit 5b487de

36 files changed

+2495
-48
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
66

77
## [Unreleased]
88

9-
- Initial release
9+
- v0.0.1 Highlights Nacha Ach file fields. Supports PPD and CCD entries as well as type 5 addenda records.
10+
- v0.0.2 Adds support for the remaining SEC code entries and addenda records. Highlighting tweeks and support for light and dark themes.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ Is an extension that highlights the fields of an Ach File, giving its name and a
99
### [0.0.1](https://github.com/brian-pickens/vscode-ach-highlighter/releases/tag/0.0.1)
1010

1111
Alpha release - Supports PPD and CCD entries as well as type 5 addenda records.
12+
13+
### [0.0.2](https://github.com/brian-pickens/vscode-ach-highlighter/releases/tag/0.0.1)
14+
15+
Beta release
16+
17+
Adds support for the remaining SEC code entries and addenda records. Highlighting tweeks and support for light and dark themes.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"author": {
88
"name": "Brian Pickens"
99
},
10-
"version": "0.0.1",
10+
"version": "0.0.2",
1111
"engines": {
1212
"vscode": "^1.94.0"
1313
},

src/extension.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,43 @@
11
import * as vscode from 'vscode';
2-
import { Record } from './record';
2+
import { GetRecord } from './record';
33

44
export function activate(context: vscode.ExtensionContext) {
5-
const activeEditor = vscode.window.activeTextEditor;
65
const fieldDecorationType = vscode.window.createTextEditorDecorationType({
6+
borderStyle: 'solid',
7+
borderWidth: "0 0 1px 0",
78
light: {
89
// this color will be used in light color themes
9-
backgroundColor: 'darkGrey'
10+
backgroundColor: 'lightGrey',
11+
borderColor: 'darkRed',
1012
},
1113
dark: {
1214
// this color will be used in dark color themes
13-
backgroundColor: 'lightGrey'
15+
backgroundColor: 'darkGrey',
16+
borderColor: 'lightRed'
1417
}
1518
});
1619

17-
vscode.languages.registerHoverProvider('*', {
20+
// Loop backwards from the current position looking for the previous 5 record and return its sec code.
21+
function GetSecCode(document: vscode.TextDocument, cursor: vscode.Position): string {
22+
let typeCode = "6";
23+
let line = cursor.line;
24+
while (line > 0 && typeCode === "6") {
25+
let lineText = document.lineAt(line).text.substring(0, 94);
26+
let typeCode = lineText.substring(0, 1);
27+
if (typeCode === "5"){
28+
const secCode = lineText.substring(50, 53);
29+
return secCode;
30+
}
31+
line -= 1;
32+
}
33+
return "";
34+
}
35+
36+
vscode.languages.registerHoverProvider('nacha-ach', {
1837
provideHover(document, cursor, token) {
38+
const activeEditor = vscode.window.activeTextEditor;
1939
const text = document.lineAt(cursor.line).text.substring(0, 94);
20-
const record = new Record(text);
40+
const record = GetRecord(text, GetSecCode(document, cursor));
2141
const selectedField = record.getField(cursor.character+1);
2242
if (selectedField === null) { return; }
2343

@@ -28,5 +48,4 @@ ${selectedField.Description}`;
2848
return new vscode.Hover(new vscode.MarkdownString(message));
2949
}
3050
});
31-
3251
}

src/record.ts

Lines changed: 80 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
1-
import * as spec from './nacha-spec.json';
1+
/* eslint-disable @typescript-eslint/naming-convention */
2+
import * as _records from './spec/record-spec.json';
3+
import * as _entries from './spec/entry-spec.json';
4+
import * as _addenda from './spec/addenda-spec.json';
5+
6+
const entries: any = _entries;
7+
const addenda: any = _addenda;
28

39
// Reform the spec to be able to index into the correct record via TypeCode
4-
const indexedSpec = Object.entries(spec).reduce((acc: any, [key, value]) => {
10+
const recordsByTypeCode = Object.entries(_records).reduce((acc: any, [key, value]) => {
511
acc[value.TypeCode] = {
6-
Id: key,
7-
...value // spread operator to keep other properties (Description, Fields, etc.)
12+
Id: key,
13+
...value // spread operator to keep other properties (Description, Fields, etc.)
814
};
915
return acc;
10-
}, {});
16+
}, {});
17+
18+
export interface Record {
19+
Id: string;
20+
Name: string;
21+
TypeCode: string;
22+
Description: string;
23+
Fields: Field[];
24+
Line: string;
25+
getField(position: number): SpecField | null;
26+
}
1127

12-
interface Field {
28+
export interface Field {
1329
Id: string;
1430
Name: string;
1531
StartPosition: number;
1632
EndPosition: number;
1733
Description: string;
1834
Value: string;
35+
Parent: Record;
1936
}
2037

2138
class FileControlPaddingField implements Field {
@@ -25,7 +42,9 @@ class FileControlPaddingField implements Field {
2542
EndPosition: number;
2643
Description: string;
2744
Value: string;
28-
constructor(line: string){
45+
Parent: Record;
46+
constructor(parent: Record, line: string) {
47+
this.Parent = parent;
2948
this.Id = "FileControlPadding";
3049
this.Name = "File Control Padding";
3150
this.StartPosition = 0;
@@ -42,47 +61,71 @@ class SpecField implements Field {
4261
EndPosition: number;
4362
Description: string;
4463
Value: string;
45-
constructor(parent: Record, fieldId: string){
46-
this.Id = fieldId;
47-
this.Name = indexedSpec[parent.TypeCode].Fields[fieldId].Name;
48-
this.StartPosition = indexedSpec[parent.TypeCode].Fields[fieldId].StartPosition-1;
49-
this.EndPosition =indexedSpec[parent.TypeCode].Fields[fieldId].EndPosition;
50-
this.Description = indexedSpec[parent.TypeCode].Fields[fieldId].Description;
64+
Parent: Record;
65+
constructor(parent: Record, id: string, spec: any) {
66+
this.Parent = parent;
67+
this.Id = id;
68+
this.Name = spec.Name;
69+
this.StartPosition = spec.StartPosition - 1;
70+
this.EndPosition = spec.EndPosition;
71+
this.Description = spec.Description;
5172
this.Value = parent.Line.substring(this.StartPosition, this.EndPosition);
5273
}
5374
}
5475

55-
export class Record {
56-
Id: string;
57-
Name: string;
58-
TypeCode: string;
59-
Description: string;
76+
class SpecRecord implements Record {
77+
Id: string = "";
78+
Name: string = "";
79+
TypeCode: string = "";
80+
Description: string = "";
6081
Fields: Field[] = [];
61-
Line: string;
62-
63-
constructor(line: string){
64-
this.Line = line;
65-
this.TypeCode = line.substring(0,1);
66-
this.Name = indexedSpec[this.TypeCode].Name;
67-
this.Id = indexedSpec[this.TypeCode].Id;
68-
this.Description = indexedSpec[this.TypeCode].Description;
82+
Line: string = "";
6983

70-
if (line.startsWith('99999')) {
71-
this.Fields.push(new FileControlPaddingField(line));
72-
}
73-
74-
for (const key in indexedSpec[this.TypeCode].Fields) {
75-
let field = new SpecField(this, key);
76-
this.Fields.push(field);
77-
}
78-
}
79-
80-
public getField(position: number): SpecField|null {
84+
public getField(position: number): SpecField | null {
8185
for (const field of this.Fields) {
8286
if (position >= field.StartPosition && position <= field.EndPosition) {
8387
return field;
8488
}
8589
}
8690
return null;
8791
}
92+
}
93+
94+
export function GetRecord(line: string, secCode?: string): Record{
95+
const record = new SpecRecord();
96+
record.Line = line;
97+
record.TypeCode = line.substring(0, 1);
98+
record.Id = recordsByTypeCode[record.TypeCode].Id;
99+
record.Name = recordsByTypeCode[record.TypeCode].Name;
100+
record.Description = recordsByTypeCode[record.TypeCode].Description;
101+
102+
switch (record.TypeCode) {
103+
case "6":
104+
if (secCode === undefined || secCode === "") {
105+
throw new Error("An SEC code is required to create an entry record.");
106+
}
107+
for (const key in entries[secCode].Fields) {
108+
let field = new SpecField(record, key, entries[secCode].Fields[key]);
109+
record.Fields.push(field);
110+
}
111+
break;
112+
case "7":
113+
const addendaTypeCode = line.substring(1,3);
114+
for (const key in addenda[addendaTypeCode].Fields) {
115+
let field = new SpecField(record, key, addenda[addendaTypeCode].Fields[key]);
116+
record.Fields.push(field);
117+
}
118+
break;
119+
default:
120+
if (line.startsWith('99999')) {
121+
record.Fields.push(new FileControlPaddingField(record, line));
122+
}
123+
for (const key in recordsByTypeCode[record.TypeCode].Fields) {
124+
let field = new SpecField(record, key, recordsByTypeCode[record.TypeCode].Fields[key]);
125+
record.Fields.push(field);
126+
}
127+
break;
128+
}
129+
130+
return record;
88131
}

0 commit comments

Comments
 (0)