mirror of
https://gitlab.com/aviortheking/code-stats-vscode.git
synced 2025-06-07 15:59:54 +00:00
Change detection and tracking.
This commit is contained in:
parent
69f89cc4c4
commit
cb048907f3
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
out
|
out
|
||||||
node_modules
|
node_modules
|
||||||
|
.vscode-test/
|
||||||
|
@ -11,14 +11,11 @@
|
|||||||
"Other"
|
"Other"
|
||||||
],
|
],
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"onCommand:codestats.sayHello"
|
"*"
|
||||||
],
|
],
|
||||||
"main": "./out/src/code-stats",
|
"main": "./out/src/code-stats",
|
||||||
"contributes": {
|
"contributes": {
|
||||||
"commands": [{
|
"commands": []
|
||||||
"command": "codestats.sayHello",
|
|
||||||
"title": "Code::Stats"
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"vscode:prepublish": "tsc -p ./",
|
"vscode:prepublish": "tsc -p ./",
|
||||||
|
@ -1,34 +1,17 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
// the module 'vscode' contains the VS Code extensibility API
|
import { ExtensionContext } from "vscode";
|
||||||
// import the module and reference it with the alias vscode in your code below
|
import { XpCounter } from "./xp-counter";
|
||||||
import * as vscode from "vscode";
|
|
||||||
|
|
||||||
// this method is called when your extension is activated
|
export function activate(context: ExtensionContext): void {
|
||||||
// your extension is activated the very first time the command is executed
|
console.log("Activating code-stats-vscode");
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
|
||||||
|
|
||||||
// use the console to output diagnostic information (console.log) and errors (console.error)
|
let controller: XpCounter = new XpCounter();
|
||||||
// this line of code will only be executed once when your extension is activated
|
|
||||||
console.log("Congratulations, your extension \"code-stats-vscode\" is now active!");
|
|
||||||
|
|
||||||
// the command has been defined in the package.json file
|
// add to a list of disposables which are disposed when this extension is deactivated.
|
||||||
// now provide the implementation of the command with registerCommand
|
context.subscriptions.push(controller);
|
||||||
// the commandId parameter must match the command field in package.json
|
|
||||||
let disposable: vscode.Disposable = vscode.commands.registerCommand("codestats.sayHello", () => {
|
|
||||||
var editor: vscode.TextEditor = vscode.window.activeTextEditor;
|
|
||||||
if (!editor) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var selection: vscode.Selection = editor.selection;
|
|
||||||
var text: string = editor.document.getText(selection);
|
|
||||||
|
|
||||||
vscode.window.showInformationMessage("Selected characters: " + text.length);
|
|
||||||
});
|
|
||||||
|
|
||||||
context.subscriptions.push(disposable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is called when your extension is deactivated
|
// this method is called when your extension is deactivated
|
||||||
export function deactivate() {
|
export function deactivate(): void {
|
||||||
}
|
console.log("Deactivating code-stats-vscode");
|
||||||
|
}
|
||||||
|
28
src/pulse.ts
Normal file
28
src/pulse.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
export class Pulse {
|
||||||
|
xps: Map < string, number > ;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
console.log("Creating Pulse");
|
||||||
|
this.xps = new Map < string, number > ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getXP(language: string): number {
|
||||||
|
let xp: number = this.xps.get(language);
|
||||||
|
|
||||||
|
if (xp === null || xp === undefined) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return xp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public addXP(language: string, amount: number): void {
|
||||||
|
let xp: number = this.getXP(language);
|
||||||
|
|
||||||
|
xp += amount;
|
||||||
|
|
||||||
|
this.xps.set(language, xp);
|
||||||
|
|
||||||
|
// console.log(`Added ${amount} of XP to ${language}, total is now ${xp}`);
|
||||||
|
}
|
||||||
|
}
|
20
src/utils.ts
Normal file
20
src/utils.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// converted to ts from https://github.com/Nicd/code-stats-atom/blob/master/lib/utils.js
|
||||||
|
export function getISOTimestamp(date: Date): string {
|
||||||
|
const offset: number = -date.getTimezoneOffset();
|
||||||
|
const prefix: string = (offset >= 0) ? "+" : "-";
|
||||||
|
|
||||||
|
function pad(num: number): string {
|
||||||
|
const norm: number = Math.abs(Math.floor(num));
|
||||||
|
|
||||||
|
return ((norm < 10) ? "0" : "") + norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.getFullYear() +
|
||||||
|
"-" + pad(date.getMonth() + 1) +
|
||||||
|
"-" + pad(date.getDate()) +
|
||||||
|
"T" + pad(date.getHours()) +
|
||||||
|
":" + pad(date.getMinutes()) +
|
||||||
|
":" + pad(date.getSeconds()) +
|
||||||
|
prefix + pad(offset / 60) +
|
||||||
|
pad(offset % 60);
|
||||||
|
}
|
72
src/xp-counter.ts
Normal file
72
src/xp-counter.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { Disposable, workspace, window, StatusBarItem, TextDocument, StatusBarAlignment, TextDocumentChangeEvent, Range } from "vscode";
|
||||||
|
import { Pulse } from "./pulse";
|
||||||
|
|
||||||
|
export class XpCounter {
|
||||||
|
private combinedDisposable: Disposable;
|
||||||
|
private statusBarItem: StatusBarItem;
|
||||||
|
private pulse: Pulse;
|
||||||
|
private languages: Array<string> = ["typescript", "javascript"];
|
||||||
|
private changeCount: number = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
console.log(`Supported languages for Code::Stats are ${this.languages}`);
|
||||||
|
this.pulse = new Pulse();
|
||||||
|
|
||||||
|
if (!this.statusBarItem) {
|
||||||
|
this.statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
|
||||||
|
}
|
||||||
|
|
||||||
|
let subscriptions: Disposable[] = [];
|
||||||
|
workspace.onDidChangeTextDocument(this.onTextDocumentChanged, this, subscriptions);
|
||||||
|
this.combinedDisposable = Disposable.from(...subscriptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this.combinedDisposable.dispose();
|
||||||
|
this.statusBarItem.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onTextDocumentChanged(event: TextDocumentChangeEvent): void {
|
||||||
|
let changeCount: number = 0;
|
||||||
|
for (let change of event.contentChanges) {
|
||||||
|
changeCount += this.determineChangeCount(change.range);
|
||||||
|
}
|
||||||
|
this.updateXpCount(event.document, changeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private determineChangeCount(range: Range): number {
|
||||||
|
if (range === null || range === undefined ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// console.log(`L${range.start.line}C${range.start.character} to L${range.end.line}C${range.end.character}`);
|
||||||
|
if (range.start.line === range.end.line) {
|
||||||
|
if (range.start.character === range.end.character) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
console.log(`L${range.start.line}C${range.start.character} to L${range.end.line}C${range.end.character}`);
|
||||||
|
return range.end.character - range.start.character;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// todo detect multiline changes
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateXpCount(document: TextDocument, changeCount: number): void {
|
||||||
|
// only update xp if one of supported languages
|
||||||
|
if (this.isSupportedLanguage(document.languageId)) {
|
||||||
|
this.pulse.addXP(document.languageId, changeCount);
|
||||||
|
// this.statusBarItem.text = this.changeCount !== 1 ?
|
||||||
|
// ` C::S ${this.changeCount} Words` : "$(pencil) C::S 1 Word";
|
||||||
|
this.statusBarItem.text = `C::S $(pencil) ${this.pulse.getXP(document.languageId)}`;
|
||||||
|
this.statusBarItem.show();
|
||||||
|
} else {
|
||||||
|
this.statusBarItem.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private isSupportedLanguage(language: string): boolean {
|
||||||
|
// todo: check supported languages
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,22 +1,53 @@
|
|||||||
//
|
import * as assert from "assert";
|
||||||
// Note: This example test is leveraging the Mocha test framework.
|
|
||||||
// Please refer to their documentation on https://mochajs.org/ for help.
|
|
||||||
//
|
|
||||||
|
|
||||||
// The module 'assert' provides assertion methods from node
|
// tslint:disable-next-line:no-unused-variable
|
||||||
import * as assert from 'assert';
|
import * as vscode from "vscode";
|
||||||
|
// tslint:disable-next-line:no-unused-variable
|
||||||
|
import * as codestats from "../src/code-stats";
|
||||||
|
import { Pulse } from "../src/pulse";
|
||||||
|
|
||||||
// You can import and use all API from the 'vscode' module
|
suite("code-stats-vscode extension tests", () => {
|
||||||
// as well as import your extension to test it
|
test("Initialized Pulse is empty", () => {
|
||||||
import * as vscode from 'vscode';
|
let pulse: Pulse = new Pulse();
|
||||||
import * as myExtension from '../src/code-stats';
|
const language: string = "typescript";
|
||||||
|
|
||||||
// Defines a Mocha test suite to group tests of similar kind together
|
let initialXP: number = pulse.getXP(language);
|
||||||
suite("Extension Tests", () => {
|
|
||||||
|
|
||||||
// Defines a Mocha unit test
|
assert.equal(initialXP, 0);
|
||||||
test("Something 1", () => {
|
});
|
||||||
assert.equal(-1, [1, 2, 3].indexOf(5));
|
|
||||||
assert.equal(-1, [1, 2, 3].indexOf(0));
|
test("Add XP to Pulse", () => {
|
||||||
|
let pulse: Pulse = new Pulse();
|
||||||
|
|
||||||
|
const language1: string = "typescript";
|
||||||
|
const language2: string = "javascript";
|
||||||
|
const language3: string = "coffeescript";
|
||||||
|
const addedXP: number = 1000;
|
||||||
|
|
||||||
|
let xp1: number = pulse.getXP(language1);
|
||||||
|
let xp2: number = pulse.getXP(language2);
|
||||||
|
let xp3: number = pulse.getXP(language3);
|
||||||
|
assert.equal(xp1, 0);
|
||||||
|
assert.equal(xp2, 0);
|
||||||
|
assert.equal(xp3, 0);
|
||||||
|
|
||||||
|
pulse.addXP(language1, addedXP);
|
||||||
|
xp1 = pulse.getXP(language1);
|
||||||
|
xp2 = pulse.getXP(language2);
|
||||||
|
xp3 = pulse.getXP(language3);
|
||||||
|
|
||||||
|
assert.equal(xp1, addedXP);
|
||||||
|
assert.equal(xp2, 0);
|
||||||
|
assert.equal(xp3, 0);
|
||||||
|
|
||||||
|
pulse.addXP(language1, addedXP);
|
||||||
|
pulse.addXP(language2, addedXP);
|
||||||
|
xp1 = pulse.getXP(language1);
|
||||||
|
xp2 = pulse.getXP(language2);
|
||||||
|
xp3 = pulse.getXP(language3);
|
||||||
|
|
||||||
|
assert.equal(xp1, 2 * addedXP);
|
||||||
|
assert.equal(xp2, addedXP);
|
||||||
|
assert.equal(xp3, 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
Loading…
x
Reference in New Issue
Block a user