Skip to content

Commit

Permalink
Merge pull request #1 from brian-pickens/implement-more-spec-codes
Browse files Browse the repository at this point in the history
Implement more spec codes
  • Loading branch information
brian-pickens authored Jan 3, 2025
2 parents 31a2dd3 + 8abb939 commit 5b487de
Show file tree
Hide file tree
Showing 36 changed files with 2,495 additions and 48 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how

## [Unreleased]

- Initial release
- v0.0.1 Highlights Nacha Ach file fields. Supports PPD and CCD entries as well as type 5 addenda records.
- v0.0.2 Adds support for the remaining SEC code entries and addenda records. Highlighting tweeks and support for light and dark themes.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ Is an extension that highlights the fields of an Ach File, giving its name and a
### [0.0.1](https://github.com/brian-pickens/vscode-ach-highlighter/releases/tag/0.0.1)

Alpha release - Supports PPD and CCD entries as well as type 5 addenda records.

### [0.0.2](https://github.com/brian-pickens/vscode-ach-highlighter/releases/tag/0.0.1)

Beta release

Adds support for the remaining SEC code entries and addenda records. Highlighting tweeks and support for light and dark themes.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"author": {
"name": "Brian Pickens"
},
"version": "0.0.1",
"version": "0.0.2",
"engines": {
"vscode": "^1.94.0"
},
Expand Down
33 changes: 26 additions & 7 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
import * as vscode from 'vscode';
import { Record } from './record';
import { GetRecord } from './record';

