├── files
├── window.gif
├── settings.png
└── 劝学.txt
├── src
└── main
│ ├── resources
│ ├── icons
│ │ └── fish_14.png
│ └── META-INF
│ │ └── plugin.xml
│ └── java
│ └── cn
│ └── luojunhui
│ └── touchfish
│ ├── windwos
│ ├── BookWindowFactory.java
│ ├── Book.form
│ └── Book.java
│ └── config
│ ├── BookSettingsState.java
│ ├── BookSettingsComponent.java
│ └── BookSettingsConfigurable.java
├── .gitattributes
├── settings.gradle
├── .gitignore
├── README.md
├── LICENSE
├── gradlew.bat
└── gradlew
/files/window.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luojunhui/touch-fish/HEAD/files/window.gif
--------------------------------------------------------------------------------
/files/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luojunhui/touch-fish/HEAD/files/settings.png
--------------------------------------------------------------------------------
/src/main/resources/icons/fish_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luojunhui/touch-fish/HEAD/src/main/resources/icons/fish_14.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | #
2 | # https://help.github.com/articles/dealing-with-line-endings/
3 | #
4 | # These are explicitly windows files and should use crlf
5 | *.bat text eol=crlf
6 |
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This file was generated by the Gradle 'init' task.
3 | *
4 | * The settings file is used to specify which projects to include in your build.
5 | *
6 | * Detailed information about configuring a multi-project build in Gradle can be found
7 | * in the user manual at https://docs.gradle.org/6.7.1/userguide/multi_project_builds.html
8 | */
9 |
10 | rootProject.name = 'touch-fish'
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | .idea/
26 | out/
27 | build/
28 | .gradle/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # touch-fish
2 | 一款jetbrains旗下的ide上touch fish(摸鱼)的插件,一般用来看小说?
3 |
4 | # 效果图
5 | 
6 |
7 | # 插件安装
8 | 直接在Settings的Plugins搜Touch Fish安装.
9 |
10 | # 手动安装
11 | 以IDEA为例:
12 | ```Intellij IDEA File——>Settings——>IDE setttings——>Plugins——>Install plugin from disk```
13 |
14 | 选择`touch-fish.jar`,完成后重启IDEA,可以看到IDEA下方工具栏(与Terminal同一行)里多了个`Touch Fish`了.
15 | `touch-fish.jar`文件请到[https://github.com/luojunhui/touch-fish/releases](https://github.com/luojunhui/touch-fish/releases)下载最新版,也可以下载本项目后自行编译.
16 |
17 |
18 | # 使用
19 |
20 | > 1. 打开settings下的`Touch Fish`,输入文本文件的`绝对路径`/当前页/每页加载行数后保存(如下图所示),然后重启IDEA.
21 | > 2. 打开`Touch Fish`窗口,如无意外就能看到文本内容了.
22 | > 3. 快捷键↑向上读取内容,↓向下读取内容.
23 |
24 | 
25 |
26 | # 设置快捷键
27 | 给`Touch Fish`窗口加一个呼出隐藏的快捷键吧,
28 | 打开IDEA的```settings```里的```keymap```,
29 | 在搜索框内搜索`Touch Fish`后,
30 | 右键添加自定义快捷键.
--------------------------------------------------------------------------------
/src/main/java/cn/luojunhui/touchfish/windwos/BookWindowFactory.java:
--------------------------------------------------------------------------------
1 | package cn.luojunhui.touchfish.windwos;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.wm.ToolWindow;
5 | import com.intellij.openapi.wm.ToolWindowFactory;
6 | import com.intellij.ui.content.Content;
7 | import com.intellij.ui.content.ContentFactory;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | /**
11 | * BookWindowFactory.class
12 | * 添加自定义的toolWindow
13 | * @author junhui
14 | */
15 | public class BookWindowFactory implements ToolWindowFactory {
16 | @Override
17 | public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
18 | Book book = new Book(toolWindow);
19 | ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
20 | Content content = contentFactory.createContent(book.getContent(), "", false);
21 | toolWindow.getContentManager().addContent(content);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 junhui
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/main/java/cn/luojunhui/touchfish/windwos/Book.form:
--------------------------------------------------------------------------------
1 |
2 |
24 |
--------------------------------------------------------------------------------
/files/劝学.txt:
--------------------------------------------------------------------------------
1 | 君子曰:学不可以已。
2 |
3 | 青,取之于蓝,而青于蓝;冰,水为之,而寒于水。木直中绳,輮以为轮,其曲中规。虽有槁暴,不复挺者,輮使之然也。故木受绳则直,金就砺则利,君子博学而日参省乎己,则知明而行无过矣。
4 |
5 | 故不登高山,不知天之高也;不临深溪,不知地之厚也;不闻先王之遗言,不知学问之大也。干、越、夷、貉之子,生而同声,长而异俗,教使之然也。诗曰:“嗟尔君子,无恒安息。靖共尔位,好是正直。神之听之,介尔景福。”神莫大于化道,福莫长于无祸。(此段教材无)
6 |
7 | 吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。登高而招,臂非加长也,而见者远;顺风而呼,声非加疾也,而闻者彰。假舆马者,非利足也,而致千里;假舟楫者,非能水也,而绝江河。君子生非异也,善假于物也。
8 |
9 | 南方有鸟焉,名曰蒙鸠,以羽为巢,而编之以发,系之苇苕,风至苕折,卵破子死。巢非不完也,所系者然也。西方有木焉,名曰射干,茎长四寸,生于高山之上,而临百仞之渊,木茎非能长也,所立者然也。蓬生麻中,不扶而直;白沙在涅,与之俱黑。兰槐之根是为芷,其渐之滫,君子不近,庶人不服。其质非不美也,所渐者然也。故君子居必择乡,游必就士,所以防邪辟而近中正也。
10 |
11 | 物类之起,必有所始。荣辱之来,必象其德。肉腐出虫,鱼枯生蠹。怠慢忘身,祸灾乃作。强自取柱,柔自取束。邪秽在身,怨之所构。施薪若一,火就燥也,平地若一,水就湿也。草木畴生,禽兽群焉,物各从其类也。是故质的张,而弓矢至焉;林木茂,而斧斤至焉;树成荫,而众鸟息焉。醯酸,而蚋聚焉。故言有招祸也,行有招辱也,君子慎其所立乎!(此段教材无)
12 |
13 | 积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。
14 |
15 | 是故无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。行衢道者不至,事两君者不容。目不能两视而明,耳不能两听而聪。螣蛇无足而飞,鼫鼠五技而穷。《诗》曰:“尸鸠在桑,其子七兮。淑人君子,其仪一兮。其仪一兮,心如结兮!”故君子结于一也。
16 |
17 | 昔者瓠巴鼓瑟,而流鱼出听;伯牙鼓琴,而六马仰秣。故声无小而不闻,行无隐而不形。玉在山而草润,渊生珠而崖不枯。为善不积邪?安有不闻者乎?
18 |
19 | 学恶乎始?恶乎终?曰:其数则始乎诵经,终乎读礼;其义则始乎为士,终乎为圣人,真积力久则入,学至乎没而后止也。故学数有终,若其义则不可须臾舍也。为之,人也;舍 之,禽兽也。故书者,政事之纪也;诗者,中声之所止也;礼者,法之大分,类之纲纪也。故学至乎礼而止矣。夫是之谓道德之极。礼之敬文也,乐之中和也,诗书之博也,春秋之微 也,在天地之间者毕矣。君子之学也,入乎耳,着乎心,布乎四体,形乎动静。端而言,蝡而动,一可以为法则。小人之学也,入乎耳,出乎口;口耳之间,则四寸耳,曷足以美七尺之躯哉!古之学者为己,今之学者为人。君子之学也,以美其身;小人之学也,以为禽犊。故不问而告谓之傲,问一而告二谓之囋。傲、非也,囋、非也;君子如向矣。
20 |
21 | 学莫便乎近其人。礼乐法而不说,诗书故而不切,春秋约而不速。方其人之习君子之说,则尊以遍矣,周于世矣。故曰:学莫便乎近其人。
22 |
23 | 学之经莫速乎好其人,隆礼次之。上不能好其人,下不能隆礼,安特将学杂识志,顺诗书而已耳。则末世穷年,不免为陋儒而已。将原先王,本仁义,则礼正其经纬蹊径也。若挈裘领,诎五指而顿之,顺者不可胜数也。不道礼宪,以诗书为之,譬之犹以指测河也,以戈舂黍也,以锥餐壶也,不可以得之矣。故隆礼,虽未明,法士也;不隆礼,虽察辩,散儒也。
24 |
25 | 问楛者,勿告也;告楛者,勿问也;说楛者,勿听也。有争气者,勿与辩也。故必由其道至,然后接之;非其道则避之。故礼恭,而后可与言道之方;辞顺,而后可与言道之理;色从而后可与言道之致。故未可与言而言,谓之傲;可与言而不言,谓之隐;不观气色而言,谓瞽。故君子不傲、不隐、不瞽,谨顺其身。诗曰:“匪交匪舒,天子所予。”此之谓也。
26 |
27 | 百发失一,不足谓善射;千里蹞步不至,不足谓善御;伦类不通,仁义不一,不足谓善学。学也者,固学一之也。一出焉,一入焉,涂巷之人也;其善者少,不善者多,桀纣盗跖也;全之尽之,然后学者也。
28 |
29 | 君子知夫不全不粹之不足以为美也,故诵数以贯之,思索以通之,为其人以处之,除其害者以持养之。使目非是无欲见也,使耳非是无欲闻也,使口非是无欲言也,使心非是无欲虑也。及至其致好之也,目好之五色,耳好之五声,口好之五味,心利之有天下。是故权利不能倾也,群众不能移也,天下不能荡也。生乎由是,死乎由是,夫是之谓德操。德操然后能定,能定然后能应。能定能应,夫是之谓成人。天见其明,地见其光,君子贵其全也。
--------------------------------------------------------------------------------
/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | cn.luojunhui.touchfish
3 | Touch Fish
4 | 2.3.1
5 | luojunhui
6 |
7 |
8 |
9 | If you have nothing to do, why don't you try reading with this plugin?
11 |
12 | - Find the "Touch Fish" settings interface under ide settings.
13 | - Choose the text file.
14 | - Enter page number and number of rows per page.
15 | - Shortcut key ↑ read content up
16 | - Shortcut ↓ read content down
17 | - In keymap, you can set shortcut keys for text windows, which can quickly exhale and hide.
18 |
19 |
20 | 如果你无事可作,为何不试试用此插件看书呢?
21 |
22 | - 在ide设置下找到“Touch Fish”设置界面。
23 | - 选择你想要阅读的txt文件
24 | - 输入页码和每次阅读多少行
25 | - 快捷键↑向上读取内容
26 | - 快捷键↓向下读取内容
27 | - 在keymap里可以给本插件设置快捷键,可以快速呼出与隐藏
28 |
29 | 项目地址:https://github.com/luojunhui/touch-fish
30 | 如果有bug,请在help - Show Log in Explorer里查找idea.log相关报错信息,与我联系
31 | ]]>
32 |
33 |
34 |
35 |
36 |
38 | v2.3.2 support IntelliJ Platform version 2022.1 version
39 | v2.3.1 using Gradle as a build system. fix bugs.
40 | v2.3 change input file path to select file on settings form
41 | v2.2 add change notes description in English
42 | V2.1 add plugin description in English and modify the text of the settings interface.
43 | V2.0 change the way to turn pages.
44 | V1.1 fix bugs.
45 | V1.0 release.
46 |
47 | ]]>
48 |
49 |
50 | com.intellij.modules.platform
51 |
52 |
53 |
56 |
58 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/main/java/cn/luojunhui/touchfish/config/BookSettingsState.java:
--------------------------------------------------------------------------------
1 | package cn.luojunhui.touchfish.config;
2 |
3 | import com.intellij.openapi.components.PersistentStateComponent;
4 | import com.intellij.openapi.components.ServiceManager;
5 | import com.intellij.openapi.components.State;
6 | import com.intellij.openapi.components.Storage;
7 | import com.intellij.util.xmlb.XmlSerializerUtil;
8 | import org.jetbrains.annotations.NotNull;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * 持久存储自定义设置
16 | * https://jetbrains.org/intellij/sdk/docs/tutorials/settings_tutorial.html#declaring-appsettingsstate
17 | *
18 | * @author : junhui.luo
19 | * @version V1.0
20 | * @date Date : 2020年11月27日
21 | */
22 | @State(
23 | name = "cn.luojunhui.touchfish.config.BookSettingsState",
24 | storages = {@Storage("TouchFishSettingsPlugin.xml")}
25 | )
26 | public class BookSettingsState implements PersistentStateComponent {
27 | /**
28 | * txt文本的绝对路径
29 | */
30 | private String bookPath = "";
31 | /**
32 | * 当前页码
33 | */
34 | private Integer page = 1;
35 | /**
36 | * 每页展示多少行文字
37 | */
38 | private Integer pageSize = 3;
39 | /**
40 | * txt文本按pageSize分页的总页码
41 | */
42 | private Integer totalPage = 0;
43 | /**
44 | * txt内容,当文本内容过大时,会占用很多内存,建议分割成多个txt文件
45 | */
46 | private List lines = new ArrayList<>();
47 |
48 | /**
49 | * 获取配置实例
50 | *
51 | * @return
52 | */
53 | public static BookSettingsState getInstance() {
54 | return ServiceManager.getService(BookSettingsState.class);
55 | }
56 |
57 | @Nullable
58 | @Override
59 | public BookSettingsState getState() {
60 | return this;
61 | }
62 |
63 | @Override
64 | public void loadState(@NotNull BookSettingsState appSettingsState) {
65 | XmlSerializerUtil.copyBean(appSettingsState, this);
66 | }
67 |
68 | public String getBookPath() {
69 | return bookPath;
70 | }
71 |
72 | public void setBookPath(String bookPath) {
73 | this.bookPath = bookPath;
74 | }
75 |
76 | public Integer getPage() {
77 | return page;
78 | }
79 |
80 | public void setPage(Integer page) {
81 | this.page = page;
82 | }
83 |
84 | public Integer getPageSize() {
85 | return pageSize;
86 | }
87 |
88 | public void setPageSize(Integer pageSize) {
89 | this.pageSize = pageSize;
90 | }
91 |
92 | public Integer getTotalPage() {
93 | return totalPage;
94 | }
95 |
96 | public void setTotalPage(Integer totalPage) {
97 | this.totalPage = totalPage;
98 | }
99 |
100 | public List getLines() {
101 | return lines;
102 | }
103 |
104 | public void setLines(List lines) {
105 | this.lines = lines;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/cn/luojunhui/touchfish/config/BookSettingsComponent.java:
--------------------------------------------------------------------------------
1 | package cn.luojunhui.touchfish.config;
2 |
3 | import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
4 | import com.intellij.openapi.ui.TextFieldWithBrowseButton;
5 | import com.intellij.openapi.util.text.StringUtil;
6 | import com.intellij.ui.components.JBLabel;
7 | import com.intellij.util.ui.FormBuilder;
8 |
9 | import javax.swing.*;
10 |
11 | /**
12 | * 配置页的表单
13 | */
14 | public class BookSettingsComponent {
15 |
16 | private final JPanel settingPanel;
17 | private final TextFieldWithBrowseButton chooseFileBtn = new TextFieldWithBrowseButton();
18 | private JTextField pageTextField = new JTextField();
19 | private JTextField pageSizeTextField = new JTextField();
20 |
21 |
22 | public BookSettingsComponent() {
23 | settingPanel = FormBuilder.createFormBuilder()
24 | .addLabeledComponent(new JBLabel("文件路径: "), chooseFileBtn, 1, false)
25 | .addLabeledComponent(new JBLabel("每页行数: "), pageSizeTextField, 1, false)
26 | .addLabeledComponent(new JBLabel("当前页码: "), pageTextField, 1, false)
27 | .getPanel();
28 | }
29 |
30 | /**
31 | * 表单初始化赋值
32 | */
33 | public void init() {
34 | //按钮绑定事件
35 | this.chooseFileBtn.addBrowseFolderListener("选择文件", null, null,
36 | FileChooserDescriptorFactory.createSingleFileDescriptor("txt"));
37 |
38 | BookSettingsState settings = BookSettingsState.getInstance().getState();
39 | String bookPath = settings.getBookPath();
40 | if (StringUtil.isNotEmpty(bookPath)) {
41 | this.setBookPath(bookPath.trim());
42 | this.setPage(settings.getPage());
43 | this.setPageSize(settings.getPageSize());
44 | }
45 | }
46 |
47 | public JPanel getPanel() {
48 | return settingPanel;
49 | }
50 |
51 | public String getBookPath() {
52 | return chooseFileBtn.getTextField().getText();
53 | }
54 |
55 | public void setBookPath(String s) {
56 | this.chooseFileBtn.getTextField().setText(s);
57 | }
58 |
59 | /**
60 | * 获取设置的行数,不能小于1
61 | *
62 | * @return
63 | */
64 | public int getPage() {
65 | int line = Integer.valueOf(this.pageTextField.getText());
66 | if (line < 1) {
67 | this.pageTextField.setText("1");
68 | return 1;
69 | }
70 | return line;
71 | }
72 |
73 | public void setPage(int line) {
74 | this.pageTextField.setText(String.valueOf(line));
75 | }
76 |
77 | /**
78 | * 获取加载行数,不能小于1
79 | *
80 | * @return
81 | */
82 | public int getPageSize() {
83 | int rowCount = Integer.valueOf(this.pageSizeTextField.getText());
84 | if (rowCount < 1) {
85 | this.setPageSize(1);
86 | return 1;
87 | }
88 | return rowCount;
89 | }
90 |
91 | public void setPageSize(int rowCount) {
92 | this.pageSizeTextField.setText(String.valueOf(rowCount));
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/main/java/cn/luojunhui/touchfish/config/BookSettingsConfigurable.java:
--------------------------------------------------------------------------------
1 | package cn.luojunhui.touchfish.config;
2 |
3 | import com.intellij.openapi.diagnostic.Logger;
4 | import com.intellij.openapi.options.Configurable;
5 | import com.intellij.openapi.options.ConfigurationException;
6 | import com.intellij.openapi.util.NlsContexts;
7 | import com.intellij.util.ExceptionUtil;
8 | import org.apache.commons.lang.StringUtils;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import javax.swing.*;
12 | import java.io.IOException;
13 | import java.nio.file.Files;
14 | import java.nio.file.Paths;
15 | import java.util.List;
16 | import java.util.Optional;
17 |
18 | /**
19 | * 修改配置
20 | * @author : junhui.luo
21 | * @version V1.0
22 | * @date Date : 2020年11月27日
23 | */
24 | public class BookSettingsConfigurable implements Configurable {
25 | private static final Logger LOGGER = Logger.getInstance(BookSettingsConfigurable.class);
26 | private BookSettingsComponent bookSettingsComponent;
27 |
28 | public BookSettingsConfigurable() {
29 | }
30 |
31 | @Override
32 | public @NlsContexts.ConfigurableName String getDisplayName() {
33 | return "Touch Fish";
34 | }
35 |
36 | /**
37 | * 创建一个Component用于展示
38 | * @return bookSettingsComponent
39 | */
40 | @Nullable
41 | @Override
42 | public JComponent createComponent() {
43 | if (this.bookSettingsComponent == null) {
44 | this.bookSettingsComponent = new BookSettingsComponent();
45 | try {
46 | this.bookSettingsComponent.init();
47 | }catch (Exception e){
48 | String errInfo = "设置面板出现错误:\n" + ExceptionUtil.currentStackTrace();
49 | LOGGER.error(errInfo,e);
50 | }
51 | }
52 | return this.bookSettingsComponent.getPanel();
53 | }
54 |
55 | /**
56 | * IDEA 初始化设置页面时,判断 "Apply" 按钮是否为可用
57 | * 存在条件修改返回true
58 | * @return true 是;false 否
59 | */
60 | @Override
61 | public boolean isModified() {
62 | if (this.bookSettingsComponent == null) {
63 | return false;
64 | }
65 | BookSettingsState settings = BookSettingsState.getInstance();
66 | String inputFilePath = this.bookSettingsComponent.getBookPath();
67 | int inputPage = this.bookSettingsComponent.getPage();
68 | int inputPageSize = this.bookSettingsComponent.getPageSize();
69 | return !StringUtils.equals(settings.getBookPath().trim(), inputFilePath)
70 | || settings.getPage() != inputPage
71 | || settings.getPageSize() != inputPageSize;
72 | }
73 |
74 | /**
75 | * 用户点击 "Apply" 按钮或 "OK" 按钮之后,会调用此方法
76 | */
77 | @Override
78 | public void apply() throws ConfigurationException {
79 | if (null == this.bookSettingsComponent) {
80 | return;
81 | }
82 | BookSettingsState settings = BookSettingsState.getInstance();
83 | if (settings == null) {
84 | String errInfo = "Touch Fish 工具设置对象为空,请查看idea.log查询更多信息";
85 | LOGGER.error(errInfo);
86 | throw new ConfigurationException(errInfo);
87 | }
88 | settings.setBookPath(this.bookSettingsComponent.getBookPath());
89 | settings.setPage(this.bookSettingsComponent.getPage());
90 | settings.setPageSize(this.bookSettingsComponent.getPageSize());
91 | // 更新文本内容
92 | List lines;
93 | try {
94 | lines = Files.readAllLines(Paths.get(settings.getBookPath()));
95 | int totalPage = (lines.size() + settings.getPageSize() - 1) / settings.getPageSize();
96 | settings.setTotalPage(totalPage);
97 | settings.setLines(lines);
98 | } catch (IOException e) {
99 | throw new ConfigurationException("读取文件失败!");
100 | }
101 | }
102 |
103 | /**
104 | * 重置值
105 | */
106 | @Override
107 | public void reset() {
108 | BookSettingsState settings = BookSettingsState.getInstance().getState();
109 | String bookPath = Optional.of(settings).map(s->s.getBookPath()).orElse("");
110 | int page = Optional.of(settings).map(s->s.getPage()).orElse(1);
111 | int pageSize = Optional.of(settings).map(s->s.getPageSize()).orElse(5);
112 | this.bookSettingsComponent.setBookPath(bookPath);
113 | this.bookSettingsComponent.setPage(page);
114 | this.bookSettingsComponent.setPageSize(pageSize);
115 | }
116 |
117 | /**
118 | * IDEA 销毁设置页面后,会调用此方法
119 | */
120 | @Override
121 | public void disposeUIResources() {
122 | this.bookSettingsComponent = null;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/cn/luojunhui/touchfish/windwos/Book.java:
--------------------------------------------------------------------------------
1 | package cn.luojunhui.touchfish.windwos;
2 |
3 | import cn.luojunhui.touchfish.config.BookSettingsState;
4 | import com.intellij.notification.Notification;
5 | import com.intellij.notification.NotificationType;
6 | import com.intellij.notification.Notifications;
7 | import com.intellij.openapi.diagnostic.Logger;
8 | import com.intellij.openapi.util.text.StringUtil;
9 | import com.intellij.openapi.wm.ToolWindow;
10 |
11 | import javax.swing.*;
12 | import java.awt.event.KeyEvent;
13 | import java.awt.event.KeyListener;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.stream.Collectors;
17 |
18 | /**
19 | * Book.class
20 | *
21 | * @author junhui
22 | */
23 | public class Book {
24 | private static final Logger LOGGER = Logger.getInstance(Book.class);
25 |
26 | private static final int PREV = 0;
27 | private static final int NEXT = 1;
28 | private static final int CURRENT = 2;
29 |
30 | private JPanel book;
31 | private JTextPane text;
32 |
33 | public Book(ToolWindow toolWindow) {
34 | this.init();
35 | }
36 |
37 |
38 | private void init() {
39 | BookSettingsState settings = BookSettingsState.getInstance().getState();
40 | if (settings == null) {
41 | String info = "请先到插件面板设置阅读信息。";
42 | LOGGER.info(info);
43 | Notifications.Bus.notify(new Notification("", "tip", info, NotificationType.INFORMATION));
44 | return;
45 | }
46 | if (StringUtil.isNotEmpty(settings.getBookPath())) {
47 | this.readText(CURRENT);
48 | } else {
49 | this.setText("没有文本文件路径...");
50 | }
51 |
52 | // 设置键盘监听
53 | this.text.addKeyListener(new KeyListener() {
54 | @Override
55 | public void keyTyped(KeyEvent keyEvent) {
56 | }
57 |
58 | @Override
59 | public void keyPressed(KeyEvent keyEvent) {
60 | boolean isNext = keyEvent.getKeyCode() == KeyEvent.VK_DOWN;
61 | boolean isPrev = keyEvent.getKeyCode() == KeyEvent.VK_UP;
62 | if (isNext) {
63 | readText(NEXT);
64 | } else if (isPrev) {
65 | readText(PREV);
66 | }
67 | }
68 |
69 | @Override
70 | public void keyReleased(KeyEvent keyEvent) {
71 | }
72 | });
73 | }
74 |
75 | /**
76 | * 按页读取内容
77 | *
78 | * @param op user option
79 | */
80 | private void readText(int op) {
81 | BookSettingsState settings = BookSettingsState.getInstance().getState();
82 | if (settings == null) {
83 | String info = "请先到插件面板设置阅读信息。";
84 | LOGGER.info(info);
85 | Notifications.Bus.notify(new Notification("", "tip", info, NotificationType.INFORMATION));
86 | return;
87 | }
88 | int curPage = settings.getPage();
89 | List list = null;
90 | switch (op) {
91 | case PREV:
92 | int prevPage = curPage == 1 ? curPage : curPage - 1;
93 | list = this.readFromPage(settings.getLines(), prevPage, settings.getPageSize());
94 | if (prevPage == curPage) {
95 | Notifications.Bus.notify(new Notification("", "tip", "不能再往前翻页了...", NotificationType.INFORMATION));
96 | settings.setPage(1);
97 | } else {
98 | settings.setPage(prevPage);
99 | }
100 | break;
101 | case NEXT:
102 | int nextPage = curPage == settings.getTotalPage() ? curPage : curPage + 1;
103 | list = this.readFromPage(settings.getLines(), nextPage, settings.getPageSize());
104 | if (nextPage == curPage) {
105 | Notifications.Bus.notify(new Notification("", "tip", "不能再后前翻页了...", NotificationType.INFORMATION));
106 | settings.setPage(curPage);
107 | } else {
108 | settings.setPage(nextPage);
109 | }
110 | break;
111 | case CURRENT:
112 | list = this.readFromPage(settings.getLines(), curPage, settings.getPageSize());
113 | break;
114 | default:
115 | break;
116 | }
117 | this.setText(list);
118 | //更新值
119 | BookSettingsState.getInstance().loadState(settings);
120 | }
121 |
122 | /**
123 | * 使用java8 stream分页读取
124 | *
125 | * @param list
126 | * @param page 页码
127 | * @param pageSize 每页行数
128 | * @return
129 | */
130 | private List readFromPage(List list, int page, int pageSize) {
131 | ArrayList prevPageList = list.stream()
132 | .skip((page - 1) * pageSize)
133 | .limit(pageSize)
134 | .collect(Collectors.toCollection(ArrayList::new));
135 | return prevPageList;
136 | }
137 |
138 | private void setText(List list) {
139 | if (list != null && !list.isEmpty()) {
140 | StringBuilder sb = new StringBuilder();
141 | list.forEach(s -> sb.append(s).append("\n"));
142 | this.text.setText(sb.toString());
143 | }
144 | }
145 |
146 | private void setText(String text) {
147 | this.text.setText(text);
148 | }
149 |
150 | public JComponent getContent() {
151 | return this.book;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------