2020-12-28 16:06:36 +02:00
|
|
|
///
|
2023-01-31 10:43:56 +02:00
|
|
|
/// Copyright © 2016-2023 The Thingsboard Authors
|
2020-12-28 16:06:36 +02:00
|
|
|
///
|
|
|
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
/// you may not use this file except in compliance with the License.
|
|
|
|
|
/// You may obtain a copy of the License at
|
|
|
|
|
///
|
|
|
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
///
|
|
|
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
/// See the License for the specific language governing permissions and
|
|
|
|
|
/// limitations under the License.
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
import { Ace } from 'ace-builds';
|
|
|
|
|
import { Observable } from 'rxjs/internal/Observable';
|
|
|
|
|
import { forkJoin, from, of } from 'rxjs';
|
|
|
|
|
import { map, mergeMap, tap } from 'rxjs/operators';
|
|
|
|
|
|
|
|
|
|
let aceDependenciesLoaded = false;
|
|
|
|
|
let aceModule: any;
|
2022-05-27 13:14:18 +03:00
|
|
|
let aceDiffModule: any;
|
2020-12-28 16:06:36 +02:00
|
|
|
|
2021-11-04 18:05:13 +02:00
|
|
|
function loadAceDependencies(): Observable<any> {
|
2020-12-28 16:06:36 +02:00
|
|
|
if (aceDependenciesLoaded) {
|
|
|
|
|
return of(null);
|
|
|
|
|
} else {
|
|
|
|
|
const aceObservables: Observable<any>[] = [];
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/ext-language_tools')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/ext-searchbox')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-java')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-css')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-json')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-javascript')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-text')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-markdown')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-html')));
|
2021-10-27 11:08:57 +03:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-c_cpp')));
|
2021-10-26 07:31:24 +03:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/mode-protobuf')));
|
2020-12-28 16:06:36 +02:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/java')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/css')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/json')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/javascript')));
|
2023-04-19 19:37:01 +03:00
|
|
|
aceObservables.push(from(import('./tbel/mode-tbel')));
|
2020-12-28 16:06:36 +02:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/text')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/markdown')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/html')));
|
2021-10-27 11:08:57 +03:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/c_cpp')));
|
|
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/snippets/protobuf')));
|
2021-10-20 20:12:08 +03:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/theme-textmate')));
|
2020-12-28 16:06:36 +02:00
|
|
|
aceObservables.push(from(import('ace-builds/src-noconflict/theme-github')));
|
|
|
|
|
return forkJoin(aceObservables).pipe(
|
|
|
|
|
tap(() => {
|
|
|
|
|
aceDependenciesLoaded = true;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getAce(): Observable<any> {
|
|
|
|
|
if (aceModule) {
|
|
|
|
|
return of(aceModule);
|
|
|
|
|
} else {
|
|
|
|
|
return from(import('ace')).pipe(
|
|
|
|
|
mergeMap((module) => {
|
|
|
|
|
return loadAceDependencies().pipe(
|
|
|
|
|
map(() => module)
|
|
|
|
|
);
|
|
|
|
|
}),
|
|
|
|
|
tap((module) => {
|
|
|
|
|
aceModule = module;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-27 13:14:18 +03:00
|
|
|
export function getAceDiff(): Observable<any> {
|
|
|
|
|
if (aceDiffModule) {
|
|
|
|
|
return of(aceDiffModule);
|
|
|
|
|
} else {
|
|
|
|
|
return getAce().pipe(
|
|
|
|
|
mergeMap((ace) => {
|
|
|
|
|
return from(import('ace-diff'));
|
|
|
|
|
}),
|
|
|
|
|
tap((module) => {
|
|
|
|
|
aceDiffModule = module;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 16:06:36 +02:00
|
|
|
export class Range implements Ace.Range {
|
|
|
|
|
|
|
|
|
|
public start: Ace.Point;
|
|
|
|
|
public end: Ace.Point;
|
|
|
|
|
|
|
|
|
|
constructor(startRow: number, startColumn: number, endRow: number, endColumn: number) {
|
|
|
|
|
this.start = {
|
|
|
|
|
row: startRow,
|
|
|
|
|
column: startColumn
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.end = {
|
|
|
|
|
row: endRow,
|
|
|
|
|
column: endColumn
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static fromPoints(start: Ace.Point, end: Ace.Point): Ace.Range {
|
|
|
|
|
return new Range(start.row, start.column, end.row, end.column);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clipRows(firstRow: number, lastRow: number): Ace.Range {
|
|
|
|
|
let end: Ace.Point;
|
|
|
|
|
let start: Ace.Point;
|
|
|
|
|
if (this.end.row > lastRow) {
|
|
|
|
|
end = {row: lastRow + 1, column: 0};
|
|
|
|
|
} else if (this.end.row < firstRow) {
|
|
|
|
|
end = {row: firstRow, column: 0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.start.row > lastRow) {
|
|
|
|
|
start = {row: lastRow + 1, column: 0};
|
|
|
|
|
} else if (this.start.row < firstRow) {
|
|
|
|
|
start = {row: firstRow, column: 0};
|
|
|
|
|
}
|
|
|
|
|
return Range.fromPoints(start || this.start, end || this.end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clone(): Ace.Range {
|
|
|
|
|
return Range.fromPoints(this.start, this.end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collapseRows(): Ace.Range {
|
|
|
|
|
if (this.end.column === 0) {
|
|
|
|
|
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row - 1), 0);
|
|
|
|
|
} else {
|
|
|
|
|
return new Range(this.start.row, 0, this.end.row, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compare(row: number, column: number): number {
|
|
|
|
|
if (!this.isMultiLine()) {
|
|
|
|
|
if (row === this.start.row) {
|
|
|
|
|
return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (row < this.start.row) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (row > this.end.row) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.start.row === row) {
|
|
|
|
|
return column >= this.start.column ? 0 : -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.end.row === row) {
|
|
|
|
|
return column <= this.end.column ? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compareEnd(row: number, column: number): number {
|
|
|
|
|
if (this.end.row === row && this.end.column === column) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
return this.compare(row, column);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compareInside(row: number, column: number): number {
|
|
|
|
|
if (this.end.row === row && this.end.column === column) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else if (this.start.row === row && this.start.column === column) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
return this.compare(row, column);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
comparePoint(p: Ace.Point): number {
|
|
|
|
|
return this.compare(p.row, p.column);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compareRange(range: Ace.Range): number {
|
|
|
|
|
let cmp: number;
|
|
|
|
|
const end = range.end;
|
|
|
|
|
const start = range.start;
|
|
|
|
|
|
|
|
|
|
cmp = this.compare(end.row, end.column);
|
|
|
|
|
if (cmp === 1) {
|
|
|
|
|
cmp = this.compare(start.row, start.column);
|
|
|
|
|
if (cmp === 1) {
|
|
|
|
|
return 2;
|
|
|
|
|
} else if (cmp === 0) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
} else if (cmp === -1) {
|
|
|
|
|
return -2;
|
|
|
|
|
} else {
|
|
|
|
|
cmp = this.compare(start.row, start.column);
|
|
|
|
|
if (cmp === -1) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else if (cmp === 1) {
|
|
|
|
|
return 42;
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compareStart(row: number, column: number): number {
|
|
|
|
|
if (this.start.row === row && this.start.column === column) {
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
return this.compare(row, column);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
contains(row: number, column: number): boolean {
|
|
|
|
|
return this.compare(row, column) === 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
containsRange(range: Ace.Range): boolean {
|
|
|
|
|
return this.comparePoint(range.start) === 0 && this.comparePoint(range.end) === 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extend(row: number, column: number): Ace.Range {
|
|
|
|
|
const cmp = this.compare(row, column);
|
|
|
|
|
let end: Ace.Point;
|
|
|
|
|
let start: Ace.Point;
|
|
|
|
|
if (cmp === 0) {
|
|
|
|
|
return this;
|
|
|
|
|
} else if (cmp === -1) {
|
|
|
|
|
start = {row, column};
|
|
|
|
|
} else {
|
|
|
|
|
end = {row, column};
|
|
|
|
|
}
|
|
|
|
|
return Range.fromPoints(start || this.start, end || this.end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inside(row: number, column: number): boolean {
|
|
|
|
|
if (this.compare(row, column) === 0) {
|
|
|
|
|
if (this.isEnd(row, column) || this.isStart(row, column)) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
insideEnd(row: number, column: number): boolean {
|
|
|
|
|
if (this.compare(row, column) === 0) {
|
|
|
|
|
if (this.isStart(row, column)) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
insideStart(row: number, column: number): boolean {
|
|
|
|
|
if (this.compare(row, column) === 0) {
|
|
|
|
|
if (this.isEnd(row, column)) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intersects(range: Ace.Range): boolean {
|
|
|
|
|
const cmp = this.compareRange(range);
|
|
|
|
|
return (cmp === -1 || cmp === 0 || cmp === 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isEmpty(): boolean {
|
|
|
|
|
return (this.start.row === this.end.row && this.start.column === this.end.column);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isEnd(row: number, column: number): boolean {
|
|
|
|
|
return this.end.row === row && this.end.column === column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isEqual(range: Ace.Range): boolean {
|
|
|
|
|
return this.start.row === range.start.row &&
|
|
|
|
|
this.end.row === range.end.row &&
|
|
|
|
|
this.start.column === range.start.column &&
|
|
|
|
|
this.end.column === range.end.column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isMultiLine(): boolean {
|
|
|
|
|
return (this.start.row !== this.end.row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isStart(row: number, column: number): boolean {
|
|
|
|
|
return this.start.row === row && this.start.column === column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
moveBy(row: number, column: number): void {
|
|
|
|
|
this.start.row += row;
|
|
|
|
|
this.start.column += column;
|
|
|
|
|
this.end.row += row;
|
|
|
|
|
this.end.column += column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setEnd(row: number, column: number): void {
|
|
|
|
|
if (typeof row === 'object') {
|
|
|
|
|
this.end.column = (row as Ace.Point).column;
|
|
|
|
|
this.end.row = (row as Ace.Point).row;
|
|
|
|
|
} else {
|
|
|
|
|
this.end.row = row;
|
|
|
|
|
this.end.column = column;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setStart(row: number, column: number): void {
|
|
|
|
|
if (typeof row === 'object') {
|
|
|
|
|
this.start.column = (row as Ace.Point).column;
|
|
|
|
|
this.start.row = (row as Ace.Point).row;
|
|
|
|
|
} else {
|
|
|
|
|
this.start.row = row;
|
|
|
|
|
this.start.column = column;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toScreenRange(session: Ace.EditSession): Ace.Range {
|
|
|
|
|
const screenPosStart = session.documentToScreenPosition(this.start);
|
|
|
|
|
const screenPosEnd = session.documentToScreenPosition(this.end);
|
|
|
|
|
|
|
|
|
|
return new Range(
|
|
|
|
|
screenPosStart.row, screenPosStart.column,
|
|
|
|
|
screenPosEnd.row, screenPosEnd.column
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|