From 5d4ab855077d9724ad1f6e843005d5a3d97c84fc Mon Sep 17 00:00:00 2001 From: dalbee Date: Wed, 13 May 2026 11:13:14 +0900 Subject: [PATCH 1/2] Expose current-file upload as a shortcut command The bounty asks for a shortcut-driven upload path. NppFTP already had the correct current-file upload behavior behind the toolbar and context-menu handler, so this extracts that path into FTPWindow::UploadCurrentFile and exposes it through the Notepad++ plugin command list for Shortcut Mapper assignment. Constraint: Windows/Notepad++ plugin behavior cannot be runtime-tested from this macOS environment. Rejected: Add a hard-coded default shortcut | Notepad++ lets users map plugin commands, and default shortcuts risk colliding with editor or user mappings. Rejected: Implement arbitrary file-list upload | the issue discussion identifies active-current-file upload as the useful bounded shortcut path. Confidence: medium Scope-risk: narrow Directive: Preserve the existing toolbar upload behavior; shortcut command should call the same upload path. Tested: repo_vet.py static safety scan Tested: git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check Not-tested: Windows Notepad++ build/runtime and actual FTP upload flow. --- docs/index.md | 2 ++ src/NppFTP.cpp | 7 ++++++ src/NppFTP.h | 1 + src/PluginInterface.cpp | 13 +++++++++- src/Windows/FTPWindow.cpp | 51 ++++++++++++++++++++++++--------------- src/Windows/FTPWindow.h | 2 +- 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/docs/index.md b/docs/index.md index 53d9244..a994045 100644 --- a/docs/index.md +++ b/docs/index.md @@ -76,6 +76,8 @@ The toolbar provides the following buttons: * _Settings_: Access settings dialogs. * _Show Message Window_: Hide or Show the messages window. +The same current-file upload action is also available from the Notepad++ **Plugins > NppFTP > Upload Current File** menu item. Assign a shortcut to that command with Notepad++'s Shortcut Mapper if you want to upload the active local file without clicking the NppFTP toolbar. + ## Treeview If an FTP session is active, the treeview will show the files on the server. Some actions of the toolbar depend on the selected object in the treeview (see toolbar). Double-clicking on a directory will show its contents. Double-clicking on a file will download it to the cache and open it. diff --git a/src/NppFTP.cpp b/src/NppFTP.cpp index f2c269e..8a0cfa1 100644 --- a/src/NppFTP.cpp +++ b/src/NppFTP.cpp @@ -158,6 +158,13 @@ int NppFTP::ShowAboutDialog() const { return 0; } +int NppFTP::UploadCurrentFile() { + if (!m_ftpWindow) { + return -1; + } + return m_ftpWindow->UploadCurrentFile(); +} + int NppFTP::OnSave(const TCHAR* path) { if (!path || !m_ftpSession) return -1; diff --git a/src/NppFTP.h b/src/NppFTP.h index 8235079..0c2fccf 100644 --- a/src/NppFTP.h +++ b/src/NppFTP.h @@ -36,6 +36,7 @@ class NppFTP { int ShowFTPWindow(); int FocusFTPWindow(); int ShowAboutDialog() const; + int UploadCurrentFile(); int OnSave(const TCHAR* path); int OnActivateLocalFile(const TCHAR* path); diff --git a/src/PluginInterface.cpp b/src/PluginInterface.cpp index 448a5a1..ca85d08 100644 --- a/src/PluginInterface.cpp +++ b/src/PluginInterface.cpp @@ -26,7 +26,7 @@ typedef void* BufferID; -const int nrFuncItem = 3; +const int nrFuncItem = 4; FuncItem funcItems[nrFuncItem]; NppData nppData; NppFTP nppFTP; @@ -38,6 +38,7 @@ bool isStarted = false; void __cdecl ShowFTPWindow(); void __cdecl FocusFTPWindow(); +void __cdecl UploadCurrentFile(); void __cdecl ShowAboutDialog(); void __cdecl FakeItem(); @@ -91,6 +92,11 @@ FuncItem * getFuncsArray(int * arraysize) { funcItems[2]._pShKey = NULL; lstrcpyn(funcItems[2]._itemName, TEXT("About NppFTP"), menuItemSize); + funcItems[3]._pFunc = &UploadCurrentFile; + funcItems[3]._init2Check = false; + funcItems[3]._pShKey = NULL; + lstrcpyn(funcItems[3]._itemName, TEXT("Upload Current File"), menuItemSize); + return &funcItems[0]; } @@ -169,5 +175,10 @@ void __cdecl ShowAboutDialog() { nppFTP.ShowAboutDialog(); } +void __cdecl UploadCurrentFile() { + if (isStarted) + nppFTP.UploadCurrentFile(); +} + void __cdecl FakeItem() { } diff --git a/src/Windows/FTPWindow.cpp b/src/Windows/FTPWindow.cpp index 4b2f73a..33a8027 100644 --- a/src/Windows/FTPWindow.cpp +++ b/src/Windows/FTPWindow.cpp @@ -272,6 +272,37 @@ int FTPWindow::OnActivateLocalFile(const TCHAR* filename) { return 0; } +int FTPWindow::UploadCurrentFile(bool promptForFile) { + if (!m_ftpSession || !m_currentSelection) { + return -1; + } + + TCHAR source[MAX_PATH]{}; + BOOL doUpload = FALSE; + + if (promptForFile) { + source[0] = 0; + int res = PU::GetOpenFilename(source, MAX_PATH, m_hParent); + if (res == 0) { + doUpload = TRUE; + } + } else if (m_localFileExists) { + doUpload = ::SendMessage(m_hNpp, NPPM_GETFULLCURRENTPATH, (WPARAM)MAX_PATH, (LPARAM)source); + } + + if (doUpload != TRUE) { + return -1; + } + + if (m_currentSelection->isDir()) { + m_ftpSession->UploadFile(source, m_currentSelection->GetPath(), true); + } else { + m_ftpSession->UploadFile(source, m_currentSelection->GetParent()->GetPath(), true); + } + + return 0; +} + int FTPWindow::RegisterClass() { WNDCLASSEX FTPWindowClass{}; FTPWindowClass.cbSize = sizeof(WNDCLASSEX); @@ -469,26 +500,8 @@ LRESULT FTPWindow::MessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { break; } case IDM_POPUP_UPLOADFILE: case IDB_BUTTON_TOOLBAR_UPLOAD: { - //upload(TRUE, TRUE); //upload to cached folder is present, else upload to last selected folder - //m_ftpSession->UploadFile(); - TCHAR source[MAX_PATH]{}; - BOOL doUpload = FALSE; SHORT state = GetKeyState(VK_CONTROL); - if ((state & 0x8000) && LOWORD(wParam) == IDB_BUTTON_TOOLBAR_UPLOAD) { - source[0] = 0; - int res = PU::GetOpenFilename(source, MAX_PATH, m_hParent); - if (res == 0) - doUpload = TRUE; - } else { - doUpload = ::SendMessage(m_hNpp, NPPM_GETFULLCURRENTPATH, (WPARAM)MAX_PATH, (LPARAM)source); - } - if (doUpload == TRUE) { - if (m_currentSelection->isDir()) { - m_ftpSession->UploadFile(source, m_currentSelection->GetPath(), true); - } else { - m_ftpSession->UploadFile(source, m_currentSelection->GetParent()->GetPath(), true); - } - } + UploadCurrentFile((state & 0x8000) && LOWORD(wParam) == IDB_BUTTON_TOOLBAR_UPLOAD); result = TRUE; break;} case IDM_POPUP_UPLOADOTHERFILE: { diff --git a/src/Windows/FTPWindow.h b/src/Windows/FTPWindow.h index 678228f..b2c0900 100644 --- a/src/Windows/FTPWindow.h +++ b/src/Windows/FTPWindow.h @@ -57,6 +57,7 @@ class FTPWindow : public DockableWindow, public DropTargetWindow, public DropDat virtual int OnSize(int newWidth, int newHeight); virtual int OnProfileChange(); virtual int OnActivateLocalFile(const TCHAR* filename); + virtual int UploadCurrentFile(bool promptForFile = false); static int RegisterClass(); @@ -104,7 +105,6 @@ class FTPWindow : public DockableWindow, public DropTargetWindow, public DropDat virtual int Copy(FileObject* fo, FileObject* _newParent); virtual int VScrollTreeView(LONG pos); - //virtual int UploadCurrentFile(FileObject * parent); //virtual int UploadOtherFile(FileObject * parent); Toolbar m_toolbar; From c87960eda5c9892defc0c09d75ac5d80c94c6b89 Mon Sep 17 00:00:00 2001 From: dalbee Date: Wed, 13 May 2026 11:14:06 +0900 Subject: [PATCH 2/2] Preserve upload path lookup for current-file command The shared upload helper must not narrow the existing tree-menu behavior. The previous code resolved the current Notepad++ path at invocation time, so the extracted helper now does the same instead of depending on the cached toolbar-enabled state. Constraint: Follow-up came from code review before runtime validation was available. Confidence: medium Scope-risk: narrow Tested: git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check Not-tested: Windows Notepad++ build/runtime and actual FTP upload flow. --- src/Windows/FTPWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/FTPWindow.cpp b/src/Windows/FTPWindow.cpp index 33a8027..db8cd24 100644 --- a/src/Windows/FTPWindow.cpp +++ b/src/Windows/FTPWindow.cpp @@ -286,7 +286,7 @@ int FTPWindow::UploadCurrentFile(bool promptForFile) { if (res == 0) { doUpload = TRUE; } - } else if (m_localFileExists) { + } else { doUpload = ::SendMessage(m_hNpp, NPPM_GETFULLCURRENTPATH, (WPARAM)MAX_PATH, (LPARAM)source); }