2
0

FormRemoteEditor.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. {Programa ejemplo de uso de la librería para implementar editores "utilEditSyn".
  2. Por Tito Hinostroza 11/07/2014 }
  3. unit FormRemoteEditor;
  4. {$mode objfpc}{$H+}
  5. interface
  6. uses
  7. Classes, SysUtils, FileUtil, LazUTF8, SynEdit, Forms, Controls, Graphics,
  8. Dialogs, Menus, ComCtrls, ActnList, StdActns, SynEditMiscClasses, MisUtils,
  9. Globales, SynFacilUtils, FormRemoteOpenDial, FrameTabSession;
  10. type
  11. // TEditionMode = (
  12. // temLocal, //Edición normal de un archivo local
  13. // temRemSFTP, //Edición remota pro SFTP
  14. // temRemShell //Ediicón remota por comandos SSH (No recomendable)
  15. // );
  16. { TfrmRemoteEditor }
  17. TfrmRemoteEditor = class(TForm)
  18. published
  19. acFilOpen: TAction;
  20. acFilSaveAs: TAction;
  21. acFilSave: TAction;
  22. acFilNew: TAction;
  23. acFilExit: TAction;
  24. acSrchSearch: TAction;
  25. acSrchSearchNext: TAction;
  26. acSrchReplace: TAction;
  27. acEdiCopy: TEditCopy;
  28. acEdiCut: TEditCut;
  29. acEdiPaste: TEditPaste;
  30. acEdiRedo: TAction;
  31. acEdiSelecAll: TAction;
  32. acEdiUndo: TAction;
  33. AcToolSettings: TAction;
  34. ActionList: TActionList;
  35. acViewFilPanel: TAction;
  36. ImageList1: TImageList;
  37. MainMenu1: TMainMenu;
  38. MenuItem1: TMenuItem;
  39. MenuItem10: TMenuItem;
  40. MenuItem11: TMenuItem;
  41. MenuItem12: TMenuItem;
  42. MenuItem13: TMenuItem;
  43. MenuItem14: TMenuItem;
  44. MenuItem15: TMenuItem;
  45. MenuItem16: TMenuItem;
  46. MenuItem18: TMenuItem;
  47. MenuItem19: TMenuItem;
  48. MenuItem20: TMenuItem;
  49. MenuItem21: TMenuItem;
  50. MenuItem22: TMenuItem;
  51. MenuItem24: TMenuItem;
  52. MenuItem25: TMenuItem;
  53. MenuItem26: TMenuItem;
  54. mnLenguaje: TMenuItem;
  55. mnRecents: TMenuItem;
  56. MenuItem17: TMenuItem;
  57. MenuItem2: TMenuItem;
  58. MenuItem23: TMenuItem;
  59. MenuItem3: TMenuItem;
  60. MenuItem4: TMenuItem;
  61. MenuItem5: TMenuItem;
  62. MenuItem6: TMenuItem;
  63. MenuItem7: TMenuItem;
  64. MenuItem8: TMenuItem;
  65. MenuItem9: TMenuItem;
  66. OpenDialog1: TOpenDialog;
  67. PopupMenu1: TPopupMenu;
  68. SaveDialog1: TSaveDialog;
  69. StatusBar1: TStatusBar;
  70. ed: TSynEdit;
  71. ToolBar1: TToolBar;
  72. ToolButton1: TToolButton;
  73. ToolButton10: TToolButton;
  74. ToolButton11: TToolButton;
  75. ToolButton2: TToolButton;
  76. ToolButton3: TToolButton;
  77. ToolButton4: TToolButton;
  78. ToolButton5: TToolButton;
  79. ToolButton6: TToolButton;
  80. ToolButton7: TToolButton;
  81. ToolButton8: TToolButton;
  82. ToolButton9: TToolButton;
  83. acViewStaBar: TAction;
  84. acViewLinNum: TAction;
  85. procedure acFilOpenExecute(Sender: TObject);
  86. procedure acFilSaveAsExecute(Sender: TObject);
  87. procedure acFilSaveExecute(Sender: TObject);
  88. procedure acFilNewExecute(Sender: TObject);
  89. procedure acFilExitExecute(Sender: TObject);
  90. procedure acEdiRedoExecute(Sender: TObject);
  91. procedure acEdiSelecAllExecute(Sender: TObject);
  92. procedure acEdiUndoExecute(Sender: TObject);
  93. procedure acSrchSearchExecute(Sender: TObject);
  94. procedure acSrchSearchNextExecute(Sender: TObject);
  95. procedure AcToolSettingsExecute(Sender: TObject);
  96. procedure ChangeEditorState;
  97. procedure editChangeFileInform;
  98. procedure edSpecialLineMarkup(Sender: TObject; Line: integer;
  99. var Special: boolean; Markup: TSynSelectedColor);
  100. procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
  101. procedure FormCreate(Sender: TObject);
  102. procedure FormDestroy(Sender: TObject);
  103. procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
  104. procedure FormShow(Sender: TObject);
  105. private
  106. ses: TfraTabSession;
  107. edit: TSynFacilEditor;
  108. lineas: TStringList; //lista temporal
  109. localFile, destFile: String; //Rutas de archivo
  110. procedure editFindDialog1Close(Sender: TObject);
  111. public
  112. MsjErr: String;
  113. NomArcLocal: string; //nombre de archivo local
  114. procedure Open(destFile0: string);
  115. procedure Init(ses0: TfraTabSession);
  116. end;
  117. var
  118. frmRemoteEditor: TfrmRemoteEditor;
  119. implementation
  120. uses FormConfig, Comandos;
  121. {$R *.lfm}
  122. { TfrmRemoteEditor }
  123. procedure TfrmRemoteEditor.FormCreate(Sender: TObject);
  124. begin
  125. InicEditorC1(ed); //inicia editor con configuraciones por defecto
  126. ed.OnSpecialLineMarkup:=@edSpecialLineMarkup; //solo para corregir falla de resaltado de línea actual
  127. edit := TSynFacilEditor.Create(ed,'SinNombre', 'sh');
  128. edit.OnChangeEditorState:=@ChangeEditorState;
  129. edit.OnChangeFileInform:=@editChangeFileInform;
  130. //define paneles
  131. edit.PanFileSaved := StatusBar1.Panels[0]; //panel para mensaje "Guardado"
  132. edit.PanCursorPos := StatusBar1.Panels[1]; //panel para la posición del cursor
  133. edit.PanForEndLin := StatusBar1.Panels[2]; //panel para el tipo de delimitador de línea
  134. edit.PanCodifFile := StatusBar1.Panels[3]; //panel para la codificación del archivo
  135. edit.PanLangName := StatusBar1.Panels[4]; //panel para el nombre del lenguaje
  136. lineas := TStringList.Create;
  137. end;
  138. procedure TfrmRemoteEditor.FormShow(Sender: TObject);
  139. begin
  140. edit.NewFile; //para actualizar estado
  141. mnLenguaje.Clear;
  142. edit.InitMenuLanguages(mnLenguaje, patSyntax);
  143. edit.LoadSyntaxFromPath; //para que busque el archivo apropiado
  144. edit.InitMenuRecents(mnRecents,nil); //inicia el menú "Recientes"
  145. end;
  146. procedure TfrmRemoteEditor.FormCloseQuery(Sender: TObject; var CanClose: boolean);
  147. var
  148. rpta: Byte;
  149. begin
  150. if edit.Modified then begin //primero pregunta
  151. rpta := MsgYesNoCancel('File modified. Save on Server?');
  152. if rpta = 3 then begin //Cancel
  153. CanClose := false; //no deja cerrar
  154. exit;
  155. end;
  156. if rpta = 1 then begin //Yes
  157. acFilSaveExecute(self); //Primero guarda
  158. end;
  159. end;
  160. //se debe cerrar.
  161. //Limpiar el contenido, ya que solo se ocultará, y no queremos que aparezca el último
  162. //archivo cargado.
  163. edit.NewFile(false);
  164. end;
  165. procedure TfrmRemoteEditor.FormDestroy(Sender: TObject);
  166. begin
  167. lineas.Destroy;
  168. edit.Destroy;
  169. end;
  170. procedure TfrmRemoteEditor.FormDropFiles(Sender: TObject; const FileNames: array of String);
  171. begin
  172. //Carga archivo arrastrados
  173. if edit.SaveQuery then Exit; //Verifica cambios
  174. edit.LoadFile(FileNames[0]);
  175. edit.LoadSyntaxFromPath; //para que busque el archivo apropiado
  176. end;
  177. procedure TfrmRemoteEditor.ChangeEditorState;
  178. begin
  179. acFilSave.Enabled:=edit.Modified;
  180. acEdiUndo.Enabled:=edit.CanUndo;
  181. acEdiRedo.Enabled:=edit.CanRedo;
  182. //Para estas acciones no es necesario controlarlas, porque son acciones pre-determinadas
  183. // acEdiCortar.Enabled := edit.canCopy;
  184. // acEdiCopiar.Enabled := edit.canCopy;
  185. // acEdiPegar.Enabled:= edit.CanPaste;
  186. end;
  187. procedure TfrmRemoteEditor.editChangeFileInform;
  188. begin
  189. //actualiza nombre de archivo
  190. Caption := 'Remote Editor - ' + edit.FileName;
  191. end;
  192. procedure TfrmRemoteEditor.edSpecialLineMarkup(Sender: TObject; Line: integer;
  193. var Special: boolean; Markup: TSynSelectedColor);
  194. begin
  195. //vacío
  196. end;
  197. procedure TfrmRemoteEditor.editFindDialog1Close(Sender: TObject);
  198. {Se usa este evento para retornar el enfoque al editor.}
  199. begin
  200. self.SetFocus;
  201. end;
  202. /////////////////// Acciones de Archivo /////////////////////
  203. procedure TfrmRemoteEditor.acFilNewExecute(Sender: TObject);
  204. begin
  205. edit.NewFile;
  206. edit.LoadSyntaxFromPath; //para que busque el archivo apropiado
  207. end;
  208. procedure TfrmRemoteEditor.acFilOpenExecute(Sender: TObject);
  209. begin
  210. // OpenDialog1.Filter:='Text files|*.txt|All files|*.*';
  211. // edit.OpenDialog(OpenDialog1);
  212. frmRemoteOpenDial.ShowModal;
  213. if frmRemoteOpenDial.archivo <> '' then begin
  214. Open(frmRemoteOpenDial.archivo);
  215. end;
  216. end;
  217. procedure TfrmRemoteEditor.acFilSaveExecute(Sender: TObject);
  218. var
  219. txt: String;
  220. begin
  221. if ses.editMode = edtLocal then begin
  222. //Edición normal en archivo local
  223. edit.SaveFile;
  224. end else if ses.editMode = edtRemotSFTP then begin
  225. if destFile='' then begin
  226. MsgExc('There isn''t a file opened');
  227. exit;
  228. end;
  229. //Modo SFTP
  230. edit.SaveFile; //Guarda localmente
  231. //Transfiere archivo usando la misma IP de la conexión.
  232. ExecSFTP(ses.ftpEditUser, ses.ftpEditPass, ses.ip,
  233. 'lcd "'+ patTemp + '"' + LineEnding +
  234. 'cd "'+ ExtractFileDir(destFile) + '"' + LineEnding +
  235. 'put "' + ExtractFileName(destFile) + '"' + LineEnding +
  236. 'quit');
  237. end else if ses.editMode = edtBashComm then begin
  238. //Modo de puro comandos del shell
  239. txt := edit.Text; //toma texto
  240. {Usa comillas simples para evitar sustitución, porque las comillas simples ponen todo
  241. literalmente. El problema está cuando se quiere imprimir precisamente, comilla simple.
  242. Para ello se debe hacer una sustitución}
  243. ed.Enabled := False;
  244. txt := StringReplace(txt, '''', '''"''"''',[rfReplaceAll]);
  245. if ses<>nil then begin
  246. ses.EnviarComando('echo ''' + txt + ''' > "' + edit.FileName+'"', lineas);
  247. end;
  248. ed.Enabled := True;
  249. //para actualizar controles
  250. edit.Modified:=false; //Este método no es público en la librería original
  251. end;
  252. end;
  253. procedure TfrmRemoteEditor.acFilSaveAsExecute(Sender: TObject);
  254. var
  255. arc0: String;
  256. begin
  257. // edit.SaveAsDialog(SaveDialog1);
  258. if not SaveDialog1.Execute then begin //se canceló
  259. exit; //se canceló
  260. end;
  261. arc0 := SaveDialog1.FileName;
  262. if FileExists(arc0) then begin
  263. if MsgYesNoCancel('File already exists. Overwrite?',[arc0]) in [2,3] then exit;
  264. end;
  265. NomArcLocal := UTF8ToSys(arc0); //asigna nuevo nombre
  266. // if ExtractFileExt(NomArc) = '' then NomArc += '.'+extDef; //completa extensión
  267. edit.SaveFile; //lo guarda
  268. end;
  269. procedure TfrmRemoteEditor.acFilExitExecute(Sender: TObject);
  270. begin
  271. frmRemoteEditor.Close;
  272. end;
  273. //////////// Acciones de Edición ////////////////
  274. procedure TfrmRemoteEditor.acEdiUndoExecute(Sender: TObject);
  275. begin
  276. edit.Undo;
  277. end;
  278. //Acciones de búsqueda
  279. procedure TfrmRemoteEditor.acSrchSearchExecute(Sender: TObject);
  280. begin
  281. edit.FindDialog1.OnClose := @editFindDialog1Close;
  282. edit.FindDialog;
  283. end;
  284. procedure TfrmRemoteEditor.acSrchSearchNextExecute(Sender: TObject);
  285. begin
  286. edit.FindDialog_Find(self);
  287. end;
  288. procedure TfrmRemoteEditor.AcToolSettingsExecute(Sender: TObject);
  289. begin
  290. config.Configurar('3');
  291. end;
  292. procedure TfrmRemoteEditor.acEdiRedoExecute(Sender: TObject);
  293. begin
  294. edit.Redo;
  295. end;
  296. procedure TfrmRemoteEditor.acEdiSelecAllExecute(Sender: TObject);
  297. begin
  298. ed.SelectAll;
  299. end;
  300. procedure TfrmRemoteEditor.Open(destFile0: string); //Opcional para archivos locales
  301. //Permite editar un archivo almacenado en un archivo externo
  302. begin
  303. destFile := destFile0; //Guarda archivo abierto
  304. if self.Visible and edit.SaveQuery then Exit; //Verifica cambios
  305. if not self.Visible then self.Show;
  306. if ses.editMode = edtLocal then begin
  307. //Edición normal
  308. edit.LoadFile(destFile);
  309. end else if ses.editMode = edtRemotSFTP then begin //Edición por SFTP
  310. //Crea ruta de archivo local
  311. localFile := patTemp + DirectorySeparator + ExtractFileName(destFile);
  312. //Elimina si ya existe
  313. if FileExists(localFile) then DeleteFile(localFile);
  314. //Trae archivo usando la misma IP de la conexión.
  315. ExecSFTP(ses.ftpEditUser, ses.ftpEditPass, ses.ip,
  316. 'lcd "'+ patTemp + '"' + LineEnding +
  317. 'get ' + destFile + LineEnding +
  318. 'quit');
  319. //Carga archivo local
  320. //edit.Text := StringFromFile(patTemp + DirectorySeparator + localFile);
  321. edit.LoadFile(localFile);
  322. end else if ses.editMode = edtBashComm then begin
  323. //Ediicón por comandos
  324. if ses<>nil then begin
  325. MsjErr := ses.EnviarComando('cat "'+destFile+'"', lineas);
  326. end;
  327. ed.Lines.Clear;
  328. ed.Lines.AddStrings(lineas);
  329. edit.FileName:=destFile;
  330. //para actualizar controles
  331. edit.Modified:=false; //Este método no es público en la librería original)
  332. //para actualizar nombre
  333. edit.ChangeFileInform; //Este método no es público en la librería original)
  334. edit.LoadSyntaxFromPath; //para que busque el archivo apropiado
  335. end;
  336. end;
  337. procedure TfrmRemoteEditor.Init(ses0: TfraTabSession);
  338. {Inicializa parámetros que necesita la herramienta Editor.
  339. Para mostrar el editor se necesita simplemente llamar a .Show }
  340. begin
  341. //Se necesita acceder a la sesión para determinar el modo de edición.
  342. ses := ses0;
  343. end;
  344. end.