分类 技术 下的文章

LibreOffice 是一款自由开源的跨平台办公生产力软件。如果你没有充分利用它,那么必须看下 LibreOffice 小技巧

甚至在非编程人员中,深色主题也越来越受欢迎。它减轻了眼睛的压力,特别适合长时间使用屏幕。有人认为,这使文本看起来清晰明了,有助于提高生产率。

如今,某些 Linux 发行版例如 Ubuntu 带有深色模式,使你的系统具有更暗的色彩。当你打开 深色模式 dark mode 时,某些应用将自动切换到深色模式。

LibreOffice 也会这样,但你编辑的主区域除外:

LibreOffice semi dark mode matching with the system theme

你可以更改它。如果要让 LibreOffice 进入完全深色模式,只需更改一些设置。让我告诉你如何做。

如何在 LibreOffice 中完全启用深色模式

如前所述,你需要先启用系统范围的深色模式。这样可以确保窗口颜色(或标题栏)与应用内深色完全融合。

接下来,打开套件中的任意 LibreOffice 应用,例如 Writer。然后从菜单中,依次点击 Tools -> Options -> Application Colors,然后选择 Document background 和 Application backgroundBlackAutomatic(任意适合你的方式)。

如果图标不是深色,那么可以从菜单(如下图所示)中更改它们,Tools -> Options -> View ,我在 MX Linux 上的个人选择是 Ubuntu 的 Yaru 图标样式(如果你使用的图标包为深色版本,请选择它) 。

当然,你也可以尝试其他 Linux 发行版的 icon 主题

最终结果应如下所示:

LibreOffice flatpak 软件包的其他技巧

如果你使用的是 LibreOffice 套件的 Flatpak 软件包,那么 LibreOffice 的标题区域(或菜单区域)可能看起来是白色的。在这种情况下,你可以尝试进入 Tools -> Options -> Personalization,然后选择 “灰色主题”,如下截图所示。

它并不完全是黑色的,但应该可以使外观看起来更好。希望可以帮助你切换到深色主题的 LibreOffice 体验!

总结

深色主题逐渐开始在我们的台式机中占主导地位,它具有现代品味并减少了眼睛疲劳,尤其是在弱光条件下。

LibreOffice 使你可以自由地将工作环境切换为深色主题或保留浅色主题元素。实际上,你将有大量的自定义选项来调整你喜欢的内容。你是否已在 LibreOffice 上切换为深色主题?你首选哪种颜色组合?在下面的评论中让我们知道!


via: https://itsfoss.com/libreoffice-dark-mode/

作者:Dimitrios Savvopoulos 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是一份在同一台机器上设置 Linux 和 Windows 双重启动的速成解释,使用统一可扩展固件接口(UEFI)。

我将强调一些重要点,而不是一步一步地指导你来如何配置你的系统以实现双重启动。作为一个示例,我将提到我在几个月之前新买的笔记本计算机。我先是安装 Ubuntu Linux 到整个硬盘中,这就摧毁了预装的 Windows 10 环境。几个月后,我决定安装一个不同的 Linux 发行版 Fedora Linux,也决定在双重启动配置中与它一起再次安装 Windows 10 。我将强调一些极其重要的实际情况。让我们开始吧!

固件

双重启动不仅仅是软件问题。或者说它算是软件的问题,因为它需要更改你的固件,以告诉你的机器如何开始启动程序。这里有一些和固件相关的重要事项要铭记于心。

UEFI vs BIOS

在尝试安装前,确保你的固件配置是最佳的。现在出售的大多数计算机有一个名为 统一可扩展固件接口 Unified Extensible Firmware Interface (UEFI)的新类型固件,UEFI 差不多取代了另一个名为 基本输入输出系统 Basic Input Output System (BIOS)的固件类型,(包括很多固件供应商在内的很多人)通常称 BIOS 为 传统启动模式 Legacy Boot

我不需要 BIOS,所以我选择了 UEFI 模式。

安全启动

