mirror of
https://github.com/catppuccin/catppuccin
synced 2024-11-21 19:13:05 +00:00
docs: restructure & improve contrib docs (#1876)
* docs: restructure & improve contrib docs * chore: rework samples code * docs: fix capitalization & brand names * docs: PR comments & try to standardise palette vs flavor * docs: add sample-programs * docs: update submission guidelines (refs: #1821) * refactor: tidy up docs Co-authored-by: winston <hey@winston.sh>
This commit is contained in:
parent
e4ebfa468c
commit
b9bbd77c7f
40 changed files with 1189 additions and 4831 deletions
|
@ -2,25 +2,22 @@
|
||||||
|
|
||||||
🎉 First off, thanks for taking the time to contribute! 🎉
|
🎉 First off, thanks for taking the time to contribute! 🎉
|
||||||
|
|
||||||
> **Note**: if you are here because you want to submit a port/learn how to port Catppuccin to a program please refer to the [documentation](https://github.com/catppuccin/catppuccin/blob/main/docs/contributing.md)
|
|
||||||
|
|
||||||
## Guidelines
|
## Guidelines
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to this project. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
The following is a set of guidelines for contributing to this repository. Use your best judgment, and feel free to propose
|
||||||
|
changes to this document in a pull request.
|
||||||
|
|
||||||
- PRs should go to the `dev` branch. Reasons:
|
- Use the `.editorconfig` file (located at the root of this project) on your editor to "maintain consistent coding
|
||||||
- If there is already stuff under development, then it's likely that a conflict may occur.
|
styles." For instructions on how to use this file refer to [EditorConfig's website](https://editorconfig.org/).
|
||||||
- Releases/Deployment.
|
|
||||||
- Documentation tends not to be updated by PRs.
|
|
||||||
- Testing.
|
|
||||||
- Use the `.editorconfig` file (located at the root of this project) on your editor so as to "maintain consistent coding styles". For instructions on how to use this file refer to [EditorConfig's website](https://editorconfig.org/).
|
|
||||||
|
|
||||||
## Recommendations
|
## Recommendations
|
||||||
|
|
||||||
- Create a topic branch on your fork for your specific PR.
|
- Create a [topic branch](git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) on your fork for your
|
||||||
- Consider using [conventionalcommits.org's](https://www.conventionalcommits.org/en/v1.0.0/) rules for creating explicit and meaningful commit messages.
|
specific PR.
|
||||||
- If it's your first time contributing to a project then read [About pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests) on Github's docs.
|
- Consider using [conventionalcommits.org](https://www.conventionalcommits.org/en/v1.0.0/)'s rules for creating explicit
|
||||||
|
and meaningful commit messages.
|
||||||
## License
|
- If it's your first time contributing to a project then you should look to the
|
||||||
|
popular [first-contributions](https://github.com/firstcontributions/first-contributions) repository on GitHub. This
|
||||||
Any contribution will be published under the same licensing terms as the project itself.
|
will give you hands-on experience with the features of GitHub required to make a contribution. As always, feel free to
|
||||||
|
join our [Discord](https://discord.com/invite/r6Mdz5dpFc) to ask any questions and clarify your understanding, we are
|
||||||
|
more than happy to help!
|
||||||
|
|
66
README.md
66
README.md
|
@ -6,7 +6,7 @@
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<h6 align="center">
|
<h6 align="center">
|
||||||
<a href="https://github.com/catppuccin/catppuccin#-palettes">Palettes</a>
|
<a href="https://github.com/catppuccin/catppuccin#-palette">Palette</a>
|
||||||
·
|
·
|
||||||
<a href="https://github.com/catppuccin/catppuccin#-ports-and-more">Ports</a>
|
<a href="https://github.com/catppuccin/catppuccin#-ports-and-more">Ports</a>
|
||||||
·
|
·
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Catppuccin is a community-driven pastel theme that aims to be the middle ground between low and high contrast themes. It consists of 4 soothing warm palettes with 26 eye-candy colors each, perfect for coding, designing, and much more! In addition, this repository tracks the development of the actual color palette, <a href="https://github.com/catppuccin/catppuccin/tree/main/docs"><b>the project's documentation</b></a>, organization-wide assets, resources and code samples for maintainers/developers.
|
Catppuccin is a community-driven pastel theme that aims to be the middle ground between low and high contrast themes. It consists of 4 soothing warm flavors with 26 eye-candy colors each, perfect for coding, designing, and much more! In addition, this repository tracks the development of the actual color palette, <a href="https://github.com/catppuccin/catppuccin/tree/main/docs"><b>the project's documentation</b></a>, organization-wide assets, resources and code samples for maintainers/developers.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
@ -58,16 +58,18 @@ Join our community!
|
||||||
|
|
||||||
### 🧠 Design Philosophy
|
### 🧠 Design Philosophy
|
||||||
|
|
||||||
- **Colorful is better than colorless**: the colorfulness of something contributes to the distinction amongst the parts of that _something_, making it marginally easier to understand how things are structured.
|
- **Colorful is better than colorless**: the colorfulness of something contributes to the distinction amongst the parts
|
||||||
- **There should be balance**: not too dull, not too bright. Suitability under various light conditions is a must.
|
of that _something_, making it marginally easier to understand how things are structured.
|
||||||
- **Harmony is superior to dissonance**: vivacious colors must complement each other.
|
- **There should be balance**: not too dull, not too bright. Suitability under various light conditions is a must.
|
||||||
|
- **Harmony is superior to dissonance**: vivacious colors must complement each other.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 🎨 Palettes
|
### 🎨 Palette
|
||||||
|
|
||||||
**Catppuccin** consists of 4 beautiful pastel color palettes. All the details can be found below.<br>
|
**Catppuccin** consists of 4 beautiful pastel color palettes, named **flavors**. All the details can be found below.<br>
|
||||||
To make the best use of them, please refer to the [style guide](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md).
|
To make the best use of them, please refer to
|
||||||
|
the [style guide](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md).
|
||||||
<br><img src="assets/misc/transparent.png" height="10" width="0" />
|
<br><img src="assets/misc/transparent.png" height="10" width="0" />
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -856,7 +858,7 @@ To make the best use of them, please refer to the [style guide](https://github.c
|
||||||
|
|
||||||
Catppuccin is available for various apps and in different formats. Here is a list of them:
|
Catppuccin is available for various apps and in different formats. Here is a list of them:
|
||||||
|
|
||||||
<details open><summary>👾 Code Editors</summary>
|
<details open><summary>👾 Code Editors</summary>
|
||||||
|
|
||||||
- [Binary Ninja](https://github.com/catppuccin/binary-ninja)
|
- [Binary Ninja](https://github.com/catppuccin/binary-ninja)
|
||||||
- [Cutter](https://github.com/catppuccin/cutter)
|
- [Cutter](https://github.com/catppuccin/cutter)
|
||||||
|
@ -880,6 +882,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Visual Studio](https://github.com/catppuccin/visual-studio)
|
- [Visual Studio](https://github.com/catppuccin/visual-studio)
|
||||||
- [Xcode](https://github.com/catppuccin/xcode)
|
- [Xcode](https://github.com/catppuccin/xcode)
|
||||||
- [Xed](https://github.com/catppuccin/xed)
|
- [Xed](https://github.com/catppuccin/xed)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>💭 Development</summary>
|
<details open><summary>💭 Development</summary>
|
||||||
|
@ -891,7 +894,8 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Toolbox](https://github.com/catppuccin/toolbox)
|
- [Toolbox](https://github.com/catppuccin/toolbox)
|
||||||
- [mdBook](https://github.com/catppuccin/mdBook)
|
- [mdBook](https://github.com/catppuccin/mdBook)
|
||||||
- [egui](https://github.com/catppuccin/egui)
|
- [egui](https://github.com/catppuccin/egui)
|
||||||
</details>
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details open><summary>🔧 System</summary>
|
<details open><summary>🔧 System</summary>
|
||||||
|
|
||||||
|
@ -932,12 +936,14 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Waybar](https://github.com/catppuccin/waybar)
|
- [Waybar](https://github.com/catppuccin/waybar)
|
||||||
- [Xresources](https://github.com/catppuccin/xresources)
|
- [Xresources](https://github.com/catppuccin/xresources)
|
||||||
- [Rboard](https://github.com/catppuccin/rboard)
|
- [Rboard](https://github.com/catppuccin/rboard)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🐚 Shells</summary>
|
<details open><summary>🐚 Shells</summary>
|
||||||
|
|
||||||
- [Fish](https://github.com/catppuccin/fish)
|
- [Fish](https://github.com/catppuccin/fish)
|
||||||
- [zsh-syntax-highlighting](https://github.com/catppuccin/zsh-syntax-highlighting)
|
- [zsh-syntax-highlighting](https://github.com/catppuccin/zsh-syntax-highlighting)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🤓 Productivity</summary>
|
<details open><summary>🤓 Productivity</summary>
|
||||||
|
@ -960,6 +966,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Vercel](https://github.com/catppuccin/vercel)
|
- [Vercel](https://github.com/catppuccin/vercel)
|
||||||
- [Wikiwand](https://github.com/catppuccin/wikiwand)
|
- [Wikiwand](https://github.com/catppuccin/wikiwand)
|
||||||
- [Zathura](https://github.com/catppuccin/zathura)
|
- [Zathura](https://github.com/catppuccin/zathura)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🌈 Leisure</summary>
|
<details open><summary>🌈 Leisure</summary>
|
||||||
|
@ -977,9 +984,10 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Spicetify](https://github.com/catppuccin/spicetify)
|
- [Spicetify](https://github.com/catppuccin/spicetify)
|
||||||
- [Spotify Player](https://github.com/catppuccin/spotify-player)
|
- [Spotify Player](https://github.com/catppuccin/spotify-player)
|
||||||
- [Spotify-TUI](https://github.com/catppuccin/spotify-tui)
|
- [Spotify-TUI](https://github.com/catppuccin/spotify-tui)
|
||||||
- [Stable Diffusion Web Ui](https://github.com/catppuccin/Stable-Diffusion-Web-UI)
|
- [Stable Diffusion Web UI](https://github.com/catppuccin/stable-diffusion-web-ui)
|
||||||
- [Steam](https://github.com/catppuccin/steam)
|
- [Steam](https://github.com/catppuccin/steam)
|
||||||
- [Youtube Music](https://github.com/catppuccin/youtubemusic)
|
- [YouTube Music](https://github.com/catppuccin/youtubemusic)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🖥️ Browsers</summary>
|
<details open><summary>🖥️ Browsers</summary>
|
||||||
|
@ -988,6 +996,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Firefox](https://github.com/catppuccin/firefox)
|
- [Firefox](https://github.com/catppuccin/firefox)
|
||||||
- [Vivaldi](https://github.com/catppuccin/vivaldi)
|
- [Vivaldi](https://github.com/catppuccin/vivaldi)
|
||||||
- [qutebrowser](https://github.com/catppuccin/qutebrowser)
|
- [qutebrowser](https://github.com/catppuccin/qutebrowser)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🔎 Search engines</summary>
|
<details open><summary>🔎 Search engines</summary>
|
||||||
|
@ -995,8 +1004,9 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Brave Search](https://github.com/catppuccin/brave-search)
|
- [Brave Search](https://github.com/catppuccin/brave-search)
|
||||||
- [DuckDuckGo](https://github.com/catppuccin/duckduckgo)
|
- [DuckDuckGo](https://github.com/catppuccin/duckduckgo)
|
||||||
- [Whoogle](https://github.com/catppuccin/whoogle)
|
- [Whoogle](https://github.com/catppuccin/whoogle)
|
||||||
- [SearxNG](https://github.com/catppuccin/searxng)
|
- [SearXNG](https://github.com/catppuccin/searxng)
|
||||||
- [Startpage](https://github.com/catppuccin/startpage)
|
- [Startpage](https://github.com/catppuccin/startpage)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🧩 Extensions</summary>
|
<details open><summary>🧩 Extensions</summary>
|
||||||
|
@ -1006,6 +1016,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Sidebery](https://github.com/catppuccin/sidebery)
|
- [Sidebery](https://github.com/catppuccin/sidebery)
|
||||||
- [Vimium](https://github.com/catppuccin/vimium)
|
- [Vimium](https://github.com/catppuccin/vimium)
|
||||||
- [Nighttab](https://github.com/catppuccin/nighttab)
|
- [Nighttab](https://github.com/catppuccin/nighttab)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>💬 Messaging</summary>
|
<details open><summary>💬 Messaging</summary>
|
||||||
|
@ -1020,6 +1031,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Revolt](https://github.com/catppuccin/revolt)
|
- [Revolt](https://github.com/catppuccin/revolt)
|
||||||
- [Slack](https://github.com/catppuccin/slack)
|
- [Slack](https://github.com/catppuccin/slack)
|
||||||
- [Telegram](https://github.com/catppuccin/telegram)
|
- [Telegram](https://github.com/catppuccin/telegram)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>📝 Note-taking</summary>
|
<details open><summary>📝 Note-taking</summary>
|
||||||
|
@ -1028,6 +1040,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Joplin](https://github.com/catppuccin/joplin)
|
- [Joplin](https://github.com/catppuccin/joplin)
|
||||||
- [Obsidian](https://github.com/catppuccin/obsidian)
|
- [Obsidian](https://github.com/catppuccin/obsidian)
|
||||||
- [Remnote](https://github.com/catppuccin/remnote)
|
- [Remnote](https://github.com/catppuccin/remnote)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>🌱 Terminals</summary>
|
<details open><summary>🌱 Terminals</summary>
|
||||||
|
@ -1059,13 +1072,14 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Xfce4 Terminal](https://github.com/catppuccin/xfce4-terminal)
|
- [Xfce4 Terminal](https://github.com/catppuccin/xfce4-terminal)
|
||||||
- [Zellij](https://github.com/catppuccin/zellij)
|
- [Zellij](https://github.com/catppuccin/zellij)
|
||||||
- [Zutty](https://github.com/catppuccin/zutty)
|
- [Zutty](https://github.com/catppuccin/zutty)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details open><summary>✨ Social</summary>
|
<details open><summary>✨ Social</summary>
|
||||||
|
|
||||||
- [AniList](https://github.com/catppuccin/anilist)
|
- [AniList](https://github.com/catppuccin/anilist)
|
||||||
- [Elk](https://github.com/catppuccin/elk)
|
- [Elk](https://github.com/catppuccin/elk)
|
||||||
- [Github Readme Stats](https://github.com/catppuccin/github-readme-stats)
|
- [GitHub Readme Stats](https://github.com/catppuccin/github-readme-stats)
|
||||||
- [GitHub Readme Tech Stack](https://github.com/catppuccin/github-readme-tech-stack)
|
- [GitHub Readme Tech Stack](https://github.com/catppuccin/github-readme-tech-stack)
|
||||||
- [Hacker News](https://github.com/catppuccin/hacker-news)
|
- [Hacker News](https://github.com/catppuccin/hacker-news)
|
||||||
- [Infinity for Reddit](https://github.com/catppuccin/infinity)
|
- [Infinity for Reddit](https://github.com/catppuccin/infinity)
|
||||||
|
@ -1077,6 +1091,7 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
- [Reddit](https://github.com/catppuccin/reddit)
|
- [Reddit](https://github.com/catppuccin/reddit)
|
||||||
- [Thunderbird](https://github.com/catppuccin/thunderbird)
|
- [Thunderbird](https://github.com/catppuccin/thunderbird)
|
||||||
- [YouTube](https://github.com/catppuccin/youtube)
|
- [YouTube](https://github.com/catppuccin/youtube)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1086,22 +1101,37 @@ Catppuccin is available for various apps and in different formats. Here is a lis
|
||||||
> **Note** <br>
|
> **Note** <br>
|
||||||
> Catppuccin staff reserve the right to remove and reject showcase additions if we determine the addition to be in
|
> Catppuccin staff reserve the right to remove and reject showcase additions if we determine the addition to be in
|
||||||
> violation of our [CODE OF CONDUCT](https://github.com/catppuccin/.github/blob/main/CODE_OF_CONDUCT.md). Extremely
|
> violation of our [CODE OF CONDUCT](https://github.com/catppuccin/.github/blob/main/CODE_OF_CONDUCT.md). Extremely
|
||||||
> personal configurations will **not** be approved and added.
|
> personal configurations and websites will **not** be added.
|
||||||
|
|
||||||
If you're making an application or tool using our palette, please let us know by adding it below!
|
If you're making an application or tool using our palette, please let us know by adding it below!
|
||||||
|
|
||||||
- 🌟 [flotes.app](https://flotes.app/) - A free note-taking app enhanced with flashcard features
|
- 🌟 [flotes.app](https://flotes.app/) - A free note-taking app enhanced with flashcard features
|
||||||
- 🌟 [AnuPpuccin](https://github.com/AnubisNekhet/AnuPpuccin) - Highly customisable theme for [Obsidian](https://obsidian.md/)
|
- 🌟 [AnuPpuccin](https://github.com/AnubisNekhet/AnuPpuccin) - Highly customisable theme
|
||||||
- 🌟 [name] - [short description]
|
for [Obsidian](https://obsidian.md/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 👐 Contribute
|
### 👐 Contributing
|
||||||
|
|
||||||
|
> **Note** <br>
|
||||||
|
> if you would like to submit a port or learn how to port Catppuccin to a program, please refer to
|
||||||
|
> the [port-creation.md](https://github.com/catppuccin/catppuccin/blob/main/docs/port-creation.md).
|
||||||
|
|
||||||
See [CONTRIBUTING.md](https://github.com/catppuccin/catppuccin/blob/main/CONTRIBUTING.md).
|
See [CONTRIBUTING.md](https://github.com/catppuccin/catppuccin/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 🔧 Usage
|
||||||
|
|
||||||
|
If you're interested in using our palette for your own project, make sure to check
|
||||||
|
out [catppuccin/palette](https://github.com/catppuccin/palette) where you can find integrations with popular frameworks
|
||||||
|
and tools.
|
||||||
|
|
||||||
|
If you already have a project using our palette, don't forget to add it to
|
||||||
|
our [showcase](#-showcase) section above!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 📜 License
|
### 📜 License
|
||||||
|
|
||||||
Catppuccin is released under the MIT license, which grants the following permissions:
|
Catppuccin is released under the MIT license, which grants the following permissions:
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Catppuccin is a community-driven pastel theme that aims to be the middle ground between low and high contrast themes. It consists of 4 soothing warms palette with 26 eye-candy colors each, perfect for coding, designing, and much more! In addition, this repository tracks the development of the actual color palette, organization-wide assets, resources and code samples for maintainers/developers.
|
Catppuccin is a community-driven pastel theme that aims to be the middle ground between low and high contrast themes. It consists of 4 soothing warm flavors with 26 eye-candy colors each, perfect for coding, designing, and much more! In addition, this repository tracks the development of the actual color palette, organization-wide assets, resources and code samples for maintainers/developers.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,10 +20,9 @@ Catppuccin is a community-driven pastel theme that aims to be the middle ground
|
||||||
|
|
||||||
### 🪴 Index
|
### 🪴 Index
|
||||||
|
|
||||||
+ [Specifications](https://github.com/catppuccin/catppuccin/blob/main/docs/specs.md): properties of the palettes
|
+ [Specifications](https://github.com/catppuccin/catppuccin/blob/main/docs/specs.md): properties of the palette
|
||||||
+ [Integrating](https://github.com/catppuccin/catppuccin/blob/main/docs/integration.md): how to implement Catppuccin in your own projects
|
+ [Style Guide](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md): a guide on how to properly use the palette
|
||||||
+ [Style Guide](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md): a guide on how to properly use the palettes
|
+ [Port Creation](https://github.com/catppuccin/catppuccin/blob/main/docs/port-creation.md): creating Catppuccin ports
|
||||||
+ [Contributing](https://github.com/catppuccin/catppuccin/blob/main/docs/contributing.md): creating Catppuccin ports
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
<p align="center">
|
|
||||||
<h2 align="center">🤝 Contributing</h2>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
Creating Catppuccin ports
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### What's a port?
|
|
||||||
|
|
||||||
A port is basically an adaptation of Catppuccin's palettes for an app to use. Think of it as a colorscheme for a program that styles every UI component it consists of!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Creation
|
|
||||||
|
|
||||||
You can create ports using [this](https://github.com/catppuccin/template) public template as a blueprint. However, you must **not** create it the traditional way (by clicking **Use this template**), because this leaves a _small_ tag under the repos' name that says `generated from <template>`. To avoid this, follow the instructions below:
|
|
||||||
|
|
||||||
1. Create the repo and leave it empty:
|
|
||||||
```
|
|
||||||
mkdir name_of_your_port
|
|
||||||
cd name_of_your_port
|
|
||||||
git init
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Add this template as a remote:
|
|
||||||
```
|
|
||||||
git remote add template https://github.com/catppuccin/template.git
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Pull from it:
|
|
||||||
```
|
|
||||||
git pull template main
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Delete the remote:
|
|
||||||
```
|
|
||||||
git remote remove template
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Make the template its own repository by running
|
|
||||||
```
|
|
||||||
git reset $(git commit-tree HEAD^{tree} -m "feat: initial commit")
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Set up the rest of your port, and push it to your user repository!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Styling!
|
|
||||||
|
|
||||||
Although you just created the repo successfully, it's important to style it properly to ensure consistency:
|
|
||||||
|
|
||||||
- The name of the repo must be the simplest version of the app's name (e.g `nvim` instead of `NeoVim`). You may use hyphens if needed (e.g. `windows-files`).
|
|
||||||
- Put the images under `assets/`. If there are a bunch of them consider [creating an empty branch](https://gist.github.com/joncardasis/e6494afd538a400722545163eb2e1fa5) (e.g. `assets`) and storing them there.
|
|
||||||
- Format the repo's description as "`<emoji>` Soothing pastel theme for `<app name>`".
|
|
||||||
- `<emoji>` should be an emoji that you feel represents the app best.
|
|
||||||
- `<app name>` is the name of the app, capitalized properly.
|
|
||||||
- Add `catppuccin` to the topics.
|
|
||||||
- Ensure uppercase meta files (e.g. `README.md`)
|
|
||||||
- Don't add health files (e.g. `CODE_OF_CONDUCTS.md`, `SUPPORT.md`), those are organization-wide files stored [here](https://github.com/catppuccin/.github).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Tools
|
|
||||||
|
|
||||||
Since Catppuccin is available in 4 palettes it's understandable that it may not be quite as easy to make 4 versions of a port. So to help with that, we have built a bunch of tools to make life easier when creating Catppuccin ports. You'll find them all (with instructions) under our [catppuccin/toolbox](https://github.com/catppuccin/toolbox) repo. Particularly, for the initial problem stated, you'd want to take a look at the [Puccinier](https://github.com/catppuccin/toolbox#%EF%B8%8F-puccinier) tool.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Submission
|
|
||||||
|
|
||||||
Raise a discussion under main repository [here!](https://github.com/catppuccin/catppuccin/discussions/new?category=port-requests)
|
|
||||||
The title should be the **simplest** name of the application/tool/website in **lower-kebab-case** that you are wanting ported over.
|
|
||||||
E.g. **NeoVim** -> **neovim**
|
|
||||||
|
|
||||||
If you have already created a repository containing the work, make sure to include it within the description for others to see! Feel free to join our [Discord](https://discord.com/invite/r6Mdz5dpFc) and share it there too!
|
|
||||||
|
|
||||||
The discussion will be transferred to an issue once the [staff team](https://github.com/orgs/catppuccin/teams/staff/members)
|
|
||||||
have deemed the port ready to be reviewed and merged!
|
|
|
@ -1,30 +0,0 @@
|
||||||
<p align="center">
|
|
||||||
<h2 align="center">📦 Integration</h2>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
How to implement Catppuccin in your own projects
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### How to
|
|
||||||
|
|
||||||
Catppuccin comes in many formats to cover a wide range of project types and tech stacks. Its palettes have especially been designed for UI elements and code syntax highlighting often found in projects build with web technologies like websites; hence why we have a dedicated repository for storing the various formats and presentation of the palettes: [catppuccin/palette](https://github.com/catppuccin/palette).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Web Development
|
|
||||||
|
|
||||||
Since Catppuccin is heavily used in web technology based projects, it's main installation method is therefore npm, the Node.js package manager.
|
|
||||||
Install and add it as production dependency by running `npm` from the command line:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install --save @catppuccin/palette
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Graphical Design
|
|
||||||
|
|
||||||
Color swatches are simply a palette showing a variety of shades of the same color. Here, Catppuccin has various "swatches" in different formats to be used in software ranging from Adobe Products to graphical design apps such as Figma and InkScape. You can find them under [catppuccin/palette](https://github.com/catppuccin/palette).
|
|
96
docs/port-creation.md
Normal file
96
docs/port-creation.md
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<p align="center">
|
||||||
|
<h2 align="center">🧱 Port Creation</h2>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
Guidelines for submitting and creating ports
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### What's a port?
|
||||||
|
|
||||||
|
A port is an adaptation of Catppuccin's palette for an app to use. Think of it as a colorscheme for a program
|
||||||
|
that styles every UI component it consists of!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Submission
|
||||||
|
|
||||||
|
Raise a discussion under main
|
||||||
|
repository [here!](https://github.com/catppuccin/catppuccin/discussions/new?category=port-requests) The title should be
|
||||||
|
the **simplest** name of the application/tool/website/etc that you are wanting ported over.
|
||||||
|
|
||||||
|
If you have already created a repository containing the work, make sure to include it within the description for others
|
||||||
|
to see! Feel free to join our [Discord](https://discord.com/invite/r6Mdz5dpFc) and share it there too!
|
||||||
|
|
||||||
|
The discussion will be transferred to an issue by
|
||||||
|
the [staff team](https://github.com/orgs/catppuccin/teams/staff/members) once we have deemed the port ready to be
|
||||||
|
reviewed and merged!
|
||||||
|
|
||||||
|
All ports should conform to our [CODE OF CONDUCT](https://github.com/catppuccin/.github/blob/main/CODE_OF_CONDUCT.md)
|
||||||
|
and we, the staff team, reserve the right to choose what ports will be included under the organisation. As a
|
||||||
|
community-driven project, we want to keep a neutral environment for all users. Therefore, **we do not accept
|
||||||
|
contributions that have a religious or political context.** However, we have no issue with our palette being used in
|
||||||
|
these contexts.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Creation
|
||||||
|
|
||||||
|
You can create ports using [this](https://github.com/catppuccin/template) public template as a blueprint.
|
||||||
|
|
||||||
|
1. Clone template repository
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/catppuccin/template.git <name_of_your_port>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Navigate into the cloned repository
|
||||||
|
|
||||||
|
```
|
||||||
|
cd <name_of_your_port>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Delete the existing remote
|
||||||
|
|
||||||
|
```
|
||||||
|
git remote remove origin
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Set up the rest of your port, and push it to your user repository!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Licensing
|
||||||
|
|
||||||
|
Any contribution will be published under the same licensing terms as the project itself. However, there
|
||||||
|
are [exceptions to this rule](https://github.com/search?q=org%3Acatppuccin+-license%3Amit). Please get in touch with us
|
||||||
|
if that is the case with your work!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Styling!
|
||||||
|
|
||||||
|
After creating the repo successfully, it's important to style it properly to ensure consistency:
|
||||||
|
|
||||||
|
- The name of the repo must be the simplest version of the app's name (e.g. `nvim` instead of `NeoVim`). You may use
|
||||||
|
hyphens if needed (e.g. `windows-files`).
|
||||||
|
- Put the images under `assets/`.
|
||||||
|
- Format the repo's description as "`<emoji>` Soothing pastel theme for `<app name>`".
|
||||||
|
- `<emoji>` should be an emoji that you feel represents the app best.
|
||||||
|
- `<app name>` is the name of the app, capitalized properly.
|
||||||
|
- Add `catppuccin`, and `theme` to the topics.
|
||||||
|
- Ensure uppercase meta files (e.g. `README.md`)
|
||||||
|
- Don't add health files (e.g. `CODE_OF_CONDUCT.md`, `SUPPORT.md`), those are organization-wide files
|
||||||
|
stored [here](https://github.com/catppuccin/.github).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
|
Since Catppuccin is available in 4 flavors it's understandable that it may be difficult to make 4 versions of a
|
||||||
|
port. So to help with that, we have built a bunch of tools to make life easier when creating Catppuccin ports. You'll
|
||||||
|
find them all (with instructions) under our [catppuccin/toolbox](https://github.com/catppuccin/toolbox) repo.
|
||||||
|
An essential tool for creating ports is [catwalk](https://github.com/catppuccin/toolbox#catwalk), this is used to create
|
||||||
|
a layered screenshot of your port which combines all four flavors into one.
|
|
@ -3,20 +3,25 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Properties of the palettes
|
Properties of the palette
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Palettes
|
### Palette
|
||||||
|
|
||||||
Catppuccin consists of four named color palettes: Latte, Frappe, Macchiato, and Mocha. Each palette has its use-cases and a reason to exist! (so to speak). Every palette has labels (AKA colors) that provide different syntactic meanings and color effects for dark & bright ambiance designs. Each one of them was created aiming for a clear, uncluttered, and elegant design following a minimal and flat style pattern.
|
Catppuccin consists of four named flavors: Latte, Frappé, Macchiato, and Mocha. Each flavor has its use-cases
|
||||||
|
and a reason to exist! (so to speak). Every flavor has labels (AKA colors) that provide different syntactic meanings
|
||||||
|
and color effects for dark & bright ambiance designs. Each one of them was created aiming for a clear, uncluttered, and
|
||||||
|
elegant design following a minimal and flat style pattern.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Subpalettes
|
### Sub-palettes
|
||||||
|
|
||||||
Every palette consists of two subpalettes: one monochromatic and one analogous. The Monochromatic subpalette consists of different shades of a purple-gray and a very pale lavender and is often used for UI components. Whereas the Analogous palette has every color in the rainbow and is often used for syntactic elements.
|
Every flavor consists of two sub-palettes: one monochromatic and one analogous. The monochromatic sub-palette consists
|
||||||
|
of different shades of a purple-gray and a very pale lavender and is often used for UI components. Whereas the analogous
|
||||||
|
palette has every color in the rainbow and is often used for syntactic elements.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
# Coding Samples
|
# Coding Samples
|
||||||
|
|
||||||
Small samples from various programming/markup/config languages to check how Catppuccin looks on them.
|
Small samples from various programming/markup/config languages to check how Catppuccin looks on them.
|
||||||
|
|
||||||
|
## Other Sources
|
||||||
|
|
||||||
|
When you need samples from a wider set of languages, please look towards:
|
||||||
|
|
||||||
|
- [kate-editor.org/syntax](kate-editor.org/syntax)
|
||||||
|
- [TheRenegadeCoder/sample-programs](https://github.com/TheRenegadeCoder/sample-programs)
|
||||||
|
|
||||||
|
# Acknowledgement
|
||||||
|
|
||||||
|
These samples were taken from [JetBrains Intellij IDEA](https://www.jetbrains.com/idea/)'s syntax highlighting tools.
|
||||||
|
|
653
samples/bash.sh
653
samples/bash.sh
|
@ -1,640 +1,23 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#sve = System Variable Exemplifier
|
#Sample comment
|
||||||
#This script executes whatever file you tell regardless of in which directory it's currently in.
|
let "a=16 << 2";
|
||||||
|
b="Sample text";
|
||||||
|
|
||||||
# TO-DO
|
function foo() {
|
||||||
# + on recurse_dirs2() -- make it so that any file with 'Main' on its name will get compiled at the end, cuz else it's going to cause error
|
if [ $string1 == $string2 ]; then
|
||||||
# + make it so that $temp_cp can be edited using this scritpt
|
for url in `cat example.txt`; do
|
||||||
# +,i remove one of the entries
|
curl $url > result.html
|
||||||
# +,i add an entry
|
done
|
||||||
# + fix bugs
|
fi
|
||||||
# +,i if entry if removed and entry is last of entries then the entry before that one will have an collon, which is something that will cause an error to the parser
|
}
|
||||||
# this is a simple test becas (done)
|
|
||||||
# + from $0 -ef a -> if "entry" is on $temp_cp then do not add entry, print message, else, add it (done)
|
|
||||||
# + edit --help str (done)
|
|
||||||
# + avoid compiling already compiled files
|
|
||||||
# +,i mkdir /tmp/2sve_tmp -- dir where "already compiled things" file is stored
|
|
||||||
# +,j touch /tmp/2sve_tmp/compiled_file_list.json
|
|
||||||
# +,i after first compile add all files compiled to list
|
|
||||||
# +,i if `stat --format "%Y" <file_name>` == `stat --format "%Y" hello.txt` of file with same name in compiled_file_list.json, then don't compile, else, do so
|
|
||||||
|
|
||||||
OUT_DICT=out
|
rm -f $(find / -name core) &> /dev/null
|
||||||
temp_cp=/usr/local/bin/kt_temp_classpaths/kttemp_cp.json
|
mkdir -p "${AGENT_USER_HOME_${PLATFORM}}"
|
||||||
temp_temp_cp=/usr/local/bin/kt_temp_classpaths/kttemp_temp_cp.json
|
|
||||||
|
|
||||||
#lists
|
|
||||||
dir_compiled=/tmp/2sve_tmp/
|
|
||||||
dir_sessions=/tmp/2sve_tmp/sessions/
|
|
||||||
txt_sessions=/tmp/2sve_tmp/current_sessions.txt
|
|
||||||
lines_sessions=`wc -l $txt_sessions | awk '{ print $1 }'`
|
|
||||||
testable_file=/tmp/2sve_tmp/test1.txt
|
|
||||||
hashtag="#"
|
|
||||||
|
|
||||||
#get shortened version of script's name
|
|
||||||
# this_scrpt=`basename "$0" &>/dev/null`
|
|
||||||
this_scrpt=`basename "$0"`
|
|
||||||
|
|
||||||
script_help=$( cat << EOF
|
|
||||||
|
|
||||||
This script simplifies the process of executing and compiling kolin code/projects
|
|
||||||
using simple configuration files.
|
|
||||||
|
|
||||||
Usages:
|
|
||||||
#0: ${this_scrpt} [arg] <modifier(s)?>
|
|
||||||
Arguments:
|
|
||||||
-h,--help See this help message.
|
|
||||||
-c,--compile Compile all .kt files in current dir into
|
|
||||||
current dir or a given dir a subargument. Fail: if errror on the code of given files.
|
|
||||||
-r,--run Run a .class file using 'kotlin'. Fail: if file
|
|
||||||
does not exist
|
|
||||||
-ef,--edit-file [mode: a(dd)/d(elete)] Edit the configuration file ($temp_cp) to
|
|
||||||
either add or remove an entry depinding on the mode. Fail [when adding]: if entry alredy
|
|
||||||
exists; Fail [when removing]: if out of range index is given.
|
|
||||||
-gcp|--get-class-paths Show prettily all the entries in the configuration
|
|
||||||
file ($temp_cp)
|
|
||||||
Example:
|
|
||||||
#0: $this_scrpt -c . 0
|
|
||||||
Explanation: compile all .kt files in cwd into cwd using the default classpath
|
|
||||||
|
|
||||||
|
multiline='first line
|
||||||
|
second line
|
||||||
|
third line'
|
||||||
|
cat << EOF
|
||||||
|
Sample text
|
||||||
EOF
|
EOF
|
||||||
)
|
|
||||||
|
|
||||||
function create_dirs() {
|
|
||||||
|
|
||||||
for_jsons=$( cat << EOF
|
|
||||||
{
|
|
||||||
"test_key": "test_val"
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
in_dir=$1
|
|
||||||
compiled_list="${in_dir}compiled_list.json"
|
|
||||||
compiled_list_tmp="${in_dir}compiled_list_tmp.json"
|
|
||||||
touch $compiled_list $compiled_list_tmp
|
|
||||||
echo "$for_jsons" > $compiled_list
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function recurse_dirs1() {
|
|
||||||
|
|
||||||
# readarray -t assArrayCP2< <(jq -r '.[]' $compiled_list)
|
|
||||||
files_array=$(find . -type f -name "*.kt") #find all files with the .kt (kotlin) exte
|
|
||||||
test_array=()
|
|
||||||
|
|
||||||
sub_str1="main"
|
|
||||||
sub_str2="Main"
|
|
||||||
c_line=1
|
|
||||||
|
|
||||||
for j in "${files_array[@]}"; do #this is because files on $files_array can't one by one
|
|
||||||
test_array+=($j)
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $lines_sessions == 0 ]]; then
|
|
||||||
new_session="${dir_sessions}session1/"
|
|
||||||
mkdir $new_session
|
|
||||||
|
|
||||||
# append to file
|
|
||||||
echo "$out" >> $txt_sessions
|
|
||||||
create_dirs $new_session
|
|
||||||
else
|
|
||||||
while read -r line; do
|
|
||||||
# echo "current line = $c_line\ttotal lines = $lines_file"
|
|
||||||
if [[ "$line" == "$out" ]]; then
|
|
||||||
compiled_list="${dir_sessions}session$c_line/compiled_list.json"
|
|
||||||
compiled_list_tmp="${dir_sessions}session$c_line/compiled_list_tmp.json"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
if [[ $c_line == $lines_sessions ]]; then
|
|
||||||
# echo "recursion limit reached"; break
|
|
||||||
new_session="${dir_sessions}session$((lines_sessions+1))/"
|
|
||||||
mkdir $new_session
|
|
||||||
|
|
||||||
# append to file
|
|
||||||
echo "$out" >> $txt_sessions
|
|
||||||
create_dirs $new_session
|
|
||||||
break
|
|
||||||
else
|
|
||||||
c_line=$((c_line+1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done < $txt_sessions
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
testarray_size=${#test_array[@]}
|
|
||||||
# echo "files array size = $testarray_size"
|
|
||||||
second_counter=0
|
|
||||||
|
|
||||||
|
|
||||||
for file in "${test_array[@]}"; do
|
|
||||||
readarray -t assArrayCP2< <(jq -r '.[]' $compiled_list)
|
|
||||||
counter=-1
|
|
||||||
|
|
||||||
for key in ${!assArrayCP2[@]}; do
|
|
||||||
counter=$((counter+1))
|
|
||||||
done
|
|
||||||
|
|
||||||
counter_plus_two=$((counter+2))
|
|
||||||
counter_plus_one=$((counter+1))
|
|
||||||
counter_plus_three=$((counter+3))
|
|
||||||
final_counter="${counter_plus_three}s"
|
|
||||||
|
|
||||||
counter=$((AACP2_size + 1))
|
|
||||||
last_entry=-1
|
|
||||||
lines_in_list=`wc -l $compiled_list | awk '{ print $1 }'`
|
|
||||||
lines_minusone="$((lines_in_list - 1))s"
|
|
||||||
tarray_size=${#test_array[@]}
|
|
||||||
tas_plus1=$((tarray_size + 1))
|
|
||||||
|
|
||||||
# echo "\tSECOND COUNTER = $second_counter"
|
|
||||||
|
|
||||||
AACP2_size=${#assArrayCP2[@]}
|
|
||||||
inner_counter=1
|
|
||||||
|
|
||||||
current_stats=`stat --format "%Y" $file`
|
|
||||||
only_name=`basename "$file"`
|
|
||||||
cmd1="cat $compiled_list | jq '.\"$only_name\"'"
|
|
||||||
# cmd1="cat $compiled_list | jq '.\"$test_name\"'"
|
|
||||||
evaluation_file=`eval $cmd1`
|
|
||||||
eval_file_without_apostrofes=${evaluation_file//\"/}
|
|
||||||
|
|
||||||
if [[ "$evaluation_file" == "null" ]]; then #file is not on the list
|
|
||||||
if [[ "$file" == *"$sub_str2"* || "$file" == *"$sub_str1"* ]]; then
|
|
||||||
is_main=$file
|
|
||||||
to_change=true
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
|
|
||||||
str_replacement="${hashtag}${counter_plus_one};${file_stats}"
|
|
||||||
cat $compiled_list | jq --arg fsts "$current_stats" '. + {"###": $fsts}' > $compiled_list_tmp; cat $compiled_list_tmp > $compiled_list; echo "" > $compiled_list_tmp
|
|
||||||
sed -i "$final_counter/"$hashtag$hashtag$hashtag"/"$only_name"/g" $compiled_list
|
|
||||||
|
|
||||||
if [[ $((testarray_size)) == 1 ]]; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
continue #this continue is causing issues but it also helps in some situations
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🍉 File = $file"
|
|
||||||
# echo "var is empty, therefore file is not added into the array"
|
|
||||||
echo -e "\tIn config status: not sited"
|
|
||||||
echo -e "\tChanged? = Null\n"
|
|
||||||
|
|
||||||
str_replacement="${hashtag}${counter_plus_one};${file_stats}"
|
|
||||||
cat $compiled_list | jq --arg fsts "$current_stats" '. + {"###": $fsts}' > $compiled_list_tmp; cat $compiled_list_tmp > $compiled_list; echo "" > $compiled_list_tmp
|
|
||||||
sed -i "$final_counter/"$hashtag$hashtag$hashtag"/"$only_name"/g" $compiled_list
|
|
||||||
|
|
||||||
#compile the file here
|
|
||||||
if [[ -z "$out" ]]; then #var is empty, therefore no out dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$file"; `kotlinc $file -d . -cp $whichKeyCP`
|
|
||||||
echo ""
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
else #var has something, dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$file"; `kotlinc $file -d $out -cp $whichKeyCP`
|
|
||||||
echo ""
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $second_counter == $((testarray_size)) ]]; then
|
|
||||||
if [[ "${test_array[@]}" =~ "${is_main}" && $to_change = true ]]; then
|
|
||||||
echo "🍉 File = $is_main"
|
|
||||||
# echo "var is empty, therefore file is not added into the array"
|
|
||||||
echo -e "\tIn config status: not sited"
|
|
||||||
echo -e "\tChanged? = Null\n"
|
|
||||||
if [[ -z "$out" ]]; then #var is empty, therefore no out dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$is_main"; `kotlinc $is_main -d . -cp $whichKeyCP`
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo -e "\t🔰 compiling:\t$is_main"; `kotlinc $is_main -d $out -cp $whichKeyCP`
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
else #file is on the list
|
|
||||||
# echo "File is already on the the configuration file"
|
|
||||||
# echo -e "\tCurrent stats = $current_stats\n\tStats in config = $eval_file_without_apostrofes"
|
|
||||||
if [[ "$current_stats" == "$eval_file_without_apostrofes" ]]; then
|
|
||||||
if [[ "$file" == *"$sub_str2"* || "$file" == *"$sub_str1"* ]]; then
|
|
||||||
is_main=$file
|
|
||||||
to_change=false
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🍉 File = $file"
|
|
||||||
echo -e "\tIn config status: sited"
|
|
||||||
# echo -e "\n---------File hasn't been changed---------\n" #file shouldn't be compiled
|
|
||||||
echo -e "\tChanged? = False\n"
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
#not compile
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
if [[ "$file" == *"$sub_str2"* || "$file" == *"$sub_str1"* ]]; then
|
|
||||||
is_main=$file
|
|
||||||
to_change=true
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
|
|
||||||
cmd2="cat $compiled_list | jq --arg foo "$current_stats" '. + {\"$only_name\": \$foo}'"
|
|
||||||
final_str=`eval $cmd2`
|
|
||||||
echo "$final_str" > $compiled_list_tmp; cat $compiled_list_tmp > $compiled_list; echo "" > $compiled_list_tmp; continue
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🍉 File = $file"
|
|
||||||
echo -e "\tIn config status: sited"
|
|
||||||
# echo -e "\n-------------File was changed--------------\n"
|
|
||||||
echo -e "\tChanged? = True\n"
|
|
||||||
|
|
||||||
#replace with new stats
|
|
||||||
cmd2="cat $compiled_list | jq --arg foo "$current_stats" '. + {\"$only_name\": \$foo}'"
|
|
||||||
final_str=`eval $cmd2`
|
|
||||||
echo "$final_str" > $compiled_list_tmp; cat $compiled_list_tmp > $compiled_list; echo "" > $compiled_list_tmp
|
|
||||||
|
|
||||||
if [[ -z "$out" ]]; then #var is empty, therefore no out dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$file"; `kotlinc $file -d . -cp $whichKeyCP`
|
|
||||||
echo ""
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
else #var has something, dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$file"; `kotlinc $file -d $out -cp $whichKeyCP`
|
|
||||||
echo ""
|
|
||||||
second_counter=$((second_counter+1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $second_counter == $((testarray_size)) ]]; then
|
|
||||||
if [[ "${test_array[@]}" =~ "${is_main}" && $to_change = true ]]; then
|
|
||||||
echo "🍉 File = $is_main"
|
|
||||||
# echo "var is empty, therefore file is not added into the array"
|
|
||||||
echo -e "\tIn config status: not sited"
|
|
||||||
echo -e "\tChanged? = Null\n"
|
|
||||||
if [[ -z "$out" ]]; then #var is empty, therefore no out dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$is_main"; `kotlinc $is_main -d . -cp $whichKeyCP`
|
|
||||||
else #var has something, dir was given
|
|
||||||
echo -e "\t🔰 compiling:\t$is_main"; `kotlinc $is_main -d $out -cp $whichKeyCP`
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
time_end=`date +%s`
|
|
||||||
runtime=$((time_end-time_start))
|
|
||||||
|
|
||||||
case ${?} in
|
|
||||||
0)
|
|
||||||
echo -e "\n-----------------------------------------"
|
|
||||||
echo -e "Everything was compiled successfully!"
|
|
||||||
echo -e "Time: ${runtime}secs."
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "\n\nAn error ocurred while compiling, check '$this_scrpt -h' for help."
|
|
||||||
echo -e "Time: ${runtime}secs."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function recurse_dirs2() {
|
|
||||||
|
|
||||||
files_array=$(find . -type f -name "*.kt") #find all files with the .kt (kotlin) extension
|
|
||||||
test_array=()
|
|
||||||
|
|
||||||
for j in "${files_array[@]}"; do #this is because files on $files_array can't be accessed one by one
|
|
||||||
test_array+=($j)
|
|
||||||
done
|
|
||||||
|
|
||||||
sub_str1="main"
|
|
||||||
sub_str2="Main"
|
|
||||||
|
|
||||||
echo -e "\n\t--------Files--------\n"
|
|
||||||
#note: the emoji is for orientating the user in case the error output is huge
|
|
||||||
time_start=`date +%s`
|
|
||||||
if [[ -z "$out" ]]; then #var is empty, therefore no out dir was given
|
|
||||||
for file in "${test_array[@]}"; do
|
|
||||||
if [[ "$file" == *"$sub_str2"* || "$file" == *"$sub_str1"* ]]; then
|
|
||||||
is_main=$file
|
|
||||||
else
|
|
||||||
echo -e "🍉 compiling:\t$file"; `kotlinc $file -d . -cp $whichKeyCP`
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo -e "🍉 compiling:\t$is_main"; `kotlinc $is_main -d . -cp $whichKeyCP`
|
|
||||||
else #var has something, dir was given
|
|
||||||
for file in "${test_array[@]}"; do
|
|
||||||
if [[ "$file" == *"$sub_str2"* || "$file" == *"$sub_str1"* ]]; then
|
|
||||||
is_main="$file"
|
|
||||||
else
|
|
||||||
|
|
||||||
echo -e "🍉 compiling:\t$file"; `kotlinc $file -d $out -cp $whichKeyCP`
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo -e "🍉 compiling:\t$is_main"; `kotlinc $is_main -d $out -cp $whichKeyCP`
|
|
||||||
fi
|
|
||||||
time_end=`date +%s`
|
|
||||||
runtime=$((time_end-time_start))
|
|
||||||
|
|
||||||
|
|
||||||
case ${?} in
|
|
||||||
0)
|
|
||||||
echo -e "\n\nEverything was compiled successfully!"
|
|
||||||
echo -e "Time: ${runtime}secs."
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "\n\nAn error ocurred while compiling, check '$this_scrpt -h' for help."
|
|
||||||
echo -e "Time: ${runtime}secs."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_class_paths() {
|
|
||||||
readarray -t assArrayCP< <(jq -r '.[]' $temp_cp)
|
|
||||||
|
|
||||||
echo -e "This are the available classpaths: \n"
|
|
||||||
|
|
||||||
echo -e "--------------------------CLASSPATHS--------------------------"
|
|
||||||
for key in ${!assArrayCP[@]}; do
|
|
||||||
echo -e " 💡$key -> ${assArrayCP[$key]}"
|
|
||||||
done
|
|
||||||
echo -e "--------------------------CLASSPATHS--------------------------"
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_trailing_comma() {
|
|
||||||
`sed -i.bak ':begin;$!N;s/,\n}/\n}/g;tbegin;P;D' $temp_cp` #remove trailing comma if any
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_func() {
|
|
||||||
|
|
||||||
for file in *; do
|
|
||||||
if [[ "$file" == "$0" ]]; then
|
|
||||||
echo "found"
|
|
||||||
else
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ -n "$1" ]]; then
|
|
||||||
case "$1" in
|
|
||||||
-h|--help)
|
|
||||||
echo "$script_help"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-c|--compile) #$1 = "-c"
|
|
||||||
out=$2
|
|
||||||
whichKeyCP=$3
|
|
||||||
|
|
||||||
if [[ -z "$out" ]]; then
|
|
||||||
out=`pwd`
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
# echo "1 = $1; 2 = $2; 3 = $3"
|
|
||||||
# echo -e "\n\nout= $out; whichKeyCP= $whichKeyCP"
|
|
||||||
readarray -t assArrayCP< <(jq -r '.[]' $temp_cp)
|
|
||||||
AACP_size=${#assArrayCP[@]}
|
|
||||||
|
|
||||||
if [[ -z "$3" ]]; then #var is empty
|
|
||||||
echo "this ran"
|
|
||||||
whichKeyCP=0
|
|
||||||
else
|
|
||||||
counter=1
|
|
||||||
for key in ${!assArrayCP[@]}; do
|
|
||||||
# echo "key = $key"
|
|
||||||
if [[ "$key" == "$whichKeyCP" ]]; then
|
|
||||||
# echo -e " 💡$key -> ${assArrayCP[$key]}"
|
|
||||||
whichKeyCP=${assArrayCP[$key]}; break
|
|
||||||
else
|
|
||||||
if [[ $AACP_size == $counter ]]; then
|
|
||||||
echo -e "\nERROR: Unfortunately the key '$whichKeyCP' was not found on the config file.\nFor more information run '$this_scrpt --get-class-paths' or '$this_scrpt -gcp'"
|
|
||||||
whichKeyCP=0
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
counter=$((counter+1))
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# echo -e "which key = $whichKeyCP"
|
|
||||||
echo -e "\nCLASSPATH:\t$whichKeyCP\nOUT DIR:\t$out\n"
|
|
||||||
recurse_dirs2
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-sc|--smart-compile)
|
|
||||||
|
|
||||||
if [[ -f "$compiled_list" ]]; then #exists
|
|
||||||
:
|
|
||||||
else #does not exist
|
|
||||||
# mkdir -p $dir_compiled && touch $compiled_list $compiled_list_tmp
|
|
||||||
# `echo '{ "test_file":"test_stats" }' | jq . > $compiled_list`
|
|
||||||
mkdir -p $dir_compiled $dir_sessions && touch $txt_sessions
|
|
||||||
lines_sessions=`wc -l $txt_sessions | awk '{ print $1 }'`
|
|
||||||
fi
|
|
||||||
|
|
||||||
#--------Status of a file---------#
|
|
||||||
#In config staus: [sited|not sited]
|
|
||||||
#Change? = [Null|True|False]
|
|
||||||
#
|
|
||||||
#for config statuses:
|
|
||||||
# sited: the program already has a register of that given file in the configurationg files
|
|
||||||
# not sited: the program does not has a register of that given file in the configurationg files
|
|
||||||
#for changed:
|
|
||||||
# Null: for files that are yet to be registered in the archive
|
|
||||||
# True: Files' current stats and in-config stats are different, therefore file is considered to have changed
|
|
||||||
# +,i what is considered as changed?
|
|
||||||
# +,j if file was directly written
|
|
||||||
# +,j if a program saved the file (regardless of having edited something). E.g. when writing with vim (:w)
|
|
||||||
# False: File' current stats and in-config stats are the same, therefore file has not changed
|
|
||||||
|
|
||||||
|
|
||||||
out=$2
|
|
||||||
whichKeyCP=$3
|
|
||||||
time_start=`date +%s`
|
|
||||||
|
|
||||||
# echo "1 = $1; 2 = $2; 3 = $3"
|
|
||||||
# echo -e "\n\nout= $out; whichKeyCP= $whichKeyCP"
|
|
||||||
readarray -t assArrayCP< <(jq -r '.[]' $temp_cp)
|
|
||||||
AACP_size=${#assArrayCP[@]}
|
|
||||||
|
|
||||||
if [[ -z "$3" ]]; then #var is empty
|
|
||||||
echo "this ran"
|
|
||||||
whichKeyCP=0
|
|
||||||
else
|
|
||||||
counter=1
|
|
||||||
for key in ${!assArrayCP[@]}; do
|
|
||||||
# echo "key = $key"
|
|
||||||
if [[ "$key" == "$whichKeyCP" ]]; then
|
|
||||||
# echo -e " 💡$key -> ${assArrayCP[$key]}"
|
|
||||||
whichKeyCP=${assArrayCP[$key]}; break
|
|
||||||
else
|
|
||||||
if [[ $AACP_size == $counter ]]; then
|
|
||||||
echo -e "\nERROR: Unfortunately the key '$whichKeyCP' was not found on the config file.\nFor more information run '$this_scrpt --get-class-paths' or '$this_scrpt -gcp'"
|
|
||||||
whichKeyCP=0
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
counter=$((counter+1))
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "\nCLASSPATH:\t$whichKeyCP\nOUT DIR:\t$out\n"
|
|
||||||
recurse_dirs1
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-gcp|--get-class-paths)
|
|
||||||
get_class_paths
|
|
||||||
echo -e "\nNote: you can add/remove more if you want by accessing the configuration file or using\n\t'$this_scrpt --edit-file --add' #for adding a new entry\n\t'$this_scrpt --edit-file --delete' #for deleting entries\nThe configuration file is located at: $temp_cp\n"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-ef|--edit-file)
|
|
||||||
mode=$2
|
|
||||||
get_class_paths; echo ""
|
|
||||||
AACP_size=${#assArrayCP[@]}
|
|
||||||
|
|
||||||
if [ "$mode" == "d" ] || [ "$mode" == "-d" ] || [ "$mode" == "delete" ] || [ "$mode" == "--delete" ]; then #delete mode
|
|
||||||
read -p "Which of the aforeshown entries do you want to remove [0-$((AACP_size-1))]?: " entry_to_remove
|
|
||||||
|
|
||||||
if (($entry_to_remove >= 0 && $entry_to_remove <= $((AACP_size-1)))); then
|
|
||||||
counter=1
|
|
||||||
for key in ${!assArrayCP[@]}; do
|
|
||||||
# echo -e " 💡$key -> ${assArrayCP[$key]}"
|
|
||||||
if [[ $key == $entry_to_remove ]]; then
|
|
||||||
#entry was found
|
|
||||||
entry="${assArrayCP[$key]}"
|
|
||||||
# match=`grep -n "$entry" $temp_cp &>/dev/null` #will supress output as well as error messages
|
|
||||||
match=`grep -n "$entry" $temp_cp` #will supress output as well as error messages
|
|
||||||
line_number=$(echo "$match" | cut -c1-1) #gets just the line number of the $match
|
|
||||||
line_wd="${line_number}d"
|
|
||||||
echo -e "\tentry = $entry\n\tmatch = $match\n\tline_number = $line_number\n\tline_wd = $line_wdn\n\tcounter = $counter" #show info
|
|
||||||
read -t 10 -n 1 -s -r -p "Press any key to continue (you have 10 seconds)..." #ask for authorization
|
|
||||||
`sed -i $line_wd $temp_cp` #delete the line
|
|
||||||
|
|
||||||
case ${?} in
|
|
||||||
0)
|
|
||||||
echo -e "\n\n-----------------------------------------"
|
|
||||||
echo -e "Entry removed successfully"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "\n\nAn error ocurred while removing the entry, check '$this_scrpt -h' for help."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
# `sed -i.bak ':begin;$!N;s/,\n}/\n}/g;tbegin;P;D' $temp_cp` #remove trailing comma if any #mn: was replaced by a function
|
|
||||||
check_trailing_comma
|
|
||||||
echo ""
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
if [[ $AACP_size == $counter ]]; then
|
|
||||||
echo -e "\nERROR: Unfortunately the key '$entry_to_remove' was not found on the config file.\nFor more information run '$this_scrpt --get-class-paths' or '$this_scrpt -gcp'"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
counter=$((counter+1))
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo -e "\nThe number $entry_to_remove is out of range, remember it must be between 0 and $((AACP_size-1)) (according to the options above)"
|
|
||||||
fi
|
|
||||||
elif [ "$mode" == "a" ] || [ "$mode" == "-a" ] ||[ "$mode" == "add" ] || [ "$mode" == "--add" ]; then #append mode
|
|
||||||
read -p "Type or paste the directories' path here: " entry_to_add
|
|
||||||
|
|
||||||
for key in ${!assArrayCP[@]}; do
|
|
||||||
if [[ "$entry_to_add" == "${assArrayCP[$key]}" ]]; then
|
|
||||||
echo -e "Sorry, your desired entry ($entry_to_add) is already on the configuration (.json) file.\nIf you think this is a mistake you can run '$this_scrpt -ef --delete' to remove the 'problematic' entry".
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
: # do nothing
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
readarray -t assArrayCP< <(jq -r '.[]' $temp_cp)
|
|
||||||
AACP_size=${#assArrayCP[@]}
|
|
||||||
|
|
||||||
counter=-1
|
|
||||||
for key in ${!assArrayCP[@]}; do
|
|
||||||
# echo -e " 💡$key -> ${assArrayCP[$key]}"
|
|
||||||
counter=$((counter+1))
|
|
||||||
done
|
|
||||||
counter_plus_three=$((counter+3))
|
|
||||||
counter_plus_two=$((counter+2))
|
|
||||||
counter_plus_one=$((counter+1))
|
|
||||||
final_counter="${counter_plus_three}s"
|
|
||||||
|
|
||||||
read -t 10 -n 1 -s -r -p "Press any key to continue (you have 10 seconds)..." #ask for authorization
|
|
||||||
echo "\n"
|
|
||||||
cat $temp_cp | jq --arg classpath "$entry_to_add" '. + {"classpath#": $classpath}' > $temp_temp_cp && cat $temp_temp_cp > $temp_cp; echo "" > $temp_temp_cp
|
|
||||||
sed -i "$final_counter/"$hashtag"/"$hashtag$counter_plus_one"/g" $temp_cp
|
|
||||||
|
|
||||||
case ${?} in
|
|
||||||
0)
|
|
||||||
echo -e "\n-----------------------------------------"
|
|
||||||
echo -e "Entry added successfully"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "\n\nAn error ocurred while adding the entry, check '$this_scrpt -h' for help."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
check_trailing_comma
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
-r|--run)
|
|
||||||
file=$2
|
|
||||||
final_file=${file/".class"/}
|
|
||||||
kotlin $final_file
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
i=0
|
|
||||||
file=$1
|
|
||||||
#echo "arg 1 = $1" #works
|
|
||||||
#it will try to find out/ 18 times, this so as to avoid overloading the ram
|
|
||||||
#trying to find an unexistent out/. Of course this number can be increased
|
|
||||||
|
|
||||||
while [[ $i -le 18 ]]; do
|
|
||||||
if [[ -d "$OUT_DICT" ]]; then #out found
|
|
||||||
cd $OUT_DICT
|
|
||||||
kotlin $file
|
|
||||||
break
|
|
||||||
else #out not found
|
|
||||||
cd ..
|
|
||||||
i=$((i+1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
echo -e "This script needs at least one argument to work.\nType '$this_scrpt -h' or '$this_scrpt --help' for help "
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
document.addEventListener("DOMContentLoaded", () =>
|
|
||||||
document.querySelectorAll("pre.msh .js-copy").forEach((copy) =>
|
|
||||||
copy.addEventListener("click", (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
content = copy.nextElementSibling
|
|
||||||
range = document.createRange()
|
|
||||||
range.selectNode(content)
|
|
||||||
|
|
||||||
window.getSelection().addRange(range)
|
|
||||||
|
|
||||||
try
|
|
||||||
successful = document.execCommand("copy")
|
|
||||||
copy.innerHTML = "Copied!"
|
|
||||||
|
|
||||||
setTimeout =>
|
|
||||||
copy.innerHTML = "Copy"
|
|
||||||
, 1500
|
|
||||||
|
|
||||||
msg = successful ? "successful" : "unsuccessful"
|
|
||||||
console.log({ msg })
|
|
||||||
|
|
||||||
catch error
|
|
||||||
console.log("Oops, unable to copy...")
|
|
||||||
|
|
||||||
window.getSelection().removeAllRanges()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
document.querySelectorAll("pre.msh code[data-language='html'] span.line").forEach((line) =>
|
|
||||||
content = line.innerHTML
|
|
||||||
content = content.replaceAll(/(<(\/?))(.+?(?=>))(>)/g, "$1<span class='c2'>$3</span>$4")
|
|
||||||
|
|
||||||
line.innerHTML = content
|
|
||||||
pink = line.querySelector(".c2")
|
|
||||||
|
|
||||||
if pink != null
|
|
||||||
content = pink.innerHTML.split(" ")
|
|
||||||
content = content.map((part, index) =>
|
|
||||||
if index > 0
|
|
||||||
if part.includes("=")
|
|
||||||
part = part.replaceAll(/(.+?)(".*)/g, "<span class='c3'>$1</span><span class='c4'>$2</span>")
|
|
||||||
else
|
|
||||||
part = part.replaceAll(/(.*\S)/g, "<span class='c3'>$1</span>")
|
|
||||||
part
|
|
||||||
).join(" ")
|
|
||||||
pink.innerHTML = content
|
|
||||||
return
|
|
||||||
)
|
|
||||||
|
|
||||||
document.querySelectorAll("pre.msh code[data-language='css'] span.line").forEach((line) =>
|
|
||||||
content = line.innerHTML
|
|
||||||
|
|
||||||
if line.dataset.indent
|
|
||||||
content = content.split(/:/g).map((part, index) =>
|
|
||||||
if index == 0
|
|
||||||
part.replace(/(.*)/g, "<span class='c7'>$1</span>")
|
|
||||||
else
|
|
||||||
part = part.replaceAll(/(\S.+?(?=\s|;))/g, "<span class='c6'>$1</span>")
|
|
||||||
part = part.replaceAll(/(".+?(?=,|\s|;))/g, "<span class='c4'>$1</span>")
|
|
||||||
part = part.replaceAll(/(url\(.+?(?=\s|;))/g, "<span class='c3'>$1</span>")
|
|
||||||
part.replaceAll(/\((.+?(?=\)))/g, "(<span class='c4'>$1</span>")
|
|
||||||
).join(":")
|
|
||||||
else
|
|
||||||
content = content.replaceAll(/(.+?(?=,|\s|{}))/g, "<span class='c2'>$1</span>")
|
|
||||||
content = content.replaceAll(/((\.|:).+?(?=\s))/g, "<span class='c3'>$1</span>")
|
|
||||||
|
|
||||||
line.innerHTML = content
|
|
||||||
return
|
|
||||||
)
|
|
||||||
)
|
|
52
samples/coffeescript.coffee
Normal file
52
samples/coffeescript.coffee
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
###
|
||||||
|
Some tests
|
||||||
|
###
|
||||||
|
class Animal
|
||||||
|
constructor: (@name) ->
|
||||||
|
move: (meters) -> alert @name + " moved " + meters + "m."
|
||||||
|
|
||||||
|
class Snake extends Animal
|
||||||
|
move: ->
|
||||||
|
alert 'Slithering...'
|
||||||
|
super 5
|
||||||
|
|
||||||
|
number = 42; opposite = true
|
||||||
|
|
||||||
|
/^a\/\\[a-z/\n]\u00A3b$/.test 'a//b'
|
||||||
|
|
||||||
|
square = (x) -> x * x
|
||||||
|
|
||||||
|
range = [1..2]
|
||||||
|
list = [1...5]
|
||||||
|
|
||||||
|
math =
|
||||||
|
root: Math.sqrt
|
||||||
|
cube: (x) => x * square x
|
||||||
|
|
||||||
|
race = (winner, runners...) ->
|
||||||
|
print winner, runners
|
||||||
|
|
||||||
|
alert "I knew it!" if elvis?
|
||||||
|
|
||||||
|
cubes = math.cube num for num in list
|
||||||
|
|
||||||
|
text = """
|
||||||
|
Result
|
||||||
|
is #{ @number }"""
|
||||||
|
|
||||||
|
html = ''' <body></body>'''
|
||||||
|
|
||||||
|
String::dasherize = ->
|
||||||
|
this.replace /_/g, "-"
|
||||||
|
SINGERS = {Jagger: "Rock", Elvis: "Roll"}
|
||||||
|
|
||||||
|
t = ///
|
||||||
|
[a-z]
|
||||||
|
///
|
||||||
|
|
||||||
|
$('.shopping_cart').bind 'click', (event) =>
|
||||||
|
@customer.purchase @cart
|
||||||
|
|
||||||
|
hi = `function() {
|
||||||
|
return [document.title, "Hello JavaScript"].join(": ");
|
||||||
|
}`
|
110
samples/conf.ini
110
samples/conf.ini
|
@ -1,110 +0,0 @@
|
||||||
# Howdy's config file: https://github.com/boltgolt/howdy/blob/beta/howdy/src/config.ini
|
|
||||||
# Press CTRL + X to save in the nano editor
|
|
||||||
|
|
||||||
[core]
|
|
||||||
# Print that face detection is being attempted
|
|
||||||
detection_notice = false
|
|
||||||
|
|
||||||
# Print that face detection has timed out
|
|
||||||
timeout_notice = true
|
|
||||||
|
|
||||||
# Do not print anything when a face verification succeeds
|
|
||||||
no_confirmation = false
|
|
||||||
|
|
||||||
# When a user without a known face model tries to use this script, don't
|
|
||||||
# show an error but fail silently
|
|
||||||
suppress_unknown = false
|
|
||||||
|
|
||||||
# Disable Howdy in remote shells
|
|
||||||
abort_if_ssh = true
|
|
||||||
|
|
||||||
# Disable Howdy if lid is closed
|
|
||||||
abort_if_lid_closed = true
|
|
||||||
|
|
||||||
# Disable howdy in the PAM
|
|
||||||
# The howdy command will still function
|
|
||||||
disabled = false
|
|
||||||
|
|
||||||
# Use CNN instead of HOG
|
|
||||||
# CNN model is much more accurate than the HOG based model, but takes much more
|
|
||||||
# computational power to run, and is meant to be executed on a GPU to attain reasonable speed.
|
|
||||||
use_cnn = false
|
|
||||||
|
|
||||||
[video]
|
|
||||||
# The certainty of the detected face belonging to the user of the account
|
|
||||||
# On a scale from 1 to 10, values above 5 are not recommended
|
|
||||||
# Lower is better
|
|
||||||
certainty = 3.5
|
|
||||||
|
|
||||||
# The number of seconds to search before timing out
|
|
||||||
timeout = 4
|
|
||||||
|
|
||||||
# The path of the device to capture frames from
|
|
||||||
# Should be set automatically by an installer if your distro has one
|
|
||||||
device_path = none
|
|
||||||
|
|
||||||
# Print a warning if the the video device is not found
|
|
||||||
warn_no_device = true
|
|
||||||
|
|
||||||
# Scale down the video feed to this maximum height
|
|
||||||
# Speeds up face recognition but can make it less precise
|
|
||||||
max_height = 320
|
|
||||||
|
|
||||||
# Set the camera input profile to this width and height
|
|
||||||
# The largest profile will be used if set to -1
|
|
||||||
# Automatically ignored if not a valid profile
|
|
||||||
frame_width = -1
|
|
||||||
frame_height = -1
|
|
||||||
|
|
||||||
# Because of flashing IR emitters, some frames can be completely unlit
|
|
||||||
# Skip the frame if the lowest 1/8 of the histogram is above this percentage
|
|
||||||
# of the total
|
|
||||||
# The lower this setting is, the more dark frames are ignored
|
|
||||||
dark_threshold = 50
|
|
||||||
|
|
||||||
# The recorder to use. Can be either opencv (default), ffmpeg or pyv4l2.
|
|
||||||
# Switching from the default opencv to ffmpeg can help with grayscale issues.
|
|
||||||
recording_plugin = opencv
|
|
||||||
|
|
||||||
# Video format used by ffmpeg. Options include vfwcap or v4l2.
|
|
||||||
# FFMPEG only.
|
|
||||||
device_format = v4l2
|
|
||||||
|
|
||||||
# Force the use of Motion JPEG when decoding frames, fixes issues with YUYV
|
|
||||||
# raw frame decoding.
|
|
||||||
# OPENCV only.
|
|
||||||
force_mjpeg = false
|
|
||||||
|
|
||||||
# Specify exposure value explicitly. This disables autoexposure.
|
|
||||||
# Use qv4l2 to determine an appropriate value.
|
|
||||||
# OPENCV only.
|
|
||||||
exposure = -1
|
|
||||||
|
|
||||||
[snapshots]
|
|
||||||
# Capture snapshots of failed login attempts and save them to disk with metadata
|
|
||||||
# Snapshots are saved to the "snapshots" folder
|
|
||||||
save_failed = false
|
|
||||||
|
|
||||||
# Do the same as the option above but for successful attempts
|
|
||||||
save_successful = false
|
|
||||||
|
|
||||||
[rubberstamps]
|
|
||||||
# Enable specific extra checks after the user has been recognised
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
# What type of stamps to run and with what options. The type, timeout and
|
|
||||||
# failure mode are required. One line per stamp. Rule syntax:
|
|
||||||
# stamptype timeout (failsafe | faildeadly) [extra_argument=value]
|
|
||||||
stamp_rules =
|
|
||||||
nod 5s failsafe min_distance=12
|
|
||||||
|
|
||||||
[debug]
|
|
||||||
# Show a short but detailed diagnostic report in console
|
|
||||||
# Enabling this can cause some UI apps to fail, only enable it to debug
|
|
||||||
end_report = false
|
|
||||||
|
|
||||||
# More verbose logging from the rubberstamps system
|
|
||||||
verbose_stamps = false
|
|
||||||
|
|
||||||
# Pass output of the GTK auth window to the terminal
|
|
||||||
gtk_stdout = false
|
|
995
samples/cpp.cpp
995
samples/cpp.cpp
File diff suppressed because it is too large
Load diff
|
@ -1,183 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace PathCreation.Utility {
|
|
||||||
public static class MathUtility {
|
|
||||||
|
|
||||||
float4 frag (v2f i) : SV_Target {
|
|
||||||
float2 uv = pointOnSphereToUV(i.pos);
|
|
||||||
float2 countryData = text2D(countryData, UV).rg;
|
|
||||||
float countryOutLine = countryData[0];
|
|
||||||
int countryIndex = (int)countryData[1] - 1;
|
|
||||||
|
|
||||||
float3 colour = countryOutline;
|
|
||||||
|
|
||||||
if (countryIndex >= 0) {
|
|
||||||
float lastVisited = CountryLastVisitTime[countryIndex];
|
|
||||||
float timeSinceVisit = currentTime - lastVisitTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform point from local to world space
|
|
||||||
public static Vector3 TransformPoint (Vector3 p, Transform t, PathSpace space) {
|
|
||||||
// path only works correctly for uniform scales, so average out xyz global scale
|
|
||||||
float scale = Vector3.Dot (t.lossyScale, Vector3.one) / 3;
|
|
||||||
Vector3 constrainedPos = t.position;
|
|
||||||
Quaternion constrainedRot = t.rotation;
|
|
||||||
ConstrainPosRot (ref constrainedPos, ref constrainedRot, space);
|
|
||||||
return constrainedRot * p * scale + constrainedPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform point from world to local space
|
|
||||||
public static Vector3 InverseTransformPoint (Vector3 p, Transform t, PathSpace space) {
|
|
||||||
Vector3 constrainedPos = t.position;
|
|
||||||
Quaternion constrainedRot = t.rotation;
|
|
||||||
ConstrainPosRot (ref constrainedPos, ref constrainedRot, space);
|
|
||||||
|
|
||||||
// path only works correctly for uniform scales, so average out xyz global scale
|
|
||||||
float scale = Vector3.Dot (t.lossyScale, Vector3.one) / 3;
|
|
||||||
var offset = p - constrainedPos;
|
|
||||||
|
|
||||||
return Quaternion.Inverse (constrainedRot) * offset / scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vector from local to world space (affected by rotation and scale, but not position)
|
|
||||||
public static Vector3 TransformVector (Vector3 p, Transform t, PathSpace space) {
|
|
||||||
// path only works correctly for uniform scales, so average out xyz global scale
|
|
||||||
float scale = Vector3.Dot (t.lossyScale, Vector3.one) / 3;
|
|
||||||
Quaternion constrainedRot = t.rotation;
|
|
||||||
ConstrainRot (ref constrainedRot, space);
|
|
||||||
return constrainedRot * p * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vector from world to local space (affected by rotation and scale, but not position)
|
|
||||||
public static Vector3 InverseTransformVector (Vector3 p, Transform t, PathSpace space) {
|
|
||||||
Quaternion constrainedRot = t.rotation;
|
|
||||||
ConstrainRot (ref constrainedRot, space);
|
|
||||||
// path only works correctly for uniform scales, so average out xyz global scale
|
|
||||||
float scale = Vector3.Dot (t.lossyScale, Vector3.one) / 3;
|
|
||||||
return Quaternion.Inverse (constrainedRot) * p / scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vector from local to world space (affected by rotation, but not position or scale)
|
|
||||||
public static Vector3 TransformDirection (Vector3 p, Transform t, PathSpace space) {
|
|
||||||
Quaternion constrainedRot = t.rotation;
|
|
||||||
ConstrainRot (ref constrainedRot, space);
|
|
||||||
return constrainedRot * p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform vector from world to local space (affected by rotation, but not position or scale)
|
|
||||||
public static Vector3 InverseTransformDirection (Vector3 p, Transform t, PathSpace space) {
|
|
||||||
Quaternion constrainedRot = t.rotation;
|
|
||||||
ConstrainRot (ref constrainedRot, space);
|
|
||||||
return Quaternion.Inverse (constrainedRot) * p;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool LineSegmentsIntersect (Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2) {
|
|
||||||
float d = (b2.x - b1.x) * (a1.y - a2.y) - (a1.x - a2.x) * (b2.y - b1.y);
|
|
||||||
if (d == 0)
|
|
||||||
return false;
|
|
||||||
float t = ((b1.y - b2.y) * (a1.x - b1.x) + (b2.x - b1.x) * (a1.y - b1.y)) / d;
|
|
||||||
float u = ((a1.y - a2.y) * (a1.x - b1.x) + (a2.x - a1.x) * (a1.y - b1.y)) / d;
|
|
||||||
|
|
||||||
return t >= 0 && t <= 1 && u >= 0 && u <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool LinesIntersect (Vector2 a1, Vector2 a2, Vector2 a3, Vector2 a4) {
|
|
||||||
return (a1.x - a2.x) * (a3.y - a4.y) - (a1.y - a2.y) * (a3.x - a4.x) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector2 PointOfLineLineIntersection (Vector2 a1, Vector2 a2, Vector2 a3, Vector2 a4) {
|
|
||||||
float d = (a1.x - a2.x) * (a3.y - a4.y) - (a1.y - a2.y) * (a3.x - a4.x);
|
|
||||||
if (d == 0) {
|
|
||||||
Debug.LogError ("Lines are parallel, please check that this is not the case before calling line intersection method");
|
|
||||||
return Vector2.zero;
|
|
||||||
} else {
|
|
||||||
float n = (a1.x - a3.x) * (a3.y - a4.y) - (a1.y - a3.y) * (a3.x - a4.x);
|
|
||||||
float t = n / d;
|
|
||||||
return a1 + (a2 - a1) * t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector2 ClosestPointOnLineSegment (Vector2 p, Vector2 a, Vector2 b) {
|
|
||||||
Vector2 aB = b - a;
|
|
||||||
Vector2 aP = p - a;
|
|
||||||
float sqrLenAB = aB.sqrMagnitude;
|
|
||||||
|
|
||||||
if (sqrLenAB == 0)
|
|
||||||
return a;
|
|
||||||
|
|
||||||
float t = Mathf.Clamp01 (Vector2.Dot (aP, aB) / sqrLenAB);
|
|
||||||
return a + aB * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector3 ClosestPointOnLineSegment (Vector3 p, Vector3 a, Vector3 b) {
|
|
||||||
Vector3 aB = b - a;
|
|
||||||
Vector3 aP = p - a;
|
|
||||||
float sqrLenAB = aB.sqrMagnitude;
|
|
||||||
|
|
||||||
if (sqrLenAB == 0)
|
|
||||||
return a;
|
|
||||||
|
|
||||||
float t = Mathf.Clamp01 (Vector3.Dot (aP, aB) / sqrLenAB);
|
|
||||||
return a + aB * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int SideOfLine (Vector2 a, Vector2 b, Vector2 c) {
|
|
||||||
return (int) Mathf.Sign ((c.x - a.x) * (-b.y + a.y) + (c.y - a.y) * (b.x - a.x));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the smallest angle between ABC. Never greater than 180
|
|
||||||
public static float MinAngle (Vector3 a, Vector3 b, Vector3 c) {
|
|
||||||
return Vector3.Angle ((a - b), (c - b));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool PointInTriangle (Vector2 a, Vector2 b, Vector2 c, Vector2 p) {
|
|
||||||
float area = 0.5f * (-b.y * c.x + a.y * (-b.x + c.x) + a.x * (b.y - c.y) + b.x * c.y);
|
|
||||||
float s = 1 / (2 * area) * (a.y * c.x - a.x * c.y + (c.y - a.y) * p.x + (a.x - c.x) * p.y);
|
|
||||||
float t = 1 / (2 * area) * (a.x * b.y - a.y * b.x + (a.y - b.y) * p.x + (b.x - a.x) * p.y);
|
|
||||||
return s >= 0 && t >= 0 && (s + t) <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool PointsAreClockwise (Vector2[] points) {
|
|
||||||
float signedArea = 0;
|
|
||||||
for (int i = 0; i < points.Length; i++) {
|
|
||||||
int nextIndex = (i + 1) % points.Length;
|
|
||||||
signedArea += (points[nextIndex].x - points[i].x) * (points[nextIndex].y + points[i].y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return signedArea >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ConstrainPosRot (ref Vector3 pos, ref Quaternion rot, PathSpace space) {
|
|
||||||
if (space == PathSpace.xy) {
|
|
||||||
var eulerAngles = rot.eulerAngles;
|
|
||||||
if (eulerAngles.x != 0 || eulerAngles.y != 0) {
|
|
||||||
rot = Quaternion.AngleAxis (eulerAngles.z, Vector3.forward);
|
|
||||||
}
|
|
||||||
pos = new Vector3 (pos.x, pos.y, 0);
|
|
||||||
} else if (space == PathSpace.xz) {
|
|
||||||
var eulerAngles = rot.eulerAngles;
|
|
||||||
if (eulerAngles.x != 0 || eulerAngles.z != 0) {
|
|
||||||
rot = Quaternion.AngleAxis (eulerAngles.y, Vector3.up);
|
|
||||||
}
|
|
||||||
pos = new Vector3 (pos.x, 0, pos.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ConstrainRot (ref Quaternion rot, PathSpace space) {
|
|
||||||
if (space == PathSpace.xy) {
|
|
||||||
var eulerAngles = rot.eulerAngles;
|
|
||||||
if (eulerAngles.x != 0 || eulerAngles.y != 0) {
|
|
||||||
rot = Quaternion.AngleAxis (eulerAngles.z, Vector3.forward);
|
|
||||||
}
|
|
||||||
} else if (space == PathSpace.xz) {
|
|
||||||
var eulerAngles = rot.eulerAngles;
|
|
||||||
if (eulerAngles.x != 0 || eulerAngles.z != 0) {
|
|
||||||
rot = Quaternion.AngleAxis (eulerAngles.y, Vector3.up);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
180
samples/css.css
180
samples/css.css
|
@ -1,175 +1,25 @@
|
||||||
body {
|
@import "manual.css";
|
||||||
background-color: #111921;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
|
||||||
display: block;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Galada-Regular';
|
font-family: DroidSans;
|
||||||
src: url('Galada-Regular.ttf');
|
src: url(DroidSans.ttf);
|
||||||
|
unicode-range: U+000-5FF, U+1e00-1fff, U+2000-2300;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
h1.mystyle:lang(en) {
|
||||||
font-family: 'Overpass';
|
color: blue; /* TODO: change THIS to yellow for next version! */
|
||||||
font-style: normal;
|
border: rgb(255, 0, 0);
|
||||||
font-weight: 400;
|
background-color: #FAFAFA;
|
||||||
font-display: swap;
|
background: url(hello.jpg) !important;
|
||||||
src: url(https://fonts.gstatic.com/s/overpass/v5/qFdH35WCmI96Ajtm81GrU9vyww.woff2)
|
|
||||||
format('woff2');
|
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
|
|
||||||
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
||||||
}
|
|
||||||
/* latin */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Overpass';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
font-display: swap;
|
|
||||||
src: url(https://fonts.gstatic.com/s/overpass/v5/qFdH35WCmI96Ajtm81GlU9s.woff2)
|
|
||||||
format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
|
||||||
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212,
|
|
||||||
U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@import url(https://fonts.googleapis.com/css?family=Roboto:400, 300);
|
div > p, p ~ ul, input [type="radio"] {
|
||||||
|
color: green;
|
||||||
* {
|
width: 80%;
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
#header:after {
|
||||||
font-family: 'Galada-Regular';
|
color: red;
|
||||||
/* color: #000000; */
|
|
||||||
font-size: 90px;
|
|
||||||
text-align: center;
|
|
||||||
color: whitesmoke;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
&!
|
||||||
font-family: 'Courier';
|
|
||||||
font-size: 30px;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-family: 'Courier New', Courier, monospace;
|
|
||||||
color: #000000;
|
|
||||||
font-size: 30px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-family: 'Courier New', Courier, monospace;
|
|
||||||
font-size: 25px;
|
|
||||||
text-align: center;
|
|
||||||
color: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
#about {
|
|
||||||
color: blue;
|
|
||||||
font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande',
|
|
||||||
'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a black background color to the top navigation */
|
|
||||||
.topnav {
|
|
||||||
background-color: #333;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Style the links inside the navigation bar */
|
|
||||||
.topnav a {
|
|
||||||
float: left;
|
|
||||||
color: #f2f2f2;
|
|
||||||
text-align: center;
|
|
||||||
padding: 14px 16px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Change the color of links on hover */
|
|
||||||
.topnav a:hover {
|
|
||||||
background-color: #ddd;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a color to the active/current link */
|
|
||||||
.topnav a.active {
|
|
||||||
background-color: #04aa6d;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 4px;
|
|
||||||
max-width: 1291px;
|
|
||||||
margin: 10% auto;
|
|
||||||
height: 301px;
|
|
||||||
position: relative;
|
|
||||||
padding: 34px;
|
|
||||||
color: #444;
|
|
||||||
cursor: pointer;
|
|
||||||
&:before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
background-color: #ccc;
|
|
||||||
left: 20px;
|
|
||||||
right: 20px;
|
|
||||||
bottom: 0;
|
|
||||||
top: 50%;
|
|
||||||
z-index: -1;
|
|
||||||
box-shadow: 0 0 40px lighten(#000, 60%);
|
|
||||||
transition: box-shadow 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
&.level-3 {
|
|
||||||
&:hover {
|
|
||||||
&:before {
|
|
||||||
box-shadow: 0 0 80px lighten(#000, 60%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The sidebar menu */
|
|
||||||
.sidenav {
|
|
||||||
height: 100%; /* Full-height: remove this if you want "auto" height */
|
|
||||||
width: 160px; /* Set the width of the sidebar */
|
|
||||||
position: fixed; /* Fixed Sidebar (stay in place on scroll) */
|
|
||||||
z-index: 1; /* Stay on top */
|
|
||||||
top: 0; /* Stay at the top */
|
|
||||||
left: 0;
|
|
||||||
background-color: #111; /* Black */
|
|
||||||
overflow-x: hidden; /* Disable horizontal scroll */
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The navigation menu links */
|
|
||||||
.sidenav a {
|
|
||||||
padding: 6px 8px 6px 16px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 25px;
|
|
||||||
color: #818181;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When you mouse over the navigation links, change their color */
|
|
||||||
.sidenav a:hover {
|
|
||||||
color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* On smaller screens, where height is less than 450px, change the style of the sidebar (less padding and a smaller font size) */
|
|
||||||
@media screen and (max-height: 450px) {
|
|
||||||
.sidenav {
|
|
||||||
padding-top: 15px;
|
|
||||||
}
|
|
||||||
.sidenav a {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
@import url(https://fonts.googleapis.com/css?family=Roboto:400);
|
|
||||||
@import url("chrome://communicator/skin/");
|
|
||||||
@import 'custom.css' screen and (max-width: 768px);
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Galada-Regular';
|
|
||||||
src: url('Galada-Regular.ttf');
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Applies to the entire body of the HTML document (except where overridden by more specific
|
|
||||||
selectors). */
|
|
||||||
body {
|
|
||||||
margin: 25px;
|
|
||||||
background-color: rgb(240,240,240);
|
|
||||||
font-family: arial, sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Applies to all <h1>...</h1> elements. */
|
|
||||||
h1 {
|
|
||||||
font-size: 35px;
|
|
||||||
font-weight: normal;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Applies to all elements with <... class="someclass"> specified. */
|
|
||||||
.someclass { color: red; }
|
|
||||||
|
|
||||||
/* Applies to the element with <... id="someid"> specified. */
|
|
||||||
#someid { color: green; }
|
|
161
samples/go.go
Normal file
161
samples/go.go
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Go highlight sample
|
||||||
|
*/
|
||||||
|
//go:build (linux || windows) && arm
|
||||||
|
// +build linux,arm windows,arm
|
||||||
|
|
||||||
|
// Package main
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import alias "fmt"
|
||||||
|
|
||||||
|
//go:generate go tool yacc -o gopher.go -p parser gopher.y
|
||||||
|
|
||||||
|
/*
|
||||||
|
Semantic highlighting:
|
||||||
|
Generated spectrum to pick colors for local variables and parameters:
|
||||||
|
Color#1 SC1.1 SC1.2 SC1.3 SC1.4 Color#2 SC2.1 SC2.2 SC2.3 SC2.4 Color#3
|
||||||
|
Color#3 SC3.1 SC3.2 SC3.3 SC3.4 Color#4 SC4.1 SC4.2 SC4.3 SC4.4 Color#5
|
||||||
|
*/
|
||||||
|
|
||||||
|
type (
|
||||||
|
PublicInterface interface {
|
||||||
|
PublicFunc() int
|
||||||
|
privateFunc() int
|
||||||
|
}
|
||||||
|
|
||||||
|
privateInterface interface {
|
||||||
|
PublicFunc() int
|
||||||
|
privateFunc() int
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicStruct struct {
|
||||||
|
PublicField int
|
||||||
|
privateField int
|
||||||
|
}
|
||||||
|
|
||||||
|
privateStruct struct {
|
||||||
|
PublicField int
|
||||||
|
privateField int
|
||||||
|
}
|
||||||
|
|
||||||
|
demoInt int
|
||||||
|
|
||||||
|
T struct {
|
||||||
|
FirstName string `json:"first_name" arbitrary text`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PublicConst = 1
|
||||||
|
privateConst = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
PublicVar = 1
|
||||||
|
privateVar = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicFunc does the thing
|
||||||
|
func PublicFunc() int {
|
||||||
|
localVar := PublicVar
|
||||||
|
return localVar
|
||||||
|
}
|
||||||
|
|
||||||
|
// privateFunc does the thing
|
||||||
|
func privateFunc() (int, int) {
|
||||||
|
LocalVar := privateVar
|
||||||
|
return LocalVar, PublicVar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps PublicStruct) PublicFunc() int {
|
||||||
|
return ps.privateField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps privateStruct) privateFunc() int {
|
||||||
|
return ps.PublicField
|
||||||
|
}
|
||||||
|
|
||||||
|
func _(pi PublicInterface) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func _(pi privateInterface) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func variableFunc(demo1 int, demo2 demoInt) {
|
||||||
|
demo1 = 3
|
||||||
|
a := PublicStruct{}
|
||||||
|
a.PublicFunc()
|
||||||
|
b := privateStruct{}
|
||||||
|
b.privateFunc()
|
||||||
|
demo2 = 4
|
||||||
|
if demo1, demo2 := privateFunc(); demo1 != 3 {
|
||||||
|
_ = demo1
|
||||||
|
_ = demo2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
demoLabel:
|
||||||
|
for demo1 := range []int{1, 2, 3, 4} {
|
||||||
|
_ = demo1
|
||||||
|
continue demoLabel
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case 1 == 2:
|
||||||
|
demo1, demo2 := privateFunc()
|
||||||
|
_ = demo1
|
||||||
|
_ = demo2
|
||||||
|
default:
|
||||||
|
_ = demo1
|
||||||
|
}
|
||||||
|
|
||||||
|
f := func() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
f()
|
||||||
|
PublicFunc()
|
||||||
|
variableFunc(1, 2)
|
||||||
|
_ = demo1
|
||||||
|
_ = demo2
|
||||||
|
println("builtin function")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
const LocalConst = 1
|
||||||
|
const localConst = 2
|
||||||
|
fmt.Println("demo\n\xA")
|
||||||
|
alias.Println("demo")
|
||||||
|
variableFunc(1, 2)
|
||||||
|
var d, c *int = nil, nil
|
||||||
|
_, _ = c, d
|
||||||
|
_, _ = true, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var ExportedVariableFunction = func() {}
|
||||||
|
var packageLocalVariableFunction = func() {}
|
||||||
|
|
||||||
|
type typeWithCall struct {
|
||||||
|
PublicFieldCall func()
|
||||||
|
privateFieldCall func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func calls(t typeWithCall) {
|
||||||
|
var localVariableFunction = func() {}
|
||||||
|
|
||||||
|
ExportedVariableFunction()
|
||||||
|
packageLocalVariableFunction()
|
||||||
|
localVariableFunction()
|
||||||
|
t.PublicFieldCall()
|
||||||
|
t.privateFieldCall()
|
||||||
|
}
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
var err error
|
||||||
|
a, err := 1, nil
|
||||||
|
println(a, err)
|
||||||
|
|
||||||
|
for a := 0; a < 10; a++ {
|
||||||
|
println(a)
|
||||||
|
}
|
||||||
|
}
|
16
samples/haskell.hs
Normal file
16
samples/haskell.hs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
module ModuleName
|
||||||
|
import qualified ImportModuleName
|
||||||
|
"string literal"
|
||||||
|
'c'
|
||||||
|
intPair :: (Int, Int)
|
||||||
|
intPair = (456,434)
|
||||||
|
-- line comment
|
||||||
|
{- nested
|
||||||
|
comment -}
|
||||||
|
data Bool = True | False
|
||||||
|
let l1 = [1, 2]
|
||||||
|
let l2 = 1 : []
|
||||||
|
let two = 1 + 1
|
||||||
|
let f = \_ + 1
|
||||||
|
[t|select * from foo|]
|
131
samples/header.h
131
samples/header.h
|
@ -1,131 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
/* appearance */
|
|
||||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
|
||||||
static const char dmenufont[] = "monospace:size=10";
|
|
||||||
static const char col_gray1[] = "#5F6587";
|
|
||||||
static const char col_gray2[] = "#8289AA";
|
|
||||||
static const char col_gray3[] = "#A6AFD2";
|
|
||||||
static const char col_gray4[] = "#C5CFF5";
|
|
||||||
static const char col_teal[] = "#78DCCC";
|
|
||||||
static const char *colors[][3] = {
|
|
||||||
/* fg bg border */
|
|
||||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
|
||||||
[SchemeSel] = { col_gray4, col_teal, col_teal },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
|
||||||
|
|
||||||
static const Rule rules[] = {
|
|
||||||
/* xprop(1):
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
* WM_NAME(STRING) = title
|
|
||||||
*/
|
|
||||||
/* class instance title tags mask isfloating monitor */
|
|
||||||
{ "Gimp", NULL, NULL, 0, 1, -1 },
|
|
||||||
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
|
||||||
};
|
|
||||||
static const int ruleperiod = 5; /* number of seconds before rules are ignored */
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
|
||||||
static const int nmaster = 1; /* number of clients in master area */
|
|
||||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
|
||||||
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
|
||||||
|
|
||||||
static const LayoutMonitorRule lm_rules[] = {
|
|
||||||
/* >=w, >=h, req'd layout, new nmaster, new mfact */
|
|
||||||
{ 3000, 0, 0, 2, 0.66 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
|
||||||
/* symbol arrange function */
|
|
||||||
{ "[]=", tile }, /* first entry is default */
|
|
||||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
|
||||||
{ "[M]", monocle },
|
|
||||||
{ "TTT", bstack },
|
|
||||||
{ "===", bstackhoriz },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* key definitions */
|
|
||||||
#define MODKEY Mod1Mask
|
|
||||||
#define TAGKEYS(KEY,TAG) \
|
|
||||||
{ KeyPress, MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
|
||||||
{ KeyPress, MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
|
||||||
{ KeyPress, MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
|
||||||
{ KeyPress, MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
|
||||||
|
|
||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
|
||||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
|
||||||
|
|
||||||
/* commands */
|
|
||||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
|
||||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_teal, "-sf", col_gray4, NULL };
|
|
||||||
static const char *termcmd[] = { "st", NULL };
|
|
||||||
|
|
||||||
#include "movestack.c"
|
|
||||||
static Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
|
||||||
{ MODKEY, XK_b, togglebar, {0} },
|
|
||||||
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
|
||||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
|
||||||
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_Return, zoom, {0} },
|
|
||||||
{ MODKEY, XK_Tab, view, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_x, killunsel, {0} },
|
|
||||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
|
||||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
|
||||||
{ MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
|
|
||||||
{ MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
|
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
|
||||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
|
||||||
{ MODKEY|ControlMask, XK_comma, tagallmon, {.i = -1 } },
|
|
||||||
{ MODKEY|ControlMask, XK_period, tagallmon, {.i = +1 } },
|
|
||||||
TAGKEYS( XK_1, 0)
|
|
||||||
TAGKEYS( XK_2, 1)
|
|
||||||
TAGKEYS( XK_3, 2)
|
|
||||||
TAGKEYS( XK_4, 3)
|
|
||||||
TAGKEYS( XK_5, 4)
|
|
||||||
TAGKEYS( XK_6, 5)
|
|
||||||
TAGKEYS( XK_7, 6)
|
|
||||||
TAGKEYS( XK_8, 7)
|
|
||||||
TAGKEYS( XK_9, 8)
|
|
||||||
{ KeyPress, MODKEY|ShiftMask, XK_q, quit, {0} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* button definitions */
|
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
|
||||||
static Button buttons[] = {
|
|
||||||
/* click event mask button function argument */
|
|
||||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
|
||||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
|
||||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
|
||||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
|
||||||
{ ClkTagBar, 0, Button1, view, {0} },
|
|
||||||
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
|
||||||
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
|
||||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
|
||||||
};
|
|
|
@ -1,41 +1,15 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||||
<html lang="en">
|
<!--
|
||||||
<head>
|
* Sample comment
|
||||||
<meta charset="UTF-8" />
|
-->
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<HTML>
|
||||||
<link href="css/style.css" rel="stylesheet" />
|
<head>
|
||||||
<title>GNU/Linux Doc</title>
|
<title>IntelliJ IDEA</title>
|
||||||
|
</head>
|
||||||
<div class="topnav">
|
<body>
|
||||||
<a class="active" href="#home">Home</a>
|
<h1>IntelliJ IDEA</h1>
|
||||||
<a href="#news">News</a>
|
<p><br><b><IMG border=0 height=12 src="images/hg.gif" width=18 >
|
||||||
<a href="#contact">Contact</a>
|
What is IntelliJ IDEA? · Α </b><br><br>
|
||||||
<a href="#about">About</a>
|
<custom-tag>hello</custom_tag>
|
||||||
</div>
|
</body>
|
||||||
|
|
||||||
<h1>
|
|
||||||
GNU/Linux
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<h5>
|
|
||||||
Posted on Wednesday, 12 May 2021
|
|
||||||
</h5>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- Page content -->
|
|
||||||
<div class="card level-3">
|
|
||||||
<h2>
|
|
||||||
"<b>GNU/Linux</b> and the family of operating systems made from the GNU
|
|
||||||
system, developed by the same project, introduced the Linux
|
|
||||||
kernel. It is one of the most well-known examples of free
|
|
||||||
software and open source <em>software</em>: according to proprietary
|
|
||||||
operating systems such as Windows and Mac OS, all source code is
|
|
||||||
available to the public and the world can freely use, change and
|
|
||||||
redistribute."
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<img src="https://www.nicepng.com/png/full/201-2015470_gnu-tux-gnu-linux-logo-png.png" alt="GNU/Linux" class="center">
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,77 +1,66 @@
|
||||||
package project1.ui;
|
/* Block comment */
|
||||||
|
|
||||||
import static project1.umethods.SleepTime.*;
|
import java.util.Date;
|
||||||
import static project1.umethods.ScreenManipulation.*;
|
|
||||||
|
|
||||||
import java.util.Scanner;
|
import static AnInterface.CONSTANT;
|
||||||
import project1.ui.PatientMenu;
|
import static java.util.Date.parse;
|
||||||
import project1.ui.DoctorMenu;
|
import static SomeClass.staticField;
|
||||||
import project1.ui.authentication.AuthenticationMenu;
|
|
||||||
|
|
||||||
enum Months { //"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
|
|
||||||
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE,
|
|
||||||
JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UIMenu
|
* Doc comment here for <code>SomeClass</code>
|
||||||
|
*
|
||||||
|
* @param T type parameter
|
||||||
|
* @see Math#sin(double)
|
||||||
*/
|
*/
|
||||||
public class UIMenu {
|
@Annotation(name = value)
|
||||||
|
public class SomeClass<T extends Runnable> { // some comment
|
||||||
|
private T field = null;
|
||||||
|
private double unusedField = 12345.67890;
|
||||||
|
private UnknownType anotherString = "Another\nStrin\g";
|
||||||
|
public static int staticField = 0;
|
||||||
|
public final int instanceFinalField = 0;
|
||||||
|
protected final int protectedField = 0;
|
||||||
|
final int packagePrivateField = 0;
|
||||||
|
|
||||||
//months is not a var, is a constant becuase of `final`
|
/**
|
||||||
public static final int year = 2021;
|
* Semantic highlighting:
|
||||||
|
* Generated spectrum to pick colors for local variables and parameters:
|
||||||
public static void showMenu(){
|
* Color#1 SC1.1 SC1.2 SC1.3 SC1.4 Color#2 SC2.1 SC2.2 SC2.3 SC2.4 Color#3
|
||||||
Scanner keyboard = new Scanner(System.in);
|
* Color#3 SC3.1 SC3.2 SC3.3 SC3.4 Color#4 SC4.1 SC4.2 SC4.3 SC4.4 Color#5
|
||||||
int uResponse = 0;
|
*
|
||||||
String test = "";
|
* @param param1
|
||||||
|
* @param param2
|
||||||
do {
|
* @param param3
|
||||||
System.out.printf("\t----Menu----\n\n");
|
*/
|
||||||
int time = 50;
|
public SomeClass(AnInterface param1,
|
||||||
sleepText("1) Doctors", time); sleepText("2) Patient", time); sleepText("0) Exit", time);
|
int param2,
|
||||||
System.out.printf("\nType here 👉 ");
|
int param3) {
|
||||||
|
int reassignedValue = this.staticField + param2 + param3;
|
||||||
do {
|
long localVar1, localVar2, localVar3, localVar4;
|
||||||
try {
|
int localVar = "IntelliJ"; // Error, incompatible types
|
||||||
try {
|
System.out.println(anotherString + toString() + localVar);
|
||||||
test = keyboard.nextLine(); //receive whatever input
|
int sum = protectedField + packagePrivateField + staticField;
|
||||||
if (test.isEmpty()) {
|
long time = parse("1.2.3"); // Method is deprecated
|
||||||
throw new NullPointerException("var is empty");
|
new Thread().countStackFrames(); // Method is deprecated and marked for removal
|
||||||
} else {
|
reassignedValue++;
|
||||||
sleepFor(500);
|
field.run();
|
||||||
uResponse = Integer.parseInt(test); //parse that input into an Integer (not an int)
|
new SomeClass() {
|
||||||
break;
|
{
|
||||||
}
|
int a = localVar;
|
||||||
} catch(NullPointerException e) {
|
}
|
||||||
System.out.printf("\nRemember you must type at least ony number from 0-2\n"); showMenu();
|
};
|
||||||
}
|
int[] l = new ArrayList<String>().toArray(new int[CONSTANT]);
|
||||||
} catch (NumberFormatException e) {
|
}
|
||||||
//TODO: handle exception
|
}
|
||||||
clearScreen();
|
|
||||||
System.out.printf("\n\nERROR (❌): this program only accepts integers\n\n");
|
enum AnEnum {CONST1, CONST2}
|
||||||
showMenu();
|
|
||||||
}
|
interface AnInterface {
|
||||||
} while (true);
|
int CONSTANT = 2;
|
||||||
|
|
||||||
switch (uResponse) {
|
void method();
|
||||||
case 0:
|
}
|
||||||
System.out.printf("Goodbye! Hope I helped!\n");
|
|
||||||
System.exit(0);
|
abstract class SomeAbstractClass {
|
||||||
break;
|
protected int instanceField = staticField;
|
||||||
case 1:
|
|
||||||
clearScreen();
|
|
||||||
if (AuthenticationMenu.startAuthMenu(1) == true) { DoctorMenu.showDoctorMenu(); } else { System.out.printf("Something went wrong :)\n"); }
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
clearScreen();
|
|
||||||
if (AuthenticationMenu.startAuthMenu(2) == true) { PatientMenu.showPatientMenu(); } else { System.out.printf("Something went wrong :)\n"); }
|
|
||||||
//PatientMenu.showPatientMenu();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
System.out.print("\033[H\033[2J"); System.out.flush();
|
|
||||||
System.out.printf("ERROR (❌): command not recognized\ntry again ↓\n");
|
|
||||||
}
|
|
||||||
} while (uResponse != 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
33
samples/javascript.js
Normal file
33
samples/javascript.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
var globalVar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for AjaxRequest class
|
||||||
|
* @param {string} url the url for the request<p/>
|
||||||
|
*/
|
||||||
|
function AjaxRequest(url) {
|
||||||
|
function local() {}
|
||||||
|
var urls = [ "www.cnn.com", 5, globalVar];
|
||||||
|
this.request = new XMLHttpRequest();
|
||||||
|
url = url.replace(/^\s*(.*)/, "$1"); // skip leading whitespace
|
||||||
|
/* check the url to be in urls */
|
||||||
|
var a = "\u1111\z\n\u11";
|
||||||
|
this.foo = new function() {};
|
||||||
|
foo();
|
||||||
|
#
|
||||||
|
var hello = () => console.log("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
@decorator()
|
||||||
|
class NameClass {
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module name{
|
||||||
|
declare export var exportedVar: string;
|
||||||
|
declare export function exportedFunction(): void;
|
||||||
|
declare export class ExportedClass {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyInterface { }
|
||||||
|
type FooBarAlias = string;
|
||||||
|
var html =`<div title='HTML injection'>Injected language fragment</div>`;
|
||||||
|
var x: MyInterface, y: string, z: FooBarAlias;
|
|
@ -1,28 +0,0 @@
|
||||||
const Generator = require("yeoman-generator")
|
|
||||||
const chalk = require('chalk')
|
|
||||||
const yosay = require("yosay")
|
|
||||||
|
|
||||||
module.exports = class extends Generator {
|
|
||||||
prompting() {
|
|
||||||
// have yeoman greet the user
|
|
||||||
this.log(chalk.red("Let\'s do this"))
|
|
||||||
|
|
||||||
const prompts = [{
|
|
||||||
message: 'Enter the excercise title',
|
|
||||||
worker: true,
|
|
||||||
action: null,
|
|
||||||
age: 123
|
|
||||||
}];
|
|
||||||
|
|
||||||
return this.prompt(prompts).then(props => {
|
|
||||||
// you can access them later
|
|
||||||
this.props = props
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function exclamate(message) {
|
|
||||||
return message + "!"
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(exclamate("lol"))
|
|
|
@ -1,88 +0,0 @@
|
||||||
import { SET_TOKEN } from "./authTypes";
|
|
||||||
|
|
||||||
function isJson(str) {
|
|
||||||
try {
|
|
||||||
JSON.parse(str);
|
|
||||||
} catch (e) {
|
|
||||||
//the json is not ok
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//the json is ok
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const login = async (data, dispatchToken) => {
|
|
||||||
const requestOptions = {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Accept: "application/json",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`http://127.0.0.1:8000/api/token`,
|
|
||||||
requestOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const res = await response.json();
|
|
||||||
window.localStorage.setItem("userToken", res.token);
|
|
||||||
dispatchToken({ type: SET_TOKEN, token: res.token });
|
|
||||||
return {
|
|
||||||
ok: true,
|
|
||||||
successMessage: "Login Successfull.",
|
|
||||||
errors: null,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const res = await response.json();
|
|
||||||
return {
|
|
||||||
ok: false,
|
|
||||||
successMessage: null,
|
|
||||||
errors: { password: res.errors["non_field_errors"] },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
alert(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const register = async (data, dispatchToken) => {
|
|
||||||
const requestOptions = {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
Accept: "application/json",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`http://127.0.0.1:8000/api/register`,
|
|
||||||
requestOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const res = await response.json();
|
|
||||||
window.localStorage.setItem("userToken", res.token);
|
|
||||||
dispatchToken({ type: SET_TOKEN, token: res.token });
|
|
||||||
return {
|
|
||||||
ok: true,
|
|
||||||
successMessage: "Register Successfull.",
|
|
||||||
errors: null,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const res = await response.json();
|
|
||||||
return {
|
|
||||||
ok: false,
|
|
||||||
successMessage: null,
|
|
||||||
errors: res["errors"],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
alert(error);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,24 +1,19 @@
|
||||||
{
|
{
|
||||||
"name": "Catppuccin",
|
// Line comments are not included in standard but nonetheless allowed.
|
||||||
"version": "1.0.0",
|
/* As well as block comments. */
|
||||||
"description": "JSON sample",
|
"the only keywords are": [
|
||||||
"main": "readme.md",
|
true,
|
||||||
"scripts": {
|
false,
|
||||||
"gulp": "gulp"
|
null
|
||||||
},
|
],
|
||||||
"devDependencies": {
|
"strings with": {
|
||||||
"gulp": "^4.0.2",
|
"no escapes": "pseudopolinomiality"
|
||||||
"browser-sync": "^2.27.5",
|
"valid escapes": "C-style\r\n and unicode\u0021",
|
||||||
"gulp-sass": "^5.0.0",
|
"illegal escapes": "\0377\x\"
|
||||||
"gulp-uglify-es": "^2.0.0",
|
},
|
||||||
"sass": "^1.35.1"
|
"some numbers": [
|
||||||
},
|
42,
|
||||||
"repository": {
|
-0.0e-0,
|
||||||
"type": "git",
|
6.626e-34
|
||||||
"url": "https://github.com/catppuccin/catppuccin"
|
]
|
||||||
},
|
|
||||||
"keywords": ["gulp", "pugjs", "sass", "coffeescript", "template"],
|
|
||||||
"author": "John Doe",
|
|
||||||
"license": "MIT",
|
|
||||||
"homepage": "https://github.com/catppuccin"
|
|
||||||
}
|
}
|
||||||
|
|
68
samples/kotlin.kt
Normal file
68
samples/kotlin.kt
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/* Block comment */
|
||||||
|
package hello
|
||||||
|
|
||||||
|
import kotlin.collections.* // line comment
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doc comment here for `SomeClass`
|
||||||
|
* @see Iterator#next()
|
||||||
|
*/
|
||||||
|
@Deprecated(message = "Deprecated class")
|
||||||
|
private class MyClass<out T : Iterable<T>>(var prop1: Int) {
|
||||||
|
fun foo(nullable: String?, r: Runnable, f: () -> Int, fl: FunctionLike, dyn: dynamic) {
|
||||||
|
println("length\nis ${nullable?.length} \e")
|
||||||
|
println(nullable!!.length)
|
||||||
|
val ints = java.util.ArrayList<Int?>(2)
|
||||||
|
ints[0] = 102 + f() + fl()
|
||||||
|
val myFun = { -> "" };
|
||||||
|
var ref = ints.size
|
||||||
|
ints.lastIndex + globalCounter
|
||||||
|
ints.forEach lit@{
|
||||||
|
if (it == null) return@lit
|
||||||
|
println(it + ref)
|
||||||
|
}
|
||||||
|
dyn.dynamicCall()
|
||||||
|
dyn.dynamicProp = 5
|
||||||
|
val klass = MyClass::class
|
||||||
|
val year = java.time.LocalDate.now().year
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return super.hashCode() * 31
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Int?.bar() {
|
||||||
|
if (this != null) {
|
||||||
|
println(message = toString())
|
||||||
|
} else {
|
||||||
|
println(this.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalCounter: Int = 5
|
||||||
|
get() = field
|
||||||
|
|
||||||
|
abstract class Abstract {
|
||||||
|
val bar get() = 1
|
||||||
|
fun test() {
|
||||||
|
bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Obj
|
||||||
|
|
||||||
|
enum class E { A, B }
|
||||||
|
|
||||||
|
interface FunctionLike {
|
||||||
|
operator fun invoke() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias Predicate<T> = (T) -> Boolean
|
||||||
|
|
||||||
|
fun baz(p: Predicate<Int>) = p(42)
|
||||||
|
|
||||||
|
suspend fun suspendCall() =
|
||||||
|
suspendFn()
|
||||||
|
|
||||||
|
suspend fun suspendFn() {}
|
|
@ -1,41 +1,27 @@
|
||||||
local M = {}
|
---@class Emmy
|
||||||
|
local var = {} -- a short comment
|
||||||
|
local a, b, c = true, false, nil
|
||||||
|
--region my class members region
|
||||||
|
|
||||||
local api
|
---@alias MyType Emmy
|
||||||
local line_text = { here = "hey" }
|
|
||||||
local test_tbl = {
|
|
||||||
num = 0,
|
|
||||||
bool = true,
|
|
||||||
str = "aye!",
|
|
||||||
something = line_text.here
|
|
||||||
}
|
|
||||||
|
|
||||||
--- @class example
|
--- doc comment
|
||||||
-- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean accumsan dapibus ex,
|
---@param par1 Par1Type @comments
|
||||||
-- duis tincidunt consectetur nisl at auctor. Mauris et dictum urna, ac maximus mi.
|
function var:fun(par1, par2)
|
||||||
function M:render(line_info, startline, endline)
|
print('hello')
|
||||||
startline = startline or 0
|
return self.len + 2
|
||||||
endline = endline or api.nvim_buf_line_count(self.buffer)
|
|
||||||
|
|
||||||
local lines = {}
|
|
||||||
|
|
||||||
for index, line in pairs(line_info) do
|
|
||||||
local line_no = index
|
|
||||||
local column = 1
|
|
||||||
|
|
||||||
if #line > 0 then
|
|
||||||
for _, segment in ipairs(line) do
|
|
||||||
table.insert(self.highlights, {
|
|
||||||
range = { line_no, column, #segment.text },
|
|
||||||
color_group = segment.color_group,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(lines, line_text)
|
|
||||||
end
|
|
||||||
|
|
||||||
api.nvim_buf_set_lines(self.buffer, startline, endline, true, lines)
|
|
||||||
self:_set_highlights()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
---@overload fun(name:string):Emmy
|
||||||
|
function var.staticFun()
|
||||||
|
end
|
||||||
|
--endregion end my class members region
|
||||||
|
|
||||||
|
---@return Emmy
|
||||||
|
function findEmmy()
|
||||||
|
return "string" .. var
|
||||||
|
end
|
||||||
|
|
||||||
|
globalVar = {
|
||||||
|
property = value
|
||||||
|
}
|
||||||
|
|
174
samples/markdown.md
Normal file
174
samples/markdown.md
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
Test Markdown document
|
||||||
|
======================
|
||||||
|
|
||||||
|
Text
|
||||||
|
----
|
||||||
|
|
||||||
|
Here is a paragraph with bold text. **This is some bold text.** Here is a
|
||||||
|
paragraph with bold text. __This is also some bold text.__
|
||||||
|
|
||||||
|
Here is another one with italic text. *This is some italic text.* Here is
|
||||||
|
another one with italic text. _This is some italic text._
|
||||||
|
|
||||||
|
Here is another one with struckout text. ~~This is some struckout text.~~
|
||||||
|
|
||||||
|
|
||||||
|
Links
|
||||||
|
-----
|
||||||
|
|
||||||
|
Autolink: <http://example.com>
|
||||||
|
|
||||||
|
Link: [Example](http://example.com)
|
||||||
|
|
||||||
|
Reference style [link][1].
|
||||||
|
|
||||||
|
[1]: http://example.com "Example"
|
||||||
|
|
||||||
|
|
||||||
|
Images
|
||||||
|
------
|
||||||
|
|
||||||
|
Image: ![My image](http://www.foo.bar/image.png)
|
||||||
|
|
||||||
|
Headers
|
||||||
|
-------
|
||||||
|
|
||||||
|
# First level title
|
||||||
|
|
||||||
|
## Second level title
|
||||||
|
|
||||||
|
### Third level title
|
||||||
|
|
||||||
|
#### Fourth level title
|
||||||
|
|
||||||
|
##### Fifth level title
|
||||||
|
|
||||||
|
###### Sixth level title
|
||||||
|
|
||||||
|
### Title with [link](http://localhost)
|
||||||
|
|
||||||
|
### Title with ![image](http://localhost)
|
||||||
|
|
||||||
|
Code
|
||||||
|
----
|
||||||
|
|
||||||
|
```
|
||||||
|
This
|
||||||
|
is
|
||||||
|
code
|
||||||
|
fence
|
||||||
|
```
|
||||||
|
|
||||||
|
Inline `code span in a` paragraph.
|
||||||
|
|
||||||
|
This is a code block:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the specified array into ascending numerical order.
|
||||||
|
*
|
||||||
|
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
|
||||||
|
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
|
||||||
|
* offers O(n log(n)) performance on many data sets that cause other
|
||||||
|
* quicksorts to degrade to quadratic performance, and is typically
|
||||||
|
* faster than traditional (one-pivot) Quicksort implementations.
|
||||||
|
*
|
||||||
|
* @param a the array to be sorted
|
||||||
|
*/
|
||||||
|
public static void sort(byte[] a) {
|
||||||
|
DualPivotQuicksort.sort(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quotes
|
||||||
|
------
|
||||||
|
|
||||||
|
> This is the first level of quoting.
|
||||||
|
>
|
||||||
|
> > This is nested blockquote.
|
||||||
|
>
|
||||||
|
> Back to the first level.
|
||||||
|
|
||||||
|
|
||||||
|
> A list within a blockquote:
|
||||||
|
>
|
||||||
|
> * asterisk 1
|
||||||
|
> * asterisk 2
|
||||||
|
> * asterisk 3
|
||||||
|
|
||||||
|
|
||||||
|
> Formatting within a blockquote:
|
||||||
|
>
|
||||||
|
> ### header
|
||||||
|
> Link: [Example](http://example.com)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Html
|
||||||
|
-------
|
||||||
|
|
||||||
|
This is inline <span>html</html>.
|
||||||
|
And this is an html block.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Column 1</th>
|
||||||
|
<th>Column 2</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Row 1 Cell 1</td>
|
||||||
|
<td>Row 1 Cell 2</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Row 2 Cell 1</td>
|
||||||
|
<td>Row 2 Cell 2</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
Horizontal rules
|
||||||
|
----------------
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
|
||||||
|
Lists
|
||||||
|
-----
|
||||||
|
|
||||||
|
Unordered list:
|
||||||
|
|
||||||
|
* asterisk 1
|
||||||
|
* asterisk 2
|
||||||
|
* asterisk 3
|
||||||
|
|
||||||
|
Ordered list:
|
||||||
|
|
||||||
|
1. First
|
||||||
|
2. Second
|
||||||
|
3. Third
|
||||||
|
|
||||||
|
Mixed:
|
||||||
|
|
||||||
|
1. First
|
||||||
|
2. Second:
|
||||||
|
|
||||||
|
* Fee
|
||||||
|
* Fie
|
||||||
|
* Foe
|
||||||
|
|
||||||
|
3. Third
|
||||||
|
|
||||||
|
Definition list:
|
||||||
|
|
||||||
|
Some term
|
||||||
|
: First definition
|
||||||
|
: Second definition
|
||||||
|
|
||||||
|
|
||||||
|
Tables:
|
||||||
|
|
||||||
|
| Header 1 | Header 2 |
|
||||||
|
| -------- | -------- |
|
||||||
|
| Data 1 | Data 2 |
|
|
@ -1,172 +1,32 @@
|
||||||
import sys
|
@decorator(param=1)
|
||||||
import os
|
def f(x):
|
||||||
import re
|
"""
|
||||||
|
Syntax Highlighting Demo
|
||||||
|
@param x Parameter
|
||||||
|
|
||||||
from i18n import _
|
Semantic highlighting:
|
||||||
|
Generated spectrum to pick colors for local variables and parameters:
|
||||||
|
Color#1 SC1.1 SC1.2 SC1.3 SC1.4 Color#2 SC2.1 SC2.2 SC2.3 SC2.4 Color#3
|
||||||
|
Color#3 SC3.1 SC3.2 SC3.3 SC3.4 Color#4 SC4.1 SC4.2 SC4.3 SC4.4 Color#5
|
||||||
|
"""
|
||||||
|
|
||||||
from importlib.machinery import SourceFileLoader
|
def nested_func(y):
|
||||||
|
print(y + 1)
|
||||||
|
|
||||||
|
s = ("Test", 2+3, {'a': 'b'}, f'{x!s:{"^10"}}') # Comment
|
||||||
|
f(s[0].lower())
|
||||||
|
nested_func(42)
|
||||||
|
|
||||||
class RubberStamp:
|
class Foo:
|
||||||
"""Howdy rubber stamp"""
|
tags: List[str]
|
||||||
|
|
||||||
UI_TEXT = "ui_text"
|
def __init__(self: Foo):
|
||||||
UI_SUBTEXT = "ui_subtext"
|
byte_string: bytes = b'newline:\n also newline:\x0a'
|
||||||
|
text_string = u"Cyrillic Я is \u042f. Oops: \u042g"
|
||||||
|
self.make_sense(whatever=1)
|
||||||
|
|
||||||
def set_ui_text(self, text, type=None):
|
def make_sense(self, whatever):
|
||||||
"""Convert an ui string to input howdy-gtk understands"""
|
self.sense = whatever
|
||||||
typedec = "M"
|
|
||||||
|
|
||||||
if type == self.UI_SUBTEXT:
|
x = len('abc')
|
||||||
typedec = "S"
|
print(f.__doc__)
|
||||||
|
|
||||||
return self.send_ui_raw(typedec + "=" + text)
|
|
||||||
|
|
||||||
def send_ui_raw(self, command):
|
|
||||||
"""Write raw command to howdy-gtk stdin"""
|
|
||||||
if self.config.getboolean("debug", "verbose_stamps", fallback=False):
|
|
||||||
print("Sending command to howdy-gtk: " + command)
|
|
||||||
|
|
||||||
# Add a newline because the ui reads per line
|
|
||||||
command += " \n"
|
|
||||||
if self.gtk_proc:
|
|
||||||
# Send the command as bytes
|
|
||||||
self.gtk_proc.stdin.write(bytearray(command.encode("utf-8")))
|
|
||||||
self.gtk_proc.stdin.flush()
|
|
||||||
|
|
||||||
def execute(config, gtk_proc, opencv):
|
|
||||||
verbose = config.getboolean("debug", "verbose_stamps", fallback=False)
|
|
||||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
installed_stamps = []
|
|
||||||
|
|
||||||
# Go through each file in the rubberstamp folder
|
|
||||||
for filename in os.listdir(dir_path):
|
|
||||||
# Remove non-readable file or directories
|
|
||||||
if not os.path.isfile(dir_path + "/" + filename):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Remove meta files
|
|
||||||
if filename in ["__init__.py", ".gitignore"]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Add the found file to the list of enabled rubberstamps
|
|
||||||
installed_stamps.append(filename.split(".")[0])
|
|
||||||
|
|
||||||
if verbose: print("Installed rubberstamps: " + ", ".join(installed_stamps))
|
|
||||||
|
|
||||||
# Get the rules defined in the config
|
|
||||||
raw_rules = config.get("rubberstamps", "stamp_rules")
|
|
||||||
rules = raw_rules.split("\n")
|
|
||||||
|
|
||||||
# Go through the rules one by one
|
|
||||||
for rule in rules:
|
|
||||||
rule = rule.strip()
|
|
||||||
|
|
||||||
if len(rule) <= 1:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Parse the rule with regex
|
|
||||||
regex_result = re.search("^(\w+)\s+([\w\.]+)\s+([a-z]+)(.*)?$", rule, re.IGNORECASE)
|
|
||||||
|
|
||||||
# Error out if the regex did not match (invalid line)
|
|
||||||
if not regex_result:
|
|
||||||
print(_("Error parsing rubberstamp rule: {}").format(rule))
|
|
||||||
continue
|
|
||||||
|
|
||||||
type = regex_result.group(1)
|
|
||||||
|
|
||||||
# Error out if the stamp name in the rule is not a file
|
|
||||||
if type not in installed_stamps:
|
|
||||||
print(_("Stamp not installed: {}").format(type))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Load the module from file
|
|
||||||
module = SourceFileLoader(type, dir_path + "/" + type + ".py").load_module()
|
|
||||||
|
|
||||||
# Try to get the class with the same name
|
|
||||||
try:
|
|
||||||
constructor = getattr(module, type)
|
|
||||||
except AttributeError:
|
|
||||||
print(_("Stamp error: Class {} not found").format(type))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Init the class and set common values
|
|
||||||
instance = constructor()
|
|
||||||
instance.verbose = verbose
|
|
||||||
instance.config = config
|
|
||||||
instance.gtk_proc = gtk_proc
|
|
||||||
instance.opencv = opencv
|
|
||||||
|
|
||||||
# Set some opensv shorthands
|
|
||||||
instance.video_capture = opencv["video_capture"]
|
|
||||||
instance.face_detector = opencv["face_detector"]
|
|
||||||
instance.pose_predictor = opencv["pose_predictor"]
|
|
||||||
instance.clahe = opencv["clahe"]
|
|
||||||
|
|
||||||
# Parse and set the 2 required options for all rubberstamps
|
|
||||||
instance.options = {
|
|
||||||
"timeout": float(re.sub("[a-zA-Z]", "", regex_result.group(2))),
|
|
||||||
"failsafe": regex_result.group(3) != "faildeadly"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try to get the class do declare its other config variables
|
|
||||||
try:
|
|
||||||
instance.declare_config()
|
|
||||||
except Exception:
|
|
||||||
print(_("Internal error in rubberstamp configuration declaration:"))
|
|
||||||
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Split the optional arguments at the end of the rule by spaces
|
|
||||||
raw_options = regex_result.group(4).split()
|
|
||||||
|
|
||||||
# For each of those aoptional arguments
|
|
||||||
for option in raw_options:
|
|
||||||
# Get the key to the left, and the value to the right of the equal sign
|
|
||||||
key, value = option.split("=")
|
|
||||||
|
|
||||||
# Error out if a key has been set that was not declared by the module before
|
|
||||||
if key not in instance.options:
|
|
||||||
print("Unknow config option for rubberstamp " + type + ": " + key)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Convert the argument string to an int or float if the declared option has that type
|
|
||||||
if isinstance(instance.options[key], int):
|
|
||||||
value = int(value)
|
|
||||||
elif isinstance(instance.options[key], float):
|
|
||||||
value = float(value)
|
|
||||||
|
|
||||||
instance.options[key] = value
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
print("Stamp \"" + type + "\" options parsed:")
|
|
||||||
print(instance.options)
|
|
||||||
print("Executing stamp")
|
|
||||||
|
|
||||||
# Make the stamp fail by default
|
|
||||||
result = False
|
|
||||||
|
|
||||||
# Run the stamp code
|
|
||||||
try:
|
|
||||||
result = instance.run()
|
|
||||||
except Exception:
|
|
||||||
print(_("Internal error in rubberstamp:"))
|
|
||||||
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if verbose: print("Stamp \"" + type + "\" returned: " + str(result))
|
|
||||||
|
|
||||||
# Abort authentication if the stamp returned false
|
|
||||||
if result is False:
|
|
||||||
if verbose: print("Authentication aborted by rubber stamp")
|
|
||||||
sys.exit(14)
|
|
||||||
|
|
||||||
# This is outside the for loop, so we've run all the rules
|
|
||||||
if verbose: print("All rubberstamps processed, authentication successful")
|
|
||||||
|
|
||||||
# Exit with no errors
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
|
@ -1,815 +0,0 @@
|
||||||
# source: https://github.com/gornostal/Modific
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import sublime
|
|
||||||
import sublime_plugin
|
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
import subprocess
|
|
||||||
import functools
|
|
||||||
import re
|
|
||||||
from copy import copy
|
|
||||||
|
|
||||||
IS_ST3 = sublime.version().startswith('3') or sublime.version().startswith('4')
|
|
||||||
|
|
||||||
|
|
||||||
def get_settings():
|
|
||||||
return sublime.load_settings("Modific.sublime-settings")
|
|
||||||
|
|
||||||
|
|
||||||
def get_vcs_settings():
|
|
||||||
"""
|
|
||||||
Returns list of dictionaries
|
|
||||||
each dict. represents settings for VCS
|
|
||||||
"""
|
|
||||||
|
|
||||||
default = [
|
|
||||||
{"name": "git", "dir": ".git", "cmd": "git"},
|
|
||||||
{"name": "svn", "dir": ".svn", "cmd": "svn"},
|
|
||||||
{"name": "bzr", "dir": ".bzr", "cmd": "bzr"},
|
|
||||||
{"name": "hg", "dir": ".hg", "cmd": "hg"},
|
|
||||||
{"name": "tf", "dir": "$tf", "cmd": "C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/TF.exe"}
|
|
||||||
]
|
|
||||||
settings = get_settings().get('vcs', default)
|
|
||||||
|
|
||||||
# re-format settings array if user has old format of settings
|
|
||||||
if type(settings[0]) == list:
|
|
||||||
settings = [dict(name=name, cmd=cmd, dir='.'+name) for name, cmd in settings]
|
|
||||||
|
|
||||||
return settings
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_command(vcs_name):
|
|
||||||
"""
|
|
||||||
Returns command that user specified for vcs_name
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
return [vcs['cmd'] for vcs in get_vcs_settings() if vcs.get('name') == vcs_name][0]
|
|
||||||
except IndexError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def tfs_root(directory):
|
|
||||||
try:
|
|
||||||
tf_cmd = get_user_command('tf') or 'tf'
|
|
||||||
command = [tf_cmd, 'workfold', directory]
|
|
||||||
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
||||||
shell=True, universal_newlines=False)
|
|
||||||
out, err = p.communicate()
|
|
||||||
m = re.search(r"^ \$\S+: (\S+)$", out, re.MULTILINE)
|
|
||||||
if m:
|
|
||||||
return {'root': m.group(1), 'name': 'tf', 'cmd': tf_cmd}
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_vcs(directory):
|
|
||||||
"""
|
|
||||||
Determines root directory for VCS and which of VCS systems should be used for a given directory
|
|
||||||
Returns dictionary {name: .., root: .., cmd: .., dir: ..}
|
|
||||||
"""
|
|
||||||
|
|
||||||
vcs_check = [(lambda vcs: lambda dir: os.path.exists(os.path.join(dir, vcs.get('dir', False)))
|
|
||||||
and vcs)(vcs) for vcs in get_vcs_settings()]
|
|
||||||
|
|
||||||
start_directory = directory
|
|
||||||
while directory:
|
|
||||||
available = list(filter(bool, [check(directory) for check in vcs_check]))
|
|
||||||
if available:
|
|
||||||
available[0]['root'] = directory
|
|
||||||
return available[0]
|
|
||||||
|
|
||||||
parent = os.path.realpath(os.path.join(directory, os.path.pardir))
|
|
||||||
if parent == directory: # /.. == /
|
|
||||||
# try TFS as a last resort
|
|
||||||
# I'm not sure why we need to do this. Seems like it should find root for TFS in the main loop
|
|
||||||
return tfs_root(start_directory)
|
|
||||||
directory = parent
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def main_thread(callback, *args, **kwargs):
|
|
||||||
# sublime.set_timeout gets used to send things onto the main thread
|
|
||||||
# most sublime.[something] calls need to be on the main thread
|
|
||||||
sublime.set_timeout(functools.partial(callback, *args, **kwargs), 0)
|
|
||||||
|
|
||||||
|
|
||||||
def _make_text_safeish(text, fallback_encoding, method='decode'):
|
|
||||||
# The unicode decode here is because sublime converts to unicode inside
|
|
||||||
# insert in such a way that unknown characters will cause errors, which is
|
|
||||||
# distinctly non-ideal... and there's no way to tell what's coming out of
|
|
||||||
# git in output. So...
|
|
||||||
try:
|
|
||||||
unitext = getattr(text, method)('utf-8')
|
|
||||||
except (UnicodeEncodeError, UnicodeDecodeError):
|
|
||||||
unitext = getattr(text, method)(fallback_encoding)
|
|
||||||
except AttributeError:
|
|
||||||
# strongly implies we're already unicode, but just in case let's cast
|
|
||||||
# to string
|
|
||||||
unitext = str(text)
|
|
||||||
return unitext
|
|
||||||
|
|
||||||
|
|
||||||
def do_when(conditional, callback, *args, **kwargs):
|
|
||||||
if conditional():
|
|
||||||
return callback(*args, **kwargs)
|
|
||||||
sublime.set_timeout(functools.partial(do_when, conditional, callback, *args, **kwargs), 50)
|
|
||||||
|
|
||||||
|
|
||||||
def log(*args, **kwargs):
|
|
||||||
"""
|
|
||||||
@param *args: string arguments that should be logged to console
|
|
||||||
@param debug=True: debug log mode
|
|
||||||
@param settings=None: instance of sublime.Settings
|
|
||||||
"""
|
|
||||||
debug = kwargs.get('debug', True)
|
|
||||||
settings = kwargs.get('settings', None)
|
|
||||||
|
|
||||||
if not settings:
|
|
||||||
settings = get_settings()
|
|
||||||
|
|
||||||
if debug and not settings.get('debug', False):
|
|
||||||
return
|
|
||||||
|
|
||||||
print('Modific:', *args)
|
|
||||||
|
|
||||||
|
|
||||||
class CommandThread(threading.Thread):
|
|
||||||
|
|
||||||
def __init__(self, command, on_done, working_dir="", fallback_encoding="", console_encoding="", **kwargs):
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
self.command = command
|
|
||||||
self.on_done = on_done
|
|
||||||
self.working_dir = working_dir
|
|
||||||
if 'stdin' in kwargs:
|
|
||||||
self.stdin = kwargs['stdin'].encode()
|
|
||||||
else:
|
|
||||||
self.stdin = None
|
|
||||||
self.stdout = kwargs.get('stdout', subprocess.PIPE)
|
|
||||||
self.console_encoding = console_encoding
|
|
||||||
self.fallback_encoding = fallback_encoding
|
|
||||||
self.kwargs = kwargs
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
try:
|
|
||||||
# Per http://bugs.python.org/issue8557 shell=True is required to
|
|
||||||
# get $PATH on Windows. Yay portable code.
|
|
||||||
shell = os.name == 'nt'
|
|
||||||
|
|
||||||
if self.console_encoding:
|
|
||||||
self.command = [s.encode(self.console_encoding) for s in self.command]
|
|
||||||
|
|
||||||
proc = subprocess.Popen(self.command,
|
|
||||||
stdout=self.stdout, stderr=subprocess.STDOUT,
|
|
||||||
stdin=subprocess.PIPE,
|
|
||||||
cwd=self.working_dir if self.working_dir != '' else None,
|
|
||||||
shell=shell, universal_newlines=False)
|
|
||||||
output = proc.communicate(self.stdin)[0]
|
|
||||||
if not output:
|
|
||||||
output = ''
|
|
||||||
# if sublime's python gets bumped to 2.7 we can just do:
|
|
||||||
# output = subprocess.check_output(self.command)
|
|
||||||
main_thread(self.on_done,
|
|
||||||
_make_text_safeish(output, self.fallback_encoding), **self.kwargs)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
main_thread(self.on_done, e.returncode)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == 2:
|
|
||||||
main_thread(sublime.error_message,
|
|
||||||
"'%s' binary could not be found in PATH\n\nConsider using `vcs` property to specify PATH\n\nPATH is: %s" % (self.command[0], os.environ['PATH']))
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
|
|
||||||
class EditViewCommand(sublime_plugin.TextCommand):
|
|
||||||
|
|
||||||
def run(self, edit, command=None, output='', begin=0, region=None):
|
|
||||||
"""
|
|
||||||
For some reason Sublime's view.run_command() doesn't allow to pass tuples,
|
|
||||||
therefore region must be a list
|
|
||||||
"""
|
|
||||||
region = sublime.Region(int(region[0]), int(region[1])) if region else None
|
|
||||||
if command == 'insert':
|
|
||||||
self.view.insert(edit, int(begin), output)
|
|
||||||
elif command == 'replace':
|
|
||||||
self.view.replace(edit, region, output)
|
|
||||||
elif command == 'erase':
|
|
||||||
self.view.erase(edit, region)
|
|
||||||
else:
|
|
||||||
print('Invalid command: ', command)
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
class VcsCommand(object):
|
|
||||||
may_change_files = False
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.settings = get_settings()
|
|
||||||
super(VcsCommand, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def log(self, *args, **kwargs):
|
|
||||||
return log(settings=self.settings, *args, **kwargs)
|
|
||||||
|
|
||||||
def run_command(self, command, callback=None, show_status=False,
|
|
||||||
filter_empty_args=True, **kwargs):
|
|
||||||
if filter_empty_args:
|
|
||||||
command = [arg for arg in command if arg]
|
|
||||||
if 'working_dir' not in kwargs:
|
|
||||||
kwargs['working_dir'] = self.get_working_dir()
|
|
||||||
if 'fallback_encoding' not in kwargs and self.active_view() and self.active_view().settings().get('fallback_encoding'):
|
|
||||||
kwargs['fallback_encoding'] = self.active_view().settings().get('fallback_encoding').rpartition('(')[2].rpartition(')')[0]
|
|
||||||
kwargs['console_encoding'] = self.settings.get('console_encoding')
|
|
||||||
|
|
||||||
autosave = self.settings.get('autosave', True)
|
|
||||||
if self.active_view() and self.active_view().is_dirty() and autosave:
|
|
||||||
self.active_view().run_command('save')
|
|
||||||
if not callback:
|
|
||||||
callback = self.generic_done
|
|
||||||
|
|
||||||
log('run command:', ' '.join(command))
|
|
||||||
thread = CommandThread(command, callback, **kwargs)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
if show_status:
|
|
||||||
message = kwargs.get('status_message', False) or ' '.join(command)
|
|
||||||
sublime.status_message(message + 'wef')
|
|
||||||
|
|
||||||
def generic_done(self, result):
|
|
||||||
self.log('generic_done', result)
|
|
||||||
if self.may_change_files and self.active_view() and self.active_view().file_name():
|
|
||||||
if self.active_view().is_dirty():
|
|
||||||
result = "WARNING: Current view is dirty.\n\n"
|
|
||||||
else:
|
|
||||||
# just asking the current file to be re-opened doesn't do anything
|
|
||||||
print("reverting")
|
|
||||||
position = self.active_view().viewport_position()
|
|
||||||
self.active_view().run_command('revert')
|
|
||||||
do_when(lambda: not self.active_view().is_loading(),
|
|
||||||
lambda: self.active_view().set_viewport_position(position, False))
|
|
||||||
|
|
||||||
if not result.strip():
|
|
||||||
return
|
|
||||||
self.panel(result)
|
|
||||||
|
|
||||||
def _output_to_view(self, output_file, output, clear=False,
|
|
||||||
syntax="Packages/Diff/Diff.tmLanguage"):
|
|
||||||
output_file.set_syntax_file(syntax)
|
|
||||||
if clear:
|
|
||||||
output_file.run_command('edit_view', dict(command='replace', region=[0, self.output_view.size()], output=output))
|
|
||||||
else:
|
|
||||||
output_file.run_command('edit_view', dict(command='insert', output=output))
|
|
||||||
|
|
||||||
def scratch(self, output, title=False, position=None, **kwargs):
|
|
||||||
scratch_file = self.get_window().new_file()
|
|
||||||
if title:
|
|
||||||
scratch_file.set_name(title)
|
|
||||||
scratch_file.set_scratch(True)
|
|
||||||
self._output_to_view(scratch_file, output, **kwargs)
|
|
||||||
scratch_file.set_read_only(True)
|
|
||||||
if position:
|
|
||||||
sublime.set_timeout(lambda: scratch_file.set_viewport_position(position), 0)
|
|
||||||
return scratch_file
|
|
||||||
|
|
||||||
def panel(self, output, **kwargs):
|
|
||||||
if not hasattr(self, 'output_view'):
|
|
||||||
self.output_view = self.get_window().get_output_panel("vcs")
|
|
||||||
self.output_view.set_read_only(False)
|
|
||||||
self._output_to_view(self.output_view, output, clear=True, **kwargs)
|
|
||||||
self.output_view.set_read_only(True)
|
|
||||||
self.get_window().run_command("show_panel", {"panel": "output.vcs"})
|
|
||||||
|
|
||||||
def _active_file_name(self):
|
|
||||||
view = self.active_view()
|
|
||||||
if view and view.file_name() and len(view.file_name()) > 0:
|
|
||||||
return view.file_name()
|
|
||||||
|
|
||||||
def active_view(self):
|
|
||||||
return self.view
|
|
||||||
|
|
||||||
def get_window(self):
|
|
||||||
if (hasattr(self, 'view') and hasattr(self.view, 'window')):
|
|
||||||
return self.view.window()
|
|
||||||
else:
|
|
||||||
return sublime.active_window()
|
|
||||||
|
|
||||||
def get_working_dir(self):
|
|
||||||
return os.path.dirname(self._active_file_name())
|
|
||||||
|
|
||||||
def is_enabled(self):
|
|
||||||
file_name = self._active_file_name()
|
|
||||||
if file_name and os.path.exists(file_name):
|
|
||||||
return bool(get_vcs(self.get_working_dir()))
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class DiffCommand(VcsCommand):
|
|
||||||
""" Here you can define diff commands for your VCS
|
|
||||||
method name pattern: %(vcs_name)s_diff_command
|
|
||||||
"""
|
|
||||||
|
|
||||||
def run(self, edit):
|
|
||||||
vcs = get_vcs(self.get_working_dir())
|
|
||||||
filepath = self.view.file_name()
|
|
||||||
filename = os.path.basename(filepath)
|
|
||||||
max_file_size = self.settings.get('max_file_size', 1024) * 1024
|
|
||||||
if not os.path.exists(filepath) or os.path.getsize(filepath) > max_file_size:
|
|
||||||
# skip large files
|
|
||||||
return
|
|
||||||
get_command = getattr(self, '{0}_diff_command'.format(vcs['name']), None)
|
|
||||||
if get_command:
|
|
||||||
self.run_command(get_command(filename), self.diff_done)
|
|
||||||
|
|
||||||
def diff_done(self, result):
|
|
||||||
self.log('diff_done', result)
|
|
||||||
|
|
||||||
def git_diff_command(self, file_name):
|
|
||||||
vcs_options = self.settings.get('vcs_options', {}).get('git') or ['--no-color', '--no-ext-diff']
|
|
||||||
return [get_user_command('git') or 'git', 'diff'] + vcs_options + ['--', file_name]
|
|
||||||
|
|
||||||
def svn_diff_command(self, file_name):
|
|
||||||
params = [get_user_command('svn') or 'svn', 'diff']
|
|
||||||
params.extend(self.settings.get('vcs_options', {}).get('svn', []))
|
|
||||||
|
|
||||||
if '--internal-diff' not in params and self.settings.get('svn_use_internal_diff', True):
|
|
||||||
params.append('--internal-diff')
|
|
||||||
|
|
||||||
# if file starts with @, use `--revision HEAD` option
|
|
||||||
# https://github.com/gornostal/Modific/issues/17
|
|
||||||
if file_name.find('@') != -1:
|
|
||||||
file_name += '@'
|
|
||||||
params.extend(['--revision', 'HEAD'])
|
|
||||||
|
|
||||||
params.append(file_name)
|
|
||||||
return params
|
|
||||||
|
|
||||||
def bzr_diff_command(self, file_name):
|
|
||||||
vcs_options = self.settings.get('vcs_options', {}).get('bzr', [])
|
|
||||||
return [get_user_command('bzr') or 'bzr', 'diff'] + vcs_options + [file_name]
|
|
||||||
|
|
||||||
def hg_diff_command(self, file_name):
|
|
||||||
vcs_options = self.settings.get('vcs_options', {}).get('hg', [])
|
|
||||||
return [get_user_command('hg') or 'hg', 'diff'] + vcs_options + [file_name]
|
|
||||||
|
|
||||||
def tf_diff_command(self, file_name):
|
|
||||||
vcs_options = self.settings.get('vcs_options', {}).get('tf') or ['-format:unified']
|
|
||||||
return [get_user_command('tf') or 'tf', 'diff'] + vcs_options + [file_name]
|
|
||||||
|
|
||||||
def get_line_ending(self):
|
|
||||||
return '\n'
|
|
||||||
|
|
||||||
def join_lines(self, lines):
|
|
||||||
"""
|
|
||||||
Join lines using os.linesep.join(), unless another method is specified in ST settings
|
|
||||||
"""
|
|
||||||
return self.get_line_ending().join(lines)
|
|
||||||
|
|
||||||
|
|
||||||
class ShowDiffCommand(DiffCommand, sublime_plugin.TextCommand):
|
|
||||||
def diff_done(self, result):
|
|
||||||
self.log('on show_diff', result)
|
|
||||||
|
|
||||||
if not result.strip():
|
|
||||||
return
|
|
||||||
|
|
||||||
result = result.replace('\r\n', '\n')
|
|
||||||
file_name = re.findall(r'([^\\\/]+)$', self.view.file_name())
|
|
||||||
scratch = self.scratch(result, title="Diff - " + file_name[0])
|
|
||||||
|
|
||||||
# Select the line in the diff output where the cursor is located.
|
|
||||||
point = self.view.sel()[0].b
|
|
||||||
region = self.view.line(point)
|
|
||||||
line = self.view.substr(region)
|
|
||||||
|
|
||||||
region = scratch.find(line, 0, sublime.LITERAL)
|
|
||||||
scratch.show_at_center(region)
|
|
||||||
scratch.sel().clear()
|
|
||||||
# Place the cursor at the beginning of the line
|
|
||||||
scratch.sel().add(scratch.line(region).a)
|
|
||||||
|
|
||||||
|
|
||||||
class DiffParser(object):
|
|
||||||
instance = None
|
|
||||||
|
|
||||||
def __init__(self, diff):
|
|
||||||
self.diff = diff
|
|
||||||
self.chunks = None
|
|
||||||
self.__class__.instance = self
|
|
||||||
|
|
||||||
def _append_to_chunks(self, start, lines):
|
|
||||||
self.chunks.append({
|
|
||||||
"start": start,
|
|
||||||
"end": start + len(lines),
|
|
||||||
"lines": lines
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_chunks(self):
|
|
||||||
if self.chunks is None:
|
|
||||||
self.chunks = []
|
|
||||||
diff = self.diff.strip()
|
|
||||||
if diff:
|
|
||||||
re_header = re.compile(r'^@@[0-9\-, ]+\+(\d+)', re.S)
|
|
||||||
current = None
|
|
||||||
lines = []
|
|
||||||
for line in diff.splitlines():
|
|
||||||
# ignore lines with '\' at the beginning
|
|
||||||
if line.startswith('\\'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
matches = re.findall(re_header, line)
|
|
||||||
if matches:
|
|
||||||
if current is not None:
|
|
||||||
self._append_to_chunks(current, lines)
|
|
||||||
current = int(matches[0])
|
|
||||||
lines = []
|
|
||||||
elif current:
|
|
||||||
lines.append(line)
|
|
||||||
if current is not None and lines:
|
|
||||||
self._append_to_chunks(current, lines)
|
|
||||||
|
|
||||||
return self.chunks
|
|
||||||
|
|
||||||
def get_lines_to_hl(self):
|
|
||||||
inserted = []
|
|
||||||
changed = []
|
|
||||||
deleted = []
|
|
||||||
|
|
||||||
for chunk in self.get_chunks():
|
|
||||||
current = chunk['start']
|
|
||||||
deleted_line = None
|
|
||||||
for line in chunk['lines']:
|
|
||||||
if line.startswith('-'):
|
|
||||||
if (not deleted_line or deleted_line not in deleted):
|
|
||||||
deleted.append(current)
|
|
||||||
deleted_line = current
|
|
||||||
elif line.startswith('+'):
|
|
||||||
if deleted_line:
|
|
||||||
deleted.pop()
|
|
||||||
deleted_line = None
|
|
||||||
changed.append(current)
|
|
||||||
elif current - 1 in changed:
|
|
||||||
changed.append(current)
|
|
||||||
else:
|
|
||||||
inserted.append(current)
|
|
||||||
current += 1
|
|
||||||
else:
|
|
||||||
deleted_line = None
|
|
||||||
current += 1
|
|
||||||
|
|
||||||
return inserted, changed, deleted
|
|
||||||
|
|
||||||
def get_original_part(self, line_num):
|
|
||||||
""" returns a chunk of code that relates to the given line
|
|
||||||
and was there before modifications
|
|
||||||
return (lines list, start_line int, replace_lines int)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# for each chunk from diff:
|
|
||||||
for chunk in self.get_chunks():
|
|
||||||
# if line_num is within that chunk
|
|
||||||
if chunk['start'] <= line_num <= chunk['end']:
|
|
||||||
ret_lines = []
|
|
||||||
current = chunk['start'] # line number that corresponds to current version of file
|
|
||||||
first = None # number of the first line to change
|
|
||||||
replace_lines = 0 # number of lines to change
|
|
||||||
return_this_lines = False # flag shows whether we can return accumulated lines
|
|
||||||
for line in chunk['lines']:
|
|
||||||
if line.startswith('-') or line.startswith('+'):
|
|
||||||
first = first or current
|
|
||||||
if current == line_num:
|
|
||||||
return_this_lines = True
|
|
||||||
if line.startswith('-'):
|
|
||||||
# if line starts with '-' we have previous version
|
|
||||||
ret_lines.append(line[1:])
|
|
||||||
else:
|
|
||||||
# if line starts with '+' we only increment numbers
|
|
||||||
replace_lines += 1
|
|
||||||
current += 1
|
|
||||||
elif return_this_lines:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# gap between modifications
|
|
||||||
# reset our variables
|
|
||||||
current += 1
|
|
||||||
first = current
|
|
||||||
replace_lines = 0
|
|
||||||
ret_lines = []
|
|
||||||
if return_this_lines:
|
|
||||||
return ret_lines, first, replace_lines
|
|
||||||
|
|
||||||
return None, None, None
|
|
||||||
|
|
||||||
|
|
||||||
class HlChangesCommand(DiffCommand, sublime_plugin.TextCommand):
|
|
||||||
def hl_lines(self, lines, hl_key):
|
|
||||||
if (not len(lines) or not self.settings.get('highlight_changes')):
|
|
||||||
self.view.erase_regions(hl_key)
|
|
||||||
return
|
|
||||||
|
|
||||||
icon = self.settings.get('region_icon') or 'modific'
|
|
||||||
if icon == 'none':
|
|
||||||
return
|
|
||||||
|
|
||||||
if icon == 'modific':
|
|
||||||
if IS_ST3:
|
|
||||||
icon = 'Packages/Modific/icons/' + hl_key + '.png'
|
|
||||||
else:
|
|
||||||
icon = '../Modific/icons/' + hl_key
|
|
||||||
points = [self.view.text_point(l - 1, 0) for l in lines]
|
|
||||||
regions = [sublime.Region(p, p) for p in points]
|
|
||||||
self.view.add_regions(hl_key, regions, "markup.%s.diff" % hl_key, icon, sublime.HIDDEN | sublime.DRAW_EMPTY)
|
|
||||||
|
|
||||||
def diff_done(self, diff):
|
|
||||||
self.log('on hl_changes:', diff)
|
|
||||||
|
|
||||||
if diff and '@@' not in diff:
|
|
||||||
# probably this is an error message
|
|
||||||
# if print raise UnicodeEncodeError, try to encode string to utf-8 (issue #35)
|
|
||||||
try:
|
|
||||||
print(diff)
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
print(diff.encode('utf-8'))
|
|
||||||
|
|
||||||
diff_parser = DiffParser(diff)
|
|
||||||
(inserted, changed, deleted) = diff_parser.get_lines_to_hl()
|
|
||||||
|
|
||||||
self.log('new lines:', inserted)
|
|
||||||
self.log('modified lines:', changed)
|
|
||||||
self.log('deleted lines:', deleted)
|
|
||||||
|
|
||||||
self.hl_lines(inserted, 'inserted')
|
|
||||||
self.hl_lines(deleted, 'deleted')
|
|
||||||
self.hl_lines(changed, 'changed')
|
|
||||||
|
|
||||||
|
|
||||||
class ShowOriginalPartCommand(DiffCommand, sublime_plugin.TextCommand):
|
|
||||||
def run(self, edit):
|
|
||||||
diff_parser = DiffParser.instance
|
|
||||||
if not diff_parser:
|
|
||||||
return
|
|
||||||
|
|
||||||
(row, col) = self.view.rowcol(self.view.sel()[0].begin())
|
|
||||||
(lines, start, replace_lines) = diff_parser.get_original_part(row + 1)
|
|
||||||
if lines is not None:
|
|
||||||
self.panel(self.join_lines(lines))
|
|
||||||
|
|
||||||
|
|
||||||
class ReplaceModifiedPartCommand(DiffCommand, sublime_plugin.TextCommand):
|
|
||||||
def run(self, edit):
|
|
||||||
self.view.run_command('save')
|
|
||||||
|
|
||||||
diff_parser = DiffParser.instance
|
|
||||||
if not diff_parser:
|
|
||||||
return
|
|
||||||
|
|
||||||
(row, col) = self.view.rowcol(self.view.sel()[0].begin())
|
|
||||||
(lines, current, replace_lines) = diff_parser.get_original_part(row + 1)
|
|
||||||
if self.settings.get('debug'):
|
|
||||||
print('replace', (lines, current, replace_lines))
|
|
||||||
if lines is not None:
|
|
||||||
begin = self.view.text_point(current - 1, 0)
|
|
||||||
content = self.join_lines(lines)
|
|
||||||
if replace_lines:
|
|
||||||
end = self.view.line(self.view.text_point(replace_lines + current - 2, 0)).end()
|
|
||||||
region = sublime.Region(begin, end)
|
|
||||||
if lines:
|
|
||||||
self.view.run_command('edit_view', dict(command='replace', region=[region.begin(), region.end()], output=content))
|
|
||||||
else:
|
|
||||||
region = self.view.full_line(region)
|
|
||||||
self.view.run_command('edit_view', dict(command='erase', region=[region.begin(), region.end()]))
|
|
||||||
else:
|
|
||||||
self.view.run_command('edit_view', dict(command='insert', begin=begin,
|
|
||||||
output=content + self.get_line_ending()))
|
|
||||||
self.view.run_command('save')
|
|
||||||
|
|
||||||
|
|
||||||
class HlChangesBackground(sublime_plugin.EventListener):
|
|
||||||
def on_load(self, view):
|
|
||||||
if not IS_ST3:
|
|
||||||
view.run_command('hl_changes')
|
|
||||||
|
|
||||||
def on_load_async(self, view):
|
|
||||||
view.run_command('hl_changes')
|
|
||||||
|
|
||||||
def on_activated(self, view):
|
|
||||||
if not IS_ST3:
|
|
||||||
view.run_command('hl_changes')
|
|
||||||
|
|
||||||
def on_activated_async(self, view):
|
|
||||||
view.run_command('hl_changes')
|
|
||||||
|
|
||||||
def on_post_save(self, view):
|
|
||||||
if not IS_ST3:
|
|
||||||
view.run_command('hl_changes')
|
|
||||||
|
|
||||||
def on_post_save_async(self, view):
|
|
||||||
view.run_command('hl_changes')
|
|
||||||
|
|
||||||
|
|
||||||
class JumpBetweenChangesCommand(DiffCommand, sublime_plugin.TextCommand):
|
|
||||||
def run(self, edit, direction='next'):
|
|
||||||
lines = self._get_lines()
|
|
||||||
if not lines:
|
|
||||||
return
|
|
||||||
|
|
||||||
if direction == 'prev':
|
|
||||||
lines.reverse()
|
|
||||||
|
|
||||||
(current_line, col) = self.view.rowcol(self.view.sel()[0].begin())
|
|
||||||
current_line += 1
|
|
||||||
jump_to = None
|
|
||||||
for line in lines:
|
|
||||||
if direction == 'next' and current_line < line:
|
|
||||||
jump_to = line
|
|
||||||
break
|
|
||||||
if direction == 'prev' and current_line > line:
|
|
||||||
jump_to = line
|
|
||||||
break
|
|
||||||
|
|
||||||
if not jump_to and self.settings.get('jump_between_changes_wraps_around', True):
|
|
||||||
jump_to = lines[0]
|
|
||||||
|
|
||||||
if jump_to is not None:
|
|
||||||
self.goto_line(edit, jump_to)
|
|
||||||
|
|
||||||
def goto_line(self, edit, line):
|
|
||||||
# Convert from 1 based to a 0 based line number
|
|
||||||
line = int(line) - 1
|
|
||||||
|
|
||||||
# Negative line numbers count from the end of the buffer
|
|
||||||
if line < 0:
|
|
||||||
lines, _ = self.view.rowcol(self.view.size())
|
|
||||||
line = lines + line + 1
|
|
||||||
|
|
||||||
pt = self.view.text_point(line, 0)
|
|
||||||
|
|
||||||
self.view.sel().clear()
|
|
||||||
self.view.sel().add(sublime.Region(pt))
|
|
||||||
|
|
||||||
self.view.show(pt)
|
|
||||||
|
|
||||||
def _get_lines(self):
|
|
||||||
diff_parser = DiffParser.instance
|
|
||||||
if not diff_parser:
|
|
||||||
return
|
|
||||||
|
|
||||||
(inserted, changed, deleted) = diff_parser.get_lines_to_hl()
|
|
||||||
lines = list(set(inserted + changed + deleted))
|
|
||||||
lines.sort()
|
|
||||||
|
|
||||||
prev = None
|
|
||||||
ret_lines = []
|
|
||||||
for line in lines:
|
|
||||||
if prev != line - 1:
|
|
||||||
ret_lines.append(line)
|
|
||||||
prev = line
|
|
||||||
|
|
||||||
return ret_lines
|
|
||||||
|
|
||||||
|
|
||||||
class UncommittedFilesCommand(VcsCommand, sublime_plugin.WindowCommand):
|
|
||||||
def active_view(self):
|
|
||||||
return self.window.active_view()
|
|
||||||
|
|
||||||
def is_enabled(self):
|
|
||||||
return bool(self.get_working_dir())
|
|
||||||
|
|
||||||
def get_working_dir(self):
|
|
||||||
if self._active_file_name():
|
|
||||||
working_dir = super(UncommittedFilesCommand, self).get_working_dir()
|
|
||||||
if working_dir and get_vcs(working_dir):
|
|
||||||
return working_dir
|
|
||||||
|
|
||||||
# If the user has opened a vcs folder, use it.
|
|
||||||
folders = self.window.folders()
|
|
||||||
for folder in folders:
|
|
||||||
if folder and os.path.exists(folder) and get_vcs(folder):
|
|
||||||
return folder
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.vcs = get_vcs(self.get_working_dir())
|
|
||||||
status_command = getattr(self, '{0}_status_command'.format(self.vcs['name']), None)
|
|
||||||
if status_command:
|
|
||||||
self.run_command(status_command(), self.status_done, working_dir=self.vcs['root'])
|
|
||||||
|
|
||||||
def git_status_command(self):
|
|
||||||
return [get_user_command('git') or 'git', 'status', '--porcelain']
|
|
||||||
|
|
||||||
def svn_status_command(self):
|
|
||||||
return [get_user_command('svn') or 'svn', 'status', '--quiet']
|
|
||||||
|
|
||||||
def bzr_status_command(self):
|
|
||||||
return [get_user_command('bzr') or 'bzr', 'status', '-S', '--no-pending', '-V']
|
|
||||||
|
|
||||||
def hg_status_command(self):
|
|
||||||
return [get_user_command('hg') or 'hg', 'status']
|
|
||||||
|
|
||||||
def tf_status_command(self):
|
|
||||||
return [get_user_command('tf') or 'tf', 'status']
|
|
||||||
|
|
||||||
def filter_unified_status(self, result):
|
|
||||||
return list(filter(lambda x: len(x) > 0 and not x.lstrip().startswith('>'),
|
|
||||||
result.rstrip().replace('"', '').split('\n')))
|
|
||||||
|
|
||||||
def git_filter_status(self, result):
|
|
||||||
return self.filter_unified_status(result)
|
|
||||||
|
|
||||||
def svn_filter_status(self, result):
|
|
||||||
return self.filter_unified_status(result)
|
|
||||||
|
|
||||||
def bzr_filter_status(self, result):
|
|
||||||
return self.filter_unified_status(result)
|
|
||||||
|
|
||||||
def hg_filter_status(self, result):
|
|
||||||
return self.filter_unified_status(result)
|
|
||||||
|
|
||||||
def tf_filter_status(self, result):
|
|
||||||
filtered = []
|
|
||||||
can_add = False
|
|
||||||
for line in result.split('\n'):
|
|
||||||
if line.startswith('$'):
|
|
||||||
can_add = True
|
|
||||||
continue
|
|
||||||
if line == '':
|
|
||||||
can_add = False
|
|
||||||
continue
|
|
||||||
if can_add:
|
|
||||||
filtered.append(line)
|
|
||||||
|
|
||||||
return filtered
|
|
||||||
|
|
||||||
def git_status_file(self, file_name):
|
|
||||||
# first 2 characters are status codes, the third is a space
|
|
||||||
return file_name[3:]
|
|
||||||
|
|
||||||
def svn_status_file(self, file_name):
|
|
||||||
return file_name[8:]
|
|
||||||
|
|
||||||
def bzr_status_file(self, file_name):
|
|
||||||
return file_name[4:]
|
|
||||||
|
|
||||||
def hg_status_file(self, file_name):
|
|
||||||
return file_name[2:]
|
|
||||||
|
|
||||||
def tf_status_file(self, file_name):
|
|
||||||
try:
|
|
||||||
# assume that file name should always contain colon
|
|
||||||
return re.findall(r'\s+(\S+:.+)$', file_name)[0]
|
|
||||||
except:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def status_done(self, result):
|
|
||||||
filter_status = getattr(self, '{0}_filter_status'.format(self.vcs['name']), None)
|
|
||||||
|
|
||||||
self.results = [item.replace('\r', '') for item in filter_status(result)]
|
|
||||||
|
|
||||||
if self.results:
|
|
||||||
self.show_status_list()
|
|
||||||
else:
|
|
||||||
sublime.status_message("Nothing to show")
|
|
||||||
|
|
||||||
def show_status_list(self):
|
|
||||||
options = copy(self.results)
|
|
||||||
options.insert(0, " - Open All")
|
|
||||||
if self.settings.get('uncommitted_files_use_monospace_font', True):
|
|
||||||
self.get_window().show_quick_panel(options, self.panel_done, sublime.MONOSPACE_FONT)
|
|
||||||
else:
|
|
||||||
self.get_window().show_quick_panel(options, self.panel_done)
|
|
||||||
|
|
||||||
def panel_done(self, picked):
|
|
||||||
if picked == 0:
|
|
||||||
self.open_files(*self.results)
|
|
||||||
return
|
|
||||||
elif 0 > picked < len(self.results):
|
|
||||||
return
|
|
||||||
picked_file = self.results[picked - 1]
|
|
||||||
self.open_files(picked_file)
|
|
||||||
|
|
||||||
def open_files(self, *files):
|
|
||||||
for f in files:
|
|
||||||
get_file = getattr(self, '{0}_status_file'.format(self.vcs['name']), None)
|
|
||||||
if get_file:
|
|
||||||
fname = get_file(f)
|
|
||||||
if os.path.isfile(os.path.join(self.vcs['root'], fname)):
|
|
||||||
self.window.open_file(os.path.join(self.vcs['root'], fname))
|
|
||||||
else:
|
|
||||||
sublime.status_message("File '{0}' doesn't exist".format(fname))
|
|
||||||
|
|
||||||
|
|
||||||
class ToggleHighlightChangesCommand(sublime_plugin.TextCommand):
|
|
||||||
def run(self, edit):
|
|
||||||
setting_name = "highlight_changes"
|
|
||||||
settings = get_settings()
|
|
||||||
is_on = settings.get(setting_name)
|
|
||||||
|
|
||||||
if is_on:
|
|
||||||
# remove highlighting
|
|
||||||
[self.view.erase_regions(k) for k in ('inserted', 'changed', 'deleted')]
|
|
||||||
else:
|
|
||||||
self.view.run_command('hl_changes')
|
|
||||||
|
|
||||||
settings.set(setting_name, not is_on)
|
|
||||||
sublime.save_settings("Modific.sublime-settings")
|
|
|
@ -1,35 +0,0 @@
|
||||||
# Simple Python Sample
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
import sublime
|
|
||||||
|
|
||||||
IS_ST3 = sublime.version().startswith('3')
|
|
||||||
|
|
||||||
def get_vcs_settings():
|
|
||||||
"""Returns list of dictionaries"""
|
|
||||||
if self.config.getboolean("verbose_stamps", fallback=False):
|
|
||||||
print("Sending " + command)
|
|
||||||
|
|
||||||
# Add a newline because the ui reads per line
|
|
||||||
command += " \n"
|
|
||||||
if self.gtk_proc:
|
|
||||||
# Send the command as bytes
|
|
||||||
self.gtk_proc.stdin.write(bytearray(command.encode("utf-8")))
|
|
||||||
self.gtk_proc.stdin.flush()
|
|
||||||
try:
|
|
||||||
constructor = getattr(module, type)
|
|
||||||
except AttributeError:
|
|
||||||
print(_("Error: Class {} not found").format(type))
|
|
||||||
continue
|
|
||||||
|
|
||||||
else
|
|
||||||
instance = constructor()
|
|
||||||
instance.verbose = verbose
|
|
||||||
instance.config = config
|
|
||||||
|
|
||||||
def do_when(conditional, callback, *args, **kwargs):
|
|
||||||
if conditional():
|
|
||||||
return callback(*args, **kwargs)
|
|
||||||
sublime.set_timeout(functools.partial(do_when, conditional, callback, *args, **kwargs), 50)
|
|
117
samples/rust.rs
Normal file
117
samples/rust.rs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
mod stuff;
|
||||||
|
|
||||||
|
pub enum Flag {
|
||||||
|
Good,
|
||||||
|
Bad,
|
||||||
|
Ugly
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUALITY: Flag = Flag::Good;
|
||||||
|
|
||||||
|
struct Table<const N: usize>([[i32; N]; N])
|
||||||
|
|
||||||
|
pub trait Write {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Object<T> {
|
||||||
|
flag: Flag,
|
||||||
|
fields: HashMap<T, u64>
|
||||||
|
}
|
||||||
|
|
||||||
|
union MyUnion {
|
||||||
|
f1: u32,
|
||||||
|
f2: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
type RcObject<T> = Rc<Object<T>>;
|
||||||
|
|
||||||
|
impl<T> Write for Object<T> {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||||
|
let s = stuff::write_map(&self.fields, buf)?;
|
||||||
|
info!("{} byte(s) written", s);
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Object<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Object { flag: Flag::Good, fields: HashMap::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! make_wrapper {
|
||||||
|
($wrapper_ty:ident, $base_ty:ty $(, $lu_ty:ty)?) => {
|
||||||
|
pub struct $wrapper_ty($base_ty);
|
||||||
|
impl From<$base_ty> for $wrapper_ty {
|
||||||
|
fn from(base: $base_ty) -> Self {
|
||||||
|
Self(base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(
|
||||||
|
impl From<$lu_ty> for $wrapper_ty {
|
||||||
|
fn from(lu: $lu_ty) -> Self {
|
||||||
|
Self(lu.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<$wrapper_ty> for $lu_ty {
|
||||||
|
fn from(st: $wrapper_ty) -> Self {
|
||||||
|
Self::new(st.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Block comment */
|
||||||
|
fn main() {
|
||||||
|
// A simple integer calculator:
|
||||||
|
// `+` or `-` means add or subtract by 1
|
||||||
|
// `*` or `/` means multiply or divide by 2
|
||||||
|
stuff::AppVersion::print();
|
||||||
|
|
||||||
|
let input = Option::None;
|
||||||
|
let program = input.unwrap_or_else(|| "+ + * - /");
|
||||||
|
let mut accumulator = 0;
|
||||||
|
|
||||||
|
for token in program.chars() {
|
||||||
|
match token {
|
||||||
|
'+' => accumulator += 1,
|
||||||
|
'-' => accumulator -= 1,
|
||||||
|
'*' => accumulator *= 2,
|
||||||
|
'/' => accumulator /= 2,
|
||||||
|
_ => { /* ignore everything else */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("The program \"{}\" calculates the value {}",
|
||||||
|
program, accumulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Some documentation `with a code`, *an italic text*
|
||||||
|
/// and **a bold text**
|
||||||
|
/// # Heading
|
||||||
|
/// [Rust](https://www.rust-lang.org/)
|
||||||
|
#[cfg(target_os="linux")]
|
||||||
|
unsafe fn a_function<T: 'lifetime>(count: &mut i64) -> ! {
|
||||||
|
count += 1;
|
||||||
|
'label: loop {
|
||||||
|
let str_with_escapes = "Hello\x20W\u{f3}rld!\u{abcdef}";
|
||||||
|
println!("{} {foo:<4}", str_with_escapes, foo = 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
unsafe {
|
||||||
|
a_function(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "disabled_feature")]
|
||||||
|
fn cfg_disabled_function() {}
|
|
@ -1,45 +0,0 @@
|
||||||
#![warn(rust_2018_idioms)]
|
|
||||||
#![allow(elided_lifetimes_in_paths)]
|
|
||||||
|
|
||||||
use std::net::TcpListener;
|
|
||||||
use std::io;
|
|
||||||
use std::thread::spawn;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
let solar_distance = HashMap::from([
|
|
||||||
("Mercury", 0.4),
|
|
||||||
("Venus", 0.7),
|
|
||||||
("Earth", 1.0),
|
|
||||||
("Mars", 1.5),
|
|
||||||
]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lorem ipsum dolor sit amet, consectetur adipiscing elit 1 + 1 = 3
|
|
||||||
* augue ut nulla convallis finibus.
|
|
||||||
* */
|
|
||||||
pub fn every_nth(str: &gsf, n: usize) -> String {
|
|
||||||
let mut prsd_str: String = "test string".to_string().to_owned();
|
|
||||||
let lenght:usize = gsf.len();
|
|
||||||
for (i, j) in gsf.chars().enumerate() {
|
|
||||||
if length%2 == 0 {
|
|
||||||
if i%n < n-1 {
|
|
||||||
parsed_str.push();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if i%n < n-2 {
|
|
||||||
parsed_str.push(gsf.substr(i, j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parsed_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main(){
|
|
||||||
let arr:[i32;4] = [10,20,30,40];
|
|
||||||
println!("array is {:?}",arr);
|
|
||||||
println!("array size is :{}",arr.len());
|
|
||||||
|
|
||||||
for index in 0..4 {
|
|
||||||
println!("index is: {} & value is : {}",index,arr[index]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,961 +0,0 @@
|
||||||
use crate::context::DrawContext;
|
|
||||||
use crate::controller::Controller;
|
|
||||||
use crate::font::FontCache;
|
|
||||||
use crate::scene::*;
|
|
||||||
use crate::wayland::*;
|
|
||||||
use crate::*;
|
|
||||||
use smithay_client_toolkit::reexports::calloop::{EventLoop, LoopHandle, RegistrationToken};
|
|
||||||
use smithay_client_toolkit::seat::keyboard::ModifiersState;
|
|
||||||
use smithay_client_toolkit::shm::AutoMemPool;
|
|
||||||
use smithay_client_toolkit::WaylandSource;
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use smithay_client_toolkit::reexports::client::{
|
|
||||||
global_filter,
|
|
||||||
protocol::wl_buffer::WlBuffer,
|
|
||||||
protocol::wl_callback,
|
|
||||||
protocol::wl_compositor::WlCompositor,
|
|
||||||
protocol::wl_output::{self, WlOutput},
|
|
||||||
protocol::wl_pointer::{self, WlPointer},
|
|
||||||
protocol::wl_region::WlRegion,
|
|
||||||
protocol::wl_seat::{self, Capability, WlSeat},
|
|
||||||
protocol::wl_shm::WlShm,
|
|
||||||
protocol::wl_surface::WlSurface,
|
|
||||||
Attached, Display, GlobalError, GlobalManager, Interface, Main, Proxy,
|
|
||||||
};
|
|
||||||
use smithay_client_toolkit::reexports::protocols::wlr::unstable::layer_shell::v1::client::{
|
|
||||||
zwlr_layer_shell_v1::ZwlrLayerShellV1, zwlr_layer_surface_v1,
|
|
||||||
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Application<M, C>
|
|
||||||
where
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
display: Display,
|
|
||||||
globals: Rc<RefCell<Globals>>,
|
|
||||||
global_manager: GlobalManager,
|
|
||||||
pub inner: Vec<InnerApplication<M, C>>,
|
|
||||||
token: RegistrationToken,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Context {
|
|
||||||
pending_cb: bool,
|
|
||||||
time: Option<u32>,
|
|
||||||
render_node: Option<RenderNode>,
|
|
||||||
font_cache: FontCache,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CoreApplication<M, C>
|
|
||||||
where
|
|
||||||
C: Controller<M> + Clone,
|
|
||||||
{
|
|
||||||
pub controller: C,
|
|
||||||
ctx: Context,
|
|
||||||
globals: Rc<RefCell<Globals>>,
|
|
||||||
mempool: AutoMemPool,
|
|
||||||
widget: Box<dyn Widget<M>>,
|
|
||||||
surface: Option<Surface>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct InnerApplication<M, C>
|
|
||||||
where
|
|
||||||
C: Controller<M> + Clone,
|
|
||||||
{
|
|
||||||
core: CoreApplication<M, C>,
|
|
||||||
cb: Box<dyn FnMut(&mut CoreApplication<M, C>, Event<M>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Surface {
|
|
||||||
fn new(
|
|
||||||
surface: Main<WlSurface>,
|
|
||||||
shell: Shell,
|
|
||||||
region: Main<WlRegion>,
|
|
||||||
previous: Option<Surface>,
|
|
||||||
) -> Self {
|
|
||||||
Surface {
|
|
||||||
alive: true,
|
|
||||||
surface,
|
|
||||||
shell,
|
|
||||||
region,
|
|
||||||
previous: if let Some(surface) = previous {
|
|
||||||
Some(Box::new(surface))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
buffer: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn commit(&mut self) {
|
|
||||||
self.surface.commit();
|
|
||||||
std::mem::drop(&mut self.previous);
|
|
||||||
self.previous = None;
|
|
||||||
}
|
|
||||||
fn destroy(&mut self) {
|
|
||||||
self.alive = false;
|
|
||||||
self.surface.destroy();
|
|
||||||
self.region.destroy();
|
|
||||||
self.shell.destroy();
|
|
||||||
if let Some(buffer) = self.buffer.as_ref() {
|
|
||||||
buffer.destroy();
|
|
||||||
}
|
|
||||||
self.buffer = None;
|
|
||||||
}
|
|
||||||
fn destroy_previous(&mut self) {
|
|
||||||
if let Some(surface) = self.previous.as_mut() {
|
|
||||||
surface.destroy();
|
|
||||||
}
|
|
||||||
self.previous = None;
|
|
||||||
}
|
|
||||||
fn set_size(&self, width: u32, height: u32) {
|
|
||||||
self.shell.set_size(width, height);
|
|
||||||
}
|
|
||||||
fn damage(&self, report: &[Region]) {
|
|
||||||
self.surface.attach(self.buffer.as_ref(), 0, 0);
|
|
||||||
for d in report {
|
|
||||||
self.surface
|
|
||||||
.damage(d.x as i32, d.y as i32, d.width as i32, d.height as i32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn attach_buffer(&mut self, buffer: WlBuffer) {
|
|
||||||
self.buffer = Some(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Globals {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
outputs: Vec::new(),
|
|
||||||
seats: Vec::new(),
|
|
||||||
shm: None,
|
|
||||||
compositor: None,
|
|
||||||
shell: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn create_shell_surface_from<M, C>(
|
|
||||||
&self,
|
|
||||||
geometry: &dyn Widget<M>,
|
|
||||||
config: ShellConfig,
|
|
||||||
previous: Option<Surface>,
|
|
||||||
) -> Option<Surface>
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
if self.compositor.is_some() {
|
|
||||||
match config {
|
|
||||||
ShellConfig::LayerShell(config) => {
|
|
||||||
if let Some(layer_shell) = self.shell.as_ref() {
|
|
||||||
let region = self.compositor.as_ref().unwrap().create_region();
|
|
||||||
let wl_surface = self.compositor.as_ref().unwrap().create_surface();
|
|
||||||
let layer_surface = layer_shell.get_layer_surface(
|
|
||||||
&wl_surface,
|
|
||||||
config.output.as_ref(),
|
|
||||||
config.layer,
|
|
||||||
config.namespace.clone(),
|
|
||||||
);
|
|
||||||
if let Some(anchor) = &config.anchor {
|
|
||||||
layer_surface.set_anchor(*anchor);
|
|
||||||
}
|
|
||||||
wl_surface.quick_assign(|_, _, _| {});
|
|
||||||
layer_surface.set_exclusive_zone(config.exclusive);
|
|
||||||
layer_surface.set_keyboard_interactivity(config.interactivity);
|
|
||||||
layer_surface.set_size(geometry.width() as u32, geometry.height() as u32);
|
|
||||||
layer_surface.set_margin(
|
|
||||||
config.margin[0],
|
|
||||||
config.margin[1],
|
|
||||||
config.margin[2],
|
|
||||||
config.margin[3],
|
|
||||||
);
|
|
||||||
wl_surface.commit();
|
|
||||||
assign_surface::<M, C>(&layer_surface);
|
|
||||||
return Some(Surface::new(
|
|
||||||
wl_surface,
|
|
||||||
Shell::LayerShell {
|
|
||||||
surface: layer_surface,
|
|
||||||
config,
|
|
||||||
},
|
|
||||||
region,
|
|
||||||
previous,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub fn create_mempool(&self) -> AutoMemPool {
|
|
||||||
let attached = Attached::from(self.shm.clone().unwrap());
|
|
||||||
AutoMemPool::new(attached).unwrap()
|
|
||||||
}
|
|
||||||
pub fn get_outputs(&self) -> Vec<Output> {
|
|
||||||
self.outputs.clone()
|
|
||||||
}
|
|
||||||
pub fn get_seats(&self) -> &[Seat] {
|
|
||||||
&self.seats
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Output {
|
|
||||||
fn new(output: Main<WlOutput>) -> Self {
|
|
||||||
Output {
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
scale: 1,
|
|
||||||
name: String::new(),
|
|
||||||
output,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M, C> Application<M, C>
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
pub fn new(pointer: bool) -> (Self, EventLoop<'static, Self>) {
|
|
||||||
let display = Display::connect_to_env().unwrap();
|
|
||||||
let event_queue = display.create_event_queue();
|
|
||||||
let attached_display = (*display).clone().attach(event_queue.token());
|
|
||||||
|
|
||||||
let display_handle = display.clone();
|
|
||||||
|
|
||||||
let globals = Globals::new();
|
|
||||||
|
|
||||||
let global_manager = GlobalManager::new_with_cb(
|
|
||||||
&attached_display,
|
|
||||||
global_filter!(
|
|
||||||
[
|
|
||||||
ZwlrLayerShellV1,
|
|
||||||
1,
|
|
||||||
|layer_shell: Main<ZwlrLayerShellV1>, mut application: DispatchData| {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
globals.shell = Some(layer_shell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
WlShm,
|
|
||||||
1,
|
|
||||||
|shm: Main<WlShm>, mut application: DispatchData| {
|
|
||||||
shm.quick_assign(|_, _, _| {});
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
globals.shm = Some(shm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
WlCompositor,
|
|
||||||
4,
|
|
||||||
|compositor: Main<WlCompositor>, mut application: DispatchData| {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
globals.compositor = Some(compositor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[WlSeat, 7, move |seat: Main<WlSeat>, _: DispatchData| {
|
|
||||||
seat.quick_assign(move |wl_seat, event, mut application| match event {
|
|
||||||
wl_seat::Event::Capabilities { capabilities } => {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if pointer
|
|
||||||
&& capabilities & Capability::Pointer == Capability::Pointer
|
|
||||||
{
|
|
||||||
let pointer = wl_seat.get_pointer();
|
|
||||||
assign_pointer::<M, C>(&pointer);
|
|
||||||
}
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
let mut found = None;
|
|
||||||
for seat in &mut globals.seats {
|
|
||||||
if wl_seat.eq(&seat.seat) {
|
|
||||||
found = Some(());
|
|
||||||
seat.capabilities = capabilities;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found.is_none() {
|
|
||||||
globals.seats.push(Seat {
|
|
||||||
capabilities,
|
|
||||||
seat: wl_seat,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
}],
|
|
||||||
[
|
|
||||||
WlOutput,
|
|
||||||
3,
|
|
||||||
|output: Main<WlOutput>, _application: DispatchData| {
|
|
||||||
output.quick_assign(move |wl_output, event, mut application| match event {
|
|
||||||
wl_output::Event::Geometry {
|
|
||||||
x: _,
|
|
||||||
y: _,
|
|
||||||
physical_width: _,
|
|
||||||
physical_height: _,
|
|
||||||
subpixel: _,
|
|
||||||
make,
|
|
||||||
model: _,
|
|
||||||
transform: _,
|
|
||||||
} => {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
let mut found = None;
|
|
||||||
for output in &mut globals.outputs {
|
|
||||||
if wl_output.eq(&output.output) {
|
|
||||||
found = Some(());
|
|
||||||
output.name = make.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found.is_none() {
|
|
||||||
let mut output = Output::new(wl_output);
|
|
||||||
output.name = make;
|
|
||||||
globals.outputs.push(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_output::Event::Mode {
|
|
||||||
flags: _,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
refresh: _,
|
|
||||||
} => {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
let mut found = None;
|
|
||||||
for output in &mut globals.outputs {
|
|
||||||
if wl_output.eq(&output.output) {
|
|
||||||
found = Some(());
|
|
||||||
output.width = width;
|
|
||||||
output.height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found.is_none() {
|
|
||||||
let mut output = Output::new(wl_output);
|
|
||||||
output.width = width;
|
|
||||||
output.height = height;
|
|
||||||
globals.outputs.push(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_output::Event::Scale { factor } => {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
|
||||||
let mut found = None;
|
|
||||||
for output in &mut globals.outputs {
|
|
||||||
if wl_output.eq(&output.output) {
|
|
||||||
found = Some(());
|
|
||||||
output.scale = factor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if found.is_none() {
|
|
||||||
let mut output = Output::new(wl_output);
|
|
||||||
output.scale = factor;
|
|
||||||
globals.outputs.push(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_output::Event::Done => {}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
]
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
let event_loop = EventLoop::try_new().expect("Failed to initialize the event loop!");
|
|
||||||
let token = WaylandSource::new(event_queue)
|
|
||||||
.quick_insert(event_loop.handle())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (mut application, mut event_loop) = (
|
|
||||||
Application {
|
|
||||||
display,
|
|
||||||
globals: Rc::new(RefCell::new(globals)),
|
|
||||||
global_manager,
|
|
||||||
inner: Vec::new(),
|
|
||||||
token,
|
|
||||||
},
|
|
||||||
event_loop,
|
|
||||||
);
|
|
||||||
|
|
||||||
for _ in 0..2 {
|
|
||||||
display_handle.flush().unwrap();
|
|
||||||
event_loop.dispatch(None, &mut application).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
(application, event_loop)
|
|
||||||
}
|
|
||||||
fn get_index(&self, surface: &WlSurface) -> usize {
|
|
||||||
for i in 0..self.inner.len() {
|
|
||||||
if self.inner[i].eq(surface) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
fn get_application(&mut self, surface: &WlSurface) -> Option<&mut InnerApplication<M, C>> {
|
|
||||||
for inner in &mut self.inner {
|
|
||||||
if inner.eq(surface) {
|
|
||||||
return Some(inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub fn get_global<I>(&self) -> Result<Main<I>, GlobalError>
|
|
||||||
where
|
|
||||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
|
||||||
{
|
|
||||||
self.global_manager.instantiate_range::<I>(0, 1 << 8)
|
|
||||||
}
|
|
||||||
pub fn create_empty_inner_application<Data: 'static>(
|
|
||||||
&mut self,
|
|
||||||
controller: C,
|
|
||||||
widget: impl Widget<M> + 'static,
|
|
||||||
handle: LoopHandle<'_, Data>,
|
|
||||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
|
||||||
) {
|
|
||||||
let inner_application =
|
|
||||||
InnerApplication::empty(controller, widget, self.globals.clone(), cb);
|
|
||||||
self.inner.push(inner_application);
|
|
||||||
handle.update(&self.token).unwrap();
|
|
||||||
}
|
|
||||||
pub fn create_inner_application_from<Data: 'static>(
|
|
||||||
&mut self,
|
|
||||||
controller: C,
|
|
||||||
config: ShellConfig,
|
|
||||||
widget: impl Widget<M> + 'static,
|
|
||||||
handle: LoopHandle<'_, Data>,
|
|
||||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
|
||||||
) {
|
|
||||||
let inner_application =
|
|
||||||
InnerApplication::new(controller, widget, config, self.globals.clone(), cb);
|
|
||||||
self.inner.push(inner_application);
|
|
||||||
handle.update(&self.token).unwrap();
|
|
||||||
}
|
|
||||||
pub fn create_inner_application<Data: 'static>(
|
|
||||||
&mut self,
|
|
||||||
controller: C,
|
|
||||||
widget: impl Widget<M> + 'static,
|
|
||||||
handle: LoopHandle<'_, Data>,
|
|
||||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
|
||||||
) {
|
|
||||||
let inner_application =
|
|
||||||
InnerApplication::normal(controller, widget, self.globals.clone(), cb);
|
|
||||||
self.inner.push(inner_application);
|
|
||||||
handle.update(&self.token).unwrap();
|
|
||||||
}
|
|
||||||
pub fn run(mut self, event_loop: &mut EventLoop<'static, Self>) {
|
|
||||||
loop {
|
|
||||||
self.display.flush().unwrap();
|
|
||||||
event_loop.dispatch(None, &mut self).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M, C> Deref for InnerApplication<M, C>
|
|
||||||
where
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
type Target = CoreApplication<M, C>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.core
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M, C> DerefMut for InnerApplication<M, C>
|
|
||||||
where
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.core
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M, C> CoreApplication<M, C>
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
pub fn poll(&mut self, ev: Event<M>) -> C {
|
|
||||||
let mut ctl = self.controller.clone();
|
|
||||||
let mut sync_ctx = SyncContext::new(&mut ctl, &mut self.ctx.font_cache);
|
|
||||||
self.widget.sync(&mut sync_ctx, ev);
|
|
||||||
ctl
|
|
||||||
}
|
|
||||||
pub fn sync(&mut self, ev: Event<M>) -> bool {
|
|
||||||
let mut sync_ctx = SyncContext::new(&mut self.controller, &mut self.ctx.font_cache);
|
|
||||||
let mut damage = self.widget.sync(&mut sync_ctx, ev);
|
|
||||||
while let Ok(msg) = sync_ctx.sync() {
|
|
||||||
damage = damage.max(self.widget.sync(&mut sync_ctx, Event::Message(&msg)));
|
|
||||||
}
|
|
||||||
if damage == Damage::Frame {
|
|
||||||
if self.ctx.time.is_none() {
|
|
||||||
self.ctx.time = Some(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
damage.is_some() && !self.ctx.pending_cb
|
|
||||||
}
|
|
||||||
pub fn destroy(&mut self) {
|
|
||||||
if let Some(surface) = self.surface.as_mut() {
|
|
||||||
surface.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn get_layer_surface(&self) -> ZwlrLayerSurfaceV1 {
|
|
||||||
match &self.surface.as_ref().unwrap().shell {
|
|
||||||
Shell::LayerShell { config: _, surface } => surface.detach(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn is_hidden(&self) -> bool {
|
|
||||||
if let Some(surface) = self.surface.as_ref() {
|
|
||||||
return !surface.alive;
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn replace_surface(&mut self) {
|
|
||||||
if let Some(surface) = self.surface.as_mut() {
|
|
||||||
surface.destroy();
|
|
||||||
surface.alive = true;
|
|
||||||
match &surface.shell {
|
|
||||||
Shell::LayerShell { config, surface: _ } => {
|
|
||||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
|
||||||
self.widget.deref(),
|
|
||||||
ShellConfig::LayerShell(config.clone()),
|
|
||||||
Some(surface.clone()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
|
||||||
self.widget.deref(),
|
|
||||||
ShellConfig::LayerShell(LayerShellConfig::default()),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn replace_surface_by(&mut self, config: ShellConfig) {
|
|
||||||
if let Some(surface) = self.surface.as_mut() {
|
|
||||||
surface.destroy();
|
|
||||||
surface.alive = true;
|
|
||||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
|
||||||
self.widget.deref(),
|
|
||||||
config,
|
|
||||||
Some(surface.clone()),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
|
||||||
self.widget.deref(),
|
|
||||||
config,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M, C> Geometry for InnerApplication<M, C>
|
|
||||||
where
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
fn width(&self) -> f32 {
|
|
||||||
self.widget.width()
|
|
||||||
}
|
|
||||||
fn height(&self) -> f32 {
|
|
||||||
self.widget.height()
|
|
||||||
}
|
|
||||||
fn set_size(&mut self, width: f32, height: f32) -> Result<(), (f32, f32)> {
|
|
||||||
if let Some(surface) = self.surface.as_ref() {
|
|
||||||
surface.set_size(width as u32, height as u32);
|
|
||||||
surface.surface.commit();
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M, C> InnerApplication<M, C>
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
pub fn empty(
|
|
||||||
controller: C,
|
|
||||||
widget: impl Widget<M> + 'static,
|
|
||||||
globals: Rc<RefCell<Globals>>,
|
|
||||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
|
||||||
) -> Self {
|
|
||||||
let mempool = globals.borrow().create_mempool();
|
|
||||||
let mut default = InnerApplication {
|
|
||||||
core: CoreApplication {
|
|
||||||
controller,
|
|
||||||
ctx: Context {
|
|
||||||
pending_cb: false,
|
|
||||||
time: None,
|
|
||||||
font_cache: FontCache::new(),
|
|
||||||
render_node: None,
|
|
||||||
},
|
|
||||||
surface: None,
|
|
||||||
widget: Box::new(widget),
|
|
||||||
mempool,
|
|
||||||
globals,
|
|
||||||
},
|
|
||||||
cb: Box::new(cb),
|
|
||||||
};
|
|
||||||
default.sync(Event::Prepare);
|
|
||||||
default
|
|
||||||
}
|
|
||||||
pub fn normal(
|
|
||||||
controller: C,
|
|
||||||
widget: impl Widget<M> + 'static,
|
|
||||||
globals: Rc<RefCell<Globals>>,
|
|
||||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
|
||||||
) -> Self {
|
|
||||||
let mempool = globals.borrow().create_mempool();
|
|
||||||
let mut default = InnerApplication {
|
|
||||||
core: CoreApplication {
|
|
||||||
controller,
|
|
||||||
ctx: Context {
|
|
||||||
pending_cb: false,
|
|
||||||
time: None,
|
|
||||||
font_cache: FontCache::new(),
|
|
||||||
render_node: None,
|
|
||||||
},
|
|
||||||
surface: None,
|
|
||||||
widget: Box::new(widget),
|
|
||||||
mempool,
|
|
||||||
globals,
|
|
||||||
},
|
|
||||||
cb: Box::new(cb),
|
|
||||||
};
|
|
||||||
default.sync(Event::Prepare);
|
|
||||||
default.replace_surface();
|
|
||||||
default
|
|
||||||
}
|
|
||||||
pub fn new(
|
|
||||||
controller: C,
|
|
||||||
widget: impl Widget<M> + 'static,
|
|
||||||
config: ShellConfig,
|
|
||||||
globals: Rc<RefCell<Globals>>,
|
|
||||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
|
||||||
) -> Self {
|
|
||||||
let mempool = globals.borrow().create_mempool();
|
|
||||||
let mut new = InnerApplication {
|
|
||||||
core: CoreApplication {
|
|
||||||
controller,
|
|
||||||
ctx: Context {
|
|
||||||
pending_cb: false,
|
|
||||||
time: None,
|
|
||||||
font_cache: FontCache::new(),
|
|
||||||
render_node: None,
|
|
||||||
},
|
|
||||||
surface: None,
|
|
||||||
widget: Box::new(widget),
|
|
||||||
mempool,
|
|
||||||
globals,
|
|
||||||
},
|
|
||||||
cb: Box::new(cb),
|
|
||||||
};
|
|
||||||
new.sync(Event::Prepare);
|
|
||||||
new.replace_surface_by(config);
|
|
||||||
new
|
|
||||||
}
|
|
||||||
fn eq(&self, wl_surface: &WlSurface) -> bool {
|
|
||||||
if let Some(surface) = &self.surface {
|
|
||||||
return surface.surface.detach().eq(wl_surface);
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
pub fn roundtrip(&mut self, ev: Event<M>) -> Result<RenderNode, ()> {
|
|
||||||
let width = self.width();
|
|
||||||
let height = self.height();
|
|
||||||
|
|
||||||
// Sending the event to the widget tree
|
|
||||||
if self.sync(ev) || ev.is_frame() {
|
|
||||||
// Calling the application´s closure
|
|
||||||
(self.cb)(&mut self.core, ev);
|
|
||||||
|
|
||||||
if !self.is_hidden() {
|
|
||||||
let current_width = self.width();
|
|
||||||
let current_height = self.height();
|
|
||||||
|
|
||||||
// Resizing the surface in case the widget changed size
|
|
||||||
if ev.is_frame() {
|
|
||||||
self.ctx.render_node = None;
|
|
||||||
} else if width != current_width || height != current_height {
|
|
||||||
let _ = self.set_size(current_width, current_height);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creating the render node
|
|
||||||
let render_node = self.core.widget.create_node(0., 0.);
|
|
||||||
|
|
||||||
self.ctx.pending_cb = true;
|
|
||||||
|
|
||||||
return Ok(render_node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Calling the application´s closure
|
|
||||||
(self.cb)(&mut self.core, ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
fn render(&mut self, time: u32, recent_node: RenderNode) {
|
|
||||||
let width = recent_node.width();
|
|
||||||
let height = recent_node.height();
|
|
||||||
if Some(time).ne(&self.core.ctx.time) || time == 0 {
|
|
||||||
if let Ok((buffer, wl_buffer)) =
|
|
||||||
Buffer::new(&mut self.core.mempool, width as i32, height as i32)
|
|
||||||
{
|
|
||||||
let mut v = Vec::new();
|
|
||||||
let mut ctx =
|
|
||||||
DrawContext::new(buffer.backend, &mut self.core.ctx.font_cache, &mut v);
|
|
||||||
if let Some(render_node) = self.core.ctx.render_node.as_mut() {
|
|
||||||
if let Err(region) = render_node.draw_merge(
|
|
||||||
recent_node,
|
|
||||||
&mut ctx,
|
|
||||||
&Instruction::empty(0., 0., width, height),
|
|
||||||
None,
|
|
||||||
) {
|
|
||||||
ctx.damage_region(&Background::Transparent, region, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ctx.damage_region(
|
|
||||||
&Background::Transparent,
|
|
||||||
Region::new(0., 0., width, height),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
recent_node.render(&mut ctx, None);
|
|
||||||
self.core.ctx.render_node = Some(recent_node);
|
|
||||||
}
|
|
||||||
self.core.ctx.pending_cb = false;
|
|
||||||
if let Some(surface) = self.core.surface.as_mut() {
|
|
||||||
surface.attach_buffer(wl_buffer);
|
|
||||||
surface.damage(&v);
|
|
||||||
surface.commit();
|
|
||||||
if let Some(_) = self.core.ctx.time {
|
|
||||||
self.core.ctx.time = Some(time);
|
|
||||||
frame_callback::<M, C>(time, surface.surface.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn callback(&mut self, ev: Event<M>) {
|
|
||||||
if self.ctx.time.is_none() || ev.is_cb() {
|
|
||||||
if let Ok(render_node) = self.roundtrip(ev) {
|
|
||||||
if let Some(surface) = self.surface.as_ref() {
|
|
||||||
draw_callback::<M, C>(&surface.surface, render_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let width = self.width();
|
|
||||||
let height = self.height();
|
|
||||||
|
|
||||||
self.sync(ev);
|
|
||||||
|
|
||||||
let current_width = self.width();
|
|
||||||
let current_height = self.height();
|
|
||||||
|
|
||||||
// Resizing the surface in case the widget changed size
|
|
||||||
if width != current_width || height != current_height {
|
|
||||||
let _ = self.set_size(current_width, current_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn frame_callback<M, C>(time: u32, surface: Main<WlSurface>)
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
let h = surface.detach();
|
|
||||||
surface
|
|
||||||
.frame()
|
|
||||||
.quick_assign(move |_, event, mut application| match event {
|
|
||||||
wl_callback::Event::Done { callback_data } => {
|
|
||||||
let timeout = (callback_data - time).min(50);
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
if let Some(inner_application) = application.get_application(&h) {
|
|
||||||
inner_application.ctx.time = None;
|
|
||||||
inner_application.callback(Event::Callback(timeout));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
surface.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_callback<M, C>(surface: &Main<WlSurface>, mut recent_node: RenderNode)
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
let h = surface.detach();
|
|
||||||
surface
|
|
||||||
.frame()
|
|
||||||
.quick_assign(move |_, event, mut application| match event {
|
|
||||||
wl_callback::Event::Done { callback_data } => {
|
|
||||||
if let Some(application) = application.get::<Application<M, C>>() {
|
|
||||||
let inner_application = application.get_application(&h).unwrap();
|
|
||||||
inner_application.render(callback_data, std::mem::take(&mut recent_node));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
surface.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ModifiersState> for Modifiers {
|
|
||||||
fn from(modifer_state: ModifiersState) -> Modifiers {
|
|
||||||
Modifiers {
|
|
||||||
ctrl: modifer_state.ctrl,
|
|
||||||
alt: modifer_state.alt,
|
|
||||||
shift: modifer_state.shift,
|
|
||||||
caps_lock: modifer_state.caps_lock,
|
|
||||||
logo: modifer_state.logo,
|
|
||||||
num_lock: modifer_state.num_lock,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_pointer<M, C>(pointer: &Main<WlPointer>)
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
let mut index = 0;
|
|
||||||
let mut input = Pointer::Enter;
|
|
||||||
let (mut x, mut y) = (0., 0.);
|
|
||||||
pointer.quick_assign(move |_, event, mut inner| match event {
|
|
||||||
wl_pointer::Event::Leave { serial: _, surface } => {
|
|
||||||
input = Pointer::Leave;
|
|
||||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
|
||||||
if let Some(inner_application) = application.get_application(&surface) {
|
|
||||||
inner_application.callback(Event::Pointer(x as f32, y as f32, input));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_pointer::Event::Button {
|
|
||||||
serial: _,
|
|
||||||
time,
|
|
||||||
button,
|
|
||||||
state,
|
|
||||||
} => {
|
|
||||||
input = Pointer::MouseClick {
|
|
||||||
time,
|
|
||||||
button: MouseButton::new(button),
|
|
||||||
pressed: state == wl_pointer::ButtonState::Pressed,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
wl_pointer::Event::Frame => {
|
|
||||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
|
||||||
let inner_application = application.inner.get_mut(index).unwrap();
|
|
||||||
inner_application.callback(Event::Pointer(x as f32, y as f32, input));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_pointer::Event::Axis {
|
|
||||||
time: _,
|
|
||||||
axis,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
input = Pointer::Scroll {
|
|
||||||
orientation: match axis {
|
|
||||||
wl_pointer::Axis::VerticalScroll => Orientation::Vertical,
|
|
||||||
wl_pointer::Axis::HorizontalScroll => Orientation::Horizontal,
|
|
||||||
_ => Orientation::Vertical,
|
|
||||||
},
|
|
||||||
value: value as f32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_pointer::Event::Enter {
|
|
||||||
serial: _,
|
|
||||||
surface,
|
|
||||||
surface_x,
|
|
||||||
surface_y,
|
|
||||||
} => {
|
|
||||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
|
||||||
x = surface_x;
|
|
||||||
y = surface_y;
|
|
||||||
index = application.get_index(&surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wl_pointer::Event::Motion {
|
|
||||||
time: _,
|
|
||||||
surface_x,
|
|
||||||
surface_y,
|
|
||||||
} => {
|
|
||||||
x = surface_x;
|
|
||||||
y = surface_y;
|
|
||||||
input = Pointer::Hover;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_surface<M, C>(shell: &Main<ZwlrLayerSurfaceV1>)
|
|
||||||
where
|
|
||||||
M: 'static,
|
|
||||||
C: Controller<M> + Clone + 'static,
|
|
||||||
{
|
|
||||||
shell.quick_assign(move |shell, event, mut inner| match event {
|
|
||||||
zwlr_layer_surface_v1::Event::Configure {
|
|
||||||
serial,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
} => {
|
|
||||||
shell.ack_configure(serial);
|
|
||||||
println!("\nCONFIGURE - {} : {} X {}\n", serial, width, height);
|
|
||||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
|
||||||
for inner_application in &mut application.inner {
|
|
||||||
if let Some(app_surface) = inner_application.surface.as_mut() {
|
|
||||||
match &app_surface.shell {
|
|
||||||
Shell::LayerShell { config: _, surface } => {
|
|
||||||
if shell.eq(surface) {
|
|
||||||
app_surface.destroy_previous();
|
|
||||||
let _ = inner_application
|
|
||||||
.widget
|
|
||||||
.set_size(width as f32, height as f32);
|
|
||||||
if inner_application.ctx.pending_cb {
|
|
||||||
if let Ok(render_node) =
|
|
||||||
inner_application.roundtrip(Event::Frame)
|
|
||||||
{
|
|
||||||
draw_callback::<M, C>(
|
|
||||||
&inner_application
|
|
||||||
.surface
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.surface,
|
|
||||||
render_node,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Ok(render_node) =
|
|
||||||
inner_application.roundtrip(Event::Frame)
|
|
||||||
{
|
|
||||||
inner_application.render(0, render_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
});
|
|
||||||
}
|
|
53
samples/scala.scala
Normal file
53
samples/scala.scala
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import scala.collection.mutable._
|
||||||
|
import java.util.TreeMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ScalaDoc comment: <code>Some code</code>
|
||||||
|
* Html escape sequence ^
|
||||||
|
* ''Text''
|
||||||
|
*
|
||||||
|
* @param x Int param
|
||||||
|
* @author IntelliJ
|
||||||
|
*/
|
||||||
|
class ScalaClass(x: Int) extends ScalaObject {
|
||||||
|
1 to 5
|
||||||
|
(x: Int) => x
|
||||||
|
val field = "Some\nStrin\g"
|
||||||
|
|
||||||
|
def foo(x: Float, y: Float) = {
|
||||||
|
def empty = 2
|
||||||
|
|
||||||
|
val local = 1000 - empty
|
||||||
|
Math.sqrt(x + y + local); //this can crash
|
||||||
|
}
|
||||||
|
|
||||||
|
def t[T]: T = null
|
||||||
|
|
||||||
|
foo(0, -1) match {
|
||||||
|
case x => x
|
||||||
|
}
|
||||||
|
type G = Int
|
||||||
|
val xml = <element attibute="value">data</element>
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
And now ScalaObject
|
||||||
|
*/
|
||||||
|
object Object {
|
||||||
|
val layer = -5.0
|
||||||
|
val mutableCollection = HashMap[Int, Int]()
|
||||||
|
val immutableCollection = List(1, 2)
|
||||||
|
val javaCollection = new TreeMap[Int, Int]()
|
||||||
|
|
||||||
|
def foo: ScalaClass = new ScalaClass(23, 9)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Annotation(2) {val name = value}
|
||||||
|
trait Trait {
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SomeAbstract {
|
||||||
|
for (x <- list) {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}
|
14
samples/sql.sql
Normal file
14
samples/sql.sql
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-- DDL section
|
||||||
|
create table crm.product (
|
||||||
|
id numeric primary key,
|
||||||
|
title varchar(255) character set utf8
|
||||||
|
);
|
||||||
|
-- DML section
|
||||||
|
insert into product
|
||||||
|
values (1, 'Product1');
|
||||||
|
|
||||||
|
select count(*) from crm.product;
|
||||||
|
select id as ProductID, title as ProductName
|
||||||
|
from crm.product where id = :id;
|
||||||
|
|
||||||
|
\set content `cat data.txt`
|
32
samples/toml.toml
Normal file
32
samples/toml.toml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# This is a TOML document.
|
||||||
|
|
||||||
|
title = "TOML Example"
|
||||||
|
description = """
|
||||||
|
Multiline
|
||||||
|
description
|
||||||
|
"""
|
||||||
|
date = 2019-11-04T07:32:00-08:00
|
||||||
|
|
||||||
|
[database]
|
||||||
|
server = "192.168.1.1"
|
||||||
|
ports = [ 8001, 8001, 8002 ]
|
||||||
|
"connection_max" = 5000
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
[servers]
|
||||||
|
alpha = { ip = '10.0.0.1', dc = "eqdc10" }
|
||||||
|
beta = { ip = '10.0.0.2', dc = "eqdc10" }
|
||||||
|
|
||||||
|
[clients]
|
||||||
|
data = [ ["gamma", "delta"], [1.0, 2.0] ]
|
||||||
|
|
||||||
|
hosts = [
|
||||||
|
"alpha",
|
||||||
|
"omega",
|
||||||
|
]
|
||||||
|
|
||||||
|
valid-escapes = """\tline \"1\"
|
||||||
|
line\u00202
|
||||||
|
line 3\U0000002E
|
||||||
|
"""
|
||||||
|
invalid-escapes = "\a \u20 \U0020"
|
|
@ -1,110 +1,54 @@
|
||||||
// src: https://github.com/n8n-io/n8n/blob/master/packages/core/src/Credentials.ts
|
module ModuleValidator {
|
||||||
|
import checkChars = CharUtils.notWhiteSpace
|
||||||
|
|
||||||
import {
|
export interface HasValidator<T> {
|
||||||
CredentialInformation,
|
validateValue(): Boolean;
|
||||||
ICredentialDataDecryptedObject,
|
}
|
||||||
ICredentials,
|
|
||||||
ICredentialsEncrypted,
|
|
||||||
} from 'n8n-workflow';
|
|
||||||
|
|
||||||
import { AES, enc } from 'crypto-js';
|
type FooBarAlias = string;
|
||||||
|
|
||||||
export class Credentials extends ICredentials {
|
@decorator()
|
||||||
/**
|
class HasValidator implements HasValidator<String> {
|
||||||
* Returns if the given nodeType has access to data
|
/* Processed values */
|
||||||
*/
|
static validatedValue: Array<String> = ['', 'aa']
|
||||||
hasNodeAccess(nodeType: string): boolean {
|
private myValue: String
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
for (const accessData of this.nodesAccess) {
|
|
||||||
if (accessData.nodeType === nodeType) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
/**
|
||||||
}
|
* Constructor for class
|
||||||
|
* @param valueParameter Value for <i>validation</i>
|
||||||
|
*/
|
||||||
|
constructor(valueParameter: String) {
|
||||||
|
this.myValue = valueParameter
|
||||||
|
HasValidator.validatedValue.push(value)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public validateValue(): Boolean {
|
||||||
* Sets new credential object
|
var resultValue: Boolean = checkChars(this.myValue)
|
||||||
*/
|
return resultValue
|
||||||
setData(data: ICredentialDataDecryptedObject, encryptionKey: string): void {
|
}
|
||||||
this.data = AES.encrypt(JSON.stringify(data), encryptionKey).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
static createInstance(valueParameter: string): HasValidator {
|
||||||
* Sets new credentials for given key
|
return new HasValidator(valueParameter)
|
||||||
*/
|
}
|
||||||
setDataKey(key: string, data: CredentialInformation, encryptionKey: string): void {
|
}
|
||||||
let fullData;
|
|
||||||
try {
|
|
||||||
fullData = this.getData(encryptionKey);
|
|
||||||
} catch (e) {
|
|
||||||
fullData = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
fullData[key] = data;
|
function globalFunction<TypeParameter>(value: TypeParameter) { //global function
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
|
||||||
return this.setData(fullData, encryptionKey);
|
declare var declareUrl
|
||||||
}
|
var varUrl = declareUrl.replace(/^\s*(.*)/, '$1').concat('\u1111\z\n\u22')
|
||||||
|
var html = `<div title='HTML injection'>Injected language fragment</div>`
|
||||||
|
var hello = () => console.log('hello')
|
||||||
|
HasValidator.createInstance(varUrl).validateValue()
|
||||||
|
|
||||||
/**
|
function acceptsUnion(s: string | number) {
|
||||||
* Returns the decrypted credential object
|
if (typeof s === 'string') {
|
||||||
*/
|
s
|
||||||
getData(encryptionKey: string, nodeType?: string): ICredentialDataDecryptedObject {
|
}
|
||||||
if (nodeType && !this.hasNodeAccess(nodeType)) {
|
}
|
||||||
throw new Error(
|
|
||||||
`The node of type "${nodeType}" does not have access to credentials "${this.name}" of type "${this.type}".`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.data === undefined) {
|
enum EnumName {
|
||||||
throw new Error('No data is set so nothing can be returned.');
|
EnumMember
|
||||||
}
|
}
|
||||||
|
|
||||||
const decryptedData = AES.decrypt(this.data, encryptionKey);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
||||||
return JSON.parse(decryptedData.toString(enc.Utf8));
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(
|
|
||||||
'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the decrypted credentials for given key
|
|
||||||
*/
|
|
||||||
getDataKey(key: string, encryptionKey: string, nodeType?: string): CredentialInformation {
|
|
||||||
const fullData = this.getData(encryptionKey, nodeType);
|
|
||||||
|
|
||||||
if (fullData === null) {
|
|
||||||
throw new Error(`No data was set.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
|
||||||
if (!fullData.hasOwnProperty(key)) {
|
|
||||||
throw new Error(`No data for key "${key}" exists.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fullData[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the encrypted credentials to be saved
|
|
||||||
*/
|
|
||||||
getDataToSave(): ICredentialsEncrypted {
|
|
||||||
if (this.data === undefined) {
|
|
||||||
throw new Error(`No credentials were set to save.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
name: this.name,
|
|
||||||
type: this.type,
|
|
||||||
data: this.data,
|
|
||||||
nodesAccess: this.nodesAccess,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
19
samples/yaml.yaml
Normal file
19
samples/yaml.yaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||||
|
static_sidebar:
|
||||||
|
id: "foo"
|
||||||
|
name: 'side_bar'
|
||||||
|
staged_position: 1
|
||||||
|
blog_id: 1
|
||||||
|
config: |+
|
||||||
|
--- !map:HashWithIndifferentAccess
|
||||||
|
title: Static Sidebar
|
||||||
|
body: The body of a static sidebar
|
||||||
|
type: StaticSidebar
|
||||||
|
description: >
|
||||||
|
Sidebar configuration example
|
||||||
|
extensions:
|
||||||
|
- ¶ms
|
||||||
|
auto_run: true
|
||||||
|
reload: true
|
||||||
|
- *params
|
Loading…
Reference in a new issue