export function activate(context: vscode.ExtensionContext) {
const activeEditor = vscode.window.activeTextEditor;
const fieldDecorationType = vscode.window.createTextEditorDecorationType({
borderStyle: 'solid',
borderWidth: "0 0 1px 0",
light: {
// this color will be used in light color themes
backgroundColor: 'darkGrey'
backgroundColor: 'lightGrey',
borderColor: 'darkRed',
},
dark: {
// this color will be used in dark color themes
backgroundColor: 'lightGrey'
backgroundColor: 'darkGrey',
borderColor: 'lightRed'
}
});

vscode.languages.registerHoverProvider('*', {
// Loop backwards from the current position looking for the previous 5 record and return its sec code.
function GetSecCode(document: vscode.TextDocument, cursor: vscode.Position): string {
let typeCode = "6";
let line = cursor.line;
while (line > 0 && typeCode === "6") {
let lineText = document.lineAt(line).text.substring(0, 94);
let typeCode = lineText.substring(0, 1);
if (typeCode === "5"){
const secCode = lineText.substring(50, 53);
return secCode;
}
line -= 1;
}
return "";
}

vscode.languages.registerHoverProvider('nacha-ach', {
provideHover(document, cursor, token) {
const activeEditor = vscode.window.activeTextEditor;
const text = document.lineAt(cursor.line).text.substring(0, 94);
const record = new Record(text);
const record = GetRecord(text, GetSecCode(document, cursor));
const selectedField = record.getField(cursor.character+1);
if (selectedField === null) { return; }

Expand All @@ -28,5 +48,4 @@ ${selectedField.Description}`;
return new vscode.Hover(new vscode.MarkdownString(message));
}
});

}
117 changes: 80 additions & 37 deletions src/record.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
import * as spec from './nacha-spec.json';
/* eslint-disable @typescript-eslint/naming-convention */
import * as _records from './spec/record-spec.json';
import * as _entries from './spec/entry-spec.json';
import * as _addenda from './spec/addenda-spec.json';

const entries: any = _entries;
const addenda: any = _addenda;

// Reform the spec to be able to index into the correct record via TypeCode
const indexedSpec = Object.entries(spec).reduce((acc: any, [key, value]) => {
const recordsByTypeCode = Object.entries(_records).reduce((acc: any, [key, value]) => {
acc[value.TypeCode] = {
Id: key,
...value // spread operator to keep other properties (Description, Fields, etc.)
Id: key,
...value // spread operator to keep other properties (Description, Fields, etc.)
};
return acc;
}, {});
}, {});

export interface Record {
Id: string;
Name: string;
TypeCode: string;
Description: string;
Fields: Field[];
Line: string;
getField(position: number): SpecField | null;
}

interface Field {
export interface Field {
Id: string;
Name: string;
StartPosition: number;
EndPosition: number;
Description: string;
Value: string;
Parent: Record;
}

class FileControlPaddingField implements Field {
Expand All @@ -25,7 +42,9 @@ class FileControlPaddingField implements Field {
EndPosition: number;
Description: string;
Value: string;
constructor(line: string){
Parent: Record;
constructor(parent: Record, line: string) {
this.Parent = parent;
this.Id = "FileControlPadding";
this.Name = "File Control Padding";
this.StartPosition = 0;
Expand All @@ -42,47 +61,71 @@ class SpecField implements Field {
EndPosition: number;
Description: string;
Value: string;
constructor(parent: Record, fieldId: string){
this.Id = fieldId;
this.Name = indexedSpec[parent.TypeCode].Fields[fieldId].Name;
this.StartPosition = indexedSpec[parent.TypeCode].Fields[fieldId].StartPosition-1;
this.EndPosition =indexedSpec[parent.TypeCode].Fields[fieldId].EndPosition;
this.Description = indexedSpec[parent.TypeCode].Fields[fieldId].Description;
Parent: Record;
constructor(parent: Record, id: string, spec: any) {
this.Parent = parent;
this.Id = id;
this.Name = spec.Name;
this.StartPosition = spec.StartPosition - 1;
this.EndPosition = spec.EndPosition;
this.Description = spec.Description;
this.Value = parent.Line.substring(this.StartPosition, this.EndPosition);
}
}

export class Record {
Id: string;
Name: string;
TypeCode: string;
Description: string;
class SpecRecord implements Record {
Id: string = "";
Name: string = "";
TypeCode: string = "";
Description: string = "";
Fields: Field[] = [];
Line: string;

constructor(line: string){
this.Line = line;
this.TypeCode = line.substring(0,1);
this.Name = indexedSpec[this.TypeCode].Name;
this.Id = indexedSpec[this.TypeCode].Id;
this.Description = indexedSpec[this.TypeCode].Description;
Line: string = "";

if (line.startsWith('99999')) {
this.Fields.push(new FileControlPaddingField(line));
}

for (const key in indexedSpec[this.TypeCode].Fields) {
let field = new SpecField(this, key);
this.Fields.push(field);
}
}

public getField(position: number): SpecField|null {
public getField(position: number): SpecField | null {
for (const field of this.Fields) {
if (position >= field.StartPosition && position <= field.EndPosition) {
return field;
}
}
return null;
}
}

export function GetRecord(line: string, secCode?: string): Record{
const record = new SpecRecord();
record.Line = line;
record.TypeCode = line.substring(0, 1);
record.Id = recordsByTypeCode[record.TypeCode].Id;
record.Name = recordsByTypeCode[record.TypeCode].Name;
record.Description = recordsByTypeCode[record.TypeCode].Description;

switch (record.TypeCode) {
case "6":
if (secCode === undefined || secCode === "") {
throw new Error("An SEC code is required to create an entry record.");
}
for (const key in entries[secCode].Fields) {
let field = new SpecField(record, key, entries[secCode].Fields[key]);
record.Fields.push(field);
}
break;
case "7":
const addendaTypeCode = line.substring(1,3);
for (const key in addenda[addendaTypeCode].Fields) {
let field = new SpecField(record, key, addenda[addendaTypeCode].Fields[key]);
record.Fields.push(field);
}
break;
default:
if (line.startsWith('99999')) {
record.Fields.push(new FileControlPaddingField(record, line));
}
for (const key in recordsByTypeCode[record.TypeCode].Fields) {
let field = new SpecField(record, key, recordsByTypeCode[record.TypeCode].Fields[key]);
record.Fields.push(field);
}
break;
}

return record;
}
Loading

0 comments on commit 5b487de

Please sign in to comment.