jarvis-ai-assistant 0.1.177__py3-none-any.whl → 0.1.179__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +145 -125
- jarvis/jarvis_agent/builtin_input_handler.py +1 -1
- jarvis/jarvis_agent/jarvis.py +9 -13
- jarvis/jarvis_agent/main.py +4 -2
- jarvis/jarvis_code_agent/code_agent.py +34 -23
- jarvis/jarvis_code_agent/lint.py +164 -0
- jarvis/jarvis_code_analysis/checklists/loader.py +6 -20
- jarvis/jarvis_code_analysis/code_review.py +8 -6
- jarvis/jarvis_dev/main.py +1 -8
- jarvis/jarvis_event/__init__.py +0 -0
- jarvis/jarvis_git_details/main.py +1 -1
- jarvis/jarvis_git_squash/main.py +5 -3
- jarvis/jarvis_git_utils/git_commiter.py +24 -23
- jarvis/jarvis_mcp/sse_mcp_client.py +6 -4
- jarvis/jarvis_mcp/stdio_mcp_client.py +5 -4
- jarvis/jarvis_mcp/streamable_mcp_client.py +404 -0
- jarvis/jarvis_methodology/main.py +10 -9
- jarvis/jarvis_multi_agent/main.py +3 -1
- jarvis/jarvis_platform/base.py +14 -8
- jarvis/jarvis_platform/human.py +3 -1
- jarvis/jarvis_platform/kimi.py +10 -7
- jarvis/jarvis_platform/openai.py +70 -11
- jarvis/jarvis_platform/registry.py +6 -2
- jarvis/jarvis_platform/yuanbao.py +13 -10
- jarvis/jarvis_platform_manager/main.py +11 -9
- jarvis/jarvis_smart_shell/main.py +1 -0
- jarvis/jarvis_tools/ask_codebase.py +6 -4
- jarvis/jarvis_tools/ask_user.py +2 -1
- jarvis/jarvis_tools/base.py +3 -1
- jarvis/jarvis_tools/chdir.py +2 -1
- jarvis/jarvis_tools/cli/main.py +1 -0
- jarvis/jarvis_tools/code_plan.py +5 -3
- jarvis/jarvis_tools/create_code_agent.py +5 -2
- jarvis/jarvis_tools/create_sub_agent.py +1 -3
- jarvis/jarvis_tools/edit_file.py +37 -29
- jarvis/jarvis_tools/execute_script.py +1 -1
- jarvis/jarvis_tools/file_analyzer.py +5 -3
- jarvis/jarvis_tools/file_operation.py +4 -7
- jarvis/jarvis_tools/find_methodology.py +4 -2
- jarvis/jarvis_tools/generate_new_tool.py +2 -1
- jarvis/jarvis_tools/methodology.py +3 -4
- jarvis/jarvis_tools/read_code.py +2 -1
- jarvis/jarvis_tools/read_webpage.py +3 -1
- jarvis/jarvis_tools/registry.py +23 -14
- jarvis/jarvis_tools/rewrite_file.py +2 -1
- jarvis/jarvis_tools/search_web.py +1 -0
- jarvis/jarvis_tools/virtual_tty.py +5 -4
- jarvis/jarvis_utils/__init__.py +2 -0
- jarvis/jarvis_utils/builtin_replace_map.py +1 -1
- jarvis/jarvis_utils/config.py +40 -1
- jarvis/jarvis_utils/embedding.py +4 -3
- jarvis/jarvis_utils/file_processors.py +1 -0
- jarvis/jarvis_utils/git_utils.py +55 -25
- jarvis/jarvis_utils/globals.py +4 -2
- jarvis/jarvis_utils/input.py +14 -7
- jarvis/jarvis_utils/methodology.py +6 -4
- jarvis/jarvis_utils/output.py +10 -6
- jarvis/jarvis_utils/utils.py +89 -13
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/METADATA +45 -33
- jarvis_ai_assistant-0.1.179.dist-info/RECORD +98 -0
- jarvis/jarvis_lsp/base.py +0 -66
- jarvis/jarvis_lsp/cpp.py +0 -99
- jarvis/jarvis_lsp/go.py +0 -104
- jarvis/jarvis_lsp/python.py +0 -58
- jarvis/jarvis_lsp/registry.py +0 -169
- jarvis/jarvis_lsp/rust.py +0 -107
- jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -147
- jarvis_ai_assistant-0.1.177.dist-info/RECORD +0 -102
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.177.dist-info → jarvis_ai_assistant-0.1.179.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
jarvis/__init__.py,sha256=AHtR6TjwF1QgHEj70zUFmweOTTTW-KN1Gtvw7DOSA9k,74
|
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=9vyME5JbA4koVoqJ_zv5N9eNdvu6iBkB4o4a1CmkVgA,30054
|
|
3
|
+
jarvis/jarvis_agent/builtin_input_handler.py,sha256=f4DaEHPakXcAbgykFP-tiOQP6fh_yGFlZx_h91_j2tQ,1529
|
|
4
|
+
jarvis/jarvis_agent/jarvis.py,sha256=UkNMVUlSNKV6y3v12eAhqc_gIDB6Obxrwk5f7-sQeiQ,6137
|
|
5
|
+
jarvis/jarvis_agent/main.py,sha256=GkjMTIbsd56nkVuRwD_tU_PZWyzixZZhMjVOCd0SzOA,2669
|
|
6
|
+
jarvis/jarvis_agent/output_handler.py,sha256=7qori-RGrQmdiFepoEe3oPPKJIvRt90l_JDmvCoa4zA,1219
|
|
7
|
+
jarvis/jarvis_agent/shell_input_handler.py,sha256=pi3AtPKrkKc6K9e99S1djKXQ_XrxtP6FrSWebQmRT6E,1261
|
|
8
|
+
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
jarvis/jarvis_code_agent/code_agent.py,sha256=jEJhPk4Eg-2hsDYeIa2NOfk2YnuvhuPrLCtVHm5hTPg,17879
|
|
10
|
+
jarvis/jarvis_code_agent/lint.py,sha256=TZlhNbeaoLzO9DzExjN5GAjrt66owd8lyQV56LTfkrs,4370
|
|
11
|
+
jarvis/jarvis_code_analysis/code_review.py,sha256=SEK5NOGDWgMNX3zmRMWrIOtq3Xr8cKt_asG51U8h6SA,30219
|
|
12
|
+
jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=cKQ_FOGy5TQgM-YkRCqORo-mUOZaPAJ9VDmZoFX58us,78
|
|
13
|
+
jarvis/jarvis_code_analysis/checklists/c_cpp.py,sha256=SXPpYCNeCtU1PpKdKPiYDuOybfY9vaL0ejDn4imxDwA,1317
|
|
14
|
+
jarvis/jarvis_code_analysis/checklists/csharp.py,sha256=vS-cu6RCGg5SyK9MJ3RE381gt3xYl-yea3Bj2UQEcwQ,2420
|
|
15
|
+
jarvis/jarvis_code_analysis/checklists/data_format.py,sha256=0ljCQPNrhFq3Qzl7WQZy-5jRE5OQG-6fjK-ZMQhP7AE,3005
|
|
16
|
+
jarvis/jarvis_code_analysis/checklists/devops.py,sha256=caupq-mZyXOfK5cSkpgcxdivqK89_2lWuDbXDuVndI8,3542
|
|
17
|
+
jarvis/jarvis_code_analysis/checklists/docs.py,sha256=lOr69-3-wobyfx82NLYZmZKHfoAov_rF4D6YMjsmOkY,3341
|
|
18
|
+
jarvis/jarvis_code_analysis/checklists/go.py,sha256=8Q16X08aj9pyLyi5c85xB2CcZI-eLlxw7TJDTij5BBY,1388
|
|
19
|
+
jarvis/jarvis_code_analysis/checklists/infrastructure.py,sha256=KgyuZHJfKCbon1qxqoTDBnUbDrY7dfFnfPkTlH4BrlI,3765
|
|
20
|
+
jarvis/jarvis_code_analysis/checklists/java.py,sha256=RReiw64i-o5yLIhZdFkkWzMl9yE4_SnQr7CwWz5dTas,2085
|
|
21
|
+
jarvis/jarvis_code_analysis/checklists/javascript.py,sha256=i1srwYq0H-d9Ql98UpJSvceHe5jTJX3CFO_sgmw7_AU,2340
|
|
22
|
+
jarvis/jarvis_code_analysis/checklists/kotlin.py,sha256=AgVEDHdDC4kD-XYjT5V3LNjRpcWeVCoPThVg1juD1Ns,4436
|
|
23
|
+
jarvis/jarvis_code_analysis/checklists/loader.py,sha256=N9tSH4R_HYS5280CQoEcGJSGFq0WbAbYYQNQsKQTCDI,2102
|
|
24
|
+
jarvis/jarvis_code_analysis/checklists/php.py,sha256=_EvpnWwHOGM3wAc9aXJrtwy3LQvYNR-oxPhtv71qZj4,2481
|
|
25
|
+
jarvis/jarvis_code_analysis/checklists/python.py,sha256=rQ2jpDG0CPzeWiBc2Q6kJA0IBpyheL4-gtMwe6whgOM,1452
|
|
26
|
+
jarvis/jarvis_code_analysis/checklists/ruby.py,sha256=JbU1eHafIhlV0qWtYxEltz6AaFzUSU_F3KuqylnMcgc,4274
|
|
27
|
+
jarvis/jarvis_code_analysis/checklists/rust.py,sha256=oe_1wPaBgMScQTn-697aghWVsIvNO2v8E6m_lcP8_iU,1646
|
|
28
|
+
jarvis/jarvis_code_analysis/checklists/shell.py,sha256=IXQkWHwA-4GUQz3WUs7l6hEy7Vrjd92egUYXGfu2FKQ,2619
|
|
29
|
+
jarvis/jarvis_code_analysis/checklists/sql.py,sha256=ecKKT6wJAibn8R0NxGZDNlm4teYXvF3CAJvVk8mmX7w,2355
|
|
30
|
+
jarvis/jarvis_code_analysis/checklists/swift.py,sha256=YcsYFxAitHqOtBZjG-RV9-KNM7X5lIcl6zlEI9XfmfM,2566
|
|
31
|
+
jarvis/jarvis_code_analysis/checklists/web.py,sha256=-Pnj1FQTsGVZUQK7-4ptDsGd7a22Cs0585jRAPT2SdQ,3943
|
|
32
|
+
jarvis/jarvis_data/huggingface.tar.gz,sha256=dWKnc_tvyx-I_ZkXo91O0b38KxDmLW1ZbmJ3E6fCl_k,1120205
|
|
33
|
+
jarvis/jarvis_dev/main.py,sha256=RJ7Z7_qX6ENKrlgjlz7tMfpBTh9g22mGqcasWCv5ygw,42710
|
|
34
|
+
jarvis/jarvis_event/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
+
jarvis/jarvis_git_details/main.py,sha256=MfR7feVVQ7Eo9eZk-wO2bFypnA6uRrYUQn6iTeoF0Os,9007
|
|
37
|
+
jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
jarvis/jarvis_git_squash/main.py,sha256=q8-r0TtVOaCqY_uYwnWAY76k8YCDd5se_feB6ZWKo9M,2278
|
|
39
|
+
jarvis/jarvis_git_utils/git_commiter.py,sha256=GuUHL0crFZ1QE8MKYr4zAdRd0Y3YnW-C_k_PbokuiX4,12964
|
|
40
|
+
jarvis/jarvis_mcp/__init__.py,sha256=NF_vqRxaNyz8ColcpRh0bOkinV90YLAKHEN--jkP-B8,2114
|
|
41
|
+
jarvis/jarvis_mcp/sse_mcp_client.py,sha256=QNA7HqFvLbvhNaFp3ZsXzs2Rm6_gHUMcpd4t4qAzymY,23485
|
|
42
|
+
jarvis/jarvis_mcp/stdio_mcp_client.py,sha256=IEkas4ojP5J0TdVaUglvlEp61RyezBtuejv4lN3n1I4,11831
|
|
43
|
+
jarvis/jarvis_mcp/streamable_mcp_client.py,sha256=t2uKiIbKlmMsaiN9xHCZC3WTdl7mmoBuIZ_ph-QshzE,15084
|
|
44
|
+
jarvis/jarvis_methodology/main.py,sha256=HhEArlKI5PCpGnBCwVrXMuDn2z84LgpgK7-aGSQH0v4,11880
|
|
45
|
+
jarvis/jarvis_multi_agent/__init__.py,sha256=Xab5sFltJmX_9MoXqanmZs6FqKfUb2v_pG29Vk8ZXaw,4311
|
|
46
|
+
jarvis/jarvis_multi_agent/main.py,sha256=KeGv8sdpSgTjW6VE4-tQ8BWDC_a0aE_4R3OqzPBd5N4,1646
|
|
47
|
+
jarvis/jarvis_platform/__init__.py,sha256=0YnsUoM4JkIBOtImFdjfuDbrqQZT3dEaAwSJ62DrpCc,104
|
|
48
|
+
jarvis/jarvis_platform/base.py,sha256=EyZOl98rpYUX1yISDFvj1ztrYfWIT2ozenwUIZ7TyyI,6972
|
|
49
|
+
jarvis/jarvis_platform/human.py,sha256=xwaTZ1zdrAYZZFXxkbHvUdECwCGsic0kgAFUncUr45g,2567
|
|
50
|
+
jarvis/jarvis_platform/kimi.py,sha256=kkYWmJoOIT-7tp5_v2LaQGUFsEuCftfma3Ztn1P4CKo,13111
|
|
51
|
+
jarvis/jarvis_platform/openai.py,sha256=k1h_FLCd-nqvBFUBDJC_eNjSMohh5huWRJcMe1RLrHQ,5588
|
|
52
|
+
jarvis/jarvis_platform/registry.py,sha256=CxAELjDrc-KKPPKdP71E_qaFisfQztvwc_tdf3WpOt8,7863
|
|
53
|
+
jarvis/jarvis_platform/yuanbao.py,sha256=giuHCDSAhVlaUykoN5D6oZ0DtYu81zMpVHnMepFkt_I,21672
|
|
54
|
+
jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
+
jarvis/jarvis_platform_manager/main.py,sha256=OXWj18SqiV0Gl75YT6D9wspCCB4Nes04EY-ShI9kbpU,25677
|
|
56
|
+
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
|
+
jarvis/jarvis_smart_shell/main.py,sha256=CaqAXPk1XW3ruQf2AJjdeZBhqD2xh09KvG3TM0o6-aw,5209
|
|
58
|
+
jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
+
jarvis/jarvis_tools/ask_codebase.py,sha256=FYlrbiN5PjxS4hGvCjN8idF6YnESDH6NLBgQguSnG48,10145
|
|
60
|
+
jarvis/jarvis_tools/ask_user.py,sha256=qwxwJIL698rEWdi1txxlPgIr4UFuihfe--NqBEYhIQQ,2168
|
|
61
|
+
jarvis/jarvis_tools/base.py,sha256=OdlvzUjYQBmZIMcAeBxAqIQo2urh126OerArK-wOPzU,1191
|
|
62
|
+
jarvis/jarvis_tools/chdir.py,sha256=DNKVFrWqu6t_sZ2ipv99s6802QR4cSGlqKlmaI--arE,2707
|
|
63
|
+
jarvis/jarvis_tools/code_plan.py,sha256=pfGOX3fH4-Gg2ECuJkjGpnRtHXEhlVWLV8ZVJAEKmwk,7755
|
|
64
|
+
jarvis/jarvis_tools/create_code_agent.py,sha256=-nHfo5O5pDIG5IX3w1ClQafGvGcdI2_w75-KGrD-gUQ,3458
|
|
65
|
+
jarvis/jarvis_tools/create_sub_agent.py,sha256=lyFrrg4V0yXULmU3vldwGp_euZjwZzJcRU6mJ20zejY,3023
|
|
66
|
+
jarvis/jarvis_tools/edit_file.py,sha256=50OZSdR6bJM7eMh5KCI2pOI5WV7ofUeMh7-ABCKulXY,16249
|
|
67
|
+
jarvis/jarvis_tools/execute_script.py,sha256=yQpc90t678UGbkr-ycGeB7jwqmY7GWWbtFtmcAI0-d4,5739
|
|
68
|
+
jarvis/jarvis_tools/file_analyzer.py,sha256=7ILHkUFm8pPZn1y_s4uT0kaWHP-EmlHnpkovDdA1yRE,4872
|
|
69
|
+
jarvis/jarvis_tools/file_operation.py,sha256=RcOKuMFUv01tvKoiOfu1ERCjvDVfJBvkT4oBpq-8vNQ,9036
|
|
70
|
+
jarvis/jarvis_tools/find_methodology.py,sha256=P1IJU2x9yBoOK-X5TTvzC9Lfa1i6ES3eZn5kjEpWGdA,2440
|
|
71
|
+
jarvis/jarvis_tools/generate_new_tool.py,sha256=k1Vt88kI1bYi1OwxvJqFKr3Ewwwv7lOegYNmZ-1F7x0,10283
|
|
72
|
+
jarvis/jarvis_tools/methodology.py,sha256=m7cQmVhhQpUUl_uYTVvcW0JBovQLx5pWTXh_8K77HsU,5237
|
|
73
|
+
jarvis/jarvis_tools/read_code.py,sha256=j4niDMOAKW_3rVxmOo3wxYBQ2T8vkxqEiTkBt28gUT8,5898
|
|
74
|
+
jarvis/jarvis_tools/read_webpage.py,sha256=PFAYuKjay9j6phWzyuZ99ZfNaHJljmRWAgS0bsvbcvE,2219
|
|
75
|
+
jarvis/jarvis_tools/registry.py,sha256=emAX3DjdWcluthEVSHKs1W5ieKtvaKr2uM2DIlEErHQ,24417
|
|
76
|
+
jarvis/jarvis_tools/rewrite_file.py,sha256=3V2l7kG5DG9iRimBce-1qCRuJPL0QM32SBTzOl2zCqM,7004
|
|
77
|
+
jarvis/jarvis_tools/search_web.py,sha256=rzxrCOTEo-MmLQrKI4k-AbfidUfJUeCPK4f5ZJy48G8,952
|
|
78
|
+
jarvis/jarvis_tools/virtual_tty.py,sha256=8E_n-eC-RRPTqYx6BI5Q2RnorY8dbhKFBfAjIiRQROA,16397
|
|
79
|
+
jarvis/jarvis_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
|
+
jarvis/jarvis_tools/cli/main.py,sha256=3UuU9tk5cQAS0rfNPXgdtnAd5uDB7v0Exo0_I9sJHRE,6355
|
|
81
|
+
jarvis/jarvis_utils/__init__.py,sha256=x5lbQRH1uOulmWr1IEqNMLXNmDHbqQQot7d1uhKFg4M,851
|
|
82
|
+
jarvis/jarvis_utils/builtin_replace_map.py,sha256=Cx0HFvMmDkkYR9htSS-PCCd8D0Np7yRm2g-C1J2-u08,4314
|
|
83
|
+
jarvis/jarvis_utils/config.py,sha256=5Fouj2RgzsktxptociwJcaXYCcoVctJS3x5CQWRab5I,5684
|
|
84
|
+
jarvis/jarvis_utils/embedding.py,sha256=J8YAqIEj16TJIPEG24uvUlPHeN-5zq0JW_hbNLizQug,3832
|
|
85
|
+
jarvis/jarvis_utils/file_processors.py,sha256=G5kQI7vCGIDnjgAB5J1dYIR102u6WUv3IhcWFfDh_gs,2977
|
|
86
|
+
jarvis/jarvis_utils/git_utils.py,sha256=XJ42U3eVNI5QV7onGbTYlJY-XWdLFSLnQ5QMaonQDSI,12312
|
|
87
|
+
jarvis/jarvis_utils/globals.py,sha256=6JWtB1XoD-wEFiMzZNA790ixlZ_OsJEYUM_B8EwkOE8,2277
|
|
88
|
+
jarvis/jarvis_utils/input.py,sha256=FkLW7MXL8awQUghFLQnW1r5F1wV8K3EZeVPwHFRHJTo,7458
|
|
89
|
+
jarvis/jarvis_utils/methodology.py,sha256=A8pE8ZqNHvGKaDO4TFtg7Oz-hAXPBcQfhmSPWMr6vdg,8629
|
|
90
|
+
jarvis/jarvis_utils/output.py,sha256=QboL42GtG_dnvd1O64sl8o72mEBhXNRADPXQMXgDE7Q,9661
|
|
91
|
+
jarvis/jarvis_utils/tag.py,sha256=YJHmuedLb7_AiqvKQetHr4R1FxyzIh7HN0RRkWMmYbU,429
|
|
92
|
+
jarvis/jarvis_utils/utils.py,sha256=XV-9T8yqThuo0aXkA7BOfBVt1YMUwkyIKeuvK2oDujM,8471
|
|
93
|
+
jarvis_ai_assistant-0.1.179.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
94
|
+
jarvis_ai_assistant-0.1.179.dist-info/METADATA,sha256=wospENCawSz6yu0ulALwAbZcY5VtG03oV2N-nOI08PM,15200
|
|
95
|
+
jarvis_ai_assistant-0.1.179.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
|
96
|
+
jarvis_ai_assistant-0.1.179.dist-info/entry_points.txt,sha256=rjj61tZ7ahLi1R-JkJmX-IzIPPHD8mnwDZap1CnMe2s,973
|
|
97
|
+
jarvis_ai_assistant-0.1.179.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
98
|
+
jarvis_ai_assistant-0.1.179.dist-info/RECORD,,
|
jarvis/jarvis_lsp/base.py
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from abc import ABC, abstractmethod
|
|
3
|
-
from typing import List, Dict, Any, Union
|
|
4
|
-
|
|
5
|
-
class BaseLSP(ABC):
|
|
6
|
-
"""Base class for Language Server Protocol integration.
|
|
7
|
-
|
|
8
|
-
Core LSP features needed for LLM-based code editing:
|
|
9
|
-
1. Code navigation and analysis
|
|
10
|
-
2. Code modification validation
|
|
11
|
-
3. Diagnostic information
|
|
12
|
-
4. Symbol analysis
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
language: Union[str, List[str]] = "" # Language identifier, should be overridden by subclasses
|
|
16
|
-
|
|
17
|
-
@abstractmethod
|
|
18
|
-
def initialize(self, workspace_path: str) -> bool:
|
|
19
|
-
"""Initialize LSP server for the workspace.
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
workspace_path: Root path of the workspace
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
bool: True if initialization successful
|
|
26
|
-
"""
|
|
27
|
-
return False
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@abstractmethod
|
|
31
|
-
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
32
|
-
"""Get diagnostics (errors, warnings) for file.
|
|
33
|
-
|
|
34
|
-
Args:
|
|
35
|
-
file_path: Path to the file
|
|
36
|
-
|
|
37
|
-
Returns:
|
|
38
|
-
List of diagnostic items:
|
|
39
|
-
[
|
|
40
|
-
{
|
|
41
|
-
"range": {
|
|
42
|
-
"start": {"line": int, "character": int},
|
|
43
|
-
"end": {"line": int, "character": int}
|
|
44
|
-
},
|
|
45
|
-
"severity": 1 | 2 | 3 | 4, # Error=1, Warning=2, Info=3, Hint=4
|
|
46
|
-
"code": str, # Error code if any
|
|
47
|
-
"source": str, # Source of diagnostic (e.g. "pylint")
|
|
48
|
-
"message": str, # Diagnostic message
|
|
49
|
-
"relatedInformation": [ # Optional related info
|
|
50
|
-
{
|
|
51
|
-
"location": {
|
|
52
|
-
"uri": str,
|
|
53
|
-
"range": {...}
|
|
54
|
-
},
|
|
55
|
-
"message": str
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
"""
|
|
61
|
-
return []
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def shutdown(self):
|
|
65
|
-
"""Shutdown LSP server cleanly."""
|
|
66
|
-
pass
|
jarvis/jarvis_lsp/cpp.py
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import os
|
|
3
|
-
import shutil
|
|
4
|
-
import subprocess
|
|
5
|
-
from typing import List, Dict, Optional, Any
|
|
6
|
-
import json
|
|
7
|
-
from jarvis.jarvis_lsp.base import BaseLSP
|
|
8
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
9
|
-
|
|
10
|
-
class CPPLSP(BaseLSP):
|
|
11
|
-
"""C++ LSP implementation using clangd."""
|
|
12
|
-
|
|
13
|
-
language = ["cpp", "c"]
|
|
14
|
-
|
|
15
|
-
@staticmethod
|
|
16
|
-
def check() -> bool:
|
|
17
|
-
"""Check if clangd is installed."""
|
|
18
|
-
return shutil.which("clangd") is not None
|
|
19
|
-
|
|
20
|
-
def __init__(self):
|
|
21
|
-
self.workspace_path = ""
|
|
22
|
-
self.clangd_process = None
|
|
23
|
-
self.request_id = 0
|
|
24
|
-
|
|
25
|
-
def initialize(self, workspace_path: str) -> bool:
|
|
26
|
-
try:
|
|
27
|
-
self.workspace_path = workspace_path
|
|
28
|
-
# Start clangd process
|
|
29
|
-
self.clangd_process = subprocess.Popen(
|
|
30
|
-
["clangd", "--background-index"],
|
|
31
|
-
stdin=subprocess.PIPE,
|
|
32
|
-
stdout=subprocess.PIPE,
|
|
33
|
-
stderr=subprocess.PIPE
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
# Send initialize request
|
|
37
|
-
self._send_request("initialize", {
|
|
38
|
-
"processId": os.getpid(),
|
|
39
|
-
"rootUri": f"file://{workspace_path}",
|
|
40
|
-
"capabilities": {}
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
return True
|
|
44
|
-
except Exception as e:
|
|
45
|
-
PrettyOutput.print(f"C++ LSP 初始化失败: {str(e)}", OutputType.ERROR)
|
|
46
|
-
return False
|
|
47
|
-
|
|
48
|
-
def _send_request(self, method: str, params: Dict) -> Optional[Dict]:
|
|
49
|
-
"""Send JSON-RPC request to clangd."""
|
|
50
|
-
if not self.clangd_process:
|
|
51
|
-
return None
|
|
52
|
-
|
|
53
|
-
try:
|
|
54
|
-
self.request_id += 1
|
|
55
|
-
request = {
|
|
56
|
-
"jsonrpc": "2.0",
|
|
57
|
-
"id": self.request_id,
|
|
58
|
-
"method": method,
|
|
59
|
-
"params": params
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
self.clangd_process.stdin.write(json.dumps(request).encode() + b"\n") # type: ignore
|
|
63
|
-
self.clangd_process.stdin.flush() # type: ignore
|
|
64
|
-
|
|
65
|
-
response = json.loads(self.clangd_process.stdout.readline().decode()) # type: ignore
|
|
66
|
-
return response.get("result")
|
|
67
|
-
except Exception:
|
|
68
|
-
return None
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
72
|
-
# Send didOpen notification to trigger diagnostics
|
|
73
|
-
self._send_request("textDocument/didOpen", {
|
|
74
|
-
"textDocument": {
|
|
75
|
-
"uri": f"file://{file_path}",
|
|
76
|
-
"languageId": "cpp",
|
|
77
|
-
"version": 1,
|
|
78
|
-
"text": open(file_path).read()
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
# Wait for diagnostic notification
|
|
83
|
-
try:
|
|
84
|
-
response = json.loads(self.clangd_process.stdout.readline().decode()) # type: ignore
|
|
85
|
-
if response.get("method") == "textDocument/publishDiagnostics":
|
|
86
|
-
return response.get("params", {}).get("diagnostics", [])
|
|
87
|
-
except Exception:
|
|
88
|
-
pass
|
|
89
|
-
return []
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def shutdown(self):
|
|
93
|
-
if self.clangd_process:
|
|
94
|
-
try:
|
|
95
|
-
self._send_request("shutdown", {})
|
|
96
|
-
self.clangd_process.terminate()
|
|
97
|
-
self.clangd_process = None
|
|
98
|
-
except Exception:
|
|
99
|
-
pass
|
jarvis/jarvis_lsp/go.py
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import os
|
|
3
|
-
import shutil
|
|
4
|
-
import subprocess
|
|
5
|
-
from typing import List, Dict, Optional, Any
|
|
6
|
-
import json
|
|
7
|
-
from jarvis.jarvis_lsp.base import BaseLSP
|
|
8
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
9
|
-
|
|
10
|
-
class GoLSP(BaseLSP):
|
|
11
|
-
"""Go LSP implementation using gopls."""
|
|
12
|
-
|
|
13
|
-
language = "go"
|
|
14
|
-
|
|
15
|
-
@staticmethod
|
|
16
|
-
def check() -> bool:
|
|
17
|
-
"""Check if gopls is installed."""
|
|
18
|
-
return shutil.which("gopls") is not None
|
|
19
|
-
|
|
20
|
-
def __init__(self):
|
|
21
|
-
self.workspace_path = ""
|
|
22
|
-
self.gopls_process = None
|
|
23
|
-
self.request_id = 0
|
|
24
|
-
|
|
25
|
-
def initialize(self, workspace_path: str) -> bool:
|
|
26
|
-
try:
|
|
27
|
-
self.workspace_path = workspace_path
|
|
28
|
-
# Start gopls process
|
|
29
|
-
self.gopls_process = subprocess.Popen(
|
|
30
|
-
["gopls", "serve"],
|
|
31
|
-
stdin=subprocess.PIPE,
|
|
32
|
-
stdout=subprocess.PIPE,
|
|
33
|
-
stderr=subprocess.PIPE
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
# Send initialize request
|
|
37
|
-
self._send_request("initialize", {
|
|
38
|
-
"processId": os.getpid(),
|
|
39
|
-
"rootUri": f"file://{workspace_path}",
|
|
40
|
-
"capabilities": {
|
|
41
|
-
"textDocument": {
|
|
42
|
-
"hover": {"contentFormat": ["markdown", "plaintext"]},
|
|
43
|
-
"completion": {"completionItem": {"snippetSupport": True}},
|
|
44
|
-
"signatureHelp": {"signatureInformation": {"documentationFormat": ["markdown", "plaintext"]}},
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
return True
|
|
50
|
-
except Exception as e:
|
|
51
|
-
PrettyOutput.print(f"Go LSP 初始化失败: {str(e)}", OutputType.ERROR)
|
|
52
|
-
return False
|
|
53
|
-
|
|
54
|
-
def _send_request(self, method: str, params: Dict) -> Optional[Dict]:
|
|
55
|
-
"""Send JSON-RPC request to gopls."""
|
|
56
|
-
if not self.gopls_process:
|
|
57
|
-
return None
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
self.request_id += 1
|
|
61
|
-
request = {
|
|
62
|
-
"jsonrpc": "2.0",
|
|
63
|
-
"id": self.request_id,
|
|
64
|
-
"method": method,
|
|
65
|
-
"params": params
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
self.gopls_process.stdin.write(json.dumps(request).encode() + b"\n") # type: ignore
|
|
69
|
-
self.gopls_process.stdin.flush() # type: ignore
|
|
70
|
-
|
|
71
|
-
response = json.loads(self.gopls_process.stdout.readline().decode()) # type: ignore
|
|
72
|
-
return response.get("result")
|
|
73
|
-
except Exception:
|
|
74
|
-
return None
|
|
75
|
-
|
|
76
|
-
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
77
|
-
# Send didOpen notification to trigger diagnostics
|
|
78
|
-
self._send_request("textDocument/didOpen", {
|
|
79
|
-
"textDocument": {
|
|
80
|
-
"uri": f"file://{file_path}",
|
|
81
|
-
"languageId": "go",
|
|
82
|
-
"version": 1,
|
|
83
|
-
"text": open(file_path).read()
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
# Wait for diagnostic notification
|
|
88
|
-
try:
|
|
89
|
-
response = json.loads(self.gopls_process.stdout.readline().decode()) # type: ignore
|
|
90
|
-
if response.get("method") == "textDocument/publishDiagnostics":
|
|
91
|
-
return response.get("params", {}).get("diagnostics", [])
|
|
92
|
-
except Exception:
|
|
93
|
-
pass
|
|
94
|
-
return []
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def shutdown(self):
|
|
98
|
-
if self.gopls_process:
|
|
99
|
-
try:
|
|
100
|
-
self._send_request("shutdown", {})
|
|
101
|
-
self.gopls_process.terminate()
|
|
102
|
-
self.gopls_process = None
|
|
103
|
-
except Exception:
|
|
104
|
-
pass
|
jarvis/jarvis_lsp/python.py
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from typing import List, Dict, Any
|
|
3
|
-
import jedi
|
|
4
|
-
from jarvis.jarvis_lsp.base import BaseLSP
|
|
5
|
-
|
|
6
|
-
class PythonLSP(BaseLSP):
|
|
7
|
-
"""Python LSP implementation using jedi."""
|
|
8
|
-
|
|
9
|
-
language = "python"
|
|
10
|
-
|
|
11
|
-
def __init__(self):
|
|
12
|
-
self.workspace_path = ""
|
|
13
|
-
self.script_cache = {}
|
|
14
|
-
|
|
15
|
-
def initialize(self, workspace_path: str) -> bool:
|
|
16
|
-
self.workspace_path = workspace_path
|
|
17
|
-
return True
|
|
18
|
-
|
|
19
|
-
def _get_script(self, file_path: str):
|
|
20
|
-
if file_path not in self.script_cache:
|
|
21
|
-
try:
|
|
22
|
-
with open(file_path, 'r', errors="ignore") as f:
|
|
23
|
-
content = f.read()
|
|
24
|
-
self.script_cache[file_path] = jedi.Script(code=content, path=file_path)
|
|
25
|
-
except Exception:
|
|
26
|
-
return None
|
|
27
|
-
return self.script_cache[file_path]
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _location_to_dict(self, location) -> Dict[str, Any]:
|
|
31
|
-
return {
|
|
32
|
-
"uri": location.module_path,
|
|
33
|
-
"range": {
|
|
34
|
-
"start": {"line": location.line - 1, "character": location.column},
|
|
35
|
-
"end": {"line": location.line - 1, "character": location.column + len(location.name)}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
40
|
-
script = self._get_script(file_path)
|
|
41
|
-
if not script:
|
|
42
|
-
return []
|
|
43
|
-
try:
|
|
44
|
-
errors = script.get_syntax_errors()
|
|
45
|
-
return [{
|
|
46
|
-
"range": {
|
|
47
|
-
"start": {"line": e.line - 1, "character": e.column},
|
|
48
|
-
"end": {"line": e.line - 1, "character": e.column + 1}
|
|
49
|
-
},
|
|
50
|
-
"severity": 1, # Error
|
|
51
|
-
"source": "jedi",
|
|
52
|
-
"message": str(e)
|
|
53
|
-
} for e in errors]
|
|
54
|
-
except Exception:
|
|
55
|
-
return []
|
|
56
|
-
|
|
57
|
-
def shutdown(self):
|
|
58
|
-
self.script_cache.clear()
|
jarvis/jarvis_lsp/registry.py
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import importlib
|
|
3
|
-
import inspect
|
|
4
|
-
import os
|
|
5
|
-
import re
|
|
6
|
-
import sys
|
|
7
|
-
from typing import Dict, Type, Optional, List
|
|
8
|
-
from jarvis.jarvis_lsp.base import BaseLSP
|
|
9
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
10
|
-
from jarvis.jarvis_utils.config import get_data_dir
|
|
11
|
-
|
|
12
|
-
REQUIRED_METHODS = [
|
|
13
|
-
('initialize', ['workspace_path']),
|
|
14
|
-
('get_diagnostics', ['file_path']),
|
|
15
|
-
('shutdown', [])
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
class LSPRegistry:
|
|
19
|
-
"""LSP server registry"""
|
|
20
|
-
|
|
21
|
-
global_lsp_registry = None
|
|
22
|
-
|
|
23
|
-
@staticmethod
|
|
24
|
-
def get_lsp_dir() -> str:
|
|
25
|
-
"""Get LSP implementation directory."""
|
|
26
|
-
user_lsp_dir = os.path.join(get_data_dir(), "lsp")
|
|
27
|
-
if not os.path.exists(user_lsp_dir):
|
|
28
|
-
try:
|
|
29
|
-
os.makedirs(user_lsp_dir)
|
|
30
|
-
with open(os.path.join(user_lsp_dir, "__init__.py"), "w", errors="ignore") as f:
|
|
31
|
-
pass
|
|
32
|
-
except Exception as e:
|
|
33
|
-
PrettyOutput.print(f"创建 LSP 目录失败: {str(e)}", OutputType.ERROR)
|
|
34
|
-
return ""
|
|
35
|
-
return user_lsp_dir
|
|
36
|
-
|
|
37
|
-
@staticmethod
|
|
38
|
-
def check_lsp_implementation(lsp_class: Type[BaseLSP]) -> bool:
|
|
39
|
-
"""Check if the LSP class implements all necessary methods."""
|
|
40
|
-
missing_methods = []
|
|
41
|
-
|
|
42
|
-
for method_name, params in REQUIRED_METHODS:
|
|
43
|
-
if not hasattr(lsp_class, method_name):
|
|
44
|
-
missing_methods.append(method_name)
|
|
45
|
-
continue
|
|
46
|
-
|
|
47
|
-
method = getattr(lsp_class, method_name)
|
|
48
|
-
if not callable(method):
|
|
49
|
-
missing_methods.append(method_name)
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
sig = inspect.signature(method)
|
|
53
|
-
method_params = [p for p in sig.parameters if p != 'self']
|
|
54
|
-
if len(method_params) != len(params):
|
|
55
|
-
missing_methods.append(f"{method_name}(parameter mismatch)")
|
|
56
|
-
|
|
57
|
-
if missing_methods:
|
|
58
|
-
PrettyOutput.print(
|
|
59
|
-
f"LSP {lsp_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
|
|
60
|
-
OutputType.WARNING
|
|
61
|
-
)
|
|
62
|
-
return False
|
|
63
|
-
|
|
64
|
-
return True
|
|
65
|
-
|
|
66
|
-
@staticmethod
|
|
67
|
-
def load_lsp_from_dir(directory: str) -> Dict[str, Type[BaseLSP]]:
|
|
68
|
-
"""Load LSP implementations from specified directory."""
|
|
69
|
-
lsp_servers = {}
|
|
70
|
-
|
|
71
|
-
if not os.path.exists(directory):
|
|
72
|
-
PrettyOutput.print(f"LSP 目录不存在: {directory}", OutputType.WARNING)
|
|
73
|
-
return lsp_servers
|
|
74
|
-
|
|
75
|
-
package_name = None
|
|
76
|
-
if directory == os.path.dirname(__file__):
|
|
77
|
-
package_name = "jarvis.jarvis_lsp"
|
|
78
|
-
|
|
79
|
-
if directory not in sys.path:
|
|
80
|
-
sys.path.append(directory)
|
|
81
|
-
|
|
82
|
-
for filename in os.listdir(directory):
|
|
83
|
-
if filename.endswith('.py') and not filename.startswith('__'):
|
|
84
|
-
module_name = filename[:-3]
|
|
85
|
-
try:
|
|
86
|
-
if package_name:
|
|
87
|
-
module = importlib.import_module(f"{package_name}.{module_name}")
|
|
88
|
-
else:
|
|
89
|
-
module = importlib.import_module(module_name)
|
|
90
|
-
|
|
91
|
-
for _, obj in inspect.getmembers(module):
|
|
92
|
-
if (inspect.isclass(obj) and
|
|
93
|
-
issubclass(obj, BaseLSP) and
|
|
94
|
-
obj != BaseLSP and
|
|
95
|
-
hasattr(obj, 'language')):
|
|
96
|
-
if not LSPRegistry.check_lsp_implementation(obj):
|
|
97
|
-
continue
|
|
98
|
-
if hasattr(obj, 'check'):
|
|
99
|
-
if not obj.check(): # type: ignore
|
|
100
|
-
continue
|
|
101
|
-
if isinstance(obj.language, str):
|
|
102
|
-
lsp_servers[obj.language] = obj
|
|
103
|
-
elif isinstance(obj.language, list):
|
|
104
|
-
for lang in obj.language: # type: ignore
|
|
105
|
-
lsp_servers[lang] = obj
|
|
106
|
-
break
|
|
107
|
-
except Exception as e:
|
|
108
|
-
PrettyOutput.print(f"加载 LSP {module_name} 失败: {str(e)}", OutputType.ERROR)
|
|
109
|
-
|
|
110
|
-
return lsp_servers
|
|
111
|
-
|
|
112
|
-
@staticmethod
|
|
113
|
-
def get_global_lsp_registry():
|
|
114
|
-
"""Get global LSP registry instance."""
|
|
115
|
-
if LSPRegistry.global_lsp_registry is None:
|
|
116
|
-
LSPRegistry.global_lsp_registry = LSPRegistry()
|
|
117
|
-
return LSPRegistry.global_lsp_registry
|
|
118
|
-
|
|
119
|
-
def __init__(self):
|
|
120
|
-
"""Initialize LSP registry."""
|
|
121
|
-
self.lsp_servers: Dict[str, Type[BaseLSP]] = {}
|
|
122
|
-
|
|
123
|
-
# Load from user LSP directory
|
|
124
|
-
lsp_dir = LSPRegistry.get_lsp_dir()
|
|
125
|
-
if lsp_dir and os.path.exists(lsp_dir):
|
|
126
|
-
for language, lsp_class in LSPRegistry.load_lsp_from_dir(lsp_dir).items():
|
|
127
|
-
self.register_lsp(language, lsp_class)
|
|
128
|
-
|
|
129
|
-
# Load from built-in LSP directory
|
|
130
|
-
lsp_dir = os.path.dirname(__file__)
|
|
131
|
-
if lsp_dir and os.path.exists(lsp_dir):
|
|
132
|
-
for language, lsp_class in LSPRegistry.load_lsp_from_dir(lsp_dir).items():
|
|
133
|
-
self.register_lsp(language, lsp_class)
|
|
134
|
-
|
|
135
|
-
def register_lsp(self, language: str, lsp_class: Type[BaseLSP]):
|
|
136
|
-
"""Register LSP implementation for a language."""
|
|
137
|
-
self.lsp_servers[language] = lsp_class
|
|
138
|
-
|
|
139
|
-
def create_lsp(self, language: str) -> Optional[BaseLSP]:
|
|
140
|
-
"""Create LSP instance for specified language."""
|
|
141
|
-
if language not in self.lsp_servers:
|
|
142
|
-
PrettyOutput.print(f"没有找到 LSP 支持的语言: {language}", OutputType.WARNING)
|
|
143
|
-
return None
|
|
144
|
-
|
|
145
|
-
try:
|
|
146
|
-
lsp = self.lsp_servers[language]()
|
|
147
|
-
return lsp
|
|
148
|
-
except Exception as e:
|
|
149
|
-
PrettyOutput.print(f"创建 LSP 失败: {str(e)}", OutputType.ERROR)
|
|
150
|
-
return None
|
|
151
|
-
|
|
152
|
-
def get_supported_languages(self) -> List[str]:
|
|
153
|
-
"""Get list of supported languages."""
|
|
154
|
-
return list(self.lsp_servers.keys())
|
|
155
|
-
|
|
156
|
-
@staticmethod
|
|
157
|
-
def get_text_at_position(file_path: str, line: int, start_character: int) -> str:
|
|
158
|
-
"""Get text at position."""
|
|
159
|
-
with open(file_path, 'r', errors="ignore") as file:
|
|
160
|
-
lines = file.readlines()
|
|
161
|
-
symbol = re.search(r'\b\w+\b', lines[line][start_character:])
|
|
162
|
-
return symbol.group() if symbol else ""
|
|
163
|
-
|
|
164
|
-
@staticmethod
|
|
165
|
-
def get_line_at_position(file_path: str, line: int) -> str:
|
|
166
|
-
"""Get line at position."""
|
|
167
|
-
with open(file_path, 'r', errors="ignore") as file:
|
|
168
|
-
lines = file.readlines()
|
|
169
|
-
return lines[line]
|