另一个重要的设置是 安全启动 Secure Boot 。这个功能将检测启动路径是否被篡改,并阻止未经批准的操作系统的启动。现在,我禁用这个选项来确保我能够安装 Fedora Linux 。依据 Fedora 项目维基“功能/安全启动”部分的介绍可知:Fedora Linux 在安全启动选项启用的时候也可以工作。这对其它的 Linux 发行版来说可能有所不同 — 我打算今后重新研究这项设置。

简而言之,如果你发现在这项设置启用时你不能安装你的 Linux 操作系统,那么禁用安全启动并再次重新尝试安装。

对启动驱动器进行分区

如果你选择双重启动并且两个操作系统都在同一个驱动器上,那么你必须将它分成多个分区。即使你使用两个不同的驱动器进行双重启动,出于各种各样的原因,大多数 Linux 环境也最好分成几个基本的分区。这里有一些选项值得考虑。

GPT vs MBR

如果你决定手动分区你的启动驱动器,在动手前,我建议使用 GUID 分区表 GUID Partition Table (GPT),而不是使用旧的 主启动记录 Master Boot Record (MBR) 。这种更改的原因之一是:MBR 有两个特定的限制,而 GPT 却没有:

  • MBR 可以最多拥有 15 个分区,而 GPT 可以最多拥有 128 个分区。
  • MBR 最多仅支持 2 TB 磁盘,而 GPT 使用 64 位地址,这使得它最多支持 800 万 TB 的磁盘。

如果你最近购买过硬盘,那么你可能会知道现代的很多硬盘都超过了 2 TB 的限制。

EFI 系统分区

如果你正在进行一次全新的安装或使用一块新的驱动器,那么这里可能没有可以开始的分区。在这种情况下,操作系统安装程序将先创建一个分区,即 EFI 系统分区 EFI System Partition (ESP)。如果你选择使用一个诸如 gdisk 之类的工具来手动分区你的驱动器,你将需要使用一些参数来创建这个分区。基于现有的 ESP ,我设置它为约 500 MB 的大小,并分配它为 ef00( EFI 系统 )分区类型。UEFI 规范要求格式化为 FAT32/msdos ,很可能是因为这种格式被大量的操作系统所支持。

分区

操作系统安装

在你完成先前的两个任务后,你就可以安装你的操作系统了。虽然我在这里关注的是 Windows 10 和 Fedora Linux ,当安装其它组合时的过程也是非常相似。

Windows 10

我开始 Windows 10 的安装,并创建了一个 20 GB 的 Windows 分区。因为我先前在我的笔记本计算机上安装了 Linux ,所以驱动器已经有了一个 ESP ,我选择保留它。我删除所有的现有 Linux 和交换分区来开始一次全新安装,然后开始我的 Windows 安装。Windows 安装程序自动创建另一个 16 MB 的小分区,称为 微软保留分区 Microsoft Reserved Partition (MSR)。在这完成后,在 512 GB 启动驱动器上仍然有大约 400 GB 的未分配空间。

接下来,我继续完成了 Windows 10 安装过程。随后我重新启动到 Windows 来确保它是工作的,在操作系统第一次启动时,创建我的用户账号,设置 Wi-Fi ,并完成其它必须的任务。

Fedora Linux

接下来,我将心思转移到安装 Linux 。我开始了安装过程,当安装进行到磁盘配置的步骤时,我确保不会更改 Windows NTFS 和 MSR 分区。我也不会更改 ESP ,但是我设置它的挂载点为 /boot/efi。然后我创建常用的 ext4 格式分区, /(根分区)、/boot/home。我创建的最后一个分区是 Linux 的交换分区(swap)。

像安装 Windows 一样,我继续完成了 Linux 安装,随后重新启动。令我高兴的是,在启动时 大一统启动加载程序 GRand Unified Boot Loader (GRUB)菜单提供选择 Windows 或 Linux 的选项,这意味着我不需要再做任何额外的配置。我选择 Linux 并完成了诸如创建我的用户账号等常规步骤。

总结

总体而言,这个过程是不难的,在过去的几年里,从 BIOS 过渡到 UEFI 有一些困难需要解决,加上诸如安全启动等功能的引入。我相信我们现在已经克服了这些障碍,可以可靠地设置多重启动系统。

