Terminal для linux на Lazarus

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Terminal для linux на Lazarus

Сообщение khvalera » 02.09.2013 19:03:36

Народ, нужна подсказка! Есть задача, реализовать простенький терминал для своей проги.
Вот набросал тестовый пример:

Код: Выделить всё
procedure Run(FullPathRunProcessCommand:String);
var
  CharBuffer: array [0..511] of char;
  i, n, ReadCount: integer;
  Str, StrTemp, StrRemainder: string;
  Running: Boolean;
begin
  ExitCode := -1;
  Proc := TProcess.Create(nil);
  Proc.Options := [poUsePipes];
  Proc.CommandLine := 'bash';
//  Proc.CurrentDirectory := '/home';
  Proc.Execute;

  Proc.Input.Write(Pointer(FullPathRunProcessCommand)^, Length(FullPathRunProcessCommand));
  Proc.CloseInput;

  while Proc.Running do
    begin
      StrRemainder:= '';
      // read stdout and write to our stdout
      while Proc.Output.NumBytesAvailable > 0 do
      begin
        ReadCount := Min(512, Proc.Output.NumBytesAvailable); //Read up to buffer, not more
        Proc.Output.Read(CharBuffer, ReadCount);
        Str:= StrRemainder + Copy(CharBuffer, 0, ReadCount);
        for i:=0 to Length(Str) do
          begin
            n:= Pos(''#10'', Str);
            if n > 0 then
            begin
              StrTemp:= Copy(Str, 1, n - 1);
              Delete(Str, 1, Length(StrTemp)+1);
              FormMain.CmdBox1.Writeln(StrTemp);
            end
            else
              begin
                StrRemainder:= Str;
                Break;
              end;
          end;
      end;

      // read stderr and write to our stderr
     StrRemainder:= '';
     while Proc.Stderr.NumBytesAvailable > 0 do
      begin
        ReadCount := Min(512, Proc.Stderr.NumBytesAvailable); //Read up to buffer, not more
        Proc.Stderr.Read(CharBuffer, ReadCount);
        Str:= StrRemainder + Copy(CharBuffer, 0, ReadCount);
        for i:=0 to Length(Str) do
          begin
            n:= Pos(''#10'', Str);
            if n > 0 then
            begin
              StrTemp:= Copy(Str, 1, n - 1);
              Delete(Str, 1, Length(StrTemp)+1);
              FormMain.CmdBox1.Writeln(StrTemp);
            end
            else
              begin
                StrRemainder:= Str;
                Break;
              end;
          end;
      end;
    end;

    ExitCode := Proc.ExitStatus;
    if ExitCode > 0 then
      begin
        FormMain.CmdBox1.Writeln('Error code: ' + IntToStr(ExitCode));
      end;
end;               

Описание проблемы:
при смене каталога (допустим выполнения cd..) не могу придумать как получить новое значение каталога, есть два варианта:
1й - отслеживать вручную значение FullPathRunProcessCommand, но это не всегда прокатит.
2й - как то заставить не завершаться запущенный процесс bash и передавать ему pwd (не нашел параметра для bash как это сделать).

есть ли у кого то мысли как можно это реализовать?
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение Ism » 02.09.2013 19:27:51

http://code.google.com/p/xroot/
Пример работы с терминалом.

В других транках есть разные решения для работы с терминалом не зависящие от MseGui
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Terminal для linux на Lazarus

Сообщение khvalera » 03.09.2013 14:51:48

Ism писал(а):http://code.google.com/p/xroot/
Пример работы с терминалом.
В других транках есть разные решения для работы с терминалом не зависящие от MseGui


спасибо за ответ! но xroot не работает с терминалом, а просто создает процесс для выполнения команды.
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение Ism » 03.09.2013 16:26:35

Прикрутить можно любой интерфейс, и бросать из него команды как xroot

Proc.CommandLine не поддерживается в последних версиях Lazarus
Надо так
http://www.freepascal.ru/forum/viewtopi ... 237#p61238

TProcess в таких вещах глючит
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Terminal для linux на Lazarus

Сообщение Alex2013 » 05.09.2013 09:29:58

Что за чепуха !
Прекрасно работает что-то типа этого ..

Код: Выделить всё

var
  pro:TProcess;
  s:String;
begin
S:='cmd /c dir >tmp.tmp ';// или для линукса 'sh ls  >tmp.tmp'
     PRO:=TProcess.Create(nil);
     PRO.Options:=PRO.Options+[poWaitOnExit];
     S:=S+#0;
     pro.CommandLine:=s;
     PRO.Execute;
     pro.Free;
end;

может все дело было в том что нолик забыл прибавить ? ( S:=S+#0;)
Да и зачем нужно что то вводить во время работы терминала ?
Большинство команд все что нужно берет из командной строки ...
Ну в крайнем случае можно перенаправить ввод
su < PWD.TMP
(пример от балды man su делать умею )

или я все-же что-то нет понял о том для чего все это нужно ?
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Terminal для linux на Lazarus

Сообщение khvalera » 08.09.2013 18:32:12

Ism писал(а):Proc.CommandLine не поддерживается в последних версиях Lazarus
Надо так
viewtopi ... 237#p61238

автор наверно имел ввиду, что commandline устарел но поддерживается!? :) использую commandline, а также Parameters.Add много где, различий в работе и в том числе проблем не заметил.

Добавлено спустя 5 минут 33 секунды:
khvalera писал(а):или я все-же что-то нет понял о том для чего все это нужно ?

...да, вы не поняли задачу.

вот нашел: viewtopic.php?f=1&t=5419
буду ковырять исходники doublecmd.
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение khvalera » 15.09.2013 23:26:11

Как построен терминал в doublecmd разобрался, остались три не решенные задачи:
1. нужно как то отловить ExitCode для функции Con.Terminal.Write_pty(sCmd + sLineBreak).
2. пока не разобрался как работать с мышкой в CmdBox1 и как сделать выделение текста.
3. в компоненте CmdBox1 как то странно отображаются некоторые символы (пробел, дефис и некоторые другие), получаются меньше по размеру остальных символов:
Код: Выделить всё
  CmdBox1.Writeln('CmdLine/      lazterminal.ico  lazterminal.res    unit_terminal.pas');
  CmdBox1.Writeln('backup/       lazterminal.lpi  lib/               uterminal.pas');

должно выводиться ровненько как в табличке, а получаю следующее:
Изображение
может у кого есть мысли по этому поводу?
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение B4rr4cuda » 16.09.2013 02:25:56

2. Насколько я помню, этот функционал пропал после одной из доработок. Возможно требуется работа напильником над компонентом.
3. Лечится подбором шрифта.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Terminal для linux на Lazarus

Сообщение khvalera » 16.09.2013 22:28:27

B4rr4cuda писал(а):3. Лечится подбором шрифта.

...благодарю! действительно использование шрифта Monospace решает проблему.
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение khvalera » 24.09.2013 21:47:50

Используя forkpty для создания псевдо-терминала, при запуске bash и после выполнения любой команды, выводится строка приглашения, которую нужно программно отделять из всего вывода.
Проковырялся день и что то ни как не пойму, как красиво отловить эту строку приглашения!?

Если передать в execl в качестве параметра 'sh', то строка приглашения становится 'sh-4.1$', можно прицепиться к этому значению но это будет мега костыль :) .
Код: Выделить всё
function TUnixTerm.Fork_pty(const rows, cols: integer; const cmd:UTF8string; const params:UTF8string=''): System.THandle;
var WS: TWinSize;
    ChildPid: System.THandle;
    Pterm: Ptermios;
begin
  FCols:= Cols;
  Frows:= Rows;
  WS.ws_row:= Rows;
  WS.ws_col:= Cols;
  WS.ws_xpixel:= 0;
  WS.ws_ypixel:= 0;

  ChildPid:= forkpty(@Fpty, tName, Pterm, @WS);
  if ChildPid < 0 then
  begin
    Result:= -1;
    Exit;
  end;

  if ChildPid = 0 then
  begin
    //Child
    setenv('TERM', 'linux', 1);
    execl(pchar(cmd), 'sh');
    fpWrite(C_stderr, pchar('execl() failed. Command: ' + cmd), Length('execl() failed. Command: ' + cmd));
    Exit(127);  // error exec'ing
  end;

  FChildPid:= ChildPid;
  Result:= ChildPid;
end;

можно также сразу выполнить export PS1='' и тогда строка приглашения в терминале пропадет, а в CmdBox1 выводить свое приглашения, но это тоже костыль :(.
Может кто знает более красивое решение?
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение B4rr4cuda » 25.09.2013 04:09:27

Ну, кроме костыликов можно еще парсить PS1 и смотреть какая часть вывода ей соответсвует.. ну и отделять соответственно.
Я так понимаю у вас ввод идет тоже через Cmdline, потому и возник вопрос?
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Terminal для linux на Lazarus

Сообщение khvalera » 25.09.2013 14:35:21

B4rr4cuda писал(а):Я так понимаю у вас ввод идет тоже через Cmdline, потому и возник вопрос?

...совершенно верно! Парсить по PS1 думаю проблематично, хотя все же как вариант попробую.
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение 0beron » 09.08.2014 15:20:33

Извините, а CmdBox это стандартный компонент Lazarus и где его взять?
0beron
новенький
 
Сообщения: 23
Зарегистрирован: 18.08.2012 19:32:10

Re: Terminal для linux на Lazarus

Сообщение khvalera » 10.08.2014 01:35:12

В свое время компонента CmdBox, была в исходниках doublecmd.
Аватара пользователя
khvalera
новенький
 
Сообщения: 57
Зарегистрирован: 29.06.2010 00:49:43

Re: Terminal для linux на Lazarus

Сообщение sign » 11.08.2014 06:46:53

Можете качнуть CodeTyphon.
Там есть группы компонентов Extra...
CmdBox в наборе ExtraSystem.
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 28

Рейтинг@Mail.ru