├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github └── workflows │ └── yarn.yml ├── .gitignore ├── .vscode └── tasks.json ├── .yarn └── releases │ └── yarn-3.0.2.cjs ├── .yarnrc.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── COPYING ├── README.md ├── angular.json ├── angular.webpack.js ├── builder ├── default.json └── no-mingw.json ├── main.ts ├── main.webpack.js ├── package.json ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── codicon │ │ ├── codicon.css │ │ └── codicon.ttf │ ├── configs │ │ ├── cppLanguageConfig.ts │ │ └── editorKeybindings.ts │ ├── core │ │ ├── core.module.ts │ │ ├── directives │ │ │ ├── autofocus.directive.spec.ts │ │ │ └── autofocus.directive.ts │ │ ├── icon │ │ │ ├── icon.component.html │ │ │ ├── icon.component.scss │ │ │ ├── icon.component.spec.ts │ │ │ └── icon.component.ts │ │ ├── ipcTyping.d.ts │ │ └── services │ │ │ ├── electron.service.spec.ts │ │ │ ├── electron.service.ts │ │ │ └── index.ts │ ├── header │ │ ├── build-control │ │ │ ├── build-control.component.html │ │ │ ├── build-control.component.scss │ │ │ ├── build-control.component.spec.ts │ │ │ └── build-control.component.ts │ │ ├── file-control │ │ │ ├── file-control.component.html │ │ │ ├── file-control.component.scss │ │ │ ├── file-control.component.spec.ts │ │ │ └── file-control.component.ts │ │ ├── header-dropdown │ │ │ ├── header-dropdown.component.html │ │ │ ├── header-dropdown.component.scss │ │ │ ├── header-dropdown.component.spec.ts │ │ │ └── header-dropdown.component.ts │ │ ├── header.component.html │ │ ├── header.component.scss │ │ ├── header.component.spec.ts │ │ ├── header.component.ts │ │ └── header.module.ts │ ├── main-view │ │ ├── empty-page │ │ │ ├── empty-page.component.html │ │ │ ├── empty-page.component.scss │ │ │ ├── empty-page.component.spec.ts │ │ │ └── empty-page.component.ts │ │ ├── main-view.component.html │ │ ├── main-view.component.scss │ │ ├── main-view.component.spec.ts │ │ ├── main-view.component.ts │ │ ├── main-view.module.ts │ │ ├── sidebar │ │ │ ├── outline │ │ │ │ ├── outline.component.html │ │ │ │ ├── outline.component.scss │ │ │ │ ├── outline.component.spec.ts │ │ │ │ └── outline.component.ts │ │ │ ├── sidebar-routing.module.ts │ │ │ ├── sidebar.module.ts │ │ │ └── watch │ │ │ │ ├── watch.component.html │ │ │ │ ├── watch.component.scss │ │ │ │ ├── watch.component.spec.ts │ │ │ │ └── watch.component.ts │ │ ├── tabs │ │ │ ├── editor │ │ │ │ ├── editor.component.html │ │ │ │ ├── editor.component.scss │ │ │ │ ├── editor.component.spec.ts │ │ │ │ └── editor.component.ts │ │ │ ├── settings │ │ │ │ ├── build-setting │ │ │ │ │ ├── build-setting.component.html │ │ │ │ │ ├── build-setting.component.scss │ │ │ │ │ ├── build-setting.component.spec.ts │ │ │ │ │ ├── build-setting.component.ts │ │ │ │ │ ├── env-setting │ │ │ │ │ │ ├── env-setting.component.html │ │ │ │ │ │ ├── env-setting.component.scss │ │ │ │ │ │ ├── env-setting.component.spec.ts │ │ │ │ │ │ └── env-setting.component.ts │ │ │ │ │ └── sfb-setting │ │ │ │ │ │ ├── sfb-setting.component.html │ │ │ │ │ │ ├── sfb-setting.component.scss │ │ │ │ │ │ ├── sfb-setting.component.spec.ts │ │ │ │ │ │ └── sfb-setting.component.ts │ │ │ │ ├── common_styles.scss │ │ │ │ ├── common_subsetting_styles.scss │ │ │ │ └── editor-setting │ │ │ │ │ ├── editor-setting.component.html │ │ │ │ │ ├── editor-setting.component.scss │ │ │ │ │ ├── editor-setting.component.spec.ts │ │ │ │ │ ├── editor-setting.component.ts │ │ │ │ │ └── theme-setting │ │ │ │ │ ├── theme-setting.component.html │ │ │ │ │ ├── theme-setting.component.scss │ │ │ │ │ ├── theme-setting.component.spec.ts │ │ │ │ │ └── theme-setting.component.ts │ │ │ ├── tabs-routing.module.ts │ │ │ ├── tabs.module.ts │ │ │ └── tabs │ │ │ │ ├── tabs.component.html │ │ │ │ ├── tabs.component.scss │ │ │ │ ├── tabs.component.spec.ts │ │ │ │ └── tabs.component.ts │ │ └── tools │ │ │ ├── debug │ │ │ ├── debug.component.html │ │ │ ├── debug.component.scss │ │ │ ├── debug.component.spec.ts │ │ │ └── debug.component.ts │ │ │ ├── output │ │ │ ├── output.component.html │ │ │ ├── output.component.scss │ │ │ ├── output.component.spec.ts │ │ │ └── output.component.ts │ │ │ ├── problems │ │ │ ├── problems.component.html │ │ │ ├── problems.component.scss │ │ │ ├── problems.component.spec.ts │ │ │ └── problems.component.ts │ │ │ ├── tools-routing.module.ts │ │ │ └── tools.module.ts │ └── services │ │ ├── README.md │ │ ├── build.service.spec.ts │ │ ├── build.service.ts │ │ ├── debug.service.spec.ts │ │ ├── debug.service.ts │ │ ├── editor.service.spec.ts │ │ ├── editor.service.ts │ │ ├── file.service.spec.ts │ │ ├── file.service.ts │ │ ├── hotkeys.service.spec.ts │ │ ├── hotkeys.service.ts │ │ ├── problems.service.spec.ts │ │ ├── problems.service.ts │ │ ├── settings.service.spec.ts │ │ ├── settings.service.ts │ │ ├── status.service.spec.ts │ │ ├── status.service.ts │ │ ├── tabs.service.spec.ts │ │ ├── tabs.service.ts │ │ ├── theme.service.spec.ts │ │ ├── theme.service.ts │ │ ├── watch.service.spec.ts │ │ └── watch.service.ts ├── assets │ ├── .gitkeep │ ├── i18n │ │ └── en.json │ └── icons │ │ ├── cpp.ico │ │ ├── favicon.ico │ │ └── favicon.png ├── background │ ├── basicUtil.ts │ ├── handlers │ │ ├── build.ts │ │ ├── constants.ts │ │ ├── debug.ts │ │ ├── encode.ts │ │ ├── file.ts │ │ ├── index.ts │ │ ├── server.ts │ │ ├── store.ts │ │ ├── theme.ts │ │ └── window.ts │ ├── index.ts │ ├── ipcTyping.d.ts │ └── server │ │ └── server.js ├── environments │ ├── environment.dev.ts │ ├── environment.prod.ts │ ├── environment.ts │ └── environment.web.ts ├── extraResources │ ├── .gitignore │ ├── README.md │ ├── anon_workspace │ │ └── compile_flags.txt │ ├── generateResource.ps1 │ ├── src │ │ └── ConsolePauser.cpp │ └── themes │ │ ├── classic.json │ │ ├── dark_plus.json │ │ ├── light_plus.json │ │ ├── monokai.json │ │ └── theme.schema.jsonc ├── index.html ├── karma.conf.js ├── main.ts ├── polyfills-test.ts ├── polyfills.ts ├── styles.scss ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json ├── tsconfig.serve.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | 15 | [*.txt] 16 | insert_final_newline = false 17 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "es6": true, 6 | "es2017": true 7 | }, 8 | "overrides": [ 9 | { 10 | "files": ["*.ts"], 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:@typescript-eslint/eslint-recommended", 14 | "plugin:@typescript-eslint/recommended", 15 | "plugin:@typescript-eslint/recommended-requiring-type-checking" 16 | ], 17 | "parser": "@typescript-eslint/parser", 18 | "parserOptions": { 19 | "ecmaVersion": 10, 20 | "project": [ 21 | "./tsconfig.serve.json", 22 | "./src/tsconfig.app.json", 23 | "./src/tsconfig.spec.json" 24 | ], 25 | "sourceType": "module", 26 | "ecmaFeatures": { 27 | "modules": true 28 | } 29 | }, 30 | "plugins": [ 31 | "@typescript-eslint", 32 | "@angular-eslint/eslint-plugin" 33 | ], 34 | "rules": { 35 | "@typescript-eslint/no-empty-function": 0, 36 | "@typescript-eslint/no-explicit-any": 0, 37 | "@typescript-eslint/no-var-requires": 0, 38 | "@typescript-eslint/no-unsafe-call": 0, 39 | "@typescript-eslint/no-unsafe-member-access": 0, 40 | "@typescript-eslint/no-unsafe-assignment": 0, 41 | "@typescript-eslint/no-unsafe-return": 0, 42 | "@typescript-eslint/no-floating-promises": 0, 43 | "@typescript-eslint/semi": "error", 44 | "no-useless-escape": "warn", 45 | "@angular-eslint/use-injectable-provided-in": "error", 46 | "@angular-eslint/no-attribute-decorator": "error" 47 | } 48 | }, 49 | { 50 | "files": ["*.component.html"], 51 | "parser": "@angular-eslint/template-parser", 52 | "plugins": ["@angular-eslint/template"], 53 | "rules": { 54 | "@angular-eslint/template/banana-in-box": "error", 55 | "@angular-eslint/template/no-negated-async": "error" 56 | } 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/app/codicon/* linguist-vendored 2 | .yarn/** linguist-vendored 3 | -------------------------------------------------------------------------------- /.github/workflows/yarn.yml: -------------------------------------------------------------------------------- 1 | # Install dependencies and try build this project with electron-builder 2 | 3 | name: Yarn CI 4 | 5 | on: 6 | push: 7 | branches: [ master ] 8 | pull_request: 9 | branches: [ master ] 10 | 11 | jobs: 12 | build: 13 | runs-on: windows-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: actions/setup-node@v2 17 | with: 18 | node-version: '16' 19 | - run: npx yarn install 20 | - run: npx yarn build 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /app-builds 8 | /release 9 | main.js 10 | !src/karma.conf.js 11 | *.js.map 12 | 13 | # dependencies 14 | /node_modules 15 | 16 | # yarn 17 | .yarn/* 18 | !.yarn/patches 19 | !.yarn/releases 20 | !.yarn/plugins 21 | !.yarn/sdks 22 | !.yarn/versions 23 | .pnp.* 24 | 25 | # IDEs and editors 26 | /.idea 27 | .project 28 | .classpath 29 | .c9/ 30 | *.launch 31 | .settings/ 32 | *.sublime-workspace 33 | 34 | # IDE - VSCode 35 | .vscode/* 36 | .vscode/settings.json 37 | !.vscode/tasks.json 38 | !.vscode/launch.json 39 | !.vscode/extensions.json 40 | 41 | # misc 42 | /.sass-cache 43 | /connect.lock 44 | /coverage 45 | /libpeerconnection.log 46 | npm-debug.log 47 | testem.log 48 | /typings 49 | # package-lock.json 50 | 51 | # System Files 52 | .DS_Store 53 | Thumbs.db 54 | 55 | # Temporary files 56 | temp.* 57 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build.All", 6 | "type": "shell", 7 | "command": "npm run electron:serve-tsc && ng serve", 8 | "isBackground": true, 9 | "group": { 10 | "kind": "build", 11 | "isDefault": true 12 | }, 13 | "problemMatcher": { 14 | "owner": "typescript", 15 | "source": "ts", 16 | "applyTo": "closedDocuments", 17 | "fileLocation": ["relative", "${cwd}"], 18 | "pattern": "$tsc", 19 | "background": { 20 | "activeOnStart": true, 21 | "beginsPattern": "^.*", 22 | "endsPattern": "^.*Compiled successfully.*" 23 | } 24 | } 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | enableInlineBuilds: true 2 | 3 | nodeLinker: node-modules 4 | 5 | yarnPath: .yarn/releases/yarn-3.0.2.cjs 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2109.1 4 | 5 | - Fix bugs: 6 | - Reopen settings tab should locate to correct page (last release doesn't fix it properly) 7 | 8 | ## 2109.0 9 | 10 | - Features 11 | - GCC diagnostics translation powered by [gcc-translation](https://github.com/Guyutongxue/gcc-translation) 12 | - Use your own MinGW instead of the bundle one. Change portable release to "no-mingw" 13 | - Change editor theme. Now it have 4 initial themes: 14 | - VS Code Light+ 15 | - Vs Code Dark+ 16 | - Dev-C++ Classic+ 17 | - Monokai 18 | - (You can define your own theme if you want.) 19 | - Fix bugs: 20 | - Reopen settings tab should locate to correct page 21 | 22 | ## 2108.0 23 | 24 | - Fix bugs: 25 | - Clangd should recognize compiler options. 26 | 27 | > I do not have time on developing this. 😞 28 | 29 | ## 2107.0 30 | 31 | - Features: 32 | - Ability to adjust code pages (GBK or UTF-8 or sth else) 33 | - Modal for unsaved settings 34 | 35 | ## 2105.0 36 | 37 | - Fix bugs: 38 | - `ConsolePauser.exe` not launched when path contains space. 39 | - [#1](https://github.com/Guyutongxue/devcpp7/issues/1) 40 | 41 | ## 2104.1 42 | 43 | - Fix bug - `spawn` failed when path contains spaces 44 | 45 | ## 2104.0 46 | 47 | - Fix a packing problem. 48 | 49 | ## 2103.0 50 | 51 | - Fix unknown error - set env:Path while compiling 52 | 53 | ## 2102.0 54 | 55 | - First release - basic features finish 56 | 57 | ## alpha2 58 | 59 | - Migrate from Vue.js to Angular 60 | 61 | ## alpha1 62 | 63 | - Start developing Dev-C++ 7 with Vue.js and Electron. 64 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Explanation of source 2 | 3 | ## Background and Foreground 4 | 5 | As an Electron application, Dev-C++ 7 includes 2 part: foreground process (renderer proces) and background process (main process). Background process run JavaScript in Nodejs (V8 engine) and foreground process run JavaScript (include HTML/CSS) in Chromium (Blink engine). 6 | 7 | (That's why this application has a very large size.) 8 | 9 | Two processes communicate through IPC. Here IPC is provided by Electron. 10 | 11 | ## Foreground detail 12 | 13 | The foreground is built under the Angular framework. It deals with codes that don't need the support of filesystem, compiler, or linter (Such as UI). 14 | 15 | The Angular app is started at `src/main.ts`. It will load the root module located at `src/app/app.module.ts`. All components, services, and directives are located at `src/app`. 16 | 17 | ``` 18 | |- src 19 | | |- app 20 | | | |- ... other components 21 | | | |- services 22 | | | | +- ... services 23 | | | +- app.module.ts 24 | | |- main.ts // Foreground entry (Root JS) 25 | | |- index.html // Root HTML 26 | | +- styles.scss // Root CSS 27 | |- main.ts // Background entry (we will talk it later) 28 | ``` 29 | 30 | All components' location equals to its view location. (i.e. If A is B's child component, then A's folder is located under B's folder.) 31 | 32 | All services are located at `src/app/services`. (Exclude `ElectronService` which is provided by the `angular-electron` template.) 33 | 34 | Notice that `EditorService` and `TabsService` are the most fundamental services. You cannot inject other services into them. `EditorService` is injected into `TabsService`. 35 | 36 | I use `ng-zorro-antd` as the UI framework. Sometimes I also use `codicon` for more icons. 37 | 38 | The editor component `ngx-monaco-editor` is a wrapper of Monaco Editor. It won't render on Electron-hot-load environment (I don't know why). But it works under browsers and production mode. 39 | 40 | The Editor communicates with Language Server by LSP through Electron's IPC. It will request to start Language Server when initializing, so Language Server won't work in the browser. Components like `outline` need Language Server working. 41 | 42 | When opening/saving/compiling/running, foreground process will send a request to the background, and background deal with these request, and return an optional response. 43 | 44 | Angular will translate all TypeScript-written-things to runtime JavaScript. When building, TypeScript compiler compiles all things into JS, then WebPack packs all JS (including `node_modules`) into a single JS file located in `dist` folder. The corresponding `tsconfig.json` is located at `src`. 45 | 46 | ## Background detail 47 | 48 | The entry point of this whole project is also the entry point of the background project. It is `main.ts` in the root directory. 49 | 50 | First, it will open an Electron window (here, a foreground process will start). Then It will hook all handles of IPC, and listening to request from the renderer. This part of the code is located at `src/background/background.ts`. 51 | 52 | When it received a start-language-server request, it will start an Express Server in a new process through `child_process.fork`. The Server will run on a runtime-determined port (3000 is preferred) and send the port info back to the foreground. The Language Server - Clangd is *inside* the compiler set (or it won't find header files). 53 | 54 | When it received a compile (or run) request, it will execute the compiler in the `extraResource` folder. 55 | 56 | Background codes are written in TypeScript, and they will be packed by WebPack when building. The corresponding `tsconfig.json` is located at the root folder, called `tsconfig.serve.json`, and WebPack's configuration is `main.webpack.js`. Packed bundle is located in `dist` folder which is same as renderer process. 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dev-C++ 7 2 | 3 | ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/Guyutongxue/devcpp7/Yarn%20CI) 4 | ![LGTM Grade](https://img.shields.io/lgtm/grade/javascript/github/Guyutongxue/devcpp7?label=code%20quality) 5 | 6 |

7 | Dev C++ 7 = 8 | Angular+ 9 | Electron+ 10 | Monaco Editor+ 11 | MinGW-w64+ 12 | Clangd 13 |

14 | 15 | ## Info 16 | 17 | A project simulating legacy Dev-C++, a tiny C++ IDE, powered by Angular, Electron, Monaco Editor, MinGW-w64 and Clangd. 18 | 19 | **This repository has no relationship to Bloodshed's Dev-C++.** 20 | 21 | ![Snapshot](https://s3.ax1x.com/2021/02/22/yHDron.png) 22 | 23 | ## Current Status 24 | 25 | **NOT UNDER MAINTENANCE** 26 | 27 | Current features: 28 | - Basic New/Open/Save 29 | - Features provided by LSP: suggestions, hover message, outline, squiggles, etc. 30 | - Basic single file Compile/Run 31 | - Basic step-by-step debug 32 | 33 | ## :warning: Warning 34 | 35 | **This project is not aimed to replace legacy Dev-C++.** If you want a newer version of that, please check [royqh1979/Dev-CPP](https://github.com/royqh1979/Dev-CPP). This project is just a practice of using Angular and Electron to built a desktop application. So it: 36 | - **WON'T** support 32-bit system. 37 | - **WON'T** test on any system lower than Windows 10. 38 | - **MAY NOT** support C project or file. 39 | - **MAY NOT** support i18n. (Only Simplified Chinese now.) 40 | - **PRETTY LARGER** than legacy Dev-C++ (because of Electron, Clangd and so on). 41 | 42 | ## Build instructions 43 | 44 | This repo is based on [angular-electron](https://github.com/maximegris/angular-electron) template. Following instructions are copied from there. 45 | 46 | ### Install dependencies 47 | 48 | Install Node.js and Yarn on Windows. You should install node-gyp (including Python & MSVC) to build some modules. 49 | 50 | Then: 51 | ``` 52 | yarn 53 | yarn electron:rebuild # rebuild node modules to match electron version 54 | ``` 55 | in the root directory of this project to install all the dependencies. 56 | 57 | ### Dealing with extraResousrce 58 | 59 | Follow [here](src/extraResources/README.md). 60 | 61 | ### Included Commands 62 | 63 | | Command | Description | 64 | | ------------------- | --------------------------------------------- | 65 | | `yarn start` | Hot reload in browser, for debugging UI stuff | 66 | | `yarn electron:dev` | Run developer env in Electron | 67 | | `yarn build` | Build executable with electron-builder | 68 | 69 | > `npx electron-rebuild -o chcp -v 11.1.0` 70 | -------------------------------------------------------------------------------- /angular.webpack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom angular webpack configuration 3 | */ 4 | const path = require('path'); 5 | 6 | /** 7 | * 8 | * @param {import('webpack').Configuration} config 9 | * @param {import('@angular-builders/custom-webpack').CustomWebpackBrowserSchema} options 10 | */ 11 | module.exports = (config, options) => { 12 | config.target = 'electron-renderer'; 13 | 14 | if (options.fileReplacements) { 15 | for (let fileReplacement of options.fileReplacements) { 16 | if (fileReplacement.replace !== 'src/environments/environment.ts') { 17 | continue; 18 | } 19 | 20 | let fileReplacementParts = fileReplacement['with'].split('.'); 21 | if (fileReplacementParts.length > 1 && ['web'].indexOf(fileReplacementParts[1]) >= 0) { 22 | config.target = 'web'; 23 | } 24 | break; 25 | } 26 | } 27 | 28 | config.resolve.alias = { 29 | 'vscode': path.resolve(__dirname, './node_modules/monaco-languageclient/lib/vscode-compatibility') 30 | }; 31 | config.resolve.fallback = { 32 | "path": require.resolve("path-browserify"), 33 | "crypto": false, 34 | "fs": false, 35 | "os": false, 36 | "tls": false, 37 | "net": false, 38 | // "process": true, 39 | "module": false, 40 | "clearImmediate": false, 41 | // "setImmediate": true 42 | } 43 | config.node = { 44 | "global": true, 45 | }; 46 | return config; 47 | } 48 | -------------------------------------------------------------------------------- /builder/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/electron-builder", 3 | "productName": "Dev-C++ 7", 4 | "directories": { 5 | "output": "release/" 6 | }, 7 | "extraResources": [ 8 | { 9 | "from": "./src/extraResources/", 10 | "to": "extraResources", 11 | "filter": [ 12 | "**/*" 13 | ] 14 | } 15 | ], 16 | "files": [ 17 | "dist/**/*" 18 | ], 19 | "nsis": { 20 | "oneClick": false, 21 | "perMachine": true, 22 | "allowElevation": true, 23 | "allowToChangeInstallationDirectory": true 24 | }, 25 | "win": { 26 | "icon": "dist/assets/icons/favicon.ico", 27 | "fileAssociations": { 28 | "ext": ["cc", "cxx", "cpp", "h"], 29 | "description": "C++ source file", 30 | "icon": "dist/assets/icons/cpp.ico" 31 | }, 32 | "target": [ 33 | "nsis" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /builder/no-mingw.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/electron-builder", 3 | "productName": "Dev-C++ 7", 4 | "directories": { 5 | "output": "release/" 6 | }, 7 | "extraResources": [ 8 | { 9 | "from": "./src/extraResources/", 10 | "to": "extraResources", 11 | "filter": [ 12 | "**/*", 13 | "!mingw64${/*}" 14 | ] 15 | } 16 | ], 17 | "files": [ 18 | "dist/**/*" 19 | ], 20 | "artifactName": "${productName}-${version}-no-mingw.${ext}", 21 | "nsis": { 22 | "oneClick": false, 23 | "perMachine": true, 24 | "allowElevation": true, 25 | "allowToChangeInstallationDirectory": true 26 | }, 27 | "win": { 28 | "icon": "dist/assets/icons/favicon.ico", 29 | "fileAssociations": { 30 | "ext": ["cc", "cxx", "cpp", "h"], 31 | "description": "C++ source file", 32 | "icon": "dist/assets/icons/cpp.ico" 33 | }, 34 | "target": [ 35 | "7z" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { app, BrowserWindow, Menu } from 'electron'; 19 | import * as path from 'path'; 20 | import * as url from 'url'; 21 | 22 | let win: BrowserWindow = null; 23 | function createWindow(): BrowserWindow { 24 | 25 | // const electronScreen = screen; 26 | // const size = electronScreen.getPrimaryDisplay().workAreaSize; 27 | 28 | // Create the browser window. 29 | win = new BrowserWindow({ 30 | width: 1000, 31 | height: 600, 32 | minWidth: 500, 33 | minHeight: 300, 34 | webPreferences: { 35 | nodeIntegration: true, 36 | allowRunningInsecureContent: false, 37 | contextIsolation: false 38 | }, 39 | }); 40 | global["win"] = win; 41 | win.loadURL(url.format({ 42 | pathname: path.join(__dirname, 'index.html'), 43 | protocol: 'file:', 44 | slashes: true 45 | })); 46 | 47 | // Emitted when the window is closed. 48 | win.on('closed', () => { 49 | // Dereference the window object, usually you would store window 50 | // in an array if your app supports multi windows, this is the time 51 | // when you should delete the corresponding element. 52 | win = null; 53 | }); 54 | 55 | Menu.setApplicationMenu(null); 56 | 57 | return win; 58 | } 59 | 60 | try { 61 | // This method will be called when Electron has finished 62 | // initialization and is ready to create browser windows. 63 | // Some APIs can only be used after this event occurs. 64 | // Added 400 ms to fix the black background issue while using transparent window. More details at https://github.com/electron/electron/issues/15947 65 | app.on('ready', () => setTimeout(createWindow, 400)); 66 | 67 | // Quit when all windows are closed. 68 | app.on('window-all-closed', () => { 69 | // On OS X it is common for applications and their menu bar 70 | // to stay active until the user quits explicitly with Cmd + Q 71 | if (process.platform !== 'darwin') { 72 | app.quit(); 73 | } 74 | }); 75 | 76 | app.on('activate', () => { 77 | // On OS X it's common to re-create a window in the app when the 78 | // dock icon is clicked and there are no other windows open. 79 | if (win === null) { 80 | createWindow(); 81 | } 82 | }); 83 | 84 | } catch (e) { 85 | // Catch Error 86 | // throw e; 87 | } 88 | 89 | import './src/background'; 90 | -------------------------------------------------------------------------------- /main.webpack.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | const path = require('path'); 19 | const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); 20 | const CopyPlugin = require('copy-webpack-plugin'); 21 | 22 | module.exports = { 23 | node: { 24 | __dirname: false 25 | }, 26 | mode: 'none', 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.ts$/, 31 | use: 'ts-loader', 32 | include: [ 33 | path.resolve(__dirname, "src/background"), 34 | path.resolve(__dirname, "main.ts"), 35 | ] 36 | }, 37 | { 38 | test: /\.node$/, 39 | loader: "node-loader", 40 | } 41 | ] 42 | }, 43 | resolve: { 44 | extensions: ['.ts', '.js', '.node'], 45 | plugins: [ 46 | new TsconfigPathsPlugin({ 47 | configFile: path.resolve(__dirname, "tsconfig.serve.json") 48 | }) 49 | ] 50 | }, 51 | plugins: [ 52 | new CopyPlugin({ 53 | patterns: [ 54 | { from: 'src/background/server', to: 'server' } 55 | ] 56 | }) 57 | ], 58 | target: 'electron-main', 59 | entry: './main.ts', 60 | output: { 61 | filename: 'background-bundle.js', 62 | path: path.resolve(__dirname, 'dist') 63 | }, 64 | }; 65 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { Routes, RouterModule } from '@angular/router'; 20 | 21 | import { TabsRoutingModule } from './main-view/tabs/tabs-routing.module'; 22 | import { SidebarRoutingModule } from './main-view/sidebar/sidebar-routing.module'; 23 | import { ToolsRoutingModule } from './main-view/tools/tools-routing.module'; 24 | 25 | const routes: Routes = [ 26 | ]; 27 | 28 | @NgModule({ 29 | imports: [ 30 | RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' }), 31 | TabsRoutingModule, 32 | SidebarRoutingModule, 33 | ToolsRoutingModule 34 | ], 35 | exports: [RouterModule] 36 | }) 37 | export class AppRoutingModule { } 38 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 4 |
5 | 6 | 13 | 必要设置 14 | 15 | 16 |

MinGW 路径(如 C:\mingw64

17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | height: 100vh; 3 | 4 | #header { 5 | width : 100%; 6 | } 7 | 8 | #mainView { 9 | width: 100%; 10 | height: 100%; 11 | } 12 | 13 | #footer { 14 | width : 100%; 15 | height: 20px; 16 | line-height: 20px; 17 | background-color: #eeeeee; 18 | padding: 0 20px; 19 | } 20 | } -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | import { TranslateModule } from '@ngx-translate/core'; 5 | import { ElectronService } from './core/services'; 6 | 7 | describe('AppComponent', () => { 8 | beforeEach(waitForAsync(() => { 9 | TestBed.configureTestingModule({ 10 | declarations: [AppComponent], 11 | providers: [ElectronService], 12 | imports: [RouterTestingModule, TranslateModule.forRoot()] 13 | }).compileComponents(); 14 | })); 15 | 16 | it('should create the app', waitForAsync(() => { 17 | const fixture = TestBed.createComponent(AppComponent); 18 | const app = fixture.debugElement.componentInstance; 19 | expect(app).toBeTruthy(); 20 | })); 21 | }); 22 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, HostListener, OnInit } from '@angular/core'; 19 | import { ElectronService } from './core/services'; 20 | import { TranslateService } from '@ngx-translate/core'; 21 | import { AppConfig } from '../environments/environment'; 22 | 23 | import { HotkeysService } from './services/hotkeys.service'; 24 | import { StatusService } from './services/status.service'; 25 | import { ThemeService } from './services/theme.service'; 26 | 27 | @Component({ 28 | selector: 'app-root', 29 | templateUrl: './app.component.html', 30 | styleUrls: ['./app.component.scss'] 31 | }) 32 | export class AppComponent implements OnInit { 33 | constructor( 34 | private electronService: ElectronService, 35 | private translate: TranslateService, 36 | private statusService: StatusService, 37 | private themeService: ThemeService 38 | ) { 39 | this.translate.setDefaultLang('en'); 40 | console.log('AppConfig', AppConfig); 41 | 42 | if (electronService.isElectron) { 43 | console.log(process.env); 44 | console.log('Run in electron'); 45 | console.log('Electron ipcRenderer', this.electronService.ipcRenderer); 46 | console.log('NodeJS childProcess', this.electronService.childProcess); 47 | } else { 48 | console.log('Run in browser'); 49 | } 50 | this.windowHeight = window.innerHeight; 51 | } 52 | 53 | private windowHeight: number; 54 | 55 | @HostListener('window:resize', ['$event']) 56 | onResize() { 57 | this.windowHeight = window.innerHeight; 58 | } 59 | 60 | get headerHeight() { 61 | return 32 + 1 * 32; 62 | } 63 | 64 | get footerHeight() { 65 | return 20; 66 | } 67 | 68 | get mainViewHeight() { 69 | return this.windowHeight - this.headerHeight - this.footerHeight; 70 | } 71 | 72 | async ngOnInit(): Promise { 73 | // this.electronService.ipcRenderer.invoke('window/toggleDevTools'); 74 | this.themeService.setTheme(); 75 | const [mingwPath, useBundled] = await Promise.all([ 76 | this.electronService.getConfig('env.mingwPath'), 77 | this.electronService.getConfig('env.useBundledMingw') 78 | ]); 79 | if (!useBundled && mingwPath === '') { 80 | this.setEnvModal = true; 81 | } 82 | } 83 | 84 | setEnvModal = false; 85 | tempMingwPath = ""; 86 | tempUseBundledMingw = false; 87 | 88 | confirmPaths(): void { 89 | this.electronService.setConfig('env.mingwPath', this.tempMingwPath); 90 | this.electronService.setConfig('env.useBundledMingw', this.tempUseBundledMingw); 91 | this.setEnvModal = false; 92 | } 93 | 94 | get currentStatus(): string { 95 | if (this.statusService.isBuilding) return "正在编译中"; 96 | if (this.statusService.isDebugging) return "正在调试中"; 97 | return "就绪"; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { BrowserModule } from '@angular/platform-browser'; 19 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 20 | import { NgModule } from '@angular/core'; 21 | import { FormsModule } from '@angular/forms'; 22 | import { HttpClientModule, HttpClient } from '@angular/common/http'; 23 | import { CoreModule } from './core/core.module'; 24 | 25 | import { AppRoutingModule } from './app-routing.module'; 26 | 27 | // NG Translate 28 | import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; 29 | import { TranslateHttpLoader } from '@ngx-translate/http-loader'; 30 | 31 | import { NzModalModule } from 'ng-zorro-antd/modal'; 32 | import { NzButtonModule } from 'ng-zorro-antd/button'; 33 | import { NzIconModule } from 'ng-zorro-antd/icon'; 34 | import { NzInputModule } from 'ng-zorro-antd/input'; 35 | import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; 36 | import { IconDefinition } from '@ant-design/icons-angular'; 37 | import * as AllIcons from '@ant-design/icons-angular/icons'; 38 | 39 | import { MainViewModule } from './main-view/main-view.module'; 40 | import { HeaderModule } from './header/header.module'; 41 | 42 | import { AppComponent } from './app.component'; 43 | 44 | // AoT requires an exported function for factories 45 | export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader { 46 | return new TranslateHttpLoader(http, './assets/i18n/', '.json'); 47 | } 48 | 49 | const antDesignIcons = AllIcons as { 50 | [key: string]: IconDefinition; 51 | }; 52 | const icons: IconDefinition[] = Object.keys(antDesignIcons).map(key => antDesignIcons[key]); 53 | 54 | @NgModule({ 55 | declarations: [AppComponent], 56 | imports: [ 57 | BrowserModule, 58 | BrowserAnimationsModule, 59 | FormsModule, 60 | HttpClientModule, 61 | CoreModule, 62 | MainViewModule, 63 | HeaderModule, 64 | NzModalModule, 65 | NzButtonModule, 66 | NzInputModule, 67 | NzCheckboxModule, 68 | NzIconModule.forRoot(icons), 69 | AppRoutingModule, 70 | TranslateModule.forRoot({ 71 | loader: { 72 | provide: TranslateLoader, 73 | useFactory: HttpLoaderFactory, 74 | deps: [HttpClient] 75 | } 76 | }) 77 | ], 78 | providers: [], 79 | bootstrap: [AppComponent] 80 | }) 81 | export class AppModule { } 82 | -------------------------------------------------------------------------------- /src/app/codicon/codicon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/app/codicon/codicon.ttf -------------------------------------------------------------------------------- /src/app/configs/editorKeybindings.ts: -------------------------------------------------------------------------------- 1 | enum KeyCode { 2 | Unknown = 0, 3 | Backspace = 1, 4 | Tab = 2, 5 | Enter = 3, 6 | Shift = 4, 7 | Ctrl = 5, 8 | Alt = 6, 9 | PauseBreak = 7, 10 | CapsLock = 8, 11 | Escape = 9, 12 | Space = 10, 13 | PageUp = 11, 14 | PageDown = 12, 15 | End = 13, 16 | Home = 14, 17 | LeftArrow = 15, 18 | UpArrow = 16, 19 | RightArrow = 17, 20 | DownArrow = 18, 21 | Insert = 19, 22 | Delete = 20, 23 | KEY_0 = 21, 24 | KEY_1 = 22, 25 | KEY_2 = 23, 26 | KEY_3 = 24, 27 | KEY_4 = 25, 28 | KEY_5 = 26, 29 | KEY_6 = 27, 30 | KEY_7 = 28, 31 | KEY_8 = 29, 32 | KEY_9 = 30, 33 | KEY_A = 31, 34 | KEY_B = 32, 35 | KEY_C = 33, 36 | KEY_D = 34, 37 | KEY_E = 35, 38 | KEY_F = 36, 39 | KEY_G = 37, 40 | KEY_H = 38, 41 | KEY_I = 39, 42 | KEY_J = 40, 43 | KEY_K = 41, 44 | KEY_L = 42, 45 | KEY_M = 43, 46 | KEY_N = 44, 47 | KEY_O = 45, 48 | KEY_P = 46, 49 | KEY_Q = 47, 50 | KEY_R = 48, 51 | KEY_S = 49, 52 | KEY_T = 50, 53 | KEY_U = 51, 54 | KEY_V = 52, 55 | KEY_W = 53, 56 | KEY_X = 54, 57 | KEY_Y = 55, 58 | KEY_Z = 56, 59 | Meta = 57, 60 | ContextMenu = 58, 61 | F1 = 59, 62 | F2 = 60, 63 | F3 = 61, 64 | F4 = 62, 65 | F5 = 63, 66 | F6 = 64, 67 | F7 = 65, 68 | F8 = 66, 69 | F9 = 67, 70 | F10 = 68, 71 | F11 = 69, 72 | F12 = 70, 73 | F13 = 71, 74 | F14 = 72, 75 | F15 = 73, 76 | F16 = 74, 77 | F17 = 75, 78 | F18 = 76, 79 | F19 = 77, 80 | NumLock = 78, 81 | ScrollLock = 79, 82 | US_SEMICOLON = 80, 83 | US_EQUAL = 81, 84 | US_COMMA = 82, 85 | US_MINUS = 83, 86 | US_DOT = 84, 87 | US_SLASH = 85, 88 | US_BACKTICK = 86, 89 | US_OPEN_SQUARE_BRACKET = 87, 90 | US_BACKSLASH = 88, 91 | US_CLOSE_SQUARE_BRACKET = 89, 92 | US_QUOTE = 90, 93 | OEM_8 = 91, 94 | OEM_102 = 92, 95 | NUMPAD_0 = 93, 96 | NUMPAD_1 = 94, 97 | NUMPAD_2 = 95, 98 | NUMPAD_3 = 96, 99 | NUMPAD_4 = 97, 100 | NUMPAD_5 = 98, 101 | NUMPAD_6 = 99, 102 | NUMPAD_7 = 100, 103 | NUMPAD_8 = 101, 104 | NUMPAD_9 = 102, 105 | NUMPAD_MULTIPLY = 103, 106 | NUMPAD_ADD = 104, 107 | NUMPAD_SEPARATOR = 105, 108 | NUMPAD_SUBTRACT = 106, 109 | NUMPAD_DECIMAL = 107, 110 | NUMPAD_DIVIDE = 108, 111 | KEY_IN_COMPOSITION = 109, 112 | ABNT_C1 = 110, 113 | ABNT_C2 = 111, 114 | MAX_VALUE = 112 115 | } 116 | enum KeyMod { 117 | CtrlCmd = (1 << 11) >>> 0, 118 | Shift = (1 << 10) >>> 0, 119 | Alt = (1 << 9) >>> 0, 120 | WinCtrl = (1 << 8) >>> 0 121 | } 122 | 123 | 124 | export const defaultKeybindings: { 125 | keybinding: number, 126 | message: string 127 | }[] = []; 128 | -------------------------------------------------------------------------------- /src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { AutofocusDirective } from './directives/autofocus.directive'; 21 | import { IconComponent } from './icon/icon.component'; 22 | import { NzIconModule } from 'ng-zorro-antd/icon'; 23 | 24 | @NgModule({ 25 | declarations: [AutofocusDirective, IconComponent], 26 | imports: [ 27 | CommonModule, 28 | NzIconModule 29 | ], 30 | exports: [ AutofocusDirective, IconComponent ] 31 | }) 32 | export class CoreModule { } 33 | -------------------------------------------------------------------------------- /src/app/core/directives/autofocus.directive.spec.ts: -------------------------------------------------------------------------------- 1 | import { AutofocusDirective } from './autofocus.directive'; 2 | 3 | describe('AutofocusDirective', () => { 4 | it('should create an instance', () => { 5 | const directive = new AutofocusDirective(); 6 | expect(directive).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/core/directives/autofocus.directive.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Directive, ElementRef } from '@angular/core'; 19 | 20 | @Directive({ 21 | selector: '[appAutofocus]' 22 | }) 23 | export class AutofocusDirective { 24 | 25 | constructor(private el: ElementRef) { 26 | if (!el.nativeElement['focus']) { 27 | throw new Error('Element does not accept focus.'); 28 | } 29 | } 30 | 31 | ngOnInit(): void { 32 | const input: HTMLInputElement = this.el.nativeElement as HTMLInputElement; 33 | input.focus(); 34 | input.select(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/app/core/icon/icon.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/core/icon/icon.component.scss: -------------------------------------------------------------------------------- 1 | span.app-icon { 2 | display: inline-block; 3 | width: 1.5em; 4 | } -------------------------------------------------------------------------------- /src/app/core/icon/icon.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { IconComponent } from './icon.component'; 4 | 5 | describe('IconComponent', () => { 6 | let component: IconComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ IconComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(IconComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/core/icon/icon.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, Input, OnInit } from '@angular/core'; 19 | 20 | @Component({ 21 | selector: 'app-icon', 22 | templateUrl: './icon.component.html', 23 | styleUrls: ['./icon.component.scss'] 24 | }) 25 | export class IconComponent implements OnInit { 26 | 27 | @Input('type') type: string; 28 | 29 | constructor() { } 30 | 31 | ngOnInit(): void { 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/app/core/services/electron.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ElectronService } from './electron.service'; 4 | 5 | describe('ElectronService', () => { 6 | beforeEach(() => TestBed.configureTestingModule({})); 7 | 8 | it('should be created', () => { 9 | const service: ElectronService = TestBed.get(ElectronService); 10 | expect(service).toBeTruthy(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/app/core/services/electron.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | // If you import a module but never use any of the imported values other than as TypeScript types, 4 | // the resulting javascript file will look as if you never imported the module at all. 5 | import { webFrame, remote } from 'electron'; 6 | import * as childProcess from 'child_process'; 7 | import * as fs from 'fs'; 8 | import { TypedIpcRenderer } from 'electron-typed-ipc'; 9 | 10 | import { IpcEvents, IpcCommands, Configurations } from '../ipcTyping'; 11 | 12 | 13 | @Injectable({ 14 | providedIn: 'root' 15 | }) 16 | export class ElectronService { 17 | ipcRenderer: TypedIpcRenderer; 18 | webFrame: typeof webFrame; 19 | remote: typeof remote; 20 | childProcess: typeof childProcess; 21 | fs: typeof fs; 22 | 23 | get isElectron(): boolean { 24 | return !!(window && window.process && window.process.type); 25 | } 26 | 27 | constructor() { 28 | // Conditional imports 29 | if (this.isElectron) { 30 | // eslint-disable-next-line 31 | this.ipcRenderer = window.require('electron').ipcRenderer as any; 32 | this.webFrame = window.require('electron').webFrame; 33 | this.childProcess = window.require('child_process'); 34 | this.fs = window.require('fs'); 35 | } else { 36 | // do not make error in browser 37 | this.ipcRenderer = { 38 | on() { }, 39 | send() { }, 40 | sendSync() { }, 41 | invoke() { } 42 | } as any; 43 | } 44 | this.getConfig('build.compileArgs'); 45 | } 46 | 47 | async getConfig (key: K): Promise { 48 | return this.ipcRenderer.invoke('store/get', key) as Promise; 49 | } 50 | 51 | setConfig (key: K, value: Configurations[K]): void { 52 | this.ipcRenderer.invoke('store/set', key, value); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/core/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './electron.service'; 2 | -------------------------------------------------------------------------------- /src/app/header/build-control/build-control.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/header/build-control/build-control.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/app/header/build-control/build-control.component.scss -------------------------------------------------------------------------------- /src/app/header/build-control/build-control.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BuildControlComponent } from './build-control.component'; 4 | 5 | describe('BuildControlComponent', () => { 6 | let component: BuildControlComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ BuildControlComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(BuildControlComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/header/build-control/build-control.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | 20 | import { BuildService } from '../../services/build.service'; 21 | import { StatusService } from '../../services/status.service'; 22 | 23 | @Component({ 24 | selector: 'app-build-control', 25 | templateUrl: './build-control.component.html', 26 | styleUrls: ['./build-control.component.scss'] 27 | }) 28 | export class BuildControlComponent implements OnInit { 29 | 30 | constructor( 31 | private buildService: BuildService, 32 | private statusService: StatusService 33 | ) { } 34 | 35 | get enabled() { 36 | return this.statusService.saveEnabled; 37 | } 38 | 39 | ngOnInit(): void { } 40 | 41 | compile() { 42 | this.buildService.compile(); 43 | } 44 | 45 | runExe() { 46 | this.buildService.runExe(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/app/header/file-control/file-control.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/header/file-control/file-control.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/app/header/file-control/file-control.component.scss -------------------------------------------------------------------------------- /src/app/header/file-control/file-control.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { FileControlComponent } from './file-control.component'; 4 | 5 | describe('FileControlComponent', () => { 6 | let component: FileControlComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ FileControlComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(FileControlComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/header/file-control/file-control.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | 20 | import { FileService } from '../../services/file.service'; 21 | import { StatusService } from '../../services/status.service'; 22 | 23 | @Component({ 24 | selector: 'app-file-control', 25 | templateUrl: './file-control.component.html', 26 | styleUrls: ['./file-control.component.scss'] 27 | }) 28 | export class FileControlComponent implements OnInit { 29 | 30 | constructor( 31 | private fileService: FileService, 32 | private statusService: StatusService 33 | ) { } 34 | 35 | get isSaveEnable() { 36 | return this.statusService.saveEnabled; 37 | } 38 | 39 | ngOnInit(): void { } 40 | 41 | newFile() { 42 | this.fileService.new(); 43 | } 44 | 45 | openFile() { 46 | this.fileService.open(); 47 | } 48 | 49 | saveFile() { 50 | this.fileService.save(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/app/header/header-dropdown/header-dropdown.component.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
  • 8 | 9 | 10 | {{ commandList[idStr].name }} 11 | {{ commandList[idStr].shortcut | shortcutTranslate }} 12 | 13 |
  • 14 |
    15 | 16 |
  • 17 |
      18 | 19 |
    • 23 | 24 | 25 | {{ commandList[subId].name }} 26 | {{ commandList[subId].shortcut | shortcutTranslate }} 27 | 28 |
    • 29 |
      30 |
    31 |
  • 32 |
    33 | 34 |
  • 35 |
    36 | 37 | 38 | 39 |
    40 |
41 | -------------------------------------------------------------------------------- /src/app/header/header-dropdown/header-dropdown.component.scss: -------------------------------------------------------------------------------- 1 | li span.item { 2 | display: flex; 3 | flex-direction: row; 4 | 5 | .item-name { 6 | flex-grow: 1; 7 | flex-shrink: 0; 8 | } 9 | .item-shortcut { 10 | flex-shrink: 0; 11 | padding-left: 1em; 12 | } 13 | } -------------------------------------------------------------------------------- /src/app/header/header-dropdown/header-dropdown.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HeaderDropdownComponent } from './header-dropdown.component'; 4 | 5 | describe('HeaderDropdownComponent', () => { 6 | let component: HeaderDropdownComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ HeaderDropdownComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HeaderDropdownComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/header/header-dropdown/header-dropdown.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, Input, OnInit } from '@angular/core'; 19 | 20 | import { Pipe, PipeTransform } from '@angular/core'; 21 | import { Command, StatusService } from '../../services/status.service'; 22 | 23 | export type DropdownList = Array< 24 | string | { 25 | title: string, 26 | children: string[] 27 | } 28 | >; 29 | 30 | @Pipe({ 31 | name: 'typeof' 32 | }) 33 | export class TypeofPipe implements PipeTransform { 34 | transform(value: any, typeofChecker: T): T { 35 | return typeof value === typeof typeofChecker ? value : undefined; 36 | } 37 | } 38 | 39 | @Pipe({ 40 | name: 'shortcutTranslate' 41 | }) 42 | export class ShortcutTranslatePipe implements PipeTransform { 43 | transform(value: string): string { 44 | if (value === null) return ''; 45 | return value.split('.').map(v => { 46 | switch (v) { 47 | case 'control': return 'Ctrl'; 48 | case 'alt': return 'Alt'; 49 | case 'shift': return 'Shift'; 50 | default: return v.toUpperCase(); 51 | } 52 | }).join('+'); 53 | } 54 | } 55 | 56 | @Component({ 57 | selector: 'app-header-dropdown', 58 | templateUrl: './header-dropdown.component.html', 59 | styleUrls: ['./header-dropdown.component.scss'] 60 | }) 61 | export class HeaderDropdownComponent implements OnInit { 62 | 63 | readonly commandList: { 64 | [key: string]: Command 65 | }; 66 | 67 | constructor( 68 | private statusService: StatusService 69 | ) { 70 | this.commandList = this.statusService.commandList; 71 | } 72 | 73 | @Input('data') list: DropdownList; 74 | 75 | ngOnInit(): void { 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/app/header/header.component.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/app/header/header.component.scss: -------------------------------------------------------------------------------- 1 | #menuBar { 2 | .ant-menu-horizontal { 3 | line-height: 25px; 4 | >.ant-menu-submenu { 5 | margin: -1px 8px 0; 6 | } 7 | } 8 | } 9 | 10 | // .ant-menu-vertical.ant-menu-sub { 11 | // min-width: 200px; 12 | 13 | // .mySubmenu { 14 | // .ant-menu-item,.ant-menu-submenu-title { 15 | // $h: 26px; 16 | // height: $h; 17 | // line-height: $h; 18 | // } 19 | // .ant-dropdown-menu-item-divider { 20 | // margin-top: -4px; 21 | // } 22 | // } 23 | // } -------------------------------------------------------------------------------- /src/app/header/header.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HeaderComponent } from './header.component'; 4 | 5 | describe('HeaderComponent', () => { 6 | let component: HeaderComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ HeaderComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HeaderComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/header/header.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit, ViewEncapsulation } from '@angular/core'; 19 | 20 | import { Command } from '../services/status.service'; 21 | import { DropdownList } from './header-dropdown/header-dropdown.component'; 22 | 23 | 24 | @Component({ 25 | selector: 'app-header', 26 | templateUrl: './header.component.html', 27 | styleUrls: ['./header.component.scss'], 28 | encapsulation: ViewEncapsulation.None 29 | }) 30 | export class HeaderComponent implements OnInit { 31 | 32 | readonly commandList: { 33 | [key: string]: Command 34 | }; 35 | 36 | fileMenuId: DropdownList = [ 37 | "file.new", 38 | "file.open", 39 | "#divider", 40 | "file.save", 41 | "file.saveAs" 42 | ]; 43 | editMenuId: DropdownList = [ 44 | "edit.undo", 45 | "edit.redo", 46 | "#divider", 47 | "edit.cut", 48 | "edit.copy", 49 | "edit.paste", 50 | "#divider", 51 | "edit.find", 52 | "edit.replace", 53 | "#divider", 54 | "edit.commentLine" 55 | ]; 56 | runMenuId: DropdownList = [ 57 | "build.build", 58 | "build.run", 59 | "build.buildRun", 60 | "#divider", 61 | "debug.start", 62 | "debug.exit" 63 | ]; 64 | 65 | toolMenuId: DropdownList = [ 66 | "tool.openBuildSetting", 67 | "tool.openEditorSetting" 68 | ]; 69 | 70 | helpMenuId: DropdownList = [ 71 | "window.toggleDevtools" 72 | ]; 73 | 74 | constructor() { 75 | } 76 | 77 | ngOnInit(): void { 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/app/header/header.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | 21 | import { NzDropDownModule } from 'ng-zorro-antd/dropdown'; 22 | import { NzButtonModule } from 'ng-zorro-antd/button'; 23 | import { NzModalModule } from 'ng-zorro-antd/modal'; 24 | import { NzNotificationModule } from 'ng-zorro-antd/notification'; 25 | import { NzIconModule } from 'ng-zorro-antd/icon'; 26 | import { NzNoAnimationModule } from 'ng-zorro-antd/core/no-animation' 27 | 28 | import { FileControlComponent } from './file-control/file-control.component'; 29 | import { BuildControlComponent } from './build-control/build-control.component'; 30 | import { HeaderComponent } from './header.component'; 31 | import { HeaderDropdownComponent, ShortcutTranslatePipe, TypeofPipe } from './header-dropdown/header-dropdown.component'; 32 | import { CoreModule } from '../core/core.module'; 33 | 34 | @NgModule({ 35 | declarations: [ 36 | FileControlComponent, 37 | BuildControlComponent, 38 | HeaderComponent, 39 | HeaderDropdownComponent, 40 | TypeofPipe, 41 | ShortcutTranslatePipe 42 | ], 43 | imports: [ 44 | CommonModule, 45 | NzDropDownModule, 46 | NzButtonModule, 47 | NzModalModule, 48 | NzNotificationModule, 49 | NzIconModule, 50 | NzNoAnimationModule, 51 | CoreModule 52 | ], 53 | exports: [HeaderComponent] 54 | }) 55 | export class HeaderModule { } 56 | -------------------------------------------------------------------------------- /src/app/main-view/empty-page/empty-page.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/main-view/empty-page/empty-page.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | height: 100%; 3 | width: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items :center; 8 | user-select: none; 9 | 10 | // p { 11 | // display:block; 12 | // font-size: 30pt; 13 | // color: lightgray; 14 | // } 15 | 16 | img { 17 | display: block; 18 | filter: grayscale(100%) brightness(2); 19 | max-width: 40%; 20 | max-height: 40%; 21 | } 22 | } -------------------------------------------------------------------------------- /src/app/main-view/empty-page/empty-page.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EmptyPageComponent } from './empty-page.component'; 4 | 5 | describe('EmptyPageComponent', () => { 6 | let component: EmptyPageComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EmptyPageComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EmptyPageComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/empty-page/empty-page.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | 20 | @Component({ 21 | selector: 'app-empty-page', 22 | templateUrl: './empty-page.component.html', 23 | styleUrls: ['./empty-page.component.scss'] 24 | }) 25 | export class EmptyPageComponent implements OnInit { 26 | 27 | constructor() { } 28 | 29 | ngOnInit(): void { 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/app/main-view/main-view.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |
    7 |
  • 10 | 11 |
  • 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 |
27 | 28 | 32 | 33 |
34 | -------------------------------------------------------------------------------- /src/app/main-view/main-view.component.scss: -------------------------------------------------------------------------------- 1 | #asContainer { 2 | width : 100%; 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | 7 | #outerSplit { 8 | flex-grow: 1; 9 | } 10 | 11 | #upperPart { 12 | height: 100%; 13 | display: flex; 14 | flex-direction: row; 15 | 16 | #sidebarMenu { 17 | width: 32px; 18 | } 19 | } 20 | 21 | #toolsArea { 22 | overflow: hidden; 23 | } 24 | } -------------------------------------------------------------------------------- /src/app/main-view/main-view.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { MainViewComponent } from './main-view.component'; 4 | 5 | describe('MainViewComponent', () => { 6 | let component: MainViewComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ MainViewComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(MainViewComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/main-view.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { AfterViewInit, Component, OnInit, QueryList, ViewChildren } from '@angular/core'; 19 | import { Router } from '@angular/router'; 20 | import { IOutputData } from 'angular-split'; 21 | import { ProblemsService } from '../services/problems.service'; 22 | 23 | @Component({ 24 | selector: 'app-main-view', 25 | templateUrl: './main-view.component.html', 26 | styleUrls: ['./main-view.component.scss'] 27 | }) 28 | export class MainViewComponent implements OnInit { 29 | readonly sidebarItems = [ 30 | { 31 | title: '大纲', 32 | url: 'outline', 33 | icon: 'partition', 34 | disabled: false 35 | }, 36 | { 37 | title: '项目管理', 38 | url: 'project', 39 | icon: 'project', 40 | disabled: true 41 | }, 42 | { 43 | title: '调试查看', 44 | url: 'watch', 45 | icon: 'eye', 46 | disabled: false 47 | } 48 | ]; 49 | currentOutletUrl(name: string) { 50 | const routerChildren = this.router.parseUrl(this.router.url).root.children; 51 | if (name in routerChildren) { 52 | return routerChildren[name].segments[0].path; 53 | } 54 | return null; 55 | } 56 | 57 | readonly toolsItems = [ 58 | { 59 | title: '问题', 60 | url: 'problems', 61 | disabled: false 62 | }, 63 | { 64 | title: '输出', 65 | url: 'output', 66 | disabled: false 67 | }, 68 | { 69 | title: '调试', 70 | url: 'debug', 71 | disabled: false 72 | } 73 | ]; 74 | 75 | constructor(private router: Router, private problemsService: ProblemsService) { } 76 | 77 | ngOnInit(): void { } 78 | 79 | showSidebar(who: string): void { 80 | if (who === this.currentOutletUrl("sidebar") || who === null) { 81 | this.router.navigate([{ 82 | outlets: { 83 | sidebar: null 84 | } 85 | }]); 86 | } else { 87 | if (this.sidebarItems.find(i => i.url === who).disabled) return; 88 | this.router.navigate([{ 89 | outlets: { 90 | sidebar: who 91 | } 92 | }]); 93 | } 94 | } 95 | 96 | showTools(who: string): void { 97 | if (who === this.currentOutletUrl("tools") || who === null) { 98 | this.router.navigate([{ 99 | outlets: { 100 | tools: null 101 | } 102 | }]); 103 | } else { 104 | if (this.toolsItems.find(i => i.url === who).disabled) return; 105 | this.router.navigate([{ 106 | outlets: { 107 | tools: who 108 | } 109 | }]); 110 | } 111 | } 112 | 113 | toolsSizeOnChange(event: IOutputData) { 114 | this.problemsService.panelHeight = event.sizes[1] as number; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/app/main-view/main-view.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { AppRoutingModule } from '../app-routing.module'; 21 | import { NzMenuModule } from 'ng-zorro-antd/menu'; 22 | import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; 23 | import { NzButtonModule } from 'ng-zorro-antd/button'; 24 | import { NzIconModule } from 'ng-zorro-antd/icon'; 25 | import { AngularSplitModule } from 'angular-split'; 26 | 27 | import { MainViewComponent } from './main-view.component'; 28 | import { TabsModule } from './tabs/tabs.module'; 29 | import { SidebarModule } from './sidebar/sidebar.module'; 30 | import { ToolsModule } from './tools/tools.module'; 31 | 32 | @NgModule({ 33 | declarations: [MainViewComponent], 34 | imports: [ 35 | CommonModule, 36 | AppRoutingModule, 37 | NzMenuModule, 38 | NzToolTipModule, 39 | NzButtonModule, 40 | NzIconModule, 41 | AngularSplitModule, 42 | TabsModule, 43 | SidebarModule, 44 | ToolsModule 45 | ], 46 | exports: [MainViewComponent] 47 | }) 48 | export class MainViewModule { } 49 | -------------------------------------------------------------------------------- /src/app/main-view/sidebar/outline/outline.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ node.name }} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {{ node.name }} 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/app/main-view/sidebar/outline/outline.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | font-family: var(--monospace-font); 3 | .codicon { 4 | transform: translateY(25%); 5 | } 6 | } 7 | 8 | // Copied from VS Code runtime 9 | .codicon.codicon-symbol-array { color: #616161; } 10 | .codicon.codicon-symbol-boolean { color: #616161; } 11 | .codicon.codicon-symbol-class { color: #d67e00; } 12 | .codicon.codicon-symbol-method { color: #652d90; } 13 | .codicon.codicon-symbol-color { color: #616161; } 14 | .codicon.codicon-symbol-constant { color: #616161; } 15 | .codicon.codicon-symbol-constructor { color: #652d90; } 16 | .codicon.codicon-symbol-value { color: #d67e00; } 17 | .codicon.codicon-symbol-enum { color: #d67e00; } 18 | .codicon.codicon-symbol-enum-member { color: #007acc; } 19 | .codicon.codicon-symbol-event { color: #d67e00; } 20 | .codicon.codicon-symbol-field { color: #007acc; } 21 | .codicon.codicon-symbol-file { color: #616161; } 22 | .codicon.codicon-symbol-folder { color: #616161; } 23 | .codicon.codicon-symbol-function { color: #652d90; } 24 | .codicon.codicon-symbol-interface { color: #007acc; } 25 | .codicon.codicon-symbol-key { color: #616161; } 26 | .codicon.codicon-symbol-keyword { color: #616161; } 27 | .codicon.codicon-symbol-module { color: #616161; } 28 | .codicon.codicon-symbol-namespace { color: #616161; } 29 | .codicon.codicon-symbol-null { color: #616161; } 30 | .codicon.codicon-symbol-number { color: #616161; } 31 | .codicon.codicon-symbol-object { color: #616161; } 32 | .codicon.codicon-symbol-operator { color: #616161; } 33 | .codicon.codicon-symbol-package { color: #616161; } 34 | .codicon.codicon-symbol-property { color: #616161; } 35 | .codicon.codicon-symbol-reference { color: #616161; } 36 | .codicon.codicon-symbol-snippet { color: #616161; } 37 | .codicon.codicon-symbol-string { color: #616161; } 38 | .codicon.codicon-symbol-struct { color: #616161; } 39 | .codicon.codicon-symbol-text { color: #616161; } 40 | .codicon.codicon-symbol-type-parameter { color: #616161; } 41 | .codicon.codicon-symbol-unit { color: #616161; } 42 | .codicon.codicon-symbol-variable { color: #007acc; } -------------------------------------------------------------------------------- /src/app/main-view/sidebar/outline/outline.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { OutlineComponent } from './outline.component'; 4 | 5 | describe('OutlineComponent', () => { 6 | let component: OutlineComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ OutlineComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(OutlineComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/sidebar/sidebar-routing.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { Routes, RouterModule } from '@angular/router'; 21 | 22 | import { OutlineComponent } from './outline/outline.component'; 23 | import { WatchComponent } from './watch/watch.component'; 24 | 25 | const routes: Routes = [ 26 | { 27 | path: 'outline', 28 | component: OutlineComponent, 29 | outlet: 'sidebar' 30 | }, 31 | { 32 | path: 'watch', 33 | component: WatchComponent, 34 | outlet: 'sidebar' 35 | } 36 | ]; 37 | 38 | @NgModule({ 39 | declarations: [], 40 | imports: [CommonModule, RouterModule.forChild(routes)], 41 | exports: [RouterModule] 42 | }) 43 | export class SidebarRoutingModule {} -------------------------------------------------------------------------------- /src/app/main-view/sidebar/sidebar.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { FormsModule } from '@angular/forms'; 21 | import { NzTreeModule } from 'ng-zorro-antd/tree'; 22 | import { NzTreeViewModule } from 'ng-zorro-antd/tree-view'; 23 | import { NzInputModule } from 'ng-zorro-antd/input'; 24 | import { NzButtonModule } from 'ng-zorro-antd/button'; 25 | import { NzTagModule } from 'ng-zorro-antd/tag'; 26 | import { NzIconModule } from 'ng-zorro-antd/icon'; 27 | 28 | import { CoreModule } from '../../core/core.module'; 29 | 30 | import { OutlineComponent } from './outline/outline.component'; 31 | import { WatchComponent } from './watch/watch.component'; 32 | 33 | @NgModule({ 34 | declarations: [ OutlineComponent, WatchComponent ], 35 | imports: [ 36 | CommonModule, 37 | FormsModule, 38 | NzTreeModule, 39 | NzTreeViewModule, 40 | NzInputModule, 41 | NzButtonModule, 42 | NzTagModule, 43 | NzIconModule, 44 | CoreModule 45 | ], 46 | exports: [ OutlineComponent, WatchComponent ] 47 | }) 48 | export class SidebarModule { } 49 | -------------------------------------------------------------------------------- /src/app/main-view/sidebar/watch/watch.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{ node.expression }} : {{ node.value === null ? '未知' : node.value }} 21 | 22 | 24 | 25 | 26 | 28 | 29 | 30 | {{node.title}} 31 | 32 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /src/app/main-view/sidebar/watch/watch.component.scss: -------------------------------------------------------------------------------- 1 | #watchVarTreeWrapper { 2 | .node-label { 3 | user-select: none; 4 | } 5 | 6 | #localTree { 7 | .ant-tree-node-selected,.ant-tree-node-content-wrapper:hover { 8 | background: inherit !important; 9 | } 10 | 11 | .ant-tree-node-content-wrapper { 12 | cursor: initial !important; 13 | } 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /src/app/main-view/sidebar/watch/watch.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { WatchComponent } from './watch.component'; 4 | 5 | describe('WatchComponent', () => { 6 | let component: WatchComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ WatchComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(WatchComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/sidebar/watch/watch.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit, ViewEncapsulation } from '@angular/core'; 19 | import { TreeControl } from '@angular/cdk/tree'; 20 | import { NzTreeNodeOptions } from 'ng-zorro-antd/tree'; 21 | import { Observable } from 'rxjs'; 22 | import { distinctUntilChanged, map } from 'rxjs/operators'; 23 | import { DebugService } from '../../../services/debug.service'; 24 | import { WatchService, DynamicDatasource, GdbVarInfoNode } from '../../../services/watch.service'; 25 | 26 | @Component({ 27 | selector: 'app-watch', 28 | templateUrl: './watch.component.html', 29 | styleUrls: ['./watch.component.scss'], 30 | encapsulation: ViewEncapsulation.None 31 | }) 32 | export class WatchComponent implements OnInit { 33 | 34 | localVariables$: Observable; 35 | isDebugging$: Observable; 36 | treeControl: TreeControl; 37 | dataSource: DynamicDatasource; 38 | editingNodeId: string | null = null; 39 | editingValue: string = ""; 40 | 41 | constructor(private debugService: DebugService, private watchService: WatchService) { } 42 | 43 | ngOnInit(): void { 44 | this.localVariables$ = this.debugService.localVariables$.pipe( 45 | map(arr => arr.map(val => ({ 46 | key: val["name"], 47 | title: `${val["name"]} : ${val["value"]}`, 48 | isLeaf: true 49 | }))) 50 | ); 51 | this.isDebugging$ = this.debugService.isDebugging$.pipe( 52 | distinctUntilChanged() 53 | ); 54 | this.dataSource = this.watchService.dataSource; 55 | this.treeControl = this.watchService.treeControl; 56 | } 57 | 58 | tryEdit(node: GdbVarInfoNode) { 59 | if (node.level !== 0) return; 60 | this.watchService.editNode(node); 61 | this.editingValue = node.expression; 62 | this.editingNodeId = node.id; 63 | } 64 | saveEdit(node: GdbVarInfoNode) { 65 | if (this.editingValue.trim() !== "") 66 | this.watchService.saveNode(node, this.editingValue); 67 | else 68 | this.watchService.deleteNode(node, 'user'); 69 | this.editingNodeId = null; 70 | } 71 | 72 | newVariable() { 73 | const newId = this.watchService.newNode(); 74 | this.editingValue = ''; 75 | this.editingNodeId = newId; 76 | } 77 | 78 | clearAll() { 79 | this.watchService.clearAllNode(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/editor/editor.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/editor/editor.component.scss: -------------------------------------------------------------------------------- 1 | ngx-monaco-editor { 2 | height: 100%; 3 | 4 | .editor-container { 5 | overflow: overlay !important; 6 | 7 | .bkpt-line-decoration { 8 | background: var(--breakpoint-background-color); 9 | } 10 | 11 | .bkpt-glyph-margin { 12 | color : red // $font-size: 14px; 13 | // $icon-size: $font-size * 0.8; 14 | // $padding: $font-size * 0.3; 15 | 16 | // background: red; 17 | // width: $icon-size !important; 18 | // height: $icon-size !important; 19 | // margin: $padding; 20 | // border-radius: $icon-size / 2; 21 | } 22 | 23 | .trace-line-decoration { 24 | background: var(--debug-step-background-color); 25 | } 26 | 27 | .trace-glyph-margin { 28 | color: blue; 29 | } 30 | 31 | .bkpt-glyph-margin.codicon, 32 | .trace-glyph-margin.codicon { 33 | // Disable global translateY(15%) 34 | transform: none; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/editor/editor.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditorComponent } from './editor.component'; 4 | 5 | describe('EditorComponent', () => { 6 | let component: EditorComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EditorComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditorComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/editor/editor.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; 19 | import { ActivatedRoute } from '@angular/router'; 20 | 21 | import { EditorService } from '../../../services/editor.service'; 22 | import { TabsService } from '../../../services/tabs.service'; 23 | 24 | @Component({ 25 | selector: 'app-editor', 26 | templateUrl: './editor.component.html', 27 | styleUrls: ['./editor.component.scss'], 28 | encapsulation: ViewEncapsulation.None 29 | }) 30 | export class EditorComponent implements OnInit, OnDestroy { 31 | 32 | editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = { 33 | glyphMargin: true, 34 | lineNumbersMinChars: 2, 35 | 'semanticHighlighting.enabled': true 36 | }; 37 | key: string; 38 | get code() { 39 | return this.editorService.getCode(); 40 | } 41 | 42 | constructor(private route: ActivatedRoute, 43 | private tabsService: TabsService, 44 | private editorService: EditorService) { } 45 | 46 | 47 | private keyOnChange(key: string) { 48 | if (typeof key === "undefined") this.key = null; 49 | this.key = key; 50 | } 51 | 52 | ngOnInit(): void { 53 | this.route.params.subscribe(routeParams => { 54 | this.keyOnChange(routeParams['key']); 55 | }); 56 | console.log(this.editorService); 57 | } 58 | 59 | ngOnDestroy() { 60 | this.editorService.editorDestroy(); 61 | } 62 | 63 | editorInit(editor: monaco.editor.IStandaloneCodeEditor) { 64 | if (!this.editorService.isLanguageClientStarted) this.editorService.startLanguageClient(); 65 | this.editorService.editorInit(editor); 66 | if (this.key) { 67 | const activeTab = this.tabsService.getByKey(this.key).value; 68 | this.editorService.switchToModel(activeTab); 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/build-setting.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
    5 |
  • 编译环境
  • 6 |
  • 单文件编译
  • 7 |
8 |
9 | 10 | 11 | 12 |
13 | 14 | 保存后设置才会生效。 15 | 16 | 17 | 18 |
19 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/build-setting.component.scss: -------------------------------------------------------------------------------- 1 | @import "../common_styles.scss" 2 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/build-setting.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BuildSettingComponent } from './build-setting.component'; 4 | 5 | describe('BuildSettingComponent', () => { 6 | let component: BuildSettingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ BuildSettingComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(BuildSettingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/build-setting.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | import { ActivatedRoute } from '@angular/router'; 20 | import { SettingsService } from '../../../../services/settings.service'; 21 | 22 | @Component({ 23 | selector: 'app-build-setting', 24 | templateUrl: './build-setting.component.html', 25 | styleUrls: ['./build-setting.component.scss'] 26 | }) 27 | export class BuildSettingComponent implements OnInit { 28 | 29 | constructor(private route: ActivatedRoute, 30 | private settingsService: SettingsService) { } 31 | 32 | ngOnInit() { } 33 | 34 | saveOption() { 35 | this.settingsService.saveSetting('build'); 36 | } 37 | 38 | resetOption() { 39 | this.settingsService.resetSetting('build'); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/env-setting/env-setting.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

输入输出编码

5 | 6 | 7 | 8 | 9 | 设置与编译器和 GDB 交互时将采用的编码。若在单文件编译中启用了“调整可执行文件编码”选项,则可执行文件的输出编码也将设置为此。 10 | 11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 |

MinGW 路径

19 | 20 | 21 |
22 |
23 |

Clangd 路径

24 | 25 | 26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/env-setting/env-setting.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../common_subsetting_styles.scss"; 2 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/env-setting/env-setting.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EnvSettingComponent } from './env-setting.component'; 4 | 5 | describe('EnvSettingComponent', () => { 6 | let component: EnvSettingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EnvSettingComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EnvSettingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/env-setting/env-setting.component.ts: -------------------------------------------------------------------------------- 1 | import { ActivatedRoute } from '@angular/router'; 2 | import { Component, OnInit } from '@angular/core'; 3 | import { Subject } from 'rxjs'; 4 | import { debounceTime } from 'rxjs/operators'; 5 | import { ElectronService } from '../../../../../core/services'; 6 | import { EnvOptions, SettingsGuard, SettingsService } from '../../../../../services/settings.service'; 7 | 8 | @Component({ 9 | selector: 'app-env-setting', 10 | templateUrl: './env-setting.component.html', 11 | styleUrls: ['./env-setting.component.scss'] 12 | }) 13 | export class EnvSettingComponent implements OnInit { 14 | 15 | constructor(private settingsService: SettingsService, 16 | private electronService: ElectronService, 17 | private settingsGuard: SettingsGuard) { 18 | } 19 | 20 | currentEncoding = new Subject(); 21 | currentEncodingValid = true; 22 | 23 | get currentEnvOptions(): EnvOptions { 24 | return this.settingsService.getOptions('build').env; 25 | } 26 | 27 | ngOnInit(): void { 28 | this.settingsGuard.lastVisitedUrl['~build'] = 'env'; 29 | this.currentEncoding.pipe( 30 | debounceTime(200) 31 | ).subscribe(e => { 32 | this.electronService.ipcRenderer.invoke('encode/verify', e) 33 | .then(r => this.currentEncodingValid = r); 34 | }); 35 | } 36 | 37 | onChange(): void { 38 | this.settingsService.onChange('build'); 39 | } 40 | 41 | verify(): void { 42 | this.currentEncoding.next(this.currentEnvOptions.ioEncoding); 43 | } 44 | 45 | async getDefaultEncoding(): Promise { 46 | const cp = await this.electronService.ipcRenderer.invoke('encode/getAcp'); 47 | this.currentEnvOptions.ioEncoding = cp; 48 | this.onChange(); 49 | this.verify(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/sfb-setting/sfb-setting.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

标准

5 | 6 | 7 | 8 |
9 | 12 |
13 |
14 |

优化

15 | 16 | 17 | 18 | 19 |
20 |
21 |

调试

22 | 25 |
26 | 调试前的编译会默认启用 -g 27 |
28 |
29 |
30 |
31 |

警告

32 |
35 |
38 |
41 |
42 |
43 |

编码

44 |
47 |
48 |
49 |

自定义...

50 |
51 | 52 | {{arg.substr(3) + '...'}} 53 | 54 | {{arg}} 55 | 56 | 57 | {{arg}} 59 | 63 |
64 |
65 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/sfb-setting/sfb-setting.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../common_subsetting_styles.scss"; 2 | 3 | nz-layout { 4 | 5 | #customArgs { 6 | font-family: var(--monospace-font); 7 | cursor: text; 8 | 9 | #innerInput { 10 | width: 150px; 11 | display: inline-block; 12 | } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/sfb-setting/sfb-setting.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SfbSettingComponent } from './sfb-setting.component'; 4 | 5 | describe('SfbSettingComponent', () => { 6 | let component: SfbSettingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SfbSettingComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SfbSettingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/build-setting/sfb-setting/sfb-setting.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { SettingsGuard, SettingsService, SfbOptions } from '../../../../../services/settings.service'; 4 | 5 | @Component({ 6 | selector: 'app-sfb-setting', 7 | templateUrl: './sfb-setting.component.html', 8 | styleUrls: ['./sfb-setting.component.scss'] 9 | }) 10 | export class SfbSettingComponent implements OnInit { 11 | 12 | customArgsDivClass: string[] = []; 13 | 14 | constructor(private settingsService: SettingsService, 15 | private settingsGuard: SettingsGuard) { 16 | } 17 | 18 | stdOptions = [ 19 | '98', 20 | '11', 21 | '14', 22 | '17', 23 | '20', 24 | ]; 25 | optOptions = [ 26 | '1', '2', '3', 's', 'fast', 'g' 27 | ]; 28 | 29 | ngOnInit(): void { 30 | console.log(this.currentOptions); 31 | this.settingsGuard.lastVisitedUrl['~build'] = 'sfb'; 32 | } 33 | 34 | onChange(): void { 35 | this.settingsService.onChange('build'); 36 | } 37 | 38 | get currentOptions(): SfbOptions { 39 | return this.settingsService.getOptions('build').sfb; 40 | } 41 | 42 | get buildedArgs(): string[] { 43 | return this.currentOptions.toList(); 44 | } 45 | 46 | customSubmit(value: string): void { 47 | const index = this.currentOptions.other.indexOf(value); 48 | if (index === -1) { 49 | this.currentOptions.other.push(value); 50 | this.onChange(); 51 | } 52 | } 53 | customRemove(value: string): void { 54 | this.onChange(); 55 | const index = this.currentOptions.other.indexOf(value); 56 | if (index !== -1) { 57 | this.currentOptions.other.splice(index, 1); 58 | this.onChange(); 59 | } 60 | } 61 | removeLast(): void { 62 | if (this.currentOptions.other.length > 0) { 63 | this.onChange(); 64 | this.currentOptions.other.pop(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/common_styles.scss: -------------------------------------------------------------------------------- 1 | #wrapper { 2 | height: 100%; 3 | background: inherit; 4 | 5 | display: flex; 6 | flex-direction: column; 7 | 8 | nz-layout { 9 | background: inherit; 10 | flex-grow: 1; 11 | overflow-y: auto; 12 | 13 | >nz-sider { 14 | background: inherit; 15 | 16 | ul { 17 | height: 100%; 18 | } 19 | } 20 | } 21 | 22 | nz-footer { 23 | button { 24 | margin-right: 8px; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/common_subsetting_styles.scss: -------------------------------------------------------------------------------- 1 | nz-layout { 2 | background: inherit; 3 | padding: 20px; 4 | overflow-y: auto; 5 | 6 | div[nz-row] { 7 | margin-bottom: 16px; 8 | } 9 | 10 | nz-select { 11 | width: 100%; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/editor-setting.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
    5 |
  • 主题设置
  • 6 |
7 |
8 | 9 | 10 | 11 |
12 | 13 | 保存后设置才会生效。 14 | 15 | 16 | 17 |
18 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/editor-setting.component.scss: -------------------------------------------------------------------------------- 1 | @import "../common_styles.scss" 2 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/editor-setting.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditorSettingComponent } from './editor-setting.component'; 4 | 5 | describe('EditorSettingComponent', () => { 6 | let component: EditorSettingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ EditorSettingComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditorSettingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/editor-setting.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of devcpp7. 4 | // 5 | // devcpp7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // devcpp7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with devcpp7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | import { ActivatedRoute } from '@angular/router'; 20 | import { SettingsService } from '../../../../services/settings.service'; 21 | 22 | @Component({ 23 | selector: 'app-editor-setting', 24 | templateUrl: './editor-setting.component.html', 25 | styleUrls: ['./editor-setting.component.scss'] 26 | }) 27 | export class EditorSettingComponent implements OnInit { 28 | 29 | constructor(private route: ActivatedRoute, 30 | private settingsService: SettingsService,) { } 31 | 32 | ngOnInit() { } 33 | 34 | saveOption() { 35 | this.settingsService.saveSetting('editor'); 36 | } 37 | 38 | resetOption() { 39 | this.settingsService.resetSetting('editor'); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/theme-setting/theme-setting.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |

选择当前主题

6 | 7 | 8 | 9 |
10 | 你可以在 安装路径\resources\extraResources\themes 中添加更多主题。 11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/theme-setting/theme-setting.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../common_subsetting_styles.scss"; 2 | 3 | nz-radio-group { 4 | 5 | display: block; 6 | 7 | [nz-radio] { 8 | display: block; 9 | height: 32px; 10 | line-height: 32px; 11 | } 12 | 13 | margin-bottom: 8px; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/theme-setting/theme-setting.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ThemeSettingComponent } from './theme-setting.component'; 4 | 5 | describe('ThemeSettingComponent', () => { 6 | let component: ThemeSettingComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ThemeSettingComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ThemeSettingComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/settings/editor-setting/theme-setting/theme-setting.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of devcpp7. 4 | // 5 | // devcpp7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // devcpp7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with devcpp7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | import { ActivatedRoute } from '@angular/router'; 20 | import { ElectronService } from '../../../../../core/services'; 21 | import { SettingsGuard, SettingsService } from '../../../../../services/settings.service'; 22 | 23 | @Component({ 24 | selector: 'app-theme-setting', 25 | templateUrl: './theme-setting.component.html', 26 | styleUrls: ['./theme-setting.component.scss'] 27 | }) 28 | export class ThemeSettingComponent implements OnInit { 29 | 30 | themeList: string[] = ['1', '2']; 31 | 32 | constructor(private settingsService: SettingsService, 33 | private electronService: ElectronService, 34 | private settingsGuard: SettingsGuard) { 35 | } 36 | 37 | get currentThemeOptions(): { activeName: string } { 38 | return this.settingsService.getOptions('editor').theme; 39 | } 40 | 41 | ngOnInit(): void { 42 | this.settingsGuard.lastVisitedUrl['~editor'] = 'theme'; 43 | this.refreshList(); 44 | } 45 | 46 | refreshList(): void { 47 | this.electronService.ipcRenderer.invoke('theme/getList').then(v => this.themeList = v); 48 | } 49 | 50 | onChange(): void { 51 | this.settingsService.onChange('editor'); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/tabs-routing.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { Routes, RouterModule } from '@angular/router'; 21 | import { EditorComponent } from './editor/editor.component'; 22 | import { EmptyPageComponent } from '../empty-page/empty-page.component'; 23 | import { BuildSettingComponent } from './settings/build-setting/build-setting.component'; 24 | import { SfbSettingComponent } from './settings/build-setting/sfb-setting/sfb-setting.component'; 25 | import { EnvSettingComponent } from './settings/build-setting/env-setting/env-setting.component'; 26 | import { SettingsGuard } from '../../services/settings.service'; 27 | import { EditorSettingComponent } from './settings/editor-setting/editor-setting.component'; 28 | import { ThemeSettingComponent } from './settings/editor-setting/theme-setting/theme-setting.component'; 29 | 30 | const routes: Routes = [ 31 | { 32 | path: 'empty', 33 | component: EmptyPageComponent 34 | }, 35 | { 36 | path: 'file/:key', 37 | component: EditorComponent 38 | }, 39 | { 40 | path: 'setting/~build', 41 | component: BuildSettingComponent, 42 | children: [ 43 | { 44 | path: '', 45 | canActivate: [SettingsGuard], 46 | component: EmptyPageComponent 47 | }, 48 | { 49 | path: 'sfb', 50 | component: SfbSettingComponent 51 | }, 52 | { 53 | path: 'env', 54 | component: EnvSettingComponent 55 | } 56 | ] 57 | }, 58 | { 59 | path: 'setting/~editor', 60 | component: EditorSettingComponent, 61 | children: [ 62 | { 63 | path: '', 64 | canActivate: [SettingsGuard], 65 | component: EmptyPageComponent 66 | }, 67 | { 68 | path: 'theme', 69 | component: ThemeSettingComponent 70 | } 71 | ] 72 | }, 73 | { 74 | path: '**', 75 | redirectTo: 'empty' 76 | } 77 | ]; 78 | 79 | @NgModule({ 80 | declarations: [], 81 | imports: [CommonModule, RouterModule.forChild(routes)], 82 | exports: [RouterModule] 83 | }) 84 | export class TabsRoutingModule { } 85 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/tabs.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { FormsModule } from '@angular/forms'; 21 | import { DragDropModule } from '@angular/cdk/drag-drop'; 22 | import { AppRoutingModule } from '../../app-routing.module'; 23 | 24 | import { NzTabsModule } from 'ng-zorro-antd/tabs'; 25 | import { NzLayoutModule } from 'ng-zorro-antd/layout'; 26 | import { NzGridModule } from 'ng-zorro-antd/grid'; 27 | import { NzMenuModule } from 'ng-zorro-antd/menu'; 28 | import { NzSelectModule } from 'ng-zorro-antd/select'; 29 | import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; 30 | import { NzRadioModule } from 'ng-zorro-antd/radio'; 31 | import { NzInputModule } from 'ng-zorro-antd/input'; 32 | import { NzButtonModule } from 'ng-zorro-antd/button'; 33 | import { NzModalModule } from 'ng-zorro-antd/modal'; 34 | import { NzAlertModule } from 'ng-zorro-antd/alert'; 35 | import { NzIconModule } from 'ng-zorro-antd/icon'; 36 | 37 | import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor'; 38 | 39 | import { TabsComponent } from './tabs/tabs.component'; 40 | import { EditorComponent } from './editor/editor.component'; 41 | import { BuildSettingComponent } from './settings/build-setting/build-setting.component'; 42 | import { SfbSettingComponent } from './settings/build-setting/sfb-setting/sfb-setting.component'; 43 | import { EnvSettingComponent } from './settings/build-setting/env-setting/env-setting.component'; 44 | 45 | import { EditorSettingComponent } from './settings/editor-setting/editor-setting.component'; 46 | import { ThemeSettingComponent } from './settings/editor-setting/theme-setting/theme-setting.component'; 47 | import { NzTagModule } from 'ng-zorro-antd/tag'; 48 | 49 | @NgModule({ 50 | declarations: [ 51 | TabsComponent, EditorComponent, 52 | BuildSettingComponent, SfbSettingComponent, EnvSettingComponent, 53 | EditorSettingComponent, ThemeSettingComponent 54 | ], 55 | imports: [ 56 | CommonModule, 57 | AppRoutingModule, 58 | FormsModule, 59 | DragDropModule, 60 | NzTabsModule, 61 | NzLayoutModule, 62 | NzGridModule, 63 | NzMenuModule, 64 | NzButtonModule, 65 | NzSelectModule, 66 | NzCheckboxModule, 67 | NzRadioModule, 68 | NzTagModule, 69 | NzInputModule, 70 | NzModalModule, 71 | NzAlertModule, 72 | NzIconModule, 73 | MonacoEditorModule 74 | ], 75 | exports: [TabsComponent] 76 | }) 77 | export class TabsModule { } 78 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/tabs/tabs.component.html: -------------------------------------------------------------------------------- 1 |
2 | 4 | 5 | 6 |
7 | 8 | {{ (tab.saved? '' : '*') + tab.title }} 9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 | 19 | 是否保存为 {{ notSaveModalTab.title }}? 20 | 21 |
22 | 23 | 24 | 25 |
26 |
-------------------------------------------------------------------------------- /src/app/main-view/tabs/tabs/tabs.component.scss: -------------------------------------------------------------------------------- 1 | #tabContainer { 2 | height : 100%; 3 | width : 100%; 4 | display : flex; 5 | flex-direction: column; 6 | 7 | nz-tabset { 8 | flex-shrink: 0; 9 | } 10 | .tab-title { 11 | display : inline; 12 | user-select: none; 13 | } 14 | 15 | #routerWrapper { 16 | flex-grow : 1; 17 | min-height: 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/tabs/tabs.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { TabsComponent } from './tabs.component'; 4 | 5 | describe('TabsComponent', () => { 6 | let component: TabsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ TabsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(TabsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tabs/tabs/tabs.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; 20 | import { Tab, TabsService } from '../../../services/tabs.service'; 21 | import { Router } from '@angular/router'; 22 | import { FileService } from '../../../services/file.service'; 23 | import { StatusService } from '../../../services/status.service'; 24 | import { ElectronService } from '../../../core/services'; 25 | import { AppConfig } from '../../../../environments/environment'; 26 | import { SettingsService } from '../../../services/settings.service'; 27 | 28 | @Component({ 29 | selector: 'app-tabs', 30 | templateUrl: './tabs.component.html', 31 | styleUrls: ['./tabs.component.scss'] 32 | }) 33 | export class TabsComponent implements OnInit { 34 | 35 | constructor( 36 | private router: Router, 37 | private electronService: ElectronService, 38 | private tabsService: TabsService, 39 | private fileService: FileService, 40 | private settingsService: SettingsService, 41 | // private statusService: StatusService 42 | ) { } 43 | 44 | ngOnInit(): void { 45 | if (AppConfig.production) { 46 | this.electronService.ipcRenderer.invoke('window/getArgv').then(argv => { 47 | argv.shift(); 48 | this.fileService.open(false, argv); 49 | }); 50 | } 51 | if (this.tabsService.getActive().index !== null) { 52 | // eslint-disable-next-line 53 | this.activeIndex = this.activeIndex; 54 | } 55 | } 56 | 57 | get tabList() { 58 | return this.tabsService.tabList; 59 | } 60 | 61 | 62 | 63 | get activeIndex(): number { 64 | return this.tabsService.getActive().index; 65 | } 66 | set activeIndex(index: number) { 67 | if (index >= 0) { 68 | this.tabsService.changeActive(index); 69 | const tab = this.tabList[index]; 70 | this.router.navigate([tab.type + '/' + tab.key]); 71 | } 72 | } 73 | 74 | private doRemoveTab(tab: Tab) { 75 | this.activeIndex = this.tabsService.remove(tab.key); 76 | if (this.tabList.length === 0) { 77 | this.router.navigate(['empty']); 78 | } 79 | } 80 | 81 | closeTab(e: { index: number }) { 82 | const target = this.tabList[e.index]; 83 | if (target.saved === false) { 84 | this.notSaveModalShow(target); 85 | } else { 86 | this.doRemoveTab(target); 87 | } 88 | } 89 | 90 | // https://github.com/NG-ZORRO/ng-zorro-antd/issues/3461 91 | cdkOnDrop(event: CdkDragDrop) { 92 | moveItemInArray(this.tabsService.tabList, event.previousIndex, event.currentIndex); 93 | // this.activeIndex = event.currentIndex; 94 | } 95 | 96 | notSaveModalTab: Tab; 97 | notSaveModalVisible = false; 98 | async notSaveModalYes() { 99 | this.notSaveModalVisible = false; 100 | if (this.notSaveModalTab.type === "file" && await this.fileService.save(this.notSaveModalTab)) 101 | this.doRemoveTab(this.notSaveModalTab); 102 | if (this.notSaveModalTab.type === "setting" && this.settingsService.saveTab(this.notSaveModalTab)) 103 | this.doRemoveTab(this.notSaveModalTab); 104 | } 105 | notSaveModalNo() { 106 | this.notSaveModalVisible = false; 107 | this.doRemoveTab(this.notSaveModalTab); 108 | } 109 | notSaveModalCancel() { 110 | this.notSaveModalVisible = false; 111 | } 112 | 113 | private notSaveModalShow(target: Tab) { 114 | this.notSaveModalTab = target; 115 | this.notSaveModalVisible = true; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/app/main-view/tools/debug/debug.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | 3 | #debugPanel { 4 | display : flex; 5 | height : 100%; 6 | flex-direction: row; 7 | 8 | #leftPart { 9 | width : 225px; 10 | flex-shrink : 0; 11 | display : flex; 12 | flex-direction : column; 13 | justify-content: center; 14 | border-right : 2px solid lightgrey; 15 | padding : 10px; 16 | 17 | #exprEval { 18 | flex-grow: 1; 19 | text-align: center; 20 | 21 | input { 22 | width: 100%; 23 | } 24 | 25 | #exprResult { 26 | border : 1px solid lightgray; 27 | border-radius : 2px; 28 | font-family : var(--monospace-font); 29 | text-align: initial; 30 | } 31 | } 32 | 33 | #debugControl { 34 | display : flex; 35 | flex-direction : row; 36 | justify-content: center; 37 | 38 | button { 39 | padding: 4px 6px; 40 | } 41 | } 42 | } 43 | 44 | #rightPart { 45 | flex-grow : 1; 46 | height : 100%; 47 | padding : 10px; 48 | display : flex; 49 | flex-direction: row-reverse; 50 | 51 | #tabHeadWrapper { 52 | flex-shrink: 0; 53 | } 54 | 55 | #tabContentWrapper { 56 | flex-grow : 1; 57 | min-width : 0px; 58 | height : 100%; 59 | overflow-y: auto; 60 | 61 | #console { 62 | display : flex; 63 | flex-direction: column; 64 | border : 1px solid lightgray; 65 | border-radius : 2px; 66 | font-family : var(--monospace-font); 67 | 68 | #consoleOutput { 69 | flex-grow : 1; 70 | border-bottom: 1px solid lightgrey; 71 | padding : 4px 11px; 72 | white-space : pre-wrap; 73 | overflow-y : scroll; 74 | } 75 | 76 | #consoleInput { 77 | display : flex; 78 | flex-direction: row; 79 | align-items : center; 80 | 81 | i { 82 | padding-left: 4px; 83 | } 84 | 85 | input { 86 | flex-grow : 1; 87 | padding-left: 2px; 88 | } 89 | } 90 | } 91 | 92 | #callStackTableBody { 93 | font-family: var(--monospace-font); 94 | } 95 | 96 | #breakpointTableBody { 97 | font-family: var(--monospace-font); 98 | 99 | .editable-cell { 100 | position: relative; 101 | padding : 5px 12px; 102 | cursor : pointer; 103 | } 104 | 105 | .editable-row:hover .editable-cell { 106 | border : 1px solid #d9d9d9; 107 | border-radius: 2px; 108 | padding : 4px 11px; 109 | } 110 | } 111 | } 112 | 113 | .tab-content { 114 | height: 100%; 115 | } 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /src/app/main-view/tools/debug/debug.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { DebugComponent } from './debug.component'; 4 | 5 | describe('DebugComponent', () => { 6 | let component: DebugComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ DebugComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(DebugComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tools/output/output.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
{{ compileMessage$ | async }}
5 |
6 | 7 |
{{ linkMessage$ | async }}
8 |
9 | 10 |
{{ otherMessage$ | async }}
11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
-------------------------------------------------------------------------------- /src/app/main-view/tools/output/output.component.scss: -------------------------------------------------------------------------------- 1 | #collapseContainer { 2 | height: 100%; 3 | overflow-y: scroll; 4 | 5 | .output { 6 | font-family: var(--monospace-font); 7 | word-break: break-all; 8 | white-space: pre-wrap; 9 | } 10 | } -------------------------------------------------------------------------------- /src/app/main-view/tools/output/output.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { OutputComponent } from './output.component'; 4 | 5 | describe('OutputComponent', () => { 6 | let component: OutputComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ OutputComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(OutputComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tools/output/output.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | import { Observable } from 'rxjs'; 20 | import { map } from 'rxjs/operators'; 21 | import { ProblemsService } from '../../../services/problems.service'; 22 | 23 | @Component({ 24 | selector: 'app-output', 25 | templateUrl: './output.component.html', 26 | styleUrls: ['./output.component.scss'] 27 | }) 28 | export class OutputComponent implements OnInit { 29 | 30 | constructor(private problemsService: ProblemsService) { } 31 | 32 | compileMessage$: Observable; 33 | linkMessage$: Observable; 34 | otherMessage$: Observable; 35 | 36 | ngOnInit(): void { 37 | this.compileMessage$ = this.problemsService.problems.pipe( 38 | map(data => JSON.stringify(data).replace(/\n/g, '\\')) 39 | ); 40 | this.linkMessage$ = this.problemsService.linkerr; 41 | this.otherMessage$ = this.problemsService.unknownerr; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/app/main-view/tools/problems/problems.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 错误信息 6 | 位置 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | {{ item.message }} 24 | 25 | 26 | {{ printPosition(item.locations[0].caret) }} 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/app/main-view/tools/problems/problems.component.scss: -------------------------------------------------------------------------------- 1 | .message { 2 | font-family: var(--monospace-font); 3 | } -------------------------------------------------------------------------------- /src/app/main-view/tools/problems/problems.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProblemsComponent } from './problems.component'; 4 | 5 | describe('ProblemsComponent', () => { 6 | let component: ProblemsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ProblemsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProblemsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/main-view/tools/problems/problems.component.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Component, OnInit } from '@angular/core'; 19 | import { GccDiagnostic, GccDiagnosticPosition } from '../../../core/ipcTyping'; 20 | import { ProblemsService } from '../../../services/problems.service'; 21 | import * as path from 'path'; 22 | import { FileService } from '../../../services/file.service'; 23 | import { Observable } from 'rxjs'; 24 | import { map } from 'rxjs/operators'; 25 | 26 | import { replaceGccDiagnostics } from 'gcc-translation'; 27 | 28 | export interface ITreeNode extends GccDiagnostic { 29 | level: number; 30 | expand: boolean; 31 | parent?: ITreeNode; 32 | } 33 | 34 | 35 | @Component({ 36 | selector: 'app-problems', 37 | templateUrl: './problems.component.html', 38 | styleUrls: ['./problems.component.scss'] 39 | }) 40 | export class ProblemsComponent implements OnInit { 41 | 42 | readonly iconMap: { [key: string]: { type: string, color: string } } = { 43 | error: { 44 | type: 'close-circle', 45 | color: 'red' 46 | }, 47 | warning: { 48 | type: 'warning', 49 | color: 'orange' 50 | }, 51 | note: { 52 | type: 'info-circle', 53 | color: 'blue' 54 | } 55 | }; 56 | 57 | printPosition(position: GccDiagnosticPosition): string { 58 | return `${path.basename(position.file.replace(/\n/g, '\\'))}:${position.line}:${position.column}`; 59 | } 60 | 61 | flattenData$: Observable; 62 | 63 | constructor( 64 | private fileService: FileService, 65 | private problemsService: ProblemsService) { } 66 | 67 | ngOnInit(): void { 68 | this.flattenData$ = this.problemsService.problems.pipe( 69 | map(rawData => { 70 | const flatten: ITreeNode[] = []; 71 | rawData.forEach(item => { 72 | flatten.splice(-1, 0, ...this.flattener(item)); 73 | }); 74 | console.log(flatten); 75 | return flatten; 76 | }) 77 | ); 78 | } 79 | 80 | get tableHeight(): number { 81 | return this.problemsService.panelHeight - this.tableHeaderHeight; 82 | } 83 | 84 | // Ant-design: font-size * line-height + 2 * padding 85 | private readonly tableHeaderHeight: number = 14 * 1.5715 + 2 * 8; 86 | 87 | private flattener(root: GccDiagnostic): ITreeNode[] { 88 | const stack: ITreeNode[] = []; 89 | const array: ITreeNode[] = []; 90 | stack.push({ ...root, level: 0, expand: false }); 91 | while (stack.length !== 0) { 92 | const node = stack.pop(); 93 | node.message = replaceGccDiagnostics(node.message); 94 | array.push(node); 95 | if (node.children) { 96 | for (let i = node.children.length - 1; i >= 0; i--) { 97 | stack.push({ ...node.children[i], level: node.level + 1, expand: false, parent: node }); 98 | } 99 | } 100 | } 101 | return array; 102 | } 103 | 104 | showProblem(item: ITreeNode): void { 105 | const mainLocation = item.locations[0].caret; 106 | this.fileService.locate(mainLocation.file.replace(/\n|\//g, '\\'), mainLocation.line, mainLocation.column); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/app/main-view/tools/tools-routing.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { Routes, RouterModule } from '@angular/router'; 21 | 22 | import { ProblemsComponent } from './problems/problems.component' 23 | import { OutputComponent } from './output/output.component'; 24 | import { DebugComponent } from './debug/debug.component'; 25 | 26 | const routes: Routes = [ 27 | { 28 | path: 'problems', 29 | component: ProblemsComponent, 30 | outlet: 'tools' 31 | }, 32 | { 33 | path: 'output', 34 | component: OutputComponent, 35 | outlet: 'tools' 36 | }, 37 | { 38 | path: 'debug', 39 | component: DebugComponent, 40 | outlet: 'tools' 41 | } 42 | ]; 43 | 44 | @NgModule({ 45 | declarations: [], 46 | imports: [CommonModule, RouterModule.forChild(routes)], 47 | exports: [RouterModule] 48 | }) 49 | export class ToolsRoutingModule {} -------------------------------------------------------------------------------- /src/app/main-view/tools/tools.module.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { NgModule } from '@angular/core'; 19 | import { CommonModule } from '@angular/common'; 20 | import { FormsModule } from '@angular/forms'; 21 | import { ClipboardModule } from '@angular/cdk/clipboard'; 22 | import { NzIconModule } from 'ng-zorro-antd/icon'; 23 | import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; 24 | import { NzButtonModule } from 'ng-zorro-antd/button'; 25 | import { NzInputModule } from 'ng-zorro-antd/input'; 26 | import { NzTableModule } from 'ng-zorro-antd/table'; 27 | import { NzTabsModule } from 'ng-zorro-antd/tabs'; 28 | import { NzCollapseModule } from 'ng-zorro-antd/collapse'; 29 | 30 | import { CoreModule } from '../../core/core.module'; 31 | 32 | import { ProblemsComponent } from './problems/problems.component'; 33 | import { OutputComponent } from './output/output.component'; 34 | import { DebugComponent } from './debug/debug.component'; 35 | 36 | @NgModule({ 37 | declarations: [ ProblemsComponent, OutputComponent, DebugComponent ], 38 | imports: [ 39 | CommonModule, 40 | FormsModule, 41 | ClipboardModule, 42 | NzIconModule, 43 | NzToolTipModule, 44 | NzButtonModule, 45 | NzInputModule, 46 | NzTableModule, 47 | NzTabsModule, 48 | NzCollapseModule, 49 | CoreModule 50 | ] 51 | }) 52 | export class ToolsModule { } 53 | -------------------------------------------------------------------------------- /src/app/services/README.md: -------------------------------------------------------------------------------- 1 | # Informations about services 2 | 3 | The most part of code is in these services. 4 | 5 | ## Dependency graph 6 | 7 | Below chart shows all services' dependency relation. `A --> B` means that A is depend on B. 8 | 9 | ``` 10 | Components StatusService 11 | ===================||===================== 12 | vv 13 | 14 | HotkeysService WatchService 15 | | 16 | | 17 | v 18 | BuildService DebugService SettingsService 19 | +---------------+ | | 20 | | v +----|--------------------+ 21 | v ProblemService | | | 22 | FileService <---------------------+----+ (Set trace line) | 23 | | | | 24 | +--------+ | ThemeService 25 | v | | | 26 | TabsService | | (Get breakpoint) | 27 | | | | | 28 | | +----+ | | 29 | v v | | 30 | EditorService <------------------------+--------------------+ 31 | 32 | ===================||===================== 33 | vv 34 | core/ElectronService (if needed) 35 | ``` 36 | -------------------------------------------------------------------------------- /src/app/services/build.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { BuildService } from './build.service'; 4 | 5 | describe('BuildService', () => { 6 | let service: BuildService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(BuildService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/debug.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { DebugService } from './debug.service'; 4 | 5 | describe('DebugService', () => { 6 | let service: DebugService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(DebugService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/editor.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { EditorService } from './editor.service'; 4 | 5 | describe('EditorService', () => { 6 | let service: EditorService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(EditorService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/file.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { FileService } from './file.service'; 4 | 5 | describe('FileService', () => { 6 | let service: FileService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(FileService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/hotkeys.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { HotkeysService } from './hotkeys.service'; 4 | 5 | describe('HotkeysService', () => { 6 | let service: HotkeysService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(HotkeysService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/hotkeys.service.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Inject, Injectable } from '@angular/core'; 19 | import { EventManager } from '@angular/platform-browser'; 20 | import { DOCUMENT } from '@angular/common'; 21 | import { Observable } from 'rxjs'; 22 | 23 | interface Options { 24 | element: any; 25 | keys: string; 26 | } 27 | 28 | @Injectable({ 29 | providedIn: 'root' 30 | }) 31 | export class HotkeysService { 32 | 33 | private readonly defaults: Partial = { 34 | element: this.document 35 | }; 36 | 37 | constructor(private eventManager: EventManager, 38 | @Inject(DOCUMENT) private document: Document 39 | ) { } 40 | 41 | addShortcut(options: Partial) { 42 | const merged = { ...this.defaults, ...options }; 43 | const event = `keydown.${merged.keys}`; 44 | return new Observable(observer => { 45 | const handler = (e: KeyboardEvent) => { 46 | e.preventDefault(); 47 | observer.next(e); 48 | }; 49 | const dispose = this.eventManager.addEventListener( 50 | merged.element, event, handler 51 | ); 52 | return () => dispose(); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/app/services/problems.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ProblemsService } from './problems.service'; 4 | 5 | describe('ProblemsService', () => { 6 | let service: ProblemsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(ProblemsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/problems.service.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { Injectable } from '@angular/core'; 19 | import { BehaviorSubject } from 'rxjs'; 20 | import { GccDiagnostics } from '../core/ipcTyping'; 21 | 22 | @Injectable({ 23 | providedIn: 'root' 24 | }) 25 | export class ProblemsService { 26 | 27 | panelHeight = 200; 28 | 29 | problems = new BehaviorSubject([]); 30 | linkerr = new BehaviorSubject(""); 31 | unknownerr = new BehaviorSubject(""); 32 | 33 | constructor() { } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/app/services/settings.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { SettingsService } from './settings.service'; 4 | 5 | describe('SettingsService', () => { 6 | let service: SettingsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(SettingsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/status.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { StatusService } from './status.service'; 4 | 5 | describe('StatusService', () => { 6 | let service: StatusService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(StatusService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/tabs.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { TabsService } from './tabs.service'; 4 | 5 | describe('TabsService', () => { 6 | let service: TabsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(TabsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/theme.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ThemeService } from './theme.service'; 4 | 5 | describe('ThemeService', () => { 6 | let service: ThemeService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(ThemeService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/services/watch.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { WatchService } from './watch.service'; 4 | 5 | describe('WatchService', () => { 6 | let service: WatchService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(WatchService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "PAGES": { 3 | "HOME": { 4 | "TITLE": "App works !", 5 | "GO_TO_DETAIL": "Go to Detail" 6 | }, 7 | "DETAIL": { 8 | "TITLE": "Detail page !", 9 | "BACK_TO_HOME": "Back to Home" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/assets/icons/cpp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/assets/icons/cpp.ico -------------------------------------------------------------------------------- /src/assets/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/assets/icons/favicon.ico -------------------------------------------------------------------------------- /src/assets/icons/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyutongxue/devcpp7/aa801a6cf296d69c2f366ddb021265eead33658c/src/assets/icons/favicon.png -------------------------------------------------------------------------------- /src/background/basicUtil.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import * as fs from "fs"; 19 | import * as path from 'path'; 20 | import { BrowserWindow, ipcMain } from 'electron'; 21 | import * as isAsar from 'electron-is-running-in-asar'; 22 | import * as Store from 'electron-store'; 23 | import * as chcp from 'chcp'; 24 | import { TypedIpcMain, TypedWebContents } from 'electron-typed-ipc'; 25 | 26 | import { IpcEvents, IpcCommands, Configurations } from './ipcTyping'; 27 | 28 | // very stupid to import a package, but useful. 29 | export const extraResourcesPath = 30 | !isAsar() 31 | ? path.join(__dirname, '../src/extraResources') 32 | : path.join(process['resourcesPath'], 'extraResources'); 33 | 34 | export function getWindow(): BrowserWindow { 35 | return global["win"]; 36 | } 37 | export function getWebContents(): TypedWebContents { 38 | return getWindow().webContents; 39 | } 40 | 41 | export const typedIpcMain = ipcMain as TypedIpcMain; 42 | 43 | export function getACP(): number { 44 | return chcp.getAnsiCodePage(); 45 | } 46 | 47 | export const store = new Store({ 48 | defaults: { 49 | 'build.compileArgs': [ 50 | '-g', '-std=c++20', 'DYN-fexec-charset' 51 | ], 52 | 'env.mingwPath': '', 53 | 'env.useBundledMingw': fs.existsSync(path.join(extraResourcesPath, "mingw64")), 54 | 'env.clangdPath': '', 55 | 'env.useBundledClangd': fs.existsSync(path.join(extraResourcesPath, "clangd")), 56 | 'advanced.ioEncoding': 'cp936', 57 | 'theme.active': 'classic' 58 | }, 59 | accessPropertiesByDotNotation: false 60 | }); 61 | 62 | export function getMingwPath(): string { 63 | if (store.get('env.useBundledMingw')) { 64 | return path.join(extraResourcesPath, 'mingw64'); 65 | } 66 | return store.get('env.mingwPath'); 67 | } 68 | 69 | export function getClangdPath(): string { 70 | if (store.get('env.useBundledClangd')) { 71 | return path.join(extraResourcesPath, 'clangd'); 72 | } 73 | return store.get('env.clangdPath'); 74 | } 75 | -------------------------------------------------------------------------------- /src/background/handlers/constants.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | -------------------------------------------------------------------------------- /src/background/handlers/debug.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { GdbController } from "tsgdbmi"; 19 | import * as path from 'path'; 20 | 21 | import { doCompile } from './build'; 22 | import { getWebContents, getWindow, typedIpcMain, store, getMingwPath } from '../basicUtil'; 23 | 24 | const gdb = new GdbController(store.get('advanced.ioEncoding')); 25 | gdb.onResponse(response => { 26 | switch (response.type) { 27 | case "console": 28 | getWebContents().send('ng:debug/console', response); 29 | break; 30 | case "notify": 31 | getWebContents().send('ng:debug/notify', response); 32 | getWindow().focus(); 33 | break; 34 | case "result": 35 | getWebContents().send('ng:debug/result', response); 36 | break; 37 | default: 38 | break; 39 | } 40 | }); 41 | gdb.onClose(() => { 42 | getWebContents().send('ng:debug/debuggerStopped'); 43 | }); 44 | const gdbPath = path.join(getMingwPath(), 'bin/gdb.exe'); 45 | const startupCommand = [ 46 | '-gdb-set new-console on', 47 | '-enable-pretty-printing' 48 | ]; 49 | 50 | typedIpcMain.handle('debug/start', async (_, arg) => { 51 | const result = await doCompile(arg.srcPath, true); 52 | getWebContents().send('ng:build/buildComplete', result); 53 | if (!result.success) { 54 | return { 55 | success: false, 56 | error: "Compilation failed." 57 | }; 58 | } 59 | if (gdb.isRunning) { 60 | gdb.exit(); 61 | // wait for a while 62 | await new Promise(r => setTimeout(r, 500)); 63 | } 64 | const cwd = path.dirname(result.output); 65 | const filename = path.basename(result.output); 66 | gdb.launch(gdbPath, [filename], { 67 | cwd: cwd 68 | }); 69 | try { 70 | for (const command of startupCommand) { 71 | const response = await gdb.sendRequest(command); 72 | if (response.message === "error") { 73 | return { 74 | success: false, 75 | error: `Startup command '${command}' execution failed` 76 | }; 77 | } 78 | } 79 | } catch (e) { 80 | return { 81 | success: false, 82 | error: e 83 | }; 84 | } 85 | getWebContents().send('ng:debug/debuggerStarted'); 86 | return { 87 | success: true 88 | }; 89 | }); 90 | 91 | typedIpcMain.handle('debug/exit', (_) => { 92 | if (!gdb.isRunning) { 93 | return; 94 | } 95 | gdb.exit(); 96 | }); 97 | 98 | typedIpcMain.handle('debug/sendRequest', (_, arg) => { 99 | if (!gdb.isRunning) { 100 | return { 101 | success: false, 102 | error: "GDB not started" 103 | }; 104 | } 105 | try { 106 | console.log("request: " + arg.command); 107 | gdb.sendRequest(arg.command, false); 108 | return { 109 | success: true 110 | }; 111 | } catch (e) { 112 | return { 113 | success: false, 114 | error: e 115 | }; 116 | } 117 | }); 118 | -------------------------------------------------------------------------------- /src/background/handlers/encode.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { typedIpcMain, getACP } from "../basicUtil"; 19 | import * as iconv from "iconv-lite"; 20 | 21 | // Codepages that are missing from iconv-lite 22 | const missingCP: { [key: string]: string } = { 23 | "1200": "utf-16le", 24 | "1201": "utf-16be", 25 | "12000": "utf-32le", 26 | "12001": "utf-32be", 27 | // "16969": "utf-64le", 28 | "20127": "ascii", 29 | "65000": "utf-7", 30 | "65001": "utf-8", 31 | }; 32 | 33 | typedIpcMain.handle('encode/getAcp', (_) => { 34 | const cp: string = getACP().toString(); 35 | if (cp in missingCP) 36 | return missingCP[cp]; 37 | // iconv, used by MinGW, only recognize cp-prefix codepages 38 | return "cp" + cp; 39 | }); 40 | 41 | typedIpcMain.handle('encode/verify', (_, encode: string) => { 42 | return iconv.encodingExists(encode); 43 | }); 44 | -------------------------------------------------------------------------------- /src/background/handlers/file.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import * as electron from 'electron'; 19 | import * as fs from 'fs'; 20 | import { v4 as uuidv4 } from 'uuid'; 21 | import { getWindow, typedIpcMain } from '../basicUtil'; 22 | 23 | // interface Result { success: boolean, [key: string]: any }; 24 | 25 | typedIpcMain.handle('file/save', (_, arg) => { 26 | try { 27 | fs.writeFileSync(arg.path, arg.content, "utf-8"); 28 | return { 29 | success: true 30 | }; 31 | } catch (e) { 32 | return { 33 | success: false, 34 | error: e 35 | } 36 | } 37 | }); 38 | 39 | typedIpcMain.handle('file/saveAs', async (_, arg) => { 40 | try { 41 | let options: electron.SaveDialogOptions = { 42 | defaultPath: arg.defaultFilename, 43 | filters: [ 44 | { name: "C++ 源文件", extensions: ["cpp", "h", "hpp", "cc", "cxx"] }, 45 | { name: "C 源文件", extensions: ["c", "h"] }, 46 | { name: "所有文件", extensions: ["*"] }, 47 | ], 48 | }; 49 | const r = await electron.dialog.showSaveDialog(getWindow(), options); 50 | if (!r.canceled) { 51 | fs.writeFileSync(r.filePath, arg.content, "utf-8"); 52 | return { 53 | success: true, 54 | path: r.filePath 55 | } 56 | } else { 57 | return { 58 | success: false, 59 | cancelled: true 60 | }; 61 | } 62 | } catch (e) { 63 | return { 64 | success: false, 65 | cancelled: false, 66 | error: e 67 | }; 68 | } 69 | }); 70 | 71 | 72 | typedIpcMain.handle('file/open', async (_, arg) => { 73 | interface FileInfo { 74 | path: string; 75 | content: string; 76 | key: string; 77 | }; 78 | try { 79 | const files: FileInfo[] = []; 80 | arg.paths.forEach(path => { 81 | const content = fs.readFileSync(path).toString("utf-8"); 82 | const key = uuidv4(); 83 | files.push({ 84 | content: content, 85 | key: key, 86 | path: path 87 | }); 88 | }); 89 | if (arg.showDialog) { 90 | const options: electron.OpenDialogOptions = { 91 | filters: [ 92 | { name: "C++ Source Files", extensions: ["cpp"] }, 93 | { name: "All Files", extensions: ["*"] }, 94 | ], 95 | properties: [ 96 | "openFile", 97 | "multiSelections" 98 | ] 99 | }; 100 | const result = await electron.dialog.showOpenDialog(getWindow(), options); 101 | if (!result.canceled) { 102 | result.filePaths.forEach(path => { 103 | const content = fs.readFileSync(path).toString("utf-8"); 104 | const key = uuidv4(); 105 | files.push({ 106 | content: content, 107 | key: key, 108 | path: path 109 | }); 110 | }); 111 | } 112 | } 113 | return { 114 | success: true, 115 | files: files 116 | }; 117 | } catch (e) { 118 | return { 119 | success: false, 120 | error: e 121 | }; 122 | } 123 | }); 124 | -------------------------------------------------------------------------------- /src/background/handlers/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import './store'; 19 | import './file'; 20 | import './build'; 21 | import './server'; 22 | import './debug'; 23 | import './window'; 24 | import './encode'; 25 | import './theme'; 26 | -------------------------------------------------------------------------------- /src/background/handlers/server.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import * as child_process from 'child_process'; 19 | import * as path from 'path'; 20 | import * as getPort from 'get-port'; 21 | 22 | import { extraResourcesPath, getClangdPath, getMingwPath, getWebContents, typedIpcMain } from '../basicUtil'; 23 | 24 | 25 | async function doStart() { 26 | const port = await getPort({ port: 3000 }); 27 | const process = child_process.fork( 28 | path.join(__dirname, 'server/server.js'), 29 | [ 30 | port.toString(), 31 | path.join(getClangdPath(), 'bin/clangd.exe'), 32 | path.join(getMingwPath(), 'bin'), 33 | `--compile-commands-dir=${path.join(extraResourcesPath, 'anon_workspace')}`, 34 | // `--log=verbose` 35 | ], 36 | { 37 | stdio: "ignore" 38 | } 39 | ); 40 | return { port, process }; 41 | } 42 | 43 | function getServerProc(): child_process.ChildProcess | null { 44 | return global['langServerProcess']; 45 | } 46 | function setServerProc(proc: child_process.ChildProcess | null) { 47 | global['langServerProcess'] = proc; 48 | } 49 | 50 | async function startServer() { 51 | console.log("Starting language server..."); 52 | const result = await doStart(); 53 | console.log("done"); 54 | getWebContents().send('ng:langServer/started', result.port); 55 | setServerProc(result.process); 56 | result.process.addListener('close', () => { 57 | setServerProc(null); 58 | getWebContents().send('ng:langServer/stopped'); 59 | }); 60 | } 61 | 62 | function stopServer() { 63 | const proc = getServerProc(); 64 | if (proc !== null) { 65 | proc.kill(); 66 | } 67 | } 68 | 69 | export function restartServer(): Promise { 70 | stopServer(); 71 | return startServer(); 72 | } 73 | 74 | typedIpcMain.handle('langServer/start', startServer); 75 | 76 | typedIpcMain.handle('langServer/stop', stopServer); 77 | -------------------------------------------------------------------------------- /src/background/handlers/store.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import * as path from 'path'; 19 | import * as fs from 'fs'; 20 | import * as iconv from 'iconv-lite'; 21 | 22 | import { store, typedIpcMain, extraResourcesPath } from "../basicUtil"; 23 | import { Configurations } from '../ipcTyping'; 24 | import { restartServer } from './server'; 25 | 26 | function ignoreByClangdFilter(arg: string) { 27 | if (arg.startsWith('DYN')) return false; 28 | if (arg.startsWith('-fexec-charset')) return false; 29 | if (arg.startsWith('-finput-charset')) return false; 30 | return true; 31 | } 32 | 33 | function updateClangdCompileArgs(value: string[]) { 34 | const flags = [ 35 | '-xc++', '--target=x86_64-pc-windows-gnu', ...value.filter(ignoreByClangdFilter) 36 | ]; 37 | fs.writeFileSync(path.join(extraResourcesPath, '/anon_workspace/compile_flags.txt'), flags.join('\n')); 38 | } 39 | 40 | 41 | typedIpcMain.handle('store/get', (_, key) => { 42 | return store.get(key); 43 | }); 44 | 45 | 46 | type SetStoreHandlerMap = { 47 | [K in keyof Configurations]?: (value: Configurations[K]) => boolean; 48 | }; 49 | 50 | const setStoreHandlers: SetStoreHandlerMap = { 51 | 'advanced.ioEncoding': (value) => { 52 | if (!iconv.encodingExists(value)) { 53 | console.error(`[Set IO Encoding] ${value} is not a valid encoding`); 54 | return false; 55 | } 56 | return true; 57 | }, 58 | 'build.compileArgs': (value) => { 59 | updateClangdCompileArgs(value); 60 | return true; 61 | }, 62 | // Restart language server when mingw or clangd path changed 63 | 'env.mingwPath': () => (restartServer(), true), 64 | 'env.useBundledMingw': () => (restartServer(), true), 65 | 'env.clangdPath': () => (restartServer(), true), 66 | 'env.useBundledClangd': () => (restartServer(), true) 67 | }; 68 | 69 | typedIpcMain.handle('store/set', (_, key, value) => { 70 | if (key in setStoreHandlers) { 71 | const handler = setStoreHandlers[key] as (value: any) => boolean; 72 | if (!handler(value)) return; 73 | } 74 | store.set(key, value); 75 | }); 76 | 77 | typedIpcMain.handle('store/reset', (_, key) => { 78 | if (typeof key === "undefined") { 79 | store.clear(); 80 | } else { 81 | store.reset(key); 82 | } 83 | }); 84 | -------------------------------------------------------------------------------- /src/background/handlers/theme.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of devcpp7. 4 | // 5 | // devcpp7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // devcpp7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with devcpp7. If not, see . 17 | 18 | import * as fallbackTheme from '../../extraResources/themes/classic.json'; 19 | import * as fs from 'fs'; 20 | import * as path from 'path'; 21 | import { extraResourcesPath, store, typedIpcMain } from '../basicUtil'; 22 | import { Theme } from '../ipcTyping'; 23 | 24 | typedIpcMain.handle('theme/getList', (_) => { 25 | const themePath = path.join(extraResourcesPath, 'themes'); 26 | if (!fs.existsSync(themePath)) return []; 27 | const themeList = fs.readdirSync(themePath) 28 | .filter((file) => file.endsWith('.json')) 29 | .map((file) => file.slice(0, -5)); 30 | return themeList; 31 | }); 32 | 33 | typedIpcMain.handle('theme/getData', (_, name?) => { 34 | if (typeof name === 'undefined') { 35 | name = store.get('theme.active'); 36 | } 37 | const jsonPath = path.join(extraResourcesPath, 'themes', `${name}.json`); 38 | if (!fs.existsSync(jsonPath)) { 39 | return { 40 | success: false, 41 | theme: fallbackTheme, 42 | error: `Theme file ${name}.json not found.` 43 | }; 44 | } 45 | let theme: Theme | null = null; 46 | try { 47 | theme = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); 48 | } catch (e) { 49 | console.error(e); 50 | return { 51 | success: false, 52 | theme: fallbackTheme, 53 | error: `Theme file ${name}.json is not a valid JSON file.` 54 | }; 55 | } 56 | // validate 57 | if (!(('type' in theme) && 58 | ('name' in theme) && 59 | (theme.type === 'dark' || theme.type === 'light'))) { 60 | console.error("Invalid theme type"); 61 | return { 62 | success: false, 63 | theme: fallbackTheme, 64 | error: `Theme file ${name}.json is not a valid theme file.` 65 | }; 66 | } 67 | 68 | return { 69 | success: true, 70 | theme: { 71 | type: theme.type, 72 | name: theme.name, 73 | colors: { 74 | debugStep: fallbackTheme.colors.debugStep, 75 | breakpoint: fallbackTheme.colors.breakpoint, 76 | ...theme.colors 77 | }, 78 | boldTokens: theme.boldTokens ?? [], 79 | italicTokens: theme.italicTokens ?? [], 80 | underlineTokens: theme.underlineTokens ?? [] 81 | } 82 | }; 83 | }); 84 | -------------------------------------------------------------------------------- /src/background/handlers/window.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { extraResourcesPath, getWebContents, getWindow, typedIpcMain } from "../basicUtil"; 19 | 20 | typedIpcMain.handle('window/toggleDevTools', (_) => { 21 | getWebContents().toggleDevTools(); 22 | }); 23 | 24 | typedIpcMain.handle('window/setTitle', (_, title) => { 25 | if (title === "") getWindow().setTitle('Dev-C++ 7'); 26 | else getWindow().setTitle(title + ' - Dev-C++ 7'); 27 | }); 28 | 29 | typedIpcMain.handle('window/getArgv', (_) => process.argv); 30 | 31 | typedIpcMain.handle('window/getExtraResourcePath', (_) => extraResourcesPath); 32 | -------------------------------------------------------------------------------- /src/background/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | 19 | 20 | global['langServerProcess'] = null; 21 | 22 | // Hook all handlers 23 | import './handlers'; -------------------------------------------------------------------------------- /src/background/ipcTyping.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | // This file re-export ipcTyping declarations. 19 | 20 | export * from "../app/core/ipcTyping"; 21 | -------------------------------------------------------------------------------- /src/background/server/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018 TypeFox GmbH (http://www.typefox.io). All rights reserved. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | const http = require("http"); 7 | const url = require("url"); 8 | const net = require("net"); 9 | const ws = require("ws"); 10 | const express = require("express"); 11 | const rpc = require("@codingame/monaco-jsonrpc"); 12 | const lsp = require("vscode-languageserver"); 13 | 14 | /** 15 | * 16 | * @param {rpc.IWebSocket} socket 17 | * @param {string} serverPath 18 | * @param {NodeJS.ProcessEnv} env 19 | * @param {string[]} args 20 | */ 21 | function launch(socket, serverPath, env, args) { 22 | const reader = new rpc.WebSocketMessageReader(socket); 23 | const writer = new rpc.WebSocketMessageWriter(socket); 24 | const server = require("@codingame/monaco-jsonrpc/lib/server"); 25 | const socketConnection = server.createConnection(reader, writer, () => socket.dispose()); 26 | const serverConnection = server.createServerProcess('C++', serverPath, args, { 27 | env 28 | }); 29 | server.forward(socketConnection, serverConnection, message => { 30 | if (rpc.isRequestMessage(message)) { 31 | if (message.method === lsp.InitializeRequest.type.method) { 32 | /** @type lsp.InitializeParams */ 33 | const initializeParams = message.params; 34 | initializeParams.processId = process.pid; 35 | } 36 | } 37 | return message; 38 | }); 39 | } 40 | 41 | 42 | console.log(process.argv); 43 | // ["electron", "server.js", port, execPath, PATH, argv... ] 44 | if (process.argv.length < 5) { 45 | console.log(`Usage: server.js [...]`); 46 | process.exit(1); 47 | } 48 | const [port, execPath, PATH, ...serverArgs] = process.argv.slice(2); 49 | if (!/^\+?(0|[1-9]\d*)$/.test(port)) { // not a port number 50 | console.log(`Port "${port}" invalid.`); 51 | process.exit(1); 52 | } 53 | 54 | process.on('uncaughtException', function (err) { 55 | console.error('Uncaught Exception: ', err.toString()); 56 | if (err.stack) { 57 | console.error(err.stack); 58 | } 59 | }); 60 | 61 | // create the express application 62 | const app = express(); 63 | // server the static content, i.e. index.html 64 | app.use(express.static(__dirname)); 65 | // start the server 66 | const server = app.listen(port); 67 | // create the web socket 68 | const wss = new ws.Server({ 69 | noServer: true, 70 | perMessageDeflate: false 71 | }); 72 | 73 | /** 74 | * 75 | * @param {http.IncomingMessage} request 76 | * @param {net.Socket} socket 77 | * @param {Buffer} head 78 | */ 79 | const handler = (request, socket, head) => { 80 | const pathname = request.url ? url.parse(request.url).pathname : undefined; 81 | if (pathname === '/langServer') { 82 | wss.handleUpgrade(request, socket, head, webSocket => { 83 | /** @type rpc.IWebSocket */ 84 | const socket = { 85 | send: content => webSocket.send(content, error => { 86 | if (error) { 87 | throw error; 88 | } 89 | }), 90 | onMessage: cb => webSocket.on('message', cb), 91 | onError: cb => webSocket.on('error', cb), 92 | onClose: cb => webSocket.on('close', cb), 93 | dispose: () => webSocket.close() 94 | }; 95 | // launch the server when the web socket is opened 96 | if (webSocket.readyState === webSocket.OPEN) { 97 | launch(socket, execPath, { Path: PATH }, serverArgs); 98 | } else { 99 | webSocket.on('open', () => { 100 | launch(socket, execPath, { Path: PATH }, serverArgs); 101 | }); 102 | } 103 | }); 104 | } 105 | } 106 | server.on('upgrade', handler); 107 | -------------------------------------------------------------------------------- /src/environments/environment.dev.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: false, 3 | environment: 'DEV' 4 | }; 5 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: true, 3 | environment: 'PROD' 4 | }; 5 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: false, 3 | environment: 'LOCAL' 4 | }; 5 | -------------------------------------------------------------------------------- /src/environments/environment.web.ts: -------------------------------------------------------------------------------- 1 | export const AppConfig = { 2 | production: false, 3 | environment: 'WEB' 4 | }; 5 | -------------------------------------------------------------------------------- /src/extraResources/.gitignore: -------------------------------------------------------------------------------- 1 | /mingw64/ 2 | /clangd/ 3 | /bin/ 4 | -------------------------------------------------------------------------------- /src/extraResources/README.md: -------------------------------------------------------------------------------- 1 | # `extraResources` 2 | 3 | ## MinGW 4 | 5 | Unpacked https://github.com/Guyutongxue/mingw-release/releases/download/v11.1.0/gytx_x86_64-11.1.0-posix-seh.7z to `mingw64` directory. 6 | ### Language Server 7 | 8 | Unpacked https://github.com/clangd/clangd/releases/download/12.0.0/clangd-windows-12.0.0.zip to `clangd` directory. 9 | 10 | ## ConsolePauser 11 | 12 | A subproject copied from original Dev-C++. Put it at `bin/ConsolePauser.exe`. 13 | -------------------------------------------------------------------------------- /src/extraResources/anon_workspace/compile_flags.txt: -------------------------------------------------------------------------------- 1 | -xc++ 2 | --target=x86_64-pc-windows-gnu 3 | -std=c++20 4 | -g -------------------------------------------------------------------------------- /src/extraResources/generateResource.ps1: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 Guyutongxue 2 | # 3 | # This file is part of devcpp7. 4 | # 5 | # devcpp7 is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # devcpp7 is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with devcpp7. If not, see . 17 | 18 | $WITH_MINGW = $false; 19 | $WITH_CLANGD = $true; 20 | 21 | $GENERATE_ANON_WS = $true; 22 | 23 | $MINGW_VERSION = "11.2.0"; 24 | $MINGW_REV = "1" 25 | $CLANGD_VERSION = "12.0.0"; 26 | 27 | $DEFAULT_COMPILE_FLAGS = @( 28 | "-xc++", 29 | "--target=x86_64-pc-windows-gnu", 30 | "-std=c++20", 31 | "-g" 32 | ); 33 | 34 | # parse argv 35 | foreach ($arg in $args) { 36 | if ($arg -eq "--mingw") { 37 | $WITH_MINGW = $true; 38 | } 39 | if ($arg -eq "--no-mingw") { 40 | $WITH_MINGW = $false; 41 | } 42 | if ($arg -eq "--clangd") { 43 | $WITH_CLANGD = $true; 44 | } 45 | if ($arg -eq "--no-clangd") { 46 | $WITH_CLANGD = $false; 47 | } 48 | if ($arg -eq "--anon-ws") { 49 | $GENERATE_ANON_WS = $true; 50 | } 51 | if ($arg -eq "--no-anon-ws") { 52 | $GENERATE_ANON_WS = $false; 53 | } 54 | } 55 | 56 | Import-Module BitsTransfer; 57 | 58 | if ($WITH_MINGW || $WITH_CLANGD) { 59 | $env:Path += ";C:\\Program Files\\7-zip"; 60 | Get-Command "7z" -ErrorAction SilentlyContinue; 61 | if (!$?) { 62 | Write-Error "7z is not installed. Install 7-zip from 7-zip.org. You may need to add it to Path environment variable."; 63 | } 64 | } 65 | 66 | if ($WITH_MINGW) { 67 | if ($MINGW_REV -ne "0") { $DASH_REV = "-r$MINGW_REV"; $US_REV = "_r$MINGW_REV" } 68 | Start-BitsTransfer -Source "https://github.com/Guyutongxue/mingw-release/releases/download/v$MINGW_VERSION$DASH_REV/gytx_x86_64-$MINGW_VERSION-posix-seh$US_REV.7z" -Destination "mingw.7z"; 69 | 7z x -y mingw.7z 70 | Remove-Item -Path "mingw.7z"; 71 | Remove-Variable -Name DASH_REV, US_REV; 72 | } 73 | if ($WITH_CLANGD) { 74 | Start-BitsTransfer -Source "https://github.com/clangd/clangd/releases/download/$CLANGD_VERSION/clangd-windows-$CLANGD_VERSION.zip" -Destination "clangd.zip"; 75 | 7z x -y clangd.zip 76 | Rename-Item -Path "clangd_$CLANGD_VERSION" -NewName "clangd"; 77 | Remove-Item -Path "clangd.zip"; 78 | } 79 | if ($GENERATE_ANON_WS) { 80 | Remove-Item -Path "anon_workspace" -Recurse; 81 | New-Item -Path "anon_workspace" -ItemType Directory | Out-Null; 82 | New-Item -Path "anon_workspace/compile_flags.txt" | Out-Null; 83 | $DEFAULT_COMPILE_FLAGS -join "`r`n" | Out-File "anon_workspace/compile_flags.txt"; 84 | } 85 | -------------------------------------------------------------------------------- /src/extraResources/src/ConsolePauser.cpp: -------------------------------------------------------------------------------- 1 | // This Code was licensed under GPL v2 by Bloodshed Dev-C++ 2 | // Execute & Pause 3 | // Runs a program, then keeps the console window open after it finishes 4 | #include 5 | using std::string; 6 | #include 7 | #include 8 | #define MAX_COMMAND_LENGTH 32768 9 | #define MAX_ERROR_LENGTH 2048 10 | LONGLONG GetClockTick() { 11 | LARGE_INTEGER dummy; 12 | QueryPerformanceCounter(&dummy); 13 | return dummy.QuadPart; 14 | } 15 | LONGLONG GetClockFrequency() { 16 | LARGE_INTEGER dummy; 17 | QueryPerformanceFrequency(&dummy); 18 | return dummy.QuadPart; 19 | } 20 | void PauseExit(int exitcode) { 21 | system("pause"); 22 | exit(exitcode); 23 | } 24 | string GetErrorMessage() { 25 | string result(MAX_ERROR_LENGTH,0); 26 | 27 | FormatMessage( 28 | FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 29 | NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),&result[0],result.size(),NULL); 30 | 31 | // Clear newlines at end of string 32 | for(int i = result.length()-1;i >= 0;i--) { 33 | if(isspace(result[i])) { 34 | result[i] = 0; 35 | } else { 36 | break; 37 | } 38 | } 39 | return result; 40 | } 41 | string GetCommand(int argc,char** argv) { 42 | string result; 43 | for(int i = 1;i < argc;i++) { 44 | // Quote the first argument in case the path name contains spaces 45 | // if(i == 1) { 46 | // result += string("\"") + string(argv[i]) + string("\""); 47 | // } else { 48 | result += string(argv[i]); 49 | // } 50 | 51 | // Add a space except for the last argument 52 | if(i != (argc-1)) { 53 | result += string(" "); 54 | } 55 | } 56 | 57 | if(result.length() > MAX_COMMAND_LENGTH) { 58 | printf("\n--------------------------------"); 59 | printf("\nError: Length of command line string is over %d characters\n",MAX_COMMAND_LENGTH); 60 | PauseExit(EXIT_FAILURE); 61 | } 62 | 63 | return result; 64 | } 65 | DWORD ExecuteCommand(string& command) { 66 | STARTUPINFO si; 67 | PROCESS_INFORMATION pi; 68 | memset(&si,0,sizeof(si)); 69 | si.cb = sizeof(si); 70 | memset(&pi,0,sizeof(pi)); 71 | 72 | if(!CreateProcess(NULL, (LPSTR)command.c_str(), NULL, NULL, false, 0, NULL, NULL, &si, &pi)) { 73 | printf("\n--------------------------------"); 74 | printf("\nFailed to execute \"%s\":",command.c_str()); 75 | printf("\nError %lu: %s\n",GetLastError(),GetErrorMessage().c_str()); 76 | PauseExit(EXIT_FAILURE); 77 | } 78 | WaitForSingleObject(pi.hProcess, INFINITE); // Wait for it to finish 79 | 80 | DWORD result = 0; 81 | GetExitCodeProcess(pi.hProcess, &result); 82 | return result; 83 | } 84 | int main(int argc, char** argv) { 85 | 86 | // First make sure we aren't going to read nonexistent arrays 87 | if(argc < 2) { 88 | printf("\n--------------------------------"); 89 | printf("\nUsage: ConsolePauser.exe \n"); 90 | PauseExit(EXIT_SUCCESS); 91 | } 92 | 93 | // Make us look like the paused program 94 | SetConsoleTitle(argv[1]); 95 | 96 | // Then build the to-run application command 97 | string command = GetCommand(argc,argv); 98 | 99 | // Save starting timestamp 100 | LONGLONG starttime = GetClockTick(); 101 | 102 | // Then execute said command 103 | DWORD returnvalue = ExecuteCommand(command); 104 | 105 | // Get ending timestamp 106 | LONGLONG endtime = GetClockTick(); 107 | double seconds = (endtime - starttime) / (double)GetClockFrequency(); 108 | // Done? Print return value of executed program 109 | printf("\n--------------------------------"); 110 | printf("\nProcess exited after %.4g seconds with return value %lu\n",seconds,returnvalue); 111 | PauseExit(EXIT_SUCCESS); 112 | } -------------------------------------------------------------------------------- /src/extraResources/themes/classic.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./theme.schema.jsonc", 3 | "type": "light", 4 | "name": "Dev-C++ Classic+", 5 | "colors": { 6 | "background": "#ffffff", 7 | "foreground": "#000000", 8 | "activeLine": "#ccffff", 9 | "debugStep": "#add8e6", 10 | "breakpoint": "#f08080", 11 | "preprocessor": "#008000", 12 | "string": "#0000ff", 13 | "string.char": "#000000", 14 | "keyword": "#000000", 15 | "punctuation": "#ff0000", 16 | "number": "#800080", 17 | "comment": "#0078d7", 18 | "macro": "#008000", 19 | "type": "#267f99", 20 | "variable": "#001080", 21 | "function": "#795e26" 22 | }, 23 | "boldTokens": [ 24 | "keyword", 25 | "string", 26 | "punctuation" 27 | ], 28 | "italicTokens": [ 29 | "comment" 30 | ], 31 | "underlineTokens": [] 32 | } 33 | -------------------------------------------------------------------------------- /src/extraResources/themes/dark_plus.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./theme.schema.jsonc", 3 | "type": "dark", 4 | "name": "VS Code Dark+", 5 | "colors": { 6 | "background": "#1e1e1e", 7 | "foreground": "#d4d4d4", 8 | "activeLine": "#323232", 9 | "debugStep": "#4b4b18", 10 | "breakpoint": "#1e1e1e", 11 | "preprocessor": "#c586c0", 12 | "string": "#ce8178", 13 | "string.char": "#ce8178", 14 | "keyword": "#569cd6", 15 | "punctuation": "#d4d4d4", 16 | "number": "#b5cea8", 17 | "comment": "#6a9955", 18 | "macro": "#c586c0", 19 | "type": "#4ec9b0", 20 | "variable": "#9cdcfe", 21 | "function": "#dcdcaa" 22 | }, 23 | "boldTokens": [], 24 | "italicTokens": [], 25 | "underlineTokens": [] 26 | } 27 | -------------------------------------------------------------------------------- /src/extraResources/themes/light_plus.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./theme.schema.jsonc", 3 | "type": "light", 4 | "name": "VS Code Light+", 5 | "colors": { 6 | "background": "#ffffff", 7 | "foreground": "#000000", 8 | "activeLine": "#ffffff", 9 | "debugStep": "#add8e6", 10 | "breakpoint": "#f08080", 11 | "preprocessor": "#af00db", 12 | "string": "#a31515", 13 | "string.char": "#a31515", 14 | "keyword": "#0000ff", 15 | "punctuation": "#000000", 16 | "number": "#098658", 17 | "comment": "#008000", 18 | "macro": "#af00db", 19 | "type": "#267f99", 20 | "variable": "#001080", 21 | "function": "#795e26" 22 | }, 23 | "boldTokens": [], 24 | "italicTokens": [], 25 | "underlineTokens": [] 26 | } 27 | -------------------------------------------------------------------------------- /src/extraResources/themes/monokai.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./theme.schema.jsonc", 3 | "name": "Monokai", 4 | "type": "dark", 5 | "colors": { 6 | "background": "#282828", 7 | "foreground": "#f8f8f2", 8 | "activeLine": "#282828", 9 | "debugStep": "#4b4b18", 10 | "breakpoint": "#282828", 11 | "preprocessor": "#529b2f", 12 | "string": "#e6db74", 13 | "string.char": "#e6db74", 14 | "keyword": "#f92672", 15 | "punctuation": "#ffd569", 16 | "number": "#ae81ff", 17 | "comment": "#75715e", 18 | "macro": "#529b2f", 19 | "type": "#66d9ef", 20 | "variable": "#f8f8f2", 21 | "variable.param": "#fd971f", 22 | "function": "#a6e22e" 23 | }, 24 | "boldTokens": [], 25 | "italicTokens": [ "type", "variable.param" ], 26 | "underlineTokens": [] 27 | } 28 | -------------------------------------------------------------------------------- /src/extraResources/themes/theme.schema.jsonc: -------------------------------------------------------------------------------- 1 | // 此文件存放 Dev-C++ 7 的主题配置 Schema 2 | // 勿动 3 | { 4 | "$schema": "http://json-schema.org/draft/2020-12/schema", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "minLength": 1, 10 | "description": "主题名称" 11 | }, 12 | "type": { 13 | "type": "string", 14 | "enum": ["light", "dark"], 15 | "description": "light 或 dark,指明整体为浅色或深色" 16 | }, 17 | "colors": { 18 | "type": "object", 19 | "description": "配置主题颜色", 20 | "properties": { 21 | "background": { 22 | "$ref": "#/$defs/color", 23 | "description": "基本背景色" 24 | }, 25 | "foreground": { 26 | "$ref": "#/$defs/color", 27 | "description": "基本前景色" 28 | }, 29 | "activeLine": { 30 | "$ref": "#/$defs/color", 31 | "description": "当前行背景色" 32 | }, 33 | "breakpoint": { 34 | "$ref": "#/$defs/color", 35 | "description": "断点行背景色" 36 | }, 37 | "debugStep": { 38 | "$ref": "#/$defs/color", 39 | "description": "调试步进背景色" 40 | }, 41 | "preprocessor": { 42 | "$ref": "#/$defs/color", 43 | "description": "预处理指令前景色" 44 | }, 45 | "string": { 46 | "$ref": "#/$defs/color", 47 | "description": "字符串字面量前景色" 48 | }, 49 | "string.char": { 50 | "$ref": "#/$defs/color", 51 | "description": "字符字面量前景色" 52 | }, 53 | "keyword": { 54 | "$ref": "#/$defs/color", 55 | "description": "关键字前景色" 56 | }, 57 | "punctuation": { 58 | "$ref": "#/$defs/color", 59 | "description": "标点符号前景色" 60 | }, 61 | "number": { 62 | "$ref": "#/$defs/color", 63 | "description": "数值前景色" 64 | }, 65 | "comment": { 66 | "$ref": "#/$defs/color", 67 | "description": "注释前景色" 68 | }, 69 | "macro": { 70 | "$ref": "#/$defs/color", 71 | "description": "宏名前景色" 72 | }, 73 | "type": { 74 | "$ref": "#/$defs/color", 75 | "description": "类型名前景色" 76 | }, 77 | "variable": { 78 | "$ref": "#/$defs/color", 79 | "description": "变量名前景色" 80 | }, 81 | "function": { 82 | "$ref": "#/$defs/color", 83 | "description": "函数名前景色" 84 | } 85 | } 86 | }, 87 | "boldTokens": { 88 | "$ref": "#/$defs/tokens", 89 | "description": "指明哪些标记为粗体" 90 | }, 91 | "italicTokens": { 92 | "$ref": "#/$defs/tokens", 93 | "description": "指明哪些标记为斜体" 94 | }, 95 | "underlineTokens": { 96 | "$ref": "#/$defs/tokens", 97 | "description": "指明哪些标记为下划线" 98 | } 99 | }, 100 | "required": [ 101 | "name", "type" 102 | ], 103 | "$defs": { 104 | "color": { 105 | "type": "string", 106 | "format": "color-hex", 107 | "pattern": "^#[0-9a-f]{6}$" 108 | }, 109 | "tokens": { 110 | "type": "array", 111 | "uniqueItems": true, 112 | "items": { 113 | "type": "string", 114 | "pattern": "^(preprocessor|string|keyword|punctuation|number|comment|macro|type|variable|function)(\\.\\w+)?" 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | Dev-C++ 7 25 | 26 | 27 | 28 | 29 | 30 | 31 | 加载中... 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-electron'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: [ 'html', 'lcovonly' ], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | browsers: ['AngularElectron'], 28 | customLaunchers: { 29 | AngularElectron: { 30 | base: 'Electron', 31 | flags: [ 32 | '--remote-debugging-port=9222' 33 | ], 34 | browserWindowOptions: { 35 | webPreferences: { 36 | nodeIntegration: true, 37 | nodeIntegrationInSubFrames: true, 38 | allowRunningInsecureContent: true, 39 | enableRemoteModule: true 40 | } 41 | } 42 | } 43 | } 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 Guyutongxue 2 | // 3 | // This file is part of Dev-C++ 7. 4 | // 5 | // Dev-C++ 7 is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Dev-C++ 7 is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Dev-C++ 7. If not, see . 17 | 18 | import { enableProdMode } from '@angular/core'; 19 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 20 | 21 | import { AppModule } from './app/app.module'; 22 | import { AppConfig } from './environments/environment'; 23 | 24 | if (AppConfig.production) { 25 | enableProdMode(); 26 | } 27 | 28 | platformBrowserDynamic() 29 | .bootstrapModule(AppModule, { 30 | preserveWhitespaces: false 31 | }) 32 | .catch(err => console.error(err)); 33 | -------------------------------------------------------------------------------- /src/polyfills-test.ts: -------------------------------------------------------------------------------- 1 | import 'core-js/es/reflect'; 2 | import 'zone.js/dist/zone'; 3 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | 61 | /*************************************************************************************************** 62 | * APPLICATION IMPORTS 63 | */ 64 | 65 | (window as any).global = window; 66 | (window as any).global.Buffer = (window as any).global.Buffer || require('buffer').Buffer; 67 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | @import './app/codicon/codicon.css'; 2 | 3 | :root { 4 | --monospace-font: Consolas, 'Courier New', Courier, monospace; 5 | } 6 | 7 | html, 8 | body { 9 | margin : 0; 10 | padding: 0; 11 | 12 | height : 100%; 13 | overflow-y : hidden; 14 | font-family: Arial, Helvetica, sans-serif; 15 | 16 | user-select: none; 17 | 18 | 19 | .codicon { 20 | transform: translateY(15%); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "es2015", 6 | "baseUrl": "", 7 | "experimentalDecorators": true, 8 | "downlevelIteration": true, 9 | "types": [] 10 | }, 11 | "include": [ 12 | "main.ts", 13 | "polyfill.ts" 14 | ], 15 | "exclude": [ 16 | "**/*.spec.ts" 17 | ], 18 | "angularCompilerOptions": { 19 | "fullTemplateTypeCheck": true, 20 | "strictInjectionParameters": true, 21 | "preserveWhitespaces": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "module": "commonjs", 6 | "experimentalDecorators": true, 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "test.ts", 14 | "polyfills-test.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ], 20 | "exclude": [ 21 | "dist", 22 | "release", 23 | "node_modules" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare const nodeModule: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | interface Window { 7 | process: any; 8 | require: any; 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "module": "es2020", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "resolveJsonModule": true, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "downlevelIteration": true, 13 | "target": "es5", 14 | "typeRoots": [ 15 | "node_modules/@types" 16 | ], 17 | "skipLibCheck": true, 18 | "lib": [ 19 | "es2019", 20 | "es2017", 21 | "es2016", 22 | "es2015", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "strictTemplates": true 28 | }, 29 | "files": [ 30 | "src/main.ts", 31 | "src/polyfills.ts" 32 | ], 33 | "include": [ 34 | "src/**/*.d.ts" 35 | ], 36 | "exclude": [ 37 | "node_modules" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /tsconfig.serve.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "declaration": false, 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "target": "es2015", 9 | "baseUrl": ".", 10 | "types": [ 11 | "node" 12 | ], 13 | "lib": [ 14 | "es2019", 15 | "es2017", 16 | "es2016", 17 | "es2015", 18 | "dom" 19 | ] 20 | } 21 | } 22 | --------------------------------------------------------------------------------