我不再怀念 Linux LOader)(LILO)!


via: https://opensource.com/article/19/5/dual-booting-windows-linux-uefi

作者:Alan Formy-Duval 选题:lujun9972 译者:robsean 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

大家好!今天是我搭建这个玩具项目的第 2 天。下面再来记录一下关于 Rails 的一些有趣的事情吧!

目标:做一个冰箱诗歌论坛

我想做一种无聊的标准网站来学习 Rails,并且其他人可以与之互动,就像一个论坛一样! 但如果人们真的可以在网站上打字,那就会产生各种各样的问题(如果他们是垃圾邮件发送者怎么办?又或者只是言语刻薄?)。

我想到的第一个想法是,可以让人们与网站互动,但实际上却不能在网站上打字,那就是一个“冰箱诗歌论坛”,只给你一组固定的字,你就可以随意组合。

所以,这就是我们的计划!

我这个项目的目标是想知道我是否能用 Rails 来做其他的小型网络项目(而不是像我通常做的那样,使用一些更基本的东西,比如 Flask,或者放弃后端,用 Javascript 来写所有东西)。

怎么把字拖来拖去呢?jQuery 的可拖放 UI!

我想让大家能够把文字拖动起来,但我又不想写很多 Javascript。结果发现这超级简单 —— 有一个 jQuery 库可以做到,它叫做 draggable!一开始,拖动并不成功。

一开始拖动在手机上是不行的,但是有一个技巧可以让 jQuery UI 在手机上工作,叫做 jQuery UI touch punch。下面是它的样子(有兴趣看工作原理的可以查看源码,代码很少)。

banana forest cake is

一个有趣的 Rails 功能:关联

我以前从来没有使用过关系型 ORM,对于 Rails,我很兴奋的一件事就是想看看使用 Active Record 是什么样子的!今天我了解了 Rails 的 ORM 功能之一:关联。如果你像我一样对 ORM 完全不了解的话,那就来看看是怎么回事吧。

在我的论坛中,我有:

  • 用户
  • 话题(我本来想把它叫做“线索”,但显然这在 Rails 中是一个保留词,所以现在叫做“话题”)。
  • 帖子

当显示一个帖子时,我需要显示创建该帖子的用户的用户名。所以我想我可能需要写一些代码来加载帖子,并为每个帖子加载用户,就像这样(在 Rails 中,Post.whereUser.find 将会运行 SQL 语句,并将结果转化为 Ruby 对象):

@posts = Post.where(topic_id: id)
@posts.each do |post|
    user = User.find(post.user_id)
    post.user = user
end

这还不够好,它要为每个帖子做一次单独的 SQL 查询!我知道有一个更好的方法,我发现它叫做关联。这个链接是来自 https://guides.rubyonrails.org 的指南,到目前为止,它对我很有帮助。

基本上我需要做的就是:

  1. User 模型中添加一行 has_many :post
  2. Post 模型中添加一行 belongs_to :user
  3. Rails 现在知道如何将这两个表连接起来,尽管我没有告诉它要连接到什么列上!我认为这是因为我按照它所期望的惯例命名了 posts 表中的 user_id 列。
  4. UserTopic 做完全相同的事情(一个主题也有很多帖子:has_many :posts)。

然后我加载每一个帖子和它的关联用户的代码就变成了只有一行! 就是这一行:

@posts = @topic.posts.order(created_at: :asc).preload(:user)

比起只有一行更重要的是,它不是单独做一个查询来获取每个帖子的用户,而是在 1 个查询中获取所有用户。显然,在 Rails 中,有一堆不同的方法来做类似的事情(预加载、急切加载、联接和包含?),我还不知道这些都是什么,但也许我以后会知道的。

一个有趣的 Rails 功能:脚手架!

Rails 有一个叫 rails 的命令行工具,它可以生成很多代码。例如,我想添加一个 Topic 模型/控制器。我不用去想在哪里添加所有的代码,可以直接运行

rails generate scaffold Topic title:text

