├── .gitignore ├── README.md ├── nb-configuration.xml ├── pom.xml ├── screenshots └── demo.png └── src └── main ├── java └── com │ └── stackleader │ └── netbeans │ └── chatgpt │ ├── ChatTopComponent.java │ ├── CodeBlockLinkGenerator.java │ └── Configuration.java ├── nbm └── manifest.mf └── resources ├── com └── stackleader │ └── netbeans │ └── chatgpt │ └── Bundle.properties └── icons ├── chat.png └── options.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.jar 2 | *.war 3 | *.nar 4 | *.ear 5 | *.zip 6 | *.tar.gz 7 | *.class 8 | target/ 9 | **/nbproject/private/ 10 | build/ 11 | nbbuild/ 12 | dist/ 13 | nbdist/ 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetBeans ChatGPT Plugin 2 | 3 | This plugin allows you to use OpenAI's APIs to generate chat responses directly in NetBeans. I'll probably add some editor context menu actions to speed up code suggestions, but for now its a simple UI for chat that lives in Netbeans. 4 | 5 | ![Screenshot](screenshots/demo.png) 6 | 7 | ## Installation 8 | 9 | 1. [Download the plugin file (.nbm file)](https://github.com/Hillrunner2008/netbeans-chatgpt/releases/download/0.0.4/netbeans-chatgpt-0.0.4.nbm) 10 | 2. In NetBeans, go to `Tools > Plugins`. 11 | 3. Click on the `Downloaded` tab. 12 | 4. Click on the `Add Plugins...` button and select the downloaded ZIP file. 13 | 5. Restart NetBeans -------------------------------------------------------------------------------- /nb-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | JDK_17 17 | 18 | 19 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.stackleader 5 | netbeans-chatgpt 6 | 0.0.4 7 | nbm 8 | 9 | 10 | UTF-8 11 | RELEASE140 12 | 13 | 14 | 15 | 16 | 17 | org.apache.netbeans.utilities 18 | nbm-maven-plugin 19 | 4.8 20 | true 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-compiler-plugin 25 | 3.11.0 26 | 27 | 11 28 | 11 29 | 30 | 31 | 32 | org.apache.maven.plugins 33 | maven-jar-plugin 34 | 3.3.0 35 | 36 | 37 | ${project.build.outputDirectory}/META-INF/MANIFEST.MF 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | apache.snapshots 46 | Repository hosting NetBeans modules 47 | https://repository.apache.org/content/repositories/snapshots/ 48 | 49 | false 50 | 51 | 52 | 53 | 54 | 55 | org.netbeans.api 56 | org-netbeans-api-annotations-common 57 | ${netbeans.version} 58 | 59 | 60 | 61 | org.netbeans.api 62 | org-openide-windows 63 | ${netbeans.version} 64 | 65 | 66 | 67 | org.netbeans.api 68 | org-openide-dialogs 69 | ${netbeans.version} 70 | 71 | 72 | 73 | org.netbeans.api 74 | org-netbeans-modules-editor 75 | ${netbeans.version} 76 | 77 | 78 | 79 | org.netbeans.api 80 | org-openide-text 81 | ${netbeans.version} 82 | 83 | 84 | 85 | org.netbeans.api 86 | org-netbeans-modules-editor-lib 87 | ${netbeans.version} 88 | 89 | 90 | 91 | org.netbeans.api 92 | org-openide-util 93 | ${netbeans.version} 94 | 95 | 96 | 97 | org.netbeans.api 98 | org-openide-util-ui 99 | ${netbeans.version} 100 | 101 | 102 | 103 | org.netbeans.api 104 | org-netbeans-modules-editor-settings 105 | ${netbeans.version} 106 | 107 | 108 | 109 | com.fifesoft 110 | rsyntaxtextarea 111 | 3.3.3 112 | 113 | 114 | org.commonmark 115 | commonmark 116 | 0.21.0 117 | 118 | 119 | com.theokanning.openai-gpt3-java 120 | service 121 | 0.13.0 122 | 123 | 124 | com.squareup.retrofit2 125 | retrofit 126 | 2.9.0 127 | 128 | 129 | com.squareup.retrofit2 130 | converter-jackson 131 | 2.9.0 132 | 133 | 134 | -------------------------------------------------------------------------------- /screenshots/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hillrunner2008/netbeans-chatgpt/f0b6330e1a9bb9a2c3de91fc23fa3e5dcf80b92a/screenshots/demo.png -------------------------------------------------------------------------------- /src/main/java/com/stackleader/netbeans/chatgpt/ChatTopComponent.java: -------------------------------------------------------------------------------- 1 | package com.stackleader.netbeans.chatgpt; 2 | 3 | import com.theokanning.openai.OpenAiHttpException; 4 | import com.theokanning.openai.service.OpenAiService; 5 | import com.theokanning.openai.completion.chat.ChatCompletionChoice; 6 | import com.theokanning.openai.completion.chat.ChatCompletionChunk; 7 | import com.theokanning.openai.completion.chat.ChatCompletionRequest; 8 | import com.theokanning.openai.completion.chat.ChatMessage; 9 | import com.theokanning.openai.completion.chat.ChatMessageRole; 10 | import io.reactivex.functions.Consumer; 11 | import java.awt.BorderLayout; 12 | import java.awt.Color; 13 | import java.awt.Component; 14 | import java.awt.Dimension; 15 | import java.awt.GridBagConstraints; 16 | import java.awt.GridBagLayout; 17 | import java.awt.Insets; 18 | import javax.swing.*; 19 | import javax.swing.border.TitledBorder; 20 | import java.awt.event.ActionEvent; 21 | import java.awt.event.ActionListener; 22 | import java.awt.event.KeyAdapter; 23 | import java.awt.event.KeyEvent; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.concurrent.CopyOnWriteArrayList; 27 | import java.util.prefs.Preferences; 28 | import org.commonmark.parser.Parser; 29 | import org.commonmark.renderer.html.HtmlRenderer; 30 | import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; 31 | import org.fife.ui.rsyntaxtextarea.SyntaxConstants; 32 | import org.fife.ui.rtextarea.Gutter; 33 | import org.fife.ui.rtextarea.RTextScrollPane; 34 | import org.openide.DialogDisplayer; 35 | import org.openide.NotifyDescriptor; 36 | import org.openide.awt.ActionID; 37 | import org.openide.awt.ActionReference; 38 | import org.openide.util.ImageUtilities; 39 | import org.openide.util.NbBundle; 40 | import org.openide.windows.TopComponent; 41 | 42 | /** 43 | * 44 | * @author dcnorris 45 | */ 46 | @TopComponent.Description( 47 | preferredID = ChatTopComponent.PREFERRED_ID, 48 | iconBase = "icons/chat.png", 49 | persistenceType = TopComponent.PERSISTENCE_ALWAYS) 50 | @TopComponent.Registration(mode = "output", openAtStartup = true, position = 500) 51 | @ActionID(category = "Window", id = "com.stackleader.netbeans.chatgpt.ChatTopComponent") 52 | @ActionReference(path = "Menu/Window", position = 333) 53 | @TopComponent.OpenActionRegistration( 54 | displayName = "#Chat_TopComponent_Title", 55 | preferredID = ChatTopComponent.PREFERRED_ID) 56 | public class ChatTopComponent extends TopComponent { 57 | 58 | System.Logger LOG = System.getLogger("ChatTopComponent"); 59 | 60 | public static final String PREFERRED_ID = "ChatTopComponent"; 61 | private static final int BOTTOM_PANEL_HEIGHT = 100; 62 | private static final int BUTTON_WIDTH = 100; 63 | private static final int BUTTON_HEIGHT = 25; 64 | private static final int ACTIONS_PANEL_WIDTH = 20; 65 | public static final String QUICK_COPY_TEXT = "(Quick Copy: Ctrl+Click here)"; 66 | 67 | private RSyntaxTextArea outputTextArea; 68 | private final static List messages = new CopyOnWriteArrayList<>(); 69 | private final static Parser parser = Parser.builder().build(); 70 | private final static HtmlRenderer htmlRenderer = HtmlRenderer.builder().build(); 71 | private Gutter gutter; 72 | private boolean shouldAnnotateCodeBlock = true; 73 | private JComboBox modelSelection; 74 | private OpenAiService service; 75 | 76 | public ChatTopComponent() { 77 | setName(NbBundle.getMessage(ChatTopComponent.class, "Chat_TopComponent_Title")); // NOI18N 78 | setLayout(new BorderLayout()); 79 | Configuration config = Configuration.getInstance(); 80 | Preferences prefs = config.getPreferences(); 81 | String token = prefs.get(Configuration.OPENAI_TOKEN_KEY, null); 82 | if (token == null || token.isBlank()) { 83 | token = promptForToken(); 84 | if (token != null && !token.isBlank()) { 85 | prefs.put(Configuration.OPENAI_TOKEN_KEY, token); 86 | } else { 87 | add(createMissingTokenBanner(), BorderLayout.CENTER); 88 | return; 89 | } 90 | } 91 | addComponentsToFrame(); 92 | service = new OpenAiService(token); 93 | 94 | } 95 | 96 | private String promptForToken() { 97 | NotifyDescriptor.InputLine inputLine = new NotifyDescriptor.InputLine( 98 | "Enter OpenAI API Token:", 99 | "API Token Required" 100 | ); 101 | if (DialogDisplayer.getDefault().notify(inputLine) == NotifyDescriptor.OK_OPTION) { 102 | return inputLine.getInputText(); 103 | } 104 | return null; 105 | } 106 | 107 | @Override 108 | protected void componentOpened() { 109 | super.componentOpened(); 110 | setName(NbBundle.getMessage(ChatTopComponent.class, 111 | "Chat_TopComponent_Title")); // NOI18N 112 | } 113 | 114 | private void addComponentsToFrame() { 115 | add(createActionsPanel(), BorderLayout.WEST); 116 | JPanel mainPanel = new JPanel(new BorderLayout()); 117 | mainPanel.add(createOutputScrollPane(), BorderLayout.CENTER); 118 | mainPanel.add(createBottomPanel(), BorderLayout.SOUTH); 119 | add(mainPanel, BorderLayout.CENTER); 120 | } 121 | 122 | private JPanel createMissingTokenBanner() { 123 | JPanel missingTokenBanner = new JPanel(); 124 | JLabel messageLabel = new JLabel("
OPENAI_TOKEN environment variable is not defined.
Please restart NetBeans after defining this variable.
"); 125 | messageLabel.setHorizontalAlignment(SwingConstants.CENTER); 126 | missingTokenBanner.setLayout(new BorderLayout()); 127 | missingTokenBanner.add(messageLabel, BorderLayout.CENTER); 128 | 129 | return missingTokenBanner; 130 | } 131 | 132 | private JPanel createActionsPanel() { 133 | JPanel actionsPanel = new JPanel(); 134 | actionsPanel.setLayout(new BoxLayout(actionsPanel, BoxLayout.Y_AXIS)); 135 | actionsPanel.setPreferredSize(new Dimension(ACTIONS_PANEL_WIDTH, 500)); 136 | JButton optionsButton = new JButton(ImageUtilities.loadImageIcon("icons/options.png", true)); 137 | optionsButton.addActionListener(new ActionListener() { 138 | @Override 139 | public void actionPerformed(ActionEvent e) { 140 | handleOptionsButtonClick(); 141 | } 142 | }); 143 | actionsPanel.add(optionsButton); 144 | return actionsPanel; 145 | } 146 | 147 | private void handleOptionsButtonClick() { 148 | Configuration config = Configuration.getInstance(); 149 | Preferences prefs = config.getPreferences(); 150 | String currentToken = prefs.get(Configuration.OPENAI_TOKEN_KEY, ""); 151 | 152 | NotifyDescriptor.InputLine inputLine = new NotifyDescriptor.InputLine( 153 | "OpenAI API Token:", 154 | "Edit API Token" 155 | ); 156 | inputLine.setInputText(currentToken); 157 | 158 | if (DialogDisplayer.getDefault().notify(inputLine) == NotifyDescriptor.OK_OPTION) { 159 | String newToken = inputLine.getInputText(); 160 | prefs.put(Configuration.OPENAI_TOKEN_KEY, newToken); 161 | service = new OpenAiService(newToken); 162 | } 163 | } 164 | 165 | private JPanel createOutputScrollPane() { 166 | JPanel cp = new JPanel(new BorderLayout()); 167 | outputTextArea = createOutputTextArea(); 168 | RTextScrollPane outputScrollPane = new RTextScrollPane(outputTextArea); 169 | outputScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 170 | outputScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 171 | outputScrollPane.setBorder(new TitledBorder("Output")); 172 | gutter = outputScrollPane.getGutter(); 173 | cp.add(outputScrollPane); 174 | return cp; 175 | } 176 | 177 | private RSyntaxTextArea createOutputTextArea() { 178 | RSyntaxTextArea outputTextArea = new RSyntaxTextArea(); 179 | UIDefaults defaults = UIManager.getLookAndFeelDefaults(); 180 | Color bg = defaults.getColor("EditorPane.background"); 181 | Color fg = defaults.getColor("EditorPane.foreground"); 182 | Color menuBackground = defaults.getColor("Menu.background"); 183 | Color selectedTextColor = new Color(100, 149, 237); 184 | outputTextArea.setForeground(fg); 185 | outputTextArea.setBackground(menuBackground); 186 | outputTextArea.setSelectedTextColor(selectedTextColor); 187 | outputTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE); 188 | outputTextArea.setEditable(false); 189 | outputTextArea.setLineWrap(true); 190 | outputTextArea.setWrapStyleWord(true); 191 | outputTextArea.setLinkGenerator(new CodeBlockLinkGenerator()); 192 | return outputTextArea; 193 | } 194 | 195 | private JPanel createBottomPanel() { 196 | JPanel bottomPanel = new JPanel(new BorderLayout()); 197 | bottomPanel.add(createButtonPanel(), BorderLayout.WEST); 198 | bottomPanel.add(createInputScrollPane(), BorderLayout.CENTER); 199 | bottomPanel.setPreferredSize(new Dimension(0, BOTTOM_PANEL_HEIGHT)); 200 | return bottomPanel; 201 | } 202 | 203 | private JPanel createButtonPanel() { 204 | JPanel buttonPanel = new JPanel(); 205 | buttonPanel.setLayout(new GridBagLayout()); 206 | GridBagConstraints gbc = new GridBagConstraints(); 207 | gbc.fill = GridBagConstraints.HORIZONTAL; 208 | gbc.weightx = 1.0; 209 | gbc.gridy = 0; 210 | gbc.gridx = 0; 211 | gbc.insets = new Insets(0, 5, 5, 5); 212 | String[] models = {"gpt-3.5-turbo-1106","gpt-3.5-turbo-16k-0613", "gpt-4o"}; 213 | modelSelection = new JComboBox<>(models); 214 | modelSelection.setSelectedItem("gpt-4o"); 215 | buttonPanel.add(modelSelection, gbc); 216 | gbc.gridy++; 217 | JButton resetButton = createResetButton(); 218 | buttonPanel.add(resetButton, gbc); 219 | gbc.gridy++; 220 | JButton submitButton = createSubmitButton(); 221 | buttonPanel.add(submitButton, gbc); 222 | return buttonPanel; 223 | } 224 | 225 | private JButton createResetButton() { 226 | final JButton resetButton = createButton("Reset"); 227 | resetButton.addActionListener(new ActionListener() { 228 | @Override 229 | public void actionPerformed(ActionEvent e) { 230 | reset(); 231 | } 232 | }); 233 | return resetButton; 234 | } 235 | 236 | private JButton createSubmitButton() { 237 | final JButton submitButton = createButton("Submit"); 238 | submitButton.addActionListener(new ActionListener() { 239 | @Override 240 | public void actionPerformed(ActionEvent e) { 241 | submit(); 242 | } 243 | }); 244 | return submitButton; 245 | } 246 | 247 | private JButton createButton(String buttonText) { 248 | JButton button = new JButton(buttonText); 249 | button.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); 250 | button.setAlignmentX(Component.CENTER_ALIGNMENT); 251 | return button; 252 | } 253 | 254 | private JScrollPane createInputScrollPane() { 255 | inputTextArea = new JTextArea(); 256 | inputTextArea.setWrapStyleWord(true); 257 | inputTextArea.addKeyListener(new KeyAdapter() { 258 | public void keyPressed(KeyEvent e) { 259 | if (e.getKeyCode() == KeyEvent.VK_ENTER) { 260 | if (e.isShiftDown()) { 261 | int caret = inputTextArea.getCaretPosition(); 262 | inputTextArea.insert("\n", caret); 263 | inputTextArea.setCaretPosition(caret + 1); 264 | } else { 265 | e.consume(); // to prevent newline being added by default behavior 266 | submit(); 267 | } 268 | } 269 | } 270 | }); 271 | return new JScrollPane(inputTextArea); 272 | } 273 | private JTextArea inputTextArea; 274 | 275 | private void submit() { 276 | String userInput = inputTextArea.getText(); 277 | String selectedModel = (String) modelSelection.getSelectedItem(); // Get the selected model 278 | SwingWorker worker = new SwingWorker() { 279 | @Override 280 | protected Void doInBackground() throws Exception { 281 | callChatGPT(userInput); 282 | return null; 283 | } 284 | 285 | private void callChatGPT(String userInput) { 286 | final ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), userInput); 287 | messages.add(userMessage); 288 | appendToOutputDocument("User: "); 289 | appendToOutputDocument(System.lineSeparator()); 290 | appendToOutputDocument(userInput); 291 | appendToOutputDocument(System.lineSeparator()); 292 | // Create chat completion request 293 | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest 294 | .builder() 295 | .model(selectedModel) 296 | .messages(messages) 297 | .n(1) 298 | .maxTokens(1000) 299 | .logitBias(new HashMap<>()) 300 | .build(); 301 | try { 302 | appendToOutputDocument("ChatGPT: "); 303 | appendToOutputDocument(System.lineSeparator()); 304 | StringBuilder gptResponse = new StringBuilder(); 305 | service.streamChatCompletion(chatCompletionRequest) 306 | .doOnError(throwable -> { 307 | String errorMessage = "Error calling OpenAI API: " + throwable.getMessage(); 308 | SwingUtilities.invokeLater(() -> { 309 | JOptionPane.showMessageDialog(ChatTopComponent.this, errorMessage, "API Error", JOptionPane.ERROR_MESSAGE); 310 | }); 311 | }) 312 | .blockingForEach(new Consumer() { 313 | StringBuilder codeBlockIndicatorBuffer = new StringBuilder(); 314 | 315 | @Override 316 | public void accept(ChatCompletionChunk chunk) throws Exception { 317 | for (ChatCompletionChoice choice : chunk.getChoices()) { 318 | if (choice.getMessage().getContent() != null) { 319 | String content = choice.getMessage().getContent(); 320 | gptResponse.append(content); 321 | if (!codeBlockIndicatorBuffer.isEmpty()) { 322 | codeBlockIndicatorBuffer.append(content); 323 | if (content.contains(System.lineSeparator())) { 324 | //flush buffer 325 | appendToOutputDocument(codeBlockIndicatorBuffer.toString()); 326 | codeBlockIndicatorBuffer.setLength(0); 327 | } 328 | } else { 329 | if (content.startsWith("`")) { 330 | codeBlockIndicatorBuffer.append(content); 331 | } else { 332 | appendToOutputDocument(content); 333 | } 334 | } 335 | } 336 | } 337 | } 338 | }); 339 | final ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), gptResponse.toString()); 340 | messages.add(systemMessage); 341 | appendToOutputDocument(System.lineSeparator()); 342 | } catch (OpenAiHttpException ex) { 343 | LOG.log(System.Logger.Level.ERROR, "Error calling OpenAI API", ex); 344 | } 345 | } 346 | 347 | }; 348 | worker.execute(); 349 | inputTextArea.setText(""); 350 | } 351 | 352 | private void appendToOutputDocument(String content) { 353 | if (content.startsWith("```")) { 354 | if (shouldAnnotateCodeBlock) { 355 | int newlinePos = content.indexOf("\n"); 356 | 357 | // If a newline character is found, insert the annotation before it 358 | if (newlinePos != -1) { 359 | String beforeNewline = content.substring(0, newlinePos); 360 | String afterNewline = content.substring(newlinePos); 361 | SwingUtilities.invokeLater(() -> { 362 | outputTextArea.append(beforeNewline + " " + QUICK_COPY_TEXT + afterNewline); 363 | }); 364 | } else { 365 | // If no newline character is found, append the content as is 366 | SwingUtilities.invokeLater(() -> { 367 | outputTextArea.append(content); 368 | }); 369 | } 370 | shouldAnnotateCodeBlock = false; 371 | } else { 372 | SwingUtilities.invokeLater(() -> { 373 | outputTextArea.append(content); 374 | }); 375 | shouldAnnotateCodeBlock = true; 376 | } 377 | } else { 378 | SwingUtilities.invokeLater(() -> { 379 | outputTextArea.append(content); 380 | }); 381 | } 382 | 383 | } 384 | 385 | private void reset() { 386 | messages.clear(); 387 | shouldAnnotateCodeBlock = true; 388 | SwingUtilities.invokeLater(() -> { 389 | outputTextArea.setText(""); 390 | }); 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/main/java/com/stackleader/netbeans/chatgpt/CodeBlockLinkGenerator.java: -------------------------------------------------------------------------------- 1 | package com.stackleader.netbeans.chatgpt; 2 | 3 | /** 4 | * 5 | * @author dcnorris 6 | */ 7 | import static com.stackleader.netbeans.chatgpt.ChatTopComponent.QUICK_COPY_TEXT; 8 | import java.awt.datatransfer.Clipboard; 9 | import java.awt.datatransfer.StringSelection; 10 | import java.awt.Toolkit; 11 | import javax.swing.event.HyperlinkEvent; 12 | import org.fife.ui.rsyntaxtextarea.*; 13 | 14 | public class CodeBlockLinkGenerator implements LinkGenerator { 15 | 16 | System.Logger LOG = System.getLogger("CodeBlockLinkGenerator"); 17 | private static final String TRIPLE_BACKTICK = "```"; 18 | 19 | @Override 20 | public LinkGeneratorResult isLinkAtOffset(RSyntaxTextArea textArea, int offs) { 21 | try { 22 | int currentLine = textArea.getLineOfOffset(offs); 23 | int startOffset = textArea.getLineStartOffset(currentLine); 24 | int endOffset = textArea.getLineEndOffset(currentLine); 25 | String lineText = textArea.getText(startOffset, endOffset - startOffset); 26 | 27 | if (lineText.trim().startsWith(TRIPLE_BACKTICK) && lineText.contains(QUICK_COPY_TEXT)) { 28 | int lineCount = textArea.getLineCount(); 29 | StringBuilder sb = new StringBuilder(); 30 | for (int line = currentLine + 1; line < lineCount; line++) { 31 | int lineStartOffset = textArea.getLineStartOffset(line); 32 | int lineEndOffset = textArea.getLineEndOffset(line); 33 | String currentLineText = textArea.getText(lineStartOffset, lineEndOffset - lineStartOffset); 34 | if (currentLineText.trim().equals(TRIPLE_BACKTICK)) { 35 | break; 36 | } else { 37 | sb.append(currentLineText); 38 | } 39 | } 40 | return new LinkGeneratorResult() { 41 | @Override 42 | public HyperlinkEvent execute() { 43 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 44 | clipboard.setContents(new StringSelection(sb.toString()), null); 45 | return null; 46 | } 47 | 48 | @Override 49 | public int getSourceOffset() { 50 | return offs; 51 | } 52 | }; 53 | } 54 | } catch (Exception ex) { 55 | LOG.log(System.Logger.Level.ERROR, "CodeBlockLinkGenerator failed", ex); 56 | } 57 | return null; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/stackleader/netbeans/chatgpt/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.stackleader.netbeans.chatgpt; 2 | 3 | import java.util.prefs.Preferences; 4 | import org.openide.util.NbPreferences; 5 | 6 | public class Configuration { 7 | 8 | public static final String OPENAI_TOKEN_KEY = "OPENAI_TOKEN"; 9 | 10 | private final Preferences preferences = NbPreferences.forModule(ChatTopComponent.class); 11 | 12 | public static Configuration getInstance() { 13 | return OptionsHolder.INSTANCE; 14 | } 15 | 16 | private Configuration() { 17 | } 18 | 19 | public Preferences getPreferences() { 20 | return preferences; 21 | } 22 | 23 | private static class OptionsHolder { 24 | 25 | private static final Configuration INSTANCE = new Configuration(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/nbm/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | OpenIDE-Module-Localizing-Bundle: com/stackleader/netbeans/chatgpt/Bundle.properties 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/com/stackleader/netbeans/chatgpt/Bundle.properties: -------------------------------------------------------------------------------- 1 | #Localized module labels. Defaults taken from POM (, , ) if unset. 2 | OpenIDE-Module-Name=ChatGPT Plugin 3 | OpenIDE-Module-Short-Description=A plugin for integrating ChatGPT into NetBeans IDE 4 | OpenIDE-Module-Long-Description=\ 5 |

This plugin allows users to leverage the power of ChatGPT, a conversational AI model, within NetBeans IDE for enhanced development assistance and support.

\ 6 |

ChatGPT is an advanced conversational AI model developed by OpenAI. With this plugin, developers can access the capabilities of ChatGPT directly from within NetBeans IDE, enabling more interactive and intuitive development workflows.

\ 7 |

Key features of the ChatGPT Plugin include:

\ 8 |
    \ 9 |
  • Code Generation: Generate code snippets, templates, and boilerplate code with the help of ChatGPT
  • \ 10 |
  • Enhanced Productivity: Speed up your development process by leveraging the power of ChatGPT
  • \ 11 |
\ 12 |


\ 13 | For more information and updates, visit the GitHub repository.

\ 14 | Enjoy the enhanced development experience with ChatGPT Plugin!

15 | OpenIDE-Module-Display-Category=AI and Chatbots 16 | Chat_TopComponent_Title=ChatGPT Plugin -------------------------------------------------------------------------------- /src/main/resources/icons/chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hillrunner2008/netbeans-chatgpt/f0b6330e1a9bb9a2c3de91fc23fa3e5dcf80b92a/src/main/resources/icons/chat.png -------------------------------------------------------------------------------- /src/main/resources/icons/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hillrunner2008/netbeans-chatgpt/f0b6330e1a9bb9a2c3de91fc23fa3e5dcf80b92a/src/main/resources/icons/options.png --------------------------------------------------------------------------------