并生成了一堆代码,这样我已经有了基本的端点来创建/编辑/删除主题(Topic)。例如,这是我的现在的主题控制器,其中大部分我没有写(我只写了高亮的 3 行)。我可能会删除很多内容,但是有一个起点,让我可以扩展我想要的部分,删除我不想要的部分,感觉还不错。

数据库迁移!

rails 工具还可以生成数据库迁移! 例如,我决定要删除帖子中的 title 字段。

下面是我要做的:

rails generate migration RemoveTitleFromPosts title:string
rails db:migrate

就是这样 —— 只要运行几个命令行咒语就可以了! 我运行了几个这样的迁移,因为我改变了对我的数据库模式的设想。它是相当直接的,到目前为止 —— 感觉很神奇。

当我试图在一列中的某些字段为空的地方添加一个“不为空”(not null)约束时,情况就变得有点有趣了 —— 迁移失败。但我可以修复违例的记录,并轻松地重新运行迁移。

今天就到这里吧!

明天,如果我有更多的进展,也许我会把它放在互联网上。


via: https://jvns.ca/blog/2020/11/10/day-2--rails-associations---dragging-divs-around/

作者:Julia Evans 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用 Jupyter 和 Python 在你的日常写作背后实现一些自动化。

有些人会遵循传统,制定一年的计划。不过,一年的时间很长,所以我以季节性的主题或轨迹来规划。每个季度,我都会坐下来,看看即将到来的三个月的季节,并决定在这段时间里我将努力做什么。

对于我最新的主题,我决定要每天写一篇日记。我喜欢有明确的承诺,所以我承诺每天写 5 分钟。我也喜欢有可观察的承诺,哪怕只是对我而言,所以我把我的记录放在 Git 里。

我决定在写日记的过程中实现一些自动化,于是我使用了我最喜欢的自动化工具:Jupyter。Jupyter 有一个有趣的功能 ipywidgets,这是一套用于 Jupyter Notebooks、JupyterLab 和 IPython 内核的交互式 HTML 组件。

如果你想跟着本文的代码走,请注意,让你的 JupyterLab 实例支持组件可能有点复杂,请按照这些说明来进行设置。

导入 ipywidgets 模块

首先,你需要导入一堆东西,比如 ipywidgets 和 Twisted。Twisted 模块可以用来创建一个异步时间计数器:

import twisted.internet.asyncioreactor
twisted.internet.asyncioreactor.install()
from twisted.internet import reactor, task
import ipywidgets, datetime, subprocess, functools, os

设置定时条目

用 Twisted 实现时间计数器是利用了 task.LoopingCall。然而,结束循环调用的唯一方法是用一个异常。倒计时时钟总会停止,所以你需要一个自定义的异常来指示“一切正常;计数器结束”:

class DoneError(Exception):
    pass

现在你已经写好了异常,你可以写定时器了。第一步是创建一个 ipywidgets.Label 的文本标签组件。循环使用 divmod 计算出分和秒,然后设置标签的文本值:

def time_out_counter(reactor):
    label = ipywidgets.Label("Time left: 5:00")
    current_seconds = datetime.timedelta(minutes=5).total_seconds()
    def decrement(count):
        nonlocal current_seconds
        current_seconds -= count
        time_left = datetime.timedelta(seconds=max(current_seconds, 0))
        minutes, left = divmod(time_left, minute)
        seconds = int(left.total_seconds())
        label.value = f"Time left: {minutes}:{seconds:02}"
        if current_seconds < 0:
            raise DoneError("finished")
    minute = datetime.timedelta(minutes=1)
    call = task.LoopingCall.withCount(decrement)
    call.reactor = reactor
    d = call.start(1)
    d.addErrback(lambda f: f.trap(DoneError))
    return d, label

从 Jupyter 组件中保存文本

下一步是写一些东西,将你输入的文字保存到一个文件中,并提交到 Git。另外,由于你要写 5 分钟的日记,你需要一个能给你提供写字区域的组件(滚动肯定是可以的,但一次能看到更多的文字就更好了)。

这就用到了组件 Textarea,这是一个你可以书写的文本字段,而 Output 则是用来给出反馈的。这一点很重要,因为 git push 可能会花点时间或失败,这取决于网络。如果备份失败,用反馈提醒用户很重要:

def editor(fname):
    textarea = ipywidgets.Textarea(continuous_update=False)
    textarea.rows = 20
    output = ipywidgets.Output()
    runner = functools.partial(subprocess.run, capture_output=True, text=True, check=True)
    def save(_ignored):
        with output:
            with open(fname, "w") as fpout:
                fpout.write(textarea.value)
            print("Sending...", end='')
            try:
                runner(["git", "add", fname])
                runner(["git", "commit", "-m", f"updated {fname}"])
                runner(["git", "push"])
            except subprocess.CalledProcessError as exc:
                print("Could not send")
                print(exc.stdout)
                print(exc.stderr)
            else:
                 print("Done")
    textarea.observe(save, names="value")
    return textarea, output, save

continuous_update=False 是为了避免每个字符都保存一遍并发送至 Git。相反,只要脱离输入焦点,它就会保存。这个函数也返回 save 函数,所以可以明确地调用它。

创建一个布局

最后,你可以使用 ipywidgets.VBox 把这些东西放在一起。这是一个包含一些组件并垂直显示的东西。还有一些其他的方法来排列组件,但这足够简单:

def journal():
    date = str(datetime.date.today())
    title = f"Log: Startdate {date}"
    filename = os.path.join(f"{date}.txt")
    d, clock = time_out_counter(reactor)
    textarea, output, save = editor(filename)
    box = ipywidgets.VBox([
        ipywidgets.Label(title),
        textarea,
        clock,
        output
    ])
    d.addCallback(save)
    return box

biu!你已经定义了一个写日记的函数了,所以是时候试试了。

journal()

 title=

你现在可以写 5 分钟了!


via: https://opensource.com/article/20/11/daily-journal-jupyter

作者:Moshe Zadka 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这又是一篇关于我很喜欢的一个命令行工具的文章。

昨晚,出于官僚原因,我需要扫描一些文档。我以前从来没有在 Linux 上使用过扫描仪,我担心会花上好几个小时才弄明白。我从使用 gscan2pdf 开始,但在用户界面上遇到了麻烦。我想同时扫描两面(我知道我们的扫描仪支持),但无法使它工作。

遇到 scanimage!

scanimage 是一个命令行工具,在 sane-utils Debian 软件包中。我想所有的 Linux 扫描工具都使用 sane (“scanner access now easy”) 库,所以我猜测它和其他扫描软件有类似的能力。在这里,我不需要 OCR,所以我不打算谈论 OCR。

用 scanimage -L 得到你的扫描仪的名字

scanimage -L 列出了你所有的扫描设备。

一开始我不能让它工作,我有点沮丧,但事实证明,我把扫描仪连接到了我的电脑上,但没有插上电源。

插上后,它马上就能工作了。显然我们的扫描仪叫 fujitsu:ScanSnap S1500:2314。万岁!

用 --help 列出你的扫描仪选项

显然每个扫描仪有不同的选项(有道理!),所以我运行这个命令来获取我的扫描仪的选项:

scanimage --help -d 'fujitsu:ScanSnap S1500:2314'

我发现我的扫描仪支持 --source 选项(我可以用它来启用双面扫描)和 --resolution 选项(我把它改为 150,以减少文件大小,使扫描更快)。

scanimage 不支持输出 PDF 文件(但你可以写一个小脚本)

唯一的缺点是:我想要一个 PDF 格式的扫描文件,而 scanimage 似乎不支持 PDF 输出。

所以我写了这个 5 行的 shell 脚本在一个临时文件夹中扫描一堆 PNG 文件,并将结果保存到 PDF 中。

#!/bin/bash
set -e

DIR=`mktemp -d`
CUR=$PWD
cd $DIR
scanimage -b --format png  -d 'fujitsu:ScanSnap S1500:2314' --source 'ADF Front' --resolution 150
convert *.png $CUR/$1

我像这样运行脚本:scan-single-sided output-file-to-save.pdf

你可能需要为你的扫描仪设置不同的 -d-source

这真是太简单了!

我一直以为在 Linux 上使用打印机/扫描仪是一个噩梦,我真的很惊讶 scanimage 可以工作。我可以直接运行我的脚本 scan-single-sided receipts.pdf,它将扫描文档并将其保存到 receipts.pdf


via: https://jvns.ca/blog/2020/07/11/scanimage--scan-from-the-command-line/

作者:Julia Evans 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

今天,我开始了一个 Recurse Center 的班次学习!我认识了一些人,并开始了一个小小的有趣的 Rails 项目。我想我今天不会谈太多关于这个项目的实际内容,但这里有一些关于 Rails 一天的快速笔记。

一些关于开始的笔记

在建立 Rails 项目的过程中,我学到的主要是:

  1. 它默认使用 sqlite,你必须告诉它使用 Postgres。
  2. Rails 默认包含了大量的东西,你可以禁用。

我安装并 rm -rf Rails 大概 7 次后才满意,最后用了这个咒语:

rails new . -d postgresql --skip-sprockets --skip-javascript

主要是因为我想用 Postgres 而不是 sqlite,而且跳过 sprockets 和 javascript 似乎能让安装 Rails 的速度更快,而且我想如果我决定要它们的话,我可以在以后再安装。

官方的 Rails 指南真的很不错

我在创建我的 Rails 入门应用时主要参考了 2 个资源:

一个神秘的错误信息:undefined method 'user'

我喜欢 bug,所以今天我遇到了一个奇怪的 Rails 错误! 我有一些看起来像这样的代码:

@user = User.new(user_params)
@user.save

很简单吧?但当这段代码运行时,我得到了这个令人费解的错误信息:

undefined method `user' for #<User:0x00007fb6f4012ab8> Did you mean? super

我对这里发生的事情感到超级困惑,因为我没有调用一个叫做 user 的方法。我调用的是 .save。什么嘛?!我对此感到困惑和沮丧,大概呆了 20 分钟,最后我看了看我的 User 模型,发现了这段代码:

class User < ApplicationRecord
  has_secure_password

  validates :user, presence: true, uniqueness: true
end

validates :user... 应该是一些 Rails 魔法,验证每个 User 都有一个 username,而且用户名必须是唯一的。但我犯了一个错,我写的是 user 而不是 username。我把这个问题解决了,然后一切都正常了!万岁。

我仍然不明白我应该如何调试这个问题:堆栈跟踪告诉我问题出在 @user.save 行,根本没有提到 validates :user 的事情。我觉得一定有办法调试这个问题,但我不知道是什么办法。

我学 Rails 的目的就是想看看 Rails 的魔力在实践中是如何发挥的,所以这是个很有意思的 bug,早早的就掉坑里了。

一个简单的用户管理系统

我决定在我的玩具应用中加入用户。我在网上搜索了一下,发现有一个非常流行的叫做 devise 的工具可以处理用户。我发现它的 README 有点让人不知所措,而且我知道想要在我的玩具应用中建立一个非常简陋的用户管理系统,所以我遵循了这个名为《Rails 5.2 中从零开始进行用户验证》的指南,到目前为止,这个指南似乎还不错。Rails 似乎已经有了一大堆管理用户的内置东西,我真的很惊讶于这本指南的短小和我需要写的代码之少。

我在实现用户功能的时候了解到,Rails 有一个内置的神奇的会话管理系统(参见 Rails 会话如何工作。默认情况下,所有的会话数据似乎都存储在用户电脑上的 cookie 中,不过我想如果 cookie 太大了,你也可以把会话数据存储在数据库中。

已经有了会话管理系统,有了 cookie 和用户,却不太清楚到底发生了什么,这肯定是有点奇怪的,但也是挺好玩的!我们会看看情况如何。我们将拭目以待。

明天:更多的 Rails!

也许明天我可以在实现我的有趣的 rails 应用的想法上取得一些进展!


via: https://jvns.ca/blog/2020/11/09/day-1--a-little-rails-/

作者:Julia Evans 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出